Skip to content

Commit be9a5de

Browse files
jaracoclaude
andcommitted
gh-123976: Document the protocols shared with the backport
Assume the shared protocols from python/importlib_metadata#505 are presented by this module as well: document IDistribution and IPackagePath, correct PackageMetadata, which is already a protocol here rather than an implementation of the backport's, and write the caveats around the protocols as the interface both libraries satisfy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 69a4d48 commit be9a5de

2 files changed

Lines changed: 42 additions & 18 deletions

File tree

‎Doc/library/importlib.metadata.rst‎

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,12 @@ Distribution metadata
237237

238238
.. class:: PackageMetadata
239239

240-
A concrete implementation of the
241-
`PackageMetadata protocol <https://importlib-metadata.readthedocs.io/en/latest/api.html#importlib_metadata.PackageMetadata>`_.
240+
A protocol describing the interface distribution metadata presents. The
241+
:pypi:`importlib_metadata` backport presents the same protocol; see
242+
:ref:`metadata-backport-caveats`.
242243

243-
In addition to providing the defined protocol methods and attributes, subscripting
244-
the instance is equivalent to calling the :meth:`!get` method.
244+
In addition to the protocol methods and attributes, subscripting an
245+
instance is equivalent to calling the :meth:`!get` method.
245246

246247
Every `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_
247248
includes some metadata, which you can extract using the :func:`!metadata` function::
@@ -332,6 +333,13 @@ Distribution files
332333
check if it ``exists()``, to traverse using ``joinpath()`` and ``parent``,
333334
and to retrieve data using ``read_text()`` and ``read_bytes()``.
334335

336+
.. class:: IPackagePath
337+
338+
A protocol describing the interface a :class:`PackagePath` presents. See
339+
:ref:`metadata-backport-caveats`.
340+
341+
.. versionadded:: 3.16
342+
335343
The :func:`!files` function takes a
336344
`Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_
337345
name and returns all of the files installed by this distribution. For example::
@@ -544,6 +552,17 @@ The same applies for :func:`entry_points` and :func:`files`.
544552

545553
A shortcut for ``distribution.locate_file(filename).read_text()``.
546554

555+
.. class:: IDistribution
556+
557+
A protocol describing the interface a :class:`Distribution` presents.
558+
559+
A consumer that targets this protocol, rather than a concrete class, works
560+
with distributions from either this module or the
561+
:pypi:`importlib_metadata` backport, however they were supplied. See
562+
:ref:`metadata-backport-caveats`.
563+
564+
.. versionadded:: 3.16
565+
547566
.. _distribution-discovery:
548567

549568
Distribution Discovery
@@ -748,10 +767,15 @@ Caveats for backports
748767

749768
The :pypi:`importlib_metadata` package backports this module and supplies its
750769
own :class:`!Distribution`, :class:`!PackagePath`, and metadata classes. Those
751-
classes are separate from the ones in :mod:`!importlib.metadata`; neither set
752-
derives from the other. Both libraries discover distributions by querying the
753-
finders on :data:`sys.meta_path`, so one custom provider serves consumers of
754-
both and has no say in which of the two a given consumer uses.
770+
classes are separate from the ones here; neither set derives from the other.
771+
Both libraries discover distributions by querying the finders on
772+
:data:`sys.meta_path`, so one custom provider serves consumers of both and has
773+
no say in which of the two a given consumer uses.
774+
775+
Both libraries present the same protocols, :class:`IDistribution`,
776+
:class:`IPackagePath`, and :class:`PackageMetadata`, and the classes of both
777+
satisfy them. Those protocols, rather than any concrete class, are the
778+
interface to write against.
755779

756780
For consumers
757781
-------------
@@ -765,24 +789,23 @@ substituting its own class for each object it recognizes, such as a
765789
:class:`Distribution` subclass from a custom provider, so it passes such an
766790
object through unchanged.
767791

768-
Rely on an object satisfying the interface rather than on its type, and do not
769-
test it with :func:`isinstance` against a concrete class. The backport
770-
publishes ``IDistribution``, ``IPackagePath``, and ``PackageMetadata``
771-
protocols for this purpose, which the classes of both libraries satisfy.
772-
Import them from the backport; this module does not present them yet.
792+
Annotate against the protocols, then, and do not test an object with
793+
:func:`isinstance` against a concrete class. Code that needs the protocols on
794+
earlier Python versions can import them from the backport, which presents them
795+
there too.
773796

774797
.. _metadata-backport-providers:
775798

776799
For custom providers
777800
--------------------
778801

779802
A provider's objects reach consumers of both libraries, so supply objects that
780-
present the whole interface, not part of it. Deriving from
803+
satisfy :class:`IDistribution` whole, not in part. Deriving from
781804
:class:`Distribution`, as the example above does, achieves this: the base
782805
class builds the rest of the interface on :meth:`~Distribution.read_text` and
783-
:meth:`~Distribution.locate_file`. Where a class omits a member the interface
806+
:meth:`~Distribution.locate_file`. Where a class omits a member the protocol
784807
requires, the backport emits a :exc:`UserWarning` naming what is missing; a
785-
provider presenting the whole interface draws no warning.
808+
provider satisfying the protocol whole draws no warning.
786809

787810
Deriving from whichever of the two libraries happens to be importable is not a
788811
general answer. A provider cannot know whether a consumer will import the
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
Document how custom ``importlib.metadata`` providers interact with the
2-
``importlib_metadata`` backport.
1+
Document the ``IDistribution``, ``IPackagePath``, and ``PackageMetadata``
2+
protocols shared with the ``importlib_metadata`` backport, and how custom
3+
providers and consumers of ``importlib.metadata`` should use them.

0 commit comments

Comments
 (0)