From 006fa4245a9e211a8129c495d140aac9c77481c5 Mon Sep 17 00:00:00 2001 From: starkk242 Date: Fri, 8 May 2026 12:05:48 +0530 Subject: [PATCH 1/2] gh-149137: Fix PackagePath to normalize backslashes from Windows RECORD files Per the packaging spec, backslashes are valid path separators on Windows in RECORD files. However, PackagePath extends PurePosixPath which treats backslashes as literal characters rather than separators, causing .name and .parts to return incorrect values (e.g., the full path string instead of just the filename). Fix by overriding __init__ in PackagePath to replace backslashes with forward slashes before passing to PurePosixPath. --- Lib/importlib/metadata/__init__.py | 10 ++++++++++ Lib/test/test_importlib/metadata/test_main.py | 19 +++++++++++++++++++ ...-packagepath-backslash.gh-issue-149137.rst | 6 ++++++ 3 files changed, 35 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-05-08-fix-packagepath-backslash.gh-issue-149137.rst diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index 32f4b7d2d6e08b..a6b6ec2584cc40 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -377,6 +377,16 @@ class PackagePath(pathlib.PurePosixPath): size: int dist: Distribution + def __init__(self, *args): + # Normalize Windows backslashes to forward slashes. Per the packaging + # spec, backslashes are valid path separators in RECORD files on Windows, + # but PurePosixPath treats them as literal characters, not separators. + normalized = tuple( + arg.replace('\\', '/') if isinstance(arg, str) else arg + for arg in args + ) + super().__init__(*normalized) + def read_text(self, encoding: str = 'utf-8') -> str: return self.locate().read_text(encoding=encoding) diff --git a/Lib/test/test_importlib/metadata/test_main.py b/Lib/test/test_importlib/metadata/test_main.py index aae052160d9763..6554df8fdd424f 100644 --- a/Lib/test/test_importlib/metadata/test_main.py +++ b/Lib/test/test_importlib/metadata/test_main.py @@ -14,6 +14,7 @@ EntryPoint, MetadataNotFound, PackageNotFoundError, + PackagePath, _unique, distributions, entry_points, @@ -491,3 +492,21 @@ def test_origin(self): dist = Distribution.from_name('distinfo-pkg') assert dist.origin.url.endswith('.whl') assert dist.origin.archive_info.hashes.sha256 + + +class PackagePathTests(unittest.TestCase): + def test_backslash_in_name(self): + # Windows RECORD files may use backslashes as path separators per + # the packaging spec; PackagePath must normalize them so that + # .name/.parts/.parent behave correctly. + p = PackagePath('dist_info-1.0.dist-info\\METADATA') + self.assertEqual(p.name, 'METADATA') + + def test_backslash_parts(self): + p = PackagePath('a\\b\\c.py') + self.assertEqual(p.parts, ('a', 'b', 'c.py')) + + def test_forward_slash_unchanged(self): + p = PackagePath('dist_info-1.0.dist-info/METADATA') + self.assertEqual(p.name, 'METADATA') + self.assertEqual(p.parts, ('dist_info-1.0.dist-info', 'METADATA')) diff --git a/Misc/NEWS.d/next/Library/2026-05-08-fix-packagepath-backslash.gh-issue-149137.rst b/Misc/NEWS.d/next/Library/2026-05-08-fix-packagepath-backslash.gh-issue-149137.rst new file mode 100644 index 00000000000000..87c84594544a05 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-08-fix-packagepath-backslash.gh-issue-149137.rst @@ -0,0 +1,6 @@ +Fix :class:`importlib.metadata.PackagePath` to normalize Windows backslash +path separators from RECORD files to forward slashes. Per the packaging +specification, backslashes are valid separators on Windows, but +:class:`~pathlib.PurePosixPath` treats them as literal characters, causing +:attr:`~pathlib.PurePath.name` and :attr:`~pathlib.PurePath.parts` to return +incorrect values. From 795c6654a61860abf4d63946936ba7d83ca2c054 Mon Sep 17 00:00:00 2001 From: starkk242 Date: Fri, 8 May 2026 12:19:11 +0530 Subject: [PATCH 2/2] gh-149137: Fix NEWS entry filename to match blurb format --- ...-149137.rst => 2026-05-08-11-59-00.gh-issue-149137.Bp3xQz.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Misc/NEWS.d/next/Library/{2026-05-08-fix-packagepath-backslash.gh-issue-149137.rst => 2026-05-08-11-59-00.gh-issue-149137.Bp3xQz.rst} (100%) diff --git a/Misc/NEWS.d/next/Library/2026-05-08-fix-packagepath-backslash.gh-issue-149137.rst b/Misc/NEWS.d/next/Library/2026-05-08-11-59-00.gh-issue-149137.Bp3xQz.rst similarity index 100% rename from Misc/NEWS.d/next/Library/2026-05-08-fix-packagepath-backslash.gh-issue-149137.rst rename to Misc/NEWS.d/next/Library/2026-05-08-11-59-00.gh-issue-149137.Bp3xQz.rst