Skip to content

Commit 3fd5727

Browse files
committed
fix: install .pth files the right way #2100
1 parent 833b436 commit 3fd5727

File tree

6 files changed

+36
-17
lines changed

6 files changed

+36
-17
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ doc/sample_html_beta
4949

5050
# Build intermediaries.
5151
tmp
52-
zzz_coverage.pth
52+
a1_coverage.pth
5353

5454
# OS junk
5555
.DS_Store

CHANGES.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,16 @@ upgrading your version of coverage.py.
2323
Unreleased
2424
----------
2525

26+
- The .pth file we install was done incorrectly and didn't work when using
27+
the source wheel (`py3-none-any`). This is now fixed. Thanks, `Henry
28+
Schreiner <pull 2100_>`_.
29+
2630
- Deprecated: when coverage.py is installed, it creates three command entry
2731
points: `coverage`, `coverage3`, and `coverage-3.10` (if installed for Python
2832
3.10). The second and third of these are not needed and will eventually be
2933
removed.
3034

35+
.. _pull 2100: https://github.com/coveragepy/coveragepy/pull/2100
3136

3237
.. start-releases
3338

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ clean: debug_clean _clean_platform ## Remove artifacts of test execution, instal
3737
@rm -f MANIFEST
3838
@rm -f .coverage .coverage.* .metacov*
3939
@rm -f coverage.xml coverage.json
40-
@rm -f .tox/*/lib/*/site-packages/zzz_metacov.pth
40+
@rm -f .tox/*/lib/*/site-packages/a0_metacov.pth
4141
@rm -f */.coverage */*/.coverage */*/*/.coverage */*/*/*/.coverage */*/*/*/*/.coverage */*/*/*/*/*/.coverage
4242
@rm -f tests/covmain.zip tests/zipmods.zip tests/zip1.zip
4343
@rm -rf doc/_build doc/_spell doc/sample_html_beta
4444
@rm -rf tmp
45-
@rm -rf zzz_coverage.pth
45+
@rm -rf a1_coverage.pth
4646
@rm -rf .*cache */.*cache */*/.*cache */*/*/.*cache .hypothesis
4747
@rm -rf tests/actual
4848
@-make -C tests/gold/html clean

igor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def run_tests_with_coverage(core, *runner_args):
182182
# or the sys.path entries aren't created right?
183183
# There's an entry in "make clean" to get rid of this file.
184184
pth_dir = sysconfig.get_path("purelib")
185-
pth_path = os.path.join(pth_dir, "zzy_metacov.pth")
185+
pth_path = os.path.join(pth_dir, "a0_metacov.pth")
186186
with open(pth_path, "w", encoding="utf-8") as pth_file:
187187
pth_file.write("import coverage; coverage.process_startup(slug='meta')\n")
188188

setup.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@
1010
import os
1111
import os.path
1212
import platform
13-
import site
1413
import sys
1514
import textwrap
15+
import zipfile
1616

17+
from pathlib import Path
1718
from typing import Any
1819

1920
from setuptools import Extension, errors, setup
20-
from setuptools.command.build_ext import build_ext # pylint: disable=wrong-import-order
21+
from setuptools.command.build_ext import build_ext
22+
from setuptools.command.editable_wheel import editable_wheel
2123

2224

2325
def get_version_data() -> dict[str, Any]:
@@ -89,6 +91,14 @@ def get_classifiers(version_info: tuple[int, int, int, str, int]) -> list[str]:
8991
return classifier_list
9092

9193

94+
# The names of .pth files matter because they are read in lexicographic order.
95+
# Editable installs work because of `__editable__*.pth` files, so we need our
96+
# .pth files to come after those. But we want ours to be earlyish in the
97+
# sequence, so we start with `a`. The metacov .pth file should come before the
98+
# coverage .pth file, so we use `a0_metacov.pth` and `a1_coverage.pth`.
99+
PTH_NAME = "a1_coverage.pth"
100+
101+
92102
def make_pth_file() -> None:
93103
"""Make the packaged .pth file used for measuring subprocess coverage."""
94104

@@ -100,10 +110,20 @@ def make_pth_file() -> None:
100110

101111
# `import sys` is needed because .pth files are executed only if they start
102112
# with `import `.
103-
with open("zzz_coverage.pth", "w", encoding="utf-8") as pth_file:
113+
with open(PTH_NAME, "w", encoding="utf-8") as pth_file:
104114
pth_file.write(f"import sys; exec({code!r})\n")
105115

106116

117+
class EditableWheelWithPth(editable_wheel): # type: ignore[misc]
118+
"""Override the editable_wheel command to insert our .pth file into the wheel."""
119+
120+
def run(self) -> None:
121+
super().run()
122+
for whl in Path(self.dist_dir).glob("*editable*.whl"):
123+
with zipfile.ZipFile(whl, "a") as zf:
124+
zf.write(PTH_NAME, PTH_NAME)
125+
126+
107127
# A replacement for the build_ext command which raises a single exception
108128
# if the build fails, so we can fallback nicely.
109129

@@ -158,6 +178,7 @@ def build_extension(self, ext: Any) -> None:
158178
version_data = get_version_data()
159179
make_pth_file()
160180

181+
161182
# Create the keyword arguments for setup()
162183

163184
setup_args = dict(
@@ -170,17 +191,9 @@ def build_extension(self, ext: Any) -> None:
170191
"coverage": [
171192
"htmlfiles/*.*",
172193
"py.typed",
194+
f"../{PTH_NAME}",
173195
],
174196
},
175-
data_files=[
176-
# Write the .pth file into all site-packages directories. Different
177-
# platforms read different directories for .pth files, so put it
178-
# everywhere. The process_startup function called in the .pth file
179-
# does nothing the second time it's called, so it's fine to have
180-
# multiple .pth files.
181-
(os.path.relpath(sp, sys.prefix), ["zzz_coverage.pth"])
182-
for sp in site.getsitepackages()
183-
],
184197
entry_points={
185198
"console_scripts": [
186199
# Install a script as "coverage".
@@ -196,6 +209,7 @@ def build_extension(self, ext: Any) -> None:
196209
},
197210
cmdclass={
198211
"build_ext": ve_build_ext,
212+
"editable_wheel": EditableWheelWithPth,
199213
},
200214
# We need to get HTML assets from our htmlfiles directory.
201215
zip_safe=False,

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ commands =
108108
python -m cogapp -cP --check --check-fail-msg='run `make workflows`' --verbosity=1 .github/workflows/*.yml
109109
ruff format --check
110110
python -m pylint -j 0 --notes= --ignore-paths 'doc/_build/.*' {env:LINTABLE}
111-
check-manifest --ignore "doc/sample_html/*,zzz_coverage.pth"
111+
check-manifest --ignore "doc/sample_html/*,a1_coverage.pth"
112112
# If 'build -q' becomes a thing (https://github.com/pypa/build/issues/188),
113113
# this can be simplified:
114114
python igor.py quietly "python -m build"

0 commit comments

Comments
 (0)