author | Gregory Szorc <gps@mozilla.com> |
Tue, 06 Nov 2012 17:00:19 -0800 | |
changeset 120338 | f561a4ffeeb9f523fb59c678b7ac901763e32911 |
parent 120337 | 4f96fdb5e4f9b9e101e2e3c5f535bff8e0fe8f6c |
child 120339 | e57bd488af4c351016062e655b29415b993d7b13 |
push id | 1997 |
push user | akeybl@mozilla.com |
push date | Mon, 07 Jan 2013 21:25:26 +0000 |
treeherder | mozilla-beta@4baf45cdcf21 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jhammel |
bugs | 808346 |
milestone | 19.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
mach | file | annotate | diff | comparison | revisions | |
python/mach/README.rst | file | annotate | diff | comparison | revisions | |
python/mach/mach/main.py | file | annotate | diff | comparison | revisions | |
python/mozbuild/mach/commands/build.py | file | annotate | diff | comparison | revisions | |
python/mozbuild/mach/commands/warnings.py | file | annotate | diff | comparison | revisions | |
python/mozbuild/mozbuild/mach_commands.py | file | annotate | diff | comparison | revisions |
--- a/mach +++ b/mach @@ -35,29 +35,29 @@ SEARCH_PATHS = [ 'testing/mozbase/mozinfo', ] # Individual files providing mach commands. MACH_MODULES = [ 'layout/tools/reftest/mach_commands.py', 'python/mozboot/mozboot/mach_commands.py', 'python/mozbuild/mozbuild/config.py', + 'python/mozbuild/mozbuild/mach_commands.py', 'testing/mochitest/mach_commands.py', 'testing/xpcshell/mach_commands.py', ] our_dir = os.path.dirname(os.path.abspath(__file__)) try: import mach.main except ImportError: sys.path[0:0] = [os.path.join(our_dir, path) for path in SEARCH_PATHS] import mach.main # 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() for path in MACH_MODULES: mach.load_commands_from_file(os.path.join(our_dir, path)) sys.exit(mach.run(sys.argv[1:]))
--- a/python/mach/README.rst +++ b/python/mach/README.rst @@ -48,21 +48,17 @@ When the module is loaded, the decorator 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. 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*. +main mach source tree. Minimizing Code in Mach ----------------------- Mach is just a frontend. Therefore, code in this package should pertain to one of 3 areas: 1. Obtaining user input (parsing arguments, prompting, etc)
--- a/python/mach/mach/main.py +++ b/python/mach/mach/main.py @@ -140,38 +140,16 @@ To see more help for a specific command, self.cwd = cwd self.log_manager = LoggingManager() self.logger = logging.getLogger(__name__) self.settings = ConfigSettings() self.log_manager.register_structured_logger(self.logger) - 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': @@ -185,16 +163,22 @@ To see more help for a specific command, 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: + # Ensure parent module is present otherwise we'll (likely) get + # an error due to unknown parent. + if b'mach.commands' not in sys.modules: + mod = imp.new_module(b'mach.commands') + sys.modules[b'mach.commands'] = mod + module_name = 'mach.commands.%s' % uuid.uuid1().get_hex() imp.load_source(module_name, path) def run(self, argv, stdin=None, stdout=None, stderr=None): """Runs mach with arguments provided from the command line. Returns the integer exit code that should be used. 0 means success. All
deleted file mode 100644 --- a/python/mozbuild/mach/commands/warnings.py +++ /dev/null @@ -1,80 +0,0 @@ -# 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 print_function, unicode_literals - -import operator -import os - -from mach.decorators import ( - CommandArgument, - CommandProvider, - Command, -) - -from mozbuild.base import MachCommandBase - - -@CommandProvider -class Warnings(MachCommandBase): - """Provide commands for inspecting warnings.""" - - @property - def database_path(self): - return self._get_state_filename('warnings.json') - - @property - def database(self): - from mozbuild.compilation.warnings import WarningsDatabase - - path = self.database_path - - database = WarningsDatabase() - - if os.path.exists(path): - database.load_from_file(path) - - return database - - @Command('warnings-summary', - help='Show a summary of compiler warnings.') - @CommandArgument('report', default=None, nargs='?', - help='Warnings report to display. If not defined, show the most ' - 'recent report.') - def summary(self, report=None): - database = self.database - - type_counts = database.type_counts - sorted_counts = sorted(type_counts.iteritems(), - key=operator.itemgetter(1)) - - total = 0 - for k, v in sorted_counts: - print('%d\t%s' % (v, k)) - total += v - - print('%d\tTotal' % total) - - @Command('warnings-list', help='Show a list of compiler warnings.') - @CommandArgument('report', default=None, nargs='?', - help='Warnings report to display. If not defined, show the most ' - 'recent report.') - def list(self, report=None): - database = self.database - - by_name = sorted(database.warnings) - - for warning in by_name: - filename = warning['filename'] - - if filename.startswith(self.topsrcdir): - filename = filename[len(self.topsrcdir) + 1:] - - if warning['column'] is not None: - print('%s:%d:%d [%s] %s' % (filename, warning['line'], - warning['column'], warning['flag'], warning['message'])) - else: - print('%s:%d [%s] %s' % (filename, warning['line'], - warning['flag'], warning['message'])) -
rename from python/mozbuild/mach/commands/build.py rename to python/mozbuild/mozbuild/mach_commands.py --- a/python/mozbuild/mach/commands/build.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -1,18 +1,20 @@ # 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 unicode_literals +from __future__ import print_function, unicode_literals import logging +import operator import os from mach.decorators import ( + CommandArgument, CommandProvider, Command, ) from mozbuild.base import MachCommandBase @CommandProvider @@ -50,8 +52,72 @@ class Build(MachCommandBase): self._run_make(srcdir=True, filename='client.mk', line_handler=on_line, log=False, print_directory=False) self.log(logging.WARNING, 'warning_summary', {'count': len(warnings_collector.database)}, '{count} compiler warnings present.') warnings_database.save_to_file(warnings_path) + + +@CommandProvider +class Warnings(MachCommandBase): + """Provide commands for inspecting warnings.""" + + @property + def database_path(self): + return self._get_state_filename('warnings.json') + + @property + def database(self): + from mozbuild.compilation.warnings import WarningsDatabase + + path = self.database_path + + database = WarningsDatabase() + + if os.path.exists(path): + database.load_from_file(path) + + return database + + @Command('warnings-summary', + help='Show a summary of compiler warnings.') + @CommandArgument('report', default=None, nargs='?', + help='Warnings report to display. If not defined, show the most ' + 'recent report.') + def summary(self, report=None): + database = self.database + + type_counts = database.type_counts + sorted_counts = sorted(type_counts.iteritems(), + key=operator.itemgetter(1)) + + total = 0 + for k, v in sorted_counts: + print('%d\t%s' % (v, k)) + total += v + + print('%d\tTotal' % total) + + @Command('warnings-list', help='Show a list of compiler warnings.') + @CommandArgument('report', default=None, nargs='?', + help='Warnings report to display. If not defined, show the most ' + 'recent report.') + def list(self, report=None): + database = self.database + + by_name = sorted(database.warnings) + + for warning in by_name: + filename = warning['filename'] + + if filename.startswith(self.topsrcdir): + filename = filename[len(self.topsrcdir) + 1:] + + if warning['column'] is not None: + print('%s:%d:%d [%s] %s' % (filename, warning['line'], + warning['column'], warning['flag'], warning['message'])) + else: + print('%s:%d [%s] %s' % (filename, warning['line'], + warning['flag'], warning['message'])) +