Skip to content

Commit f96334c

Browse files
bpo-37697: Sync with importlib_metadata 0.19 (GH-14993) (GH-14995)
* bpo-37697: Sync with importlib_metadata 0.19 * Run make regen-importlib * 📜🤖 Added by blurb_it. (cherry picked from commit 049460d) Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
1 parent c94386d commit f96334c

File tree

7 files changed

+841
-794
lines changed

7 files changed

+841
-794
lines changed

Lib/importlib/_bootstrap_external.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,8 +1367,6 @@ def find_module(cls, fullname, path=None):
13671367
return None
13681368
return spec.loader
13691369

1370-
search_template = r'(?:{pattern}(-.*)?\.(dist|egg)-info|EGG-INFO)'
1371-
13721370
@classmethod
13731371
def find_distributions(cls, name=None, path=None):
13741372
"""
@@ -1400,24 +1398,35 @@ def _search_paths(cls, pattern, paths):
14001398
def _switch_path(path):
14011399
from contextlib import suppress
14021400
import zipfile
1403-
from pathlib import Path
1404-
with suppress(Exception):
1405-
return zipfile.Path(path)
1406-
return Path(path)
1401+
import pathlib
1402+
PYPY_OPEN_BUG = False
1403+
if not PYPY_OPEN_BUG or os.path.isfile(path): # pragma: no branch
1404+
with suppress(Exception):
1405+
return zipfile.Path(path)
1406+
return pathlib.Path(path)
1407+
1408+
@classmethod
1409+
def _matches_info(cls, normalized, item):
1410+
import re
1411+
template = r'{pattern}(-.*)?\.(dist|egg)-info'
1412+
manifest = template.format(pattern=normalized)
1413+
return re.match(manifest, item.name, flags=re.IGNORECASE)
14071414

14081415
@classmethod
1409-
def _predicate(cls, pattern, root, item):
1416+
def _matches_legacy(cls, normalized, item):
14101417
import re
1411-
return re.match(pattern, str(item.name), flags=re.IGNORECASE)
1418+
template = r'{pattern}-.*\.egg[\\/]EGG-INFO'
1419+
manifest = template.format(pattern=normalized)
1420+
return re.search(manifest, str(item), flags=re.IGNORECASE)
14121421

14131422
@classmethod
14141423
def _search_path(cls, root, pattern):
14151424
if not root.is_dir():
14161425
return ()
14171426
normalized = pattern.replace('-', '_')
1418-
matcher = cls.search_template.format(pattern=normalized)
14191427
return (item for item in root.iterdir()
1420-
if cls._predicate(matcher, root, item))
1428+
if cls._matches_info(normalized, item)
1429+
or cls._matches_legacy(normalized, item))
14211430

14221431

14231432
class FileFinder:

Lib/importlib/metadata/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def _from_config(cls, config):
8888

8989
@classmethod
9090
def _from_text(cls, text):
91-
config = ConfigParser()
91+
config = ConfigParser(delimiters='=')
9292
# case sensitive: https://stackoverflow.com/q/1611799/812183
9393
config.optionxform = str
9494
try:

Lib/test/test_importlib/fixtures.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class DistInfoPkg(OnSysPath, SiteDir):
8383
"entry_points.txt": """
8484
[entries]
8585
main = mod:main
86+
ns:sub = mod:main
8687
"""
8788
},
8889
"mod.py": """

Lib/test/test_importlib/test_main.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def test_new_style_classes(self):
3232
class ImportTests(fixtures.DistInfoPkg, unittest.TestCase):
3333
def test_import_nonexistent_module(self):
3434
# Ensure that the MetadataPathFinder does not crash an import of a
35-
# nonexistent module.
35+
# non-existant module.
3636
with self.assertRaises(ImportError):
3737
importlib.import_module('does_not_exist')
3838

@@ -41,6 +41,11 @@ def test_resolve(self):
4141
ep = entries['main']
4242
self.assertEqual(ep.load().__name__, "main")
4343

44+
def test_entrypoint_with_colon_in_name(self):
45+
entries = dict(entry_points()['entries'])
46+
ep = entries['ns:sub']
47+
self.assertEqual(ep.value, 'mod:main')
48+
4449
def test_resolve_without_attr(self):
4550
ep = EntryPoint(
4651
name='ep',
@@ -159,8 +164,16 @@ def test_package_discovery(self):
159164

160165

161166
class DirectoryTest(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase):
162-
def test(self):
167+
def test_egg_info(self):
163168
# make an `EGG-INFO` directory that's unrelated
164169
self.site_dir.joinpath('EGG-INFO').mkdir()
165170
# used to crash with `IsADirectoryError`
166-
self.assertIsNone(version('unknown-package'))
171+
with self.assertRaises(PackageNotFoundError):
172+
version('unknown-package')
173+
174+
def test_egg(self):
175+
egg = self.site_dir.joinpath('foo-3.6.egg')
176+
egg.mkdir()
177+
with self.add_sys_path(egg):
178+
with self.assertRaises(PackageNotFoundError):
179+
version('foo')

Lib/test/test_importlib/test_zip.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import unittest
33

44
from contextlib import ExitStack
5-
from importlib.metadata import distribution, entry_points, files, version
5+
from importlib.metadata import (
6+
distribution, entry_points, files, PackageNotFoundError, version,
7+
)
68
from importlib.resources import path
79

810

@@ -22,6 +24,10 @@ def setUp(self):
2224
def test_zip_version(self):
2325
self.assertEqual(version('example'), '21.12')
2426

27+
def test_zip_version_does_not_match(self):
28+
with self.assertRaises(PackageNotFoundError):
29+
version('definitely-not-installed')
30+
2531
def test_zip_entry_points(self):
2632
scripts = dict(entry_points()['console_scripts'])
2733
entry_point = scripts['example']
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Syncronize ``importlib.metadata`` with `importlib_metadata 0.19 <https://gitlab.com/python-devs/importlib_metadata/-/milestones/20>`_, improving handling of EGG-INFO files and fixing a crash when entry point names contained colons.

0 commit comments

Comments
 (0)