17db96d56Sopenharmony_ci.. _using:
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci=================================
47db96d56Sopenharmony_ci Using :mod:`!importlib.metadata`
57db96d56Sopenharmony_ci=================================
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci.. module:: importlib.metadata
87db96d56Sopenharmony_ci   :synopsis: The implementation of the importlib metadata.
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci.. versionadded:: 3.8
117db96d56Sopenharmony_ci.. versionchanged:: 3.10
127db96d56Sopenharmony_ci   ``importlib.metadata`` is no longer provisional.
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci**Source code:** :source:`Lib/importlib/metadata/__init__.py`
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci``importlib_metadata`` is a library that provides access to
177db96d56Sopenharmony_cithe metadata of an installed `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_,
187db96d56Sopenharmony_cisuch as its entry points
197db96d56Sopenharmony_cior its top-level names (`Import Package <https://packaging.python.org/en/latest/glossary/#term-Import-Package>`_\s, modules, if any).
207db96d56Sopenharmony_ciBuilt in part on Python's import system, this library
217db96d56Sopenharmony_ciintends to replace similar functionality in the `entry point
227db96d56Sopenharmony_ciAPI`_ and `metadata API`_ of ``pkg_resources``.  Along with
237db96d56Sopenharmony_ci:mod:`importlib.resources`,
247db96d56Sopenharmony_cithis package can eliminate the need to use the older and less efficient
257db96d56Sopenharmony_ci``pkg_resources`` package.
267db96d56Sopenharmony_ci
277db96d56Sopenharmony_ci``importlib_metadata`` operates on third-party *distribution packages*
287db96d56Sopenharmony_ciinstalled into Python's ``site-packages`` directory via tools such as
297db96d56Sopenharmony_ci`pip <https://pypi.org/project/pip/>`_.
307db96d56Sopenharmony_ciSpecifically, it works with distributions with discoverable
317db96d56Sopenharmony_ci``dist-info`` or ``egg-info`` directories,
327db96d56Sopenharmony_ciand metadata defined by the `Core metadata specifications <https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata>`_.
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci.. important::
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci   These are *not* necessarily equivalent to or correspond 1:1 with
377db96d56Sopenharmony_ci   the top-level *import package* names
387db96d56Sopenharmony_ci   that can be imported inside Python code.
397db96d56Sopenharmony_ci   One *distribution package* can contain multiple *import packages*
407db96d56Sopenharmony_ci   (and single modules),
417db96d56Sopenharmony_ci   and one top-level *import package*
427db96d56Sopenharmony_ci   may map to multiple *distribution packages*
437db96d56Sopenharmony_ci   if it is a namespace package.
447db96d56Sopenharmony_ci   You can use :ref:`package_distributions() <package-distributions>`
457db96d56Sopenharmony_ci   to get a mapping between them.
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ciBy default, distribution metadata can live on the file system
487db96d56Sopenharmony_cior in zip archives on
497db96d56Sopenharmony_ci:data:`sys.path`.  Through an extension mechanism, the metadata can live almost
507db96d56Sopenharmony_cianywhere.
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci.. seealso::
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ci   https://importlib-metadata.readthedocs.io/
567db96d56Sopenharmony_ci      The documentation for ``importlib_metadata``, which supplies a
577db96d56Sopenharmony_ci      backport of ``importlib.metadata``.
587db96d56Sopenharmony_ci      This includes an `API reference
597db96d56Sopenharmony_ci      <https://importlib-metadata.readthedocs.io/en/latest/api.html>`__
607db96d56Sopenharmony_ci      for this module's classes and functions,
617db96d56Sopenharmony_ci      as well as a `migration guide
627db96d56Sopenharmony_ci      <https://importlib-metadata.readthedocs.io/en/latest/migration.html>`__
637db96d56Sopenharmony_ci      for existing users of ``pkg_resources``.
647db96d56Sopenharmony_ci
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ciOverview
677db96d56Sopenharmony_ci========
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ciLet's say you wanted to get the version string for a
707db96d56Sopenharmony_ci`Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_ you've installed
717db96d56Sopenharmony_ciusing ``pip``.  We start by creating a virtual environment and installing
727db96d56Sopenharmony_cisomething into it:
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci.. code-block:: shell-session
757db96d56Sopenharmony_ci
767db96d56Sopenharmony_ci    $ python -m venv example
777db96d56Sopenharmony_ci    $ source example/bin/activate
787db96d56Sopenharmony_ci    (example) $ python -m pip install wheel
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ciYou can get the version string for ``wheel`` by running the following:
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci.. code-block:: pycon
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci    (example) $ python
857db96d56Sopenharmony_ci    >>> from importlib.metadata import version  # doctest: +SKIP
867db96d56Sopenharmony_ci    >>> version('wheel')  # doctest: +SKIP
877db96d56Sopenharmony_ci    '0.32.3'
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ciYou can also get a collection of entry points selectable by properties of the EntryPoint (typically 'group' or 'name'), such as
907db96d56Sopenharmony_ci``console_scripts``, ``distutils.commands`` and others.  Each group contains a
917db96d56Sopenharmony_cicollection of :ref:`EntryPoint <entry-points>` objects.
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ciYou can get the :ref:`metadata for a distribution <metadata>`::
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci    >>> list(metadata('wheel'))  # doctest: +SKIP
967db96d56Sopenharmony_ci    ['Metadata-Version', 'Name', 'Version', 'Summary', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License', 'Project-URL', 'Project-URL', 'Project-URL', 'Keywords', 'Platform', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Requires-Python', 'Provides-Extra', 'Requires-Dist', 'Requires-Dist']
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ciYou can also get a :ref:`distribution's version number <version>`, list its
997db96d56Sopenharmony_ci:ref:`constituent files <files>`, and get a list of the distribution's
1007db96d56Sopenharmony_ci:ref:`requirements`.
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ciFunctional API
1047db96d56Sopenharmony_ci==============
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_ciThis package provides the following functionality via its public API.
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci.. _entry-points:
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ciEntry points
1127db96d56Sopenharmony_ci------------
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ciThe ``entry_points()`` function returns a collection of entry points.
1157db96d56Sopenharmony_ciEntry points are represented by ``EntryPoint`` instances;
1167db96d56Sopenharmony_cieach ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and
1177db96d56Sopenharmony_cia ``.load()`` method to resolve the value.  There are also ``.module``,
1187db96d56Sopenharmony_ci``.attr``, and ``.extras`` attributes for getting the components of the
1197db96d56Sopenharmony_ci``.value`` attribute.
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ciQuery all entry points::
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci    >>> eps = entry_points()  # doctest: +SKIP
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_ciThe ``entry_points()`` function returns an ``EntryPoints`` object,
1267db96d56Sopenharmony_cia collection of all ``EntryPoint`` objects with ``names`` and ``groups``
1277db96d56Sopenharmony_ciattributes for convenience::
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci    >>> sorted(eps.groups)  # doctest: +SKIP
1307db96d56Sopenharmony_ci    ['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci``EntryPoints`` has a ``select`` method to select entry points
1337db96d56Sopenharmony_cimatching specific properties. Select entry points in the
1347db96d56Sopenharmony_ci``console_scripts`` group::
1357db96d56Sopenharmony_ci
1367db96d56Sopenharmony_ci    >>> scripts = eps.select(group='console_scripts')  # doctest: +SKIP
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ciEquivalently, since ``entry_points`` passes keyword arguments
1397db96d56Sopenharmony_cithrough to select::
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ci    >>> scripts = entry_points(group='console_scripts')  # doctest: +SKIP
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ciPick out a specific script named "wheel" (found in the wheel project)::
1447db96d56Sopenharmony_ci
1457db96d56Sopenharmony_ci    >>> 'wheel' in scripts.names  # doctest: +SKIP
1467db96d56Sopenharmony_ci    True
1477db96d56Sopenharmony_ci    >>> wheel = scripts['wheel']  # doctest: +SKIP
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ciEquivalently, query for that entry point during selection::
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci    >>> (wheel,) = entry_points(group='console_scripts', name='wheel')  # doctest: +SKIP
1527db96d56Sopenharmony_ci    >>> (wheel,) = entry_points().select(group='console_scripts', name='wheel')  # doctest: +SKIP
1537db96d56Sopenharmony_ci
1547db96d56Sopenharmony_ciInspect the resolved entry point::
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ci    >>> wheel  # doctest: +SKIP
1577db96d56Sopenharmony_ci    EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')
1587db96d56Sopenharmony_ci    >>> wheel.module  # doctest: +SKIP
1597db96d56Sopenharmony_ci    'wheel.cli'
1607db96d56Sopenharmony_ci    >>> wheel.attr  # doctest: +SKIP
1617db96d56Sopenharmony_ci    'main'
1627db96d56Sopenharmony_ci    >>> wheel.extras  # doctest: +SKIP
1637db96d56Sopenharmony_ci    []
1647db96d56Sopenharmony_ci    >>> main = wheel.load()  # doctest: +SKIP
1657db96d56Sopenharmony_ci    >>> main  # doctest: +SKIP
1667db96d56Sopenharmony_ci    <function main at 0x103528488>
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ciThe ``group`` and ``name`` are arbitrary values defined by the package author
1697db96d56Sopenharmony_ciand usually a client will wish to resolve all entry points for a particular
1707db96d56Sopenharmony_cigroup.  Read `the setuptools docs
1717db96d56Sopenharmony_ci<https://setuptools.pypa.io/en/latest/userguide/entry_point.html>`_
1727db96d56Sopenharmony_cifor more information on entry points, their definition, and usage.
1737db96d56Sopenharmony_ci
1747db96d56Sopenharmony_ci*Compatibility Note*
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ciThe "selectable" entry points were introduced in ``importlib_metadata``
1777db96d56Sopenharmony_ci3.6 and Python 3.10. Prior to those changes, ``entry_points`` accepted
1787db96d56Sopenharmony_cino parameters and always returned a dictionary of entry points, keyed
1797db96d56Sopenharmony_ciby group. For compatibility, if no parameters are passed to entry_points,
1807db96d56Sopenharmony_cia ``SelectableGroups`` object is returned, implementing that dict
1817db96d56Sopenharmony_ciinterface. In the future, calling ``entry_points`` with no parameters
1827db96d56Sopenharmony_ciwill return an ``EntryPoints`` object. Users should rely on the selection
1837db96d56Sopenharmony_ciinterface to retrieve entry points by group.
1847db96d56Sopenharmony_ci
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci.. _metadata:
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ciDistribution metadata
1897db96d56Sopenharmony_ci---------------------
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ciEvery `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_ includes some metadata,
1927db96d56Sopenharmony_ciwhich you can extract using the
1937db96d56Sopenharmony_ci``metadata()`` function::
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci    >>> wheel_metadata = metadata('wheel')  # doctest: +SKIP
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ciThe keys of the returned data structure, a ``PackageMetadata``,
1987db96d56Sopenharmony_ciname the metadata keywords, and
1997db96d56Sopenharmony_cithe values are returned unparsed from the distribution metadata::
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci    >>> wheel_metadata['Requires-Python']  # doctest: +SKIP
2027db96d56Sopenharmony_ci    '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
2037db96d56Sopenharmony_ci
2047db96d56Sopenharmony_ci``PackageMetadata`` also presents a ``json`` attribute that returns
2057db96d56Sopenharmony_ciall the metadata in a JSON-compatible form per :PEP:`566`::
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_ci    >>> wheel_metadata.json['requires_python']
2087db96d56Sopenharmony_ci    '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci.. note::
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci    The actual type of the object returned by ``metadata()`` is an
2137db96d56Sopenharmony_ci    implementation detail and should be accessed only through the interface
2147db96d56Sopenharmony_ci    described by the
2157db96d56Sopenharmony_ci    `PackageMetadata protocol <https://importlib-metadata.readthedocs.io/en/latest/api.html#importlib_metadata.PackageMetadata>`_.
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci.. versionchanged:: 3.10
2187db96d56Sopenharmony_ci   The ``Description`` is now included in the metadata when presented
2197db96d56Sopenharmony_ci   through the payload. Line continuation characters have been removed.
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_ci.. versionadded:: 3.10
2227db96d56Sopenharmony_ci   The ``json`` attribute was added.
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci
2257db96d56Sopenharmony_ci.. _version:
2267db96d56Sopenharmony_ci
2277db96d56Sopenharmony_ciDistribution versions
2287db96d56Sopenharmony_ci---------------------
2297db96d56Sopenharmony_ci
2307db96d56Sopenharmony_ciThe ``version()`` function is the quickest way to get a
2317db96d56Sopenharmony_ci`Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_'s version
2327db96d56Sopenharmony_cinumber, as a string::
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_ci    >>> version('wheel')  # doctest: +SKIP
2357db96d56Sopenharmony_ci    '0.32.3'
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci.. _files:
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ciDistribution files
2417db96d56Sopenharmony_ci------------------
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ciYou can also get the full set of files contained within a distribution.  The
2447db96d56Sopenharmony_ci``files()`` function takes a `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_ name
2457db96d56Sopenharmony_ciand returns all of the
2467db96d56Sopenharmony_cifiles installed by this distribution.  Each file object returned is a
2477db96d56Sopenharmony_ci``PackagePath``, a :class:`pathlib.PurePath` derived object with additional ``dist``,
2487db96d56Sopenharmony_ci``size``, and ``hash`` properties as indicated by the metadata.  For example::
2497db96d56Sopenharmony_ci
2507db96d56Sopenharmony_ci    >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0]  # doctest: +SKIP
2517db96d56Sopenharmony_ci    >>> util  # doctest: +SKIP
2527db96d56Sopenharmony_ci    PackagePath('wheel/util.py')
2537db96d56Sopenharmony_ci    >>> util.size  # doctest: +SKIP
2547db96d56Sopenharmony_ci    859
2557db96d56Sopenharmony_ci    >>> util.dist  # doctest: +SKIP
2567db96d56Sopenharmony_ci    <importlib.metadata._hooks.PathDistribution object at 0x101e0cef0>
2577db96d56Sopenharmony_ci    >>> util.hash  # doctest: +SKIP
2587db96d56Sopenharmony_ci    <FileHash mode: sha256 value: bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI>
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ciOnce you have the file, you can also read its contents::
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci    >>> print(util.read_text())  # doctest: +SKIP
2637db96d56Sopenharmony_ci    import base64
2647db96d56Sopenharmony_ci    import sys
2657db96d56Sopenharmony_ci    ...
2667db96d56Sopenharmony_ci    def as_bytes(s):
2677db96d56Sopenharmony_ci        if isinstance(s, text_type):
2687db96d56Sopenharmony_ci            return s.encode('utf-8')
2697db96d56Sopenharmony_ci        return s
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ciYou can also use the ``locate`` method to get a the absolute path to the
2727db96d56Sopenharmony_cifile::
2737db96d56Sopenharmony_ci
2747db96d56Sopenharmony_ci    >>> util.locate()  # doctest: +SKIP
2757db96d56Sopenharmony_ci    PosixPath('/home/gustav/example/lib/site-packages/wheel/util.py')
2767db96d56Sopenharmony_ci
2777db96d56Sopenharmony_ciIn the case where the metadata file listing files
2787db96d56Sopenharmony_ci(RECORD or SOURCES.txt) is missing, ``files()`` will
2797db96d56Sopenharmony_cireturn ``None``. The caller may wish to wrap calls to
2807db96d56Sopenharmony_ci``files()`` in `always_iterable
2817db96d56Sopenharmony_ci<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.always_iterable>`_
2827db96d56Sopenharmony_cior otherwise guard against this condition if the target
2837db96d56Sopenharmony_cidistribution is not known to have the metadata present.
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci.. _requirements:
2867db96d56Sopenharmony_ci
2877db96d56Sopenharmony_ciDistribution requirements
2887db96d56Sopenharmony_ci-------------------------
2897db96d56Sopenharmony_ci
2907db96d56Sopenharmony_ciTo get the full set of requirements for a `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_,
2917db96d56Sopenharmony_ciuse the ``requires()``
2927db96d56Sopenharmony_cifunction::
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci    >>> requires('wheel')  # doctest: +SKIP
2957db96d56Sopenharmony_ci    ["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ci
2987db96d56Sopenharmony_ci.. _package-distributions:
2997db96d56Sopenharmony_ci.. _import-distribution-package-mapping:
3007db96d56Sopenharmony_ci
3017db96d56Sopenharmony_ciMapping import to distribution packages
3027db96d56Sopenharmony_ci---------------------------------------
3037db96d56Sopenharmony_ci
3047db96d56Sopenharmony_ciA convenience method to resolve the `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_
3057db96d56Sopenharmony_ciname (or names, in the case of a namespace package)
3067db96d56Sopenharmony_cithat provide each importable top-level
3077db96d56Sopenharmony_ciPython module or `Import Package <https://packaging.python.org/en/latest/glossary/#term-Import-Package>`_::
3087db96d56Sopenharmony_ci
3097db96d56Sopenharmony_ci    >>> packages_distributions()
3107db96d56Sopenharmony_ci    {'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], 'jaraco': ['jaraco.classes', 'jaraco.functools'], ...}
3117db96d56Sopenharmony_ci
3127db96d56Sopenharmony_ci.. versionadded:: 3.10
3137db96d56Sopenharmony_ci
3147db96d56Sopenharmony_ci.. _distributions:
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_ciDistributions
3177db96d56Sopenharmony_ci=============
3187db96d56Sopenharmony_ci
3197db96d56Sopenharmony_ciWhile the above API is the most common and convenient usage, you can get all
3207db96d56Sopenharmony_ciof that information from the ``Distribution`` class.  A ``Distribution`` is an
3217db96d56Sopenharmony_ciabstract object that represents the metadata for
3227db96d56Sopenharmony_cia Python `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_.  You can
3237db96d56Sopenharmony_ciget the ``Distribution`` instance::
3247db96d56Sopenharmony_ci
3257db96d56Sopenharmony_ci    >>> from importlib.metadata import distribution  # doctest: +SKIP
3267db96d56Sopenharmony_ci    >>> dist = distribution('wheel')  # doctest: +SKIP
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ciThus, an alternative way to get the version number is through the
3297db96d56Sopenharmony_ci``Distribution`` instance::
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ci    >>> dist.version  # doctest: +SKIP
3327db96d56Sopenharmony_ci    '0.32.3'
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_ciThere are all kinds of additional metadata available on the ``Distribution``
3357db96d56Sopenharmony_ciinstance::
3367db96d56Sopenharmony_ci
3377db96d56Sopenharmony_ci    >>> dist.metadata['Requires-Python']  # doctest: +SKIP
3387db96d56Sopenharmony_ci    '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
3397db96d56Sopenharmony_ci    >>> dist.metadata['License']  # doctest: +SKIP
3407db96d56Sopenharmony_ci    'MIT'
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_ciThe full set of available metadata is not described here.
3437db96d56Sopenharmony_ciSee the `Core metadata specifications <https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata>`_ for additional details.
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ci
3467db96d56Sopenharmony_ciDistribution Discovery
3477db96d56Sopenharmony_ci======================
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ciBy default, this package provides built-in support for discovery of metadata
3507db96d56Sopenharmony_cifor file system and zip file `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_\s.
3517db96d56Sopenharmony_ciThis metadata finder search defaults to ``sys.path``, but varies slightly in how it interprets those values from how other import machinery does. In particular:
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci- ``importlib.metadata`` does not honor :class:`bytes` objects on ``sys.path``.
3547db96d56Sopenharmony_ci- ``importlib.metadata`` will incidentally honor :py:class:`pathlib.Path` objects on ``sys.path`` even though such values will be ignored for imports.
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci
3577db96d56Sopenharmony_ciExtending the search algorithm
3587db96d56Sopenharmony_ci==============================
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ciBecause `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_ metadata
3617db96d56Sopenharmony_ciis not available through :data:`sys.path` searches, or
3627db96d56Sopenharmony_cipackage loaders directly,
3637db96d56Sopenharmony_cithe metadata for a distribution is found through import
3647db96d56Sopenharmony_cisystem `finders`_.  To find a distribution package's metadata,
3657db96d56Sopenharmony_ci``importlib.metadata`` queries the list of :term:`meta path finders <meta path finder>` on
3667db96d56Sopenharmony_ci:data:`sys.meta_path`.
3677db96d56Sopenharmony_ci
3687db96d56Sopenharmony_ciBy default ``importlib_metadata`` installs a finder for distribution packages
3697db96d56Sopenharmony_cifound on the file system.
3707db96d56Sopenharmony_ciThis finder doesn't actually find any *distributions*,
3717db96d56Sopenharmony_cibut it can find their metadata.
3727db96d56Sopenharmony_ci
3737db96d56Sopenharmony_ciThe abstract class :py:class:`importlib.abc.MetaPathFinder` defines the
3747db96d56Sopenharmony_ciinterface expected of finders by Python's import system.
3757db96d56Sopenharmony_ci``importlib.metadata`` extends this protocol by looking for an optional
3767db96d56Sopenharmony_ci``find_distributions`` callable on the finders from
3777db96d56Sopenharmony_ci:data:`sys.meta_path` and presents this extended interface as the
3787db96d56Sopenharmony_ci``DistributionFinder`` abstract base class, which defines this abstract
3797db96d56Sopenharmony_cimethod::
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ci    @abc.abstractmethod
3827db96d56Sopenharmony_ci    def find_distributions(context=DistributionFinder.Context()):
3837db96d56Sopenharmony_ci        """Return an iterable of all Distribution instances capable of
3847db96d56Sopenharmony_ci        loading the metadata for packages for the indicated ``context``.
3857db96d56Sopenharmony_ci        """
3867db96d56Sopenharmony_ci
3877db96d56Sopenharmony_ciThe ``DistributionFinder.Context`` object provides ``.path`` and ``.name``
3887db96d56Sopenharmony_ciproperties indicating the path to search and name to match and may
3897db96d56Sopenharmony_cisupply other relevant context.
3907db96d56Sopenharmony_ci
3917db96d56Sopenharmony_ciWhat this means in practice is that to support finding distribution package
3927db96d56Sopenharmony_cimetadata in locations other than the file system, subclass
3937db96d56Sopenharmony_ci``Distribution`` and implement the abstract methods. Then from
3947db96d56Sopenharmony_cia custom finder, return instances of this derived ``Distribution`` in the
3957db96d56Sopenharmony_ci``find_distributions()`` method.
3967db96d56Sopenharmony_ci
3977db96d56Sopenharmony_ci
3987db96d56Sopenharmony_ci.. _`entry point API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points
3997db96d56Sopenharmony_ci.. _`metadata API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#metadata-api
4007db96d56Sopenharmony_ci.. _`finders`: https://docs.python.org/3/reference/import.html#finders-and-loaders
401