Bug 1399989 - Add python/mach to flake8 linter. r=gps

MozReview-Commit-ID: KKnBgYFwpfT

--HG--
extra : rebase_source : 4e4b3453a91970366dba0073853ad3ab62738c81
This commit is contained in:
Steve Armand 2017-09-17 22:41:17 -04:00
Родитель 57eb104b05
Коммит d11ffd18db
21 изменённых файлов: 76 добавлений и 65 удалений

Просмотреть файл

@ -23,14 +23,14 @@ class BuiltinCommands(object):
if not v.conditions or v.conditions[0].__name__ != 'REMOVED') if not v.conditions or v.conditions[0].__name__ != 'REMOVED')
@Command('mach-commands', category='misc', @Command('mach-commands', category='misc',
description='List all mach commands.') description='List all mach commands.')
def commands(self): def commands(self):
print("\n".join(self.command_keys)) print("\n".join(self.command_keys))
@Command('mach-debug-commands', category='misc', @Command('mach-debug-commands', category='misc',
description='Show info about available mach commands.') description='Show info about available mach commands.')
@CommandArgument('match', metavar='MATCH', default=None, nargs='?', @CommandArgument('match', metavar='MATCH', default=None, nargs='?',
help='Only display commands containing given substring.') help='Only display commands containing given substring.')
def debug_commands(self, match=None): def debug_commands(self, match=None):
import inspect import inspect
@ -50,4 +50,3 @@ class BuiltinCommands(object):
print('Class: %s' % cls.__name__) print('Class: %s' % cls.__name__)
print('Method: %s' % handler.method) print('Method: %s' % handler.method)
print('') print('')

Просмотреть файл

@ -274,7 +274,6 @@ class ConfigSettings(collections.Mapping):
def __delattr__(self, k): def __delattr__(self, k):
self.__delitem__(k) self.__delitem__(k)
def __init__(self): def __init__(self):
self._config = RawConfigParser() self._config = RawConfigParser()
self._config.optionxform = str self._config.optionxform = str

Просмотреть файл

@ -7,7 +7,6 @@ from __future__ import absolute_import, unicode_literals
import argparse import argparse
import collections import collections
import inspect import inspect
import os
import types import types
from .base import MachError from .base import MachError
@ -185,7 +184,7 @@ def CommandProvider(cls):
if command.name not in seen_commands: if command.name not in seen_commands:
raise MachError('Command referenced by sub-command does not ' raise MachError('Command referenced by sub-command does not '
'exist: %s' % command.name) 'exist: %s' % command.name)
if command.name not in Registrar.command_handlers: if command.name not in Registrar.command_handlers:
continue continue
@ -235,6 +234,7 @@ class Command(object):
return func return func
class SubCommand(object): class SubCommand(object):
"""Decorator for functions or methods that provide a sub-command. """Decorator for functions or methods that provide a sub-command.
@ -264,6 +264,7 @@ class SubCommand(object):
return func return func
class CommandArgument(object): class CommandArgument(object):
"""Decorator for additional arguments to mach subcommands. """Decorator for additional arguments to mach subcommands.
@ -343,4 +344,3 @@ def SettingsProvider(cls):
Registrar.register_settings_provider(cls) Registrar.register_settings_provider(cls)
return cls return cls

Просмотреть файл

