mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 794509 - Part 3: Automatically discover mach commands in sys.path; r=jhammel
DONTBUILD (NPOTB)
This commit is contained in:
parent
5385e05615
commit
60db6ddf8e
@ -14,14 +14,14 @@ Subversion, and Mercurial and provides a common driver for multiple
|
||||
subcommands.
|
||||
|
||||
Subcommands are implemented by decorating a class inheritting from
|
||||
mozbuild.base.MozbuildObject and by decorating methods that act as subcommand
|
||||
handlers.
|
||||
mozbuild.base.MozbuildObject and by decorating methods that act as
|
||||
subcommand handlers.
|
||||
|
||||
Relevant decorators are defined in the *mach.base* module. There are the
|
||||
*Command* and *CommandArgument* decorators, which should be used on methods
|
||||
to denote that a specific method represents a handler for a mach subcommand.
|
||||
There is also the *CommandProvider* decorator, which is applied to a class
|
||||
to denote that it contains mach subcommands.
|
||||
Relevant decorators are defined in the *mach.base* module. There are
|
||||
the *Command* and *CommandArgument* decorators, which should be used
|
||||
on methods to denote that a specific method represents a handler for
|
||||
a mach subcommand. There is also the *CommandProvider* decorator,
|
||||
which is applied to a class to denote that it contains mach subcommands.
|
||||
|
||||
Here is a complete example:
|
||||
|
||||
@ -41,16 +41,20 @@ Here is a complete example:
|
||||
# Do stuff here.
|
||||
|
||||
|
||||
When the module is loaded, the decorators tell mach about all handlers. When
|
||||
mach runs, it takes the assembled metadata from these handlers and hooks it
|
||||
up to the command line driver. Under the hood, arguments passed to the
|
||||
decorators are being used as arguments to *argparse.ArgumentParser.add_parser()*
|
||||
and *argparse.ArgumentParser.add_argument()*. See the documentation for
|
||||
*argparse* for more.
|
||||
When the module is loaded, the decorators tell mach about all handlers.
|
||||
When mach runs, it takes the assembled metadata from these handlers and
|
||||
hooks it up to the command line driver. Under the hood, arguments passed
|
||||
to the decorators are being used as arguments to
|
||||
*argparse.ArgumentParser.add_parser()* and
|
||||
*argparse.ArgumentParser.add_argument()*. See the documentation in the
|
||||
*mach.base* module for more.
|
||||
|
||||
Currently, you also need to hook up some plumbing in
|
||||
*mach.main.Mach*. In the future, we hope to have automatic detection
|
||||
of submodules.
|
||||
The Python modules defining mach commands do not need to live inside the
|
||||
main mach source tree. If a path on *sys.path* contains a *mach/commands*
|
||||
directory, modules will be loaded automatically by mach and any classes
|
||||
containing the decorators described above will be detected and loaded
|
||||
automatically by mach. So, to add a new subcommand to mach, you just need
|
||||
to ensure your Python module is present on *sys.path*.
|
||||
|
||||
Minimizing Code in Mach
|
||||
-----------------------
|
||||
|
@ -9,6 +9,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import codecs
|
||||
import imp
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
@ -19,13 +20,6 @@ from mozbuild.logger import LoggingManager
|
||||
|
||||
from mach.registrar import populate_argument_parser
|
||||
|
||||
# Import sub-command modules
|
||||
# TODO Bug 794509 do this via auto-discovery. Update README once this is
|
||||
# done.
|
||||
from mach.commands.build import Build
|
||||
from mach.commands.settings import Settings
|
||||
from mach.commands.testing import Testing
|
||||
from mach.commands.warnings import Warnings
|
||||
|
||||
# Classes inheriting from ConfigProvider that provide settings.
|
||||
# TODO this should come from auto-discovery somehow.
|
||||
@ -46,6 +40,8 @@ CONSUMED_ARGUMENTS = [
|
||||
'func',
|
||||
]
|
||||
|
||||
MODULES_SCANNED = False
|
||||
|
||||
|
||||
class ArgumentParser(argparse.ArgumentParser):
|
||||
"""Custom implementation argument parser to make things look pretty."""
|
||||
@ -106,6 +102,8 @@ To see more help for a specific command, run:
|
||||
"""
|
||||
|
||||
def __init__(self, cwd):
|
||||
global MODULES_SCANNED
|
||||
|
||||
assert os.path.isdir(cwd)
|
||||
|
||||
self.cwd = cwd
|
||||
@ -115,6 +113,11 @@ To see more help for a specific command, run:
|
||||
|
||||
self.log_manager.register_structured_logger(self.logger)
|
||||
|
||||
if not MODULES_SCANNED:
|
||||
self._load_modules()
|
||||
|
||||
MODULES_SCANNED = True
|
||||
|
||||
def run(self, argv):
|
||||
"""Runs mach with arguments provided from the command line.
|
||||
|
||||
@ -214,6 +217,35 @@ To see more help for a specific command, run:
|
||||
self.logger.log(level, format_str,
|
||||
extra={'action': action, 'params': params})
|
||||
|
||||
def _load_modules(self):
|
||||
"""Scan over Python modules looking for mach command providers."""
|
||||
|
||||
# Create parent module otherwise Python complains when the parent is
|
||||
# missing.
|
||||
if b'mach.commands' not in sys.modules:
|
||||
mod = imp.new_module(b'mach.commands')
|
||||
sys.modules[b'mach.commands'] = mod
|
||||
|
||||
for path in sys.path:
|
||||
# We only support importing .py files from directories.
|
||||
commands_path = os.path.join(path, 'mach', 'commands')
|
||||
|
||||
if not os.path.isdir(commands_path):
|
||||
continue
|
||||
|
||||
# We only support loading modules in the immediate mach.commands
|
||||
# module, not sub-modules. Walking the tree would be trivial to
|
||||
# implement if it were ever desired.
|
||||
for f in sorted(os.listdir(commands_path)):
|
||||
if not f.endswith('.py') or f == '__init__.py':
|
||||
continue
|
||||
|
||||
full_path = os.path.join(commands_path, f)
|
||||
module_name = 'mach.commands.%s' % f[0:-3]
|
||||
|
||||
imp.load_source(module_name, full_path)
|
||||
|
||||
|
||||
def load_settings(self, args):
|
||||
"""Determine which settings files apply and load them.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user