Aluode/PerceptionLabPortable
0
1import functools2import itertools3import operator4 5from jaraco.functools import pass_none6from jaraco.text import yield_lines7from more_itertools import consume8 9from ._importlib import metadata10from ._itertools import ensure_unique11from .errors import OptionError12 13 14def ensure_valid(ep):15 """16 Exercise one of the dynamic properties to trigger17 the pattern match.18 19 This function is deprecated in favor of importlib_metadata 8.7 and20 Python 3.14 importlib.metadata, which validates entry points on21 construction.22 """23 try:24 ep.extras25 except (AttributeError, AssertionError) as ex:26 # Why both? See https://github.com/python/importlib_metadata/issues/48827 msg = (28 f"Problems to parse {ep}.\nPlease ensure entry-point follows the spec: "29 "https://packaging.python.org/en/latest/specifications/entry-points/"30 )31 raise OptionError(msg) from ex32 33 34def load_group(value, group):35 """36 Given a value of an entry point or series of entry points,37 return each as an EntryPoint.38 """39 # normalize to a single sequence of lines40 lines = yield_lines(value)41 text = f'[{group}]\n' + '\n'.join(lines)42 return metadata.EntryPoints._from_text(text)43 44 45def by_group_and_name(ep):46 return ep.group, ep.name47 48 49def validate(eps: metadata.EntryPoints):50 """51 Ensure entry points are unique by group and name and validate each.52 """53 consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name)))54 return eps55 56 57@functools.singledispatch58def load(eps):59 """60 Given a Distribution.entry_points, produce EntryPoints.61 """62 groups = itertools.chain.from_iterable(63 load_group(value, group) for group, value in eps.items()64 )65 return validate(metadata.EntryPoints(groups))66 67 68@load.register(str)69def _(eps):70 r"""71 >>> ep, = load('[console_scripts]\nfoo=bar')72 >>> ep.group73 'console_scripts'74 >>> ep.name75 'foo'76 >>> ep.value77 'bar'78 """79 return validate(metadata.EntryPoints(metadata.EntryPoints._from_text(eps)))80 81 82load.register(type(None), lambda x: x)83 84 85@pass_none86def render(eps: metadata.EntryPoints):87 by_group = operator.attrgetter('group')88 groups = itertools.groupby(sorted(eps, key=by_group), by_group)89 90 return '\n'.join(f'[{group}]\n{render_items(items)}\n' for group, items in groups)91 92 93def render_items(eps):94 return '\n'.join(f'{ep.name} = {ep.value}' for ep in sorted(eps))95 