From f291ee0b199e0ea2df28a3386474795a95e27954 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 11 Feb 2024 14:23:33 -0500 Subject: [PATCH 1/6] Restore expectation that egg-link files will be named with dashes and not underscores for compatibility with older pips. --- setuptools/_normalization.py | 15 +++++++++++++++ setuptools/command/develop.py | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) 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: From 58af37ca8baf898695b16defc52c6b1e01ef2564 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 11 Feb 2024 14:27:55 -0500 Subject: [PATCH 2/6] Replace the incorrect phrase about 'unescaping' and instead clarify that the transformations are irreversible. --- docs/deprecated/python_eggs.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/deprecated/python_eggs.rst b/docs/deprecated/python_eggs.rst index 59d1adc55b..8519d27e3e 100644 --- a/docs/deprecated/python_eggs.rst +++ b/docs/deprecated/python_eggs.rst @@ -133,10 +133,10 @@ egg filename is as follows:: 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.) +``safe_name()`` and ``safe_version()`` respectively. 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 From 4aa55b84ba2d919ef7d7d409a533da4cf947e11f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 11 Feb 2024 14:29:40 -0500 Subject: [PATCH 3/6] Rearrange escaping functions to describe them in the order they should be used. --- docs/deprecated/python_eggs.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/deprecated/python_eggs.rst b/docs/deprecated/python_eggs.rst index 8519d27e3e..97548f183a 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. 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 "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 From f61e452d4f47277d1215047d2aa3c779fb586c0e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 11 Feb 2024 14:36:10 -0500 Subject: [PATCH 4/6] Document the incorrect behavior revealed by #4167. --- docs/deprecated/python_eggs.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/deprecated/python_eggs.rst b/docs/deprecated/python_eggs.rst index 97548f183a..4bb099e01b 100644 --- a/docs/deprecated/python_eggs.rst +++ b/docs/deprecated/python_eggs.rst @@ -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 From 0c804aa02a2c32dc1210b32e75d1a997274f06d4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 11 Feb 2024 14:49:23 -0500 Subject: [PATCH 5/6] Add a test capturing the desired expectation, marked as xfail for now. --- setuptools/tests/test_develop.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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: """ From ac20e42c2c12070089a8e0188c8d46b3ad403fdd Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 11 Feb 2024 14:52:01 -0500 Subject: [PATCH 6/6] Add news fragment. --- newsfragments/4167.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 newsfragments/4167.bugfix.rst 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