mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1108399 - Introduce decorator for mach sub-commands; r=ahal
With this patch, we now have the ability to declare mach sub-commands. Subsequent patches will implement dispatching for sub-commands. --HG-- extra : rebase_source : 32a672ff3ba7a1a1c8c27dff3fe657dec08e3569 extra : histedit_source : 2bb2c27ae0e2dab052a6ef93b0a70f488f8cd56e
This commit is contained in:
parent
66816678e1
commit
a263f9b2b2
@ -23,6 +23,15 @@ The important decorators are as follows:
|
||||
A method decorator that defines an argument to the command. Its
|
||||
arguments are essentially proxied to ArgumentParser.add_argument()
|
||||
|
||||
:py:func:`SubCommand <mach.decorators.SubCommand`
|
||||
A method decorator that denotes that the method should be a
|
||||
sub-command to an existing ``@Command``. The decorator takes the
|
||||
parent command name as its first argument and the sub-command name
|
||||
as its second argument.
|
||||
|
||||
``@CommandArgument`` can be used on ``@SubCommand`` instances just
|
||||
like they can on ``@Command`` instances.
|
||||
|
||||
Classes with the ``@CommandProvider`` decorator **must** have an
|
||||
``__init__`` method that accepts 1 or 2 arguments. If it accepts 2
|
||||
arguments, the 2nd argument will be a
|
||||
|
@ -91,11 +91,16 @@ class MethodHandler(object):
|
||||
|
||||
# Argument groups added to this command's parser.
|
||||
'argument_group_names',
|
||||
|
||||
# Dict of string to MethodHandler defining sub commands for this
|
||||
# command.
|
||||
'subcommand_handlers',
|
||||
)
|
||||
|
||||
def __init__(self, cls, method, name, category=None, description=None,
|
||||
conditions=None, parser=None, arguments=None,
|
||||
argument_group_names=None, pass_context=False):
|
||||
argument_group_names=None, pass_context=False,
|
||||
subcommand_handlers=None):
|
||||
|
||||
self.cls = cls
|
||||
self.method = method
|
||||
@ -107,4 +112,4 @@ class MethodHandler(object):
|
||||
self.arguments = arguments or []
|
||||
self.argument_group_names = argument_group_names or []
|
||||
self.pass_context = pass_context
|
||||
|
||||
self.subcommand_handlers = subcommand_handlers or {}
|
||||
|
@ -91,6 +91,41 @@ def CommandProvider(cls):
|
||||
|
||||
Registrar.register_command_handler(handler)
|
||||
|
||||
# Now do another pass to get sub-commands. We do this in two passes so
|
||||
# we can check the parent command existence without having to hold
|
||||
# state and reconcile after traversal.
|
||||
for attr in sorted(cls.__dict__.keys()):
|
||||
value = cls.__dict__[attr]
|
||||
|
||||
if not isinstance(value, types.FunctionType):
|
||||
continue
|
||||
|
||||
command, subcommand, description = getattr(value, '_mach_subcommand',
|
||||
(None, None, None))
|
||||
|
||||
if not command:
|
||||
continue
|
||||
|
||||
if command not in Registrar.command_handlers:
|
||||
raise MachError('Command referenced by sub-command does not '
|
||||
'exist: %s' % command)
|
||||
|
||||
arguments = getattr(value, '_mach_command_args', None)
|
||||
argument_group_names = getattr(value, '_mach_command_arg_group_names', None)
|
||||
|
||||
handler = MethodHandler(cls, attr, subcommand, description=description,
|
||||
arguments=arguments, argument_group_names=argument_group_names,
|
||||
pass_context=pass_context)
|
||||
parent = Registrar.command_handlers[command]
|
||||
|
||||
if parent.parser:
|
||||
raise MachError('cannot declare sub commands against a command '
|
||||
'that has a parser installed: %s' % command)
|
||||
if subcommand in parent.subcommand_handlers:
|
||||
raise MachError('sub-command already defined: %s' % subcommand)
|
||||
|
||||
parent.subcommand_handlers[subcommand] = handler
|
||||
|
||||
return cls
|
||||
|
||||
|
||||
@ -128,6 +163,33 @@ class Command(object):
|
||||
|
||||
return func
|
||||
|
||||
class SubCommand(object):
|
||||
"""Decorator for functions or methods that provide a sub-command.
|
||||
|
||||
Mach commands can have sub-commands. e.g. ``mach command foo`` or
|
||||
``mach command bar``. Each sub-command has its own parser and is
|
||||
effectively its own mach command.
|
||||
|
||||
The decorator accepts arguments that define basic attributes of the
|
||||
sub command:
|
||||
|
||||
command -- The string of the command this sub command should be
|
||||
attached to.
|
||||
|
||||
subcommand -- The string name of the sub command to register.
|
||||
|
||||
description -- A textual description for this sub command.
|
||||
"""
|
||||
def __init__(self, command, subcommand, description=None):
|
||||
self._command = command
|
||||
self._subcommand = subcommand
|
||||
self._description = description
|
||||
|
||||
def __call__(self, func):
|
||||
func._mach_subcommand = (self._command, self._subcommand,
|
||||
self._description)
|
||||
|
||||
return func
|
||||
|
||||
class CommandArgument(object):
|
||||
"""Decorator for additional arguments to mach subcommands.
|
||||
|
Loading…
Reference in New Issue
Block a user