Skip to content

Commit

Permalink
Bug 799262 - Formal API for loading mach command modules; r=jhammel
Browse files Browse the repository at this point in the history
  • Loading branch information
indygreg committed Oct 10, 2012
1 parent a9b88a6 commit 875a861
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 34 deletions.
1 change: 1 addition & 0 deletions mach
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ except ImportError:

# All of the code is in a module because EVERYTHING IS A LIBRARY.
mach = mach.main.Mach(our_dir)
mach.load_commands_from_sys_path()
sys.exit(mach.run(sys.argv[1:]))
82 changes: 48 additions & 34 deletions python/mach/mach/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import logging
import os
import sys
import uuid

from mozbuild.base import BuildConfig
from mozbuild.config import ConfigSettings
Expand Down Expand Up @@ -40,8 +41,6 @@
'func',
]

MODULES_SCANNED = False


class ArgumentParser(argparse.ArgumentParser):
"""Custom implementation argument parser to make things look pretty."""
Expand Down Expand Up @@ -113,10 +112,54 @@ def __init__(self, cwd):

self.log_manager.register_structured_logger(self.logger)

if not MODULES_SCANNED:
self._load_modules()
def load_commands_from_sys_path(self):
"""Discover and load mach command modules from sys.path.
This iterates over all paths on sys.path. If the path contains a
"mach/commands" subdirectory, all .py files in that directory will be
loaded and examined for mach commands.
"""
# 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

self.load_commands_from_directory(commands_path)

def load_commands_from_directory(self, path):
"""Scan for mach commands from modules in a directory.
This takes a path to a directory, loads the .py files in it, and
registers and found mach command providers with this mach instance.
"""
for f in sorted(os.listdir(path)):
if not f.endswith('.py') or f == '__init__.py':
continue

full_path = os.path.join(path, f)
module_name = 'mach.commands.%s' % f[0:-3]

self.load_commands_from_file(full_path, module_name=module_name)

MODULES_SCANNED = True
def load_commands_from_file(self, path, module_name=None):
"""Scan for mach commands from a file.
This takes a path to a file and loads it as a Python module under the
module name specified. If no name is specified, a random one will be
chosen.
"""
if module_name is None:
module_name = 'mach.commands.%s' % uuid.uuid1().get_hex()

imp.load_source(module_name, path)

def run(self, argv):
"""Runs mach with arguments provided from the command line.
Expand Down Expand Up @@ -217,35 +260,6 @@ def log(self, level, action, params, format_str):
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.
Expand Down

0 comments on commit 875a861

Please sign in to comment.