Skip to content

Commit

Permalink
Merge branch 'main' into Ruff--lint-pytest
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam authored Aug 16, 2024
2 parents 18042fb + 8bd9308 commit 4f98086
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 38 deletions.
2 changes: 2 additions & 0 deletions newsfragments/4420.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Raises an exception when ``py_limited_api`` is used in a build with
``Py_GIL_DISABLED``. This is currently not supported (python/cpython#111506).
2 changes: 2 additions & 0 deletions newsfragments/4559.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Prevent deprecation warning from ``pypa/wheel#631`` to accidentally
trigger when validating ``pyproject.toml``.
3 changes: 3 additions & 0 deletions newsfragments/4565.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Replace ``pip install -I`` with ``pip install --force-reinstall`` in
integration tests. Additionally, remove ``wheel`` from virtual environment as
it is no longer a build dependency.
20 changes: 16 additions & 4 deletions setuptools/command/bdist_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,7 @@ def finalize_options(self) -> None:
self.distribution.has_ext_modules() or self.distribution.has_c_libraries()
)

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

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

def _validate_py_limited_api(self) -> None:
if not self.py_limited_api:
return

if not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api):
raise ValueError(f"py-limited-api must match '{PY_LIMITED_API_PATTERN}'")

if sysconfig.get_config_var("Py_GIL_DISABLED"):
raise ValueError(
f"`py_limited_api={self.py_limited_api!r}` not supported. "
"`Py_LIMITED_API` is currently incompatible with "
f"`Py_GIL_DISABLED` ({sys.abiflags=!r}). "
"See https://github.com/python/cpython/issues/111506."
)

@property
def wheel_dist_name(self) -> str:
"""Return distribution full name with - replaced with _"""
Expand Down
5 changes: 5 additions & 0 deletions setuptools/config/_apply_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ def _valid_command_options(cmdclass: Mapping = EMPTY) -> dict[str, set[str]]:


def _load_ep(ep: metadata.EntryPoint) -> tuple[str, type] | None:
if ep.value.startswith("wheel.bdist_wheel"):
# Ignore deprecated entrypoint from wheel and avoid warning pypa/wheel#631
# TODO: remove check when `bdist_wheel` has been fully removed from pypa/wheel
return None

# Ignore all the errors
try:
return (ep.name, ep.load())
Expand Down
6 changes: 2 additions & 4 deletions setuptools/config/_validate_pyproject/error_reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import typing
from contextlib import contextmanager
from textwrap import indent, wrap
from typing import Any, Dict, Generator, Iterator, List, Optional, Sequence, Union, cast
from typing import Any, Dict, Generator, Iterator, List, Optional, Sequence, Union

from .fastjsonschema_exceptions import JsonSchemaValueException

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

def _inline_attrs(self, schema: dict, path: Sequence[str]) -> Iterator[str]:
Expand Down
48 changes: 24 additions & 24 deletions setuptools/config/_validate_pyproject/fastjsonschema_validations.py

Large diffs are not rendered by default.

23 changes: 22 additions & 1 deletion setuptools/config/_validate_pyproject/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ def pep508_identifier(name: str) -> bool:
from packaging import requirements as _req
except ImportError: # pragma: no cover
# let's try setuptools vendored version
from setuptools._vendor.packaging import requirements as _req # type: ignore
from setuptools._vendor.packaging import ( # type: ignore[no-redef]
requirements as _req,
)

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


def python_module_name_relaxed(value: str) -> bool:
"""Similar to :obj:`python_module_name`, but relaxed to also accept
dash characters (``-``) and cover special cases like ``pip-run``.
It is recommended, however, that beginners avoid dash characters,
as they require advanced knowledge about Python internals.
The following are disallowed:
* names starting/ending in dashes,
* names ending in ``-stubs`` (potentially collide with :obj:`pep561_stub_name`).
"""
if value.startswith("-") or value.endswith("-"):
return False
if value.endswith("-stubs"):
return False # Avoid collision with PEP 561
return python_module_name(value.replace("-", "_"))


def python_entrypoint_group(value: str) -> bool:
"""See ``Data model > group`` in the :ref:`PyPA's entry-points specification
<pypa:entry-points>`.
Expand Down
6 changes: 3 additions & 3 deletions setuptools/config/setuptools.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@
},
"namespace-packages": {
"type": "array",
"items": {"type": "string", "format": "python-module-name"},
"items": {"type": "string", "format": "python-module-name-relaxed"},
"$comment": "https://setuptools.pypa.io/en/latest/userguide/package_discovery.html",
"description": "**DEPRECATED**: use implicit namespaces instead (:pep:`420`)."
},
"py-modules": {
"description": "Modules that setuptools will manipulate",
"type": "array",
"items": {"type": "string", "format": "python-module-name"},
"items": {"type": "string", "format": "python-module-name-relaxed"},
"$comment": "TODO: clarify the relationship with ``packages``"
},
"data-files": {
Expand Down Expand Up @@ -250,7 +250,7 @@
"description": "Valid package name (importable or :pep:`561`).",
"type": "string",
"anyOf": [
{"type": "string", "format": "python-module-name"},
{"type": "string", "format": "python-module-name-relaxed"},
{"type": "string", "format": "pep561-stub-name"}
]
},
Expand Down
27 changes: 27 additions & 0 deletions setuptools/tests/config/test_apply_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,33 @@ def test_default_patterns(self, tmp_path):
assert set(dist.metadata.license_files) == {*license_files, "LICENSE.txt"}


class TestPyModules:
# https://github.com/pypa/setuptools/issues/4316

def dist(self, name):
toml_config = f"""
[project]
name = "test"
version = "42.0"
[tool.setuptools]
py-modules = [{name!r}]
"""
pyproject = Path("pyproject.toml")
pyproject.write_text(cleandoc(toml_config), encoding="utf-8")
return pyprojecttoml.apply_configuration(Distribution({}), pyproject)

@pytest.mark.parametrize("module", ["pip-run", "abc-d.λ-xyz-e"])
def test_valid_module_name(self, tmp_path, monkeypatch, module):
monkeypatch.chdir(tmp_path)
assert module in self.dist(module).py_modules

@pytest.mark.parametrize("module", ["pip run", "-pip-run", "pip-run-stubs"])
def test_invalid_module_name(self, tmp_path, monkeypatch, module):
monkeypatch.chdir(tmp_path)
with pytest.raises(ValueError, match="py-modules"):
self.dist(module).py_modules


class TestDeprecatedFields:
def test_namespace_packages(self, tmp_path):
pyproject = tmp_path / "pyproject.toml"
Expand Down
2 changes: 1 addition & 1 deletion setuptools/tests/integration/test_pip_install_sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def test_install_sdist(package, version, tmp_path, venv_python, setuptools_wheel
# Use a virtualenv to simulate PEP 517 isolation
# but install fresh setuptools wheel to ensure the version under development
env = EXTRA_ENV_VARS.get(package, {})
run([*venv_pip, "install", "wheel", "-I", setuptools_wheel])
run([*venv_pip, "install", "--force-reinstall", setuptools_wheel])
run([*venv_pip, "install", *INSTALL_OPTIONS, sdist], env)

# Execute a simple script to make sure the package was installed correctly
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ commands =
[testenv:generate-validation-code]
skip_install = True
deps =
validate-pyproject[all]==0.18
validate-pyproject[all]==0.19
commands =
python -m tools.generate_validation_code

Expand Down

0 comments on commit 4f98086

Please sign in to comment.