python/mach_commands.py

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 from __future__ import print_function, unicode_literals
     7 import argparse
     8 import glob
     9 import logging
    10 import mozpack.path
    11 import os
    12 import sys
    14 from mozbuild.base import (
    15     MachCommandBase,
    16 )
    18 from mach.decorators import (
    19     CommandArgument,
    20     CommandProvider,
    21     Command,
    22 )
    25 @CommandProvider
    26 class MachCommands(MachCommandBase):
    27     @Command('python', category='devenv',
    28         allow_all_args=True,
    29         description='Run Python.')
    30     @CommandArgument('args', nargs=argparse.REMAINDER)
    31     def python(self, args):
    32         # Avoid logging the command
    33         self.log_manager.terminal_handler.setLevel(logging.CRITICAL)
    35         self._activate_virtualenv()
    37         return self.run_process([self.virtualenv_manager.python_path] + args,
    38             pass_thru=True, # Allow user to run Python interactively.
    39             ensure_exit_code=False, # Don't throw on non-zero exit code.
    40             # Note: subprocess requires native strings in os.environ on Windows
    41             append_env={b'PYTHONDONTWRITEBYTECODE': str('1')})
    43     @Command('python-test', category='testing',
    44         description='Run Python unit tests.')
    45     @CommandArgument('--verbose',
    46         default=False,
    47         action='store_true',
    48         help='Verbose output.')
    49     @CommandArgument('--stop',
    50         default=False,
    51         action='store_true',
    52         help='Stop running tests after the first error or failure.')
    53     @CommandArgument('tests', nargs='+',
    54         metavar='TEST',
    55         help='Tests to run. Each test can be a single file or a directory.')
    56     def python_test(self, tests, verbose=False, stop=False):
    57         self._activate_virtualenv()
    59         # Python's unittest, and in particular discover, has problems with
    60         # clashing namespaces when importing multiple test modules. What follows
    61         # is a simple way to keep environments separate, at the price of
    62         # launching Python multiple times. This also runs tests via mozunit,
    63         # which produces output in the format Mozilla infrastructure expects.
    64         return_code = 0
    65         files = []
    66         for test in tests:
    67             if test.endswith('.py') and os.path.isfile(test):
    68                 files.append(test)
    69             elif os.path.isfile(test + '.py'):
    70                 files.append(test + '.py')
    71             elif os.path.isdir(test):
    72                 files += glob.glob(mozpack.path.join(test, 'test*.py'))
    73                 files += glob.glob(mozpack.path.join(test, 'unit*.py'))
    74             else:
    75                 self.log(logging.WARN, 'python-test', {'test': test},
    76                          'TEST-UNEXPECTED-FAIL | Invalid test: {test}')
    77                 if stop:
    78                     return 1
    80         for f in files:
    81             file_displayed_test = [] # Used as a boolean.
    82             def _line_handler(line):
    83                 if not file_displayed_test and line.startswith('TEST-'):
    84                     file_displayed_test.append(True)
    86             inner_return_code = self.run_process(
    87                 [self.virtualenv_manager.python_path, f],
    88                 ensure_exit_code=False, # Don't throw on non-zero exit code.
    89                 log_name='python-test',
    90                 # subprocess requires native strings in os.environ on Windows
    91                 append_env={b'PYTHONDONTWRITEBYTECODE': str('1')},
    92                 line_handler=_line_handler)
    93             return_code += inner_return_code
    95             if not file_displayed_test:
    96                 self.log(logging.WARN, 'python-test', {'file': f},
    97                          'TEST-UNEXPECTED-FAIL | No test output (missing mozunit.main() call?): {file}')
    99             if verbose:
   100                 if inner_return_code != 0:
   101                     self.log(logging.INFO, 'python-test', {'file': f},
   102                              'Test failed: {file}')
   103                 else:
   104                     self.log(logging.INFO, 'python-test', {'file': f},
   105                              'Test passed: {file}')
   106             if stop and return_code > 0:
   107                 return 1
   109         return 0 if return_code == 0 else 1

mercurial