Skip to content

Commit fd44868

Browse files
authored
Merge branch 'main' into type-check-3.12
2 parents 8528a60 + 8bd9308 commit fd44868

File tree

12 files changed

+108
-38
lines changed

12 files changed

+108
-38
lines changed

newsfragments/4420.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raises an exception when ``py_limited_api`` is used in a build with
2+
``Py_GIL_DISABLED``. This is currently not supported (python/cpython#111506).

newsfragments/4559.misc.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Prevent deprecation warning from ``pypa/wheel#631`` to accidentally
2+
trigger when validating ``pyproject.toml``.

newsfragments/4565.misc.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Replace ``pip install -I`` with ``pip install --force-reinstall`` in
2+
integration tests. Additionally, remove ``wheel`` from virtual environment as
3+
it is no longer a build dependency.

setuptools/command/bdist_wheel.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,7 @@ def finalize_options(self) -> None:
274274
self.distribution.has_ext_modules() or self.distribution.has_c_libraries()
275275
)
276276

277-
if self.py_limited_api and not re.match(
278-
PY_LIMITED_API_PATTERN, self.py_limited_api
279-
):
280-
raise ValueError(f"py-limited-api must match '{PY_LIMITED_API_PATTERN}'")
277+
self._validate_py_limited_api()
281278

282279
# Support legacy [wheel] section for setting universal
283280
wheel = self.distribution.get_option_dict("wheel")
@@ -291,6 +288,21 @@ def finalize_options(self) -> None:
291288
if self.build_number is not None and not self.build_number[:1].isdigit():
292289
raise ValueError("Build tag (build-number) must start with a digit.")
293290

291+
def _validate_py_limited_api(self) -> None:
292+
if not self.py_limited_api:
293+
return
294+
295+
if not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api):
296+
raise ValueError(f"py-limited-api must match '{PY_LIMITED_API_PATTERN}'")
297+
298+
if sysconfig.get_config_var("Py_GIL_DISABLED"):
299+
raise ValueError(
300+
f"`py_limited_api={self.py_limited_api!r}` not supported. "
301+
"`Py_LIMITED_API` is currently incompatible with "
302+
f"`Py_GIL_DISABLED` ({sys.abiflags=!r}). "
303+
"See https://github.com/python/cpython/issues/111506."
304+
)
305+
294306
@property
295307
def wheel_dist_name(self) -> str:
296308
"""Return distribution full name with - replaced with _"""

setuptools/config/_apply_pyprojecttoml.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,11 @@ def _valid_command_options(cmdclass: Mapping = EMPTY) -> dict[str, set[str]]:
276276

277277

278278
def _load_ep(ep: metadata.EntryPoint) -> tuple[str, type] | None:
279+
if ep.value.startswith("wheel.bdist_wheel"):
280+
# Ignore deprecated entrypoint from wheel and avoid warning pypa/wheel#631
281+
# TODO: remove check when `bdist_wheel` has been fully removed from pypa/wheel
282+
return None
283+
279284
# Ignore all the errors
280285
try:
281286
return (ep.name, ep.load())

setuptools/config/_validate_pyproject/error_reporting.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import typing
77
from contextlib import contextmanager
88
from textwrap import indent, wrap
9-
from typing import Any, Dict, Generator, Iterator, List, Optional, Sequence, Union, cast
9+
from typing import Any, Dict, Generator, Iterator, List, Optional, Sequence, Union
1010

1111
from .fastjsonschema_exceptions import JsonSchemaValueException
1212

@@ -316,9 +316,7 @@ def _label(self, path: Sequence[str]) -> str:
316316
def _value(self, value: Any, path: Sequence[str]) -> str:
317317
if path[-1] == "type" and not self._is_property(path):
318318
type_ = self._jargon(value)
319-
return (
320-
f"[{', '.join(type_)}]" if isinstance(value, list) else cast(str, type_)
321-
)
319+
return f"[{', '.join(type_)}]" if isinstance(type_, list) else type_
322320
return repr(value)
323321

324322
def _inline_attrs(self, schema: dict, path: Sequence[str]) -> Iterator[str]:

setuptools/config/_validate_pyproject/fastjsonschema_validations.py

Lines changed: 24 additions & 24 deletions
Large diffs are not rendered by default.

