|
import functools |
|
import operator |
|
import itertools |
|
|
|
from .errors import OptionError |
|
from .extern.jaraco.text import yield_lines |
|
from .extern.jaraco.functools import pass_none |
|
from ._importlib import metadata |
|
from ._itertools import ensure_unique |
|
from .extern.more_itertools import consume |
|
|
|
|
|
def ensure_valid(ep): |
|
""" |
|
Exercise one of the dynamic properties to trigger |
|
the pattern match. |
|
""" |
|
try: |
|
ep.extras |
|
except AttributeError as ex: |
|
msg = ( |
|
f"Problems to parse {ep}.\nPlease ensure entry-point follows the spec: " |
|
"https://packaging.python.org/en/latest/specifications/entry-points/" |
|
) |
|
raise OptionError(msg) from ex |
|
|
|
|
|
def load_group(value, group): |
|
""" |
|
Given a value of an entry point or series of entry points, |
|
return each as an EntryPoint. |
|
""" |
|
|
|
lines = yield_lines(value) |
|
text = f'[{group}]\n' + '\n'.join(lines) |
|
return metadata.EntryPoints._from_text(text) |
|
|
|
|
|
def by_group_and_name(ep): |
|
return ep.group, ep.name |
|
|
|
|
|
def validate(eps: metadata.EntryPoints): |
|
""" |
|
Ensure entry points are unique by group and name and validate each. |
|
""" |
|
consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name))) |
|
return eps |
|
|
|
|
|
@functools.singledispatch |
|
def load(eps): |
|
""" |
|
Given a Distribution.entry_points, produce EntryPoints. |
|
""" |
|
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): |
|
r""" |
|
>>> ep, = load('[console_scripts]\nfoo=bar') |
|
>>> ep.group |
|
'console_scripts' |
|
>>> ep.name |
|
'foo' |
|
>>> ep.value |
|
'bar' |
|
""" |
|
return validate(metadata.EntryPoints(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 |
|
) |
|
|
|
|
|
def render_items(eps): |
|
return '\n'.join( |
|
f'{ep.name} = {ep.value}' |
|
for ep in sorted(eps) |
|
) |
|
|