diff --git a/docs/deprecated/python_eggs.rst b/docs/deprecated/python_eggs.rst index 59d1adc55b..4bb099e01b 100644 --- a/docs/deprecated/python_eggs.rst +++ b/docs/deprecated/python_eggs.rst @@ -131,12 +131,12 @@ egg filename is as follows:: name ["-" version ["-py" pyver ["-" required_platform]]] "." ext -The "name" and "version" should be escaped using the ``to_filename()`` -function provided by ``pkg_resources``, after first processing them with -``safe_name()`` and ``safe_version()`` respectively. These latter two -functions can also be used to later "unescape" these parts of the -filename. (For a detailed description of these transformations, please -see the "Parsing Utilities" section of the ``pkg_resources`` manual.) +The "name" and "version" should be escaped using ``pkg_resources`` functions +``safe_name()`` and ``safe_version()`` respectively then using +``to_filename()``. Note that the escaping is irreversible and the original +name can only be retrieved from the distribution metadata. For a detailed +description of these transformations, please see the "Parsing Utilities" +section of the ``pkg_resources`` manual. The "pyver" string is the Python major version, as found in the first 3 characters of ``sys.version``. "required_platform" is essentially @@ -193,6 +193,14 @@ Python version, or platform information is included. When the runtime searches for available eggs, ``.egg-link`` files are opened and the actual egg file/directory name is read from them. +Note: Due to `pypa/setuptools#4167 +`_, the name in the egg-link +filename does not match the filename components used in similar files, but +instead presents with dash separators instead of underscore separators. For +compatibility with pip prior to version 24.0, these dash separators are +retained. In a future release, pip 24 or later will be required and the +underscore separators will be used. + Each ``.egg-link`` file should contain a single file or directory name, with no newlines. This filename should be the base location of one or more eggs. That is, the name must either end in ``.egg``, or else it diff --git a/newsfragments/4167.bugfix.rst b/newsfragments/4167.bugfix.rst new file mode 100644 index 0000000000..c61a5525bc --- /dev/null +++ b/newsfragments/4167.bugfix.rst @@ -0,0 +1 @@ +Restored expectation that egg-link files would be named with dash separators for compatibility with pip prior to version 24. \ No newline at end of file diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py index 8d4731eb60..8f211b8bfb 100644 --- a/setuptools/_normalization.py +++ b/setuptools/_normalization.py @@ -120,6 +120,21 @@ def filename_component(value: str) -> str: return value.replace("-", "_").strip("_") +def filename_component_broken(value: str) -> str: + """ + Produce the incorrect filename component for compatibility. + + See pypa/setuptools#4167 for detailed analysis. + + TODO: replace this with filename_component after pip 24 is + nearly-ubiquitous. + + >>> filename_component_broken('foo_bar-baz') + 'foo-bar-baz' + """ + return value.replace('_', '-') + + def safer_name(value: str) -> str: """Like ``safe_name`` but can be used as filename component for wheel""" # See bdist_wheel.safer_name diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 583e8cf5f2..d8c1b49b3d 100644 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -5,6 +5,7 @@ import glob from setuptools.command.easy_install import easy_install +from setuptools import _normalization from setuptools import _path from setuptools import namespaces import setuptools @@ -52,7 +53,9 @@ def finalize_options(self): # pick up setup-dir .egg files only: no .egg-info self.package_index.scan(glob.glob('*.egg')) - egg_link_fn = ei.egg_name + '.egg-link' + egg_link_fn = ( + _normalization.filename_component_broken(ei.egg_name) + '.egg-link' + ) self.egg_link = os.path.join(self.install_dir, egg_link_fn) self.egg_base = ei.egg_base if self.egg_path is None: diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index bdb4bec888..d36447edbb 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -3,6 +3,7 @@ import os import sys import subprocess +import pathlib import platform from setuptools.command import test @@ -82,6 +83,18 @@ def test_console_scripts(self, tmpdir): cmd.run() # assert '0.0' not in foocmd_text + @pytest.mark.xfail(reason="legacy behavior retained for compatibility #4167") + def test_egg_link_filename(self): + settings = dict( + name='Foo $$$ Bar_baz-bing', + ) + dist = Distribution(settings) + cmd = develop(dist) + cmd.ensure_finalized() + link = pathlib.Path(cmd.egg_link) + assert link.suffix == '.egg-link' + assert link.stem == 'Foo_Bar_baz_bing' + class TestResolver: """