@@ -736,50 +736,53 @@ The ``DatabaseDistribution`` may also provide other metadata files, like |
736 | 736 | ``RECORD`` (required for :attr:`!Distribution.files`) or override the |
737 | 737 | implementation of :attr:`!Distribution.files`. See the source for more inspiration. |
738 | 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`. |
| 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 | + |
743 | 743 |
|
744 | 744 | .. _metadata-backport-caveats: |
745 | 745 |
|
746 | 746 | Caveats for backports |
747 | | ---------------------- |
| 747 | +===================== |
748 | 748 |
|
749 | 749 | The :pypi:`importlib_metadata` package backports this module and supplies its |
750 | 750 | own :class:`!Distribution`, :class:`!PackagePath`, and metadata classes. Those |
751 | 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 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. |
783 | 786 |
|
784 | 787 | Deriving from whichever of the two libraries happens to be importable is not a |
785 | 788 | general answer. A provider cannot know whether a consumer will import the |
|