From 1f4eb724612022db65e66186e6abfde4201f40e4 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 12 Jun 2016 09:45:41 -0400 Subject: Move try_execfile.py to an unambiguous place Where it was, we were counting on "tests" referring to coverage.py's own tests directory, but a -e install of a helper like unittest-mixins could provide a tests directory, which prevented the imports we needed for the tests. Moving try_execfile.py to a new subdirectory with a less-common name solves the problem. --HG-- rename : tests/try_execfile.py => tests/modules/process_test/try_execfile.py --- tests/modules/process_test/__init__.py | 0 tests/modules/process_test/try_execfile.py | 84 ++++++++++++++++++++++++++++++ tests/test_process.py | 40 ++++++++------ tests/try_execfile.py | 84 ------------------------------ tox.ini | 3 +- 5 files changed, 110 insertions(+), 101 deletions(-) create mode 100644 tests/modules/process_test/__init__.py create mode 100644 tests/modules/process_test/try_execfile.py delete mode 100644 tests/try_execfile.py diff --git a/tests/modules/process_test/__init__.py b/tests/modules/process_test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/modules/process_test/try_execfile.py b/tests/modules/process_test/try_execfile.py new file mode 100644 index 00000000..70905071 --- /dev/null +++ b/tests/modules/process_test/try_execfile.py @@ -0,0 +1,84 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt + +"""Test file for run_python_file. + +This file is executed two ways:: + + $ coverage run try_execfile.py + +and:: + + $ python try_execfile.py + +The output is compared to see that the program execution context is the same +under coverage and under Python. + +It is not crucial that the execution be identical, there are some differences +that are OK. This program canonicalizes the output to gloss over those +differences and get a clean diff. + +""" + +import json, os, sys + +# sys.path varies by execution environments. Coverage.py uses setuptools to +# make console scripts, which means pkg_resources is imported. pkg_resources +# removes duplicate entries from sys.path. So we do that too, since the extra +# entries don't affect the running of the program. + +def same_file(p1, p2): + """Determine if `p1` and `p2` refer to the same existing file.""" + if not p1: + return not p2 + if not os.path.exists(p1): + return False + if not os.path.exists(p2): + return False + if hasattr(os.path, "samefile"): + return os.path.samefile(p1, p2) + else: + norm1 = os.path.normcase(os.path.normpath(p1)) + norm2 = os.path.normcase(os.path.normpath(p2)) + return norm1 == norm2 + +def without_same_files(filenames): + """Return the list `filenames` with duplicates (by same_file) removed.""" + reduced = [] + for filename in filenames: + if not any(same_file(filename, other) for other in reduced): + reduced.append(filename) + return reduced + +cleaned_sys_path = [os.path.normcase(p) for p in without_same_files(sys.path)] + +DATA = "xyzzy" + +import __main__ + +def my_function(a): + """A function to force execution of module-level values.""" + return "my_fn(%r)" % a + +FN_VAL = my_function("fooey") + +loader = globals().get('__loader__') +fullname = getattr(loader, 'fullname', None) or getattr(loader, 'name', None) + +globals_to_check = { + '__name__': __name__, + '__file__': __file__, + '__doc__': __doc__, + '__builtins__.has_open': hasattr(__builtins__, 'open'), + '__builtins__.dir': dir(__builtins__), + '__loader__ exists': loader is not None, + '__loader__.fullname': fullname, + '__package__': __package__, + 'DATA': DATA, + 'FN_VAL': FN_VAL, + '__main__.DATA': getattr(__main__, "DATA", "nothing"), + 'argv': sys.argv, + 'path': cleaned_sys_path, +} + +print(json.dumps(globals_to_check, indent=4, sort_keys=True)) diff --git a/tests/test_process.py b/tests/test_process.py index 51bdaf21..05588440 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -17,7 +17,7 @@ from coverage.misc import output_encoding from tests.coveragetest import CoverageTest -HERE = os.path.dirname(__file__) +TRY_EXECFILE = os.path.join(os.path.dirname(__file__), "modules", "process_test", "try_execfile.py") class ProcessTest(CoverageTest): @@ -42,7 +42,7 @@ class ProcessTest(CoverageTest): self.assert_exists(".coverage") def test_environment(self): - # Checks that we can import modules from the test directory at all! + # Checks that we can import modules from the tests directory at all! self.make_file("mycode.py", """\ import covmod1 import covmodzip1 @@ -425,23 +425,27 @@ class ProcessTest(CoverageTest): self.assertEqual(status, status2) self.assertEqual(status, 0) + def assert_execfile_output(self, out): + """Assert that the output we got is a successful run of try_execfile.py""" + self.assertIn('"DATA": "xyzzy"', out) + def test_coverage_run_is_like_python(self): - tryfile = os.path.join(HERE, "try_execfile.py") - with open(tryfile) as f: + with open(TRY_EXECFILE) as f: self.make_file("run_me.py", f.read()) out_cov = self.run_command("coverage run run_me.py") out_py = self.run_command("python run_me.py") self.assertMultiLineEqual(out_cov, out_py) + self.assert_execfile_output(out_cov) def test_coverage_run_dashm_is_like_python_dashm(self): # These -m commands assume the coverage tree is on the path. - out_cov = self.run_command("coverage run -m tests.try_execfile") - out_py = self.run_command("python -m tests.try_execfile") + out_cov = self.run_command("coverage run -m process_test.try_execfile") + out_py = self.run_command("python -m process_test.try_execfile") self.assertMultiLineEqual(out_cov, out_py) + self.assert_execfile_output(out_cov) def test_coverage_run_dir_is_like_python_dir(self): - tryfile = os.path.join(HERE, "try_execfile.py") - with open(tryfile) as f: + with open(TRY_EXECFILE) as f: self.make_file("with_main/__main__.py", f.read()) out_cov = self.run_command("coverage run with_main") out_py = self.run_command("python with_main") @@ -458,6 +462,7 @@ class ProcessTest(CoverageTest): out_cov = remove_matching_lines(out_cov, ignored) out_py = remove_matching_lines(out_py, ignored) self.assertMultiLineEqual(out_cov, out_py) + self.assert_execfile_output(out_cov) def test_coverage_run_dashm_equal_to_doubledashsource(self): """regression test for #328 @@ -467,19 +472,21 @@ class ProcessTest(CoverageTest): """ # These -m commands assume the coverage tree is on the path. out_cov = self.run_command( - "coverage run --source tests.try_execfile -m tests.try_execfile" + "coverage run --source process_test.try_execfile -m process_test.try_execfile" ) - out_py = self.run_command("python -m tests.try_execfile") + out_py = self.run_command("python -m process_test.try_execfile") self.assertMultiLineEqual(out_cov, out_py) + self.assert_execfile_output(out_cov) def test_coverage_run_dashm_superset_of_doubledashsource(self): """Edge case: --source foo -m foo.bar""" # These -m commands assume the coverage tree is on the path. out_cov = self.run_command( - "coverage run --source tests -m tests.try_execfile" + "coverage run --source process_test -m process_test.try_execfile" ) - out_py = self.run_command("python -m tests.try_execfile") + out_py = self.run_command("python -m process_test.try_execfile") self.assertMultiLineEqual(out_cov, out_py) + self.assert_execfile_output(out_cov) st, out = self.run_command_status("coverage report") self.assertEqual(st, 0) @@ -493,15 +500,16 @@ class ProcessTest(CoverageTest): # keeps the test working. self.make_file("myscript", """\ import sys; sys.dont_write_bytecode = True - import tests.try_execfile + import process_test.try_execfile """) # These -m commands assume the coverage tree is on the path. out_cov = self.run_command( - "coverage run --source tests myscript" + "coverage run --source process_test myscript" ) out_py = self.run_command("python myscript") self.assertMultiLineEqual(out_cov, out_py) + self.assert_execfile_output(out_cov) st, out = self.run_command_status("coverage report") self.assertEqual(st, 0) @@ -509,13 +517,13 @@ class ProcessTest(CoverageTest): def test_coverage_run_dashm_is_like_python_dashm_off_path(self): # https://bitbucket.org/ned/coveragepy/issue/242 - tryfile = os.path.join(HERE, "try_execfile.py") self.make_file("sub/__init__.py", "") - with open(tryfile) as f: + with open(TRY_EXECFILE) as f: self.make_file("sub/run_me.py", f.read()) out_cov = self.run_command("coverage run -m sub.run_me") out_py = self.run_command("python -m sub.run_me") self.assertMultiLineEqual(out_cov, out_py) + self.assert_execfile_output(out_cov) def test_coverage_run_dashm_is_like_python_dashm_with__main__207(self): if sys.version_info < (2, 7): diff --git a/tests/try_execfile.py b/tests/try_execfile.py deleted file mode 100644 index 70905071..00000000 --- a/tests/try_execfile.py +++ /dev/null @@ -1,84 +0,0 @@ -# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 -# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt - -"""Test file for run_python_file. - -This file is executed two ways:: - - $ coverage run try_execfile.py - -and:: - - $ python try_execfile.py - -The output is compared to see that the program execution context is the same -under coverage and under Python. - -It is not crucial that the execution be identical, there are some differences -that are OK. This program canonicalizes the output to gloss over those -differences and get a clean diff. - -""" - -import json, os, sys - -# sys.path varies by execution environments. Coverage.py uses setuptools to -# make console scripts, which means pkg_resources is imported. pkg_resources -# removes duplicate entries from sys.path. So we do that too, since the extra -# entries don't affect the running of the program. - -def same_file(p1, p2): - """Determine if `p1` and `p2` refer to the same existing file.""" - if not p1: - return not p2 - if not os.path.exists(p1): - return False - if not os.path.exists(p2): - return False - if hasattr(os.path, "samefile"): - return os.path.samefile(p1, p2) - else: - norm1 = os.path.normcase(os.path.normpath(p1)) - norm2 = os.path.normcase(os.path.normpath(p2)) - return norm1 == norm2 - -def without_same_files(filenames): - """Return the list `filenames` with duplicates (by same_file) removed.""" - reduced = [] - for filename in filenames: - if not any(same_file(filename, other) for other in reduced): - reduced.append(filename) - return reduced - -cleaned_sys_path = [os.path.normcase(p) for p in without_same_files(sys.path)] - -DATA = "xyzzy" - -import __main__ - -def my_function(a): - """A function to force execution of module-level values.""" - return "my_fn(%r)" % a - -FN_VAL = my_function("fooey") - -loader = globals().get('__loader__') -fullname = getattr(loader, 'fullname', None) or getattr(loader, 'name', None) - -globals_to_check = { - '__name__': __name__, - '__file__': __file__, - '__doc__': __doc__, - '__builtins__.has_open': hasattr(__builtins__, 'open'), - '__builtins__.dir': dir(__builtins__), - '__loader__ exists': loader is not None, - '__loader__.fullname': fullname, - '__package__': __package__, - 'DATA': DATA, - 'FN_VAL': FN_VAL, - '__main__.DATA': getattr(__main__, "DATA", "nothing"), - 'argv': sys.argv, - 'path': cleaned_sys_path, -} - -print(json.dumps(globals_to_check, indent=4, sort_keys=True)) diff --git a/tox.ini b/tox.ini index e547e69c..32dbe3fb 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,8 @@ deps = nose==1.3.7 mock==2.0.0 PyContracts==1.7.9 - unittest-mixins==1.0 + #unittest-mixins==1.0 + -egit+/Users/ned/unittest_mixins#egg=unittest-mixins==0.0 py26: unittest2==1.1.0 py{27,33,34,35,36}: gevent==1.1.1 py{26,27,33,34,35,36}: eventlet==0.19.0 -- cgit v1.2.1