@ -68,7 +68,7 @@ class CommandAction(argparse.Action):
For more, read the docs in __call__. For more, read the docs in __call__.
""" """
def __init__(self, option_strings, dest, required=True, default=None, def __init__(self, option_strings, dest, required=True, default=None,
registrar=None, context=None): registrar=None, context=None):
# A proper API would have **kwargs here. However, since we are a little # A proper API would have **kwargs here. However, since we are a little
# hacky, we intentionally omit it as a way of detecting potentially # hacky, we intentionally omit it as a way of detecting potentially
# breaking changes with argparse's implementation. # breaking changes with argparse's implementation.
@ -76,7 +76,7 @@ class CommandAction(argparse.Action):
# In a similar vein, default is passed in but is not needed, so we drop # In a similar vein, default is passed in but is not needed, so we drop
# it. # it.
argparse.Action.__init__(self, option_strings, dest, required=required, argparse.Action.__init__(self, option_strings, dest, required=required,
help=argparse.SUPPRESS, nargs=argparse.REMAINDER) help=argparse.SUPPRESS, nargs=argparse.REMAINDER)
self._mach_registrar = registrar self._mach_registrar = registrar
self._context = context self._context = context
@ -276,7 +276,7 @@ class CommandAction(argparse.Action):
description = handler.description description = handler.description
group.add_argument(command, help=description, group.add_argument(command, help=description,
action='store_true') action='store_true')
if disabled_commands and 'disabled' in r.categories: if disabled_commands and 'disabled' in r.categories:
title, description, _priority = r.categories['disabled'] title, description, _priority = r.categories['disabled']
@ -376,7 +376,7 @@ class CommandAction(argparse.Action):
for subcommand, subhandler in sorted(handler.subcommand_handlers.iteritems()): for subcommand, subhandler in sorted(handler.subcommand_handlers.iteritems()):
group.add_argument(subcommand, help=subhandler.description, group.add_argument(subcommand, help=subhandler.description,
action='store_true') action='store_true')
if handler.docstring: if handler.docstring:
parser.description = format_docstring(handler.docstring) parser.description = format_docstring(handler.docstring)
@ -413,7 +413,7 @@ class CommandAction(argparse.Action):
def _suggest_command(self, command): def _suggest_command(self, command):
# Make sure we don't suggest any deprecated commands. # Make sure we don't suggest any deprecated commands.
names = [h.name for h in self._mach_registrar.command_handlers.values() names = [h.name for h in self._mach_registrar.command_handlers.values()
if h.cls.__name__ != 'DeprecatedCommands'] if h.cls.__name__ != 'DeprecatedCommands']
# We first try to look for a valid command that is very similar to the given command. # We first try to look for a valid command that is very similar to the given command.
suggested_commands = difflib.get_close_matches(command, names, cutoff=0.8) suggested_commands = difflib.get_close_matches(command, names, cutoff=0.8)
# If we find more than one matching command, or no command at all, # If we find more than one matching command, or no command at all,

Просмотреть файл

@ -200,15 +200,17 @@ class LoggingManager(object):
self.json_handlers.append(handler) self.json_handlers.append(handler)
def add_terminal_logging(self, fh=sys.stdout, level=logging.INFO, def add_terminal_logging(self, fh=sys.stdout, level=logging.INFO,
write_interval=False, write_times=True): write_interval=False, write_times=True):
"""Enable logging to the terminal.""" """Enable logging to the terminal."""
formatter = StructuredHumanFormatter(self.start_time, formatter = StructuredHumanFormatter(self.start_time,
write_interval=write_interval, write_times=write_times) write_interval=write_interval,
write_times=write_times)
if self.terminal: if self.terminal:
formatter = StructuredTerminalFormatter(self.start_time, formatter = StructuredTerminalFormatter(self.start_time,
write_interval=write_interval, write_times=write_times) write_interval=write_interval,
write_times=write_times)
formatter.set_terminal(self.terminal) formatter.set_terminal(self.terminal)
handler = logging.StreamHandler(stream=fh) handler = logging.StreamHandler(stream=fh)

Просмотреть файл

