diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/importlib/_bootstrap_external.py | 29 | ||||
-rw-r--r-- | Lib/importlib/metadata/__init__.py | 2 | ||||
-rw-r--r-- | Lib/test/test_importlib/fixtures.py | 1 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_main.py | 19 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_zip.py | 8 |
5 files changed, 44 insertions, 15 deletions
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 5aac048..badd7a7 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1367,8 +1367,6 @@ class PathFinder: return None return spec.loader - search_template = r'(?:{pattern}(-.*)?\.(dist|egg)-info|EGG-INFO)' - @classmethod def find_distributions(cls, name=None, path=None): """ @@ -1400,24 +1398,35 @@ class PathFinder: def _switch_path(path): from contextlib import suppress import zipfile - from pathlib import Path - with suppress(Exception): - return zipfile.Path(path) - return Path(path) + import pathlib + PYPY_OPEN_BUG = False + if not PYPY_OPEN_BUG or os.path.isfile(path): # pragma: no branch + with suppress(Exception): + return zipfile.Path(path) + return pathlib.Path(path) + + @classmethod + def _matches_info(cls, normalized, item): + import re + template = r'{pattern}(-.*)?\.(dist|egg)-info' + manifest = template.format(pattern=normalized) + return re.match(manifest, item.name, flags=re.IGNORECASE) @classmethod - def _predicate(cls, pattern, root, item): + def _matches_legacy(cls, normalized, item): import re - return re.match(pattern, str(item.name), flags=re.IGNORECASE) + template = r'{pattern}-.*\.egg[\\/]EGG-INFO' + manifest = template.format(pattern=normalized) + return re.search(manifest, str(item), flags=re.IGNORECASE) @classmethod def _search_path(cls, root, pattern): if not root.is_dir(): return () normalized = pattern.replace('-', '_') - matcher = cls.search_template.format(pattern=normalized) return (item for item in root.iterdir() - if cls._predicate(matcher, root, item)) + if cls._matches_info(normalized, item) + or cls._matches_legacy(normalized, item)) class FileFinder: diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index 944dbb5..e80f4fa 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -88,7 +88,7 @@ class EntryPoint(collections.namedtuple('EntryPointBase', 'name value group')): @classmethod def _from_text(cls, text): - config = ConfigParser() + config = ConfigParser(delimiters='=') # case sensitive: https://stackoverflow.com/q/1611799/812183 config.optionxform = str try: diff --git a/Lib/test/test_importlib/fixtures.py b/Lib/test/test_importlib/fixtures.py index 3b926ba..0b4ce18 100644 --- a/Lib/test/test_importlib/fixtures.py +++ b/Lib/test/test_importlib/fixtures.py @@ -83,6 +83,7 @@ class DistInfoPkg(OnSysPath, SiteDir): "entry_points.txt": """ [entries] main = mod:main + ns:sub = mod:main """ }, "mod.py": """ diff --git a/Lib/test/test_importlib/test_main.py b/Lib/test/test_importlib/test_main.py index 5e2cb26..bc42b83 100644 --- a/Lib/test/test_importlib/test_main.py +++ b/Lib/test/test_importlib/test_main.py @@ -32,7 +32,7 @@ class BasicTests(fixtures.DistInfoPkg, unittest.TestCase): class ImportTests(fixtures.DistInfoPkg, unittest.TestCase): def test_import_nonexistent_module(self): # Ensure that the MetadataPathFinder does not crash an import of a - # nonexistent module. + # non-existant module. with self.assertRaises(ImportError): importlib.import_module('does_not_exist') @@ -41,6 +41,11 @@ class ImportTests(fixtures.DistInfoPkg, unittest.TestCase): ep = entries['main'] self.assertEqual(ep.load().__name__, "main") + def test_entrypoint_with_colon_in_name(self): + entries = dict(entry_points()['entries']) + ep = entries['ns:sub'] + self.assertEqual(ep.value, 'mod:main') + def test_resolve_without_attr(self): ep = EntryPoint( name='ep', @@ -159,8 +164,16 @@ class DiscoveryTests(fixtures.EggInfoPkg, class DirectoryTest(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): - def test(self): + def test_egg_info(self): # make an `EGG-INFO` directory that's unrelated self.site_dir.joinpath('EGG-INFO').mkdir() # used to crash with `IsADirectoryError` - self.assertIsNone(version('unknown-package')) + with self.assertRaises(PackageNotFoundError): + version('unknown-package') + + def test_egg(self): + egg = self.site_dir.joinpath('foo-3.6.egg') + egg.mkdir() + with self.add_sys_path(egg): + with self.assertRaises(PackageNotFoundError): + version('foo') diff --git a/Lib/test/test_importlib/test_zip.py b/Lib/test/test_importlib/test_zip.py index bcf7cf3..9568c22 100644 --- a/Lib/test/test_importlib/test_zip.py +++ b/Lib/test/test_importlib/test_zip.py @@ -2,7 +2,9 @@ import sys import unittest from contextlib import ExitStack -from importlib.metadata import distribution, entry_points, files, version +from importlib.metadata import ( + distribution, entry_points, files, PackageNotFoundError, version, +) from importlib.resources import path @@ -22,6 +24,10 @@ class TestZip(unittest.TestCase): def test_zip_version(self): self.assertEqual(version('example'), '21.12') + def test_zip_version_does_not_match(self): + with self.assertRaises(PackageNotFoundError): + version('definitely-not-installed') + def test_zip_entry_points(self): scripts = dict(entry_points()['console_scripts']) entry_point = scripts['example'] |