• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import functools
2import operator
3import itertools
4
5from .extern.jaraco.text import yield_lines
6from .extern.jaraco.functools import pass_none
7from ._importlib import metadata
8from ._itertools import ensure_unique
9from .extern.more_itertools import consume
10
11
12def ensure_valid(ep):
13    """
14    Exercise one of the dynamic properties to trigger
15    the pattern match.
16    """
17    ep.extras
18
19
20def load_group(value, group):
21    """
22    Given a value of an entry point or series of entry points,
23    return each as an EntryPoint.
24    """
25    # normalize to a single sequence of lines
26    lines = yield_lines(value)
27    text = f'[{group}]\n' + '\n'.join(lines)
28    return metadata.EntryPoints._from_text(text)
29
30
31def by_group_and_name(ep):
32    return ep.group, ep.name
33
34
35def validate(eps: metadata.EntryPoints):
36    """
37    Ensure entry points are unique by group and name and validate each.
38    """
39    consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name)))
40    return eps
41
42
43@functools.singledispatch
44def load(eps):
45    """
46    Given a Distribution.entry_points, produce EntryPoints.
47    """
48    groups = itertools.chain.from_iterable(
49        load_group(value, group)
50        for group, value in eps.items())
51    return validate(metadata.EntryPoints(groups))
52
53
54@load.register(str)
55def _(eps):
56    r"""
57    >>> ep, = load('[console_scripts]\nfoo=bar')
58    >>> ep.group
59    'console_scripts'
60    >>> ep.name
61    'foo'
62    >>> ep.value
63    'bar'
64    """
65    return validate(metadata.EntryPoints(metadata.EntryPoints._from_text(eps)))
66
67
68load.register(type(None), lambda x: x)
69
70
71@pass_none
72def render(eps: metadata.EntryPoints):
73    by_group = operator.attrgetter('group')
74    groups = itertools.groupby(sorted(eps, key=by_group), by_group)
75
76    return '\n'.join(
77        f'[{group}]\n{render_items(items)}\n'
78        for group, items in groups
79    )
80
81
82def render_items(eps):
83    return '\n'.join(
84        f'{ep.name} = {ep.value}'
85        for ep in sorted(eps)
86    )
87