@ -38,7 +38,6 @@ from .logging import LoggingManager
from .registrar import Registrar from .registrar import Registrar
MACH_ERROR = r''' MACH_ERROR = r'''
The error occurred in mach itself. This is likely a bug in mach itself or a The error occurred in mach itself. This is likely a bug in mach itself or a
fundamental problem with a loaded module. fundamental problem with a loaded module.
@ -103,6 +102,7 @@ to implement a mach command. Please fix the error, or uninstall the module from
your system. your system.
'''.lstrip() '''.lstrip()
class ArgumentParser(argparse.ArgumentParser): class ArgumentParser(argparse.ArgumentParser):
"""Custom implementation argument parser to make things look pretty.""" """Custom implementation argument parser to make things look pretty."""
@ -361,7 +361,7 @@ To see more help for a specific command, run:
print('mach interrupted by signal or user action. Stopping.') print('mach interrupted by signal or user action. Stopping.')
return 1 return 1
except Exception as e: except Exception:
# _run swallows exceptions in invoked handlers and converts them to # _run swallows exceptions in invoked handlers and converts them to
# a proper exit code. So, the only scenario where we should get an # a proper exit code. So, the only scenario where we should get an
# exception here is if _run itself raises. If _run raises, that's a # exception here is if _run itself raises. If _run raises, that's a
@ -393,8 +393,8 @@ To see more help for a specific command, run:
self.load_settings(self.settings_paths) self.load_settings(self.settings_paths)
context = CommandContext(cwd=self.cwd, context = CommandContext(cwd=self.cwd,
settings=self.settings, log_manager=self.log_manager, settings=self.settings, log_manager=self.log_manager,
commands=Registrar) commands=Registrar)
if self.populate_context_handler: if self.populate_context_handler:
self.populate_context_handler(context) self.populate_context_handler(context)
@ -416,12 +416,14 @@ To see more help for a specific command, run:
print(NO_COMMAND_ERROR) print(NO_COMMAND_ERROR)
return 1 return 1
except UnknownCommandError as e: except UnknownCommandError as e:
suggestion_message = SUGGESTED_COMMANDS_MESSAGE % (e.verb, ', '.join(e.suggested_commands)) if e.suggested_commands else '' suggestion_message = SUGGESTED_COMMANDS_MESSAGE % (
print(UNKNOWN_COMMAND_ERROR % (e.verb, e.command, suggestion_message)) e.verb, ', '.join(e.suggested_commands)) if e.suggested_commands else ''
print(UNKNOWN_COMMAND_ERROR %
(e.verb, e.command, suggestion_message))
return 1 return 1
except UnrecognizedArgumentError as e: except UnrecognizedArgumentError as e:
print(UNRECOGNIZED_ARGUMENT_ERROR % (e.command, print(UNRECOGNIZED_ARGUMENT_ERROR % (e.command,
' '.join(e.arguments))) ' '.join(e.arguments)))
return 1 return 1
# Add JSON logging to a file if requested. # Add JSON logging to a file if requested.
@ -442,7 +444,8 @@ To see more help for a specific command, run:
# Always enable terminal logging. The log manager figures out if we are # Always enable terminal logging. The log manager figures out if we are
# actually in a TTY or are a pipe and does the right thing. # actually in a TTY or are a pipe and does the right thing.
self.log_manager.add_terminal_logging(level=log_level, self.log_manager.add_terminal_logging(level=log_level,
write_interval=args.log_interval, write_times=write_times) write_interval=args.log_interval,
write_times=write_times)
if args.settings_file: if args.settings_file:
# Argument parsing has already happened, so settings that apply # Argument parsing has already happened, so settings that apply
@ -456,7 +459,8 @@ To see more help for a specific command, run:
try: try:
return Registrar._run_command_handler(handler, context=context, return Registrar._run_command_handler(handler, context=context,
debug_command=args.debug_command, **vars(args.command_args)) debug_command=args.debug_command,
**vars(args.command_args))
except KeyboardInterrupt as ki: except KeyboardInterrupt as ki:
raise ki raise ki
except FailedCommandError as e: except FailedCommandError as e:
@ -477,7 +481,7 @@ To see more help for a specific command, run:
if not len(stack): if not len(stack):
print(COMMAND_ERROR) print(COMMAND_ERROR)
self._print_exception(sys.stdout, exc_type, exc_value, self._print_exception(sys.stdout, exc_type, exc_value,
traceback.extract_tb(exc_tb)) traceback.extract_tb(exc_tb))
return 1 return 1
# Split the frames into those from the module containing the # Split the frames into those from the module containing the
@ -511,7 +515,7 @@ To see more help for a specific command, run:
def log(self, level, action, params, format_str): def log(self, level, action, params, format_str):
"""Helper method to record a structured log event.""" """Helper method to record a structured log event."""
self.logger.log(level, format_str, self.logger.log(level, format_str,
extra={'action': action, 'params': params}) extra={'action': action, 'params': params})
def _print_error_header(self, argv, fh): def _print_error_header(self, argv, fh):
fh.write('Error running mach:\n\n') fh.write('Error running mach:\n\n')
@ -542,6 +546,7 @@ To see more help for a specific command, run:
paths = [paths] paths = [paths]
valid_names = ('machrc', '.machrc') valid_names = ('machrc', '.machrc')
def find_in_dir(base): def find_in_dir(base):
if os.path.isfile(base): if os.path.isfile(base):
return base return base
@ -560,38 +565,40 @@ To see more help for a specific command, run:
"""Returns an argument parser for the command-line interface.""" """Returns an argument parser for the command-line interface."""
parser = ArgumentParser(add_help=False, parser = ArgumentParser(add_help=False,
usage='%(prog)s [global arguments] command [command arguments]') usage='%(prog)s [global arguments] '
'command [command arguments]')
# Order is important here as it dictates the order the auto-generated # Order is important here as it dictates the order the auto-generated
# help messages are printed. # help messages are printed.
global_group = parser.add_argument_group('Global Arguments') global_group = parser.add_argument_group('Global Arguments')
global_group.add_argument('-v', '--verbose', dest='verbose', global_group.add_argument('-v', '--verbose', dest='verbose',
action='store_true', default=False, action='store_true', default=False,
help='Print verbose output.') help='Print verbose output.')
global_group.add_argument('-l', '--log-file', dest='logfile', global_group.add_argument('-l', '--log-file', dest='logfile',
metavar='FILENAME', type=argparse.FileType('ab'), metavar='FILENAME', type=argparse.FileType('ab'),
help='Filename to write log data to.') help='Filename to write log data to.')
global_group.add_argument('--log-interval', dest='log_interval', global_group.add_argument('--log-interval', dest='log_interval',
action='store_true', default=False, action='store_true', default=False,
help='Prefix log line with interval from last message rather ' help='Prefix log line with interval from last message rather '
'than relative time. Note that this is NOT execution time ' 'than relative time. Note that this is NOT execution time '
'if there are parallel operations.') 'if there are parallel operations.')
suppress_log_by_default = False suppress_log_by_default = False
if 'INSIDE_EMACS' in os.environ: if 'INSIDE_EMACS' in os.environ:
suppress_log_by_default = True suppress_log_by_default = True
global_group.add_argument('--log-no-times', dest='log_no_times', global_group.add_argument('--log-no-times', dest='log_no_times',
action='store_true', default=suppress_log_by_default, action='store_true', default=suppress_log_by_default,
help='Do not prefix log lines with times. By default, mach will ' help='Do not prefix log lines with times. By default, '
'prefix each output line with the time since command start.') 'mach will prefix each output line with the time since '
'command start.')
global_group.add_argument('-h', '--help', dest='help', global_group.add_argument('-h', '--help', dest='help',
action='store_true', default=False, action='store_true', default=False,
help='Show this help message.') help='Show this help message.')
global_group.add_argument('--debug-command', action='store_true', global_group.add_argument('--debug-command', action='store_true',
help='Start a Python debugger when command is dispatched.') help='Start a Python debugger when command is dispatched.')
global_group.add_argument('--settings', dest='settings_file', global_group.add_argument('--settings', dest='settings_file',
metavar='FILENAME', default=None, metavar='FILENAME', default=None,
help='Path to settings file.') help='Path to settings file.')
for args, kwargs in self.global_arguments: for args, kwargs in self.global_arguments:
global_group.add_argument(*args, **kwargs) global_group.add_argument(*args, **kwargs)
@ -599,6 +606,6 @@ To see more help for a specific command, run:
# We need to be last because CommandAction swallows all remaining # We need to be last because CommandAction swallows all remaining
# arguments and argparse parses arguments in the order they were added. # arguments and argparse parses arguments in the order they were added.
parser.add_argument('command', action=CommandAction, parser.add_argument('command', action=CommandAction,
registrar=Registrar, context=context) registrar=Registrar, context=context)
return parser return parser

