@@ -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+
190221class 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
728772def files (distribution_name ):
0 commit comments