|
3 | 3 | import pytest
|
4 | 4 |
|
5 | 5 | from distutils.errors import DistutilsOptionError
|
6 |
| -from setuptools.command.sdist import sdist |
7 | 6 | from setuptools.config import expand
|
8 | 7 | from setuptools.discovery import find_package_path
|
9 | 8 |
|
@@ -56,34 +55,66 @@ def test_read_files(tmp_path, monkeypatch):
|
56 | 55 | expand.read_files(["../a.txt"], tmp_path)
|
57 | 56 |
|
58 | 57 |
|
59 |
| -def test_read_attr(tmp_path, monkeypatch): |
60 |
| - files = { |
61 |
| - "pkg/__init__.py": "", |
62 |
| - "pkg/sub/__init__.py": "VERSION = '0.1.1'", |
63 |
| - "pkg/sub/mod.py": ( |
64 |
| - "VALUES = {'a': 0, 'b': {42}, 'c': (0, 1, 1)}\n" |
65 |
| - "raise SystemExit(1)" |
66 |
| - ), |
67 |
| - } |
68 |
| - write_files(files, tmp_path) |
69 |
| - |
70 |
| - with monkeypatch.context() as m: |
71 |
| - m.chdir(tmp_path) |
72 |
| - # Make sure it can read the attr statically without evaluating the module |
73 |
| - assert expand.read_attr('pkg.sub.VERSION') == '0.1.1' |
74 |
| - values = expand.read_attr('lib.mod.VALUES', {'lib': 'pkg/sub'}) |
75 |
| - |
76 |
| - assert values['a'] == 0 |
77 |
| - assert values['b'] == {42} |
78 |
| - |
79 |
| - # Make sure the same APIs work outside cwd |
80 |
| - assert expand.read_attr('pkg.sub.VERSION', root_dir=tmp_path) == '0.1.1' |
81 |
| - values = expand.read_attr('lib.mod.VALUES', {'lib': 'pkg/sub'}, tmp_path) |
82 |
| - assert values['c'] == (0, 1, 1) |
| 58 | +class TestReadAttr: |
| 59 | + def test_read_attr(self, tmp_path, monkeypatch): |
| 60 | + files = { |
| 61 | + "pkg/__init__.py": "", |
| 62 | + "pkg/sub/__init__.py": "VERSION = '0.1.1'", |
| 63 | + "pkg/sub/mod.py": ( |
| 64 | + "VALUES = {'a': 0, 'b': {42}, 'c': (0, 1, 1)}\n" |
| 65 | + "raise SystemExit(1)" |
| 66 | + ), |
| 67 | + } |
| 68 | + write_files(files, tmp_path) |
| 69 | + |
| 70 | + with monkeypatch.context() as m: |
| 71 | + m.chdir(tmp_path) |
| 72 | + # Make sure it can read the attr statically without evaluating the module |
| 73 | + assert expand.read_attr('pkg.sub.VERSION') == '0.1.1' |
| 74 | + values = expand.read_attr('lib.mod.VALUES', {'lib': 'pkg/sub'}) |
| 75 | + |
| 76 | + assert values['a'] == 0 |
| 77 | + assert values['b'] == {42} |
| 78 | + |
| 79 | + # Make sure the same APIs work outside cwd |
| 80 | + assert expand.read_attr('pkg.sub.VERSION', root_dir=tmp_path) == '0.1.1' |
| 81 | + values = expand.read_attr('lib.mod.VALUES', {'lib': 'pkg/sub'}, tmp_path) |
| 82 | + assert values['c'] == (0, 1, 1) |
| 83 | + |
| 84 | + def test_import_order(self, tmp_path): |
| 85 | + """ |
| 86 | + Sometimes the import machinery will import the parent package of a nested |
| 87 | + module, which triggers side-effects and might create problems (see issue #3176) |
| 88 | +
|
| 89 | + ``read_attr`` should bypass these limitations by resolving modules statically |
| 90 | + (via ast.literal_eval). |
| 91 | + """ |
| 92 | + files = { |
| 93 | + "src/pkg/__init__.py": "from .main import func\nfrom .about import version", |
| 94 | + "src/pkg/main.py": "import super_complicated_dep\ndef func(): return 42", |
| 95 | + "src/pkg/about.py": "version = '42'", |
| 96 | + } |
| 97 | + write_files(files, tmp_path) |
| 98 | + attr_desc = "pkg.about.version" |
| 99 | + package_dir = {"": "src"} |
| 100 | + # `import super_complicated_dep` should not run, otherwise the build fails |
| 101 | + assert expand.read_attr(attr_desc, package_dir, tmp_path) == "42" |
83 | 102 |
|
84 | 103 |
|
85 |
| -def test_resolve_class(): |
86 |
| - assert expand.resolve_class("setuptools.command.sdist.sdist") == sdist |
| 104 | +@pytest.mark.parametrize( |
| 105 | + 'package_dir, file, module, return_value', |
| 106 | + [ |
| 107 | + ({"": "src"}, "src/pkg/main.py", "pkg.main", 42), |
| 108 | + ({"pkg": "lib"}, "lib/main.py", "pkg.main", 13), |
| 109 | + ({}, "single_module.py", "single_module", 70), |
| 110 | + ({}, "flat_layout/pkg.py", "flat_layout.pkg", 836), |
| 111 | + ] |
| 112 | +) |
| 113 | +def test_resolve_class(tmp_path, package_dir, file, module, return_value): |
| 114 | + files = {file: f"class Custom:\n def testing(self): return {return_value}"} |
| 115 | + write_files(files, tmp_path) |
| 116 | + cls = expand.resolve_class(f"{module}.Custom", package_dir, tmp_path) |
| 117 | + assert cls().testing() == return_value |
87 | 118 |
|
88 | 119 |
|
89 | 120 | @pytest.mark.parametrize(
|
|
0 commit comments