Skip to content

Commit 7a83ab0

Browse files
committed
test: don't try to make pth files when invoked from pth #2011
When we're invoked by a .pth file, site.py hasn't fully run, so we try to make a .pth file in the system Python instead of the virtualenv. System Pythons are often not writable. Also try to create this kind of not-writable arrangement in CI to find problems like this in the future.
1 parent 6d8b091 commit 7a83ab0

File tree

3 files changed

+16
-5
lines changed

3 files changed

+16
-5
lines changed

.github/workflows/testsuite.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ jobs:
132132
# For extreme debugging:
133133
# python -c "import urllib.request as r; exec(r.urlopen('https://bit.ly/pydoctor').read())"
134134
env | sort
135+
# Ideally, the system Python wouldn't have writable sitepackages so
136+
# try to make it not writable. We can't always always change the
137+
# permissions (Ubuntu & Windows yes, Mac no), so be ready for it to fail.
138+
chmod u-w $(python -c "import site; print(site.getsitepackages()[0])") || echo "Couldn't lock down site-packages"
139+
ls -ld $(python -c "import site; print(site.getsitepackages()[0])")
140+
whoami
135141
136142
- name: "Install dependencies"
137143
run: |

coverage/control.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ def __init__( # pylint: disable=too-many-arguments
269269
self._no_warn_slugs: set[str] = set()
270270
self._messages = messages
271271

272+
# If we're invoked from a .pth file, we shouldn't try to make another one.
273+
self._make_pth_file = True
274+
272275
# A record of all the warnings that have been issued.
273276
self._warnings: list[str] = []
274277

@@ -678,7 +681,7 @@ def start(self) -> None:
678681
if self._auto_load:
679682
self.load()
680683

681-
apply_patches(self, self.config)
684+
apply_patches(self, self.config, make_pth_file=self._make_pth_file)
682685

683686
self._collector.start()
684687
self._started = True
@@ -1432,6 +1435,7 @@ def process_startup() -> Coverage | None:
14321435
cov._warn_unimported_source = False
14331436
cov._warn_preimported_source = False
14341437
cov._auto_save = True
1438+
cov._make_pth_file = False
14351439
cov.start()
14361440

14371441
return cov

coverage/patch.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from coverage.config import CoverageConfig
2020

2121

22-
def apply_patches(cov: Coverage, config: CoverageConfig) -> None:
22+
def apply_patches(cov: Coverage, config: CoverageConfig, *, make_pth_file: bool=True) -> None:
2323
"""Apply invasive patches requested by `[run] patch=`."""
2424

2525
for patch in sorted(set(config.patch)):
@@ -78,9 +78,10 @@ def coverage_execv_patch(*args: Any, **kwargs: Any) -> Any:
7878
os.execve = make_execv_patch("execve", os.execve)
7979

8080
elif patch == "subprocess":
81-
pth_file = create_pth_file()
82-
assert pth_file is not None
83-
atexit.register(pth_file.unlink, missing_ok=True)
81+
if make_pth_file:
82+
pth_file = create_pth_file()
83+
assert pth_file is not None
84+
atexit.register(pth_file.unlink, missing_ok=True)
8485
assert config.config_file is not None
8586
os.environ["COVERAGE_PROCESS_START"] = config.config_file
8687

0 commit comments

Comments
 (0)