Skip to content

Commit 2afc2e1

Browse files
committed
Restore remaining changes.
1 parent 6bdaff0 commit 2afc2e1

File tree

2 files changed

+37
-17
lines changed

2 files changed

+37
-17
lines changed

Lib/importlib/metadata/__init__.py

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ class _EntryPointMatch(types.SimpleNamespace):
136136
extras: str
137137

138138

139-
from typing import Optional, List, cast, Match
140-
141139
class EntryPoint:
142140
"""An entry point as defined by Python packaging conventions.
143141
@@ -204,38 +202,44 @@ class EntryPoint:
204202
value: str
205203
group: str
206204

207-
dist: Optional[Distribution] = None
205+
dist: Distribution | None = None
208206

209207
def __init__(self, name: str, value: str, group: str) -> None:
210208
vars(self).update(name=name, value=value, group=group)
209+
self.module
211210

212211
def load(self) -> Any:
213212
"""Load the entry point from its definition. If only a module
214213
is indicated by the value, return that module. Otherwise,
215214
return the named object.
216215
"""
217-
match = cast(Match, self.pattern.match(self.value))
218-
module = import_module(match.group('module'))
219-
attrs = filter(None, (match.group('attr') or '').split('.'))
216+
module = import_module(self.module)
217+
attrs = filter(None, (self.attr or '').split('.'))
220218
return functools.reduce(getattr, attrs, module)
221219

222220
@property
223221
def module(self) -> str:
224-
match = self.pattern.match(self.value)
225-
assert match is not None
226-
return match.group('module')
222+
return self._match.module
227223

228224
@property
229225
def attr(self) -> str:
230-
match = self.pattern.match(self.value)
231-
assert match is not None
232-
return match.group('attr')
226+
return self._match.attr
233227

234228
@property
235-
def extras(self) -> List[str]:
229+
def extras(self) -> list[str]:
230+
return re.findall(r'\w+', self._match.extras or '')
231+
232+
@functools.cached_property
233+
def _match(self) -> _EntryPointMatch:
236234
match = self.pattern.match(self.value)
237-
assert match is not None
238-
return re.findall(r'\w+', match.group('extras') or '')
235+
if not match:
236+
raise ValueError(
237+
'Invalid object reference. '
238+
'See https://packaging.python.org'
239+
'/en/latest/specifications/entry-points/#data-model',
240+
self.value,
241+
)
242+
return _EntryPointMatch(**match.groupdict())
239243

240244
def _for(self, dist):
241245
vars(self).update(dist=dist)
@@ -261,9 +265,26 @@ def matches(self, **params):
261265
>>> ep.matches(attr='bong')
262266
True
263267
"""
268+
self._disallow_dist(params)
264269
attrs = (getattr(self, param) for param in params)
265270
return all(map(operator.eq, params.values(), attrs))
266271

272+
@staticmethod
273+
def _disallow_dist(params):
274+
"""
275+
Querying by dist is not allowed (dist objects are not comparable).
276+
>>> EntryPoint(name='fan', value='fav', group='fag').matches(dist='foo')
277+
Traceback (most recent call last):
278+
...
279+
ValueError: "dist" is not suitable for matching...
280+
"""
281+
if "dist" in params:
282+
raise ValueError(
283+
'"dist" is not suitable for matching. '
284+
"Instead, use Distribution.entry_points.select() on a "
285+
"located distribution."
286+
)
287+
267288
def _key(self):
268289
return self.name, self.value, self.group
269290

@@ -1094,7 +1115,7 @@ def packages_distributions() -> Mapping[str, list[str]]:
10941115
pkg_to_dist = collections.defaultdict(list)
10951116
for dist in distributions():
10961117
for pkg in _top_level_declared(dist) or _top_level_inferred(dist):
1097-
pkg_to_dist[pkg].append(dist.metadata['Name'])
1118+
pkg_to_dist[pkg].append(md_none(dist.metadata)['Name'])
10981119
return dict(pkg_to_dist)
10991120

11001121

Lib/test/test_importlib/metadata/test_main.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ def test_valid_dists_preferred(self):
157157
dist = Distribution.from_name('foo')
158158
assert dist.version == "1.0"
159159

160-
@unittest.skip("Functionality disabled")
161160
def test_missing_metadata(self):
162161
"""
163162
Dists with a missing metadata file should return None.

0 commit comments

Comments
 (0)