Skip to content

Commit ac1128a

Browse files
jaracoclaude
andcommitted
gh-123976: Document backport caveats for custom providers
Describe how the separate class hierarchies in importlib.metadata and the importlib_metadata backport affect custom providers: which objects the backport substitutes, which it passes through with a warning, and why a provider should implement the whole interface and rely on the shared protocols rather than on a particular base class. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 5a17b2e commit ac1128a

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

‎Doc/library/importlib.metadata.rst‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,3 +735,53 @@ packages served by the ``DatabaseImporter``, assuming that the
735735
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.
738+
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`.
743+
744+
.. _metadata-backport-caveats:
745+
746+
Caveats for backports
747+
---------------------
748+
749+
The :pypi:`importlib_metadata` package backports this module and supplies its
750+
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.
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 cannot do so
764+
for an arbitrary :class:`Distribution` subclass from a custom provider, having
765+
no way to reconstruct that subclass. Such an object is passed through
766+
unchanged, and the backport emits a :exc:`UserWarning` reporting the
767+
unrecognized subclass.
768+
769+
A passed-through object still serves the consumer, provided it implements the
770+
whole interface rather than part of it. 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`. A
776+
provider that assembles its objects some other way supplies every member
777+
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.
783+
784+
Deriving from whichever of the two libraries happens to be importable is not a
785+
general answer. A provider cannot know whether a consumer will import the
786+
backport, and importing it to find out activates it in environments that would
787+
otherwise never have used it.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Document how custom ``importlib.metadata`` providers interact with the
2+
``importlib_metadata`` backport.

0 commit comments

Comments
 (0)