Skip to content

Commit 2db4dad

Browse files
committed
Introduce SelectableGroups, created for the 3.x line to provide forward compatibilty to the new interfaces without sacrificing backward compatibility.
1 parent d6f7c20 commit 2db4dad

File tree

3 files changed

+65
-10
lines changed

3 files changed

+65
-10
lines changed

CHANGES.rst

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
v4.0.0
1+
v3.6.0
22
======
33

44
* #284: Introduces new ``EntryPoints`` object, a tuple of
@@ -13,10 +13,21 @@ v4.0.0
1313
- Item access (e.g. ``eps[name]``) retrieves a single
1414
entry point by name.
1515

16-
``entry_points()`` now returns an ``EntryPoints``
17-
object, but provides for backward compatibility with
18-
a ``__getitem__`` accessor by group and a ``get()``
19-
method.
16+
``entry_points`` now accepts "selection parameters",
17+
same as ``EntryPoint.select()``.
18+
19+
``entry_points()`` now provides a future-compatible
20+
``SelectableGroups`` object that supplies the above interface
21+
but remains a dict for compatibility.
22+
23+
In the future, ``entry_points()`` will return an
24+
``EntryPoints`` object, but provide for backward
25+
compatibility with a deprecated ``__getitem__``
26+
accessor by group and a ``get()`` method.
27+
28+
If passing selection parameters to ``entry_points``, the
29+
future behavior is invoked and an ``EntryPoints`` is the
30+
result.
2031

2132
Construction of entry points using
2233
``dict([EntryPoint, ...])`` is now deprecated and raises

docs/using.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ This package provides the following functionality via its public API.
6767
Entry points
6868
------------
6969

70-
The ``entry_points()`` function returns a sequence of all entry points,
71-
keyed by group. Entry points are represented by ``EntryPoint`` instances;
70+
The ``entry_points()`` function returns a collection of entry points.
71+
Entry points are represented by ``EntryPoint`` instances;
7272
each ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and
7373
a ``.load()`` method to resolve the value. There are also ``.module``,
7474
``.attr``, and ``.extras`` attributes for getting the components of the

importlib_metadata/__init__.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,37 @@ def _from_text_for(cls, text, dist):
187187
return cls(ep._for(dist) for ep in EntryPoint._from_text(text))
188188

189189

190+
class SelectableGroups(dict):
191+
"""
192+
A backward- and forward-compatible result from
193+
entry_points that fully implements the dict interface.
194+
"""
195+
196+
@classmethod
197+
def load(cls, eps):
198+
by_group = operator.attrgetter('group')
199+
ordered = sorted(eps, key=by_group)
200+
grouped = itertools.groupby(ordered, by_group)
201+
return cls((group, EntryPoints(eps)) for group, eps in grouped)
202+
203+
@property
204+
def groups(self):
205+
return self.keys()
206+
207+
@property
208+
def names(self):
209+
return (ep.name for ep in self._all)
210+
211+
@property
212+
def _all(self):
213+
return itertools.chain.from_iterable(self.values())
214+
215+
def select(self, **params):
216+
if not params:
217+
return self
218+
return EntryPoints(self._all).select(**params)
219+
220+
190221
class LegacyGroupedEntryPoints(EntryPoints):
191222
"""
192223
Compatibility wrapper around EntryPoints to provide
@@ -713,16 +744,29 @@ def version(distribution_name):
713744
return distribution(distribution_name).version
714745

715746

716-
def entry_points(**params):
747+
def entry_points(**params) -> Union[EntryPoints, SelectableGroups]:
717748
"""Return EntryPoint objects for all installed packages.
718749
719-
:return: EntryPoint objects for all installed packages.
750+
Pass selection parameters (group or name) to filter the
751+
result to entry points matching those properties (see
752+
EntryPoints.select()).
753+
754+
For compatibility, returns ``SelectableGroups`` object unless
755+
selection parameters are supplied. In the future, this function
756+
will return ``LegacyGroupedEntryPoints`` instead of
757+
``SelectableGroups`` and eventually will only return
758+
``EntryPoints``.
759+
760+
For maximum future compatibility, pass selection parameters
761+
or invoke ``.select`` with parameters on the result.
762+
763+
:return: EntryPoints or SelectableGroups for all installed packages.
720764
"""
721765
unique = functools.partial(unique_everseen, key=operator.attrgetter('name'))
722766
eps = itertools.chain.from_iterable(
723767
dist.entry_points for dist in unique(distributions())
724768
)
725-
return LegacyGroupedEntryPoints(eps).select(**params)
769+
return SelectableGroups.load(eps).select(**params)
726770

727771

728772
def files(distribution_name):

0 commit comments

Comments
 (0)