summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/importlib/_bootstrap_external.py29
-rw-r--r--Lib/importlib/metadata/__init__.py2
-rw-r--r--Lib/test/test_importlib/fixtures.py1
-rw-r--r--Lib/test/test_importlib/test_main.py19
-rw-r--r--Lib/test/test_importlib/test_zip.py8
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']