Implement Parameter Deprecation
Implements parameter deprecation for magnum client via decorator in cliutils.py and additional logic in magnumclient/shell.py. Logic in shell creates mutual exclusive (mutex) groups in argparse to enable parameter checking for required and unrequired parameters specifically to check for old parameters that are being deprecated in favor of newer ones. Change-Id: Ic72c876e556070a066b1693a119a389301dfa259 Implements: blueprint rename-id-parameter-names
This commit is contained in:
parent
06290d21d1
commit
e7f084dfa9
@ -35,6 +35,12 @@ from six import moves
|
||||
from magnumclient.i18n import _
|
||||
|
||||
|
||||
def deprecation_message(preamble, new_name):
|
||||
msg = ('%s This parameter is deprecated and will be removed in a future '
|
||||
'release. Use --%s instead.' % (preamble, new_name))
|
||||
return msg
|
||||
|
||||
|
||||
class MissingArgs(Exception):
|
||||
"""Supplied arguments are not sufficient for calling a function."""
|
||||
def __init__(self, missing):
|
||||
@ -77,14 +83,14 @@ def validate_args(fn, *args, **kwargs):
|
||||
|
||||
|
||||
def deprecated(message):
|
||||
'''Decorator for marking a call as deprecated by printing a given message.
|
||||
"""Decorator for marking a call as deprecated by printing a given message.
|
||||
|
||||
Example:
|
||||
>>> @deprecated("Bay functions are deprecated and should be replaced by "
|
||||
... "calls to cluster")
|
||||
... def bay_create(args):
|
||||
... pass
|
||||
'''
|
||||
"""
|
||||
@decorator.decorator
|
||||
def wrapper(func, *args, **kwargs):
|
||||
print(message)
|
||||
@ -92,6 +98,57 @@ def deprecated(message):
|
||||
return wrapper
|
||||
|
||||
|
||||
def deprecation_map(dep_map):
|
||||
"""Decorator for applying a map of deprecating arguments to a function.
|
||||
|
||||
The map connects deprecating arguments and their replacements. The
|
||||
shell.py script uses this map to create mutually exclusive argument groups
|
||||
in argparse and also prints a deprecation warning telling the user to
|
||||
switch to the updated argument.
|
||||
|
||||
NOTE: This decorator MUST be the outermost in the chain of argument
|
||||
decorators to work correctly.
|
||||
|
||||
Example usage:
|
||||
>>> @deprecation_map({ "old-argument": "new-argument" })
|
||||
... @args("old-argument", required=True)
|
||||
... @args("new-argument", required=True)
|
||||
... def do_command_line_stuff():
|
||||
... pass
|
||||
"""
|
||||
def _decorator(func):
|
||||
if not hasattr(func, 'arguments'):
|
||||
return func
|
||||
|
||||
func.deprecated_groups = []
|
||||
for old_param, new_param in dep_map.items():
|
||||
old_info, new_info = None, None
|
||||
required = False
|
||||
for (args, kwargs) in func.arguments:
|
||||
if old_param in args:
|
||||
old_info = (args, kwargs)
|
||||
# Old arguments shouldn't be required if they were not
|
||||
# previously, so prioritize old requirement
|
||||
if 'required' in kwargs:
|
||||
required = kwargs['required']
|
||||
# Set to false so argparse doesn't get angry
|
||||
kwargs['required'] = False
|
||||
elif new_param in args:
|
||||
new_info = (args, kwargs)
|
||||
kwargs['required'] = False
|
||||
if old_info and new_info:
|
||||
break
|
||||
# Add a tuple of (old, new, required), which in turn is:
|
||||
# ((old_args, old_kwargs), (new_args, new_kwargs), required)
|
||||
func.deprecated_groups.append((old_info, new_info, required))
|
||||
# Remove arguments that would be duplicated by the groups we made
|
||||
func.arguments.remove(old_info)
|
||||
func.arguments.remove(new_info)
|
||||
|
||||
return func
|
||||
return _decorator
|
||||
|
||||
|
||||
def arg(*args, **kwargs):
|
||||
"""Decorator for CLI args.
|
||||
|
||||
|
@ -459,6 +459,7 @@ class OpenStackMagnumShell(object):
|
||||
desc = callback.__doc__ or ''
|
||||
action_help = desc.strip()
|
||||
arguments = getattr(callback, 'arguments', [])
|
||||
group_args = getattr(callback, 'deprecated_groups', [])
|
||||
|
||||
subparser = (
|
||||
subparsers.add_parser(command,
|
||||
@ -471,6 +472,12 @@ class OpenStackMagnumShell(object):
|
||||
action='help',
|
||||
help=argparse.SUPPRESS,)
|
||||
self.subcommands[command] = subparser
|
||||
|
||||
for (old_info, new_info, req) in group_args:
|
||||
group = subparser.add_mutually_exclusive_group(required=req)
|
||||
group.add_argument(*old_info[0], **old_info[1])
|
||||
group.add_argument(*new_info[0], **new_info[1])
|
||||
|
||||
for (args, kwargs) in arguments:
|
||||
subparser.add_argument(*args, **kwargs)
|
||||
subparser.set_defaults(func=callback)
|
||||
@ -630,8 +637,31 @@ class OpenStackMagnumShell(object):
|
||||
api_version=args.magnum_api_version,
|
||||
)
|
||||
|
||||
self._check_deprecation(args.func, argv)
|
||||
args.func(self.cs, args)
|
||||
|
||||
def _check_deprecation(self, func, argv):
|
||||
if not hasattr(func, 'deprecated_groups'):
|
||||
return
|
||||
|
||||
for (old_info, new_info, required) in func.deprecated_groups:
|
||||
old_param = old_info[0][0]
|
||||
new_param = new_info[0][0]
|
||||
old_value, new_value = None, None
|
||||
for i in range(len(argv)):
|
||||
cur_arg = argv[i]
|
||||
if cur_arg == old_param:
|
||||
old_value = argv[i + 1]
|
||||
elif cur_arg == new_param[0]:
|
||||
new_value = argv[i + 1]
|
||||
|
||||
if old_value and not new_value:
|
||||
print(
|
||||
'WARNING: The %s parameter is deprecated and will be '
|
||||
'removed in a future release. Use the %s parameter to '
|
||||
'avoid seeing this message.'
|
||||
% (old_param, new_param))
|
||||
|
||||
def _dump_timings(self, timings):
|
||||
class Tyme(object):
|
||||
def __init__(self, url, seconds):
|
||||
|
Loading…
Reference in New Issue
Block a user