Просмотреть файл

@ -51,5 +51,4 @@ class LoggingMixin(object):
'User login: {username}') 'User login: {username}')
""" """
self._logger.log(level, format_str, self._logger.log(level, format_str,
extra={'action': action, 'params': params}) extra={'action': action, 'params': params})

Просмотреть файл

@ -41,9 +41,9 @@ class ProcessExecutionMixin(LoggingMixin):
"""Mix-in that provides process execution functionality.""" """Mix-in that provides process execution functionality."""
def run_process(self, args=None, cwd=None, append_env=None, def run_process(self, args=None, cwd=None, append_env=None,
explicit_env=None, log_name=None, log_level=logging.INFO, explicit_env=None, log_name=None, log_level=logging.INFO,
line_handler=None, require_unix_environment=False, line_handler=None, require_unix_environment=False,
ensure_exit_code=0, ignore_children=False, pass_thru=False): ensure_exit_code=0, ignore_children=False, pass_thru=False):
"""Runs a single process to completion. """Runs a single process to completion.
Takes a list of arguments to run where the first item is the Takes a list of arguments to run where the first item is the
@ -131,8 +131,9 @@ class ProcessExecutionMixin(LoggingMixin):
pass pass
else: else:
p = ProcessHandlerMixin(args, cwd=cwd, env=use_env, p = ProcessHandlerMixin(args, cwd=cwd, env=use_env,
processOutputLine=[handleLine], universal_newlines=True, processOutputLine=[handleLine],
ignore_children=ignore_children) universal_newlines=True,
ignore_children=ignore_children)
p.run() p.run()
p.processOutput() p.processOutput()
status = p.wait() status = p.wait()

