osc-lib 3.0.1__py3-none-any.whl → 3.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- osc_lib/api/api.py +7 -7
- osc_lib/api/auth.py +3 -4
- osc_lib/cli/client_config.py +10 -9
- osc_lib/cli/parseractions.py +20 -20
- osc_lib/clientmanager.py +4 -4
- osc_lib/command/command.py +2 -2
- osc_lib/exceptions.py +1 -1
- osc_lib/logs.py +1 -1
- osc_lib/shell.py +12 -15
- osc_lib/tests/api/fakes.py +1 -1
- osc_lib/tests/api/test_api.py +5 -5
- osc_lib/tests/api/test_utils.py +1 -1
- osc_lib/tests/cli/test_client_config.py +1 -1
- osc_lib/tests/cli/test_format_columns.py +1 -1
- osc_lib/tests/cli/test_parseractions.py +48 -100
- osc_lib/tests/command/test_timing.py +2 -2
- osc_lib/tests/fakes.py +10 -10
- osc_lib/tests/test_clientmanager.py +1 -1
- osc_lib/tests/test_logs.py +2 -2
- osc_lib/tests/test_shell.py +6 -6
- osc_lib/tests/utils/__init__.py +7 -7
- osc_lib/tests/utils/test_utils.py +3 -3
- osc_lib/utils/__init__.py +4 -4
- osc_lib/utils/columns.py +11 -8
- {osc_lib-3.0.1.dist-info → osc_lib-3.2.0.dist-info}/AUTHORS +2 -0
- {osc_lib-3.0.1.dist-info → osc_lib-3.2.0.dist-info}/METADATA +2 -2
- osc_lib-3.2.0.dist-info/RECORD +51 -0
- osc_lib-3.2.0.dist-info/pbr.json +1 -0
- osc_lib-3.0.1.dist-info/RECORD +0 -51
- osc_lib-3.0.1.dist-info/pbr.json +0 -1
- {osc_lib-3.0.1.dist-info → osc_lib-3.2.0.dist-info}/LICENSE +0 -0
- {osc_lib-3.0.1.dist-info → osc_lib-3.2.0.dist-info}/WHEEL +0 -0
- {osc_lib-3.0.1.dist-info → osc_lib-3.2.0.dist-info}/top_level.txt +0 -0
osc_lib/api/api.py
CHANGED
@@ -15,13 +15,13 @@
|
|
15
15
|
|
16
16
|
from keystoneauth1 import exceptions as ksa_exceptions
|
17
17
|
from keystoneauth1 import session as ksa_session
|
18
|
-
import
|
18
|
+
import requests
|
19
19
|
|
20
20
|
from osc_lib import exceptions
|
21
21
|
from osc_lib.i18n import _
|
22
22
|
|
23
23
|
|
24
|
-
class BaseAPI
|
24
|
+
class BaseAPI:
|
25
25
|
"""Base API wrapper for keystoneauth1.session.Session
|
26
26
|
|
27
27
|
Encapsulate the translation between keystoneauth1.session.Session
|
@@ -58,7 +58,7 @@ class BaseAPI(object):
|
|
58
58
|
Keyword arguments passed to keystoneauth1.session.Session().
|
59
59
|
"""
|
60
60
|
|
61
|
-
super(
|
61
|
+
super().__init__()
|
62
62
|
|
63
63
|
# Create a keystoneauth1.session.Session if one is not supplied
|
64
64
|
if not session:
|
@@ -153,7 +153,7 @@ class BaseAPI(object):
|
|
153
153
|
# Should this move into _requests()?
|
154
154
|
try:
|
155
155
|
return ret.json()
|
156
|
-
except
|
156
|
+
except requests.JSONDecodeError:
|
157
157
|
return ret
|
158
158
|
|
159
159
|
def delete(self, url, session=None, **params):
|
@@ -174,7 +174,7 @@ class BaseAPI(object):
|
|
174
174
|
body=None,
|
175
175
|
detailed=False,
|
176
176
|
headers=None,
|
177
|
-
**params
|
177
|
+
**params,
|
178
178
|
):
|
179
179
|
"""Return a list of resources
|
180
180
|
|
@@ -218,7 +218,7 @@ class BaseAPI(object):
|
|
218
218
|
)
|
219
219
|
try:
|
220
220
|
return ret.json()
|
221
|
-
except
|
221
|
+
except requests.JSONDecodeError:
|
222
222
|
return ret
|
223
223
|
|
224
224
|
# Layered actions built on top of the basic action methods do not
|
@@ -363,7 +363,7 @@ class BaseAPI(object):
|
|
363
363
|
try:
|
364
364
|
ret = self._request(
|
365
365
|
'GET',
|
366
|
-
"
|
366
|
+
f"/{path}/{value}",
|
367
367
|
headers=headers,
|
368
368
|
).json()
|
369
369
|
if isinstance(ret, dict):
|
osc_lib/api/auth.py
CHANGED
@@ -59,9 +59,8 @@ def get_options_list():
|
|
59
59
|
# TODO(mhu) simplistic approach, would be better to only add
|
60
60
|
# help texts if they vary from one auth plugin to another
|
61
61
|
# also the text rendering is ugly in the CLI ...
|
62
|
-
OPTIONS_LIST[os_name]['help'] +=
|
63
|
-
plugin_name
|
64
|
-
o.help,
|
62
|
+
OPTIONS_LIST[os_name]['help'] += (
|
63
|
+
f'With {plugin_name}: {o.help}\n'
|
65
64
|
)
|
66
65
|
return OPTIONS_LIST
|
67
66
|
|
@@ -177,7 +176,7 @@ def build_auth_plugins_option_parser(parser):
|
|
177
176
|
if 'tenant' not in o:
|
178
177
|
parser.add_argument(
|
179
178
|
'--os-' + o,
|
180
|
-
metavar='<auth
|
179
|
+
metavar=f'<auth-{o}>',
|
181
180
|
dest=o.replace('-', '_'),
|
182
181
|
default=envs.get(
|
183
182
|
OPTIONS_LIST[o]['env'],
|
osc_lib/cli/client_config.py
CHANGED
@@ -56,7 +56,7 @@ class OSC_Config(config.OpenStackConfig):
|
|
56
56
|
if not config.get('auth_type', None):
|
57
57
|
config['auth_type'] = 'password'
|
58
58
|
|
59
|
-
LOG.debug("Auth plugin
|
59
|
+
LOG.debug("Auth plugin {} selected".format(config['auth_type']))
|
60
60
|
return config
|
61
61
|
|
62
62
|
def _auth_v2_arguments(self, config):
|
@@ -94,14 +94,15 @@ class OSC_Config(config.OpenStackConfig):
|
|
94
94
|
if config['auth'].pop(prop, None) is not None:
|
95
95
|
if config.get('cloud'):
|
96
96
|
LOG.warning(
|
97
|
-
"Ignoring domain related config
|
98
|
-
"because identity API version is 2.0"
|
99
|
-
|
97
|
+
"Ignoring domain related config {} for {}"
|
98
|
+
"because identity API version is 2.0".format(
|
99
|
+
prop, config['cloud']
|
100
|
+
)
|
100
101
|
)
|
101
102
|
else:
|
102
103
|
LOG.warning(
|
103
|
-
"Ignoring domain related config
|
104
|
-
" identity API version is 2.0"
|
104
|
+
f"Ignoring domain related config {prop} because"
|
105
|
+
" identity API version is 2.0"
|
105
106
|
)
|
106
107
|
return config
|
107
108
|
|
@@ -204,9 +205,9 @@ class OSC_Config(config.OpenStackConfig):
|
|
204
205
|
# Prefer the plugin configuration dest value if the value's key
|
205
206
|
# is marked as depreciated.
|
206
207
|
if p_opt.dest is None:
|
207
|
-
config['auth'][
|
208
|
-
|
209
|
-
|
208
|
+
config['auth'][p_opt.name.replace('-', '_')] = (
|
209
|
+
winning_value
|
210
|
+
)
|
210
211
|
else:
|
211
212
|
config['auth'][p_opt.dest] = winning_value
|
212
213
|
|
osc_lib/cli/parseractions.py
CHANGED
@@ -37,12 +37,12 @@ class KeyValueAction(argparse.Action):
|
|
37
37
|
# NOTE(qtang): Prevent null key setting in property
|
38
38
|
if '' == values_list[0]:
|
39
39
|
msg = _("Property key must be specified: %s")
|
40
|
-
raise argparse.
|
40
|
+
raise argparse.ArgumentError(self, msg % str(values))
|
41
41
|
else:
|
42
42
|
getattr(namespace, self.dest, {}).update([values_list])
|
43
43
|
else:
|
44
44
|
msg = _("Expected 'key=value' type, but got: %s")
|
45
|
-
raise argparse.
|
45
|
+
raise argparse.ArgumentError(self, msg % str(values))
|
46
46
|
|
47
47
|
|
48
48
|
class KeyValueAppendAction(argparse.Action):
|
@@ -62,7 +62,7 @@ class KeyValueAppendAction(argparse.Action):
|
|
62
62
|
# NOTE(qtang): Prevent null key setting in property
|
63
63
|
if '' == key:
|
64
64
|
msg = _("Property key must be specified: %s")
|
65
|
-
raise argparse.
|
65
|
+
raise argparse.ArgumentError(self, msg % str(values))
|
66
66
|
|
67
67
|
dest = getattr(namespace, self.dest)
|
68
68
|
if key in dest:
|
@@ -71,7 +71,7 @@ class KeyValueAppendAction(argparse.Action):
|
|
71
71
|
dest[key] = [value]
|
72
72
|
else:
|
73
73
|
msg = _("Expected 'key=value' type, but got: %s")
|
74
|
-
raise argparse.
|
74
|
+
raise argparse.ArgumentError(self, msg % str(values))
|
75
75
|
|
76
76
|
|
77
77
|
class MultiKeyValueAction(argparse.Action):
|
@@ -91,7 +91,7 @@ class MultiKeyValueAction(argparse.Action):
|
|
91
91
|
nargs=None,
|
92
92
|
required_keys=None,
|
93
93
|
optional_keys=None,
|
94
|
-
**kwargs
|
94
|
+
**kwargs,
|
95
95
|
):
|
96
96
|
"""Initialize the action object, and parse customized options
|
97
97
|
|
@@ -106,9 +106,7 @@ class MultiKeyValueAction(argparse.Action):
|
|
106
106
|
msg = _("Parameter 'nargs' is not allowed, but got %s")
|
107
107
|
raise ValueError(msg % nargs)
|
108
108
|
|
109
|
-
super(
|
110
|
-
option_strings, dest, **kwargs
|
111
|
-
)
|
109
|
+
super().__init__(option_strings, dest, **kwargs)
|
112
110
|
|
113
111
|
# required_keys: A list of keys that is required. None by default.
|
114
112
|
if required_keys and not isinstance(required_keys, list):
|
@@ -136,12 +134,13 @@ class MultiKeyValueAction(argparse.Action):
|
|
136
134
|
"Invalid keys %(invalid_keys)s specified.\n"
|
137
135
|
"Valid keys are: %(valid_keys)s"
|
138
136
|
)
|
139
|
-
raise argparse.
|
137
|
+
raise argparse.ArgumentError(
|
138
|
+
self,
|
140
139
|
msg
|
141
140
|
% {
|
142
141
|
'invalid_keys': ', '.join(invalid_keys),
|
143
142
|
'valid_keys': ', '.join(valid_keys),
|
144
|
-
}
|
143
|
+
},
|
145
144
|
)
|
146
145
|
|
147
146
|
if self.required_keys:
|
@@ -151,12 +150,13 @@ class MultiKeyValueAction(argparse.Action):
|
|
151
150
|
"Missing required keys %(missing_keys)s.\n"
|
152
151
|
"Required keys are: %(required_keys)s"
|
153
152
|
)
|
154
|
-
raise argparse.
|
153
|
+
raise argparse.ArgumentError(
|
154
|
+
self,
|
155
155
|
msg
|
156
156
|
% {
|
157
157
|
'missing_keys': ', '.join(missing_keys),
|
158
158
|
'required_keys': ', '.join(self.required_keys),
|
159
|
-
}
|
159
|
+
},
|
160
160
|
)
|
161
161
|
|
162
162
|
def __call__(self, parser, namespace, values, metavar=None):
|
@@ -166,20 +166,20 @@ class MultiKeyValueAction(argparse.Action):
|
|
166
166
|
|
167
167
|
params = {}
|
168
168
|
for kv in values.split(','):
|
169
|
-
# Add value if an assignment else raise
|
169
|
+
# Add value if an assignment else raise ArgumentError
|
170
170
|
if '=' in kv:
|
171
171
|
kv_list = kv.split('=', 1)
|
172
172
|
# NOTE(qtang): Prevent null key setting in property
|
173
173
|
if '' == kv_list[0]:
|
174
174
|
msg = _("Each property key must be specified: %s")
|
175
|
-
raise argparse.
|
175
|
+
raise argparse.ArgumentError(self, msg % str(kv))
|
176
176
|
else:
|
177
177
|
params.update([kv_list])
|
178
178
|
else:
|
179
179
|
msg = _(
|
180
180
|
"Expected comma separated 'key=value' pairs, but got: %s"
|
181
181
|
)
|
182
|
-
raise argparse.
|
182
|
+
raise argparse.ArgumentError(self, msg % str(kv))
|
183
183
|
|
184
184
|
# Check key validation
|
185
185
|
self.validate_keys(list(params))
|
@@ -209,13 +209,13 @@ class MultiKeyValueCommaAction(MultiKeyValueAction):
|
|
209
209
|
params = {}
|
210
210
|
key = ''
|
211
211
|
for kv in values.split(','):
|
212
|
-
# Add value if an assignment else raise
|
212
|
+
# Add value if an assignment else raise ArgumentError
|
213
213
|
if '=' in kv:
|
214
214
|
kv_list = kv.split('=', 1)
|
215
215
|
# NOTE(qtang): Prevent null key setting in property
|
216
216
|
if '' == kv_list[0]:
|
217
217
|
msg = _("A key must be specified before '=': %s")
|
218
|
-
raise argparse.
|
218
|
+
raise argparse.ArgumentError(self, msg % str(kv))
|
219
219
|
else:
|
220
220
|
params.update([kv_list])
|
221
221
|
key = kv_list[0]
|
@@ -224,10 +224,10 @@ class MultiKeyValueCommaAction(MultiKeyValueAction):
|
|
224
224
|
# means the current value is a part of the previous
|
225
225
|
# key=value pair, so append it.
|
226
226
|
try:
|
227
|
-
params[key] = "
|
227
|
+
params[key] = f"{params[key]},{kv}"
|
228
228
|
except KeyError:
|
229
229
|
msg = _("A key=value pair is required: %s")
|
230
|
-
raise argparse.
|
230
|
+
raise argparse.ArgumentError(self, msg % str(kv))
|
231
231
|
|
232
232
|
# Check key validation
|
233
233
|
self.validate_keys(list(params))
|
@@ -284,4 +284,4 @@ class NonNegativeAction(argparse.Action):
|
|
284
284
|
setattr(namespace, self.dest, values)
|
285
285
|
else:
|
286
286
|
msg = _("%s expected a non-negative integer")
|
287
|
-
raise argparse.
|
287
|
+
raise argparse.ArgumentError(self, msg % str(option_string))
|
osc_lib/clientmanager.py
CHANGED
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
|
|
31
31
|
PLUGIN_MODULES = []
|
32
32
|
|
33
33
|
|
34
|
-
class ClientCache
|
34
|
+
class ClientCache:
|
35
35
|
"""Descriptor class for caching created client handles."""
|
36
36
|
|
37
37
|
def __init__(self, factory):
|
@@ -50,7 +50,7 @@ class ClientCache(object):
|
|
50
50
|
return self._handle
|
51
51
|
|
52
52
|
|
53
|
-
class ClientManager
|
53
|
+
class ClientManager:
|
54
54
|
"""Manages access to API clients, including authentication."""
|
55
55
|
|
56
56
|
# NOTE(dtroyer): Keep around the auth required state of the _current_
|
@@ -150,7 +150,7 @@ class ClientManager(object):
|
|
150
150
|
) and not self._cli_options.auth.get('password'):
|
151
151
|
self._cli_options.auth['password'] = self._pw_callback()
|
152
152
|
|
153
|
-
LOG.
|
153
|
+
LOG.debug('Using auth plugin: %s', self.auth_plugin_name)
|
154
154
|
LOG.debug(
|
155
155
|
'Using parameters %s',
|
156
156
|
strutils.mask_password(self._cli_options.auth),
|
@@ -209,7 +209,7 @@ class ClientManager(object):
|
|
209
209
|
return self._auth_ref
|
210
210
|
|
211
211
|
def _override_for(self, service_type):
|
212
|
-
key = '
|
212
|
+
key = '{}_endpoint_override'.format(service_type.replace('-', '_'))
|
213
213
|
return self._cli_options.config.get(key)
|
214
214
|
|
215
215
|
def is_service_available(self, service_type):
|
osc_lib/command/command.py
CHANGED
@@ -29,13 +29,13 @@ class CommandMeta(abc.ABCMeta):
|
|
29
29
|
cls_dict['log'] = logging.getLogger(
|
30
30
|
cls_dict['__module__'] + '.' + name
|
31
31
|
)
|
32
|
-
return super(
|
32
|
+
return super().__new__(mcs, name, bases, cls_dict)
|
33
33
|
|
34
34
|
|
35
35
|
class Command(command.Command, metaclass=CommandMeta):
|
36
36
|
def run(self, parsed_args):
|
37
37
|
self.log.debug('run(%s)', parsed_args)
|
38
|
-
return super(
|
38
|
+
return super().run(parsed_args)
|
39
39
|
|
40
40
|
def validate_os_beta_command_enabled(self):
|
41
41
|
if not self.app.options.os_beta_command:
|
osc_lib/exceptions.py
CHANGED
osc_lib/logs.py
CHANGED
@@ -114,7 +114,7 @@ class _FileFormatter(logging.Formatter):
|
|
114
114
|
logging.Formatter.__init__(self, self.fmt, self._LOG_DATE_FORMAT)
|
115
115
|
|
116
116
|
|
117
|
-
class LogConfigurator
|
117
|
+
class LogConfigurator:
|
118
118
|
_CONSOLE_MESSAGE_FORMAT = '%(message)s'
|
119
119
|
|
120
120
|
def __init__(self, options):
|
osc_lib/shell.py
CHANGED
@@ -107,7 +107,7 @@ class OpenStackShell(app.App):
|
|
107
107
|
else:
|
108
108
|
cm = command_manager
|
109
109
|
|
110
|
-
super(
|
110
|
+
super().__init__(
|
111
111
|
description=__doc__.strip(),
|
112
112
|
version=version,
|
113
113
|
command_manager=cm,
|
@@ -134,7 +134,7 @@ class OpenStackShell(app.App):
|
|
134
134
|
ret_val = 1
|
135
135
|
self.command_options = argv
|
136
136
|
try:
|
137
|
-
ret_val = super(
|
137
|
+
ret_val = super().run(argv)
|
138
138
|
return ret_val
|
139
139
|
except Exception as e:
|
140
140
|
if not logging.getLogger('').handlers:
|
@@ -147,7 +147,7 @@ class OpenStackShell(app.App):
|
|
147
147
|
return ret_val
|
148
148
|
|
149
149
|
finally:
|
150
|
-
self.log.
|
150
|
+
self.log.debug("END return value: %s", ret_val)
|
151
151
|
|
152
152
|
def init_profile(self):
|
153
153
|
self.do_profile = osprofiler_profiler and self.options.profile
|
@@ -165,20 +165,19 @@ class OpenStackShell(app.App):
|
|
165
165
|
# printed. In fact we can define custom log level here with value
|
166
166
|
# bigger than most big default one (CRITICAL) or something like
|
167
167
|
# that (PROFILE = 60 for instance), but not sure we need it here.
|
168
|
-
self.log.warning("Trace ID:
|
168
|
+
self.log.warning(f"Trace ID: {trace_id}")
|
169
169
|
self.log.warning(
|
170
|
-
"Short trace ID "
|
171
|
-
"for OpenTracing-based drivers: %s" % short_id
|
170
|
+
"Short trace ID " f"for OpenTracing-based drivers: {short_id}"
|
172
171
|
)
|
173
172
|
self.log.warning(
|
174
173
|
"Display trace data with command:\n"
|
175
|
-
"osprofiler trace show --html
|
174
|
+
f"osprofiler trace show --html {trace_id} "
|
176
175
|
)
|
177
176
|
|
178
177
|
def run_subcommand(self, argv):
|
179
178
|
self.init_profile()
|
180
179
|
try:
|
181
|
-
ret_value = super(
|
180
|
+
ret_value = super().run_subcommand(argv)
|
182
181
|
finally:
|
183
182
|
self.close_profile()
|
184
183
|
return ret_value
|
@@ -186,15 +185,13 @@ class OpenStackShell(app.App):
|
|
186
185
|
def interact(self):
|
187
186
|
self.init_profile()
|
188
187
|
try:
|
189
|
-
ret_value = super(
|
188
|
+
ret_value = super().interact()
|
190
189
|
finally:
|
191
190
|
self.close_profile()
|
192
191
|
return ret_value
|
193
192
|
|
194
193
|
def build_option_parser(self, description, version):
|
195
|
-
parser = super(
|
196
|
-
description, version
|
197
|
-
)
|
194
|
+
parser = super().build_option_parser(description, version)
|
198
195
|
|
199
196
|
# service token auth argument
|
200
197
|
parser.add_argument(
|
@@ -416,7 +413,7 @@ class OpenStackShell(app.App):
|
|
416
413
|
"""
|
417
414
|
|
418
415
|
# Parent __init__ parses argv into self.options
|
419
|
-
super(
|
416
|
+
super().initialize_app(argv)
|
420
417
|
self.log.info(
|
421
418
|
"START with options: %s",
|
422
419
|
strutils.mask_password(" ".join(self.command_options)),
|
@@ -435,7 +432,7 @@ class OpenStackShell(app.App):
|
|
435
432
|
'auth_type': self._auth_type,
|
436
433
|
},
|
437
434
|
)
|
438
|
-
except
|
435
|
+
except OSError as e:
|
439
436
|
self.log.critical("Could not read clouds.yaml configuration file")
|
440
437
|
self.print_help_if_requested()
|
441
438
|
raise e
|
@@ -478,7 +475,7 @@ class OpenStackShell(app.App):
|
|
478
475
|
|
479
476
|
def prepare_to_run_command(self, cmd):
|
480
477
|
"""Set up auth and API versions"""
|
481
|
-
self.log.
|
478
|
+
self.log.debug(
|
482
479
|
'command: %s -> %s.%s (auth=%s)',
|
483
480
|
getattr(cmd, 'cmd_name', '<none>'),
|
484
481
|
cmd.__class__.__module__,
|
osc_lib/tests/api/fakes.py
CHANGED
osc_lib/tests/api/test_api.py
CHANGED
@@ -23,7 +23,7 @@ from osc_lib.tests.api import fakes as api_fakes
|
|
23
23
|
|
24
24
|
class TestBaseAPIDefault(api_fakes.TestSession):
|
25
25
|
def setUp(self):
|
26
|
-
super(
|
26
|
+
super().setUp()
|
27
27
|
self.api = api.BaseAPI()
|
28
28
|
|
29
29
|
def test_baseapi_request_no_url(self):
|
@@ -186,7 +186,7 @@ class TestBaseAPIEndpointArg(api_fakes.TestSession):
|
|
186
186
|
|
187
187
|
class TestBaseAPIArgs(api_fakes.TestSession):
|
188
188
|
def setUp(self):
|
189
|
-
super(
|
189
|
+
super().setUp()
|
190
190
|
self.api = api.BaseAPI(
|
191
191
|
session=self.sess,
|
192
192
|
endpoint=self.BASE_URL,
|
@@ -220,7 +220,7 @@ class TestBaseAPIArgs(api_fakes.TestSession):
|
|
220
220
|
|
221
221
|
class TestBaseAPICreate(api_fakes.TestSession):
|
222
222
|
def setUp(self):
|
223
|
-
super(
|
223
|
+
super().setUp()
|
224
224
|
self.api = api.BaseAPI(
|
225
225
|
session=self.sess,
|
226
226
|
endpoint=self.BASE_URL,
|
@@ -258,7 +258,7 @@ class TestBaseAPICreate(api_fakes.TestSession):
|
|
258
258
|
|
259
259
|
class TestBaseAPIFind(api_fakes.TestSession):
|
260
260
|
def setUp(self):
|
261
|
-
super(
|
261
|
+
super().setUp()
|
262
262
|
self.api = api.BaseAPI(
|
263
263
|
session=self.sess,
|
264
264
|
endpoint=self.BASE_URL,
|
@@ -452,7 +452,7 @@ class TestBaseAPIFind(api_fakes.TestSession):
|
|
452
452
|
|
453
453
|
class TestBaseAPIList(api_fakes.TestSession):
|
454
454
|
def setUp(self):
|
455
|
-
super(
|
455
|
+
super().setUp()
|
456
456
|
self.api = api.BaseAPI(
|
457
457
|
session=self.sess,
|
458
458
|
endpoint=self.BASE_URL,
|
osc_lib/tests/api/test_utils.py
CHANGED
@@ -104,7 +104,7 @@ class TestListDictColumn(utils.TestCase):
|
|
104
104
|
# OrderedDict is a subclass of dict and would inadvertently pass
|
105
105
|
self.assertEqual(type(col.machine_readable()), list) # noqa: H212
|
106
106
|
for x in col.machine_readable():
|
107
|
-
self.assertEqual(type(x), dict) # noqa:
|
107
|
+
self.assertEqual(type(x), dict) # noqa: H211
|
108
108
|
|
109
109
|
|
110
110
|
class TestSizeColumn(utils.TestCase):
|
@@ -21,7 +21,7 @@ from osc_lib.tests import utils
|
|
21
21
|
|
22
22
|
class TestKeyValueAction(utils.TestCase):
|
23
23
|
def setUp(self):
|
24
|
-
super(
|
24
|
+
super().setUp()
|
25
25
|
|
26
26
|
self.parser = argparse.ArgumentParser()
|
27
27
|
|
@@ -68,14 +68,12 @@ class TestKeyValueAction(utils.TestCase):
|
|
68
68
|
],
|
69
69
|
]
|
70
70
|
for data in data_list:
|
71
|
-
self.assertRaises(
|
72
|
-
argparse.ArgumentTypeError, self.parser.parse_args, data
|
73
|
-
)
|
71
|
+
self.assertRaises(SystemExit, self.parser.parse_args, data)
|
74
72
|
|
75
73
|
|
76
74
|
class TestKeyValueAppendAction(utils.TestCase):
|
77
75
|
def setUp(self):
|
78
|
-
super(
|
76
|
+
super().setUp()
|
79
77
|
|
80
78
|
self.parser = argparse.ArgumentParser()
|
81
79
|
|
@@ -129,14 +127,12 @@ class TestKeyValueAppendAction(utils.TestCase):
|
|
129
127
|
],
|
130
128
|
]
|
131
129
|
for data in data_list:
|
132
|
-
self.assertRaises(
|
133
|
-
argparse.ArgumentTypeError, self.parser.parse_args, data
|
134
|
-
)
|
130
|
+
self.assertRaises(SystemExit, self.parser.parse_args, data)
|
135
131
|
|
136
132
|
|
137
133
|
class TestMultiKeyValueAction(utils.TestCase):
|
138
134
|
def setUp(self):
|
139
|
-
super(
|
135
|
+
super().setUp()
|
140
136
|
|
141
137
|
self.parser = argparse.ArgumentParser()
|
142
138
|
|
@@ -213,13 +209,11 @@ class TestMultiKeyValueAction(utils.TestCase):
|
|
213
209
|
],
|
214
210
|
]
|
215
211
|
for data in data_list:
|
216
|
-
self.assertRaises(
|
217
|
-
argparse.ArgumentTypeError, self.parser.parse_args, data
|
218
|
-
)
|
212
|
+
self.assertRaises(SystemExit, self.parser.parse_args, data)
|
219
213
|
|
220
214
|
def test_error_values_without_comma(self):
|
221
215
|
self.assertRaises(
|
222
|
-
|
216
|
+
SystemExit,
|
223
217
|
self.parser.parse_args,
|
224
218
|
[
|
225
219
|
'--test',
|
@@ -229,7 +223,7 @@ class TestMultiKeyValueAction(utils.TestCase):
|
|
229
223
|
|
230
224
|
def test_missing_key(self):
|
231
225
|
self.assertRaises(
|
232
|
-
|
226
|
+
SystemExit,
|
233
227
|
self.parser.parse_args,
|
234
228
|
[
|
235
229
|
'--test',
|
@@ -239,7 +233,7 @@ class TestMultiKeyValueAction(utils.TestCase):
|
|
239
233
|
|
240
234
|
def test_invalid_key(self):
|
241
235
|
self.assertRaises(
|
242
|
-
|
236
|
+
SystemExit,
|
243
237
|
self.parser.parse_args,
|
244
238
|
[
|
245
239
|
'--test',
|
@@ -278,7 +272,7 @@ class TestMultiKeyValueAction(utils.TestCase):
|
|
278
272
|
|
279
273
|
class TestMultiKeyValueCommaAction(utils.TestCase):
|
280
274
|
def setUp(self):
|
281
|
-
super(
|
275
|
+
super().setUp()
|
282
276
|
self.parser = argparse.ArgumentParser()
|
283
277
|
|
284
278
|
# Typical usage
|
@@ -361,21 +355,16 @@ class TestMultiKeyValueCommaAction(utils.TestCase):
|
|
361
355
|
]
|
362
356
|
self.assertCountEqual(expect, actual)
|
363
357
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
except argparse.ArgumentTypeError as e:
|
375
|
-
self.assertEqual(
|
376
|
-
'Missing required keys req1.\nRequired keys are: req1',
|
377
|
-
str(e),
|
378
|
-
)
|
358
|
+
self.assertRaises(
|
359
|
+
SystemExit,
|
360
|
+
self.parser.parse_args,
|
361
|
+
[
|
362
|
+
'--test',
|
363
|
+
'req1=aaa,bbb',
|
364
|
+
'--test',
|
365
|
+
'opt2=ccc',
|
366
|
+
],
|
367
|
+
)
|
379
368
|
|
380
369
|
def test_mkvca_multiples(self):
|
381
370
|
results = self.parser.parse_args(
|
@@ -431,75 +420,34 @@ class TestMultiKeyValueCommaAction(utils.TestCase):
|
|
431
420
|
self.assertCountEqual(expect, actual)
|
432
421
|
|
433
422
|
def test_mkvca_invalid_key(self):
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
str(e),
|
446
|
-
)
|
447
|
-
|
448
|
-
try:
|
449
|
-
self.parser.parse_args(
|
450
|
-
[
|
451
|
-
'--test',
|
452
|
-
'nnn=aaa',
|
453
|
-
]
|
454
|
-
)
|
455
|
-
self.fail('ArgumentTypeError should be raised')
|
456
|
-
except argparse.ArgumentTypeError as e:
|
457
|
-
self.assertIn(
|
458
|
-
'Invalid keys nnn specified.\nValid keys are:',
|
459
|
-
str(e),
|
460
|
-
)
|
423
|
+
self.assertRaises(
|
424
|
+
SystemExit,
|
425
|
+
self.parser.parse_args,
|
426
|
+
['--test', 'req1=aaa,bbb='],
|
427
|
+
)
|
428
|
+
|
429
|
+
self.assertRaises(
|
430
|
+
SystemExit,
|
431
|
+
self.parser.parse_args,
|
432
|
+
['--test', 'nnn=aaa'],
|
433
|
+
)
|
461
434
|
|
462
435
|
def test_mkvca_value_no_key(self):
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
self.
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
[
|
479
|
-
'--test',
|
480
|
-
'=nnn',
|
481
|
-
]
|
482
|
-
)
|
483
|
-
self.fail('ArgumentTypeError should be raised')
|
484
|
-
except argparse.ArgumentTypeError as e:
|
485
|
-
self.assertEqual(
|
486
|
-
"A key must be specified before '=': =nnn",
|
487
|
-
str(e),
|
488
|
-
)
|
489
|
-
|
490
|
-
try:
|
491
|
-
self.parser.parse_args(
|
492
|
-
[
|
493
|
-
'--test',
|
494
|
-
'nnn',
|
495
|
-
]
|
496
|
-
)
|
497
|
-
self.fail('ArgumentTypeError should be raised')
|
498
|
-
except argparse.ArgumentTypeError as e:
|
499
|
-
self.assertIn(
|
500
|
-
'A key=value pair is required:',
|
501
|
-
str(e),
|
502
|
-
)
|
436
|
+
self.assertRaises(
|
437
|
+
SystemExit,
|
438
|
+
self.parser.parse_args,
|
439
|
+
['--test', 'req1=aaa,=bbb'],
|
440
|
+
)
|
441
|
+
self.assertRaises(
|
442
|
+
SystemExit,
|
443
|
+
self.parser.parse_args,
|
444
|
+
['--test', '=nnn'],
|
445
|
+
)
|
446
|
+
self.assertRaises(
|
447
|
+
SystemExit,
|
448
|
+
self.parser.parse_args,
|
449
|
+
['--test', 'nnn'],
|
450
|
+
)
|
503
451
|
|
504
452
|
def test_mkvca_required_keys_not_list(self):
|
505
453
|
self.assertRaises(
|
@@ -532,7 +480,7 @@ class TestMultiKeyValueCommaAction(utils.TestCase):
|
|
532
480
|
|
533
481
|
class TestNonNegativeAction(utils.TestCase):
|
534
482
|
def setUp(self):
|
535
|
-
super(
|
483
|
+
super().setUp()
|
536
484
|
|
537
485
|
self.parser = argparse.ArgumentParser()
|
538
486
|
|
@@ -546,7 +494,7 @@ class TestNonNegativeAction(utils.TestCase):
|
|
546
494
|
|
547
495
|
def test_negative_values(self):
|
548
496
|
self.assertRaises(
|
549
|
-
|
497
|
+
SystemExit,
|
550
498
|
self.parser.parse_args,
|
551
499
|
"--foo -1".split(),
|
552
500
|
)
|
@@ -27,7 +27,7 @@ timing_url = 'http://localhost:5000'
|
|
27
27
|
timing_elapsed = 0.872809
|
28
28
|
|
29
29
|
|
30
|
-
class FakeGenericClient
|
30
|
+
class FakeGenericClient:
|
31
31
|
def __init__(self, **kwargs):
|
32
32
|
self.auth_token = kwargs['token']
|
33
33
|
self.management_url = kwargs['endpoint']
|
@@ -40,7 +40,7 @@ class TestTiming(utils.TestCommand):
|
|
40
40
|
)
|
41
41
|
|
42
42
|
def setUp(self):
|
43
|
-
super(
|
43
|
+
super().setUp()
|
44
44
|
|
45
45
|
self.app.timing_data = []
|
46
46
|
|
osc_lib/tests/fakes.py
CHANGED
@@ -60,12 +60,12 @@ def to_unicode_dict(catalog_dict):
|
|
60
60
|
elif isinstance(catalog_dict, list):
|
61
61
|
return [to_unicode_dict(element) for element in catalog_dict]
|
62
62
|
elif isinstance(catalog_dict, str):
|
63
|
-
return catalog_dict +
|
63
|
+
return catalog_dict + ""
|
64
64
|
else:
|
65
65
|
return catalog_dict
|
66
66
|
|
67
67
|
|
68
|
-
class FakeStdout
|
68
|
+
class FakeStdout:
|
69
69
|
def __init__(self):
|
70
70
|
self.content = []
|
71
71
|
|
@@ -79,7 +79,7 @@ class FakeStdout(object):
|
|
79
79
|
return result
|
80
80
|
|
81
81
|
|
82
|
-
class FakeLog
|
82
|
+
class FakeLog:
|
83
83
|
def __init__(self):
|
84
84
|
self.messages = {}
|
85
85
|
|
@@ -99,7 +99,7 @@ class FakeLog(object):
|
|
99
99
|
self.messages['critical'] = msg
|
100
100
|
|
101
101
|
|
102
|
-
class FakeApp
|
102
|
+
class FakeApp:
|
103
103
|
def __init__(self, _stdout, _log):
|
104
104
|
self.stdout = _stdout
|
105
105
|
self.client_manager = None
|
@@ -110,12 +110,12 @@ class FakeApp(object):
|
|
110
110
|
self.log = _log
|
111
111
|
|
112
112
|
|
113
|
-
class FakeOptions
|
113
|
+
class FakeOptions:
|
114
114
|
def __init__(self, **kwargs):
|
115
115
|
self.os_beta_command = False
|
116
116
|
|
117
117
|
|
118
|
-
class FakeClientManager
|
118
|
+
class FakeClientManager:
|
119
119
|
def __init__(self):
|
120
120
|
self.compute = None
|
121
121
|
self.identity = None
|
@@ -139,7 +139,7 @@ class FakeClientManager(object):
|
|
139
139
|
}
|
140
140
|
|
141
141
|
|
142
|
-
class FakeModule
|
142
|
+
class FakeModule:
|
143
143
|
def __init__(self, name, version):
|
144
144
|
self.name = name
|
145
145
|
self.__version__ = version
|
@@ -148,7 +148,7 @@ class FakeModule(object):
|
|
148
148
|
self.version.__version__ = version
|
149
149
|
|
150
150
|
|
151
|
-
class FakeResource
|
151
|
+
class FakeResource:
|
152
152
|
def __init__(self, manager=None, info=None, loaded=False, methods=None):
|
153
153
|
"""Set attributes and methods for a resource.
|
154
154
|
|
@@ -191,8 +191,8 @@ class FakeResource(object):
|
|
191
191
|
reprkeys = sorted(
|
192
192
|
k for k in self.__dict__.keys() if k[0] != '_' and k != 'manager'
|
193
193
|
)
|
194
|
-
info = ", ".join("
|
195
|
-
return "
|
194
|
+
info = ", ".join(f"{k}={getattr(self, k)}" for k in reprkeys)
|
195
|
+
return f"<{self.__class__.__name__} {info}>"
|
196
196
|
|
197
197
|
def keys(self):
|
198
198
|
return self._info.keys()
|
osc_lib/tests/test_logs.py
CHANGED
@@ -76,7 +76,7 @@ class TestFileFormatter(utils.TestCase):
|
|
76
76
|
)
|
77
77
|
|
78
78
|
def test_options(self):
|
79
|
-
class Opts
|
79
|
+
class Opts:
|
80
80
|
cloud = 'cloudy'
|
81
81
|
os_project_name = 'projecty'
|
82
82
|
username = 'usernamey'
|
@@ -107,7 +107,7 @@ class TestFileFormatter(utils.TestCase):
|
|
107
107
|
|
108
108
|
class TestLogConfigurator(utils.TestCase):
|
109
109
|
def setUp(self):
|
110
|
-
super(
|
110
|
+
super().setUp()
|
111
111
|
self.options = mock.Mock()
|
112
112
|
self.options.verbose_level = 1
|
113
113
|
self.options.log_file = None
|
osc_lib/tests/test_shell.py
CHANGED
@@ -123,7 +123,7 @@ class TestShellArgV(utils.TestShell):
|
|
123
123
|
"""Test the deferred help flag"""
|
124
124
|
|
125
125
|
def setUp(self):
|
126
|
-
super(
|
126
|
+
super().setUp()
|
127
127
|
|
128
128
|
def test_shell_argv(self):
|
129
129
|
"""Test argv decoding
|
@@ -148,14 +148,14 @@ class TestShellArgV(utils.TestShell):
|
|
148
148
|
|
149
149
|
# When shell.main() gets sys.argv itself it should be decoded
|
150
150
|
shell.main()
|
151
|
-
self.assertEqual(
|
151
|
+
self.assertEqual(str, type(self.app.call_args[0][0][0]))
|
152
152
|
|
153
153
|
|
154
154
|
class TestShellHelp(utils.TestShell):
|
155
155
|
"""Test the deferred help flag"""
|
156
156
|
|
157
157
|
def setUp(self):
|
158
|
-
super(
|
158
|
+
super().setUp()
|
159
159
|
self.useFixture(utils.EnvFixture())
|
160
160
|
|
161
161
|
@testtools.skip("skip until bug 1444983 is resolved")
|
@@ -182,7 +182,7 @@ class TestShellOptions(utils.TestShell):
|
|
182
182
|
"""
|
183
183
|
|
184
184
|
def setUp(self):
|
185
|
-
super(
|
185
|
+
super().setUp()
|
186
186
|
self.useFixture(utils.EnvFixture())
|
187
187
|
|
188
188
|
def test_empty_auth(self):
|
@@ -213,7 +213,7 @@ class TestShellCli(utils.TestShell):
|
|
213
213
|
"""
|
214
214
|
|
215
215
|
def setUp(self):
|
216
|
-
super(
|
216
|
+
super().setUp()
|
217
217
|
env = {}
|
218
218
|
self.useFixture(utils.EnvFixture(env.copy()))
|
219
219
|
|
@@ -465,7 +465,7 @@ class TestShellCliPrecedence(utils.TestShell):
|
|
465
465
|
"""Test option precedencr order"""
|
466
466
|
|
467
467
|
def setUp(self):
|
468
|
-
super(
|
468
|
+
super().setUp()
|
469
469
|
env = {
|
470
470
|
'OS_CLOUD': 'megacloud',
|
471
471
|
'OS_REGION_NAME': 'occ-env',
|
osc_lib/tests/utils/__init__.py
CHANGED
@@ -108,7 +108,7 @@ class TestCase(testtools.TestCase):
|
|
108
108
|
|
109
109
|
if m.called:
|
110
110
|
if not msg:
|
111
|
-
msg = 'method
|
111
|
+
msg = f'method {m} should not have been called'
|
112
112
|
self.fail(msg)
|
113
113
|
|
114
114
|
@contextlib.contextmanager
|
@@ -120,7 +120,7 @@ class TestCase(testtools.TestCase):
|
|
120
120
|
* bug in testtools that breaks support for all versions
|
121
121
|
"""
|
122
122
|
try:
|
123
|
-
with super(
|
123
|
+
with super().subTest(*args, **kwargs):
|
124
124
|
yield
|
125
125
|
except TypeError:
|
126
126
|
raise
|
@@ -134,7 +134,7 @@ class TestCommand(TestCase):
|
|
134
134
|
"""Test cliff command classes"""
|
135
135
|
|
136
136
|
def setUp(self):
|
137
|
-
super(
|
137
|
+
super().setUp()
|
138
138
|
# Build up a fake app
|
139
139
|
self.fake_stdout = fakes.FakeStdout()
|
140
140
|
self.fake_log = fakes.FakeLog()
|
@@ -201,7 +201,7 @@ class TestClientManager(TestCase):
|
|
201
201
|
}
|
202
202
|
|
203
203
|
def setUp(self):
|
204
|
-
super(
|
204
|
+
super().setUp()
|
205
205
|
self.mock = mock.Mock()
|
206
206
|
self.requests = self.useFixture(fixture.Fixture())
|
207
207
|
# fake v2password token retrieval
|
@@ -319,7 +319,7 @@ class TestShell(TestCase):
|
|
319
319
|
shell_class_name = "osc_lib.shell.OpenStackShell"
|
320
320
|
|
321
321
|
def setUp(self):
|
322
|
-
super(
|
322
|
+
super().setUp()
|
323
323
|
self.shell_class = importutils.import_class(self.shell_class_name)
|
324
324
|
self.cmd_patch = mock.patch(self.shell_class_name + ".run_subcommand")
|
325
325
|
self.cmd_save = self.cmd_patch.start()
|
@@ -349,7 +349,7 @@ class TestShell(TestCase):
|
|
349
349
|
self.assertEqual(
|
350
350
|
default_args[k],
|
351
351
|
vars(_shell.options)[k],
|
352
|
-
"
|
352
|
+
f"{k} does not match",
|
353
353
|
)
|
354
354
|
|
355
355
|
def _assert_cloud_region_arg(self, cmd_options, default_args):
|
@@ -377,7 +377,7 @@ class TestShell(TestCase):
|
|
377
377
|
self.assertEqual(
|
378
378
|
default_args[k],
|
379
379
|
vars(opts)[k],
|
380
|
-
"
|
380
|
+
f"{k} does not match",
|
381
381
|
)
|
382
382
|
|
383
383
|
def _test_options_init_app(self, test_opts):
|
@@ -368,7 +368,7 @@ class TestUtils(test_utils.TestCase):
|
|
368
368
|
self.assertFalse(utils.is_ascii(b'\xe2'))
|
369
369
|
|
370
370
|
def test_is_ascii_string(self):
|
371
|
-
self.assertFalse(utils.is_ascii(
|
371
|
+
self.assertFalse(utils.is_ascii('\u2665'))
|
372
372
|
|
373
373
|
def test_format_size(self):
|
374
374
|
self.assertEqual("999", utils.format_size(999))
|
@@ -544,7 +544,7 @@ class NoUniqueMatch(Exception):
|
|
544
544
|
|
545
545
|
class TestFindResource(test_utils.TestCase):
|
546
546
|
def setUp(self):
|
547
|
-
super(
|
547
|
+
super().setUp()
|
548
548
|
self.name = 'legos'
|
549
549
|
self.expected = mock.Mock()
|
550
550
|
self.manager = mock.Mock()
|
@@ -920,7 +920,7 @@ class TestAssertItemEqual(test_utils.TestCommand):
|
|
920
920
|
|
921
921
|
class TestSDKUtils(test_utils.TestCase):
|
922
922
|
def setUp(self):
|
923
|
-
super(
|
923
|
+
super().setUp()
|
924
924
|
|
925
925
|
def _test_get_osc_show_columns_for_sdk_resource(
|
926
926
|
self,
|
osc_lib/utils/__init__.py
CHANGED
@@ -345,7 +345,7 @@ def format_dict_of_list(data, separator='; '):
|
|
345
345
|
if value is None:
|
346
346
|
continue
|
347
347
|
value_str = format_list(value)
|
348
|
-
group = "
|
348
|
+
group = f"{key}={value_str}"
|
349
349
|
output.append(group)
|
350
350
|
|
351
351
|
return separator.join(output)
|
@@ -400,10 +400,10 @@ def format_size(size):
|
|
400
400
|
index = index + 1
|
401
401
|
size = size / base
|
402
402
|
|
403
|
-
padded = '
|
403
|
+
padded = f'{size:.1f}'
|
404
404
|
stripped = padded.rstrip('0').rstrip('.')
|
405
405
|
|
406
|
-
return '
|
406
|
+
return f'{stripped}{suffix[index]}'
|
407
407
|
|
408
408
|
|
409
409
|
def get_client_class(api_name, version, version_map):
|
@@ -596,7 +596,7 @@ def read_blob_file_contents(blob_file):
|
|
596
596
|
with open(blob_file) as file:
|
597
597
|
blob = file.read().strip()
|
598
598
|
return blob
|
599
|
-
except
|
599
|
+
except OSError:
|
600
600
|
msg = _("Error occurred trying to read from file %s")
|
601
601
|
raise exceptions.CommandError(msg % blob_file)
|
602
602
|
|
osc_lib/utils/columns.py
CHANGED
@@ -29,9 +29,11 @@ def get_column_definitions(attr_map, long_listing):
|
|
29
29
|
|
30
30
|
.. code-block:: python
|
31
31
|
|
32
|
-
(
|
33
|
-
|
34
|
-
|
32
|
+
(
|
33
|
+
('id', 'ID', LIST_BOTH),
|
34
|
+
('name', 'Name', LIST_BOTH),
|
35
|
+
('tenant_id', 'Project', LIST_LONG_ONLY),
|
36
|
+
)
|
35
37
|
|
36
38
|
The third field of each tuple must be one of LIST_BOTH,
|
37
39
|
LIST_LONG_ONLY (a corresponding column is shown only in a long mode),
|
@@ -80,17 +82,18 @@ def get_columns(item, attr_map=None):
|
|
80
82
|
|
81
83
|
.. code-block:: python
|
82
84
|
|
83
|
-
{'id': 'myid', 'name': 'myname',
|
84
|
-
'foo': 'bar', 'tenant_id': 'mytenan'}
|
85
|
+
{'id': 'myid', 'name': 'myname', 'foo': 'bar', 'tenant_id': 'mytenan'}
|
85
86
|
|
86
87
|
:param attr_map: a list of mapping from attribute to display name.
|
87
88
|
The same format is used as for get_column_definitions attr_map.
|
88
89
|
|
89
90
|
.. code-block:: python
|
90
91
|
|
91
|
-
(
|
92
|
-
|
93
|
-
|
92
|
+
(
|
93
|
+
('id', 'ID', LIST_BOTH),
|
94
|
+
('name', 'Name', LIST_BOTH),
|
95
|
+
('tenant_id', 'Project', LIST_LONG_ONLY),
|
96
|
+
)
|
94
97
|
|
95
98
|
:return: A pair of tuple of attributes and tuple of display names.
|
96
99
|
|
@@ -107,6 +107,7 @@ OpenStack Release Bot <infra-root@openstack.org>
|
|
107
107
|
Paul Belanger <paul.belanger@polybeacon.com>
|
108
108
|
Qiu Yu <qiuyu@ebaysf.com>
|
109
109
|
Rabi Mishra <ramishra@redhat.com>
|
110
|
+
Radoslaw Smigielski <rsmigiel@redhat.com>
|
110
111
|
Reedip <reedip14@gmail.com>
|
111
112
|
Riccardo Pittau <elfosardo@gmail.com>
|
112
113
|
Richard Theis <rtheis@us.ibm.com>
|
@@ -123,6 +124,7 @@ Stephen Finucane <stephenfin@redhat.com>
|
|
123
124
|
Steve Martinelli <s.martinelli@gmail.com>
|
124
125
|
Steve Martinelli <stevemar@ca.ibm.com>
|
125
126
|
Swapnil Kulkarni (coolsvap) <me@coolsvap.net>
|
127
|
+
Takashi Kajinami <kajinamit@oss.nttdata.com>
|
126
128
|
Takashi Kajinami <tkajinam@redhat.com>
|
127
129
|
Tang Chen <chen.tang@easystack.cn>
|
128
130
|
Tang Chen <tangchen@cn.fujitsu.com>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: osc-lib
|
3
|
-
Version: 3.0
|
3
|
+
Version: 3.2.0
|
4
4
|
Summary: OpenStackClient Library
|
5
5
|
Home-page: https://docs.openstack.org/osc-lib/latest/
|
6
6
|
Author: OpenStack
|
@@ -26,7 +26,7 @@ Requires-Dist: openstacksdk (>=0.15.0)
|
|
26
26
|
Requires-Dist: oslo.i18n (>=3.15.3)
|
27
27
|
Requires-Dist: oslo.utils (>=3.33.0)
|
28
28
|
Requires-Dist: pbr (!=2.1.0,>=2.0.0)
|
29
|
-
Requires-Dist:
|
29
|
+
Requires-Dist: requests (>=2.14.2)
|
30
30
|
Requires-Dist: stevedore (>=1.20.0)
|
31
31
|
|
32
32
|
=======
|
@@ -0,0 +1,51 @@
|
|
1
|
+
osc_lib/__init__.py,sha256=2NlShJ0jsku4xvwHtwbX_7-stc3huuMyfzohJcBZPGQ,673
|
2
|
+
osc_lib/clientmanager.py,sha256=zbTboCTVgeySRT5HaZOwt263bMAg3f33jBQIP5RH7aU,9812
|
3
|
+
osc_lib/exceptions.py,sha256=QfwLbvwyMNvQV63ZKdaTCLZrFhARoLBFG_Wyyf-9CY8,3439
|
4
|
+
osc_lib/i18n.py,sha256=Be2g7dxbMzzryhCecbgiAw5lHtfSQwVbAO8kC9dGvWo,783
|
5
|
+
osc_lib/logs.py,sha256=JamCFbUSqFGcbVXfxEyJQOPPvpGnlPjhSX0kpIE-U40,7119
|
6
|
+
osc_lib/shell.py,sha256=xRyEJmIo5IdVVF2AztRojNXnrSM_U7PZ7MTHhue4fKg,19050
|
7
|
+
osc_lib/version.py,sha256=Csam3SVWQ7sUSXbOOBIPyv9DAHv_EfMIPpExsXYMVX0,710
|
8
|
+
osc_lib/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
osc_lib/api/api.py,sha256=Kleyt_9F_7-_l2UsTCtwl4yDXI7u4qG75u0QU9YFBa4,12526
|
10
|
+
osc_lib/api/auth.py,sha256=u-gic_JCqF3nNbRV2mTWz9Vdybf2_48DfkbvkCIFQz4,8150
|
11
|
+
osc_lib/api/utils.py,sha256=JDpM-vQUeEL_vYBYfj-WVM_mAhxA6KDmnTTYU9TleYY,3159
|
12
|
+
osc_lib/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
osc_lib/cli/client_config.py,sha256=OqnwNm6ehFtjuxKYpYy4HFSs-bjP3inq2yGUxoheGU8,9510
|
14
|
+
osc_lib/cli/format_columns.py,sha256=loM4At-VhjR6rMNYO4w5RnuoGGr9zq5LsPC_3UaYXSY,1918
|
15
|
+
osc_lib/cli/identity.py,sha256=TIJDIEFJLKKE_HrFePxkelkev6DHuVrwo8DpJgivFs0,2711
|
16
|
+
osc_lib/cli/parseractions.py,sha256=Dj-7bHFzhxOS0DkFtr0ocafFDhE7aSpPmn2gxtMmXYs,10682
|
17
|
+
osc_lib/command/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
+
osc_lib/command/command.py,sha256=nmr6MEWXQxWzbSBuCz-VMQFh9giz6tHOlJ1bzxbFeQY,1967
|
19
|
+
osc_lib/command/commandmanager.py,sha256=s9lWu5lMKqrzasUDcK-KfJRpPCTHbC7ZYnd3Fztk_pg,761
|
20
|
+
osc_lib/command/timing.py,sha256=TGRfuhkYp-eFO-CqeEDRe_km4OiqzaybXWOPehXLoUg,1139
|
21
|
+
osc_lib/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
+
osc_lib/tests/fakes.py,sha256=i08gNu-qPtYIb5Gmk3vpDrq2RCxytOeyW0NHkhUXeZg,5720
|
23
|
+
osc_lib/tests/test_clientmanager.py,sha256=_pMlhjtxkIU5pWocs_CH8-iRaA0nkskLC6aWlNPLahs,15577
|
24
|
+
osc_lib/tests/test_logs.py,sha256=iZX3WqkNZCooe4U6j5dWVwJ4gfgMcTUGxPFnmUvBhzs,8797
|
25
|
+
osc_lib/tests/test_shell.py,sha256=PZqMq_tIP5rHMKm7MPoU78dOu8f6W5BfQa8jBAz4x50,20106
|
26
|
+
osc_lib/tests/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
+
osc_lib/tests/api/fakes.py,sha256=gz5ioOnBzh32Vbka6RSfAvC8OYnF0fxliNYENwUOPvg,1342
|
28
|
+
osc_lib/tests/api/test_api.py,sha256=hIomMc-aoWK7sTWFNARd-o3qMX4kfpRx3h-9T5zOZaE,16572
|
29
|
+
osc_lib/tests/api/test_utils.py,sha256=RSO4M8vD0GJXlxglXKgyZxHGeRqKgU8uzdQqiUMMVGI,3351
|
30
|
+
osc_lib/tests/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
+
osc_lib/tests/cli/test_client_config.py,sha256=vT-CGfEcYrfQuMKs4Nvk4fjCOKJY1vYXooip0r3UaWs,8464
|
32
|
+
osc_lib/tests/cli/test_format_columns.py,sha256=RAybYwa8ow4XjsSGjP8-T1D5pJ7bM89giLrRAJG3fps,4391
|
33
|
+
osc_lib/tests/cli/test_identity.py,sha256=-jJ4p0R4dCkgAJffOhjRcpB2qMa7OE10efbflA0B2ss,3375
|
34
|
+
osc_lib/tests/cli/test_parseractions.py,sha256=qeDIKPD0OEbEnLFgdOMSDrHOLLrMMFf2Z7j5wPMDyZA,13749
|
35
|
+
osc_lib/tests/command/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
|
+
osc_lib/tests/command/test_command.py,sha256=nCf51tbJOFQ4sQEOuaWJG4UkXmexfPED5zYzoTJ1WyI,1682
|
37
|
+
osc_lib/tests/command/test_timing.py,sha256=UtrhOMVxE4qg9x0PIXI-ExPqvAfZCZgTallMJZn0ZUo,3058
|
38
|
+
osc_lib/tests/utils/__init__.py,sha256=NTiJa_drt74jCReAbM9NtxaZh28rwlpHmq45gEcx4xA,14475
|
39
|
+
osc_lib/tests/utils/test_columns.py,sha256=OkVy-Soy899JHpNNiGZOVDsQibjwaz47lAz9bO7_9Ro,2445
|
40
|
+
osc_lib/tests/utils/test_tags.py,sha256=TlD14ggSzYLEEC4ZbFTdRckz6b8M5-3MAwV0lHU12vI,11745
|
41
|
+
osc_lib/tests/utils/test_utils.py,sha256=OpqrADPVDVlg8fr5hBbXmERZsvJMUBHKa0yJi3n_YPE,35425
|
42
|
+
osc_lib/utils/__init__.py,sha256=ZGcDIABzYFcnafwtHW1XYI27GwHNxsjjXriqoP0xDdc,27973
|
43
|
+
osc_lib/utils/columns.py,sha256=RWDddoXe4ghHMPkADZ3lBq3SLUgTM9zhRQh6iLBfq0c,4021
|
44
|
+
osc_lib/utils/tags.py,sha256=-OTKm4Bhv6GZAzO-yTOXP10uiYurN1sK3Rf1yb07r0M,7971
|
45
|
+
osc_lib-3.2.0.dist-info/AUTHORS,sha256=Z102Ulbz9vDvTh_HYZN1q0OLzLKgKe4nmiDYGkfl_Ac,6604
|
46
|
+
osc_lib-3.2.0.dist-info/LICENSE,sha256=XfKg2H1sVi8OoRxoisUlMqoo10TKvHmU_wU39ks7MyA,10143
|
47
|
+
osc_lib-3.2.0.dist-info/METADATA,sha256=NeZxccGhpf6ec4c5nBFCH3JeEhbwvxdXAeCQM9Waqj8,3602
|
48
|
+
osc_lib-3.2.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
49
|
+
osc_lib-3.2.0.dist-info/pbr.json,sha256=e8kmAgOjG9-8ysIxfXKbp77TH7gBHvGa3IZxZb8OAl8,46
|
50
|
+
osc_lib-3.2.0.dist-info/top_level.txt,sha256=2gBTdue3DjRADXu0aOKF83SmJiKaCwfZ9z6hzCrjYr4,8
|
51
|
+
osc_lib-3.2.0.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
{"git_version": "d3fdae8", "is_release": true}
|
osc_lib-3.0.1.dist-info/RECORD
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
osc_lib/__init__.py,sha256=2NlShJ0jsku4xvwHtwbX_7-stc3huuMyfzohJcBZPGQ,673
|
2
|
-
osc_lib/clientmanager.py,sha256=fijs7Piy2DL-YSJcx47af8pAKKjfQD84uN6COQfo0_Q,9821
|
3
|
-
osc_lib/exceptions.py,sha256=GjjAibV3OaMpgJPEGwIpni3sejkId-7usWPSJ34KWwM,3445
|
4
|
-
osc_lib/i18n.py,sha256=Be2g7dxbMzzryhCecbgiAw5lHtfSQwVbAO8kC9dGvWo,783
|
5
|
-
osc_lib/logs.py,sha256=fE2tCRrFps-YMnnu8vzxijcdLniYY-7_K1Z94kKDu9A,7127
|
6
|
-
osc_lib/shell.py,sha256=DWKuPDVpEpruiawF0lhEsZ-dykQgCMPgiIrd3O0-zTY,19223
|
7
|
-
osc_lib/version.py,sha256=Csam3SVWQ7sUSXbOOBIPyv9DAHv_EfMIPpExsXYMVX0,710
|
8
|
-
osc_lib/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
osc_lib/api/api.py,sha256=boBrpyKAKiKjt87EnnM3JYX8J03q6JLFlkekxUSoFbc,12554
|
10
|
-
osc_lib/api/auth.py,sha256=DeFE5zOSAIdai6iDdf1nk9gijEX2Uc0PBVmGnwB7eJU,8177
|
11
|
-
osc_lib/api/utils.py,sha256=JDpM-vQUeEL_vYBYfj-WVM_mAhxA6KDmnTTYU9TleYY,3159
|
12
|
-
osc_lib/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
osc_lib/cli/client_config.py,sha256=68cAyPRpfgAE-nK-hus2hqfmYBJYh2TU0Kprve5M3w4,9466
|
14
|
-
osc_lib/cli/format_columns.py,sha256=loM4At-VhjR6rMNYO4w5RnuoGGr9zq5LsPC_3UaYXSY,1918
|
15
|
-
osc_lib/cli/identity.py,sha256=TIJDIEFJLKKE_HrFePxkelkev6DHuVrwo8DpJgivFs0,2711
|
16
|
-
osc_lib/cli/parseractions.py,sha256=5sKKNMULzPvEr4ld-jd-dRHKSGPNUPDmfc6aAdg4Mo8,10678
|
17
|
-
osc_lib/command/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
-
osc_lib/command/command.py,sha256=4Xyzl9Gj3iJ3ip2spAqSMO_-qy7GP7bILGrTlzBHiFM,1996
|
19
|
-
osc_lib/command/commandmanager.py,sha256=s9lWu5lMKqrzasUDcK-KfJRpPCTHbC7ZYnd3Fztk_pg,761
|
20
|
-
osc_lib/command/timing.py,sha256=TGRfuhkYp-eFO-CqeEDRe_km4OiqzaybXWOPehXLoUg,1139
|
21
|
-
osc_lib/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
-
osc_lib/tests/fakes.py,sha256=EScOc1lorFXBaReUqph7gtO60HqZDNXoPoZtcpu1YOs,5789
|
23
|
-
osc_lib/tests/test_clientmanager.py,sha256=fepY1Xj_pC_IwxS03bKDTrOS6DHylUAgpgtA1ZuXy3I,15585
|
24
|
-
osc_lib/tests/test_logs.py,sha256=oXFuKQfTB5Ul4graar7o3_qTpFXHKA_C0VUPlb0sSuE,8830
|
25
|
-
osc_lib/tests/test_shell.py,sha256=c45YSErHzdjhdDlh64inIJGckSNKPgIwhivb33frsEc,20219
|
26
|
-
osc_lib/tests/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
-
osc_lib/tests/api/fakes.py,sha256=Kcw_qtegRlpkQ0fRXhUSx-HtfbEwDJcRrZLc8WAraMg,1359
|
28
|
-
osc_lib/tests/api/test_api.py,sha256=uWXgHtcEmN3UB--SGd72I8YSv_0cJbPursv_oGtog5A,16682
|
29
|
-
osc_lib/tests/api/test_utils.py,sha256=ypMP8kBSOdIXHFprtl-Kqddn4vSQNr61OLSqziEvMFQ,3374
|
30
|
-
osc_lib/tests/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
-
osc_lib/tests/cli/test_client_config.py,sha256=r5IFa-hhU0-2s_D7k6izmcas0-l5nWkRBB8oCmPsvLw,8483
|
32
|
-
osc_lib/tests/cli/test_format_columns.py,sha256=YZZEE7XMe8uGcJldpqnmILUQMAGMgVXOianx3rCzIwk,4391
|
33
|
-
osc_lib/tests/cli/test_identity.py,sha256=-jJ4p0R4dCkgAJffOhjRcpB2qMa7OE10efbflA0B2ss,3375
|
34
|
-
osc_lib/tests/cli/test_parseractions.py,sha256=BazA--mBz0RQxQ-uYWOsQSHyZ2JAf974eYUj3fEbnx4,15651
|
35
|
-
osc_lib/tests/command/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
|
-
osc_lib/tests/command/test_command.py,sha256=nCf51tbJOFQ4sQEOuaWJG4UkXmexfPED5zYzoTJ1WyI,1682
|
37
|
-
osc_lib/tests/command/test_timing.py,sha256=G6gLiY0nnnxF4sqPQ5HozRIvFe1Jb2H7mr0O8vTkvaQ,3082
|
38
|
-
osc_lib/tests/utils/__init__.py,sha256=oDZmA7JJOkBcuy3fWnkb2VqAuN5GD_H4pzrriDoh6W4,14550
|
39
|
-
osc_lib/tests/utils/test_columns.py,sha256=OkVy-Soy899JHpNNiGZOVDsQibjwaz47lAz9bO7_9Ro,2445
|
40
|
-
osc_lib/tests/utils/test_tags.py,sha256=TlD14ggSzYLEEC4ZbFTdRckz6b8M5-3MAwV0lHU12vI,11745
|
41
|
-
osc_lib/tests/utils/test_utils.py,sha256=GvnsRhilCNLzoSH1a1EQr4FxU7JAm_NcQuan70tOVo0,35466
|
42
|
-
osc_lib/utils/__init__.py,sha256=tI8GVdOZcMU0I-08Y0awYW7sMzOykw2ja-l9RFrPeKc,27985
|
43
|
-
osc_lib/utils/columns.py,sha256=Qt4wC9biUEJQ14PUi97odzSztIBY1ZOWD0YfYVmVDFY,3963
|
44
|
-
osc_lib/utils/tags.py,sha256=-OTKm4Bhv6GZAzO-yTOXP10uiYurN1sK3Rf1yb07r0M,7971
|
45
|
-
osc_lib-3.0.1.dist-info/AUTHORS,sha256=vo7hWhmcT_06HhgzRDcHrbk5DMqb2Cq2k7wEGIpghG4,6517
|
46
|
-
osc_lib-3.0.1.dist-info/LICENSE,sha256=XfKg2H1sVi8OoRxoisUlMqoo10TKvHmU_wU39ks7MyA,10143
|
47
|
-
osc_lib-3.0.1.dist-info/METADATA,sha256=_El8XTQLSfzeg3PLhE3vbyuonr2Caj_XOWgEhckN1Z0,3603
|
48
|
-
osc_lib-3.0.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
49
|
-
osc_lib-3.0.1.dist-info/pbr.json,sha256=PZSReK1M89MKVjTZr-BnJ8KiJUUg88CAMSIlJkgH6pA,46
|
50
|
-
osc_lib-3.0.1.dist-info/top_level.txt,sha256=2gBTdue3DjRADXu0aOKF83SmJiKaCwfZ9z6hzCrjYr4,8
|
51
|
-
osc_lib-3.0.1.dist-info/RECORD,,
|
osc_lib-3.0.1.dist-info/pbr.json
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"git_version": "73ecaa7", "is_release": true}
|
File without changes
|
File without changes
|
File without changes
|