|
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