https://github.com/python/cpython/commit/ae7fc4a4f6b711173bb70d23755ec15b8ac958a6
commit: ae7fc4a4f6b711173bb70d23755ec15b8ac958a6
branch: main
author: Philipp A. <[email protected]>
committer: jaraco <[email protected]>
date: 2026-02-23T18:51:03-05:00
summary:

gh-110937: Document full public importlib.metadata.Distribution API (#143480)

files:
A Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst
M Doc/library/importlib.metadata.rst
M Lib/importlib/metadata/__init__.py

diff --git a/Doc/library/importlib.metadata.rst 
b/Doc/library/importlib.metadata.rst
index 9e08e5aa989cf7..cc426326b29932 100644
--- a/Doc/library/importlib.metadata.rst
+++ b/Doc/library/importlib.metadata.rst
@@ -125,8 +125,8 @@ Entry points
    :meth:`!select` method for comparison to the attributes of
    the individual entry point definitions.
 
-   Note: it is not currently possible to query for entry points based on
-   their :attr:`!EntryPoint.dist` attribute (as different 
:class:`!Distribution`
+   Note: to query for entry points based on :attr:`!EntryPoint.dist` attribute,
+   use :meth:`Distribution.entry_points` instead (as different 
:class:`Distribution`
    instances do not currently compare equal, even if they have the same 
attributes)
 
 .. class:: EntryPoints
@@ -291,7 +291,7 @@ Distribution files
 .. function:: files(distribution_name)
 
    Return the full set of files contained within the named
-   distribution package.
+   distribution package as :class:`PackagePath` instances.
 
    Raises :exc:`PackageNotFoundError` if the named distribution
    package is not installed in the current Python environment.
@@ -304,12 +304,22 @@ Distribution files
 
     A :class:`pathlib.PurePath` derived object with additional ``dist``,
     ``size``, and ``hash`` properties corresponding to the distribution
-    package's installation metadata for that file.
+    package's installation metadata for that file, also:
+
+    .. method:: locate()
+
+       If possible, return the concrete :class:`SimplePath` allowing to access 
data,
+       or raise a :exc:`NotImplementedError` otherwise.
+
+.. class:: SimplePath
+
+    A protocol representing a minimal subset of :class:`pathlib.Path` that 
allows to
+    check if it ``exists()``, to traverse using ``joinpath()`` and ``parent``,
+    and to retrieve data using ``read_text()`` and ``read_bytes()``.
 
 The :func:`!files` function takes a
 `Distribution Package 
<https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_
-name and returns all of the files installed by this distribution. Each file is 
reported
-as a :class:`PackagePath` instance. For example::
+name and returns all of the files installed by this distribution. For example::
 
     >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0]  # 
doctest: +SKIP
     >>> util  # doctest: +SKIP
@@ -402,6 +412,18 @@ function is not reliable with such installs.
 Distributions
 =============
 
+While the module level API described above is the most common and convenient 
usage,
+all that information is accessible from the :class:`Distribution` class.
+:class:`!Distribution` is an abstract object that represents the metadata for
+a Python `Distribution Package 
<https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_.
+Get the concrete :class:`!Distribution` subclass instance for an installed
+distribution package by calling the :func:`distribution` function::
+
+    >>> from importlib.metadata import distribution  # doctest: +SKIP
+    >>> dist = distribution('wheel')  # doctest: +SKIP
+    >>> type(dist)  # doctest: +SKIP
+    <class 'importlib.metadata.PathDistribution'>
+
 .. function:: distribution(distribution_name)
 
    Return a :class:`Distribution` instance describing the named
@@ -410,6 +432,14 @@ Distributions
    Raises :exc:`PackageNotFoundError` if the named distribution
    package is not installed in the current Python environment.
 
+Thus, an alternative way to get e.g. the version number is through the
+:attr:`Distribution.version` attribute::
+
+    >>> dist.version  # doctest: +SKIP
+    '0.32.3'
+
+The same applies for :func:`entry_points` and :func:`files`.
+
 .. class:: Distribution
 
    Details of an installed distribution package.
@@ -418,53 +448,85 @@ Distributions
    equal, even if they relate to the same installed distribution and
    accordingly have the same attributes.
 
-   .. method:: discover(cls, *, context=None, **kwargs)
+   .. staticmethod:: at(path)
+   .. classmethod:: from_name(name)
+
+      Return a :class:`!Distribution` instance at the given path or
+      with the given name.
 
-      Returns an iterable of :class:`Distribution` instances for all packages.
+   .. classmethod:: discover(*, context=None, **kwargs)
+
+      Returns an iterable of :class:`!Distribution` instances for all packages
+      (see distribution-discovery_).
 
       The optional argument *context* is a :class:`DistributionFinder.Context`
       instance, used to modify the search for distributions. Alternatively,
       *kwargs* may contain keyword arguments for constructing a new
       :class:`!DistributionFinder.Context`.
 
+   .. attribute:: metadata
+      :type: PackageMetadata
 
-While the module level API described above is the most common and convenient 
usage,
-you can get all of that information from the :class:`!Distribution` class.
-:class:`!Distribution` is an abstract object that represents the metadata for
-a Python `Distribution Package 
<https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_.
-You can get the concrete :class:`!Distribution` subclass instance for an 
installed
-distribution package by calling the :func:`distribution` function::
+      There are all kinds of additional metadata available on 
:class:`!Distribution`
+      instances as a :class:`PackageMetadata` instance::
 
-    >>> from importlib.metadata import distribution  # doctest: +SKIP
-    >>> dist = distribution('wheel')  # doctest: +SKIP
-    >>> type(dist)  # doctest: +SKIP
-    <class 'importlib.metadata.PathDistribution'>
+          >>> dist.metadata['Requires-Python']  # doctest: +SKIP
+          '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
+          >>> dist.metadata['License']  # doctest: +SKIP
+          'MIT'
 
-Thus, an alternative way to get the version number is through the
-:class:`!Distribution` instance::
+      The full set of available metadata is not described here.
+      See the PyPA `Core metadata specification 
<https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata>`_
 for additional details.
 
-    >>> dist.version  # doctest: +SKIP
-    '0.32.3'
+   .. attribute:: name
+      :type: str
+   .. attribute:: requires
+      :type: list[str]
+   .. attribute:: version
+      :type: str
 
-There are all kinds of additional metadata available on :class:`!Distribution`
-instances::
+      A few metadata fields are also available as shortcut properties.
 
-    >>> dist.metadata['Requires-Python']  # doctest: +SKIP
-    '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
-    >>> dist.metadata['License']  # doctest: +SKIP
-    'MIT'
+      .. versionadded:: 3.10
 
-For editable packages, an ``origin`` property may present :pep:`610`
-metadata::
+         The ``name`` shortcut was added.
 
-    >>> dist.origin.url
-    'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl'
+   .. attribute:: origin
 
-The full set of available metadata is not described here.
-See the PyPA `Core metadata specification 
<https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata>`_
 for additional details.
+      For editable packages, an ``origin`` property may present :pep:`610`
+      metadata (for non-editable packages, ``origin`` is :const:`None`)::
+
+         >>> dist.origin.url
+         'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl'
+
+      The ``origin`` object follows the `Direct URL Data Structure
+      
<https://packaging.python.org/en/latest/specifications/direct-url-data-structure/>`_.
+
+      .. versionadded:: 3.13
+
+   .. attribute:: entry_points
+      :type: EntryPoints
+
+      The entry points provided by this distribution package.
+
+   .. attribute:: files
+      :type: list[PackagePath] | None
+
+      All files contained in this distribution package.
+      Like :func:`files`, this returns :const:`None` if there are no records.
+
+   The following two abstract methods need to be implemented when 
implementing-custom-providers_:
+
+   .. method:: locate_file(path)
+
+      Like :meth:`!PackagePath.locate`, return a :class:`SimplePath` for the 
given path.
+      Takes a :class:`os.PathLike` or a :class:`str`.
+
+   .. method:: read_text(filename)
+
+      A shortcut for ``distribution.locate_file(filename).read_text()``.
 
-.. versionadded:: 3.13
-   The ``.origin`` property was added.
+.. _distribution-discovery:
 
 Distribution Discovery
 ======================
@@ -575,8 +637,8 @@ consumer.
 
 In practice, to support finding distribution package
 metadata in locations other than the file system, subclass
-``Distribution`` and implement the abstract methods. Then from
-a custom finder, return instances of this derived ``Distribution`` in the
+:class:`!Distribution` and implement the abstract methods. Then from
+a custom finder, return instances of this derived :class:`!Distribution` in the
 ``find_distributions()`` method.
 
 Example
@@ -653,8 +715,8 @@ packages served by the ``DatabaseImporter``, assuming that 
the
 ``.entry_points`` attributes.
 
 The ``DatabaseDistribution`` may also provide other metadata files, like
-``RECORD`` (required for ``Distribution.files``) or override the
-implementation of ``Distribution.files``. See the source for more inspiration.
+``RECORD`` (required for :attr:`!Distribution.files`) or override the
+implementation of :attr:`!Distribution.files`. See the source for more 
inspiration.
 
 
 .. _`entry point API`: 
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points
diff --git a/Lib/importlib/metadata/__init__.py 
b/Lib/importlib/metadata/__init__.py
index 7cf4d29d330c91..e91acc065ba9ae 100644
--- a/Lib/importlib/metadata/__init__.py
+++ b/Lib/importlib/metadata/__init__.py
@@ -41,6 +41,7 @@
     'DistributionFinder',
     'PackageMetadata',
     'PackageNotFoundError',
+    'PackagePath',
     'SimplePath',
     'distribution',
     'distributions',
diff --git 
a/Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst 
b/Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst
new file mode 100644
index 00000000000000..d29bde5ca690c6
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst
@@ -0,0 +1 @@
+Document rest of full public :class:`importlib.metadata.Distribution` API. 
Also add the (already documented) :class:`~importlib.metadata.PackagePath` to 
``__all__``.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to