[Python-checkins] bpo-43428: Improve documentation for importlib.metadata changes. (GH-24858)

jaraco webhook-mailer at python.org
Sun Mar 14 22:20:58 EDT 2021


https://github.com/python/cpython/commit/35d5068928ab5485e5f28b60b1e33062bc2c46cc
commit: 35d5068928ab5485e5f28b60b1e33062bc2c46cc
branch: master
author: Jason R. Coombs <jaraco at jaraco.com>
committer: jaraco <jaraco at jaraco.com>
date: 2021-03-14T22:20:49-04:00
summary:

bpo-43428: Improve documentation for importlib.metadata changes. (GH-24858)

* bpo-43428: Sync with importlib_metadata 3.7.3 (16ac3a95)

* Add 'versionadded' for importlib.metadata.packages_distributions

* Add section in what's new for Python 3.10 highlighting most salient changes and relevant backport.

files:
M Doc/library/importlib.metadata.rst
M Doc/whatsnew/3.10.rst
M Lib/importlib/metadata.py

diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst
index ffce1bae979b5..fee5e677823f7 100644
--- a/Doc/library/importlib.metadata.rst
+++ b/Doc/library/importlib.metadata.rst
@@ -79,15 +79,43 @@ Entry points are represented by ``EntryPoint`` instances;
 each ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and
 a ``.load()`` method to resolve the value.  There are also ``.module``,
 ``.attr``, and ``.extras`` attributes for getting the components of the
-``.value`` attribute::
+``.value`` attribute.
+
+Query all entry points::
 
     >>> eps = entry_points()  # doctest: +SKIP
+
+The ``entry_points()`` function returns an ``EntryPoints`` object,
+a sequence of all ``EntryPoint`` objects with ``names`` and ``groups``
+attributes for convenience::
+
     >>> sorted(eps.groups)  # doctest: +SKIP
     ['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']
+
+``EntryPoints`` has a ``select`` method to select entry points
+matching specific properties. Select entry points in the
+``console_scripts`` group::
+
     >>> scripts = eps.select(group='console_scripts')  # doctest: +SKIP
+
+Equivalently, since ``entry_points`` passes keyword arguments
+through to select::
+
+    >>> scripts = entry_points(group='console_scripts')  # doctest: +SKIP
+
+Pick out a specific script named "wheel" (found in the wheel project)::
+
     >>> 'wheel' in scripts.names  # doctest: +SKIP
     True
     >>> wheel = scripts['wheel']  # doctest: +SKIP
+
+Equivalently, query for that entry point during selection::
+
+    >>> (wheel,) = entry_points(group='console_scripts', name='wheel')  # doctest: +SKIP
+    >>> (wheel,) = entry_points().select(group='console_scripts', name='wheel')  # doctest: +SKIP
+
+Inspect the resolved entry point::
+
     >>> wheel  # doctest: +SKIP
     EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')
     >>> wheel.module  # doctest: +SKIP
@@ -106,6 +134,17 @@ group.  Read `the setuptools docs
 <https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins>`_
 for more information on entry points, their definition, and usage.
 
+*Compatibility Note*
+
+The "selectable" entry points were introduced in ``importlib_metadata``
+3.6 and Python 3.10. Prior to those changes, ``entry_points`` accepted
+no parameters and always returned a dictionary of entry points, keyed
+by group. For compatibility, if no parameters are passed to entry_points,
+a ``SelectableGroups`` object is returned, implementing that dict
+interface. In the future, calling ``entry_points`` with no parameters
+will return an ``EntryPoints`` object. Users should rely on the selection
+interface to retrieve entry points by group.
+
 
 .. _metadata:
 
@@ -199,6 +238,8 @@ Python packages or modules::
     >>> packages_distributions()
     {'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], 'jaraco': ['jaraco.classes', 'jaraco.functools'], ...}
 
+.. versionadded:: 3.10
+
 
 Distributions
 =============
diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst
index db36f69e8d711..c4c282e5a04ea 100644
--- a/Doc/whatsnew/3.10.rst
+++ b/Doc/whatsnew/3.10.rst
@@ -690,6 +690,19 @@ Added the *root_dir* and *dir_fd* parameters in :func:`~glob.glob` and
 :func:`~glob.iglob` which allow to specify the root directory for searching.
 (Contributed by Serhiy Storchaka in :issue:`38144`.)
 
+importlib.metadata
+------------------
+
+Feature parity with ``importlib_metadata`` 3.7.
+
+:func:`importlib.metadata.entry_points` now provides a nicer experience
+for selecting entry points by group and name through a new
+:class:`importlib.metadata.EntryPoints` class.
+
+Added :func:`importlib.metadata.packages_distributions` for resolving
+top-level Python modules and packages to their
+:class:`importlib.metadata.Distribution`.
+
 inspect
 -------
 
diff --git a/Lib/importlib/metadata.py b/Lib/importlib/metadata.py
index 8a731858cad70..53c1a145f5c43 100644
--- a/Lib/importlib/metadata.py
+++ b/Lib/importlib/metadata.py
@@ -4,7 +4,6 @@
 import csv
 import sys
 import email
-import inspect
 import pathlib
 import zipfile
 import operator
@@ -12,7 +11,7 @@
 import functools
 import itertools
 import posixpath
-import collections.abc
+import collections
 
 from ._itertools import unique_everseen
 
@@ -33,6 +32,7 @@
     'entry_points',
     'files',
     'metadata',
+    'packages_distributions',
     'requires',
     'version',
 ]
@@ -158,21 +158,33 @@ class EntryPoints(tuple):
     __slots__ = ()
 
     def __getitem__(self, name):  # -> EntryPoint:
+        """
+        Get the EntryPoint in self matching name.
+        """
         try:
             return next(iter(self.select(name=name)))
         except StopIteration:
             raise KeyError(name)
 
     def select(self, **params):
+        """
+        Select entry points from self that match the
+        given parameters (typically group and/or name).
+        """
         return EntryPoints(ep for ep in self if ep.matches(**params))
 
     @property
     def names(self):
+        """
+        Return the set of all names of all entry points.
+        """
         return set(ep.name for ep in self)
 
     @property
     def groups(self):
         """
+        Return the set of all groups of all entry points.
+
         For coverage while SelectableGroups is present.
         >>> EntryPoints().groups
         set()
@@ -185,6 +197,9 @@ def _from_text_for(cls, text, dist):
 
 
 def flake8_bypass(func):
+    # defer inspect import as performance optimization.
+    import inspect
+
     is_flake8 = any('flake8' in str(frame.filename) for frame in inspect.stack()[:5])
     return func if not is_flake8 else lambda: None
 
@@ -813,6 +828,7 @@ def packages_distributions() -> Mapping[str, List[str]]:
     Return a mapping of top-level packages to their
     distributions.
 
+    >>> import collections.abc
     >>> pkgs = packages_distributions()
     >>> all(isinstance(dist, collections.abc.Sequence) for dist in pkgs.values())
     True



More information about the Python-checkins mailing list