Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Raise consistent ValueError for invalid EntryPoint.value #518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 27, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 47 additions & 12 deletions importlib_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from importlib import import_module
from importlib.abc import MetaPathFinder
from itertools import starmap
from re import Match
from typing import Any, cast

from . import _meta
Expand Down Expand Up @@ -135,6 +134,12 @@ def valid(line: str):
return line and not line.startswith('#')


class _EntryPointMatch(types.SimpleNamespace):
module: str
attr: str
extras: str


class EntryPoint:
"""An entry point as defined by Python packaging conventions.

Expand All @@ -150,6 +155,30 @@ class EntryPoint:
'attr'
>>> ep.extras
['extra1', 'extra2']

If the value package or module are not valid identifiers, a
ValueError is raised on access.

>>> EntryPoint(name=None, group=None, value='invalid-name').module
Traceback (most recent call last):
...
ValueError: ('Invalid object reference...invalid-name...
>>> EntryPoint(name=None, group=None, value='invalid-name').attr
Traceback (most recent call last):
...
ValueError: ('Invalid object reference...invalid-name...
>>> EntryPoint(name=None, group=None, value='invalid-name').extras
Traceback (most recent call last):
...
ValueError: ('Invalid object reference...invalid-name...

The same thing happens on construction.

>>> EntryPoint(name=None, group=None, value='invalid-name')
Traceback (most recent call last):
...
ValueError: ('Invalid object reference...invalid-name...

"""

pattern = re.compile(
Expand Down Expand Up @@ -181,34 +210,40 @@ class EntryPoint:

def __init__(self, name: str, value: str, group: str) -> None:
vars(self).update(name=name, value=value, group=group)
self.module

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

@property
def module(self) -> str:
match = self.pattern.match(self.value)
assert match is not None
return match.group('module')
return self._match.module

@property
def attr(self) -> str:
match = self.pattern.match(self.value)
assert match is not None
return match.group('attr')
return self._match.attr

@property
def extras(self) -> list[str]:
return re.findall(r'\w+', self._match.extras or '')

@functools.cached_property
def _match(self) -> _EntryPointMatch:
match = self.pattern.match(self.value)
assert match is not None
return re.findall(r'\w+', match.group('extras') or '')
if not match:
raise ValueError(
'Invalid object reference. '
'See https://packaging.python.org'
'/en/latest/specifications/entry-points/#data-model',
self.value,
)
return _EntryPointMatch(**match.groupdict())

def _for(self, dist):
vars(self).update(dist=dist)
Expand Down
Loading