Skip to content

Commit 212f471

Browse files
committed
Allow egg-info files with a test
1 parent 17958ea commit 212f471

File tree

4 files changed

+63
-21
lines changed

4 files changed

+63
-21
lines changed

importlib_metadata/_hooks.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,12 @@ def find_spec(*args, **kwargs):
4646
find_module = find_spec
4747

4848

49-
@install
50-
class MetadataPathFinder(NullFinder):
49+
class MetadataPathBaseFinder(NullFinder):
5150
"""A degenerate finder for distribution packages on the file system.
5251
5352
This finder supplies only a find_distributions() method for versions
5453
of Python that do not have a PathFinder find_distributions().
5554
"""
56-
search_template = r'{pattern}(-.*)?\.(dist|egg)-info'
5755

5856
def find_distributions(self, name=None, path=None):
5957
"""Return an iterable of all Distribution instances capable of
@@ -77,20 +75,34 @@ def _search_paths(cls, pattern, paths):
7775
for path in map(Path, paths)
7876
)
7977

78+
@classmethod
79+
def _predicate(cls, pattern, root, item):
80+
return re.match(pattern, str(item.name), flags=re.IGNORECASE)
81+
8082
@classmethod
8183
def _search_path(cls, root, pattern):
8284
if not root.is_dir():
8385
return ()
8486
normalized = pattern.replace('-', '_')
87+
matcher = cls.search_template.format(pattern=normalized)
88+
return (item for item in root.iterdir()
89+
if cls._predicate(matcher, root, item))
90+
91+
92+
@install
93+
class MetadataPathFinder(MetadataPathBaseFinder):
94+
search_template = r'{pattern}(-.*)?\.(dist|egg)-info'
95+
96+
97+
@install
98+
class MetadataPathEggInfoFileFinder(MetadataPathBaseFinder):
99+
search_template = r'{pattern}(-.*)?\.egg-info'
100+
101+
@classmethod
102+
def _predicate(cls, pattern, root, item):
85103
return (
86-
item
87-
for item in root.iterdir()
88-
if re.match(
89-
cls.search_template.format(pattern=normalized),
90-
str(item.name),
91-
flags=re.IGNORECASE,
92-
)
93-
)
104+
(root / item).is_file() and
105+
re.match(pattern, str(item.name), flags=re.IGNORECASE))
94106

95107

96108
class PathDistribution(Distribution):

importlib_metadata/tests/fixtures.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,27 @@ def setUp(self):
127127
build_files(EggInfoPkg.files, prefix=self.site_dir)
128128

129129

130+
class EggInfoFile(SiteDir):
131+
files = {
132+
"egginfo_file.egg-info": """
133+
Metadata-Version: 1.0
134+
Name: egginfo_file
135+
Version: 0.1
136+
Summary: An example package
137+
Home-page: www.example.com
138+
Author: Eric Haffa-Vee
139+
Author-email: [email protected]
140+
License: UNKNOWN
141+
Description: UNKNOWN
142+
Platform: UNKNOWN
143+
""",
144+
}
145+
146+
def setUp(self):
147+
super(EggInfoFile, self).setUp()
148+
build_files(EggInfoFile.files, prefix=self.site_dir)
149+
150+
130151
class LocalPackage:
131152
def setUp(self):
132153
self.fixtures = ExitStack()
@@ -136,15 +157,15 @@ def setUp(self):
136157

137158

138159
def build_files(file_defs, prefix=pathlib.Path()):
139-
"""
140-
Build a set of files/directories, as described by the
141-
file_defs dictionary.
142-
Each key/value pair in the dictionary is interpreted as
143-
a filename/contents
144-
pair. If the contents value is a dictionary, a directory
145-
is created, and the
146-
dictionary interpreted as the files within it, recursively.
160+
"""Build a set of files/directories, as described by the
161+
162+
file_defs dictionary. Each key/value pair in the dictionary is
163+
interpreted as a filename/contents pair. If the contents value is a
164+
dictionary, a directory is created, and the dictionary interpreted
165+
as the files within it, recursively.
166+
147167
For example:
168+
148169
{"README.txt": "A README file",
149170
"foo": {
150171
"__init__.py": "",

importlib_metadata/tests/test_api.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616
from __builtin__ import unicode as text
1717

1818

19-
class APITests(fixtures.EggInfoPkg, fixtures.DistInfoPkg, unittest.TestCase):
19+
class APITests(
20+
fixtures.EggInfoPkg,
21+
fixtures.DistInfoPkg,
22+
fixtures.EggInfoFile,
23+
unittest.TestCase):
24+
2025
version_pattern = r'\d+\.\d+(\.\d)?'
2126

2227
def test_retrieves_version_of_self(self):
@@ -100,6 +105,10 @@ def test_files_dist_info(self):
100105
def test_files_egg_info(self):
101106
self._test_files(importlib_metadata.files('egginfo-pkg'))
102107

108+
def test_version_egg_info_file(self):
109+
version = importlib_metadata.version('egginfo-file')
110+
self.assertEqual(version, '0.1')
111+
103112
def test_requires(self):
104113
deps = importlib_metadata.requires('egginfo-pkg')
105114
assert any(

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ skip_missing_interpreters = True
1010
install_command =
1111
python -c 'import subprocess, sys; pip_inst_cmd = sys.executable, "-m", "pip", "install"; subprocess.check_call(pip_inst_cmd + ("pip<19.1", )); subprocess.check_call(pip_inst_cmd + tuple(sys.argv[1:]))' {opts} {packages}
1212
commands =
13-
nocov: python -m unittest discover
13+
nocov: python -m unittest discover {posargs}
1414
cov,diffcov: python -m coverage run {[coverage]rc} -m unittest discover {posargs}
1515
cov,diffcov: python -m coverage combine {[coverage]rc}
1616
cov: python -m coverage html {[coverage]rc}

0 commit comments

Comments
 (0)