mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-25 04:29:38 +00:00
120 lines
3.8 KiB
Python
120 lines
3.8 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
from __future__ import absolute_import, unicode_literals
|
|
|
|
from .base import MachError
|
|
|
|
INVALID_COMMAND_CONTEXT = r'''
|
|
It looks like you tried to run a mach command from an invalid context. The %s
|
|
command failed to meet the following conditions: %s
|
|
|
|
Run |mach help| to show a list of all commands available to the current context.
|
|
'''.lstrip()
|
|
|
|
|
|
class MachRegistrar(object):
|
|
"""Container for mach command and config providers."""
|
|
|
|
def __init__(self):
|
|
self.command_handlers = {}
|
|
self.commands_by_category = {}
|
|
self.settings_providers = set()
|
|
self.categories = {}
|
|
self.require_conditions = False
|
|
|
|
def register_command_handler(self, handler):
|
|
name = handler.name
|
|
|
|
if not handler.category:
|
|
raise MachError('Cannot register a mach command without a '
|
|
'category: %s' % name)
|
|
|
|
if handler.category not in self.categories:
|
|
raise MachError('Cannot register a command to an undefined '
|
|
'category: %s -> %s' % (name, handler.category))
|
|
|
|
self.command_handlers[name] = handler
|
|
self.commands_by_category[handler.category].add(name)
|
|
|
|
def register_settings_provider(self, cls):
|
|
self.settings_providers.add(cls)
|
|
|
|
def register_category(self, name, title, description, priority=50):
|
|
self.categories[name] = (title, description, priority)
|
|
self.commands_by_category[name] = set()
|
|
|
|
@classmethod
|
|
def _condition_failed_message(cls, name, conditions):
|
|
msg = ['\n']
|
|
for c in conditions:
|
|
part = [' %s' % c.__name__]
|
|
if c.__doc__ is not None:
|
|
part.append(c.__doc__)
|
|
msg.append(' - '.join(part))
|
|
return INVALID_COMMAND_CONTEXT % (name, '\n'.join(msg))
|
|
|
|
def _run_command_handler(self, handler, context=None, debug_command=False, **kwargs):
|
|
cls = handler.cls
|
|
|
|
if handler.pass_context and not context:
|
|
raise Exception('mach command class requires context.')
|
|
|
|
if context:
|
|
prerun = getattr(context, 'pre_dispatch_handler', None)
|
|
if prerun:
|
|
prerun(context, handler, args=kwargs)
|
|
|
|
if handler.pass_context:
|
|
instance = cls(context)
|
|
else:
|
|
instance = cls()
|
|
|
|
if handler.conditions:
|
|
fail_conditions = []
|
|
for c in handler.conditions:
|
|
if not c(instance):
|
|
fail_conditions.append(c)
|
|
|
|
if fail_conditions:
|
|
print(self._condition_failed_message(handler.name, fail_conditions))
|
|
return 1
|
|
|
|
fn = getattr(instance, handler.method)
|
|
|
|
if debug_command:
|
|
import pdb
|
|
result = pdb.runcall(fn, **kwargs)
|
|
else:
|
|
result = fn(**kwargs)
|
|
|
|
result = result or 0
|
|
assert isinstance(result, (int, long))
|
|
return result
|
|
|
|
def dispatch(self, name, context=None, argv=None, **kwargs):
|
|
"""Dispatch/run a command.
|
|
|
|
Commands can use this to call other commands.
|
|
"""
|
|
# TODO handler.subcommand_handlers are ignored
|
|
handler = self.command_handlers[name]
|
|
|
|
if handler.parser:
|
|
parser = handler.parser
|
|
|
|
# save and restore existing defaults so **kwargs don't persist across
|
|
# subsequent invocations of Registrar.dispatch()
|
|
old_defaults = parser._defaults.copy()
|
|
parser.set_defaults(**kwargs)
|
|
kwargs, _ = parser.parse_known_args(argv or [])
|
|
kwargs = vars(kwargs)
|
|
parser._defaults = old_defaults
|
|
|
|
return self._run_command_handler(handler, context=context, **kwargs)
|
|
|
|
|
|
|
|
Registrar = MachRegistrar()
|