diff --git a/importlib_metadata/__init__.py b/importlib_metadata/__init__.py index 49f74ab5..08ebcb34 100644 --- a/importlib_metadata/__init__.py +++ b/importlib_metadata/__init__.py @@ -922,14 +922,6 @@ def __init__(self, path: FastPath): From the children in the path, calculate early all of the children that appear to represent metadata (infos) or legacy metadata (eggs). - - Children are considered in reverse lexicographic order, so when - a path supplies more than one metadata directory for a - distribution, as an interrupted or unclean upgrade may leave - behind, the greater one is found first - (python/cpython#100666). Because the order is lexicographic on - the directory name and not on the parsed version, it only - approximates a preference for the newer version. """ base = os.path.basename(path.root).lower() @@ -937,7 +929,7 @@ def __init__(self, path: FastPath): self.infos = FreezableDefaultDict(list) self.eggs = FreezableDefaultDict(list) - for child in sorted(path.children(), key=str.lower, reverse=True): + for child in path.children(): low = child.lower() if low.endswith((".dist-info", ".egg-info")): # rpartition is faster than splitext and suitable for this purpose. diff --git a/newsfragments/+revert-prefer-greater-version.feature.rst b/newsfragments/+revert-prefer-greater-version.feature.rst new file mode 100644 index 00000000..e5fa34b8 --- /dev/null +++ b/newsfragments/+revert-prefer-greater-version.feature.rst @@ -0,0 +1,6 @@ +Reverted the preference for the greater metadata directory added in v9.1.0. +The ordering was lexicographic on the directory name and not on the parsed +version, so it only approximated a preference for the newer version. Where a +path supplies more than one metadata directory for a distribution, discovery +once again reports them in the order the path supplies +(python/cpython#100666). diff --git a/tests/test_main.py b/tests/test_main.py index 3566d33b..cbcb5cbb 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -208,76 +208,6 @@ def test_missing_required_metadata(self): unversioned.version -class MultipleVersionsTests(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): - """ - An unclean upgrade can leave more than one metadata directory for a - distribution in one path. Prefer the greater one. - - Ref python/cpython#100666. - """ - - # Deliberately not in version order; the preference follows the - # lexicographic ordering of the directory names, which only - # approximates the ordering of the versions they name. - versions = '1.12.1', '1.13.1', '1.9.0', '2.0.0' - expected = '2.0.0', '1.9.0', '1.13.1', '1.12.1' - - @staticmethod - def make_pkg(name, version, files=None): - """ - Create metadata for a dist-info package at the indicated version. - """ - return { - f'{name}-{version}.dist-info': ( - {'METADATA': f'Name: {name}\nVersion: {version}\n'} - if files is None - else files - ), - } - - def build_versions(self, *versions): - for ver in versions: - fixtures.build_files(self.make_pkg('foo', ver), self.site_dir) - - def test_greater_version_preferred(self): - """ - Retrieving by name resolves to the greater version. - """ - self.build_versions(*self.versions) - assert version('foo') == self.expected[0] - - def test_discovery_order(self): - """ - Preferring one version doesn't hide the others from discovery, - which reports them greatest first. - """ - self.build_versions(*self.versions) - found = tuple(dist.version for dist in Distribution.discover(name='foo')) - assert found == self.expected - - def test_greater_version_preferred_in_eggs(self): - """ - Legacy egg-info metadata gets the same preference. - """ - fixtures.build_files( - { - f'foo-{ver}.egg-info': {'PKG-INFO': f'Name: foo\nVersion: {ver}\n'} - for ver in self.versions - }, - self.site_dir, - ) - assert version('foo') == self.expected[0] - - def test_validity_preferred_to_version(self): - """ - A valid dist is still preferred to an invalid one of a greater - version, the condition that prompted the report. - """ - self.build_versions('1.12.1') - fixtures.build_files(self.make_pkg('foo', '2.0.0', files={}), self.site_dir) - assert version('foo') == '1.12.1' - - class NonASCIITests(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): @staticmethod def pkg_with_non_ascii_description(site_dir):