summaryrefslogtreecommitdiffstats
path: root/third_party/typ
diff options
context:
space:
mode:
authordpranke <dpranke@chromium.org>2014-10-21 18:16:20 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-22 04:03:27 +0000
commitbc79418f9d091e654e83f9135b308553b990a220 (patch)
tree6e32df3d8329d696e5650c110f24672f69fa4f4c /third_party/typ
parent6d0d8be56f7af030eb3eeff25861b8ff2258ca2c (diff)
downloadchromium_src-bc79418f9d091e654e83f9135b308553b990a220.zip
chromium_src-bc79418f9d091e654e83f9135b308553b990a220.tar.gz
chromium_src-bc79418f9d091e654e83f9135b308553b990a220.tar.bz2
Roll typ to v0.8.6 / re25b780b0b147580ef248c212b238446264d9d78
This reworks the way typ handles multiprocessing again, to make the API (and the implementation) simpler for the common case. TBR=dtu@chromium.org BUG=402172 Review URL: https://codereview.chromium.org/664123005 Cr-Commit-Position: refs/heads/master@{#300599}
Diffstat (limited to 'third_party/typ')
-rw-r--r--third_party/typ/README.chromium4
-rwxr-xr-xthird_party/typ/run21
-rw-r--r--third_party/typ/typ/__main__.py8
-rw-r--r--third_party/typ/typ/fakes/host_fake.py7
-rw-r--r--third_party/typ/typ/host.py9
-rw-r--r--third_party/typ/typ/runner.py275
-rw-r--r--third_party/typ/typ/tests/host_test.py6
-rw-r--r--third_party/typ/typ/tests/runner_test.py95
-rw-r--r--third_party/typ/typ/version.py2
9 files changed, 206 insertions, 221 deletions
diff --git a/third_party/typ/README.chromium b/third_party/typ/README.chromium
index a49eb39..360a646 100644
--- a/third_party/typ/README.chromium
+++ b/third_party/typ/README.chromium
@@ -1,7 +1,7 @@
Name: typ
URL: https://github.com/dpranke/typ.git
-Version: 0.8.5
-Revision: aba6b5defd08d74dc1e52d25838b04a38088072d
+Version: 0.8.6
+Revision: e25b780b0b147580ef248c212b238446264d9d78
Security Critical: no
License: Apache 2.0
License File: NOT_SHIPPED
diff --git a/third_party/typ/run b/third_party/typ/run
index 9fb0bd2..62558a6 100755
--- a/third_party/typ/run
+++ b/third_party/typ/run
@@ -13,6 +13,9 @@ from tools import cov
is_python3 = bool(sys.version_info.major == 3)
has_python34 = False
verbose = False
+repo_dir = os.path.abspath(os.path.dirname(__file__))
+path_to_cov = os.path.join(repo_dir, 'tools', 'cov.py')
+path_to_runner = os.path.join(repo_dir, 'typ', 'runner.py')
def call(*args, **kwargs):
@@ -97,14 +100,12 @@ def run_clean(args):
def run_coverage(args):
- repo_dir = os.path.abspath(os.path.dirname(__file__))
- path_to_cov = os.path.join(repo_dir, 'tools', 'cov.py')
if not args.path:
args.path = [repo_dir]
if not args.source:
args.source = [os.path.join(repo_dir, 'typ')]
argv = cov.argv_from_args(args)
- cov_args = ['-m', 'typ', '-j', '1']
+ cov_args = [path_to_runner, '-j', '1']
call(['python', path_to_cov] + argv + cov_args)
if has_python34:
call(['python3', path_to_cov] + argv + cov_args)
@@ -138,20 +139,18 @@ def run_lint(args):
def run_tests(args):
- # Tests that we can run the command line directly if typ is in sys.path.
- call(['python', os.path.join('typ', 'runner.py'),
- 'typ.tests.main_test.TestMain.test_basic'])
+ # Test that we can run the module directly if typ is in sys.path.
+ call(['python', '-m', 'typ', 'typ.tests.main_test.TestMain.test_basic'])
# Test that we can run the command line directly if typ is not in sys.path.
- repo_dir = os.path.abspath(os.path.dirname(__file__))
home_dir = os.environ['HOME']
- call(['python', os.path.join(repo_dir, 'typ', 'runner.py'),
- 'typ.tests.main_test.TestMain.test_basic'], cwd=home_dir)
+ call(['python', path_to_runner, 'typ.tests.main_test.TestMain.test_basic'],
+ cwd=home_dir)
# Now run all the tests under Python2 and Python3.
- call(['python', '-m', 'typ'])
+ call(['python', path_to_runner])
if has_python34:
- call(['python3', '-m', 'typ'])
+ call(['python3', path_to_runner])
if __name__ == '__main__':
diff --git a/third_party/typ/typ/__main__.py b/third_party/typ/typ/__main__.py
index 375e3e2..0e026e8 100644
--- a/third_party/typ/typ/__main__.py
+++ b/third_party/typ/typ/__main__.py
@@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import sys
+import sys # pragma: no cover
-from typ import main
+from typ import main # pragma: no cover
-if __name__ == '__main__':
- sys.exit(main(win_multiprocessing='spawn'))
+if __name__ == '__main__': # pragma: no cover
+ sys.exit(main())
diff --git a/third_party/typ/typ/fakes/host_fake.py b/third_party/typ/typ/fakes/host_fake.py
index 3e8643c..5b9e46d 100644
--- a/third_party/typ/typ/fakes/host_fake.py
+++ b/third_party/typ/typ/fakes/host_fake.py
@@ -166,6 +166,13 @@ class FakeHost(object):
if path not in self.dirs:
self.dirs.add(path)
+ def mktempfile(self, delete=True):
+ curno = self.current_tmpno
+ self.current_tmpno += 1
+ f = io.StringIO()
+ f.name = '__im_tmp/tmpfile_%u' % curno
+ return f
+
def mkdtemp(self, suffix='', prefix='tmp', dir=None, **_kwargs):
if dir is None:
dir = self.sep + '__im_tmp'
diff --git a/third_party/typ/typ/host.py b/third_party/typ/typ/host.py
index c5f6ac8..fc9e113 100644
--- a/third_party/typ/typ/host.py
+++ b/third_party/typ/typ/host.py
@@ -35,6 +35,7 @@ class Host(object):
python_interpreter = sys.executable
is_python3 = bool(sys.version_info.major == 3)
+ pathsep = os.pathsep
sep = os.sep
env = os.environ
@@ -77,6 +78,11 @@ class Host(object):
return proc.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
def call_inline(self, argv, env=None):
+ if isinstance(self.stdout, _TeedStream): # pragma: no cover
+ ret, out, err = self.call(argv, env)
+ self.print_(out, end='')
+ self.print_(err, end='', stream=self.stderr)
+ return ret
return subprocess.call(argv, stdin=self.stdin, stdout=self.stdout,
stderr=self.stderr, env=env)
@@ -126,6 +132,9 @@ class Host(object):
if not self.exists(path):
os.makedirs(path)
+ def mktempfile(self, delete=True):
+ return tempfile.NamedTemporaryFile(delete=delete)
+
def mkdtemp(self, **kwargs):
return tempfile.mkdtemp(**kwargs)
diff --git a/third_party/typ/typ/runner.py b/third_party/typ/typ/runner.py
index 3a8dc82..61aeb9d 100644
--- a/third_party/typ/typ/runner.py
+++ b/third_party/typ/typ/runner.py
@@ -29,6 +29,8 @@ from collections import OrderedDict
# that typ/runner.py works when invoked via subprocess on windows in
# _spawn_main().
path_to_file = os.path.realpath(__file__)
+if path_to_file.endswith('.pyc'): # pragma: no cover
+ path_to_file = path_to_file[:-1]
dir_above_typ = os.path.dirname(os.path.dirname(path_to_file))
if dir_above_typ not in sys.path: # pragma: no cover
sys.path.append(dir_above_typ)
@@ -49,17 +51,12 @@ ResultSet = json_results.ResultSet
ResultType = json_results.ResultType
-def main(argv=None, host=None, stdout=None, stderr=None,
- win_multiprocessing=None, **defaults):
+def main(argv=None, host=None, win_multiprocessing=None, **defaults):
host = host or Host()
- if stdout:
- host.stdout = stdout
- if stderr:
- host.stderr = stderr
runner = Runner(host=host)
-
- return runner.main(argv, win_multiprocessing=win_multiprocessing,
- **defaults)
+ if win_multiprocessing is not None:
+ runner.win_multiprocessing = win_multiprocessing
+ return runner.main(argv, **defaults)
class TestInput(object):
@@ -74,8 +71,7 @@ class TestInput(object):
class TestSet(object):
def __init__(self, parallel_tests=None, isolated_tests=None,
- tests_to_skip=None, context=None, setup_fn=None,
- teardown_fn=None):
+ tests_to_skip=None):
def promote(tests):
tests = tests or []
@@ -85,18 +81,14 @@ class TestSet(object):
self.parallel_tests = promote(parallel_tests)
self.isolated_tests = promote(isolated_tests)
self.tests_to_skip = promote(tests_to_skip)
- self.context = context
- self.setup_fn = setup_fn
- self.teardown_fn = teardown_fn
class WinMultiprocessing(object):
- force = 'force'
ignore = 'ignore'
- run_serially = 'run_serially'
+ importable = 'importable'
spawn = 'spawn'
- values = [force, ignore, run_serially, spawn]
+ values = [ignore, importable, spawn]
class _AddTestsError(Exception):
@@ -106,29 +98,32 @@ class _AddTestsError(Exception):
class Runner(object):
def __init__(self, host=None):
+ self.args = None
+ self.classifier = None
+ self.cov = None
+ self.context = None
+ self.coverage_source = None
self.host = host or Host()
self.loader = unittest.loader.TestLoader()
self.printer = None
+ self.setup_fn = None
self.stats = None
- self.cov = None
- self.coverage_source = None
+ self.teardown_fn = None
self.top_level_dir = None
- self.args = None
+ self.win_multiprocessing = WinMultiprocessing.spawn
# initialize self.args to the defaults.
parser = ArgumentParser(self.host)
self.parse_args(parser, [])
- def main(self, argv=None, win_multiprocessing=None, **defaults):
+ def main(self, argv=None, **defaults):
parser = ArgumentParser(self.host)
self.parse_args(parser, argv, **defaults)
if parser.exit_status is not None:
return parser.exit_status
try:
- ret = self._handle_win_multiprocessing('main', win_multiprocessing)
- if ret is None:
- ret, _, _ = self.run(win_multiprocessing=win_multiprocessing)
+ ret, _, _ = self.run()
return ret
except KeyboardInterrupt:
self.print_("interrupted, exiting", stream=self.host.stderr)
@@ -145,65 +140,10 @@ class Runner(object):
if parser.exit_status is not None:
return
- def _handle_win_multiprocessing(self, entry_point, win_multiprocessing,
- allow_spawn=True):
- wmp = win_multiprocessing
- force, ignore, run_serially, spawn = WinMultiprocessing.values
-
- if (wmp is not None and wmp not in WinMultiprocessing.values):
- raise ValueError('illegal value %s for win_multiprocessing' %
- wmp)
-
- # First, check if __main__ is importable; if it is, we're fine.
- if (self._main_is_importable() and wmp != force):
- return None
-
- if wmp is None and self.args.jobs == 1:
- return None
-
- if wmp is None:
- raise ValueError(
- 'The __main__ module is not importable; The caller '
- 'must pass a valid WinMultiprocessing value (one of %s) '
- 'to %s to tell typ how to handle Windows.' %
- (WinMultiprocessing.values, entry_point))
-
- h = self.host
-
- if (h.platform != 'win32' and wmp != force):
- return
-
- if wmp == ignore: # pragma: win32
- raise ValueError('Cannot use WinMultiprocessing.ignore for '
- 'win_multiprocessing when actually running '
- 'on Windows.')
-
- if wmp == run_serially: # pragma: win32
- self.args.jobs = 1
- return None
-
- assert allow_spawn, ('Cannot use WinMultiprocessing.spawn '
- 'in %s' % entry_point)
- assert wmp in (force, spawn)
- argv = ArgumentParser(h).argv_from_args(self.args)
- return h.call_inline([h.python_interpreter, path_to_file] + argv)
-
- def _main_is_importable(self):
- path = self.host.realpath(sys.modules['__main__'].__file__)
- if not path or not path.endswith('.py'): # pragma: no cover
- return False
-
- for d in sys.path:
- if path.startswith(self.host.realpath(d)):
- return True
- return False # pragma: no cover
-
def print_(self, msg='', end='\n', stream=None):
self.host.print_(msg, end, stream=stream)
- def run(self, test_set=None, classifier=None,
- context=None, setup_fn=None, teardown_fn=None,
- win_multiprocessing=None):
+ def run(self, test_set=None):
ret = 0
h = self.host
@@ -212,8 +152,9 @@ class Runner(object):
self.print_(VERSION)
return ret, None, None
- self._handle_win_multiprocessing('Runner.run', win_multiprocessing,
- allow_spawn=False)
+ should_spawn = self._check_win_multiprocessing()
+ if should_spawn:
+ return self._spawn(test_set)
ret = self._set_up_runner()
if ret: # pragma: no cover
@@ -228,8 +169,7 @@ class Runner(object):
result_set = ResultSet()
if not test_set:
- ret, test_set = self.find_tests(self.args, classifier, context,
- setup_fn, teardown_fn)
+ ret, test_set = self.find_tests(self.args)
find_end = h.time()
if not ret:
@@ -243,8 +183,8 @@ class Runner(object):
trace = self._trace_from_results(result_set)
if full_results:
self._summarize(full_results)
- self.write_results(full_results)
- upload_ret = self.upload_results(full_results)
+ self._write(self.args.write_full_results_to, full_results)
+ upload_ret = self._upload(full_results)
if not ret:
ret = upload_ret
reporting_end = h.time()
@@ -252,13 +192,93 @@ class Runner(object):
self._add_trace_event(trace, 'discovery', find_start, find_end)
self._add_trace_event(trace, 'testing', find_end, test_end)
self._add_trace_event(trace, 'reporting', test_end, reporting_end)
- self.write_trace(trace)
+ self._write(self.args.write_trace_to, trace)
self.report_coverage()
else:
upload_ret = 0
return ret, full_results, trace
+ def _check_win_multiprocessing(self):
+ wmp = self.win_multiprocessing
+
+ ignore, importable, spawn = WinMultiprocessing.values
+
+ if wmp not in WinMultiprocessing.values:
+ raise ValueError('illegal value %s for win_multiprocessing' %
+ wmp)
+
+ h = self.host
+ if wmp == ignore and h.platform == 'win32': # pragma: win32
+ raise ValueError('Cannot use WinMultiprocessing.ignore for '
+ 'win_multiprocessing when actually running '
+ 'on Windows.')
+
+ if wmp == ignore or self.args.jobs == 1:
+ return False
+
+ if wmp == importable:
+ if self._main_is_importable():
+ return False
+ raise ValueError('The __main__ module (%s) ' # pragma: no cover
+ 'may not be importable' %
+ sys.modules['__main__'].__file__)
+
+ assert wmp == spawn
+ return True
+
+ def _main_is_importable(self): # pragma: untested
+ path = sys.modules['__main__'].__file__
+ if not path:
+ return False
+ if path.endswith('.pyc'):
+ path = path[:-1]
+ if not path.endswith('.py'):
+ return False
+ if path.endswith('__main__.py'):
+ # main modules are not directly importable.
+ return False
+
+ path = self.host.realpath(path)
+ for d in sys.path:
+ if path.startswith(self.host.realpath(d)):
+ return True
+ return False # pragma: no cover
+
+ def _spawn(self, test_set):
+ # TODO: Handle picklable hooks, rather than requiring them to be None.
+ assert self.classifier is None
+ assert self.context is None
+ assert self.setup_fn is None
+ assert self.teardown_fn is None
+ assert test_set is None
+ h = self.host
+
+ if self.args.write_trace_to: # pragma: untested
+ should_delete_trace = False
+ else:
+ should_delete_trace = True
+ fp = h.mktempfile(delete=False)
+ fp.close()
+ self.args.write_trace_to = fp.name
+
+ if self.args.write_full_results_to: # pragma: untested
+ should_delete_results = False
+ else:
+ should_delete_results = True
+ fp = h.mktempfile(delete=False)
+ fp.close()
+ self.args.write_full_results_to = fp.name
+
+ argv = ArgumentParser(h).argv_from_args(self.args)
+ ret = h.call_inline([h.python_interpreter, path_to_file] + argv)
+
+ trace = self._read_and_delete(self.args.write_trace_to,
+ should_delete_trace)
+ full_results = self._read_and_delete(self.args.write_full_results_to,
+ should_delete_results)
+ return ret, full_results, trace
+
def _set_up_runner(self):
h = self.host
args = self.args
@@ -303,11 +323,8 @@ class Runner(object):
self.cov.erase()
return 0
- def find_tests(self, args, classifier=None,
- context=None, setup_fn=None, teardown_fn=None):
- test_set = self._make_test_set(context=context,
- setup_fn=setup_fn,
- teardown_fn=teardown_fn)
+ def find_tests(self, args):
+ test_set = TestSet()
orig_skip = unittest.skip
orig_skip_if = unittest.skipIf
@@ -317,7 +334,7 @@ class Runner(object):
try:
names = self._name_list_from_args(args)
- classifier = classifier or _default_classifier(args)
+ classifier = self.classifier or _default_classifier(args)
for name in names:
try:
@@ -396,7 +413,7 @@ class Runner(object):
self._run_one_set(self.stats, result_set, test_set)
- failed_tests = json_results.failed_test_names(result_set)
+ failed_tests = sorted(json_results.failed_test_names(result_set))
retry_limit = self.args.retry_limit
while retry_limit and failed_tests:
@@ -414,11 +431,7 @@ class Runner(object):
stats = Stats(self.args.status_format, h.time, 1)
stats.total = len(failed_tests)
- tests_to_retry = self._make_test_set(
- isolated_tests=[TestInput(name) for name in failed_tests],
- context=test_set.context,
- setup_fn=test_set.setup_fn,
- teardown_fn=test_set.teardown_fn)
+ tests_to_retry = TestSet(isolated_tests=list(failed_tests))
retry_set = ResultSet()
self._run_one_set(stats, retry_set, tests_to_retry)
result_set.results.extend(retry_set.results)
@@ -435,26 +448,14 @@ class Runner(object):
return (json_results.exit_code_from_full_results(full_results),
full_results)
- def _make_test_set(self, parallel_tests=None, isolated_tests=None,
- tests_to_skip=None, context=None, setup_fn=None,
- teardown_fn=None):
- parallel_tests = parallel_tests or []
- isolated_tests = isolated_tests or []
- tests_to_skip = tests_to_skip or []
- return TestSet(_sort_inputs(parallel_tests),
- _sort_inputs(isolated_tests),
- _sort_inputs(tests_to_skip),
- context, setup_fn, teardown_fn)
-
def _run_one_set(self, stats, result_set, test_set):
stats.total = (len(test_set.parallel_tests) +
len(test_set.isolated_tests) +
len(test_set.tests_to_skip))
self._skip_tests(stats, result_set, test_set.tests_to_skip)
- self._run_list(stats, result_set, test_set,
- test_set.parallel_tests, self.args.jobs)
- self._run_list(stats, result_set, test_set,
- test_set.isolated_tests, 1)
+ self._run_list(stats, result_set, test_set.parallel_tests,
+ self.args.jobs)
+ self._run_list(stats, result_set, test_set.isolated_tests, 1)
def _skip_tests(self, stats, result_set, tests_to_skip):
for test_input in tests_to_skip:
@@ -470,7 +471,7 @@ class Runner(object):
stats.finished += 1
self._print_test_finished(stats, result)
- def _run_list(self, stats, result_set, test_set, test_inputs, jobs):
+ def _run_list(self, stats, result_set, test_inputs, jobs):
h = self.host
running_jobs = set()
@@ -478,7 +479,7 @@ class Runner(object):
if not jobs:
return
- child = _Child(self, self.loader, test_set)
+ child = _Child(self)
pool = make_pool(h, jobs, _run_one_test, child,
_setup_process, _teardown_process)
try:
@@ -572,19 +573,22 @@ class Runner(object):
'' if num_failures == 1 else 's'), elide=False)
self.print_()
- def write_trace(self, trace):
- if self.args.write_trace_to:
- self.host.write_text_file(
- self.args.write_trace_to,
- json.dumps(trace, indent=2) + '\n')
-
- def write_results(self, full_results):
- if self.args.write_full_results_to:
- self.host.write_text_file(
- self.args.write_full_results_to,
- json.dumps(full_results, indent=2) + '\n')
-
- def upload_results(self, full_results):
+ def _read_and_delete(self, path, delete):
+ h = self.host
+ obj = None
+ if h.exists(path):
+ contents = h.read_text_file(path)
+ if contents:
+ obj = json.loads(contents)
+ if delete:
+ h.remove(path)
+ return obj
+
+ def _write(self, path, obj):
+ if path:
+ self.host.write_text_file(path, json.dumps(obj, indent=2) + '\n')
+
+ def _upload(self, full_results):
h = self.host
if not self.args.test_results_server:
return 0
@@ -697,7 +701,7 @@ def _test_adder(test_set, classifier):
class _Child(object):
- def __init__(self, parent, loader, test_set):
+ def __init__(self, parent):
self.host = None
self.worker_num = None
self.all = parent.args.all
@@ -705,11 +709,11 @@ class _Child(object):
self.coverage = parent.args.coverage and parent.args.jobs > 1
self.coverage_source = parent.coverage_source
self.dry_run = parent.args.dry_run
- self.loader = loader
+ self.loader = parent.loader
self.passthrough = parent.args.passthrough
- self.context = test_set.context
- self.setup_fn = test_set.setup_fn
- self.teardown_fn = test_set.teardown_fn
+ self.context = parent.context
+ self.setup_fn = parent.setup_fn
+ self.teardown_fn = parent.teardown_fn
self.context_after_setup = None
self.top_level_dir = parent.top_level_dir
self.loaded_suites = {}
@@ -897,4 +901,5 @@ def _sort_inputs(inps):
if __name__ == '__main__': # pragma: no cover
- sys.exit(main(win_multiprocessing='spawn'))
+ sys.modules['__main__'].__file__ = path_to_file
+ sys.exit(main(win_multiprocessing=WinMultiprocessing.importable))
diff --git a/third_party/typ/typ/tests/host_test.py b/third_party/typ/typ/tests/host_test.py
index 50db37f..a06085a 100644
--- a/third_party/typ/typ/tests/host_test.py
+++ b/third_party/typ/typ/tests/host_test.py
@@ -130,6 +130,12 @@ class TestHost(unittest.TestCase):
self.assertEqual(h.basename('foo.txt'), 'foo.txt')
self.assertEqual(h.basename('foo/bar.txt'), 'bar.txt')
+ def test_mktempfile(self, delete=False):
+ h = self.host()
+ f= h.mktempfile()
+ f.close()
+ self.assertNotEqual(f.name, None)
+
def test_splitext(self):
h = self.host()
self.assertEqual(h.splitext('foo'), ('foo', ''))
diff --git a/third_party/typ/typ/tests/runner_test.py b/third_party/typ/typ/tests/runner_test.py
index 1d3b0cc..1d8e510 100644
--- a/third_party/typ/typ/tests/runner_test.py
+++ b/third_party/typ/typ/tests/runner_test.py
@@ -18,7 +18,7 @@ from textwrap import dedent as d
from typ import Host, Runner, TestCase, TestSet, TestInput
-from typ import WinMultiprocessing, main
+from typ import WinMultiprocessing
def _setup_process(child, context): # pylint: disable=W0613
@@ -33,8 +33,11 @@ class RunnerTests(TestCase):
def test_context(self):
r = Runner()
r.args.tests = ['typ.tests.runner_test.ContextTests']
- ret, _, _ = r.run(context={'foo': 'bar'}, setup_fn=_setup_process,
- teardown_fn=_teardown_process)
+ r.context = {'foo': 'bar'}
+ r.setup_fn = _setup_process
+ r.teardown_fn = _teardown_process
+ r.win_multiprocessing = WinMultiprocessing.importable
+ ret, _, _ = r.run()
self.assertEqual(ret, 0)
def test_bad_default(self):
@@ -57,6 +60,7 @@ class TestSetTests(TestCase):
test_set = TestSet()
test_set.parallel_tests = [TestInput('nonexistent test')]
r = Runner()
+ r.args.jobs = 1
ret, _, _ = r.run(test_set)
self.assertEqual(ret, 1)
@@ -75,6 +79,7 @@ class TestSetTests(TestCase):
test_set = TestSet()
test_set.parallel_tests = [TestInput('load_test.BaseTest.test_x')]
r = Runner()
+ r.args.jobs = 1
ret, _, _ = r.run(test_set)
self.assertEqual(ret, 1)
finally:
@@ -87,7 +92,7 @@ class TestWinMultiprocessing(TestCase):
def make_host(self):
return Host()
- def call(self, argv, platform=None, importable=None, **kwargs):
+ def call(self, argv, platform=None, win_multiprocessing=None, **kwargs):
h = self.make_host()
orig_wd = h.getcwd()
tmpdir = None
@@ -98,8 +103,8 @@ class TestWinMultiprocessing(TestCase):
if platform is not None:
h.platform = platform
r = Runner(h)
- if importable is not None:
- r._main_is_importable = lambda: importable
+ if win_multiprocessing is not None:
+ r.win_multiprocessing = win_multiprocessing
ret = r.main(argv, **kwargs)
finally:
out, err = h.restore_output()
@@ -112,64 +117,19 @@ class TestWinMultiprocessing(TestCase):
def test_bad_value(self):
self.assertRaises(ValueError, self.call, [], win_multiprocessing='foo')
- def test_force(self):
- h = self.make_host()
- tmpdir = None
- orig_wd = h.getcwd()
- out = err = None
- out_str = err_str = ''
- try:
- tmpdir = h.mkdtemp()
- h.chdir(tmpdir)
- out = tempfile.NamedTemporaryFile(delete=False)
- err = tempfile.NamedTemporaryFile(delete=False)
- ret = main([], stdout=out, stderr=err,
- win_multiprocessing=WinMultiprocessing.force)
- finally:
- h.chdir(orig_wd)
- if tmpdir:
- h.rmtree(tmpdir)
- if out:
- out.close()
- out = open(out.name)
- out_str = out.read()
- out.close()
- h.remove(out.name)
- if err:
- err.close()
- err = open(err.name)
- err_str = err.read()
- err.close()
- h.remove(err.name)
-
- self.assertEqual(ret, 1)
- self.assertEqual(out_str, 'No tests to run.\n')
- self.assertEqual(err_str, '')
-
def test_ignore(self):
h = self.make_host()
if h.platform == 'win32': # pragma: win32
self.assertRaises(ValueError, self.call, [],
win_multiprocessing=WinMultiprocessing.ignore)
else:
- result = self.call([], platform=None, importable=False,
+ result = self.call([],
win_multiprocessing=WinMultiprocessing.ignore)
ret, out, err = result
self.assertEqual(ret, 1)
self.assertEqual(out, 'No tests to run.\n')
self.assertEqual(err, '')
- def test_multiple_jobs(self):
- self.assertRaises(ValueError, self.call, ['-j', '2'],
- platform='win32', importable=False)
-
- def test_normal(self):
- # This tests that typ itself is importable ...
- ret, out, err = self.call([])
- self.assertEqual(ret, 1)
- self.assertEqual(out, 'No tests to run.\n')
- self.assertEqual(err, '')
-
def test_real_unimportable_main(self):
h = self.make_host()
tmpdir = None
@@ -182,11 +142,19 @@ class TestWinMultiprocessing(TestCase):
out = tempfile.NamedTemporaryFile(delete=False)
err = tempfile.NamedTemporaryFile(delete=False)
path_above_typ = h.realpath(h.dirname(__file__), '..', '..')
- env = {'PYTHONPATH': path_above_typ}
+ env = h.env.copy()
+ if 'PYTHONPATH' in env: # pragma: untested
+ env['PYTHONPATH'] = '%s%s%s' % (env['PYTHONPATH'],
+ h.pathsep,
+ path_above_typ)
+ else: # pragma: untested.
+ env['PYTHONPATH'] = path_above_typ
+
h.write_text_file('test', d("""
import sys
import typ
- sys.exit(typ.main())
+ importable = typ.WinMultiprocessing.importable
+ sys.exit(typ.main(win_multiprocessing=importable))
"""))
h.stdout = out
h.stderr = err
@@ -211,28 +179,19 @@ class TestWinMultiprocessing(TestCase):
self.assertEqual(ret, 1)
self.assertEqual(out_str, '')
- self.assertIn('ValueError: The __main__ module is not importable',
+ self.assertIn('ValueError: The __main__ module ',
err_str)
- def test_run_serially(self):
- ret, out, err = self.call([], importable=False,
- win_multiprocessing=WinMultiprocessing.spawn)
- self.assertEqual(ret, 1)
- self.assertEqual(out, 'No tests to run.\n')
- self.assertEqual(err, '')
-
def test_single_job(self):
- ret, out, err = self.call(['-j', '1'], platform='win32',
- importable=False)
+ ret, out, err = self.call(['-j', '1'], platform='win32')
self.assertEqual(ret, 1)
- self.assertEqual(out, 'No tests to run.\n')
+ self.assertIn('No tests to run.', out)
self.assertEqual(err, '')
def test_spawn(self):
- ret, out, err = self.call([], importable=False,
- win_multiprocessing=WinMultiprocessing.spawn)
+ ret, out, err = self.call([])
self.assertEqual(ret, 1)
- self.assertEqual(out, 'No tests to run.\n')
+ self.assertIn('No tests to run.', out)
self.assertEqual(err, '')
diff --git a/third_party/typ/typ/version.py b/third_party/typ/typ/version.py
index 96ebc7a..3b66ba0 100644
--- a/third_party/typ/typ/version.py
+++ b/third_party/typ/typ/version.py
@@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-VERSION = '0.8.5'
+VERSION = '0.8.6'