summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2022-02-06 15:22:38 -0500
committerJason R. Coombs <jaraco@jaraco.com>2022-02-06 15:22:38 -0500
commitebdaa76c3c6c55d5cffd1a80903484d80cf146c6 (patch)
treec61a47022a1d81f0701d02fb3dfa061ee6215fa4 /setuptools
parentc49b7d36f872438020b3ed3b2c1ec0a4a5978f92 (diff)
downloadpython-setuptools-git-ebdaa76c3c6c55d5cffd1a80903484d80cf146c6.tar.gz
Refactor _entry_points to separate loading from rendering. Explicitly validate and restore validation of entry points that don't match the pattern.
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/_entry_points.py72
-rw-r--r--setuptools/command/egg_info.py3
2 files changed, 57 insertions, 18 deletions
diff --git a/setuptools/_entry_points.py b/setuptools/_entry_points.py
index 35109e11..816e61b6 100644
--- a/setuptools/_entry_points.py
+++ b/setuptools/_entry_points.py
@@ -1,41 +1,79 @@
import functools
import operator
+import itertools
from .extern.jaraco.text import yield_lines
+from .extern.jaraco.functools import pass_none
from ._importlib import metadata
from ._itertools import ensure_unique
-@functools.singledispatch
-def render_items(value):
+def ensure_valid(ep):
+ """
+ Exercise one of the dynamic properties to trigger
+ the pattern match.
+ """
+ ep.extras
+ return ep
+
+
+def load_group(value, group):
"""
Given a value of an entry point or series of entry points,
- return each entry point on a single line.
+ return each as an EntryPoint.
"""
# normalize to a single sequence of lines
lines = yield_lines(value)
- parsed = metadata.EntryPoints._from_text('[x]\n' + '\n'.join(lines))
- valid = ensure_unique(parsed, key=operator.attrgetter('name'))
+ text = f'[{group}]\n' + '\n'.join(lines)
+ return metadata.EntryPoints._from_text(text)
+
- def ep_to_str(ep):
- return f'{ep.name} = {ep.value}'
- return '\n'.join(sorted(map(ep_to_str, valid)))
+def by_group_and_name(ep):
+ return ep.group, ep.name
-render_items.register(str, lambda x: x)
+def validate(eps: metadata.EntryPoints):
+ """
+ Ensure entry points are unique by group and name and validate the pattern.
+ """
+ for ep in ensure_unique(eps, key=by_group_and_name):
+ # exercise one of the dynamic properties to trigger validation
+ ep.extras
+ return eps
@functools.singledispatch
-def render(eps):
+def load(eps):
"""
- Given a Distribution.entry_points, produce a multiline
- string definition of those entry points.
+ Given a Distribution.entry_points, produce EntryPoints.
"""
- return ''.join(
- f'[{section}]\n{render_items(contents)}\n\n'
- for section, contents in sorted(eps.items())
+ groups = itertools.chain.from_iterable(
+ load_group(value, group)
+ for group, value in eps.items())
+ return validate(metadata.EntryPoints(groups))
+
+
+@load.register(str)
+def _(eps):
+ return validate(metadata.EntryPoints._from_text(eps))
+
+
+load.register(type(None), lambda x: x)
+
+
+@pass_none
+def render(eps: metadata.EntryPoints):
+ by_group = operator.attrgetter('group')
+ groups = itertools.groupby(sorted(eps, key=by_group), by_group)
+
+ return '\n'.join(
+ f'[{group}]\n{render_items(items)}\n'
+ for group, items in groups
)
-render.register(type(None), lambda x: x)
-render.register(str, lambda x: x)
+def render_items(eps):
+ return '\n'.join(
+ f'{ep.name} = {ep.value}'
+ for ep in sorted(eps)
+ )
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 2e8ca4b7..8af018f4 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -717,7 +717,8 @@ def write_arg(cmd, basename, filename, force=False):
def write_entries(cmd, basename, filename):
- defn = _entry_points.render(cmd.distribution.entry_points)
+ eps = _entry_points.load(cmd.distribution.entry_points)
+ defn = _entry_points.render(eps)
cmd.write_or_delete_file('entry points', filename, defn, True)