Skip to content

Commit 9880f81

Browse files
authored
Directory with an empty pyproject.toml files is built into an sdist+wheel by setuptools 64
Fixes pypa#3511
1 parent a135954 commit 9880f81

File tree

5 files changed

+87
-80
lines changed

5 files changed

+87
-80
lines changed

_distutils_hack/__init__.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,39 @@ def remove_shim():
199199
except ValueError:
200200
pass
201201

202+
203+
def extract_constant(code, symbol, default=-1):
204+
"""Extract the constant value of 'symbol' from 'code'
205+
206+
If the name 'symbol' is bound to a constant value by the Python code
207+
object 'code', return that value. If 'symbol' is bound to an expression,
208+
return 'default'. Otherwise, return 'None'.
209+
210+
Return value is based on the first assignment to 'symbol'. 'symbol' must
211+
be a global, or at least a non-"fast" local in the code block. That is,
212+
only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol'
213+
must be present in 'code.co_names'.
214+
"""
215+
if symbol not in code.co_names:
216+
# name's not there, can't possibly be an assignment
217+
return None
218+
219+
name_idx = list(code.co_names).index(symbol)
220+
221+
STORE_NAME = 90
222+
STORE_GLOBAL = 97
223+
LOAD_CONST = 100
224+
225+
const = default
226+
227+
for byte_code in dis.Bytecode(code):
228+
op = byte_code.opcode
229+
arg = byte_code.arg
230+
231+
if op == LOAD_CONST:
232+
const = code.co_consts[arg]
233+
elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL):
234+
return const
235+
else:
236+
const = default
237+

setuptools/depends.py

Lines changed: 4 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import sys
2-
import marshal
32
import contextlib
4-
import dis
53

6-
from setuptools.extern.packaging import version # type: ignore
4+
from setuptools.extern.packaging import version
5+
from setuptools.get_module_constant import get_module_constant # type: ignore
76

8-
from ._imp import find_module, PY_COMPIED, PY_FROZEN, PY_SOURCE
9-
from . import _imp
7+
from ._imp import find_module, PY_COMPIED
108

119

1210
__all__ = [
13-
'Require', 'find_module', 'get_module_constant', 'extract_constant'
11+
'Require', 'find_module', , 'extract_constant'
1412
]
1513

1614

@@ -93,71 +91,6 @@ def empty():
9391
return contextlib.closing(f)
9492

9593

