Bug 1176620 - Eliminate MethodHandler; r=ahal

This type is now redundant with our new rich type for capturing all mach
command metadata. Eliminate it and using _MachCommand instead.
This commit is contained in:
Gregory Szorc 2015-06-21 13:17:51 -07:00
parent b04697a8eb
commit 16254c9c6f
2 changed files with 52 additions and 93 deletions

View File

@ -44,82 +44,3 @@ class UnrecognizedArgumentError(MachError):
self.command = command
self.arguments = arguments
class MethodHandler(object):
"""Describes a Python method that implements a mach command.
Instances of these are produced by mach when it processes classes
defining mach commands.
"""
__slots__ = (
# The Python class providing the command. This is the class type not
# an instance of the class. Mach will instantiate a new instance of
# the class if the command is executed.
'cls',
# Whether the __init__ method of the class should receive a mach
# context instance. This should only affect the mach driver and how
# it instantiates classes.
'pass_context',
# The name of the method providing the command. In other words, this
# is the str name of the attribute on the class type corresponding to
# the name of the function.
'method',
# The name of the command.
'name',
# String category this command belongs to.
'category',
# Description of the purpose of this command.
'description',
# Docstring associated with command.
'docstring',
# Functions used to 'skip' commands if they don't meet the conditions
# in a given context.
'conditions',
# argparse.ArgumentParser instance to use as the basis for command
# arguments.
'_parser',
'parser',
# Arguments added to this command's parser. This is a 2-tuple of
# positional and named arguments, respectively.
'arguments',
# 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, command, pass_context=False):
self.cls = cls
self.method = method
self.name = command.subcommand if command.subcommand else command.name
self.category = command.category
self.description = command.description
self.conditions = command.conditions
self.arguments = command.arguments
self.argument_group_names = command.argument_group_names
self._parser = command.parser
self.docstring = cls.__dict__[method].__doc__
self.pass_context = pass_context
self.subcommand_handlers = {}
@property
def parser(self):
# creating cli parsers at command dispatch time can potentially be
# expensive, make it possible to lazy load them.
if callable(self._parser):
self._parser = self._parser()
return self._parser

View File

@ -9,11 +9,7 @@ import collections
import inspect
import types
from .base import (
MachError,
MethodHandler
)
from .base import MachError
from .config import ConfigProvider
from .registrar import Registrar
@ -25,14 +21,36 @@ class _MachCommand(object):
in a sane way so tuples, etc aren't used instead.
"""
__slots__ = (
# Content from decorator arguments to define the command.
'name',
'subcommand',
'category',
'description',
'conditions',
'parser',
'_parser',
'arguments',
'argument_group_names',
# Describes how dispatch is performed.
# The Python class providing the command. This is the class type not
# an instance of the class. Mach will instantiate a new instance of
# the class if the command is executed.
'cls',
# Whether the __init__ method of the class should receive a mach
# context instance. This should only affect the mach driver and how
# it instantiates classes.
'pass_context',
# The name of the method providing the command. In other words, this
# is the str name of the attribute on the class type corresponding to
# the name of the function.
'method',
# Dict of string to _MachCommand defining sub-commands for this
# command.
'subcommand_handlers',
)
def __init__(self, name=None, subcommand=None, category=None,
@ -42,10 +60,28 @@ class _MachCommand(object):
self.category = category
self.description = description
self.conditions = conditions or []
self.parser = parser
self._parser = parser
self.arguments = []
self.argument_group_names = []
self.cls = None
self.pass_context = None
self.method = None
self.subcommand_handlers = {}
@property
def parser(self):
# Creating CLI parsers at command dispatch time can be expensive. Make
# it possible to lazy load them by using functions.
if callable(self._parser):
self._parser = self._parser()
return self._parser
@property
def docstring(self):
return self.cls.__dict__[self.method].__doc__
def __ior__(self, other):
if not isinstance(other, _MachCommand):
raise ValueError('can only operate on _MachCommand instances')
@ -124,10 +160,11 @@ def CommandProvider(cls):
msg = msg % (command.name, type(c))
raise MachError(msg)
handler = MethodHandler(cls, attr, command,
pass_context=pass_context)
command.cls = cls
command.method = attr
command.pass_context = pass_context
Registrar.register_command_handler(handler)
Registrar.register_command_handler(command)
# 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
@ -153,17 +190,18 @@ def CommandProvider(cls):
if command.name not in Registrar.command_handlers:
continue
handler = MethodHandler(cls, attr, command,
pass_context=pass_context)
command.cls = cls
command.method = attr
command.pass_context = pass_context
parent = Registrar.command_handlers[command.name]
if parent.parser:
if parent._parser:
raise MachError('cannot declare sub commands against a command '
'that has a parser installed: %s' % command)
if command.subcommand in parent.subcommand_handlers:
raise MachError('sub-command already defined: %s' % command.subcommand)
parent.subcommand_handlers[command.subcommand] = handler
parent.subcommand_handlers[command.subcommand] = command
return cls