Просмотреть файл

@ -29,11 +29,11 @@ class MachRegistrar(object):
if not handler.category: if not handler.category:
raise MachError('Cannot register a mach command without a ' raise MachError('Cannot register a mach command without a '
'category: %s' % name) 'category: %s' % name)
if handler.category not in self.categories: 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)) 'category: %s -> %s' % (name, handler.category))
self.command_handlers[name] = handler self.command_handlers[name] = handler
self.commands_by_category[handler.category].add(name) self.commands_by_category[handler.category].add(name)

Просмотреть файл

@ -72,4 +72,3 @@ class TerminalFooter(object):
def draw(self): def draw(self):
raise Exception('draw() must be implemented.') raise Exception('draw() must be implemented.')

Просмотреть файл

@ -9,10 +9,10 @@ import os
import unittest import unittest
from mach.main import Mach from mach.main import Mach
from mach.base import CommandContext
here = os.path.abspath(os.path.dirname(__file__)) here = os.path.abspath(os.path.dirname(__file__))
class TestBase(unittest.TestCase): class TestBase(unittest.TestCase):
provider_dir = os.path.join(here, 'providers') provider_dir = os.path.join(here, 'providers')

Просмотреть файл

@ -9,14 +9,17 @@ from mach.decorators import (
Command, Command,
) )
def is_foo(cls): def is_foo(cls):
"""Foo must be true""" """Foo must be true"""
return cls.foo return cls.foo
def is_bar(cls): def is_bar(cls):
"""Bar must be true""" """Bar must be true"""
return cls.bar return cls.bar
@CommandProvider @CommandProvider
class ConditionsProvider(object): class ConditionsProvider(object):
foo = True foo = True
@ -34,6 +37,7 @@ class ConditionsProvider(object):
def run_foobar(self): def run_foobar(self):
pass pass
@CommandProvider @CommandProvider
class ConditionsContextProvider(object): class ConditionsContextProvider(object):
def __init__(self, context): def __init__(self, context):

Просмотреть файл

@ -9,6 +9,7 @@ from mach.decorators import (
Command, Command,
) )
@CommandProvider @CommandProvider
class ConditionsProvider(object): class ConditionsProvider(object):
@Command('cmd_foo', category='testing', conditions=["invalid"]) @Command('cmd_foo', category='testing', conditions=["invalid"])

Просмотреть файл

