| Index: third_party/google-endpoints/setuptools/command/test.py
|
| diff --git a/third_party/google-endpoints/setuptools/command/test.py b/third_party/google-endpoints/setuptools/command/test.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e7a386d19d4494ee0ccc4df51f8f6338679592b9
|
| --- /dev/null
|
| +++ b/third_party/google-endpoints/setuptools/command/test.py
|
| @@ -0,0 +1,254 @@
|
| +import os
|
| +import operator
|
| +import sys
|
| +import contextlib
|
| +import itertools
|
| +from distutils.errors import DistutilsError, DistutilsOptionError
|
| +from distutils import log
|
| +from unittest import TestLoader
|
| +
|
| +import six
|
| +from six.moves import map, filter
|
| +
|
| +from pkg_resources import (resource_listdir, resource_exists, normalize_path,
|
| + working_set, _namespace_packages,
|
| + add_activation_listener, require, EntryPoint)
|
| +from setuptools import Command
|
| +from setuptools.py31compat import unittest_main
|
| +
|
| +
|
| +class ScanningLoader(TestLoader):
|
| + def loadTestsFromModule(self, module, pattern=None):
|
| + """Return a suite of all tests cases contained in the given module
|
| +
|
| + If the module is a package, load tests from all the modules in it.
|
| + If the module has an ``additional_tests`` function, call it and add
|
| + the return value to the tests.
|
| + """
|
| + tests = []
|
| + tests.append(TestLoader.loadTestsFromModule(self, module))
|
| +
|
| + if hasattr(module, "additional_tests"):
|
| + tests.append(module.additional_tests())
|
| +
|
| + if hasattr(module, '__path__'):
|
| + for file in resource_listdir(module.__name__, ''):
|
| + if file.endswith('.py') and file != '__init__.py':
|
| + submodule = module.__name__ + '.' + file[:-3]
|
| + else:
|
| + if resource_exists(module.__name__, file + '/__init__.py'):
|
| + submodule = module.__name__ + '.' + file
|
| + else:
|
| + continue
|
| + tests.append(self.loadTestsFromName(submodule))
|
| +
|
| + if len(tests) != 1:
|
| + return self.suiteClass(tests)
|
| + else:
|
| + return tests[0] # don't create a nested suite for only one return
|
| +
|
| +
|
| +# adapted from jaraco.classes.properties:NonDataProperty
|
| +class NonDataProperty(object):
|
| + def __init__(self, fget):
|
| + self.fget = fget
|
| +
|
| + def __get__(self, obj, objtype=None):
|
| + if obj is None:
|
| + return self
|
| + return self.fget(obj)
|
| +
|
| +
|
| +class test(Command):
|
| + """Command to run unit tests after in-place build"""
|
| +
|
| + description = "run unit tests after in-place build"
|
| +
|
| + user_options = [
|
| + ('test-module=', 'm', "Run 'test_suite' in specified module"),
|
| + ('test-suite=', 's',
|
| + "Test suite to run (e.g. 'some_module.test_suite')"),
|
| + ('test-runner=', 'r', "Test runner to use"),
|
| + ]
|
| +
|
| + def initialize_options(self):
|
| + self.test_suite = None
|
| + self.test_module = None
|
| + self.test_loader = None
|
| + self.test_runner = None
|
| +
|
| + def finalize_options(self):
|
| +
|
| + if self.test_suite and self.test_module:
|
| + msg = "You may specify a module or a suite, but not both"
|
| + raise DistutilsOptionError(msg)
|
| +
|
| + if self.test_suite is None:
|
| + if self.test_module is None:
|
| + self.test_suite = self.distribution.test_suite
|
| + else:
|
| + self.test_suite = self.test_module + ".test_suite"
|
| +
|
| + if self.test_loader is None:
|
| + self.test_loader = getattr(self.distribution, 'test_loader', None)
|
| + if self.test_loader is None:
|
| + self.test_loader = "setuptools.command.test:ScanningLoader"
|
| + if self.test_runner is None:
|
| + self.test_runner = getattr(self.distribution, 'test_runner', None)
|
| +
|
| + @NonDataProperty
|
| + def test_args(self):
|
| + return list(self._test_args())
|
| +
|
| + def _test_args(self):
|
| + if self.verbose:
|
| + yield '--verbose'
|
| + if self.test_suite:
|
| + yield self.test_suite
|
| +
|
| + def with_project_on_sys_path(self, func):
|
| + """
|
| + Backward compatibility for project_on_sys_path context.
|
| + """
|
| + with self.project_on_sys_path():
|
| + func()
|
| +
|
| + @contextlib.contextmanager
|
| + def project_on_sys_path(self, include_dists=[]):
|
| + with_2to3 = six.PY3 and getattr(self.distribution, 'use_2to3', False)
|
| +
|
| + if with_2to3:
|
| + # If we run 2to3 we can not do this inplace:
|
| +
|
| + # Ensure metadata is up-to-date
|
| + self.reinitialize_command('build_py', inplace=0)
|
| + self.run_command('build_py')
|
| + bpy_cmd = self.get_finalized_command("build_py")
|
| + build_path = normalize_path(bpy_cmd.build_lib)
|
| +
|
| + # Build extensions
|
| + self.reinitialize_command('egg_info', egg_base=build_path)
|
| + self.run_command('egg_info')
|
| +
|
| + self.reinitialize_command('build_ext', inplace=0)
|
| + self.run_command('build_ext')
|
| + else:
|
| + # Without 2to3 inplace works fine:
|
| + self.run_command('egg_info')
|
| +
|
| + # Build extensions in-place
|
| + self.reinitialize_command('build_ext', inplace=1)
|
| + self.run_command('build_ext')
|
| +
|
| + ei_cmd = self.get_finalized_command("egg_info")
|
| +
|
| + old_path = sys.path[:]
|
| + old_modules = sys.modules.copy()
|
| +
|
| + try:
|
| + project_path = normalize_path(ei_cmd.egg_base)
|
| + sys.path.insert(0, project_path)
|
| + working_set.__init__()
|
| + add_activation_listener(lambda dist: dist.activate())
|
| + require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version))
|
| + with self.paths_on_pythonpath([project_path]):
|
| + yield
|
| + finally:
|
| + sys.path[:] = old_path
|
| + sys.modules.clear()
|
| + sys.modules.update(old_modules)
|
| + working_set.__init__()
|
| +
|
| + @staticmethod
|
| + @contextlib.contextmanager
|
| + def paths_on_pythonpath(paths):
|
| + """
|
| + Add the indicated paths to the head of the PYTHONPATH environment
|
| + variable so that subprocesses will also see the packages at
|
| + these paths.
|
| +
|
| + Do this in a context that restores the value on exit.
|
| + """
|
| + nothing = object()
|
| + orig_pythonpath = os.environ.get('PYTHONPATH', nothing)
|
| + current_pythonpath = os.environ.get('PYTHONPATH', '')
|
| + try:
|
| + prefix = os.pathsep.join(paths)
|
| + to_join = filter(None, [prefix, current_pythonpath])
|
| + new_path = os.pathsep.join(to_join)
|
| + if new_path:
|
| + os.environ['PYTHONPATH'] = new_path
|
| + yield
|
| + finally:
|
| + if orig_pythonpath is nothing:
|
| + os.environ.pop('PYTHONPATH', None)
|
| + else:
|
| + os.environ['PYTHONPATH'] = orig_pythonpath
|
| +
|
| + @staticmethod
|
| + def install_dists(dist):
|
| + """
|
| + Install the requirements indicated by self.distribution and
|
| + return an iterable of the dists that were built.
|
| + """
|
| + ir_d = dist.fetch_build_eggs(dist.install_requires or [])
|
| + tr_d = dist.fetch_build_eggs(dist.tests_require or [])
|
| + return itertools.chain(ir_d, tr_d)
|
| +
|
| + def run(self):
|
| + installed_dists = self.install_dists(self.distribution)
|
| +
|
| + cmd = ' '.join(self._argv)
|
| + if self.dry_run:
|
| + self.announce('skipping "%s" (dry run)' % cmd)
|
| + return
|
| +
|
| + self.announce('running "%s"' % cmd)
|
| +
|
| + paths = map(operator.attrgetter('location'), installed_dists)
|
| + with self.paths_on_pythonpath(paths):
|
| + with self.project_on_sys_path():
|
| + self.run_tests()
|
| +
|
| + def run_tests(self):
|
| + # Purge modules under test from sys.modules. The test loader will
|
| + # re-import them from the build location. Required when 2to3 is used
|
| + # with namespace packages.
|
| + if six.PY3 and getattr(self.distribution, 'use_2to3', False):
|
| + module = self.test_suite.split('.')[0]
|
| + if module in _namespace_packages:
|
| + del_modules = []
|
| + if module in sys.modules:
|
| + del_modules.append(module)
|
| + module += '.'
|
| + for name in sys.modules:
|
| + if name.startswith(module):
|
| + del_modules.append(name)
|
| + list(map(sys.modules.__delitem__, del_modules))
|
| +
|
| + exit_kwarg = {} if sys.version_info < (2, 7) else {"exit": False}
|
| + test = unittest_main(
|
| + None, None, self._argv,
|
| + testLoader=self._resolve_as_ep(self.test_loader),
|
| + testRunner=self._resolve_as_ep(self.test_runner),
|
| + **exit_kwarg
|
| + )
|
| + if not test.result.wasSuccessful():
|
| + msg = 'Test failed: %s' % test.result
|
| + self.announce(msg, log.ERROR)
|
| + raise DistutilsError(msg)
|
| +
|
| + @property
|
| + def _argv(self):
|
| + return ['unittest'] + self.test_args
|
| +
|
| + @staticmethod
|
| + def _resolve_as_ep(val):
|
| + """
|
| + Load the indicated attribute value, called, as a as if it were
|
| + specified as an entry point.
|
| + """
|
| + if val is None:
|
| + return
|
| + parsed = EntryPoint.parse("x=" + val)
|
| + return parsed.resolve()()
|
|
|