Skip to content

Commit dd25a38

Browse files
authored
Merge pull request #253 from uranusjr/search-dot-in-dist-info
Fix dot handling in dist-info directory name
2 parents 49f223d + b072a46 commit dd25a38

File tree

5 files changed

+67
-3
lines changed

5 files changed

+67
-3
lines changed

docs/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
importlib_metadata NEWS
33
=========================
44

5+
v2.1.0
6+
======
7+
8+
* #253: When querying for package metadata, the lookup
9+
now honors
10+
`package normalization rules <https://packaging.python.org/specifications/recording-installed-packages/>`_.
11+
512
v2.0.0
613
======
714

importlib_metadata/__init__.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ def search(self, name):
473473
for child in self.children():
474474
n_low = child.lower()
475475
if (n_low in name.exact_matches
476-
or n_low.startswith(name.prefix)
476+
or n_low.replace('.', '_').startswith(name.prefix)
477477
and n_low.endswith(name.suffixes)
478478
# legacy case:
479479
or self.is_egg(name) and n_low == 'egg-info'):
@@ -494,12 +494,19 @@ def __init__(self, name):
494494
self.name = name
495495
if name is None:
496496
return
497-
self.normalized = name.lower().replace('-', '_')
497+
self.normalized = self.normalize(name)
498498
self.prefix = self.normalized + '-'
499499
self.exact_matches = [
500500
self.normalized + suffix for suffix in self.suffixes]
501501
self.versionless_egg_name = self.normalized + '.egg'
502502

503+
@staticmethod
504+
def normalize(name):
505+
"""
506+
PEP 503 normalization plus dashes as underscores.
507+
"""
508+
return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_')
509+
503510

504511
@install
505512
class MetadataPathFinder(NullFinder, DistributionFinder):

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ testing =
4141
importlib_resources>=1.3; python_version < "3.9"
4242
packaging
4343
pep517
44+
unittest2; python_version < "3"
4445
docs =
4546
sphinx
4647
rst.linker

tests/fixtures.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,36 @@ def setUp(self):
104104
build_files(DistInfoPkg.files, self.site_dir)
105105

106106

107+
class DistInfoPkgWithDot(OnSysPath, SiteDir):
108+
files = {
109+
"pkg_dot-1.0.0.dist-info": {
110+
"METADATA": """
111+
Name: pkg.dot
112+
Version: 1.0.0
113+
""",
114+
},
115+
}
116+
117+
def setUp(self):
118+
super(DistInfoPkgWithDot, self).setUp()
119+
build_files(DistInfoPkgWithDot.files, self.site_dir)
120+
121+
122+
class DistInfoPkgWithDotLegacy(OnSysPath, SiteDir):
123+
files = {
124+
"pkg.dot-1.0.0.dist-info": {
125+
"METADATA": """
126+
Name: pkg.dot
127+
Version: 1.0.0
128+
""",
129+
},
130+
}
131+
132+
def setUp(self):
133+
super(DistInfoPkgWithDotLegacy, self).setUp()
134+
build_files(DistInfoPkgWithDotLegacy.files, self.site_dir)
135+
136+
107137
class DistInfoPkgOffPath(SiteDir):
108138
def setUp(self):
109139
super(DistInfoPkgOffPath, self).setUp()

tests/test_api.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import re
22
import textwrap
3-
import unittest
3+
4+
try:
5+
import unittest2 as unittest
6+
except ImportError:
7+
import unittest
48

59
from . import fixtures
610
from importlib_metadata import (
@@ -22,6 +26,7 @@
2226
class APITests(
2327
fixtures.EggInfoPkg,
2428
fixtures.DistInfoPkg,
29+
fixtures.DistInfoPkgWithDot,
2530
fixtures.EggInfoFile,
2631
unittest.TestCase):
2732

@@ -41,6 +46,12 @@ def test_for_name_does_not_exist(self):
4146
with self.assertRaises(PackageNotFoundError):
4247
distribution('does-not-exist')
4348

49+
def test_name_normalization(self):
50+
names = 'pkg.dot', 'pkg_dot', 'pkg-dot', 'pkg..dot', 'Pkg.Dot'
51+
for name in names:
52+
with self.subTest(name):
53+
assert distribution(name).metadata['Name'] == 'pkg.dot'
54+
4455
def test_for_top_level(self):
4556
self.assertEqual(
4657
distribution('egginfo-pkg').read_text('top_level.txt').strip(),
@@ -156,6 +167,14 @@ def test_more_complex_deps_requires_text(self):
156167
assert deps == expected
157168

158169

170+
class LegacyDots(fixtures.DistInfoPkgWithDotLegacy, unittest.TestCase):
171+
def test_name_normalization(self):
172+
names = 'pkg.dot', 'pkg_dot', 'pkg-dot', 'pkg..dot', 'Pkg.Dot'
173+
for name in names:
174+
with self.subTest(name):
175+
assert distribution(name).metadata['Name'] == 'pkg.dot'
176+
177+
159178
class OffSysPathTests(fixtures.DistInfoPkgOffPath, unittest.TestCase):
160179
def test_find_distributions_specified_path(self):
161180
dists = Distribution.discover(path=[str(self.site_dir)])

0 commit comments

Comments
 (0)