setuptools/config/_validate_pyproject/formats.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ def pep508_identifier(name: str) -> bool:
8383
from packaging import requirements as _req
8484
except ImportError: # pragma: no cover
8585
# let's try setuptools vendored version
86-
from setuptools._vendor.packaging import requirements as _req # type: ignore
86+
from setuptools._vendor.packaging import ( # type: ignore[no-redef]
87+
requirements as _req,
88+
)
8789

8890
def pep508(value: str) -> bool:
8991
"""See :ref:`PyPA's dependency specifiers <pypa:dependency-specifiers>`
@@ -289,6 +291,25 @@ def python_module_name(value: str) -> bool:
289291
return python_qualified_identifier(value)
290292

291293

294+
def python_module_name_relaxed(value: str) -> bool:
295+
"""Similar to :obj:`python_module_name`, but relaxed to also accept
296+
dash characters (``-``) and cover special cases like ``pip-run``.
297+
298+
It is recommended, however, that beginners avoid dash characters,
299+
as they require advanced knowledge about Python internals.
300+
301+
The following are disallowed:
302+
303+
* names starting/ending in dashes,
304+
* names ending in ``-stubs`` (potentially collide with :obj:`pep561_stub_name`).
305+
"""
306+
if value.startswith("-") or value.endswith("-"):
307+
return False
308+
if value.endswith("-stubs"):
309+
return False # Avoid collision with PEP 561
310+
return python_module_name(value.replace("-", "_"))
311+
312+
292313
def python_entrypoint_group(value: str) -> bool:
293314
"""See ``Data model > group`` in the :ref:`PyPA's entry-points specification
294315
<pypa:entry-points>`.

setuptools/config/setuptools.schema.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,14 @@
148148
},
149149
"namespace-packages": {
150150
"type": "array",
151-
"items": {"type": "string", "format": "python-module-name"},
151+
"items": {"type": "string", "format": "python-module-name-relaxed"},
152152
"$comment": "https://setuptools.pypa.io/en/latest/userguide/package_discovery.html",
153153
"description": "**DEPRECATED**: use implicit namespaces instead (:pep:`420`)."
154154
},
155155
"py-modules": {
156156
"description": "Modules that setuptools will manipulate",
157157
"type": "array",
158-
"items": {"type": "string", "format": "python-module-name"},
158+
"items": {"type": "string", "format": "python-module-name-relaxed"},
159159
"$comment": "TODO: clarify the relationship with ``packages``"
160160
},
161161
"data-files": {
@@ -250,7 +250,7 @@
250250
"description": "Valid package name (importable or :pep:`561`).",
251251
"type": "string",
252252
"anyOf": [
253-
{"type": "string", "format": "python-module-name"},
253+
{"type": "string", "format": "python-module-name-relaxed"},
254254
{"type": "string", "format": "pep561-stub-name"}
255255
]
256256
},

setuptools/tests/config/test_apply_pyprojecttoml.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,33 @@ def test_default_patterns(self, tmp_path):
297297
assert set(dist.metadata.license_files) == {*license_files, "LICENSE.txt"}
298298

299299

300+
class TestPyModules:
301+
# https://github.com/pypa/setuptools/issues/4316
302+
303+
def dist(self, name):
304+
toml_config = f"""
305+
[project]
306+
name = "test"
307+
version = "42.0"
308+
[tool.setuptools]
309+
py-modules = [{name!r}]
310+
"""
311+
pyproject = Path("pyproject.toml")
312+
pyproject.write_text(cleandoc(toml_config), encoding="utf-8")
313+
return pyprojecttoml.apply_configuration(Distribution({}), pyproject)
314+
315+
@pytest.mark.parametrize("module", ["pip-run", "abc-d.λ-xyz-e"])
316+
def test_valid_module_name(self, tmp_path, monkeypatch, module):
317+
monkeypatch.chdir(tmp_path)
318+
assert module in self.dist(module).py_modules
319+
320+
@pytest.mark.parametrize("module", ["pip run", "-pip-run", "pip-run-stubs"])
321+
def test_invalid_module_name(self, tmp_path, monkeypatch, module):
322+
monkeypatch.chdir(tmp_path)
323+
with pytest.raises(ValueError, match="py-modules"):
324+
self.dist(module).py_modules
325+
326+
300327
class TestDeprecatedFields:
301328
def test_namespace_packages(self, tmp_path):
302329
pyproject = tmp_path / "pyproject.toml"

0 commit comments

Comments
 (0)