Skip to content

Commit 54720c1

Browse files
Merge pull request #1030 from jeremy-hiatt/dont-rewrite-path-hooks
Avoid modifying path placeholders created by editable installs
2 parents f57c658 + 79fb6ff commit 54720c1

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

changelog/1028.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix compatiblity issue between `looponfail` and editable installs.

src/xdist/looponfail.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ def init_worker_session(channel, args, option_dict):
160160
newpaths = []
161161
for p in sys.path:
162162
if p:
163-
if not os.path.isabs(p):
163+
# Ignore path placeholders created for editable installs
164+
if not os.path.isabs(p) and not p.endswith(".__path_hook__"):
164165
p = os.path.abspath(p)
165166
newpaths.append(p)
166167
sys.path[:] = newpaths

testing/test_looponfail.py

+39
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pathlib
2+
import tempfile
13
import unittest.mock
24
from typing import List
35

@@ -191,6 +193,43 @@ def test_func():
191193
control.loop_once()
192194
assert control.failures
193195

196+
def test_ignore_sys_path_hook_entry(
197+
self, pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch
198+
) -> None:
199+
# Modifying sys.path as seen by the worker process is a bit tricky,
200+
# because any changes made in the current process do not carry over.
201+
# However, we can leverage the `sitecustomize` behavior to run arbitrary
202+
# code when the subprocess interpreter is starting up. We just need to
203+
# install our module in the search path, which we can accomplish by
204+
# adding a temporary directory to PYTHONPATH.
205+
tmpdir = tempfile.TemporaryDirectory()
206+
with open(pathlib.Path(tmpdir.name) / "sitecustomize.py", "w") as custom:
207+
print(
208+
textwrap.dedent(
209+
"""
210+
import sys
211+
sys.path.append('dummy.__path_hook__')
212+
"""
213+
),
214+
file=custom,
215+
)
216+
217+
monkeypatch.setenv("PYTHONPATH", tmpdir.name, prepend=":")
218+
219+
item = pytester.getitem(
220+
textwrap.dedent(
221+
"""
222+
def test_func():
223+
import sys
224+
assert "dummy.__path_hook__" in sys.path
225+
"""
226+
)
227+
)
228+
control = RemoteControl(item.config)
229+
control.setup()
230+
topdir, failures = control.runsession()[:2]
231+
assert not failures
232+
194233

195234
class TestLooponFailing:
196235
def test_looponfail_from_fail_to_ok(self, pytester: pytest.Pytester) -> None:

0 commit comments

Comments
 (0)