From 0f050a1cf4e71d79fb4402fe7ccbfcb148120234 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 14 Feb 2023 18:01:25 +0000 Subject: [PATCH 01/46] Move _deprecation_warning to warnings. The objective is to centralize all the warnings in a single module. --- setuptools/{_deprecation_warning.py => warnings.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename setuptools/{_deprecation_warning.py => warnings.py} (100%) diff --git a/setuptools/_deprecation_warning.py b/setuptools/warnings.py similarity index 100% rename from setuptools/_deprecation_warning.py rename to setuptools/warnings.py From 384d0c49740cf666771b44139d514af7d6437d6c Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 19:01:07 +0000 Subject: [PATCH 02/46] Import SetuptoolsDeprecationWarning from setuptools.warnings --- setuptools/__init__.py | 2 +- setuptools/_normalization.py | 2 +- setuptools/build_meta.py | 2 +- setuptools/command/build_py.py | 2 +- setuptools/command/dist_info.py | 2 +- setuptools/config/__init__.py | 2 +- setuptools/config/_apply_pyprojecttoml.py | 2 +- setuptools/config/setupcfg.py | 2 +- setuptools/installer.py | 2 +- setuptools/tests/config/test_apply_pyprojecttoml.py | 2 +- setuptools/tests/config/test_setupcfg.py | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 89f6f06ec0..cf233a3292 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -11,7 +11,7 @@ from distutils.errors import DistutilsOptionError from distutils.util import convert_path as _convert_path -from ._deprecation_warning import SetuptoolsDeprecationWarning +from .warnings import SetuptoolsDeprecationWarning import setuptools.version from setuptools.extension import Extension diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py index 8ba7c802fa..06e535b40e 100644 --- a/setuptools/_normalization.py +++ b/setuptools/_normalization.py @@ -10,7 +10,7 @@ from setuptools.extern import packaging -from ._deprecation_warning import SetuptoolsDeprecationWarning +from .warnings import SetuptoolsDeprecationWarning _Path = Union[str, Path] diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index 618a5e8f5e..2fd1420fef 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -43,7 +43,7 @@ from . import errors from ._path import same_path from ._reqs import parse_strings -from ._deprecation_warning import SetuptoolsDeprecationWarning +from .warnings import SetuptoolsDeprecationWarning from distutils.util import strtobool diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index ec0627429c..14094f8d3d 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -13,7 +13,7 @@ from pathlib import Path from typing import Dict, Iterable, Iterator, List, Optional, Tuple -from setuptools._deprecation_warning import SetuptoolsDeprecationWarning +from setuptools.warnings import SetuptoolsDeprecationWarning from setuptools.extern.more_itertools import unique_everseen diff --git a/setuptools/command/dist_info.py b/setuptools/command/dist_info.py index 40fdfd0a28..64aec5c066 100644 --- a/setuptools/command/dist_info.py +++ b/setuptools/command/dist_info.py @@ -13,7 +13,7 @@ from pathlib import Path from .. import _normalization -from .._deprecation_warning import SetuptoolsDeprecationWarning +from ..warnings import SetuptoolsDeprecationWarning class dist_info(Command): diff --git a/setuptools/config/__init__.py b/setuptools/config/__init__.py index 1a5153ad4f..d411aadd21 100644 --- a/setuptools/config/__init__.py +++ b/setuptools/config/__init__.py @@ -6,7 +6,7 @@ from textwrap import dedent from typing import Callable, TypeVar, cast -from .._deprecation_warning import SetuptoolsDeprecationWarning +from ..warnings import SetuptoolsDeprecationWarning from . import setupcfg Fn = TypeVar("Fn", bound=Callable) diff --git a/setuptools/config/_apply_pyprojecttoml.py b/setuptools/config/_apply_pyprojecttoml.py index c805e63940..f792521c24 100644 --- a/setuptools/config/_apply_pyprojecttoml.py +++ b/setuptools/config/_apply_pyprojecttoml.py @@ -18,7 +18,7 @@ from typing import (TYPE_CHECKING, Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union, cast) -from setuptools._deprecation_warning import SetuptoolsDeprecationWarning +from setuptools.warnings import SetuptoolsDeprecationWarning if TYPE_CHECKING: from setuptools._importlib import metadata # noqa diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py index 03a446fd2a..8c0dcc61a4 100644 --- a/setuptools/config/setupcfg.py +++ b/setuptools/config/setupcfg.py @@ -31,7 +31,7 @@ from setuptools.extern.packaging.markers import default_environment as marker_env from setuptools.extern.packaging.version import Version, InvalidVersion from setuptools.extern.packaging.specifiers import SpecifierSet -from setuptools._deprecation_warning import SetuptoolsDeprecationWarning +from setuptools.warnings import SetuptoolsDeprecationWarning from . import expand diff --git a/setuptools/installer.py b/setuptools/installer.py index e9a7567abc..137f35ace4 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -10,7 +10,7 @@ from . import _reqs from .wheel import Wheel -from ._deprecation_warning import SetuptoolsDeprecationWarning +from .warnings import SetuptoolsDeprecationWarning def _fixup_find_links(find_links): diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py index 3a66d494b3..8f76f2c99d 100644 --- a/setuptools/tests/config/test_apply_pyprojecttoml.py +++ b/setuptools/tests/config/test_apply_pyprojecttoml.py @@ -15,7 +15,7 @@ from ini2toml.api import Translator import setuptools # noqa ensure monkey patch to metadata -from setuptools._deprecation_warning import SetuptoolsDeprecationWarning +from setuptools.warnings import SetuptoolsDeprecationWarning from setuptools.dist import Distribution from setuptools.config import setupcfg, pyprojecttoml from setuptools.config import expand diff --git a/setuptools/tests/config/test_setupcfg.py b/setuptools/tests/config/test_setupcfg.py index a47138c8d0..97207829df 100644 --- a/setuptools/tests/config/test_setupcfg.py +++ b/setuptools/tests/config/test_setupcfg.py @@ -7,7 +7,7 @@ import pytest from distutils.errors import DistutilsOptionError, DistutilsFileError -from setuptools._deprecation_warning import SetuptoolsDeprecationWarning +from setuptools.warnings import SetuptoolsDeprecationWarning from setuptools.dist import Distribution, _Distribution from setuptools.config.setupcfg import ConfigHandler, read_configuration from setuptools.extern.packaging.requirements import InvalidRequirement From 57ff9519bdd7024d9b0f98227055229786181522 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 14 Feb 2023 18:02:07 +0000 Subject: [PATCH 03/46] Add warning hierarchy and helper/display functions --- setuptools/warnings.py | 99 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/setuptools/warnings.py b/setuptools/warnings.py index 086b64dd38..4ea782e509 100644 --- a/setuptools/warnings.py +++ b/setuptools/warnings.py @@ -1,7 +1,104 @@ -class SetuptoolsDeprecationWarning(Warning): +"""Provide basic warnings used by setuptools modules. + +Using custom classes (other than ``UserWarning``) allow users to set +``PYTHONWARNINGS`` filters to run tests and prepare for upcoming changes in +setuptools. +""" + +import os +import warnings +from datetime import date +from inspect import cleandoc +from textwrap import indent +from typing import Optional, Tuple + +_DueDate = Tuple[int, int, int] # time tuple +_INDENT = 8 * " " +_TEMPLATE = f"""{80 * '*'}\n{{details}}\n{80 * '*'}""" + + +class SetuptoolsWarning(UserWarning): + """Base class in ``setuptools`` warning hierarchy.""" + + @classmethod + def emit( + cls, + summary: Optional[str] = None, + details: Optional[str] = None, + due_date: Optional[_DueDate] = None, + see_docs: Optional[str] = None, + see_url: Optional[str] = None, + stacklevel: int = 2, + **kwargs + ): + """Private: reserved for ``setuptools`` internal use only""" + # Default values: + summary_ = summary or getattr(cls, "_SUMMARY", None) or "" + details_ = details or getattr(cls, "_DETAILS", None) or "" + due_date = due_date or getattr(cls, "_DUE_DATE", None) + docs_ref = see_docs or getattr(cls, "_SEE_DOCS", None) + docs_url = docs_ref and f"https://setuptools.pypa.io/en/latest/{docs_ref}" + see_url = see_url or getattr(cls, "_SEE_URL", None) + due = date(*due_date) if due_date else None + + text = cls._format(summary_, details_, due, see_url or docs_url, kwargs) + if due and due < date.today() and _should_enforce(): + raise cls(text) + warnings.warn(text, cls, stacklevel=stacklevel + 1) + + @classmethod + def _format( + cls, + summary: str, + details: str, + due_date: Optional[date] = None, + see_url: Optional[str] = None, + format_args: Optional[dict] = None, + ): + """Private: reserved for ``setuptools`` internal use only""" + today = date.today() + summary = cleandoc(summary).format_map(format_args or {}) + possible_parts = [ + cleandoc(details).format_map(format_args or {}), + ( + f"\nBy {due_date:%Y-%b-%d}, you need to update your project and remove " + "deprecated calls\nor your builds will no longer be supported." + if due_date and due_date > today else None + ), + ( + "\nThis deprecation is overdue, please update your project and remove " + "deprecated\ncalls to avoid build errors in the future." + if due_date and due_date < today else None + ), + (f"\nSee {see_url} for details." if see_url else None) + + ] + parts = [x for x in possible_parts if x] + if parts: + body = indent(_TEMPLATE.format(details="\n".join(parts)), _INDENT) + return "\n".join([summary, "!!\n", body, "\n!!"]) + return summary + + +class InformationOnly(SetuptoolsWarning): + """Currently there is no clear way of displaying messages to the users + that use the setuptools backend directly via ``pip``. + The only thing that might work is a warning, although it is not the + most appropriate tool for the job... + + See pypa/packaging-problems#558. + """ + + +class SetuptoolsDeprecationWarning(SetuptoolsWarning): """ Base class for warning deprecations in ``setuptools`` This class is not derived from ``DeprecationWarning``, and as such is visible by default. """ + + +def _should_enforce(): + enforce = os.getenv("SETUPTOOLS_ENFORCE_DEPRECATION", "false").lower() + return enforce in ("true", "on", "ok", "1") From 62be049045fad723cd6f4834ea63e47aafc7a716 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 14 Feb 2023 19:11:22 +0000 Subject: [PATCH 04/46] Add tests for warning formatting and tweaks to implementation --- setuptools/tests/test_warnings.py | 106 ++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 setuptools/tests/test_warnings.py diff --git a/setuptools/tests/test_warnings.py b/setuptools/tests/test_warnings.py new file mode 100644 index 0000000000..75e468d20b --- /dev/null +++ b/setuptools/tests/test_warnings.py @@ -0,0 +1,106 @@ +from inspect import cleandoc + +import pytest + +from setuptools.warnings import SetuptoolsDeprecationWarning, SetuptoolsWarning + + +_EXAMPLES = { + "default": dict( + args=("Hello {x}", "\n\t{target} {v:.1f}"), + kwargs={"x": 5, "v": 3, "target": "World"}, + expected = """ + Hello 5 + !! + + ******************************************************************************** + World 3.0 + ******************************************************************************** + + !! + """ # noqa, + ), + "futue_due_date": dict( + args=("Summary", "Lorem ipsum"), + kwargs={"due_date": (9999, 11, 22)}, + expected = """ + Summary + !! + + ******************************************************************************** + Lorem ipsum + + By 9999-Nov-22, you need to update your project and remove deprecated calls + or your builds will no longer be supported. + ******************************************************************************** + + !! + """ # noqa + ), + "past_due_date_with_docs": dict( + args=("Summary", "Lorem ipsum"), + kwargs={"due_date": (2000, 11, 22), "see_docs": "some_page.html"}, + expected=""" + Summary + !! + + ******************************************************************************** + Lorem ipsum + + This deprecation is overdue, please update your project and remove deprecated + calls to avoid build errors in the future. + + See https://setuptools.pypa.io/en/latest/some_page.html for details. + ******************************************************************************** + + !! + """ # noqa + ), +} + + +@pytest.mark.parametrize("example_name", _EXAMPLES.keys()) +def test_formatting(example_name): + """ + It should automatically handle indentation, interpolation and things like due date. + """ + args = _EXAMPLES[example_name]["args"] + kwargs = _EXAMPLES[example_name]["kwargs"] + expected = _EXAMPLES[example_name]["expected"] + + with pytest.warns(SetuptoolsWarning) as warn_info: + SetuptoolsWarning.emit(*args, **kwargs) + assert _get_message(warn_info) == cleandoc(expected) + + +def test_due_date_enforcement(monkeypatch): + class _MyDeprecation(SetuptoolsDeprecationWarning): + _SUMMARY = "Summary" + _DETAILS = "Lorem ipsum" + _DUE_DATE = (2000, 11, 22) + _SEE_DOCS = "some_page.html" + + monkeypatch.setenv("SETUPTOOLS_ENFORCE_DEPRECATION", "true") + with pytest.raises(SetuptoolsDeprecationWarning) as exc_info: + _MyDeprecation.emit() + + expected=""" + Summary + !! + + ******************************************************************************** + Lorem ipsum + + This deprecation is overdue, please update your project and remove deprecated + calls to avoid build errors in the future. + + See https://setuptools.pypa.io/en/latest/some_page.html for details. + ******************************************************************************** + + !! + """ # noqa + assert str(exc_info.value) == cleandoc(expected) + + +def _get_message(warn_info): + return next(warn.message.args[0] for warn in warn_info) From 3fcee5f4533e53b4424de4413420272e35b3797a Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 19:56:23 +0000 Subject: [PATCH 05/46] Use new warnings in setuptools/__init__.py --- setuptools/__init__.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index cf233a3292..6dceab5bab 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -3,7 +3,6 @@ import functools import os import re -import warnings import _distutils_hack.override # noqa: F401 @@ -249,14 +248,17 @@ def findall(dir=os.curdir): @functools.wraps(_convert_path) def convert_path(pathname): - from inspect import cleandoc + SetuptoolsDeprecationWarning.emit( + "Access to implementation detail", + """ + The function `convert_path` is not provided by setuptools itself, + and therefore not part of the public API. - msg = """ - The function `convert_path` is considered internal and not part of the public API. - Its direct usage by 3rd-party packages is considered deprecated and the function - may be removed in the future. - """ - warnings.warn(cleandoc(msg), SetuptoolsDeprecationWarning) + Its direct usage by 3rd-party packages is considered improper and the function + may be removed in the future. + """, + due_date=(2023, 11, 25) # initial deprecation 2022-03-25, see #3201 + ) return _convert_path(pathname) From c94c8fef02351b880d40a2ba622b492a2d4ffe90 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 19:58:20 +0000 Subject: [PATCH 06/46] Use new warnings in setuptools/_importlib.py --- setuptools/_importlib.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/setuptools/_importlib.py b/setuptools/_importlib.py index 819bf5d3c2..5ae94b4739 100644 --- a/setuptools/_importlib.py +++ b/setuptools/_importlib.py @@ -13,14 +13,17 @@ def disable_importlib_metadata_finder(metadata): except ImportError: return except AttributeError: - import warnings - - msg = ( - "`importlib-metadata` version is incompatible with `setuptools`.\n" - "This problem is likely to be solved by installing an updated version of " - "`importlib-metadata`." - ) - warnings.warn(msg) # Ensure a descriptive message is shown. + from .warnings import SetuptoolsWarning + + SetuptoolsWarning.emit( + "Incompatibility problem.", + """ + `importlib-metadata` version is incompatible with `setuptools`. + This problem is likely to be solved by installing an updated version of + `importlib-metadata`. + """, + see_url="https://github.com/python/importlib_metadata/issues/396" + ) # Ensure a descriptive message is shown. raise # This exception can be suppressed by _distutils_hack if importlib_metadata is metadata: From 9aafb559c1c1293c2f6bb720f6573dadc089588a Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 19:59:54 +0000 Subject: [PATCH 07/46] Use new warnings in setuptools/_normalization.py --- setuptools/_normalization.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py index 06e535b40e..c34f5ff74c 100644 --- a/setuptools/_normalization.py +++ b/setuptools/_normalization.py @@ -3,13 +3,10 @@ and core metadata """ import re -import warnings -from inspect import cleandoc from pathlib import Path from typing import Union -from setuptools.extern import packaging - +from .extern import packaging from .warnings import SetuptoolsDeprecationWarning _Path = Union[str, Path] @@ -79,18 +76,18 @@ def best_effort_version(version: str) -> str: try: return safe_version(version) except packaging.version.InvalidVersion: - msg = f"""Invalid version: {version!r}. - !!\n\n - ################### - # Invalid version # - ################### - {version!r} is not valid according to PEP 440.\n - Please make sure specify a valid version for your package. - Also note that future releases of setuptools may halt the build process - if an invalid version is given. - \n\n!! - """ - warnings.warn(cleandoc(msg), SetuptoolsDeprecationWarning) + SetuptoolsDeprecationWarning.emit( + f"Invalid version: {version!r}.", + f""" + Version {version!r} is not valid according to PEP 440. + + Please make sure specify a valid version for your package. + Also note that future releases of setuptools may halt the build process + if an invalid version is given. + """, + see_url="https://peps.python.org/pep-0440/", + due_date=(2023, 9, 26), # See setuptools/dist _validate_version + ) v = version.replace(' ', '.') return safe_name(v) From e7508d1364b0d9e6fc9ec8124bcb97dc1b64efa9 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:05:37 +0000 Subject: [PATCH 08/46] Use new warnings in setuptools/build_meta.py --- setuptools/build_meta.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index 2fd1420fef..c620d695e9 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -299,12 +299,15 @@ def _arbitrary_args(self, config_settings: _ConfigSettings) -> Iterator[str]: yield from self._get_config("--build-option", config_settings) if bad_args: - msg = f""" - The arguments {bad_args!r} were given via `--global-option`. - Please use `--build-option` instead, - `--global-option` is reserved to flags like `--verbose` or `--quiet`. - """ - warnings.warn(msg, SetuptoolsDeprecationWarning) + SetuptoolsDeprecationWarning.emit( + "Incompatible `config_settings` passed to build backend.", + f""" + The arguments {bad_args!r} were given via `--global-option`. + Please use `--build-option` instead, + `--global-option` is reserved to flags like `--verbose` or `--quiet`. + """, + due_date=(2023, 8, 11), # Warning introduced in v64.0.1, 11/Aug/2022. + ) class _BuildMetaBackend(_ConfigSettingsTranslator): From c14e9d4d76b9921fa480dd6cbb4c23be11e6ce5f Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:06:59 +0000 Subject: [PATCH 09/46] Use new warnings in setuptools/command/bdist_rpm.py --- setuptools/command/bdist_rpm.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/setuptools/command/bdist_rpm.py b/setuptools/command/bdist_rpm.py index 98bf5dea84..e9e5c1b675 100644 --- a/setuptools/command/bdist_rpm.py +++ b/setuptools/command/bdist_rpm.py @@ -1,7 +1,6 @@ import distutils.command.bdist_rpm as orig -import warnings -from setuptools import SetuptoolsDeprecationWarning +from ..warnings import SetuptoolsDeprecationWarning class bdist_rpm(orig.bdist_rpm): @@ -14,10 +13,14 @@ class bdist_rpm(orig.bdist_rpm): """ def run(self): - warnings.warn( - "bdist_rpm is deprecated and will be removed in a future " - "version. Use bdist_wheel (wheel packages) instead.", - SetuptoolsDeprecationWarning, + SetuptoolsDeprecationWarning.emit( + "Deprecated command", + """ + bdist_rpm is deprecated and will be removed in a future version. + Use bdist_wheel (wheel packages) instead. + """, + see_url="https://github.com/pypa/setuptools/issues/1988", + due_date=(2023, 10, 22) # Deprecation introduced in 22 Oct 2021. ) # ensure distro name is up-to-date From c255f063ba1273f6f26d2f55bdec78f2c10e00b4 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:08:05 +0000 Subject: [PATCH 10/46] Use new warnings in setuptools/command/build.py --- setuptools/command/build.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/setuptools/command/build.py b/setuptools/command/build.py index fa3c99ef48..8152658db8 100644 --- a/setuptools/command/build.py +++ b/setuptools/command/build.py @@ -1,9 +1,8 @@ import sys -import warnings from typing import TYPE_CHECKING, List, Dict from distutils.command.build import build as _build -from setuptools import SetuptoolsDeprecationWarning +from ..warnings import SetuptoolsDeprecationWarning if sys.version_info >= (3, 8): from typing import Protocol @@ -23,12 +22,16 @@ class build(_build): def get_sub_commands(self): subcommands = {cmd[0] for cmd in _build.sub_commands} if subcommands - _ORIGINAL_SUBCOMMANDS: - msg = """ - It seems that you are using `distutils.command.build` to add - new subcommands. Using `distutils` directly is considered deprecated, - please use `setuptools.command.build`. - """ - warnings.warn(msg, SetuptoolsDeprecationWarning) + SetuptoolsDeprecationWarning.emit( + "Directly usage of `distutils` commands", + """ + It seems that you are using `distutils.command.build` to add + new subcommands. Using `distutils` directly is considered deprecated, + please use `setuptools.command.build`. + """, + due_date=(2023, 12, 13), # Warning introduced in 13 Jun 2022. + see_url="https://peps.python.org/pep-0632/", + ) self.sub_commands = _build.sub_commands return super().get_sub_commands() From 79f66877d3712ecb1de1bbe3fd926e1a0db09624 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:31:22 +0000 Subject: [PATCH 11/46] Use new warnings in setuptools/command/build_py.py --- setuptools/command/build_py.py | 72 +++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 14094f8d3d..ccabc7b703 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -9,12 +9,11 @@ import distutils.errors import itertools import stat -import warnings from pathlib import Path from typing import Dict, Iterable, Iterator, List, Optional, Tuple -from setuptools.warnings import SetuptoolsDeprecationWarning -from setuptools.extern.more_itertools import unique_everseen +from ..extern.more_itertools import unique_everseen +from ..warnings import SetuptoolsDeprecationWarning def make_writable(target): @@ -325,28 +324,48 @@ def assert_relative(path): class _IncludePackageDataAbuse: """Inform users that package or module is included as 'data file'""" - MESSAGE = """\ - Installing {importable!r} as data is deprecated, please list it in `packages`. - !!\n\n - ############################ - # Package would be ignored # - ############################ - Python recognizes {importable!r} as an importable package, - but it is not listed in the `packages` configuration of setuptools. - - {importable!r} has been automatically added to the distribution only - because it may contain data files, but this behavior is likely to change - in future versions of setuptools (and therefore is considered deprecated). - - Please make sure that {importable!r} is included as a package by using - the `packages` configuration field or the proper discovery methods - (for example by using `find_namespace_packages(...)`/`find_namespace:` - instead of `find_packages(...)`/`find:`). - - You can read more about "package discovery" and "data files" on setuptools - documentation page. - \n\n!! - """ + class _Warning(SetuptoolsDeprecationWarning): + _SUMMARY = """ + Package {importable!r} is absent from the `packages` configuration. + """ + + _DETAILS = """ + ############################ + # Package would be ignored # + ############################ + Python recognizes {importable!r} as an importable package[^1], + but it is absent from setuptools' `packages` configuration. + + This leads to an ambiguous overall configuration. If you want distribute this + package, please make sure that {importable!r} is explicitly added + the `packages` configuration field. + + Alternatively, you can also rely on setuptools' discovery methods + (for example by using `find_namespace_packages(...)`/`find_namespace:` + instead of `find_packages(...)`/`find:`). + + You can read more about "package discovery" on setuptools documentation page: + + - https://setuptools.pypa.io/en/latest/userguide/package_discovery.html + + If you don't want {importable!r} to be distributed and are + already explicitly excluding {importable!r} via + `find_namespace_packages(...)/find_namespace` or `find_packages(...)/find`, + you can try to use `exclude_package_data`, or `include-package-data=False` in + combination with a more fine grained `package-data` configuration. + + You can read more about "package data files" on setuptools documentation page: + + - https://setuptools.pypa.io/en/latest/userguide/datafiles.html + + + [^1]: For Python, any directory (with suitable naming) can be imported, + even if it does not contain any `.py` files. + On the other hand, currently there is no concept of package data + directory, all directories are treated like packages. + """ + # _DUE_DATE: still not defined as this is particularly controversial. + # Warning initially introduced in May 2022. See issue #3340 for discussion. def __init__(self): self._already_warned = set() @@ -363,6 +382,5 @@ def importable_subpackage(self, parent, file): def warn(self, importable): if importable not in self._already_warned: - msg = textwrap.dedent(self.MESSAGE).format(importable=importable) - warnings.warn(msg, SetuptoolsDeprecationWarning, stacklevel=2) + self._Warning.emit(importable=importable) self._already_warned.add(importable) From 813b2d03a7073b632e9e63169e0b6ab99c0c156f Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:33:44 +0000 Subject: [PATCH 12/46] Use new warnings in setuptools/command/dist_info.py --- setuptools/command/dist_info.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setuptools/command/dist_info.py b/setuptools/command/dist_info.py index 64aec5c066..69d331fb88 100644 --- a/setuptools/command/dist_info.py +++ b/setuptools/command/dist_info.py @@ -6,7 +6,6 @@ import os import shutil import sys -import warnings from contextlib import contextmanager from distutils import log from distutils.core import Command @@ -51,7 +50,9 @@ def initialize_options(self): def finalize_options(self): if self.egg_base: msg = "--egg-base is deprecated for dist_info command. Use --output-dir." - warnings.warn(msg, SetuptoolsDeprecationWarning) + SetuptoolsDeprecationWarning.emit(msg, due_date=(2023, 8, 23)) + # This command is internal to setuptools, therefore it should be safe + # to remove the deprecated support soon. self.output_dir = self.egg_base or self.output_dir dist = self.distribution From 9fca13b3621663471352b601a8fac1dba96b7c16 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:36:41 +0000 Subject: [PATCH 13/46] Use new warnings in setuptools/command/easy_install.py --- setuptools/command/easy_install.py | 33 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 444d3b3311..ab717cd896 100644 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -44,8 +44,6 @@ from sysconfig import get_path -from setuptools import SetuptoolsDeprecationWarning - from setuptools import Command from setuptools.sandbox import run_setup from setuptools.command import setopt @@ -54,6 +52,7 @@ PackageIndex, parse_requirement_arg, URL_SCHEME, ) from setuptools.command import bdist_egg, egg_info +from setuptools.warnings import SetuptoolsDeprecationWarning, SetuptoolsWarning from setuptools.wheel import Wheel from pkg_resources import ( normalize_path, resource_string, @@ -141,11 +140,7 @@ class easy_install(Command): create_index = PackageIndex def initialize_options(self): - warnings.warn( - "easy_install command is deprecated. " - "Use build and pip and other standards-based tools.", - EasyInstallDeprecationWarning, - ) + EasyInstallDeprecationWarning.emit() # the --user option seems to be an opt-in one, # so the default should be False. @@ -2094,7 +2089,8 @@ def importlib_load_entry_point(spec, group, name): @classmethod def get_script_args(cls, dist, executable=None, wininst=False): # for backward compatibility - warnings.warn("Use get_args", EasyInstallDeprecationWarning) + EasyInstallDeprecationWarning.emit("Use get_args", due_date=(2023, 6, 1)) + # This is a direct API call, it should be safe to remove soon. writer = (WindowsScriptWriter if wininst else ScriptWriter).best() header = cls.get_script_header("", executable, wininst) return writer.get_args(dist, header) @@ -2102,8 +2098,8 @@ def get_script_args(cls, dist, executable=None, wininst=False): @classmethod def get_script_header(cls, script_text, executable=None, wininst=False): # for backward compatibility - warnings.warn( - "Use get_header", EasyInstallDeprecationWarning, stacklevel=2) + EasyInstallDeprecationWarning.emit("Use get_header", due_date=(2023, 6, 1)) + # This is a direct API call, it should be safe to remove soon. if wininst: executable = "python.exe" return cls.get_header(script_text, executable) @@ -2138,7 +2134,8 @@ def _ensure_safe_name(name): @classmethod def get_writer(cls, force_windows): # for backward compatibility - warnings.warn("Use best", EasyInstallDeprecationWarning) + EasyInstallDeprecationWarning.emit("Use best", due_date=(2023, 6, 1)) + # This is a direct API call, it should be safe to remove soon. return WindowsScriptWriter.best() if force_windows else cls.best() @classmethod @@ -2170,7 +2167,8 @@ class WindowsScriptWriter(ScriptWriter): @classmethod def get_writer(cls): # for backward compatibility - warnings.warn("Use best", EasyInstallDeprecationWarning) + EasyInstallDeprecationWarning.emit("Use best", due_date=(2023, 6, 1)) + # This is a direct API call, it should be safe to remove soon. return cls.best() @classmethod @@ -2195,7 +2193,7 @@ def _get_script_args(cls, type_, name, header, script_text): "{ext} not listed in PATHEXT; scripts will not be " "recognized as executables." ).format(**locals()) - warnings.warn(msg, UserWarning) + SetuptoolsWarning.emit(msg) old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe'] old.remove(ext) header = cls._adjust_header(type_, header) @@ -2307,6 +2305,11 @@ def only_strs(values): class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning): + _SUMMARY = "easy_install command is deprecated." + _DETAILS = """ + Please avoid running ``setup.py`` and ``easy_install``. + Instead, use pypa/build, pypa/installer, pypa/build or + other standards-based tools. """ - Warning for EasyInstall deprecations, bypassing suppression. - """ + _SEE_URL = "https://github.com/pypa/setuptools/issues/917" + # _DUE_DATE not defined yet From 96cc07cb149ae32994b1742592665085b06a6eb9 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:43:51 +0000 Subject: [PATCH 14/46] Use new warnings in setuptools/command/editable_wheel.py --- setuptools/command/editable_wheel.py | 131 ++++++++++++++------------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/setuptools/command/editable_wheel.py b/setuptools/command/editable_wheel.py index 6fddf03d61..fc0f4c569e 100644 --- a/setuptools/command/editable_wheel.py +++ b/setuptools/command/editable_wheel.py @@ -15,7 +15,6 @@ import shutil import sys import traceback -import warnings from contextlib import suppress from enum import Enum from inspect import cleandoc @@ -37,7 +36,6 @@ from .. import ( Command, - SetuptoolsDeprecationWarning, _normalization, _path, errors, @@ -45,6 +43,11 @@ ) from ..discovery import find_package_path from ..dist import Distribution +from ..warnings import ( + InformationOnly, + SetuptoolsDeprecationWarning, + SetuptoolsWarning, +) from .build_py import build_py as build_py_cls if TYPE_CHECKING: @@ -84,16 +87,21 @@ def convert(cls, mode: Optional[str]) -> "_EditableMode": raise errors.OptionError(f"Invalid editable mode: {mode!r}. Try: 'strict'.") if _mode == "COMPAT": - msg = """ - The 'compat' editable mode is transitional and will be removed - in future versions of `setuptools`. - Please adapt your code accordingly to use either the 'strict' or the - 'lenient' modes. - - For more information, please check: - https://setuptools.pypa.io/en/latest/userguide/development_mode.html - """ - warnings.warn(msg, SetuptoolsDeprecationWarning) + SetuptoolsDeprecationWarning.emit( + "Compat editable installs", + """ + The 'compat' editable mode is transitional and will be removed + in future versions of `setuptools`. + Please adapt your code accordingly to use either the 'strict' or the + 'lenient' modes. + """, + see_docs="userguide/development_mode.html", + # TODO: define due_date + # There is a series of shortcomings with the available editable install + # methods, and they are very controversial. This is something that still + # needs work. + # Moreover, `pip` is still hiding this warning, so users are not aware. + ) return _EditableMode[_mode] @@ -148,7 +156,7 @@ def run(self): except Exception: traceback.print_exc() project = self.distribution.name or self.distribution.get_name() - _DebuggingTips.warn(project) + _DebuggingTips.emit(project=project) raise def _ensure_dist_info(self): @@ -289,21 +297,29 @@ def _safely_run(self, cmd_name: str): try: return self.run_command(cmd_name) except Exception: - msg = f"""{traceback.format_exc()}\n - If you are seeing this warning it is very likely that a setuptools - plugin or customization overrides the `{cmd_name}` command, without - taking into consideration how editable installs run build steps - starting from v64.0.0. - - Plugin authors and developers relying on custom build steps are encouraged - to update their `{cmd_name}` implementation considering the information in - https://setuptools.pypa.io/en/latest/userguide/extension.html - about editable installs. - - For the time being `setuptools` will silence this error and ignore - the faulty command, but this behaviour will change in future versions.\n - """ - warnings.warn(msg, SetuptoolsDeprecationWarning, stacklevel=2) + SetuptoolsDeprecationWarning.emit( + "Customization incompatible with editable install", + f""" + {traceback.format_exc()} + + If you are seeing this warning it is very likely that a setuptools + plugin or customization overrides the `{cmd_name}` command, without + taking into consideration how editable installs run build steps + starting from v64.0.0. + + Plugin authors and developers relying on custom build steps are + encouraged to update their `{cmd_name}` implementation considering the + information about editable installs in + https://setuptools.pypa.io/en/latest/userguide/extension.html. + + For the time being `setuptools` will silence this error and ignore + the faulty command, but this behaviour will change in future versions. + """, + # TODO: define due_date + # There is a series of shortcomings with the available editable install + # methods, and they are very controversial. This is something that still + # needs work. + ) def _create_wheel_file(self, bdist_wheel): from wheel.wheelfile import WheelFile @@ -468,7 +484,7 @@ def __exit__(self, _exc_type, _exc_value, _traceback): Please be careful to not remove this directory, otherwise you might not be able to import/use your package. """ - warnings.warn(msg, InformationOnly) + InformationOnly.emit("Editable installation.", msg) class _TopLevelFinder: @@ -505,7 +521,7 @@ def __exit__(self, _exc_type, _exc_value, _traceback): Please be careful with folders in your working directory with the same name as your package as they may take precedence during imports. """ - warnings.warn(msg, InformationOnly) + InformationOnly.emit("Editable installation.", msg) def _can_symlink_files(base_dir: Path) -> bool: @@ -811,46 +827,31 @@ def _finder_template( return _FINDER_TEMPLATE.format(name=name, mapping=mapping, namespaces=namespaces) -class InformationOnly(UserWarning): - """Currently there is no clear way of displaying messages to the users - that use the setuptools backend directly via ``pip``. - The only thing that might work is a warning, although it is not the - most appropriate tool for the job... - """ - - class LinksNotSupported(errors.FileError): """File system does not seem to support either symlinks or hard links.""" -class _DebuggingTips(InformationOnly): - @classmethod - def warn(cls, project: str): - msg = f"""An error happened while installing {project!r} in editable mode. - - ************************************************************************ - The following steps are recommended to help debugging this problem: +class _DebuggingTips(SetuptoolsWarning): + _SUMMARY = "Problem in editable installation." + _DETAILS = """ + An error happened while installing `{project}` in editable mode. - - Try to install the project normally, without using the editable mode. - Does the error still persists? - (If it does, try fixing the problem before attempting the editable mode). - - If you are using binary extensions, make sure you have all OS-level - dependencies installed (e.g. compilers, toolchains, binary libraries, ...). - - Try the latest version of setuptools (maybe the error was already fixed). - - If you (or your project dependencies) are using any setuptools extension - or customization, make sure they support the editable mode. + The following steps are recommended to help debugging this problem: - After following the steps above, if the problem still persist and - you think this is related to how setuptools handles editable installations, - please submit a reproducible example - (see https://stackoverflow.com/help/minimal-reproducible-example) to: + - Try to install the project normally, without using the editable mode. + Does the error still persists? + (If it does, try fixing the problem before attempting the editable mode). + - If you are using binary extensions, make sure you have all OS-level + dependencies installed (e.g. compilers, toolchains, binary libraries, ...). + - Try the latest version of setuptools (maybe the error was already fixed). + - If you (or your project dependencies) are using any setuptools extension + or customization, make sure they support the editable mode. - https://github.com/pypa/setuptools/issues + After following the steps above, if the problem still persist and + you think this is related to how setuptools handles editable installations, + please submit a reproducible example + (see https://stackoverflow.com/help/minimal-reproducible-example) to: - More information about editable installs can be found in the docs: - - https://setuptools.pypa.io/en/latest/userguide/development_mode.html - ************************************************************************ - """ - # We cannot use `add_notes` since pip hides PEP 678 notes - warnings.warn(msg, cls, stacklevel=2) + https://github.com/pypa/setuptools/issues + """ + _SEE_DOCS = "userguide/development_mode.html" From 96b950bb23066adcda8cb38e3953cc851d6d4c6e Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:49:03 +0000 Subject: [PATCH 15/46] Use new warnings in setuptools/command/egg_info.py --- setuptools/command/egg_info.py | 52 ++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index e40df9bba7..8063cea642 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -13,7 +13,6 @@ import re import sys import io -import warnings import time import collections @@ -30,7 +29,7 @@ from setuptools.extern import packaging from setuptools.extern.jaraco.text import yield_lines -from setuptools import SetuptoolsDeprecationWarning +from ..warnings import SetuptoolsDeprecationWarning PY_MAJOR = '{}.{}'.format(*sys.version_info) @@ -331,12 +330,16 @@ def check_broken_egg_info(self): if self.egg_base != os.curdir: bei = os.path.join(self.egg_base, bei) if os.path.exists(bei): - log.warn( - "-" * 78 + '\n' - "Note: Your current .egg-info directory has a '-' in its name;" - '\nthis will not work correctly with "setup.py develop".\n\n' - 'Please rename %s to %s to correct this problem.\n' + '-' * 78, - bei, self.egg_info + EggInfoDeprecationWarning.emit( + "Invalid egg-info directory name.", + f""" + Your current .egg-info directory has a '-' in its name; + this will not work correctly with setuptools commands. + + Please rename {bei!r} to {self.egg_info!r} to correct this problem. + """, + due_date=(2023, 9, 1), + # Old warning, introduced in 2005, might be safe to remove soon ) self.broken_egg_info = self.egg_info self.egg_info = bei # make it work for now @@ -658,11 +661,14 @@ def _safe_data_files(self, build_py): if hasattr(build_py, 'get_data_files_without_manifest'): return build_py.get_data_files_without_manifest() - warnings.warn( - "Custom 'build_py' does not implement " - "'get_data_files_without_manifest'.\nPlease extend command classes" - " from setuptools instead of distutils.", - SetuptoolsDeprecationWarning + SetuptoolsDeprecationWarning.emit( + "`build_py` command does not inherit from setuptools' `build_py`.", + """ + Custom 'build_py' does not implement 'get_data_files_without_manifest'. + Please extend command classes from setuptools instead of distutils. + """, + see_url="https://peps.python.org/pep-0632/", + # due_date not defined yet, old projects might still do it? ) return build_py.get_data_files() @@ -701,9 +707,15 @@ def write_pkg_info(cmd, basename, filename): def warn_depends_obsolete(cmd, basename, filename): if os.path.exists(filename): - log.warn( - "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" - "Use the install_requires/extras_require setup() args instead." + EggInfoDeprecationWarning.emit( + "Deprecated config.", + """ + 'depends.txt' is not used by setuptools >= 0.6! + Configure your dependencies via `setup.cfg` or `pyproject.toml` instead. + """, + see_docs="userguide/declarative_config.html", + due_date=(2023, 9, 1), + # Old warning, introduced in 2005, it might be safe to remove soon. ) @@ -766,8 +778,12 @@ def get_pkg_info_revision(): Get a -r### off of PKG-INFO Version in case this is an sdist of a subversion revision. """ - warnings.warn( - "get_pkg_info_revision is deprecated.", EggInfoDeprecationWarning) + EggInfoDeprecationWarning.emit( + "Deprecated API call", + "get_pkg_info_revision is deprecated.", + due_date=(2023, 6, 1), + # Warning introduced in 11 Dec 2015, should be safe to remove + ) if os.path.exists('PKG-INFO'): with io.open('PKG-INFO') as f: for line in f: From cf710b602f098ed28c16e5e05fd17e7ecefdf0f5 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:50:39 +0000 Subject: [PATCH 16/46] Use new warnings in setuptools/command/install.py --- setuptools/command/install.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/setuptools/command/install.py b/setuptools/command/install.py index 55fdb124e8..dec4e32018 100644 --- a/setuptools/command/install.py +++ b/setuptools/command/install.py @@ -1,11 +1,11 @@ from distutils.errors import DistutilsArgError import inspect import glob -import warnings import platform import distutils.command.install as orig import setuptools +from ..warnings import SetuptoolsDeprecationWarning, SetuptoolsWarning # Prior to numpy 1.9, NumPy relies on the '_install' name, so provide it for # now. See https://github.com/pypa/setuptools/issues/199/ @@ -30,11 +30,17 @@ class install(orig.install): _nc = dict(new_commands) def initialize_options(self): - - warnings.warn( - "setup.py install is deprecated. " - "Use build and pip and other standards-based tools.", - setuptools.SetuptoolsDeprecationWarning, + SetuptoolsDeprecationWarning.emit( + "setup.py install is deprecated.", + """ + Please avoid running ``setup.py`` directly. + Instead, use pypa/build, pypa/installer, pypa/build or + other standards-based tools. + """, + see_url="https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html", + # TODO: Document how to bootstrap setuptools without install + # (e.g. by unziping the wheel file) + # and then add a due_date to this warning. ) orig.install.initialize_options(self) @@ -86,10 +92,10 @@ def _called_from_setup(run_frame): """ if run_frame is None: msg = "Call stack not available. bdist_* commands may fail." - warnings.warn(msg) + SetuptoolsWarning.emit(msg) if platform.python_implementation() == 'IronPython': msg = "For best results, pass -X:Frames to enable call stack." - warnings.warn(msg) + SetuptoolsWarning.emit(msg) return True frames = inspect.getouterframes(run_frame) From a74b355ca666dc850557c99bebce65df4abc06a1 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:52:55 +0000 Subject: [PATCH 17/46] Use new warnings in setuptools/command/upload_docs.py --- setuptools/command/upload_docs.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/setuptools/command/upload_docs.py b/setuptools/command/upload_docs.py index 63eb28c70c..dddde60910 100644 --- a/setuptools/command/upload_docs.py +++ b/setuptools/command/upload_docs.py @@ -16,10 +16,9 @@ import functools import http.client import urllib.parse -import warnings from .._importlib import metadata -from .. import SetuptoolsDeprecationWarning +from ..warnings import SetuptoolsDeprecationWarning from .upload import upload @@ -91,10 +90,14 @@ def create_zipfile(self, filename): zip_file.close() def run(self): - warnings.warn( - "upload_docs is deprecated and will be removed in a future " - "version. Use tools like httpie or curl instead.", - SetuptoolsDeprecationWarning, + SetuptoolsDeprecationWarning.emit( + "Deprecated command", + """ + upload_docs is deprecated and will be removed in a future version. + Instead, use tools like devpi and Read the Docs; or lower level tools like + httpie and curl to interact directly with your hosting service API. + """, + due_date=(2023, 9, 27), # warning introduced in 27 Jul 2022 ) # Run sub commands From 80af34e07dadaa2f43a21d6337af0d2e6f8fe143 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:55:23 +0000 Subject: [PATCH 18/46] Use new warnings in setuptools/config/__init__.py --- setuptools/config/__init__.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/setuptools/config/__init__.py b/setuptools/config/__init__.py index d411aadd21..ffea394436 100644 --- a/setuptools/config/__init__.py +++ b/setuptools/config/__init__.py @@ -1,9 +1,7 @@ """For backward compatibility, expose main functions from ``setuptools.config.setupcfg`` """ -import warnings from functools import wraps -from textwrap import dedent from typing import Callable, TypeVar, cast from ..warnings import SetuptoolsDeprecationWarning @@ -17,15 +15,24 @@ def _deprecation_notice(fn: Fn) -> Fn: @wraps(fn) def _wrapper(*args, **kwargs): - msg = f"""\ - As setuptools moves its configuration towards `pyproject.toml`, - `{__name__}.{fn.__name__}` became deprecated. - - For the time being, you can use the `{setupcfg.__name__}` module - to access a backward compatible API, but this module is provisional - and might be removed in the future. - """ - warnings.warn(dedent(msg), SetuptoolsDeprecationWarning, stacklevel=2) + SetuptoolsDeprecationWarning.emit( + "Deprecated API usage.", + f""" + As setuptools moves its configuration towards `pyproject.toml`, + `{__name__}.{fn.__name__}` became deprecated. + + For the time being, you can use the `{setupcfg.__name__}` module + to access a backward compatible API, but this module is provisional + and might be removed in the future. + + To read project metadata, consider using + ``build.util.project_wheel_metadata`` (https://pypi.org/project/build/). + For simple scenarios, you can also try parsing the file directly + with the help of ``configparser``. + """, + # due_date not defined yet, because the community still heavily relies on it + # Warning introduced in 24 Mar 2022 + ) return fn(*args, **kwargs) return cast(Fn, _wrapper) From b776e31badf591abab9cc7110383e830fe40ba5d Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:58:20 +0000 Subject: [PATCH 19/46] Use new warnings in setuptools/config/_apply_pyprojecttoml.py --- setuptools/config/_apply_pyprojecttoml.py | 38 +++++++++---------- .../tests/config/test_apply_pyprojecttoml.py | 2 +- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/setuptools/config/_apply_pyprojecttoml.py b/setuptools/config/_apply_pyprojecttoml.py index f792521c24..4556019eb4 100644 --- a/setuptools/config/_apply_pyprojecttoml.py +++ b/setuptools/config/_apply_pyprojecttoml.py @@ -9,7 +9,6 @@ """ import logging import os -import warnings from collections.abc import Mapping from email.headerregistry import Address from functools import partial, reduce @@ -18,7 +17,7 @@ from typing import (TYPE_CHECKING, Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union, cast) -from setuptools.warnings import SetuptoolsDeprecationWarning +from ..warnings import SetuptoolsWarning, SetuptoolsDeprecationWarning if TYPE_CHECKING: from setuptools._importlib import metadata # noqa @@ -81,9 +80,11 @@ def _apply_tool_table(dist: "Distribution", config: dict, filename: _Path): norm_key = json_compatible_key(field) if norm_key in TOOL_TABLE_DEPRECATIONS: - suggestion = TOOL_TABLE_DEPRECATIONS[norm_key] + suggestion, kwargs = TOOL_TABLE_DEPRECATIONS[norm_key] msg = f"The parameter `{norm_key}` is deprecated, {suggestion}" - warnings.warn(msg, SetuptoolsDeprecationWarning) + SetuptoolsDeprecationWarning.emit( + "Deprecated config", msg, **kwargs # type: ignore + ) norm_key = TOOL_TABLE_RENAMES.get(norm_key, norm_key) _set_config(dist, norm_key, value) @@ -99,8 +100,7 @@ def _handle_missing_dynamic(dist: "Distribution", project_table: dict): if not (field in project_table or field in dynamic): value = getter(dist) if value: - msg = _WouldIgnoreField.message(field, value) - warnings.warn(msg, _WouldIgnoreField) + _WouldIgnoreField.emit(field=field, value=value) def json_compatible_key(key: str) -> str: @@ -200,7 +200,7 @@ def _python_requires(dist: "Distribution", val: dict, _root_dir): def _dependencies(dist: "Distribution", val: list, _root_dir): if getattr(dist, "install_requires", []): msg = "`install_requires` overwritten in `pyproject.toml` (dependencies)" - warnings.warn(msg) + SetuptoolsWarning.emit(msg) _set_config(dist, "install_requires", val) @@ -325,7 +325,10 @@ def _acessor(obj): TOOL_TABLE_RENAMES = {"script_files": "scripts"} TOOL_TABLE_DEPRECATIONS = { - "namespace_packages": "consider using implicit namespaces instead (PEP 420)." + "namespace_packages": ( + "consider using implicit namespaces instead (PEP 420).", + {"due_date": (2023, 10, 15)}, # warning introduced in May 2022 + ) } SETUPTOOLS_PATCHES = {"long_description_content_type", "project_urls", @@ -349,12 +352,10 @@ def _acessor(obj): } -class _WouldIgnoreField(UserWarning): - """Inform users that ``pyproject.toml`` would overwrite previous metadata.""" +class _WouldIgnoreField(SetuptoolsDeprecationWarning): + _SUMMARY = "`{field}` defined outside of `pyproject.toml` would be ignored." - MESSAGE = """\ - {field!r} defined outside of `pyproject.toml` would be ignored. - !!\n\n + _DETAILS = """ ########################################################################## # configuration would be ignored/result in error due to `pyproject.toml` # ########################################################################## @@ -364,7 +365,7 @@ class _WouldIgnoreField(UserWarning): `{field} = {value!r}` According to the spec (see the link below), however, setuptools CANNOT - consider this value unless {field!r} is listed as `dynamic`. + consider this value unless `{field}` is listed as `dynamic`. https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ @@ -372,13 +373,8 @@ class _WouldIgnoreField(UserWarning): **transitional** measure), but please note that future releases of setuptools will follow strictly the standard. - To prevent this warning, you can list {field!r} under `dynamic` or alternatively + To prevent this warning, you can list `{field}` under `dynamic` or alternatively remove the `[project]` table from your file and rely entirely on other means of configuration. - \n\n!! """ - - @classmethod - def message(cls, field, value): - from inspect import cleandoc - return cleandoc(cls.MESSAGE.format(field=field, value=value)) + _DUE_DATE = (2023, 10, 27) # Initially introduced in 27 May 2022 diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py index 8f76f2c99d..03a974d598 100644 --- a/setuptools/tests/config/test_apply_pyprojecttoml.py +++ b/setuptools/tests/config/test_apply_pyprojecttoml.py @@ -15,12 +15,12 @@ from ini2toml.api import Translator import setuptools # noqa ensure monkey patch to metadata -from setuptools.warnings import SetuptoolsDeprecationWarning from setuptools.dist import Distribution from setuptools.config import setupcfg, pyprojecttoml from setuptools.config import expand from setuptools.config._apply_pyprojecttoml import _WouldIgnoreField, _some_attrgetter from setuptools.command.egg_info import write_requirements +from setuptools.warnings import SetuptoolsDeprecationWarning from .downloads import retrieve_file, urls_from_file From 27cfcd126e05b1e5c8413aa57d06df81cebfdeb5 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 20:59:09 +0000 Subject: [PATCH 20/46] Use new warnings in setuptools/config/expand.py --- setuptools/config/expand.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py index c8db2c4b49..309888437d 100644 --- a/setuptools/config/expand.py +++ b/setuptools/config/expand.py @@ -23,7 +23,6 @@ import os import pathlib import sys -import warnings from glob import iglob from configparser import ConfigParser from importlib.machinery import ModuleSpec @@ -48,6 +47,7 @@ from distutils.errors import DistutilsOptionError from .._path import same_path as _same_path +from ..warnings import SetuptoolsWarning if TYPE_CHECKING: from setuptools.dist import Distribution # noqa @@ -141,7 +141,7 @@ def _filter_existing_files(filepaths: Iterable[_Path]) -> Iterator[_Path]: if os.path.isfile(path): yield path else: - warnings.warn(f"File {path!r} cannot be found") + SetuptoolsWarning.emit(f"File {path!r} cannot be found") def _read_file(filepath: Union[bytes, _Path]) -> str: From a05e81ae0cea8ed4b5bf1f43ea82c5af75e4f6e3 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 21:00:40 +0000 Subject: [PATCH 21/46] Use new warnings in setuptools/config/pyprojecttoml.py --- setuptools/config/pyprojecttoml.py | 42 ++++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/setuptools/config/pyprojecttoml.py b/setuptools/config/pyprojecttoml.py index 9ce550222c..c340121cdd 100644 --- a/setuptools/config/pyprojecttoml.py +++ b/setuptools/config/pyprojecttoml.py @@ -2,19 +2,23 @@ Load setuptools configuration from ``pyproject.toml`` files. **PRIVATE MODULE**: API reserved for setuptools internal usage only. + +To read project metadata, consider using +``build.util.project_wheel_metadata`` (https://pypi.org/project/build/). +For simple scenarios, you can also try parsing the file directly +with the help of ``tomllib`` or ``tomli``. """ import logging import os -import warnings from contextlib import contextmanager from functools import partial -from typing import TYPE_CHECKING, Callable, Dict, Optional, Mapping, Set, Union - -from setuptools.errors import FileError, OptionError +from typing import TYPE_CHECKING, Callable, Dict, Mapping, Optional, Set, Union +from ..errors import FileError, OptionError +from ..warnings import SetuptoolsWarning from . import expand as _expand -from ._apply_pyprojecttoml import apply as _apply from ._apply_pyprojecttoml import _PREVIOUSLY_DEFINED, _WouldIgnoreField +from ._apply_pyprojecttoml import apply as _apply if TYPE_CHECKING: from setuptools.dist import Distribution # noqa @@ -104,8 +108,7 @@ def read_configuration( if setuptools_table: # TODO: Remove the following once the feature stabilizes: - msg = "Support for `[tool.setuptools]` in `pyproject.toml` is still *beta*." - warnings.warn(msg, _BetaConfiguration) + _BetaConfiguration.emit() # There is an overall sense in the community that making include_package_data=True # the default would be an improvement. @@ -166,7 +169,7 @@ def _skip_bad_config( # It seems that the docs in cibuildtool has been inadvertently encouraging users # to create `pyproject.toml` files that are not compliant with the standards. # Let's be forgiving for the time being. - warnings.warn(_InvalidFile.message(), _InvalidFile, stacklevel=2) + _InvalidFile.emit() return True return False @@ -369,8 +372,7 @@ def _set_scripts(field: str, group: str): if group in groups: value = groups.pop(group) if field not in self.dynamic: - msg = _WouldIgnoreField.message(field, value) - warnings.warn(msg, _WouldIgnoreField) + _WouldIgnoreField.emit(field=field, value=value) # TODO: Don't set field when support for pyproject.toml stabilizes # instead raise an error as specified in PEP 621 expanded[field] = value @@ -472,13 +474,13 @@ def __exit__(self, exc_type, exc_value, traceback): return super().__exit__(exc_type, exc_value, traceback) -class _BetaConfiguration(UserWarning): - """Explicitly inform users that some `pyproject.toml` configuration is *beta*""" +class _BetaConfiguration(SetuptoolsWarning): + _SUMMARY = "Support for `[tool.setuptools]` in `pyproject.toml` is still *beta*." -class _InvalidFile(UserWarning): - """The given `pyproject.toml` file is invalid and would be ignored. - !!\n\n +class _InvalidFile(SetuptoolsWarning): + _SUMMARY = "The given `pyproject.toml` file is invalid and would be ignored." + _DETAILS = """ ############################ # Invalid `pyproject.toml` # ############################ @@ -488,11 +490,7 @@ class _InvalidFile(UserWarning): if an invalid file is given. To prevent setuptools from considering `pyproject.toml` please - DO NOT include the `[project]` or `[tool.setuptools]` tables in your file. - \n\n!! + DO NOT include both `[project]` or `[tool.setuptools]` tables in your file. """ - - @classmethod - def message(cls): - from inspect import cleandoc - return cleandoc(cls.__doc__) + _DUE_DATE = (2023, 4, 26) # warning introduced in 2022-03-26 + _SEE_DOCS = "userguide/pyproject_config.html" From 93c4862e2274fff7263937ce4175380b14e30cf5 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 21:04:32 +0000 Subject: [PATCH 22/46] Use new warnings in setuptools/config/setupcfg.py --- setuptools/config/setupcfg.py | 93 +++++++++++++++--------- setuptools/tests/config/test_setupcfg.py | 24 +++--- 2 files changed, 66 insertions(+), 51 deletions(-) diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py index 8c0dcc61a4..050e538560 100644 --- a/setuptools/config/setupcfg.py +++ b/setuptools/config/setupcfg.py @@ -2,12 +2,15 @@ Load setuptools configuration from ``setup.cfg`` files. **API will be made private in the future** -""" -import os +To read project metadata, consider using +``build.util.project_wheel_metadata`` (https://pypi.org/project/build/). +For simple scenarios, you can also try parsing the file directly +with the help of ``configparser``. +""" import contextlib import functools -import warnings +import os from collections import defaultdict from functools import partial from functools import wraps @@ -26,19 +29,19 @@ Union, ) -from distutils.errors import DistutilsOptionError, DistutilsFileError -from setuptools.extern.packaging.requirements import Requirement, InvalidRequirement -from setuptools.extern.packaging.markers import default_environment as marker_env -from setuptools.extern.packaging.version import Version, InvalidVersion -from setuptools.extern.packaging.specifiers import SpecifierSet -from setuptools.warnings import SetuptoolsDeprecationWarning - +from ..errors import FileError, OptionError +from ..extern.packaging.markers import default_environment as marker_env +from ..extern.packaging.requirements import InvalidRequirement, Requirement +from ..extern.packaging.specifiers import SpecifierSet +from ..extern.packaging.version import InvalidVersion, Version +from ..warnings import SetuptoolsDeprecationWarning from . import expand if TYPE_CHECKING: - from setuptools.dist import Distribution # noqa from distutils.dist import DistributionMetadata # noqa + from setuptools.dist import Distribution # noqa + _Path = Union[str, os.PathLike] SingleCommandOptions = Dict["str", Tuple["str", Any]] """Dict that associate the name of the options of a particular command to a @@ -97,7 +100,7 @@ def _apply( filepath = os.path.abspath(filepath) if not os.path.isfile(filepath): - raise DistutilsFileError('Configuration file %s does not exist.' % filepath) + raise FileError(f'Configuration file {filepath} does not exist.') current_directory = os.getcwd() os.chdir(os.path.dirname(filepath)) @@ -121,7 +124,7 @@ def _get_option(target_obj: Target, key: str): the target object, either through a get_{key} method or from an attribute directly. """ - getter_name = 'get_{key}'.format(**locals()) + getter_name = f'get_{key}' by_attribute = functools.partial(getattr, target_obj, key) getter = getattr(target_obj, getter_name, by_attribute) return getter() @@ -212,19 +215,14 @@ def _warn_accidental_env_marker_misconfig(label: str, orig_value: str, parsed: l return markers = marker_env().keys() - msg = ( - f"One of the parsed requirements in `{label}` " - f"looks like a valid environment marker: '{parsed[1]}'\n" - "Make sure that the config is correct and check " - "https://setuptools.pypa.io/en/latest/userguide/declarative_config.html#opt-2" # noqa: E501 - ) try: req = Requirement(parsed[1]) if req.name in markers: - warnings.warn(msg) + _AmbiguousMarker.emit(field=label, req=parsed[1]) except InvalidRequirement as ex: if any(parsed[1].startswith(marker) for marker in markers): + msg = _AmbiguousMarker.message(field=label, req=parsed[1]) raise InvalidRequirement(msg) from ex @@ -334,9 +332,7 @@ def _parse_dict(cls, value): for line in cls._parse_list(value): key, sep, val = line.partition(separator) if sep != separator: - raise DistutilsOptionError( - 'Unable to parse option value to dict: %s' % value - ) + raise OptionError(f"Unable to parse option value to dict: {value}") result[key.strip()] = val.strip() return result @@ -496,24 +492,24 @@ def parse(self): ) if section_parser_method is None: - raise DistutilsOptionError( - 'Unsupported distribution option section: [%s.%s]' - % (self.section_prefix, section_name) + raise OptionError( + "Unsupported distribution option section: " + f"[{self.section_prefix}.{section_name}]" ) section_parser_method(section_options) - def _deprecated_config_handler(self, func, msg, warning_class): + def _deprecated_config_handler(self, func, msg, **kw): """this function will wrap around parameters that are deprecated :param msg: deprecation message - :param warning_class: class of warning exception to be raised :param func: function to be wrapped around """ @wraps(func) def config_handler(*args, **kwargs): - warnings.warn(msg, warning_class) + kw.setdefault("stacklevel", 2) + _DeprecatedConfig.emit("Deprecated config in `setup.cfg`", msg, **kw) return func(*args, **kwargs) return config_handler @@ -564,7 +560,8 @@ def parsers(self): parse_list, "The requires parameter is deprecated, please use " "install_requires for runtime dependencies.", - SetuptoolsDeprecationWarning, + due_date=(2023, 10, 30), + # Warning introduced in 27 Oct 2018 ), 'obsoletes': parse_list, 'classifiers': self._get_parser_compound(parse_file, parse_list), @@ -573,7 +570,8 @@ def parsers(self): exclude_files_parser('license_file'), "The license_file parameter is deprecated, " "use license_files instead.", - SetuptoolsDeprecationWarning, + due_date=(2023, 10, 30), + # Warning introduced in 23 May 2021 ), 'license_files': parse_list, 'description': parse_file, @@ -598,11 +596,10 @@ def _parse_version(self, value): try: Version(version) except InvalidVersion: - tmpl = ( - 'Version loaded from {value} does not ' - 'comply with PEP 440: {version}' + raise OptionError( + f'Version loaded from {value} does not ' + f'comply with PEP 440: {version}' ) - raise DistutilsOptionError(tmpl.format(**locals())) return version @@ -657,7 +654,7 @@ def parsers(self): parse_list, "The namespace_packages parameter is deprecated, " "consider using implicit namespaces instead (PEP 420).", - SetuptoolsDeprecationWarning, + # TODO: define due date, see setuptools.dist:check_nsp. ), 'install_requires': partial( self._parse_requirements_list, "install_requires" @@ -766,3 +763,27 @@ def parse_section_data_files(self, section_options): """ parsed = self._parse_section_to_dict(section_options, self._parse_list) self['data_files'] = expand.canonic_data_files(parsed, self.root_dir) + + +class _AmbiguousMarker(SetuptoolsDeprecationWarning): + _SUMMARY = "Ambiguous requirement marker." + _DETAILS = """ + One of the parsed requirements in `{field}` looks like a valid environment marker: + + {req!r} + + Please make sure that the configuration file is correct. + You can use dangling lines to avoid this problem. + """ + _SEE_DOCS = "userguide/declarative_config.html#opt-2" + # TODO: should we include due_date here? Initially introduced in 6 Aug 2022. + # Does this make sense with latest version of packaging? + + @classmethod + def message(cls, **kw): + docs = f"https://setuptools.pypa.io/en/latest/{cls._SEE_DOCS}" + return cls._format(cls._SUMMARY, cls._DETAILS, see_url=docs, format_args=kw) + + +class _DeprecatedConfig(SetuptoolsDeprecationWarning): + _SEE_DOCS = "https://setuptools.pypa.io/en/latest/userguide/declarative_config.html" diff --git a/setuptools/tests/config/test_setupcfg.py b/setuptools/tests/config/test_setupcfg.py index 97207829df..69b75a89fb 100644 --- a/setuptools/tests/config/test_setupcfg.py +++ b/setuptools/tests/config/test_setupcfg.py @@ -7,10 +7,10 @@ import pytest from distutils.errors import DistutilsOptionError, DistutilsFileError -from setuptools.warnings import SetuptoolsDeprecationWarning from setuptools.dist import Distribution, _Distribution from setuptools.config.setupcfg import ConfigHandler, read_configuration from setuptools.extern.packaging.requirements import InvalidRequirement +from setuptools.warnings import SetuptoolsDeprecationWarning from ..textwrap import DALS @@ -468,12 +468,8 @@ def test_warn_dash_deprecation(self, tmpdir): 'author-email = test@test.com\n' 'maintainer_email = foo@foo.com\n', ) - msg = ( - "Usage of dash-separated 'author-email' will not be supported " - "in future versions. " - "Please use the underscore name 'author_email' instead" - ) - with pytest.warns(UserWarning, match=msg): + msg = "Usage of dash-separated 'author-email' will not be supported" + with pytest.warns(SetuptoolsDeprecationWarning, match=msg): with get_dist(tmpdir) as dist: metadata = dist.metadata @@ -486,12 +482,8 @@ def test_make_option_lowercase(self, tmpdir): fake_env( tmpdir, '[metadata]\n' 'Name = foo\n' 'description = Some description\n' ) - msg = ( - "Usage of uppercase key 'Name' in 'metadata' will be deprecated in " - "future versions. " - "Please use lowercase 'name' instead" - ) - with pytest.warns(UserWarning, match=msg): + msg = "Usage of uppercase key 'Name' in 'metadata' will not be supported" + with pytest.warns(SetuptoolsDeprecationWarning, match=msg): with get_dist(tmpdir) as dist: metadata = dist.metadata @@ -755,7 +747,7 @@ def test_warn_accidental_env_marker_misconfig(self, config, tmpdir): r"One of the parsed requirements in `(install_requires|extras_require.+)` " "looks like a valid environment marker.*" ) - with pytest.warns(UserWarning, match=match): + with pytest.warns(SetuptoolsDeprecationWarning, match=match): with get_dist(tmpdir) as _: pass @@ -774,12 +766,14 @@ def test_warn_accidental_env_marker_misconfig(self, config, tmpdir): "[options]\ninstall_requires =\n bar\n python_version<3\n", ], ) + @pytest.mark.filterwarnings("error::setuptools.SetuptoolsDeprecationWarning") def test_nowarn_accidental_env_marker_misconfig(self, config, tmpdir, recwarn): fake_env(tmpdir, config) + num_warnings = len(recwarn) with get_dist(tmpdir) as _: pass # The examples are valid, no warnings shown - assert not any(w.category == UserWarning for w in recwarn) + assert len(recwarn) == num_warnings def test_dash_preserved_extras_require(self, tmpdir): fake_env(tmpdir, '[options.extras_require]\n' 'foo-a = foo\n' 'foo_b = test\n') From 14c420b67728479d1a2826155210667b5c20c16b Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 21:05:40 +0000 Subject: [PATCH 23/46] Use new warnings in setuptools/dist.py --- setuptools/dist.py | 82 +++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index eb59f3a0a3..6ecb29a19f 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -4,7 +4,6 @@ import sys import re import os -import warnings import numbers import distutils.log import distutils.core @@ -31,10 +30,6 @@ from setuptools.extern import ordered_set from setuptools.extern.more_itertools import unique_everseen, partition -from ._importlib import metadata - -from . import SetuptoolsDeprecationWarning, _normalization - import setuptools import setuptools.command from setuptools import windows_support @@ -45,6 +40,9 @@ from setuptools.extern.packaging import version from . import _reqs from . import _entry_points +from . import _normalization +from ._importlib import metadata +from .warnings import InformationOnly, SetuptoolsDeprecationWarning if TYPE_CHECKING: from email.message import Message @@ -54,7 +52,12 @@ def _get_unpatched(cls): - warnings.warn("Do not call this function", DistDeprecationWarning) + DistDeprecationWarning.emit( + "Private function", + "Do not call this function", + due_date=(2023, 7, 9), + # Warning initially introduced in 2016 + ) return get_unpatched(cls) @@ -156,7 +159,9 @@ def single_line(val): if '\n' in val: # TODO: Replace with `raise ValueError("newlines not allowed")` # after reviewing #2893. - warnings.warn("newlines not allowed and will break in the future") + msg = "newlines are not allowed in `summary` and will break in the future" + SetuptoolsDeprecationWarning.emit("Invalid config.", msg) + # due_date is undefined. Controversial change, there was a lot of push back. val = val.strip().split('\n')[0] return val @@ -278,13 +283,15 @@ def check_nsp(dist, attr, value): nsp, parent, ) - msg = ( - "The namespace_packages parameter is deprecated, " - "consider using implicit namespaces instead (PEP 420). " - "See https://setuptools.pypa.io/en/latest/references/" - "keywords.html#keyword-namespace-packages" + SetuptoolsDeprecationWarning.emit( + "The namespace_packages parameter is deprecated.", + "Please replace its usage with implicit namespaces (PEP 420).", + see_docs="references/keywords.html#keyword-namespace-packages" + # TODO: define due_date, it may break old packages that are no longer + # maintained (e.g. sphinxcontrib extensions) when installed from source. + # Warning officially introduced in May 2022, however the deprecation + # was mentioned much earlier in the docs (May 2020, see #2149). ) - warnings.warn(msg, SetuptoolsDeprecationWarning) def check_extras(dist, attr, value): @@ -325,8 +332,8 @@ def assert_bool(dist, attr, value): def invalid_unless_false(dist, attr, value): if not value: - warnings.warn(f"{attr} is ignored.", DistDeprecationWarning) - return + DistDeprecationWarning.emit(f"{attr} is ignored.") + # TODO: should there be a `due_date` here? raise DistutilsSetupError(f"{attr} is invalid.") @@ -543,8 +550,7 @@ def _normalize_version(version): normalized = str(packaging.version.Version(version)) if version != normalized: - tmpl = "Normalizing '{version}' to '{normalized}'" - warnings.warn(tmpl.format(**locals())) + InformationOnly.emit(f"Normalizing '{version}' to '{normalized}'") return normalized return version @@ -558,11 +564,17 @@ def _validate_version(version): try: packaging.version.Version(version) except (packaging.version.InvalidVersion, TypeError): - warnings.warn( - "The version specified (%r) is an invalid version, this " - "may not work as expected with newer versions of " - "setuptools, pip, and PyPI. Please see PEP 440 for more " - "details." % version + SetuptoolsDeprecationWarning.emit( + f"Invalid version: {version!r}.", + """ + The version specified is not a valid version according to PEP 440. + This may not work as expected with newer versions of + setuptools, pip, and PyPI. + """, + see_url="https://peps.python.org/pep-0440/", + due_date=(2023, 9, 26), + # Warning initially introduced in 26 Sept 2014 + # pypa/packaging already removed legacy versions. ) return setuptools.sic(version) return version @@ -785,10 +797,15 @@ def warn_dash_deprecation(self, opt, section): return underscore_opt if '-' in opt: - warnings.warn( - "Usage of dash-separated '%s' will not be supported in future " - "versions. Please use the underscore name '%s' instead" - % (opt, underscore_opt) + SetuptoolsDeprecationWarning.emit( + "Invalid dash-separated options", + f""" + Usage of dash-separated {opt!r} will not be supported in future + versions. Please use the underscore name {underscore_opt!r} instead. + """, + see_docs="userguide/declarative_config.html", + due_date=(2023, 9, 10), + # Warning initially introduced in 3 Mar 2021 ) return underscore_opt @@ -804,10 +821,15 @@ def make_option_lowercase(self, opt, section): return opt lowercase_opt = opt.lower() - warnings.warn( - "Usage of uppercase key '%s' in '%s' will be deprecated in future " - "versions. Please use lowercase '%s' instead" - % (opt, section, lowercase_opt) + SetuptoolsDeprecationWarning.emit( + "Invalid uppercase configuration", + f""" + Usage of uppercase key {opt!r} in {section!r} will not be supported in + future versions. Please use lowercase {lowercase_opt!r} instead + """, + see_docs="userguide/declarative_config.html", + due_date=(2023, 9, 10), + # Warning initially introduced in 6 Mar 2021 ) return lowercase_opt From 18347fb2cbe534b6d82e0b6972a1d1c7db593892 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 21:12:19 +0000 Subject: [PATCH 24/46] Use new warnings in setuptools/installer.py --- setuptools/installer.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/setuptools/installer.py b/setuptools/installer.py index 137f35ace4..44ed0da2a3 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -3,7 +3,6 @@ import subprocess import sys import tempfile -import warnings from distutils import log from distutils.errors import DistutilsError from functools import partial @@ -25,7 +24,7 @@ def fetch_build_egg(dist, req): """Fetch an egg needed for building. Use pip/wheel to fetch/build a wheel.""" - _DeprecatedInstaller.warn(stacklevel=2) + _DeprecatedInstaller.emit() _warn_wheel_not_available(dist) return _fetch_build_egg_no_warn(dist, req) @@ -33,7 +32,7 @@ def fetch_build_egg(dist, req): def _fetch_build_eggs(dist, requires): import pkg_resources # Delay import to avoid unnecessary side-effects - _DeprecatedInstaller.warn(stacklevel=3) + _DeprecatedInstaller.emit(stacklevel=3) _warn_wheel_not_available(dist) resolved_dists = pkg_resources.working_set.resolve( @@ -131,12 +130,9 @@ def _warn_wheel_not_available(dist): class _DeprecatedInstaller(SetuptoolsDeprecationWarning): - @classmethod - def warn(cls, stacklevel=1): - warnings.warn( - "setuptools.installer and fetch_build_eggs are deprecated. " - "Requirements should be satisfied by a PEP 517 installer. " - "If you are using pip, you can try `pip install --use-pep517`.", - cls, - stacklevel=stacklevel+1 - ) + _SUMMARY = "setuptools.installer and fetch_build_eggs are deprecated." + _DETAILS = """ + Requirements should be satisfied by a PEP 517 installer. + If you are using pip, you can try `pip install --use-pep517`. + """ + # _DUE_DATE not decided yet From 7fd2e7450b8b9bc4e9a5b04ea43b558bedd03517 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 6 Mar 2023 21:13:51 +0000 Subject: [PATCH 25/46] Use new warnings in setuptools/package_index.py --- setuptools/package_index.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index bec418353e..d6ba207a78 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -9,7 +9,6 @@ import base64 import hashlib import itertools -import warnings import configparser import html import http.client @@ -40,6 +39,7 @@ from fnmatch import translate from setuptools.wheel import Wheel from setuptools.extern.more_itertools import unique_everseen +from setuptools.warnings import SetuptoolsDeprecationWarning EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.+!]+)$') @@ -868,7 +868,11 @@ def _download_html(self, url, headers, filename): raise DistutilsError("Unexpected HTML page found at " + url) def _download_svn(self, url, filename): - warnings.warn("SVN download support is deprecated", UserWarning) + SetuptoolsDeprecationWarning.emit( + "Invalid config", + f"SVN download support is deprecated: {url}", + due_date=(2023, 10, 23), # Initially introduced in 23 Sept 2018 + ) url = url.split('#', 1)[0] # remove any fragment for svn's sake creds = '' if url.lower().startswith('svn:') and '@' in url: From 529efe7bc944202f19fec1f406958f1485e4056a Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 7 Mar 2023 18:21:48 +0000 Subject: [PATCH 26/46] Enforce deprecation warnings in setuptools test suite --- setuptools/tests/test_warnings.py | 3 ++- tox.ini | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/test_warnings.py b/setuptools/tests/test_warnings.py index 75e468d20b..013e2526dc 100644 --- a/setuptools/tests/test_warnings.py +++ b/setuptools/tests/test_warnings.py @@ -60,7 +60,7 @@ @pytest.mark.parametrize("example_name", _EXAMPLES.keys()) -def test_formatting(example_name): +def test_formatting(monkeypatch, example_name): """ It should automatically handle indentation, interpolation and things like due date. """ @@ -68,6 +68,7 @@ def test_formatting(example_name): kwargs = _EXAMPLES[example_name]["kwargs"] expected = _EXAMPLES[example_name]["expected"] + monkeypatch.setenv("SETUPTOOLS_ENFORCE_DEPRECATION", "false") with pytest.warns(SetuptoolsWarning) as warn_info: SetuptoolsWarning.emit(*args, **kwargs) assert _get_message(warn_info) == cleandoc(expected) diff --git a/tox.ini b/tox.ini index 2bae6728f6..2ad4f2fb0f 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,7 @@ deps = # Ideally all the dependencies should be set as "extras" setenv = PYTHONWARNDEFAULTENCODING = 1 + SETUPTOOLS_ENFORCE_DEPRECATION = 1 commands = pytest {posargs} usedevelop = True From bd04fc60505619755508ab8736286c6c6bc661b9 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 7 Mar 2023 21:17:34 +0000 Subject: [PATCH 27/46] Cluster deprecations due_date --- setuptools/__init__.py | 2 +- setuptools/build_meta.py | 2 +- setuptools/command/bdist_rpm.py | 2 +- setuptools/command/dist_info.py | 2 +- setuptools/command/egg_info.py | 4 ++-- setuptools/command/upload_docs.py | 2 +- setuptools/config/_apply_pyprojecttoml.py | 4 ++-- setuptools/config/pyprojecttoml.py | 2 +- setuptools/dist.py | 6 +++--- setuptools/package_index.py | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 6dceab5bab..35d7bd1c4a 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -257,7 +257,7 @@ def convert_path(pathname): Its direct usage by 3rd-party packages is considered improper and the function may be removed in the future. """, - due_date=(2023, 11, 25) # initial deprecation 2022-03-25, see #3201 + due_date=(2023, 12, 13) # initial deprecation 2022-03-25, see #3201 ) return _convert_path(pathname) diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index c620d695e9..3dfd667021 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -306,7 +306,7 @@ def _arbitrary_args(self, config_settings: _ConfigSettings) -> Iterator[str]: Please use `--build-option` instead, `--global-option` is reserved to flags like `--verbose` or `--quiet`. """, - due_date=(2023, 8, 11), # Warning introduced in v64.0.1, 11/Aug/2022. + due_date=(2023, 9, 26), # Warning introduced in v64.0.1, 11/Aug/2022. ) diff --git a/setuptools/command/bdist_rpm.py b/setuptools/command/bdist_rpm.py index e9e5c1b675..047a6d08c2 100644 --- a/setuptools/command/bdist_rpm.py +++ b/setuptools/command/bdist_rpm.py @@ -20,7 +20,7 @@ def run(self): Use bdist_wheel (wheel packages) instead. """, see_url="https://github.com/pypa/setuptools/issues/1988", - due_date=(2023, 10, 22) # Deprecation introduced in 22 Oct 2021. + due_date=(2023, 10, 30) # Deprecation introduced in 22 Oct 2021. ) # ensure distro name is up-to-date diff --git a/setuptools/command/dist_info.py b/setuptools/command/dist_info.py index 69d331fb88..99d3976dc5 100644 --- a/setuptools/command/dist_info.py +++ b/setuptools/command/dist_info.py @@ -50,7 +50,7 @@ def initialize_options(self): def finalize_options(self): if self.egg_base: msg = "--egg-base is deprecated for dist_info command. Use --output-dir." - SetuptoolsDeprecationWarning.emit(msg, due_date=(2023, 8, 23)) + SetuptoolsDeprecationWarning.emit(msg, due_date=(2023, 9, 26)) # This command is internal to setuptools, therefore it should be safe # to remove the deprecated support soon. self.output_dir = self.egg_base or self.output_dir diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 8063cea642..f5163ae7b5 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -338,7 +338,7 @@ def check_broken_egg_info(self): Please rename {bei!r} to {self.egg_info!r} to correct this problem. """, - due_date=(2023, 9, 1), + due_date=(2023, 6, 1), # Old warning, introduced in 2005, might be safe to remove soon ) self.broken_egg_info = self.egg_info @@ -714,7 +714,7 @@ def warn_depends_obsolete(cmd, basename, filename): Configure your dependencies via `setup.cfg` or `pyproject.toml` instead. """, see_docs="userguide/declarative_config.html", - due_date=(2023, 9, 1), + due_date=(2023, 6, 1), # Old warning, introduced in 2005, it might be safe to remove soon. ) diff --git a/setuptools/command/upload_docs.py b/setuptools/command/upload_docs.py index dddde60910..077c9d2fcd 100644 --- a/setuptools/command/upload_docs.py +++ b/setuptools/command/upload_docs.py @@ -97,7 +97,7 @@ def run(self): Instead, use tools like devpi and Read the Docs; or lower level tools like httpie and curl to interact directly with your hosting service API. """, - due_date=(2023, 9, 27), # warning introduced in 27 Jul 2022 + due_date=(2023, 9, 26), # warning introduced in 27 Jul 2022 ) # Run sub commands diff --git a/setuptools/config/_apply_pyprojecttoml.py b/setuptools/config/_apply_pyprojecttoml.py index 4556019eb4..b11be0e364 100644 --- a/setuptools/config/_apply_pyprojecttoml.py +++ b/setuptools/config/_apply_pyprojecttoml.py @@ -327,7 +327,7 @@ def _acessor(obj): TOOL_TABLE_DEPRECATIONS = { "namespace_packages": ( "consider using implicit namespaces instead (PEP 420).", - {"due_date": (2023, 10, 15)}, # warning introduced in May 2022 + {"due_date": (2023, 10, 30)}, # warning introduced in May 2022 ) } @@ -377,4 +377,4 @@ class _WouldIgnoreField(SetuptoolsDeprecationWarning): remove the `[project]` table from your file and rely entirely on other means of configuration. """ - _DUE_DATE = (2023, 10, 27) # Initially introduced in 27 May 2022 + _DUE_DATE = (2023, 10, 30) # Initially introduced in 27 May 2022 diff --git a/setuptools/config/pyprojecttoml.py b/setuptools/config/pyprojecttoml.py index c340121cdd..8d1dcaed54 100644 --- a/setuptools/config/pyprojecttoml.py +++ b/setuptools/config/pyprojecttoml.py @@ -492,5 +492,5 @@ class _InvalidFile(SetuptoolsWarning): To prevent setuptools from considering `pyproject.toml` please DO NOT include both `[project]` or `[tool.setuptools]` tables in your file. """ - _DUE_DATE = (2023, 4, 26) # warning introduced in 2022-03-26 + _DUE_DATE = (2023, 6, 1) # warning introduced in 2022-03-26 _SEE_DOCS = "userguide/pyproject_config.html" diff --git a/setuptools/dist.py b/setuptools/dist.py index 6ecb29a19f..5b4a9cb60a 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -55,7 +55,7 @@ def _get_unpatched(cls): DistDeprecationWarning.emit( "Private function", "Do not call this function", - due_date=(2023, 7, 9), + due_date=(2023, 6, 1), # Warning initially introduced in 2016 ) return get_unpatched(cls) @@ -804,7 +804,7 @@ def warn_dash_deprecation(self, opt, section): versions. Please use the underscore name {underscore_opt!r} instead. """, see_docs="userguide/declarative_config.html", - due_date=(2023, 9, 10), + due_date=(2023, 9, 26), # Warning initially introduced in 3 Mar 2021 ) return underscore_opt @@ -828,7 +828,7 @@ def make_option_lowercase(self, opt, section): future versions. Please use lowercase {lowercase_opt!r} instead """, see_docs="userguide/declarative_config.html", - due_date=(2023, 9, 10), + due_date=(2023, 9, 26), # Warning initially introduced in 6 Mar 2021 ) return lowercase_opt diff --git a/setuptools/package_index.py b/setuptools/package_index.py index d6ba207a78..06b78ac6ee 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -871,7 +871,7 @@ def _download_svn(self, url, filename): SetuptoolsDeprecationWarning.emit( "Invalid config", f"SVN download support is deprecated: {url}", - due_date=(2023, 10, 23), # Initially introduced in 23 Sept 2018 + due_date=(2023, 6, 1), # Initially introduced in 23 Sept 2018 ) url = url.split('#', 1)[0] # remove any fragment for svn's sake creds = '' From 54da8b6d69b7333424eff305218a10d9605a7e36 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Sun, 19 Mar 2023 11:03:23 +0000 Subject: [PATCH 28/46] Apply suggestions from code review Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- setuptools/_normalization.py | 2 +- setuptools/build_meta.py | 2 +- setuptools/command/build.py | 2 +- setuptools/command/build_py.py | 4 ++-- setuptools/command/editable_wheel.py | 8 ++++---- setuptools/dist.py | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py index c34f5ff74c..31899f7ab1 100644 --- a/setuptools/_normalization.py +++ b/setuptools/_normalization.py @@ -81,7 +81,7 @@ def best_effort_version(version: str) -> str: f""" Version {version!r} is not valid according to PEP 440. - Please make sure specify a valid version for your package. + Please make sure to specify a valid version for your package. Also note that future releases of setuptools may halt the build process if an invalid version is given. """, diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index 3dfd667021..ee8ef13faa 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -304,7 +304,7 @@ def _arbitrary_args(self, config_settings: _ConfigSettings) -> Iterator[str]: f""" The arguments {bad_args!r} were given via `--global-option`. Please use `--build-option` instead, - `--global-option` is reserved to flags like `--verbose` or `--quiet`. + `--global-option` is reserved for flags like `--verbose` or `--quiet`. """, due_date=(2023, 9, 26), # Warning introduced in v64.0.1, 11/Aug/2022. ) diff --git a/setuptools/command/build.py b/setuptools/command/build.py index 8152658db8..0f1d688e17 100644 --- a/setuptools/command/build.py +++ b/setuptools/command/build.py @@ -23,7 +23,7 @@ def get_sub_commands(self): subcommands = {cmd[0] for cmd in _build.sub_commands} if subcommands - _ORIGINAL_SUBCOMMANDS: SetuptoolsDeprecationWarning.emit( - "Directly usage of `distutils` commands", + "Direct usage of `distutils` commands", """ It seems that you are using `distutils.command.build` to add new subcommands. Using `distutils` directly is considered deprecated, diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index ccabc7b703..f094496e11 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -336,9 +336,9 @@ class _Warning(SetuptoolsDeprecationWarning): Python recognizes {importable!r} as an importable package[^1], but it is absent from setuptools' `packages` configuration. - This leads to an ambiguous overall configuration. If you want distribute this + This leads to an ambiguous overall configuration. If you want to distribute this package, please make sure that {importable!r} is explicitly added - the `packages` configuration field. + to the `packages` configuration field. Alternatively, you can also rely on setuptools' discovery methods (for example by using `find_namespace_packages(...)`/`find_namespace:` diff --git a/setuptools/command/editable_wheel.py b/setuptools/command/editable_wheel.py index fc0f4c569e..ffcc2cc0e6 100644 --- a/setuptools/command/editable_wheel.py +++ b/setuptools/command/editable_wheel.py @@ -305,7 +305,7 @@ def _safely_run(self, cmd_name: str): If you are seeing this warning it is very likely that a setuptools plugin or customization overrides the `{cmd_name}` command, without taking into consideration how editable installs run build steps - starting from v64.0.0. + starting from setuptools v64.0.0. Plugin authors and developers relying on custom build steps are encouraged to update their `{cmd_name}` implementation considering the @@ -836,10 +836,10 @@ class _DebuggingTips(SetuptoolsWarning): _DETAILS = """ An error happened while installing `{project}` in editable mode. - The following steps are recommended to help debugging this problem: + The following steps are recommended to help debug this problem: - Try to install the project normally, without using the editable mode. - Does the error still persists? + Does the error still persist? (If it does, try fixing the problem before attempting the editable mode). - If you are using binary extensions, make sure you have all OS-level dependencies installed (e.g. compilers, toolchains, binary libraries, ...). @@ -847,7 +847,7 @@ class _DebuggingTips(SetuptoolsWarning): - If you (or your project dependencies) are using any setuptools extension or customization, make sure they support the editable mode. - After following the steps above, if the problem still persist and + After following the steps above, if the problem still persists and you think this is related to how setuptools handles editable installations, please submit a reproducible example (see https://stackoverflow.com/help/minimal-reproducible-example) to: diff --git a/setuptools/dist.py b/setuptools/dist.py index 5b4a9cb60a..c75aaabe99 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -825,7 +825,7 @@ def make_option_lowercase(self, opt, section): "Invalid uppercase configuration", f""" Usage of uppercase key {opt!r} in {section!r} will not be supported in - future versions. Please use lowercase {lowercase_opt!r} instead + future versions. Please use lowercase {lowercase_opt!r} instead. """, see_docs="userguide/declarative_config.html", due_date=(2023, 9, 26), From b86aec30cdc2f2ba1efe85f694352488681f88d6 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 6 Apr 2023 11:38:58 +0200 Subject: [PATCH 29/46] _deprecated_config_handler(): Use warn stacklevel for better feedback --- changelog.d/change.rst | 2 ++ setuptools/config/setupcfg.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog.d/change.rst diff --git a/changelog.d/change.rst b/changelog.d/change.rst new file mode 100644 index 0000000000..afe5fcc2db --- /dev/null +++ b/changelog.d/change.rst @@ -0,0 +1,2 @@ +Add a `stacklevel` parameter to `warnings.warn()` to provide more information to the user. +-- by :user:`cclauss` diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py index 03a446fd2a..7b7d57e68c 100644 --- a/setuptools/config/setupcfg.py +++ b/setuptools/config/setupcfg.py @@ -513,7 +513,7 @@ def _deprecated_config_handler(self, func, msg, warning_class): @wraps(func) def config_handler(*args, **kwargs): - warnings.warn(msg, warning_class) + warnings.warn(msg, warning_class, stacklevel=2) return func(*args, **kwargs) return config_handler From 6c4c20a6e8eef17e2a3413fd0676b3d0fa3fd2cb Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sun, 16 Apr 2023 02:26:00 +0200 Subject: [PATCH 30/46] =?UTF-8?q?=F0=9F=8E=A8=F0=9F=93=9D=20Fix=20in-tree?= =?UTF-8?q?=20PEP=20517=20backend=20wrapper=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch, the documentation suggested the package authors to declare a fixed set of hooks inherited from setuptools. But this approach turned out non-future proof. Over time, as `setuptools` added support for editable installs, it introduced new hooks per PEP 660. But if one were to follow the outlined example, they'd end up with an in-tree build backend that does not support editable installs, nor would it re-export any hooks that might be added in future versions of setuptools, implementing any new standards that may emerge over time. This change demonstrates an approach that would allow the thin wrapper authors to get the new hooks that setuptools may add over time. Ref: https://github.com/ansible/ansible/pull/79606#discussion_r1080753862 --- docs/build_meta.rst | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/build_meta.rst b/docs/build_meta.rst index 197e591755..3c4d43b203 100644 --- a/docs/build_meta.rst +++ b/docs/build_meta.rst @@ -136,24 +136,29 @@ the ``_custom_build/backend.py`` file, as shown in the following example: .. code-block:: python - from setuptools import build_meta as _orig + from setuptools.build_meta import * - prepare_metadata_for_build_wheel = _orig.prepare_metadata_for_build_wheel - build_wheel = _orig.build_wheel - build_sdist = _orig.build_sdist + _original_get_requires_for_build_wheel = get_requires_for_build_wheel + _original_get_requires_for_build_sdist = get_requires_for_build_sdist def get_requires_for_build_wheel(config_settings=None): - return _orig.get_requires_for_build_wheel(config_settings) + [...] + return _original_get_requires_for_build_wheel(config_settings) + [...] def get_requires_for_build_sdist(config_settings=None): - return _orig.get_requires_for_build_sdist(config_settings) + [...] + return _original_get_requires_for_build_sdist(config_settings) + [...] -Note that you can override any of the functions specified in :pep:`PEP 517 -<517#build-backend-interface>`, not only the ones responsible for gathering -requirements. +.. note:: + + You can override any of the functions specified in :pep:`PEP 517 + <517#build-backend-interface>`, not only the ones responsible for gathering + requirements. It is important to ``import *`` so that the hooks that you + choose not to reimplement would be inherited from the setuptools' backend + automatically. This will also cover hooks that might be added in the future + like the ones that :pep:`660` declares. + .. important:: Make sure your backend script is included in the :doc:`source distribution `, otherwise the build will fail. From 95467ffb0b9c224732135ebb07e4633034f7cfb5 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sun, 16 Apr 2023 02:43:31 +0200 Subject: [PATCH 31/46] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20note=20?= =?UTF-8?q?for=20PR=20#3893?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.d/3893.doc.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog.d/3893.doc.rst diff --git a/changelog.d/3893.doc.rst b/changelog.d/3893.doc.rst new file mode 100644 index 0000000000..f1a6ce79d5 --- /dev/null +++ b/changelog.d/3893.doc.rst @@ -0,0 +1,3 @@ +Improved the documentation example regarding making a thin :pep:`517` in-tree +backend wrapper of ``setuptools.build_meta`` that is future-proof and supports +:pep:`660` hook too -- by :user:`webknjaz`. From ac07f21af8ee73e32448bb0429469b56f412a597 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Wed, 19 Apr 2023 17:18:27 +0100 Subject: [PATCH 32/46] Handle Python3.12a7 compatibility problems --- pkg_resources/__init__.py | 3 +++ pkg_resources/tests/test_pkg_resources.py | 8 ++++++++ pkg_resources/tests/test_resources.py | 4 ++++ pytest.ini | 3 +++ setuptools/_py312compat.py | 11 +++++++++++ setuptools/command/easy_install.py | 11 ++++++----- 6 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 setuptools/_py312compat.py diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index a73a1df3b6..8159afd224 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -3046,6 +3046,9 @@ def has_version(self): except ValueError: issue_warning("Unbuilt egg for " + repr(self)) return False + except SystemError: + # TODO: remove this except clause when python/cpython#103632 is fixed. + return False return True def clone(self, **kw): diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 684c977771..fd5cc8ceb1 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -256,6 +256,10 @@ def make_distribution_no_version(tmpdir, basename): ('dist-info', 'METADATA', DistInfoDistribution), ], ) +@pytest.mark.xfail( + sys.version_info[:2] == (3, 12) and sys.version_info.releaselevel != 'final', + reason="https://github.com/python/cpython/issues/103632", +) def test_distribution_version_missing( tmpdir, suffix, expected_filename, expected_dist_type): """ @@ -286,6 +290,10 @@ def test_distribution_version_missing( assert type(dist) == expected_dist_type +@pytest.mark.xfail( + sys.version_info[:2] == (3, 12) and sys.version_info.releaselevel != 'final', + reason="https://github.com/python/cpython/issues/103632", +) def test_distribution_version_missing_undetected_path(): """ Test Distribution.version when the "Version" header is missing and diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 2138f95e7b..baf477dba4 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -319,6 +319,10 @@ def test_marker_evaluation_with_extras_loop(self): res = list(ws.resolve(parse_requirements("a"), ad)) assert res == [a, c, b, foo] + @pytest.mark.xfail( + sys.version_info[:2] == (3, 12) and sys.version_info.releaselevel != 'final', + reason="https://github.com/python/cpython/issues/103632", + ) def testDistroDependsOptions(self): d = self.distRequires(""" Twisted>=1.5 diff --git a/pytest.ini b/pytest.ini index 016f1181a7..9131822b98 100644 --- a/pytest.ini +++ b/pytest.ini @@ -36,6 +36,9 @@ filterwarnings= # python/cpython#100750 ignore:'encoding' argument not specified::platform + # Dependencies might not have been updated yet + default:onerror argument is deprecated, use onexc instead + ## end upstream # https://github.com/pypa/setuptools/issues/1823 diff --git a/setuptools/_py312compat.py b/setuptools/_py312compat.py new file mode 100644 index 0000000000..a17d5aecc9 --- /dev/null +++ b/setuptools/_py312compat.py @@ -0,0 +1,11 @@ +import sys +import shutil + +def shutil_rmtree(path, ignore_errors=False, onexc=None): + if sys.version_info >= (3, 12): + return shutil.rmtree(path, ignore_errors, onexc=onexc) + + def _handler(fn, path, excinfo): + onexc(fn, path, excinfo[1]) + + return shutil.rmtree(path, ignore_errors, onerror=_handler) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 444d3b3311..bf6c964e8e 100644 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -62,6 +62,7 @@ VersionConflict, DEVELOP_DIST, ) import pkg_resources +from .. import _py312compat from .._path import ensure_directory from ..extern.jaraco.text import yield_lines @@ -202,7 +203,7 @@ def _delete_path(self, path): return is_tree = os.path.isdir(path) and not os.path.islink(path) - remover = rmtree if is_tree else os.unlink + remover = _rmtree if is_tree else os.unlink remover(path) @staticmethod @@ -645,7 +646,7 @@ def _tmpdir(self): # cast to str as workaround for #709 and #710 and #712 yield str(tmpdir) finally: - os.path.exists(tmpdir) and rmtree(tmpdir) + os.path.exists(tmpdir) and _rmtree(tmpdir) def easy_install(self, spec, deps=False): with self._tmpdir() as tmpdir: @@ -1182,7 +1183,7 @@ def build_and_install(self, setup_script, setup_base): dist_dir) return eggs finally: - rmtree(dist_dir) + _rmtree(dist_dir) log.set_verbosity(self.verbose) # restore our log verbosity def _set_fetcher_options(self, base): @@ -2289,8 +2290,8 @@ def load_launcher_manifest(name): return manifest.decode('utf-8') % vars() -def rmtree(path, ignore_errors=False, onerror=auto_chmod): - return shutil.rmtree(path, ignore_errors, onerror) +def _rmtree(path, ignore_errors=False, onexc=auto_chmod): + return _py312compat.shutil_rmtree(path, ignore_errors, onexc) def current_umask(): From 7f2bfb34210dc2ad13f1a6e8681ee1a460c221f8 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 09:52:47 +0100 Subject: [PATCH 33/46] Use the same naming convention for pyXXcompat files --- setuptools/command/easy_install.py | 4 ++-- setuptools/{_py312compat.py => py312compat.py} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename setuptools/{_py312compat.py => py312compat.py} (100%) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index bf6c964e8e..3185ee1d0d 100644 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -62,7 +62,7 @@ VersionConflict, DEVELOP_DIST, ) import pkg_resources -from .. import _py312compat +from .. import py312compat from .._path import ensure_directory from ..extern.jaraco.text import yield_lines @@ -2291,7 +2291,7 @@ def load_launcher_manifest(name): def _rmtree(path, ignore_errors=False, onexc=auto_chmod): - return _py312compat.shutil_rmtree(path, ignore_errors, onexc) + return py312compat.shutil_rmtree(path, ignore_errors, onexc) def current_umask(): diff --git a/setuptools/_py312compat.py b/setuptools/py312compat.py similarity index 100% rename from setuptools/_py312compat.py rename to setuptools/py312compat.py From 870268f0c57d483c0066fff661db01c33f6c3614 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 09:53:24 +0100 Subject: [PATCH 34/46] Fix flake8 problem --- setuptools/py312compat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setuptools/py312compat.py b/setuptools/py312compat.py index a17d5aecc9..dd5af58e03 100644 --- a/setuptools/py312compat.py +++ b/setuptools/py312compat.py @@ -1,6 +1,7 @@ import sys import shutil + def shutil_rmtree(path, ignore_errors=False, onexc=None): if sys.version_info >= (3, 12): return shutil.rmtree(path, ignore_errors, onexc=onexc) From aac3c669ba0ca13c8f581f99174b2a3024412f40 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 10:00:46 +0100 Subject: [PATCH 35/46] Improve wrapper compatibility with onexc for py312compat.shutil_rmtree --- setuptools/py312compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/py312compat.py b/setuptools/py312compat.py index dd5af58e03..28175b1f75 100644 --- a/setuptools/py312compat.py +++ b/setuptools/py312compat.py @@ -7,6 +7,6 @@ def shutil_rmtree(path, ignore_errors=False, onexc=None): return shutil.rmtree(path, ignore_errors, onexc=onexc) def _handler(fn, path, excinfo): - onexc(fn, path, excinfo[1]) + return onexc(fn, path, excinfo[1]) return shutil.rmtree(path, ignore_errors, onerror=_handler) From 296cb45ea5ced4c6603d4360e18894ef87a7ca77 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 13:45:39 +0100 Subject: [PATCH 36/46] Use separated import statement to avoid copying names --- docs/build_meta.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/build_meta.rst b/docs/build_meta.rst index 3c4d43b203..aa4f190712 100644 --- a/docs/build_meta.rst +++ b/docs/build_meta.rst @@ -136,18 +136,16 @@ the ``_custom_build/backend.py`` file, as shown in the following example: .. code-block:: python + from setuptools import build_meta as _orig from setuptools.build_meta import * - _original_get_requires_for_build_wheel = get_requires_for_build_wheel - _original_get_requires_for_build_sdist = get_requires_for_build_sdist - def get_requires_for_build_wheel(config_settings=None): - return _original_get_requires_for_build_wheel(config_settings) + [...] + return _orig.get_requires_for_build_wheel(config_settings) + [...] def get_requires_for_build_sdist(config_settings=None): - return _original_get_requires_for_build_sdist(config_settings) + [...] + return _orig.get_requires_for_build_sdist(config_settings) + [...] .. note:: From 8f9b212f0171394fe631ae89c25166e2610eecac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Wed, 15 Mar 2023 16:00:18 +0100 Subject: [PATCH 37/46] docs: Add a note about historical `wheel` use in `requires` Add a note explaining that the `wheel` requirement that used to be historically used in documentation was incorrect. This also explains why it can frequently be found in existing projects, and what problems it causes. I find myself repeatedly explaining it, so I think having a single official source would be better. Incorporates suggestions from Anderson Bravalheri. --- changelog.d/3859.doc.rst | 2 ++ docs/userguide/quickstart.rst | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 changelog.d/3859.doc.rst diff --git a/changelog.d/3859.doc.rst b/changelog.d/3859.doc.rst new file mode 100644 index 0000000000..2d54e996c7 --- /dev/null +++ b/changelog.d/3859.doc.rst @@ -0,0 +1,2 @@ +Added a note about historical presence of ``wheel`` +in ``build-system.requires``, in ``pyproject.toml``. diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index bf92f6a2de..ead8209d3a 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -56,6 +56,17 @@ containing a ``build-system`` section similar to the example below: This section declares what are your build system dependencies, and which library will be used to actually do the packaging. +.. note:: + + Historically this documentation has unnecessarily listed ``wheel`` + in the ``requires`` list, and many projects still do that. This is + not recommended. The backend automatically adds ``wheel`` dependency + when it is required, and listing it explicitly causes it to be + unnecessarily required for source distribution builds. + You should only include ``wheel`` in `requires` if you need to explicitly + access it during build time (e.g. if your project needs a ``setup.py`` + script that imports ``wheel``). + In addition to specifying a build system, you also will need to add some package information such as metadata, contents, dependencies, etc. This can be done in the same ``pyproject.toml`` [#beta]_ file, From 1ba53bb500958f6549a2d3af0753c48599adadf5 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 14:17:21 +0100 Subject: [PATCH 38/46] Fix sphinx error --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index ead8209d3a..3f97e8ef9b 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -63,7 +63,7 @@ library will be used to actually do the packaging. not recommended. The backend automatically adds ``wheel`` dependency when it is required, and listing it explicitly causes it to be unnecessarily required for source distribution builds. - You should only include ``wheel`` in `requires` if you need to explicitly + You should only include ``wheel`` in ``requires`` if you need to explicitly access it during build time (e.g. if your project needs a ``setup.py`` script that imports ``wheel``). From 7af8b5b790aca8af3eaf1c7106c25b8c73e0a3cb Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 14:26:34 +0100 Subject: [PATCH 39/46] Rename news fragment file --- changelog.d/{change.rst => 3884.misc.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/{change.rst => 3884.misc.rst} (100%) diff --git a/changelog.d/change.rst b/changelog.d/3884.misc.rst similarity index 100% rename from changelog.d/change.rst rename to changelog.d/3884.misc.rst From ff164d000a0d50cea388450b8a6f3535fc059067 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 14:31:00 +0100 Subject: [PATCH 40/46] Add news fragment for warnings overhaul --- changelog.d/3849.change.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/3849.change.rst diff --git a/changelog.d/3849.change.rst b/changelog.d/3849.change.rst new file mode 100644 index 0000000000..8a4bd28812 --- /dev/null +++ b/changelog.d/3849.change.rst @@ -0,0 +1 @@ +Overhaul warning system for better visibility. From 59b819adffdd1146933bfb847041da659a0982ac Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 14:34:12 +0100 Subject: [PATCH 41/46] Fix sphinx errors in news fragment --- changelog.d/3884.misc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/3884.misc.rst b/changelog.d/3884.misc.rst index afe5fcc2db..52038b22a8 100644 --- a/changelog.d/3884.misc.rst +++ b/changelog.d/3884.misc.rst @@ -1,2 +1,2 @@ -Add a `stacklevel` parameter to `warnings.warn()` to provide more information to the user. +Add a ``stacklevel`` parameter to ``warnings.warn()`` to provide more information to the user. -- by :user:`cclauss` From f11f8b16e28ef2e21c1f454d8925b2c512d32d37 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 20 Apr 2023 14:56:51 +0100 Subject: [PATCH 42/46] =?UTF-8?q?Bump=20version:=2067.6.1=20=E2=86=92=2067?= =?UTF-8?q?.7.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGES.rst | 22 ++++++++++++++++++++++ changelog.d/3849.change.rst | 1 - changelog.d/3859.doc.rst | 2 -- changelog.d/3884.misc.rst | 2 -- changelog.d/3893.doc.rst | 3 --- setup.cfg | 2 +- 7 files changed, 24 insertions(+), 10 deletions(-) delete mode 100644 changelog.d/3849.change.rst delete mode 100644 changelog.d/3859.doc.rst delete mode 100644 changelog.d/3884.misc.rst delete mode 100644 changelog.d/3893.doc.rst diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 9d4bf354f3..a590b54f88 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.6.1 +current_version = 67.7.0 commit = True tag = True diff --git a/CHANGES.rst b/CHANGES.rst index 8303123ec6..3988bb65e1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,25 @@ +v67.7.0 +------- + + +Changes +^^^^^^^ +* #3849: Overhaul warning system for better visibility. + +Documentation changes +^^^^^^^^^^^^^^^^^^^^^ +* #3859: Added a note about historical presence of ``wheel`` + in ``build-system.requires``, in ``pyproject.toml``. +* #3893: Improved the documentation example regarding making a thin :pep:`517` in-tree + backend wrapper of ``setuptools.build_meta`` that is future-proof and supports + :pep:`660` hook too -- by :user:`webknjaz`. + +Misc +^^^^ +* #3884: Add a ``stacklevel`` parameter to ``warnings.warn()`` to provide more information to the user. + -- by :user:`cclauss` + + v67.6.1 ------- diff --git a/changelog.d/3849.change.rst b/changelog.d/3849.change.rst deleted file mode 100644 index 8a4bd28812..0000000000 --- a/changelog.d/3849.change.rst +++ /dev/null @@ -1 +0,0 @@ -Overhaul warning system for better visibility. diff --git a/changelog.d/3859.doc.rst b/changelog.d/3859.doc.rst deleted file mode 100644 index 2d54e996c7..0000000000 --- a/changelog.d/3859.doc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added a note about historical presence of ``wheel`` -in ``build-system.requires``, in ``pyproject.toml``. diff --git a/changelog.d/3884.misc.rst b/changelog.d/3884.misc.rst deleted file mode 100644 index 52038b22a8..0000000000 --- a/changelog.d/3884.misc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a ``stacklevel`` parameter to ``warnings.warn()`` to provide more information to the user. --- by :user:`cclauss` diff --git a/changelog.d/3893.doc.rst b/changelog.d/3893.doc.rst deleted file mode 100644 index f1a6ce79d5..0000000000 --- a/changelog.d/3893.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improved the documentation example regarding making a thin :pep:`517` in-tree -backend wrapper of ``setuptools.build_meta`` that is future-proof and supports -:pep:`660` hook too -- by :user:`webknjaz`. diff --git a/setup.cfg b/setup.cfg index a9ef478ae8..6dbe95f384 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = setuptools -version = 67.6.1 +version = 67.7.0 author = Python Packaging Authority author_email = distutils-sig@python.org description = Easily download, build, install, upgrade, and uninstall Python packages From 979c2e0d6a804ffe1c648e8894d5e467fa0b7c4d Mon Sep 17 00:00:00 2001 From: Jam Hernandez Quiceno Date: Thu, 20 Apr 2023 14:24:15 -0400 Subject: [PATCH 43/46] Fix . When value is false return instead of raising DistutilsSetupError exception --- setuptools/dist.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setuptools/dist.py b/setuptools/dist.py index c75aaabe99..e5a7b8ed9e 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -334,6 +334,7 @@ def invalid_unless_false(dist, attr, value): if not value: DistDeprecationWarning.emit(f"{attr} is ignored.") # TODO: should there be a `due_date` here? + return raise DistutilsSetupError(f"{attr} is invalid.") From 43cafd729eaff86fffe44afdeede86a6f663d63a Mon Sep 17 00:00:00 2001 From: Jam Hernandez Quiceno Date: Thu, 20 Apr 2023 14:53:34 -0400 Subject: [PATCH 44/46] Add changelog --- changelog.d/3899.misc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/3899.misc.rst diff --git a/changelog.d/3899.misc.rst b/changelog.d/3899.misc.rst new file mode 100644 index 0000000000..d5f987b06c --- /dev/null +++ b/changelog.d/3899.misc.rst @@ -0,0 +1 @@ +Fixes setuptools.dist:invalid_unless_false when value is false don't raise error -- by :user:`jammarher` \ No newline at end of file From f9c8f7a2057a04a17f192bc4d96f1f4c7388aec4 Mon Sep 17 00:00:00 2001 From: Jam Hernandez Quiceno Date: Thu, 20 Apr 2023 17:50:43 -0400 Subject: [PATCH 45/46] Change issue number to 3898 --- changelog.d/{3899.misc.rst => 3898.misc.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/{3899.misc.rst => 3898.misc.rst} (100%) diff --git a/changelog.d/3899.misc.rst b/changelog.d/3898.misc.rst similarity index 100% rename from changelog.d/3899.misc.rst rename to changelog.d/3898.misc.rst From 53e282429043af3ed96c1684cf81b62e0471c711 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Fri, 21 Apr 2023 09:49:06 +0100 Subject: [PATCH 46/46] =?UTF-8?q?Bump=20version:=2067.7.0=20=E2=86=92=2067?= =?UTF-8?q?.7.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGES.rst | 9 +++++++++ changelog.d/3898.misc.rst | 1 - setup.cfg | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) delete mode 100644 changelog.d/3898.misc.rst diff --git a/.bumpversion.cfg b/.bumpversion.cfg index a590b54f88..dc43f1a729 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.7.0 +current_version = 67.7.1 commit = True tag = True diff --git a/CHANGES.rst b/CHANGES.rst index 3988bb65e1..addf4c3324 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,12 @@ +v67.7.1 +------- + + +Misc +^^^^ +* #3898: Fixes setuptools.dist:invalid_unless_false when value is false don't raise error -- by :user:`jammarher` + + v67.7.0 ------- diff --git a/changelog.d/3898.misc.rst b/changelog.d/3898.misc.rst deleted file mode 100644 index d5f987b06c..0000000000 --- a/changelog.d/3898.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Fixes setuptools.dist:invalid_unless_false when value is false don't raise error -- by :user:`jammarher` \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 6dbe95f384..2abb63ae7e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = setuptools -version = 67.7.0 +version = 67.7.1 author = Python Packaging Authority author_email = distutils-sig@python.org description = Easily download, build, install, upgrade, and uninstall Python packages