96-
def get_module_constant(module, symbol, default=-1, paths=None):
97-
"""Find 'module' by searching 'paths', and extract 'symbol'
98-
99-
Return 'None' if 'module' does not exist on 'paths', or it does not define
100-
'symbol'. If the module defines 'symbol' as a constant, return the
101-
constant. Otherwise, return 'default'."""
102-
103-
try:
104-
f, path, (suffix, mode, kind) = info = find_module(module, paths)
105-
except ImportError:
106-
# Module doesn't exist
107-
return None
108-
109-
with maybe_close(f):
110-
if kind == PY_COMPILED:
111-
f.read(8) # skip magic & date
112-
code = marshal.load(f)
113-
elif kind == PY_FROZEN:
114-
code = _imp.get_frozen_object(module, paths)
115-
elif kind == PY_SOURCE:
116-
code = compile(f.read(), path, 'exec')
117-
else:
118-
# Not something we can parse; we'll have to import it. :(
119-
imported = _imp.get_module(module, paths, info)
120-
return getattr(imported, symbol, None)
121-
122-
return extract_constant(code, symbol, default)
123-
124-
125-
def extract_constant(code, symbol, default=-1):
126-
"""Extract the constant value of 'symbol' from 'code'
127-
128-
If the name 'symbol' is bound to a constant value by the Python code
129-
object 'code', return that value. If 'symbol' is bound to an expression,
130-
return 'default'. Otherwise, return 'None'.
131-
132-
Return value is based on the first assignment to 'symbol'. 'symbol' must
133-
be a global, or at least a non-"fast" local in the code block. That is,
134-
only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol'
135-
must be present in 'code.co_names'.
136-
"""
137-
if symbol not in code.co_names:
138-
# name's not there, can't possibly be an assignment
139-
return None
140-
141-
name_idx = list(code.co_names).index(symbol)
142-
143-
STORE_NAME = 90
144-
STORE_GLOBAL = 97
145-
LOAD_CONST = 100
146-
147-
const = default
148-
149-
for byte_code in dis.Bytecode(code):
150-
op = byte_code.opcode
151-
arg = byte_code.arg
152-
153-
if op == LOAD_CONST:
154-
const = code.co_consts[arg]
155-
elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL):
156-
return const
157-
else:
158-
const = default
159-
160-
16194
def _update_globals():
16295
"""
16396
Patch the globals to remove the objects not available on some platforms.

setuptools/get_module_constant.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from _distutils_hack import extract_constant
2+
from setuptools import _imp
3+
from setuptools._imp import PY_FROZEN, PY_SOURCE, find_module
4+
from setuptools.depends import maybe_close
5+
6+
7+
import marshal
8+
9+
10+
def get_module_constant(module, symbol, default=-1, paths=None):
11+
"""Find 'module' by searching 'paths', and extract 'symbol'
12+
13+
Return 'None' if 'module' does not exist on 'paths', or it does not define
14+
'symbol'. If the module defines 'symbol' as a constant, return the
15+
constant. Otherwise, return 'default'."""
16+
17+
try:
18+
f, path, (suffix, mode, kind) = info = find_module(module, paths)
19+
except ImportError:
20+
# Module doesn't exist
21+
return None
22+
23+
with maybe_close(f):
24+
if kind == PY_COMPILED:
25+
f.read(8) # skip magic & date
26+
code = marshal.load(f)
27+
elif kind == PY_FROZEN:
28+
code = _imp.get_frozen_object(module, paths)
29+
elif kind == PY_SOURCE:
30+
code = compile(f.read(), path, 'exec')
31+
else:
32+
# Not something we can parse; we'll have to import it. :(
33+
imported = _imp.get_module(module, paths, info)
34+
return getattr(imported, symbol, None)
35+
36+
return extract_constant(code, symbol, default)

setuptools/tests/test_depends.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import sys
22

3-
from setuptools import depends
3+
from setuptools import get_module_constant
44

55

66
class TestGetModuleConstant:
@@ -11,6 +11,6 @@ def test_basic(self):
1111
the test package.
1212
"""
1313
mod_name = 'setuptools.tests.mod_with_constant'
14-
val = depends.get_module_constant(mod_name, 'value')
14+
val = get_module_constant.get_module_constant(mod_name, 'value')
1515
assert val == 'three, sir!'
1616
assert 'setuptools.tests.mod_with_constant' not in sys.modules

setuptools/tests/test_setuptools.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from distutils.core import Extension
1010
from zipfile import ZipFile
1111

12+
import _distutils_hack
1213
import pytest
1314

1415
from setuptools.extern.packaging import version
@@ -17,6 +18,7 @@
1718
import setuptools.dist
1819
import setuptools.depends as dep
1920
from setuptools.depends import Require
21+
import setuptools.get_module_constant
2022

2123

2224
@pytest.fixture(autouse=True)
@@ -58,16 +60,16 @@ def f1():
5860
fc = f1.__code__
5961

6062
# unrecognized name
61-
assert dep.extract_constant(fc, 'q', -1) is None
63+
assert _distutils_hack.extract_constant(fc, 'q', -1) is None
6264

6365
# constant assigned
64-
dep.extract_constant(fc, 'x', -1) == "test"
66+
_distutils_hack.extract_constant(fc, 'x', -1) == "test"
6567

6668
# expression assigned
67-
dep.extract_constant(fc, 'y', -1) == -1
69+
_distutils_hack.extract_constant(fc, 'y', -1) == -1
6870

6971
# recognized name, not assigned
70-
dep.extract_constant(fc, 'z', -1) is None
72+
_distutils_hack.extract_constant(fc, 'z', -1) is None
7173

7274
def testFindModule(self):
7375
with pytest.raises(ImportError):
@@ -80,9 +82,9 @@ def testFindModule(self):
8082
@needs_bytecode
8183
def testModuleExtract(self):
8284
from json import __version__
83-
assert dep.get_module_constant('json', '__version__') == __version__
84-
assert dep.get_module_constant('sys', 'version') == sys.version
85-
assert dep.get_module_constant(
85+
assert setuptools.get_module_constant.get_module_constant('json', '__version__') == __version__
86+
assert setuptools.get_module_constant.get_module_constant('sys', 'version') == sys.version
87+
assert setuptools.get_module_constant.get_module_constant(
8688
'setuptools.tests.test_setuptools', '__doc__') == __doc__
8789

8890
@needs_bytecode

0 commit comments

Comments
 (0)