DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
# This Source Code Form is subject to the terms of the Mozilla Public
# 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, print_function, unicode_literals


import time

import six


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
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.command_handlers = {}
        self.commands_by_category = {}
        self.settings_providers = set()
        self.categories = {}
        self.require_conditions = False
        self.command_depth = 0
        self.command_depth = 0

    def register_command_handler(self, handler):
        name = handler.name

        if not handler.category:
        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 '
            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
    @classmethod
    def _condition_failed_message(cls, name, conditions):
        msg = ['\n']
        for c in conditions:
            part = ['  %s' % getattr(c, '__name__', c)]
            part = ['  %s' % getattr(c, '__name__', c)]
            if c.__doc__ is not None:
                part.append(c.__doc__)
            msg.append(' - '.join(part))
        return INVALID_COMMAND_CONTEXT % (name, '\n'.join(msg))


    @classmethod
    def _instance(_, handler, context, **kwargs):
        cls = handler.cls

        if handler.pass_context and not context:
            raise Exception('mach command class requires context.')
            raise Exception('mach command class requires context.')

        if context:
            prerun = getattr(context, 'pre_dispatch_handler', None)
            if prerun:
                prerun(context, handler, args=kwargs)
                prerun(context, handler, args=kwargs)

        if handler.pass_context:
            context.handler = handler
            instance = cls(context)
        else:
        else:
            instance = cls()

        return instance

    @classmethod
    @classmethod
    def _fail_conditions(_, handler, instance):
        fail_conditions = []
        if handler.conditions:
            for c in handler.conditions:
                if not c(instance):
                if not c(instance):
                    fail_conditions.append(c)

        return fail_conditions
        return fail_conditions

    def _run_command_handler(self, handler, context=None, debug_command=False, **kwargs):
        instance = MachRegistrar._instance(handler, context, **kwargs)
        fail_conditions = MachRegistrar._fail_conditions(handler, instance)
        if fail_conditions:
        if fail_conditions:
            print(MachRegistrar._condition_failed_message(handler.name, fail_conditions))
            return 1

        self.command_depth += 1
        self.command_depth += 1
        fn = getattr(instance, handler.method)

        start_time = time.time()

        if debug_command:
        if debug_command:
            import pdb
            result = pdb.runcall(fn, **kwargs)
        else:
            result = fn(**kwargs)


        end_time = time.time()

        result = result or 0
        assert isinstance(result, six.integer_types)


        if context and not debug_command:
            postrun = getattr(context, 'post_dispatch_handler', None)
            if postrun:
                postrun(context, handler, instance, result,
                        start_time, end_time, self.command_depth, args=kwargs)
                        start_time, end_time, self.command_depth, args=kwargs)
        self.command_depth -= 1

        return result

    def dispatch(self, name, context=None, argv=None, subcommand=None, **kwargs):
    def dispatch(self, name, context=None, argv=None, subcommand=None, **kwargs):
        """Dispatch/run a command.

        Commands can use this to call other commands.
        """
        handler = self.command_handlers[name]
        handler = self.command_handlers[name]

        if subcommand:
            handler = handler.subcommand_handlers[subcommand]

        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()
            old_defaults = parser._defaults.copy()
            parser.set_defaults(**kwargs)
            kwargs, unknown = parser.parse_known_args(argv or [])
            kwargs = vars(kwargs)
            parser._defaults = old_defaults


            if unknown:
                if subcommand:
                    name = '{} {}'.format(name, subcommand)
                parser.error("unrecognized arguments for {}: {}".format(
                    name, ', '.join(["'{}'".format(arg) for arg in unknown])))
                    name, ', '.join(["'{}'".format(arg) for arg in unknown])))

        return self._run_command_handler(handler, context=context, **kwargs)


Registrar = MachRegistrar()
Registrar = MachRegistrar()