Skip to content

Commit 70d527b

Browse files
committed
Refine the conditions for tweaking sys.path[0]. Fixes #862
1 parent 1c653dd commit 70d527b

File tree

3 files changed

+28
-9
lines changed

3 files changed

+28
-9
lines changed

CHANGES.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ Unreleased
2828
directory before combining data, causing "Couldn't use data file: no such
2929
table: meta" errors (`issue 916`_). This is now fixed.
3030

31+
- Coverage could fail to run your program with some form of "ModuleNotFound" or
32+
"ImportError" trying to import from the current directory. This would happen
33+
if coverage had been packaged into a zip file (for example, on Windows), or
34+
was found indirectly (for example, by pyenv-virtualenv). A number of
35+
different scenarios were described in `issue 862`_ which is now fixed. Huge
36+
thanks to Agbonze O. Jeremiah for reporting it, and Alexander Waters and
37+
George-Cristian Bîrzan for protracted debugging sessions.
38+
39+
.. _issue 862: https://github.com/nedbat/coveragepy/issues/862
3140
.. _issue 916: https://github.com/nedbat/coveragepy/issues/916
3241

3342

CONTRIBUTORS.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Other contributions, including writing code, updating docs, and submitting
55
useful bug reports, have been made by:
66

77
Adi Roiban
8+
Agbonze O. Jeremiah
89
Albertas Agejevas
910
Aleksi Torhamo
1011
Alex Gaynor

coverage/execfile.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from coverage import env
1414
from coverage.backward import BUILTINS
1515
from coverage.backward import PYC_MAGIC_NUMBER, imp, importlib_util_find_spec
16-
from coverage.files import python_reported_file
16+
from coverage.files import canonical_filename, python_reported_file
1717
from coverage.misc import CoverageException, ExceptionDuringRun, NoCode, NoSource, isolate_module
1818
from coverage.phystokens import compile_unicode
1919
from coverage.python import get_python_source
@@ -120,32 +120,41 @@ def prepare(self):
120120
121121
This needs to happen before any importing, and without importing anything.
122122
"""
123-
should_update_sys_path = True
124123
if self.as_module:
125124
if env.PYBEHAVIOR.actual_syspath0_dash_m:
126125
path0 = os.getcwd()
127126
else:
128127
path0 = ""
129-
sys.path[0] = path0
130-
should_update_sys_path = False
131128
elif os.path.isdir(self.arg0):
132129
# Running a directory means running the __main__.py file in that
133130
# directory.
134131
path0 = self.arg0
135132
else:
136133
path0 = os.path.abspath(os.path.dirname(self.arg0))
137134

138-
139-
if should_update_sys_path:
135+
if os.path.isdir(sys.path[0]):
140136
# sys.path fakery. If we are being run as a command, then sys.path[0]
141137
# is the directory of the "coverage" script. If this is so, replace
142138
# sys.path[0] with the directory of the file we're running, or the
143139
# current directory when running modules. If it isn't so, then we
144140
# don't know what's going on, and just leave it alone.
145141
top_file = inspect.stack()[-1][0].f_code.co_filename
146-
if os.path.abspath(sys.path[0]) == os.path.abspath(os.path.dirname(top_file)):
147-
# Set sys.path correctly.
148-
sys.path[0] = python_reported_file(path0)
142+
sys_path_0_abs = os.path.abspath(sys.path[0])
143+
top_file_dir_abs = os.path.abspath(os.path.dirname(top_file))
144+
sys_path_0_abs = canonical_filename(sys_path_0_abs)
145+
top_file_dir_abs = canonical_filename(top_file_dir_abs)
146+
if sys_path_0_abs != top_file_dir_abs:
147+
path0 = None
148+
149+
else:
150+
# sys.path[0] is a file. Is the next entry the directory containing
151+
# that file?
152+
if sys.path[1] == os.path.dirname(sys.path[0]):
153+
# Can it be right to always remove that?
154+
del sys.path[1]
155+
156+
if path0 is not None:
157+
sys.path[0] = python_reported_file(path0)
149158

150159
def _prepare2(self):
151160
"""Do more preparation to run Python code.

0 commit comments

Comments
 (0)