Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/pypa/setuptools into setupt…
Browse files Browse the repository at this point in the history
…ools-simple-typeshed-params
  • Loading branch information
Avasam committed Oct 21, 2024
2 parents 23412b8 + 99c75c9 commit 6e8e63e
Show file tree
Hide file tree
Showing 22 changed files with 139 additions and 81 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/pyright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ env:
# For help with static-typing issues, or pyright update, ping @Avasam
#
# An exact version from https://github.com/microsoft/pyright/releases or "latest"
PYRIGHT_VERSION: "1.1.377"
PYRIGHT_VERSION: "1.1.385"

# Environment variable to support color support (jaraco/skeleton#66)
FORCE_COLOR: 1
Expand Down Expand Up @@ -73,4 +73,5 @@ jobs:
uses: jakebailey/pyright-action@v2
with:
version: ${{ env.PYRIGHT_VERSION }}
python-version: ${{ matrix.python }}
extra-args: --threads
1 change: 1 addition & 0 deletions newsfragments/4560.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bumped declared ``platformdirs`` dependency to ``>= 4.2.2`` to help platforms lacking `ctypes` support install setuptools seamlessly -- by :user:`Avasam`
4 changes: 4 additions & 0 deletions newsfragments/4567.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Ensured methods in ``setuptools.modified`` preferably raise a consistent
``distutils.errors.DistutilsError`` type
(except in the deprecated use case of ``SETUPTOOLS_USE_DISTUTILS=stdlib``)
-- by :user:`Avasam`
1 change: 1 addition & 0 deletions newsfragments/4575.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allowed using `dict` as an ordered type in ``setuptools.dist.check_requirements`` -- by :user:`Avasam`
4 changes: 4 additions & 0 deletions newsfragments/4696.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix clashes for ``optional-dependencies`` in ``pyproject.toml`` and
``extra_requires`` in ``setup.cfg/setup.py``.
As per PEP 621, ``optional-dependencies`` has to be honoured and dynamic
behaviour is not allowed.
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ core = [
"wheel>=0.43.0",

# pkg_resources
"platformdirs >= 2.6.2",
"platformdirs >= 4.2.2", # Made ctypes optional (see #4461)

# for distutils
"jaraco.collections",
Expand Down Expand Up @@ -136,7 +136,7 @@ type = [
# pin mypy version so a new version doesn't suddenly cause the CI to fail,
# until types-setuptools is removed from typeshed.
# For help with static-typing issues, or mypy update, ping @Avasam
"mypy==1.11.*",
"mypy==1.12.*",
# Typing fixes in version newer than we require at runtime
"importlib_metadata>=7.0.2; python_version < '3.10'",
# Imported unconditionally in tools/finalize.py
Expand Down
5 changes: 3 additions & 2 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ extend-select = [

# local
"ANN2", # missing-return-type-*
"FA", # flake8-future-annotations
"F404", # late-future-import
"FA", # flake8-future-annotations
"I", # isort
"PYI", # flake8-pyi
"TRY", # tryceratops
"UP", # pyupgrade
"TRY",
"YTT", # flake8-2020
]
ignore = [
"TRY003", # raise-vanilla-args, avoid multitude of exception classes
"TRY301", # raise-within-try, it's handy
"UP015", # redundant-open-modes, explicit is preferred
"UP027", # unpacked-list-comprehension, is actually slower for cases relevant to unpacking, set for deprecation: https://github.com/astral-sh/ruff/issues/12754
"UP030", # temporarily disabled
"UP031", # temporarily disabled
"UP032", # temporarily disabled
Expand Down
10 changes: 9 additions & 1 deletion setuptools/command/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# mypy: disable_error_code=call-overload
# pyright: reportCallIssue=false, reportArgumentType=false
# Can't disable on the exact line because distutils doesn't exists on Python 3.12
# and type-checkers aren't aware of distutils_hack,
# causing distutils.command.bdist.bdist.format_commands to be Any.

import sys

from distutils.command.bdist import bdist

if 'egg' not in bdist.format_commands:
try:
# format_commands is a dict in vendored distutils
# It used to be a list in older (stdlib) distutils
# We support both for backwards compatibility
bdist.format_commands['egg'] = ('bdist_egg', "Python .egg file")
except TypeError:
# For backward compatibility with older distutils (stdlib)
bdist.format_command['egg'] = ('bdist_egg', "Python .egg file")
bdist.format_commands.append('egg')

Expand Down
1 change: 0 additions & 1 deletion setuptools/command/_requirestxt.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
# dict can work as an ordered set
_T = TypeVar("_T")
_Ordered = Dict[_T, None]
_ordered = dict


def _prepare(
Expand Down
9 changes: 1 addition & 8 deletions setuptools/command/build_clib.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
from ..dist import Distribution
from ..modified import newer_pairwise_group

import distutils.command.build_clib as orig
from distutils import log
from distutils.errors import DistutilsSetupError

try:
from distutils._modified import ( # pyright: ignore[reportMissingImports]
newer_pairwise_group,
)
except ImportError:
# fallback for SETUPTOOLS_USE_DISTUTILS=stdlib
from .._distutils._modified import newer_pairwise_group


class build_clib(orig.build_clib):
"""
Expand Down
5 changes: 1 addition & 4 deletions setuptools/command/egg_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Create a distribution's .egg-info directory and contents"""

import collections
import functools
import os
import re
Expand Down Expand Up @@ -211,11 +210,9 @@ def save_version_info(self, filename):
build tag. Install build keys in a deterministic order
to avoid arbitrary reordering on subsequent builds.
"""
egg_info = collections.OrderedDict()
# follow the order these keys would have been added
# when PYTHONHASHSEED=0
egg_info['tag_build'] = self.tags()
egg_info['tag_date'] = 0
egg_info = dict(tag_build=self.tags(), tag_date=0)
edit_config(filename, dict(egg_info=egg_info))

def finalize_options(self):
Expand Down
2 changes: 1 addition & 1 deletion setuptools/command/sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class sdist(orig.sdist):
]

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
negative_opt: ClassVar[dict[str, str]] = {} # type: ignore[misc] # Fixed upstream in typeshed to be a ClassVar. Should be included in mypy 1.12
negative_opt: ClassVar[dict[str, str]] = {}

README_EXTENSIONS = ['', '.rst', '.txt', '.md']
READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS)
Expand Down
6 changes: 4 additions & 2 deletions setuptools/config/_apply_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,10 @@ def _dependencies(dist: Distribution, val: list, _root_dir: StrPath | None):


def _optional_dependencies(dist: Distribution, val: dict, _root_dir: StrPath | None):
existing = getattr(dist, "extras_require", None) or {}
dist.extras_require = {**existing, **val}
if getattr(dist, "extras_require", None):
msg = "`extras_require` overwritten in `pyproject.toml` (optional-dependencies)"
SetuptoolsWarning.emit(msg)
dist.extras_require = val


def _ext_modules(dist: Distribution, val: list[dict]) -> list[Extension]:
Expand Down
15 changes: 6 additions & 9 deletions setuptools/config/setupcfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ def __setitem__(self, option_name, value) -> None:
return

simple_setter = functools.partial(target_obj.__setattr__, option_name)
setter = getattr(target_obj, 'set_%s' % option_name, simple_setter)
setter = getattr(target_obj, f"set_{option_name}", simple_setter)
setter(parsed)

self.set_options.append(option_name)
Expand Down Expand Up @@ -375,8 +375,8 @@ def parser(value):
exclude_directive = 'file:'
if value.startswith(exclude_directive):
raise ValueError(
'Only strings are accepted for the {0} field, '
'files are not accepted'.format(key)
f'Only strings are accepted for the {key} field, '
'files are not accepted'
)
return value

Expand Down Expand Up @@ -494,12 +494,12 @@ def parse(self) -> None:
for section_name, section_options in self.sections.items():
method_postfix = ''
if section_name: # [section.option] variant
method_postfix = '_%s' % section_name
method_postfix = f"_{section_name}"

section_parser_method: Callable | None = getattr(
self,
# Dots in section names are translated into dunderscores.
('parse_section%s' % method_postfix).replace('.', '__'),
f'parse_section{method_postfix}'.replace('.', '__'),
None,
)

Expand Down Expand Up @@ -704,10 +704,7 @@ def parse_section_packages__find(self, section_options):
section_data = self._parse_section_to_dict(section_options, self._parse_list)

valid_keys = ['where', 'include', 'exclude']

find_kwargs = dict([
(k, v) for k, v in section_data.items() if k in valid_keys and v
])
find_kwargs = {k: v for k, v in section_data.items() if k in valid_keys and v}

where = find_kwargs.get('where')
if where is not None:
Expand Down
29 changes: 15 additions & 14 deletions setuptools/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
from typing import (
TYPE_CHECKING,
Any,
Dict,
List,
MutableMapping,
NoReturn,
Sequence,
Tuple,
Union,
overload,
)

from more_itertools import partition, unique_everseen
Expand All @@ -33,7 +33,6 @@
command as _, # noqa: F401 # imported for side-effects
)
from ._importlib import metadata
from ._reqs import _StrOrIter
from .config import pyprojecttoml, setupcfg
from .discovery import ConfigDiscovery
from .monkey import get_unpatched
Expand Down Expand Up @@ -66,7 +65,13 @@
"""
_Sequence: TypeAlias = Union[Tuple[str, ...], List[str]]
# This is how stringifying _Sequence would look in Python 3.10
_requence_type_repr = "tuple[str, ...] | list[str]"
_sequence_type_repr = "tuple[str, ...] | list[str]"
_OrderedStrSequence: TypeAlias = Union[str, Dict[str, Any], Sequence[str]]
"""
:meta private:
Avoid single-use iterable. Disallow sets.
A poor approximation of an OrderedSequence (dict doesn't match a Sequence).
"""


def __getattr__(name: str) -> Any: # pragma: no cover
Expand Down Expand Up @@ -100,7 +105,7 @@ def assert_string_list(dist, attr: str, value: _Sequence) -> None:
assert ''.join(value) != value
except (TypeError, ValueError, AttributeError, AssertionError) as e:
raise DistutilsSetupError(
f"{attr!r} must be of type <{_requence_type_repr}> (got {value!r})"
f"{attr!r} must be of type <{_sequence_type_repr}> (got {value!r})"
) from e


Expand Down Expand Up @@ -176,15 +181,11 @@ def invalid_unless_false(dist, attr, value):
raise DistutilsSetupError(f"{attr} is invalid.")


@overload
def check_requirements(dist, attr: str, value: set | dict) -> NoReturn: ...
@overload
def check_requirements(dist, attr: str, value: _StrOrIter) -> None: ...
def check_requirements(dist, attr: str, value: _StrOrIter) -> None:
def check_requirements(dist, attr: str, value: _OrderedStrSequence) -> None:
"""Verify that install_requires is a valid requirements list"""
try:
list(_reqs.parse(value))
if isinstance(value, (dict, set)):
if isinstance(value, set):
raise TypeError("Unordered types are not allowed")
except (TypeError, ValueError) as error:
msg = (
Expand Down Expand Up @@ -816,7 +817,7 @@ def _exclude_misc(self, name: str, value: _Sequence) -> None:
"""Handle 'exclude()' for list/tuple attrs without a special handler"""
if not isinstance(value, _sequence):
raise DistutilsSetupError(
f"{name}: setting must be of type <{_requence_type_repr}> (got {value!r})"
f"{name}: setting must be of type <{_sequence_type_repr}> (got {value!r})"
)
try:
old = getattr(self, name)
Expand All @@ -834,7 +835,7 @@ def _include_misc(self, name: str, value: _Sequence) -> None:

if not isinstance(value, _sequence):
raise DistutilsSetupError(
f"{name}: setting must be of type <{_requence_type_repr}> (got {value!r})"
f"{name}: setting must be of type <{_sequence_type_repr}> (got {value!r})"
)
try:
old = getattr(self, name)
Expand Down Expand Up @@ -876,7 +877,7 @@ def exclude(self, **attrs):
def _exclude_packages(self, packages: _Sequence) -> None:
if not isinstance(packages, _sequence):
raise DistutilsSetupError(
f"packages: setting must be of type <{_requence_type_repr}> (got {packages!r})"
f"packages: setting must be of type <{_sequence_type_repr}> (got {packages!r})"
)
list(map(self.exclude_package, packages))

Expand Down
22 changes: 16 additions & 6 deletions setuptools/modified.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
from ._distutils._modified import (
newer,
newer_group,
newer_pairwise,
newer_pairwise_group,
)
try:
# Ensure a DistutilsError raised by these methods is the same as distutils.errors.DistutilsError
from distutils._modified import (
newer,
newer_group,
newer_pairwise,
newer_pairwise_group,
)
except ImportError:
# fallback for SETUPTOOLS_USE_DISTUTILS=stdlib, because _modified never existed in stdlib
from ._distutils._modified import (
newer,
newer_group,
newer_pairwise,
newer_pairwise_group,
)

__all__ = ['newer', 'newer_pairwise', 'newer_group', 'newer_pairwise_group']
5 changes: 1 addition & 4 deletions setuptools/package_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,10 +561,7 @@ def not_found_in_index(self, requirement):
if self[requirement.key]: # we've seen at least one distro
meth, msg = self.info, "Couldn't retrieve index page for %r"
else: # no distros seen for this name, might be misspelled
meth, msg = (
self.warn,
"Couldn't find index page for %r (maybe misspelled?)",
)
meth, msg = self.warn, "Couldn't find index page for %r (maybe misspelled?)"
meth(msg, requirement.unsafe_name)
self.scan_all()

Expand Down
32 changes: 21 additions & 11 deletions setuptools/tests/config/test_pyprojecttoml_dynamic_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from setuptools.config.pyprojecttoml import apply_configuration
from setuptools.dist import Distribution
from setuptools.warnings import SetuptoolsWarning


def test_dynamic_dependencies(tmp_path):
Expand Down Expand Up @@ -77,23 +78,32 @@ def test_mixed_dynamic_optional_dependencies(tmp_path):
[tool.setuptools.dynamic.optional-dependencies.images]
file = ["requirements-images.txt"]
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
"""
),
}

path.build(files, prefix=tmp_path)

# Test that the mix-and-match doesn't currently validate.
pyproject = tmp_path / "pyproject.toml"
with pytest.raises(ValueError, match="project.optional-dependencies"):
apply_configuration(Distribution(), pyproject)

# Explicitly disable the validation and try again, to see that the mix-and-match
# result would be correct.
dist = Distribution()
dist = apply_configuration(dist, pyproject, ignore_option_errors=True)
assert dist.extras_require == {"docs": ["sphinx"], "images": ["pillow~=42.0"]}

def test_mixed_extras_require_optional_dependencies(tmp_path):
files = {
"pyproject.toml": cleandoc(
"""
[project]
name = "myproj"
version = "1.0"
optional-dependencies.docs = ["sphinx"]
"""
),
}

path.build(files, prefix=tmp_path)
pyproject = tmp_path / "pyproject.toml"

with pytest.warns(SetuptoolsWarning, match=".extras_require. overwritten"):
dist = Distribution({"extras_require": {"hello": ["world"]}})
dist = apply_configuration(dist, pyproject)
assert dist.extras_require == {"docs": ["sphinx"]}
1 change: 0 additions & 1 deletion setuptools/tests/test_core_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,6 @@ def test_parity_with_metadata_from_pypa_wheel(tmp_path):
python_requires=">=3.8",
install_requires="""
packaging==23.2
ordered-set==3.1.1
more-itertools==8.8.0; extra == "other"
jaraco.text==3.7.0
importlib-resources==5.10.2; python_version<"3.8"
Expand Down
Loading

0 comments on commit 6e8e63e

Please sign in to comment.