Skip to content

Commit 69a4d48

Browse files
jaracoclaude
andcommitted
gh-123976: Separate the consumer and provider caveats
The guidance to rely on the interface rather than the type addresses every consumer, not only a provider that consumes metadata, so promote the caveats to their own section and split it by audience. Note that the protocols come from the backport, which this module does not yet present. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent ab57ac7 commit 69a4d48

1 file changed

Lines changed: 39 additions & 36 deletions

File tree

‎Doc/library/importlib.metadata.rst‎

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -736,50 +736,53 @@ The ``DatabaseDistribution`` may also provide other metadata files, like
736736
``RECORD`` (required for :attr:`!Distribution.files`) or override the
737737
implementation of :attr:`!Distribution.files`. See the source for more inspiration.
738738

739-
Because ``DatabaseDistribution`` derives from :class:`Distribution` as defined
740-
here, consumers that use the :pypi:`importlib_metadata` backport instead of
741-
this module receive objects from a hierarchy they do not expect. See
742-
:ref:`metadata-backport-caveats`.
739+
``DatabaseDistribution`` derives from :class:`Distribution` as defined here,
740+
which has consequences for consumers that use the :pypi:`importlib_metadata`
741+
backport instead of this module. See :ref:`metadata-backport-providers`.
742+
743743

744744
.. _metadata-backport-caveats:
745745

746746
Caveats for backports
747-
---------------------
747+
=====================
748748

749749
The :pypi:`importlib_metadata` package backports this module and supplies its
750750
own :class:`!Distribution`, :class:`!PackagePath`, and metadata classes. Those
751751
classes are separate from the ones in :mod:`!importlib.metadata`; neither set
752-
derives from the other.
753-
754-
A custom provider has no say in which of the two a consumer uses. Both
755-
libraries discover distributions by querying the finders on
756-
:data:`sys.meta_path`, so a single provider installed there serves both. A
757-
consumer calling ``importlib_metadata.distributions()`` expects that package's
758-
objects, but a provider deriving from the :class:`Distribution` class
759-
documented here supplies objects from the other hierarchy.
760-
761-
The backport settles most of this on the consumer's behalf, substituting its
762-
own class for each object it recognizes, such as a :class:`!PathDistribution`,
763-
a :class:`PackagePath`, or an :class:`email.message.Message`. It has no way to
764-
reconstruct an arbitrary :class:`Distribution` subclass from a custom
765-
provider, so it passes such an object through unchanged. That serves the
766-
consumer as long as the object presents the whole interface; where the class
767-
omits a member the interface requires, the backport emits a
768-
:exc:`UserWarning` naming what is missing.
769-
770-
So, when writing a custom provider:
771-
772-
* Supply objects that present the whole interface, not part of it. Deriving
773-
from :class:`Distribution`, as the example above does, achieves this: the
774-
base class builds the rest of the interface on
775-
:meth:`~Distribution.read_text` and :meth:`~Distribution.locate_file`, and
776-
such a provider draws no warning. A provider that assembles its objects
777-
some other way supplies every member itself.
778-
* Where the provider itself consumes metadata, and in the guidance offered to
779-
its users, rely on the object satisfying that interface rather than on its
780-
type. The backport publishes ``IDistribution``, ``IPackagePath``, and
781-
``PackageMetadata`` protocols for this purpose, which both its classes and
782-
the ones documented here satisfy.
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.
755+
756+
For consumers
757+
-------------
758+
759+
A consumer calling ``importlib_metadata.distributions()`` expects that
760+
package's objects, but a custom provider may supply objects from the hierarchy
761+
documented here. The backport settles most of this on the consumer's behalf,
762+
substituting its own class for each object it recognizes, such as a
763+
:class:`!PathDistribution`, a :class:`PackagePath`, or an
764+
:class:`email.message.Message`. It has no way to reconstruct an arbitrary
765+
:class:`Distribution` subclass from a custom provider, so it passes such an
766+
object through unchanged.
767+
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.
773+
774+
.. _metadata-backport-providers:
775+
776+
For custom providers
777+
--------------------
778+
779+
A provider's objects reach consumers of both libraries, so supply objects that
780+
present the whole interface, not part of it. Deriving from
781+
:class:`Distribution`, as the example above does, achieves this: the base
782+
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
784+
requires, the backport emits a :exc:`UserWarning` naming what is missing; a
785+
provider presenting the whole interface draws no warning.
783786

784787
Deriving from whichever of the two libraries happens to be importable is not a
785788
general answer. A provider cannot know whether a consumer will import the

0 commit comments

Comments
 (0)