We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
st2 key set in CLI doesn't allow one to set a TTL. 
Reported by: psychopenguin on slack


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `st2client/st2client/commands/keyvalue.py`
Content:
```
1 # Licensed to the StackStorm, Inc ('StackStorm') under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import os
17 import json
18 import logging
19 from os.path import join as pjoin
20 
21 from st2client.commands import resource
22 from st2client.commands.noop import NoopCommand
23 from st2client.commands.resource import add_auth_token_to_kwargs_from_cli
24 from st2client.formatters import table
25 from st2client.models.keyvalue import KeyValuePair
26 from st2client.utils.date import format_isodate
27 
28 LOG = logging.getLogger(__name__)
29 
30 
31 class KeyValuePairBranch(resource.ResourceBranch):
32 
33     def __init__(self, description, app, subparsers, parent_parser=None):
34         super(KeyValuePairBranch, self).__init__(
35             KeyValuePair, description, app, subparsers,
36             parent_parser=parent_parser,
37             commands={
38                 'list': KeyValuePairListCommand,
39                 'get': KeyValuePairGetCommand,
40                 'delete': KeyValuePairDeleteCommand,
41                 'create': NoopCommand,
42                 'update': NoopCommand
43             })
44 
45         # Registers extended commands
46         self.commands['set'] = KeyValuePairSetCommand(self.resource, self.app,
47                                                       self.subparsers)
48         self.commands['load'] = KeyValuePairLoadCommand(
49             self.resource, self.app, self.subparsers)
50         self.commands['delete_by_prefix'] = KeyValuePairDeleteByPrefixCommand(
51             self.resource, self.app, self.subparsers)
52 
53         # Remove unsupported commands
54         # TODO: Refactor parent class and make it nicer
55         del self.commands['create']
56         del self.commands['update']
57 
58 
59 class KeyValuePairListCommand(resource.ResourceListCommand):
60     display_attributes = ['name', 'value', 'expire_timestamp']
61     attribute_transform_functions = {
62         'expire_timestamp': format_isodate,
63     }
64 
65     def __init__(self, *args, **kwargs):
66         super(KeyValuePairListCommand, self).__init__(*args, **kwargs)
67 
68         # Filter options
69         self.parser.add_argument('--prefix', help=('Only return values which name starts with the '
70                                                    ' provided prefix.'))
71 
72     def run_and_print(self, args, **kwargs):
73         if args.prefix:
74             kwargs['prefix'] = args.prefix
75 
76         instances = self.run(args, **kwargs)
77         self.print_output(reversed(instances), table.MultiColumnTable,
78                           attributes=args.attr, widths=args.width,
79                           json=args.json,
80                           attribute_transform_functions=self.attribute_transform_functions)
81 
82 
83 class KeyValuePairGetCommand(resource.ResourceGetCommand):
84     pk_argument_name = 'name'
85     display_attributes = ['name', 'value']
86 
87 
88 class KeyValuePairSetCommand(resource.ResourceCommand):
89     display_attributes = ['name', 'value']
90 
91     def __init__(self, resource, *args, **kwargs):
92         super(KeyValuePairSetCommand, self).__init__(
93             resource, 'set',
94             'Set an existing %s.' % resource.get_display_name().lower(),
95             *args, **kwargs
96         )
97 
98         self.parser.add_argument('name',
99                                  metavar='name',
100                                  help='Name of the key value pair.')
101         self.parser.add_argument('value', help='Value paired with the key.')
102 
103     @add_auth_token_to_kwargs_from_cli
104     def run(self, args, **kwargs):
105         instance = KeyValuePair()
106         instance.id = args.name  # TODO: refactor and get rid of id
107         instance.name = args.name
108         instance.value = args.value
109         return self.manager.update(instance, **kwargs)
110 
111     def run_and_print(self, args, **kwargs):
112         instance = self.run(args, **kwargs)
113         self.print_output(instance, table.PropertyValueTable,
114                           attributes=self.display_attributes, json=args.json)
115 
116 
117 class KeyValuePairDeleteCommand(resource.ResourceDeleteCommand):
118     pk_argument_name = 'name'
119 
120     @add_auth_token_to_kwargs_from_cli
121     def run(self, args, **kwargs):
122         resource_id = getattr(args, self.pk_argument_name, None)
123         instance = self.get_resource(resource_id, **kwargs)
124 
125         if not instance:
126             raise resource.ResourceNotFoundError('KeyValuePair with id "%s" not found', resource_id)
127 
128         instance.id = resource_id  # TODO: refactor and get rid of id
129         self.manager.delete(instance, **kwargs)
130 
131 
132 class KeyValuePairDeleteByPrefixCommand(resource.ResourceCommand):
133     """
134     Commands which delete all the key value pairs which match the provided
135     prefix.
136     """
137     def __init__(self, resource, *args, **kwargs):
138         super(KeyValuePairDeleteByPrefixCommand, self).__init__(resource, 'delete_by_prefix',
139             'Delete KeyValue pairs which match the provided prefix', *args, **kwargs)
140 
141         self.parser.add_argument('-p', '--prefix', required=True,
142                                  help='Name prefix (e.g. twitter.TwitterSensor:)')
143 
144     @add_auth_token_to_kwargs_from_cli
145     def run(self, args, **kwargs):
146         prefix = args.prefix
147         key_pairs = self.manager.get_all(prefix=prefix)
148 
149         to_delete = []
150         for key_pair in key_pairs:
151             key_pair.id = key_pair.name
152             to_delete.append(key_pair)
153 
154         deleted = []
155         for key_pair in to_delete:
156             self.manager.delete(instance=key_pair, **kwargs)
157             deleted.append(key_pair)
158 
159         return deleted
160 
161     def run_and_print(self, args, **kwargs):
162         # TODO: Need to use args, instead of kwargs (args=) because of bad API
163         # FIX ME
164         deleted = self.run(args, **kwargs)
165         key_ids = [key_pair.id for key_pair in deleted]
166 
167         print('Deleted %s keys' % (len(deleted)))
168         print('Deleted key ids: %s' % (', '.join(key_ids)))
169 
170 
171 class KeyValuePairLoadCommand(resource.ResourceCommand):
172     pk_argument_name = 'name'
173     display_attributes = ['name', 'value']
174 
175     def __init__(self, resource, *args, **kwargs):
176         help_text = ('Load a list of %s from file.' %
177                      resource.get_plural_display_name().lower())
178         super(KeyValuePairLoadCommand, self).__init__(resource, 'load',
179             help_text, *args, **kwargs)
180 
181         self.parser.add_argument(
182             'file', help=('JSON file containing the %s to create.'
183                           % resource.get_plural_display_name().lower()))
184 
185     @add_auth_token_to_kwargs_from_cli
186     def run(self, args, **kwargs):
187         file_path = os.path.normpath(pjoin(os.getcwd(), args.file))
188 
189         if not os.path.exists(args.file):
190             raise ValueError('File "%s" doesn\'t exist' % (file_path))
191 
192         if not os.path.isfile(args.file):
193             raise ValueError('"%s" is not a file' % (file_path))
194 
195         with open(file_path, 'r') as f:
196             kvps = json.loads(f.read())
197 
198         instances = []
199         for item in kvps:
200             name = item['name']
201             value = item['value']
202 
203             instance = KeyValuePair()
204             instance.id = name  # TODO: refactor and get rid of id
205             instance.name = name
206             instance.value = value
207 
208             self.manager.update(instance, **kwargs)
209             instances.append(instance)
210         return instances
211 
212     def run_and_print(self, args, **kwargs):
213         instances = self.run(args, **kwargs)
214         self.print_output(instances, table.MultiColumnTable,
215                           attributes=['id', 'name', 'value'], json=args.json)
216
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/st2client/st2client/commands/keyvalue.py b/st2client/st2client/commands/keyvalue.py
--- a/st2client/st2client/commands/keyvalue.py
+++ b/st2client/st2client/commands/keyvalue.py
@@ -82,11 +82,11 @@
 
 class KeyValuePairGetCommand(resource.ResourceGetCommand):
     pk_argument_name = 'name'
-    display_attributes = ['name', 'value']
+    display_attributes = ['name', 'value', 'expire_timestamp']
 
 
 class KeyValuePairSetCommand(resource.ResourceCommand):
-    display_attributes = ['name', 'value']
+    display_attributes = ['name', 'value', 'expire_timestamp']
 
     def __init__(self, resource, *args, **kwargs):
         super(KeyValuePairSetCommand, self).__init__(
@@ -99,6 +99,8 @@
                                  metavar='name',
                                  help='Name of the key value pair.')
         self.parser.add_argument('value', help='Value paired with the key.')
+        self.parser.add_argument('-l', '--ttl', dest='ttl', type=int, default=None,
+                                 help='TTL (in seconds) for this value.')
 
     @add_auth_token_to_kwargs_from_cli
     def run(self, args, **kwargs):
@@ -106,6 +108,10 @@
         instance.id = args.name  # TODO: refactor and get rid of id
         instance.name = args.name
         instance.value = args.value
+
+        if args.ttl:
+            instance.ttl = args.ttl
+
         return self.manager.update(instance, **kwargs)
 
     def run_and_print(self, args, **kwargs):

{"golden_diff": "diff --git a/st2client/st2client/commands/keyvalue.py b/st2client/st2client/commands/keyvalue.py\n--- a/st2client/st2client/commands/keyvalue.py\n+++ b/st2client/st2client/commands/keyvalue.py\n@@ -82,11 +82,11 @@\n \n class KeyValuePairGetCommand(resource.ResourceGetCommand):\n     pk_argument_name = 'name'\n-    display_attributes = ['name', 'value']\n+    display_attributes = ['name', 'value', 'expire_timestamp']\n \n \n class KeyValuePairSetCommand(resource.ResourceCommand):\n-    display_attributes = ['name', 'value']\n+    display_attributes = ['name', 'value', 'expire_timestamp']\n \n     def __init__(self, resource, *args, **kwargs):\n         super(KeyValuePairSetCommand, self).__init__(\n@@ -99,6 +99,8 @@\n                                  metavar='name',\n                                  help='Name of the key value pair.')\n         self.parser.add_argument('value', help='Value paired with the key.')\n+        self.parser.add_argument('-l', '--ttl', dest='ttl', type=int, default=None,\n+                                 help='TTL (in seconds) for this value.')\n \n     @add_auth_token_to_kwargs_from_cli\n     def run(self, args, **kwargs):\n@@ -106,6 +108,10 @@\n         instance.id = args.name  # TODO: refactor and get rid of id\n         instance.name = args.name\n         instance.value = args.value\n+\n+        if args.ttl:\n+            instance.ttl = args.ttl\n+\n         return self.manager.update(instance, **kwargs)\n \n     def run_and_print(self, args, **kwargs):\n", "issue": "st2 key set in CLI doesn't allow one to set a TTL. \nReported by: psychopenguin on slack\n\n", "before_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport json\nimport logging\nfrom os.path import join as pjoin\n\nfrom st2client.commands import resource\nfrom st2client.commands.noop import NoopCommand\nfrom st2client.commands.resource import add_auth_token_to_kwargs_from_cli\nfrom st2client.formatters import table\nfrom st2client.models.keyvalue import KeyValuePair\nfrom st2client.utils.date import format_isodate\n\nLOG = logging.getLogger(__name__)\n\n\nclass KeyValuePairBranch(resource.ResourceBranch):\n\n    def __init__(self, description, app, subparsers, parent_parser=None):\n        super(KeyValuePairBranch, self).__init__(\n            KeyValuePair, description, app, subparsers,\n            parent_parser=parent_parser,\n            commands={\n                'list': KeyValuePairListCommand,\n                'get': KeyValuePairGetCommand,\n                'delete': KeyValuePairDeleteCommand,\n                'create': NoopCommand,\n                'update': NoopCommand\n            })\n\n        # Registers extended commands\n        self.commands['set'] = KeyValuePairSetCommand(self.resource, self.app,\n                                                      self.subparsers)\n        self.commands['load'] = KeyValuePairLoadCommand(\n            self.resource, self.app, self.subparsers)\n        self.commands['delete_by_prefix'] = KeyValuePairDeleteByPrefixCommand(\n            self.resource, self.app, self.subparsers)\n\n        # Remove unsupported commands\n        # TODO: Refactor parent class and make it nicer\n        del self.commands['create']\n        del self.commands['update']\n\n\nclass KeyValuePairListCommand(resource.ResourceListCommand):\n    display_attributes = ['name', 'value', 'expire_timestamp']\n    attribute_transform_functions = {\n        'expire_timestamp': format_isodate,\n    }\n\n    def __init__(self, *args, **kwargs):\n        super(KeyValuePairListCommand, self).__init__(*args, **kwargs)\n\n        # Filter options\n        self.parser.add_argument('--prefix', help=('Only return values which name starts with the '\n                                                   ' provided prefix.'))\n\n    def run_and_print(self, args, **kwargs):\n        if args.prefix:\n            kwargs['prefix'] = args.prefix\n\n        instances = self.run(args, **kwargs)\n        self.print_output(reversed(instances), table.MultiColumnTable,\n                          attributes=args.attr, widths=args.width,\n                          json=args.json,\n                          attribute_transform_functions=self.attribute_transform_functions)\n\n\nclass KeyValuePairGetCommand(resource.ResourceGetCommand):\n    pk_argument_name = 'name'\n    display_attributes = ['name', 'value']\n\n\nclass KeyValuePairSetCommand(resource.ResourceCommand):\n    display_attributes = ['name', 'value']\n\n    def __init__(self, resource, *args, **kwargs):\n        super(KeyValuePairSetCommand, self).__init__(\n            resource, 'set',\n            'Set an existing %s.' % resource.get_display_name().lower(),\n            *args, **kwargs\n        )\n\n        self.parser.add_argument('name',\n                                 metavar='name',\n                                 help='Name of the key value pair.')\n        self.parser.add_argument('value', help='Value paired with the key.')\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        instance = KeyValuePair()\n        instance.id = args.name  # TODO: refactor and get rid of id\n        instance.name = args.name\n        instance.value = args.value\n        return self.manager.update(instance, **kwargs)\n\n    def run_and_print(self, args, **kwargs):\n        instance = self.run(args, **kwargs)\n        self.print_output(instance, table.PropertyValueTable,\n                          attributes=self.display_attributes, json=args.json)\n\n\nclass KeyValuePairDeleteCommand(resource.ResourceDeleteCommand):\n    pk_argument_name = 'name'\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        resource_id = getattr(args, self.pk_argument_name, None)\n        instance = self.get_resource(resource_id, **kwargs)\n\n        if not instance:\n            raise resource.ResourceNotFoundError('KeyValuePair with id \"%s\" not found', resource_id)\n\n        instance.id = resource_id  # TODO: refactor and get rid of id\n        self.manager.delete(instance, **kwargs)\n\n\nclass KeyValuePairDeleteByPrefixCommand(resource.ResourceCommand):\n    \"\"\"\n    Commands which delete all the key value pairs which match the provided\n    prefix.\n    \"\"\"\n    def __init__(self, resource, *args, **kwargs):\n        super(KeyValuePairDeleteByPrefixCommand, self).__init__(resource, 'delete_by_prefix',\n            'Delete KeyValue pairs which match the provided prefix', *args, **kwargs)\n\n        self.parser.add_argument('-p', '--prefix', required=True,\n                                 help='Name prefix (e.g. twitter.TwitterSensor:)')\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        prefix = args.prefix\n        key_pairs = self.manager.get_all(prefix=prefix)\n\n        to_delete = []\n        for key_pair in key_pairs:\n            key_pair.id = key_pair.name\n            to_delete.append(key_pair)\n\n        deleted = []\n        for key_pair in to_delete:\n            self.manager.delete(instance=key_pair, **kwargs)\n            deleted.append(key_pair)\n\n        return deleted\n\n    def run_and_print(self, args, **kwargs):\n        # TODO: Need to use args, instead of kwargs (args=) because of bad API\n        # FIX ME\n        deleted = self.run(args, **kwargs)\n        key_ids = [key_pair.id for key_pair in deleted]\n\n        print('Deleted %s keys' % (len(deleted)))\n        print('Deleted key ids: %s' % (', '.join(key_ids)))\n\n\nclass KeyValuePairLoadCommand(resource.ResourceCommand):\n    pk_argument_name = 'name'\n    display_attributes = ['name', 'value']\n\n    def __init__(self, resource, *args, **kwargs):\n        help_text = ('Load a list of %s from file.' %\n                     resource.get_plural_display_name().lower())\n        super(KeyValuePairLoadCommand, self).__init__(resource, 'load',\n            help_text, *args, **kwargs)\n\n        self.parser.add_argument(\n            'file', help=('JSON file containing the %s to create.'\n                          % resource.get_plural_display_name().lower()))\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        file_path = os.path.normpath(pjoin(os.getcwd(), args.file))\n\n        if not os.path.exists(args.file):\n            raise ValueError('File \"%s\" doesn\\'t exist' % (file_path))\n\n        if not os.path.isfile(args.file):\n            raise ValueError('\"%s\" is not a file' % (file_path))\n\n        with open(file_path, 'r') as f:\n            kvps = json.loads(f.read())\n\n        instances = []\n        for item in kvps:\n            name = item['name']\n            value = item['value']\n\n            instance = KeyValuePair()\n            instance.id = name  # TODO: refactor and get rid of id\n            instance.name = name\n            instance.value = value\n\n            self.manager.update(instance, **kwargs)\n            instances.append(instance)\n        return instances\n\n    def run_and_print(self, args, **kwargs):\n        instances = self.run(args, **kwargs)\n        self.print_output(instances, table.MultiColumnTable,\n                          attributes=['id', 'name', 'value'], json=args.json)\n", "path": "st2client/st2client/commands/keyvalue.py"}], "after_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport json\nimport logging\nfrom os.path import join as pjoin\n\nfrom st2client.commands import resource\nfrom st2client.commands.noop import NoopCommand\nfrom st2client.commands.resource import add_auth_token_to_kwargs_from_cli\nfrom st2client.formatters import table\nfrom st2client.models.keyvalue import KeyValuePair\nfrom st2client.utils.date import format_isodate\n\nLOG = logging.getLogger(__name__)\n\n\nclass KeyValuePairBranch(resource.ResourceBranch):\n\n    def __init__(self, description, app, subparsers, parent_parser=None):\n        super(KeyValuePairBranch, self).__init__(\n            KeyValuePair, description, app, subparsers,\n            parent_parser=parent_parser,\n            commands={\n                'list': KeyValuePairListCommand,\n                'get': KeyValuePairGetCommand,\n                'delete': KeyValuePairDeleteCommand,\n                'create': NoopCommand,\n                'update': NoopCommand\n            })\n\n        # Registers extended commands\n        self.commands['set'] = KeyValuePairSetCommand(self.resource, self.app,\n                                                      self.subparsers)\n        self.commands['load'] = KeyValuePairLoadCommand(\n            self.resource, self.app, self.subparsers)\n        self.commands['delete_by_prefix'] = KeyValuePairDeleteByPrefixCommand(\n            self.resource, self.app, self.subparsers)\n\n        # Remove unsupported commands\n        # TODO: Refactor parent class and make it nicer\n        del self.commands['create']\n        del self.commands['update']\n\n\nclass KeyValuePairListCommand(resource.ResourceListCommand):\n    display_attributes = ['name', 'value', 'expire_timestamp']\n    attribute_transform_functions = {\n        'expire_timestamp': format_isodate,\n    }\n\n    def __init__(self, *args, **kwargs):\n        super(KeyValuePairListCommand, self).__init__(*args, **kwargs)\n\n        # Filter options\n        self.parser.add_argument('--prefix', help=('Only return values which name starts with the '\n                                                   ' provided prefix.'))\n\n    def run_and_print(self, args, **kwargs):\n        if args.prefix:\n            kwargs['prefix'] = args.prefix\n\n        instances = self.run(args, **kwargs)\n        self.print_output(reversed(instances), table.MultiColumnTable,\n                          attributes=args.attr, widths=args.width,\n                          json=args.json,\n                          attribute_transform_functions=self.attribute_transform_functions)\n\n\nclass KeyValuePairGetCommand(resource.ResourceGetCommand):\n    pk_argument_name = 'name'\n    display_attributes = ['name', 'value', 'expire_timestamp']\n\n\nclass KeyValuePairSetCommand(resource.ResourceCommand):\n    display_attributes = ['name', 'value', 'expire_timestamp']\n\n    def __init__(self, resource, *args, **kwargs):\n        super(KeyValuePairSetCommand, self).__init__(\n            resource, 'set',\n            'Set an existing %s.' % resource.get_display_name().lower(),\n            *args, **kwargs\n        )\n\n        self.parser.add_argument('name',\n                                 metavar='name',\n                                 help='Name of the key value pair.')\n        self.parser.add_argument('value', help='Value paired with the key.')\n        self.parser.add_argument('-l', '--ttl', dest='ttl', type=int, default=None,\n                                 help='TTL (in seconds) for this value.')\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        instance = KeyValuePair()\n        instance.id = args.name  # TODO: refactor and get rid of id\n        instance.name = args.name\n        instance.value = args.value\n\n        if args.ttl:\n            instance.ttl = args.ttl\n\n        return self.manager.update(instance, **kwargs)\n\n    def run_and_print(self, args, **kwargs):\n        instance = self.run(args, **kwargs)\n        self.print_output(instance, table.PropertyValueTable,\n                          attributes=self.display_attributes, json=args.json)\n\n\nclass KeyValuePairDeleteCommand(resource.ResourceDeleteCommand):\n    pk_argument_name = 'name'\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        resource_id = getattr(args, self.pk_argument_name, None)\n        instance = self.get_resource(resource_id, **kwargs)\n\n        if not instance:\n            raise resource.ResourceNotFoundError('KeyValuePair with id \"%s\" not found', resource_id)\n\n        instance.id = resource_id  # TODO: refactor and get rid of id\n        self.manager.delete(instance, **kwargs)\n\n\nclass KeyValuePairDeleteByPrefixCommand(resource.ResourceCommand):\n    \"\"\"\n    Commands which delete all the key value pairs which match the provided\n    prefix.\n    \"\"\"\n    def __init__(self, resource, *args, **kwargs):\n        super(KeyValuePairDeleteByPrefixCommand, self).__init__(resource, 'delete_by_prefix',\n            'Delete KeyValue pairs which match the provided prefix', *args, **kwargs)\n\n        self.parser.add_argument('-p', '--prefix', required=True,\n                                 help='Name prefix (e.g. twitter.TwitterSensor:)')\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        prefix = args.prefix\n        key_pairs = self.manager.get_all(prefix=prefix)\n\n        to_delete = []\n        for key_pair in key_pairs:\n            key_pair.id = key_pair.name\n            to_delete.append(key_pair)\n\n        deleted = []\n        for key_pair in to_delete:\n            self.manager.delete(instance=key_pair, **kwargs)\n            deleted.append(key_pair)\n\n        return deleted\n\n    def run_and_print(self, args, **kwargs):\n        # TODO: Need to use args, instead of kwargs (args=) because of bad API\n        # FIX ME\n        deleted = self.run(args, **kwargs)\n        key_ids = [key_pair.id for key_pair in deleted]\n\n        print('Deleted %s keys' % (len(deleted)))\n        print('Deleted key ids: %s' % (', '.join(key_ids)))\n\n\nclass KeyValuePairLoadCommand(resource.ResourceCommand):\n    pk_argument_name = 'name'\n    display_attributes = ['name', 'value']\n\n    def __init__(self, resource, *args, **kwargs):\n        help_text = ('Load a list of %s from file.' %\n                     resource.get_plural_display_name().lower())\n        super(KeyValuePairLoadCommand, self).__init__(resource, 'load',\n            help_text, *args, **kwargs)\n\n        self.parser.add_argument(\n            'file', help=('JSON file containing the %s to create.'\n                          % resource.get_plural_display_name().lower()))\n\n    @add_auth_token_to_kwargs_from_cli\n    def run(self, args, **kwargs):\n        file_path = os.path.normpath(pjoin(os.getcwd(), args.file))\n\n        if not os.path.exists(args.file):\n            raise ValueError('File \"%s\" doesn\\'t exist' % (file_path))\n\n        if not os.path.isfile(args.file):\n            raise ValueError('\"%s\" is not a file' % (file_path))\n\n        with open(file_path, 'r') as f:\n            kvps = json.loads(f.read())\n\n        instances = []\n        for item in kvps:\n            name = item['name']\n            value = item['value']\n\n            instance = KeyValuePair()\n            instance.id = name  # TODO: refactor and get rid of id\n            instance.name = name\n            instance.value = value\n\n            self.manager.update(instance, **kwargs)\n            instances.append(instance)\n        return instances\n\n    def run_and_print(self, args, **kwargs):\n        instances = self.run(args, **kwargs)\n        self.print_output(instances, table.MultiColumnTable,\n                          attributes=['id', 'name', 'value'], json=args.json)\n", "path": "st2client/st2client/commands/keyvalue.py"}]}