7
7
from importlib import import_module
8
8
from pathlib import Path
9
9
from textwrap import dedent
10
+ from uuid import uuid4
10
11
11
12
import jaraco .envs
12
13
import jaraco .path
19
20
from setuptools ._importlib import resources as importlib_resources
20
21
from setuptools .command .editable_wheel import (
21
22
_LinkTree ,
22
- _find_mapped_namespaces ,
23
+ _find_virtual_namespaces ,
24
+ _find_namespaces ,
23
25
_find_package_roots ,
24
26
_finder_template ,
25
27
)
@@ -129,7 +131,7 @@ def test_editable_with_pyproject(tmp_path, venv, files, editable_mode):
129
131
assert subprocess .check_output (cmd ).strip () == b"3.14159.post0 foobar 42"
130
132
131
133
132
- def test_editable_with_flat_layout (tmp_path , venv , monkeypatch , editable_mode ):
134
+ def test_editable_with_flat_layout (tmp_path , venv , editable_mode ):
133
135
files = {
134
136
"mypkg" : {
135
137
"pyproject.toml" : dedent ("""\
@@ -163,9 +165,7 @@ def test_editable_with_flat_layout(tmp_path, venv, monkeypatch, editable_mode):
163
165
class TestLegacyNamespaces :
164
166
"""Ported from test_develop"""
165
167
166
- def test_namespace_package_importable (
167
- self , venv , tmp_path , monkeypatch , editable_mode
168
- ):
168
+ def test_namespace_package_importable (self , venv , tmp_path , editable_mode ):
169
169
"""
170
170
Installing two packages sharing the same namespace, one installed
171
171
naturally using pip or `--single-version-externally-managed`
@@ -184,9 +184,7 @@ def test_namespace_package_importable(
184
184
185
185
186
186
class TestPep420Namespaces :
187
- def test_namespace_package_importable (
188
- self , venv , tmp_path , monkeypatch , editable_mode
189
- ):
187
+ def test_namespace_package_importable (self , venv , tmp_path , editable_mode ):
190
188
"""
191
189
Installing two packages sharing the same namespace, one installed
192
190
normally using pip and the other installed in editable mode
@@ -200,9 +198,7 @@ def test_namespace_package_importable(
200
198
venv .run (["python" , "-m" , "pip" , "install" , "-e" , str (pkg_B ), * opts ])
201
199
venv .run (["python" , "-c" , "import myns.n.pkgA; import myns.n.pkgB" ])
202
200
203
- def test_namespace_created_via_package_dir (
204
- self , venv , tmp_path , monkeypatch , editable_mode
205
- ):
201
+ def test_namespace_created_via_package_dir (self , venv , tmp_path , editable_mode ):
206
202
"""Currently users can create a namespace by tweaking `package_dir`"""
207
203
files = {
208
204
"pkgA" : {
@@ -305,7 +301,7 @@ def test_packages(self, tmp_path):
305
301
"pkg1" : str (tmp_path / "src1/pkg1" ),
306
302
"mod2" : str (tmp_path / "src2/mod2" )
307
303
}
308
- template = _finder_template (mapping , {})
304
+ template = _finder_template (str ( uuid4 ()), mapping , {})
309
305
310
306
with contexts .save_paths (), contexts .save_sys_modules ():
311
307
for mod in ("pkg1" , "pkg1.subpkg" , "pkg1.subpkg.mod1" , "mod2" ):
@@ -326,9 +322,9 @@ def test_namespace(self, tmp_path):
326
322
jaraco .path .build (files , prefix = tmp_path )
327
323
328
324
mapping = {"ns.othername" : str (tmp_path / "pkg" )}
329
- namespaces = {"ns" }
325
+ namespaces = {"ns" : [] }
330
326
331
- template = _finder_template (mapping , namespaces )
327
+ template = _finder_template (str ( uuid4 ()), mapping , namespaces )
332
328
with contexts .save_paths (), contexts .save_sys_modules ():
333
329
for mod in ("ns" , "ns.othername" ):
334
330
sys .modules .pop (mod , None )
@@ -344,7 +340,7 @@ def test_namespace(self, tmp_path):
344
340
# Make sure resources can also be found
345
341
assert text .read_text (encoding = "utf-8" ) == "abc"
346
342
347
- def test_combine_namespaces (self , tmp_path , monkeypatch ):
343
+ def test_combine_namespaces (self , tmp_path ):
348
344
files = {
349
345
"src1" : {"ns" : {"pkg1" : {"__init__.py" : "a = 13" }}},
350
346
"src2" : {"ns" : {"mod2.py" : "b = 37" }},
@@ -355,7 +351,8 @@ def test_combine_namespaces(self, tmp_path, monkeypatch):
355
351
"ns.pkgA" : str (tmp_path / "src1/ns/pkg1" ),
356
352
"ns" : str (tmp_path / "src2/ns" ),
357
353
}
358
- template = _finder_template (mapping , {})
354
+ namespaces_ = {"ns" : [str (tmp_path / "src1" ), str (tmp_path / "src2" )]}
355
+ template = _finder_template (str (uuid4 ()), mapping , namespaces_ )
359
356
360
357
with contexts .save_paths (), contexts .save_sys_modules ():
361
358
for mod in ("ns" , "ns.pkgA" , "ns.mod2" ):
@@ -370,6 +367,42 @@ def test_combine_namespaces(self, tmp_path, monkeypatch):
370
367
assert pkgA .a == 13
371
368
assert mod2 .b == 37
372
369
370
+ def test_dynamic_path_computation (self , tmp_path ):
371
+ # Follows the example in PEP 420
372
+ files = {
373
+ "project1" : {"parent" : {"child" : {"one.py" : "x = 1" }}},
374
+ "project2" : {"parent" : {"child" : {"two.py" : "x = 2" }}},
375
+ "project3" : {"parent" : {"child" : {"three.py" : "x = 3" }}},
376
+ }
377
+ jaraco .path .build (files , prefix = tmp_path )
378
+ mapping = {}
379
+ namespaces_ = {"parent" : [str (tmp_path / "project1/parent" )]}
380
+ template = _finder_template (str (uuid4 ()), mapping , namespaces_ )
381
+
382
+ mods = (f"parent.child.{ name } " for name in ("one" , "two" , "three" ))
383
+ with contexts .save_paths (), contexts .save_sys_modules ():
384
+ for mod in ("parent" , "parent.child" , "parent.child" , * mods ):
385
+ sys .modules .pop (mod , None )
386
+
387
+ self .install_finder (template )
388
+
389
+ one = import_module ("parent.child.one" )
390
+ assert one .x == 1
391
+
392
+ with pytest .raises (ImportError ):
393
+ import_module ("parent.child.two" )
394
+
395
+ sys .path .append (str (tmp_path / "project2" ))
396
+ two = import_module ("parent.child.two" )
397
+ assert two .x == 2
398
+
399
+ with pytest .raises (ImportError ):
400
+ import_module ("parent.child.three" )
401
+
402
+ sys .path .append (str (tmp_path / "project3" ))
403
+ three = import_module ("parent.child.three" )
404
+ assert three .x == 3
405
+
373
406
374
407
def test_pkg_roots (tmp_path ):
375
408
"""This test focus in getting a particular implementation detail right.
@@ -381,22 +414,43 @@ def test_pkg_roots(tmp_path):
381
414
"d" : {"__init__.py" : "d = 1" , "e" : {"__init__.py" : "de = 1" }},
382
415
"f" : {"g" : {"h" : {"__init__.py" : "fgh = 1" }}},
383
416
"other" : {"__init__.py" : "abc = 1" },
384
- "another" : {"__init__.py" : "abcxy = 1" },
417
+ "another" : {"__init__.py" : "abcxyz = 1" },
418
+ "yet_another" : {"__init__.py" : "mnopq = 1" },
385
419
}
386
420
jaraco .path .build (files , prefix = tmp_path )
387
- package_dir = {"a.b.c" : "other" , "a.b.c.x.y" : "another" }
388
- packages = ["a" , "a.b" , "a.b.c" , "a.b.c.x.y" , "d" , "d.e" , "f" , "f.g" , "f.g.h" ]
421
+ package_dir = {
422
+ "a.b.c" : "other" ,
423
+ "a.b.c.x.y.z" : "another" ,
424
+ "m.n.o.p.q" : "yet_another"
425
+ }
426
+ packages = [
427
+ "a" ,
428
+ "a.b" ,
429
+ "a.b.c" ,
430
+ "a.b.c.x.y" ,
431
+ "a.b.c.x.y.z" ,
432
+ "d" ,
433
+ "d.e" ,
434
+ "f" ,
435
+ "f.g" ,
436
+ "f.g.h" ,
437
+ "m.n.o.p.q" ,
438
+ ]
389
439
roots = _find_package_roots (packages , package_dir , tmp_path )
390
440
assert roots == {
391
441
"a" : str (tmp_path / "a" ),
392
442
"a.b.c" : str (tmp_path / "other" ),
393
- "a.b.c.x.y" : str (tmp_path / "another" ),
443
+ "a.b.c.x.y.z " : str (tmp_path / "another" ),
394
444
"d" : str (tmp_path / "d" ),
395
445
"f" : str (tmp_path / "f" ),
446
+ "m.n.o.p.q" : str (tmp_path / "yet_another" ),
396
447
}
397
448
398
- namespaces = set (_find_mapped_namespaces (roots ))
399
- assert namespaces == {"a.b.c.x" }
449
+ ns = set (dict (_find_namespaces (packages , roots )))
450
+ assert ns == {"f" , "f.g" }
451
+
452
+ ns = set (_find_virtual_namespaces (roots ))
453
+ assert ns == {"a.b.c.x" , "a.b.c.x.y" , "m" , "m.n" , "m.n.o" , "m.n.o.p" }
400
454
401
455
402
456
class TestOverallBehaviour :
0 commit comments