@ -4,8 +4,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import time
from mach.decorators import ( from mach.decorators import (
CommandArgument, CommandArgument,
CommandProvider, CommandProvider,
@ -26,4 +24,3 @@ class TestCommandProvider(object):
@CommandArgument('--message', '-m', default='General Error') @CommandArgument('--message', '-m', default='General Error')
def throw_deep(self, message): def throw_deep(self, message):
throw2.throw_deep(message) throw2.throw_deep(message)

Просмотреть файл

@ -6,8 +6,10 @@
# exceptions that occur in mach command modules themselves and in the things # exceptions that occur in mach command modules themselves and in the things
# they call. # they call.
def throw_deep(message): def throw_deep(message):
return throw_real(message) return throw_real(message)
def throw_real(message): def throw_real(message):
raise Exception(message) raise Exception(message)

Просмотреть файл

@ -23,6 +23,7 @@ def _populate_context(context, key=None):
return False return False
raise AttributeError(key) raise AttributeError(key)
class TestConditions(TestBase): class TestConditions(TestBase):
"""Tests for conditionally filtering commands.""" """Tests for conditionally filtering commands."""
@ -30,7 +31,6 @@ class TestConditions(TestBase):
return TestBase._run_mach(self, args, 'conditions.py', return TestBase._run_mach(self, args, 'conditions.py',
context_handler=context_handler) context_handler=context_handler)
def test_conditions_pass(self): def test_conditions_pass(self):
"""Test that a command which passes its conditions is runnable.""" """Test that a command which passes its conditions is runnable."""
@ -65,7 +65,7 @@ class TestConditions(TestBase):
m = Mach(os.getcwd()) m = Mach(os.getcwd())
m.define_category('testing', 'Mach unittest', 'Testing for mach core', 10) m.define_category('testing', 'Mach unittest', 'Testing for mach core', 10)
self.assertRaises(MachError, m.load_commands_from_file, self.assertRaises(MachError, m.load_commands_from_file,
os.path.join(self.provider_dir, 'conditions_invalid.py')) os.path.join(self.provider_dir, 'conditions_invalid.py'))
def test_help_message(self): def test_help_message(self):
"""Test that commands that are not runnable do not show up in help.""" """Test that commands that are not runnable do not show up in help."""

Просмотреть файл

@ -40,6 +40,7 @@ CONFIG2 = r"""
bar = value2 bar = value2
""" """
@SettingsProvider @SettingsProvider
class Provider1(object): class Provider1(object):
config_settings = [ config_settings = [

Просмотреть файл

@ -20,7 +20,7 @@ class TestErrorOutput(TestBase):
def test_command_error(self): def test_command_error(self):
result, stdout, stderr = self._run_mach(['throw', '--message', result, stdout, stderr = self._run_mach(['throw', '--message',
'Command Error']) 'Command Error'])
self.assertEqual(result, 1) self.assertEqual(result, 1)
@ -28,7 +28,7 @@ class TestErrorOutput(TestBase):
def test_invoked_error(self): def test_invoked_error(self):
result, stdout, stderr = self._run_mach(['throw_deep', '--message', result, stdout, stderr = self._run_mach(['throw_deep', '--message',
'Deep stack']) 'Deep stack'])
self.assertEqual(result, 1) self.assertEqual(result, 1)

Просмотреть файл

@ -40,7 +40,7 @@ class TestStructuredHumanFormatter(unittest.TestCase):
value = 's\xe9curit\xe9' value = 's\xe9curit\xe9'
logger.log(logging.INFO, 'Test: {utf}', logger.log(logging.INFO, 'Test: {utf}',
extra={'action': 'action', 'params': {'utf': value}}) extra={'action': 'action', 'params': {'utf': value}})
if __name__ == '__main__': if __name__ == '__main__':

Просмотреть файл

@ -36,4 +36,3 @@ setup(
], ],
tests_require=['mock'], tests_require=['mock'],
) )

Просмотреть файл

@ -4,6 +4,7 @@ flake8:
include: include:
- config/mozunit.py - config/mozunit.py
- layout/tools/reftest - layout/tools/reftest
- python/mach
- python/mach_commands.py - python/mach_commands.py
- python/mozlint - python/mozlint
- security/manager - security/manager