diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6e5892f2ed..14f3151d34 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -64,7 +64,8 @@ jobs: python: "3.10" distutils: stdlib runs-on: ${{ matrix.platform }} - continue-on-error: ${{ matrix.python == '3.14' }} + continue-on-error: ${{ matrix.python == '3.14' || matrix.python == 'pypy3.10' }} + # XXX: pypy seems to be flaky with unrelated tests in #6345 env: SETUPTOOLS_USE_DISTUTILS: ${{ matrix.distutils || 'local' }} timeout-minutes: 75 diff --git a/newsfragments/4911.bugfix.rst b/newsfragments/4911.bugfix.rst new file mode 100644 index 0000000000..49db1a49ed --- /dev/null +++ b/newsfragments/4911.bugfix.rst @@ -0,0 +1,2 @@ +Postponed removals of deprecated dash-separated and uppercase fields in ``setup.cfg``. +All packages with deprecated configurations are advised to move before 2026. diff --git a/setuptools/dist.py b/setuptools/dist.py index fa734c651f..8d972cc49b 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -626,21 +626,41 @@ def _enforce_underscore(self, opt: str, section: str) -> str: if "-" not in opt or self._skip_setupcfg_normalization(section): return opt - raise InvalidConfigError( + underscore_opt = opt.replace('-', '_') + affected = f"(Affected: {self.metadata.name})." if self.metadata.name else "" + SetuptoolsDeprecationWarning.emit( f"Invalid dash-separated key {opt!r} in {section!r} (setup.cfg), " - f"please use the underscore name {opt.replace('-', '_')!r} instead." + f"please use the underscore name {underscore_opt!r} instead.", + f""" + Usage of dash-separated {opt!r} will not be supported in future + versions. Please use the underscore name {underscore_opt!r} instead. + {affected} + """, + see_docs="userguide/declarative_config.html", + due_date=(2026, 3, 3), # Warning initially introduced in 3 Mar 2021 ) + return underscore_opt def _enforce_option_lowercase(self, opt: str, section: str) -> str: if opt.islower() or self._skip_setupcfg_normalization(section): return opt - raise InvalidConfigError( + lowercase_opt = opt.lower() + affected = f"(Affected: {self.metadata.name})." if self.metadata.name else "" + SetuptoolsDeprecationWarning.emit( f"Invalid uppercase key {opt!r} in {section!r} (setup.cfg), " - f"please use lowercase {opt.lower()!r} instead." + f"please use lowercase {lowercase_opt!r} instead.", + f""" + Usage of uppercase key {opt!r} in {section!r} will not be supported in + future versions. Please use lowercase {lowercase_opt!r} instead. + {affected} + """, + see_docs="userguide/declarative_config.html", + due_date=(2026, 3, 3), # Warning initially introduced in 6 Mar 2021 ) + return lowercase_opt def _skip_setupcfg_normalization(self, section: str) -> bool: skip = ( diff --git a/setuptools/tests/config/test_setupcfg.py b/setuptools/tests/config/test_setupcfg.py index a199871ffd..61af990447 100644 --- a/setuptools/tests/config/test_setupcfg.py +++ b/setuptools/tests/config/test_setupcfg.py @@ -10,7 +10,6 @@ from setuptools.config.setupcfg import ConfigHandler, Target, read_configuration from setuptools.dist import Distribution, _Distribution -from setuptools.errors import InvalidConfigError from setuptools.warnings import SetuptoolsDeprecationWarning from ..textwrap import DALS @@ -423,7 +422,7 @@ def test_not_utf8(self, tmpdir): pass @pytest.mark.parametrize( - ("error_msg", "config"), + ("error_msg", "config", "invalid"), [ ( "Invalid dash-separated key 'author-email' in 'metadata' (setup.cfg)", @@ -434,6 +433,7 @@ def test_not_utf8(self, tmpdir): maintainer_email = foo@foo.com """ ), + {"author-email": "test@test.com"}, ), ( "Invalid uppercase key 'Name' in 'metadata' (setup.cfg)", @@ -444,14 +444,25 @@ def test_not_utf8(self, tmpdir): description = Some description """ ), + {"Name": "foo"}, ), ], ) - def test_invalid_options_previously_deprecated(self, tmpdir, error_msg, config): - # this test and related methods can be removed when no longer needed + def test_invalid_options_previously_deprecated( + self, tmpdir, error_msg, config, invalid + ): + # This test and related methods can be removed when no longer needed. + # Deprecation postponed due to push-back from the community in + # https://github.com/pypa/setuptools/issues/4910 fake_env(tmpdir, config) - with pytest.raises(InvalidConfigError, match=re.escape(error_msg)): - get_dist(tmpdir).__enter__() + with pytest.warns(SetuptoolsDeprecationWarning, match=re.escape(error_msg)): + dist = get_dist(tmpdir).__enter__() + + tmpdir.join('setup.cfg').remove() + + for field, value in invalid.items(): + attr = field.replace("-", "_").lower() + assert getattr(dist.metadata, attr) == value class TestOptions: