Skip to content

Commit 5e0ab5a

Browse files
committed
Document full public importlib.metadata API
1 parent 841b748 commit 5e0ab5a

File tree

2 files changed

+86
-38
lines changed

2 files changed

+86
-38
lines changed

Doc/library/importlib.metadata.rst

Lines changed: 85 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ Distribution files
291291
.. function:: files(distribution_name)
292292

293293
Return the full set of files contained within the named
294-
distribution package.
294+
distribution package as :class:`PackagePath` instances.
295295

296296
Raises :exc:`PackageNotFoundError` if the named distribution
297297
package is not installed in the current Python environment.
@@ -304,12 +304,22 @@ Distribution files
304304

305305
A :class:`pathlib.PurePath` derived object with additional ``dist``,
306306
``size``, and ``hash`` properties corresponding to the distribution
307-
package's installation metadata for that file.
307+
package's installation metadata for that file, also:
308+
309+
.. method:: locate()
310+
311+
If possible, return the concrete :class:`SimplePath` allowing to access data,
312+
or raise a :exc:`NotImplementedError` otherwise.
313+
314+
.. class:: SimplePath
315+
316+
A protocol representing a minimal subset of :class:`pathlib.Path` that allows to
317+
check if it ``exists()``, to traverse using ``joinpath()`` and ``parent``,
318+
and to retrieve data using ``read_text()`` and ``read_bytes()``.
308319

309320
The :func:`!files` function takes a
310321
`Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_
311-
name and returns all of the files installed by this distribution. Each file is reported
312-
as a :class:`PackagePath` instance. For example::
322+
name and returns all of the files installed by this distribution. For example::
313323

314324
>>> util = [p for p in files('wheel') if 'util.py' in str(p)][0] # doctest: +SKIP
315325
>>> util # doctest: +SKIP
@@ -402,6 +412,18 @@ function is not reliable with such installs.
402412
Distributions
403413
=============
404414

415+
While the module level API described above is the most common and convenient usage,
416+
you can get all of that information from the :class:`!Distribution` class.
417+
:class:`!Distribution` is an abstract object that represents the metadata for
418+
a Python `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_.
419+
You can get the concrete :class:`!Distribution` subclass instance for an installed
420+
distribution package by calling the :func:`distribution` function::
421+
422+
>>> from importlib.metadata import distribution # doctest: +SKIP
423+
>>> dist = distribution('wheel') # doctest: +SKIP
424+
>>> type(dist) # doctest: +SKIP
425+
<class 'importlib.metadata.PathDistribution'>
426+
405427
.. function:: distribution(distribution_name)
406428

407429
Return a :class:`Distribution` instance describing the named
@@ -410,6 +432,14 @@ Distributions
410432
Raises :exc:`PackageNotFoundError` if the named distribution
411433
package is not installed in the current Python environment.
412434

435+
Thus, an alternative way to get e.g. the version number is through the
436+
:attr:`!Distribution.version` attribute::
437+
438+
>>> dist.version # doctest: +SKIP
439+
'0.32.3'
440+
441+
The same applies for :func:`entry_points` and :func:`files`.
442+
413443
.. class:: Distribution
414444

415445
Details of an installed distribution package.
@@ -418,53 +448,70 @@ Distributions
418448
equal, even if they relate to the same installed distribution and
419449
accordingly have the same attributes.
420450

421-
.. method:: discover(cls, *, context=None, **kwargs)
451+
.. staticmethod:: at(path)
452+
.. classmethod:: from_name(name)
453+
454+
Return a :class:`!Distribution` instance at the given path or
455+
with the given name.
422456

423-
Returns an iterable of :class:`Distribution` instances for all packages.
457+
.. classmethod:: discover(*, context: Context | None, **kwargs)
458+
459+
Returns an iterable of :class:`Distribution` instances for all packages
460+
(see distribution-discovery_).
424461

425462
The optional argument *context* is a :class:`DistributionFinder.Context`
426463
instance, used to modify the search for distributions. Alternatively,
427464
*kwargs* may contain keyword arguments for constructing a new
428465
:class:`!DistributionFinder.Context`.
429466

467+
.. attribute:: metadata
468+
.. attribute:: name
469+
.. attribute:: requires
470+
.. attribute:: version
430471

431-
While the module level API described above is the most common and convenient usage,
432-
you can get all of that information from the :class:`!Distribution` class.
433-
:class:`!Distribution` is an abstract object that represents the metadata for
434-
a Python `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_.
435-
You can get the concrete :class:`!Distribution` subclass instance for an installed
436-
distribution package by calling the :func:`distribution` function::
472+
There are all kinds of additional metadata available on :class:`!Distribution`
473+
instances as a :class:`PackageMetadata` instance::
437474

438-
>>> from importlib.metadata import distribution # doctest: +SKIP
439-
>>> dist = distribution('wheel') # doctest: +SKIP
440-
>>> type(dist) # doctest: +SKIP
441-
<class 'importlib.metadata.PathDistribution'>
475+
>>> dist.metadata['Requires-Python'] # doctest: +SKIP
476+
'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
477+
>>> dist.metadata['License'] # doctest: +SKIP
478+
'MIT'
442479

443-
Thus, an alternative way to get the version number is through the
444-
:class:`!Distribution` instance::
480+
The full set of available metadata is not described here.
481+
See the PyPA `Core metadata specification <https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata>`_ for additional details.
445482

446-
>>> dist.version # doctest: +SKIP
447-
'0.32.3'
483+
.. attribute:: origin
448484

449-
There are all kinds of additional metadata available on :class:`!Distribution`
450-
instances::
485+
For editable packages, an ``origin`` property may present :pep:`610`
486+
metadata (for non-editable packages, ``origin`` is :const:`None`)::
451487

452-
>>> dist.metadata['Requires-Python'] # doctest: +SKIP
453-
'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
454-
>>> dist.metadata['License'] # doctest: +SKIP
455-
'MIT'
488+
>>> dist.origin.url
489+
'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl'
456490

457-
For editable packages, an ``origin`` property may present :pep:`610`
458-
metadata::
491+
The ``origin`` object follows the `Direct URL Data Structure
492+
<https://packaging.python.org/en/latest/specifications/direct-url-data-structure/>`_.
459493

460-
>>> dist.origin.url
461-
'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl'
494+
.. versionadded:: 3.13
462495

463-
The full set of available metadata is not described here.
464-
See the PyPA `Core metadata specification <https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata>`_ for additional details.
496+
.. attribute:: entry_points
497+
498+
The :class:`!EntryPoints` provided by this distribution package.
499+
500+
.. attribute:: files
501+
502+
A sequence of :class:`!PackagePath`\s contained in this distribution package.
503+
Like :func:`files`, this returns :const:`None` if there are no records.
504+
505+
.. method:: locate_file(path)
506+
507+
Like :meth:`!PackagePath.locate`, return a :class:`SimplePath` for the given path.
508+
Takes a :class:`os.PathLike` or a :class:`str`.
509+
510+
.. method:: read_text(filename)
511+
512+
A shortcut for ``distribution.locate_file(filename).read_text()``.
465513

466-
.. versionadded:: 3.13
467-
The ``.origin`` property was added.
514+
.. _distribution-discovery:
468515

469516
Distribution Discovery
470517
======================
@@ -575,8 +622,8 @@ consumer.
575622

576623
In practice, to support finding distribution package
577624
metadata in locations other than the file system, subclass
578-
``Distribution`` and implement the abstract methods. Then from
579-
a custom finder, return instances of this derived ``Distribution`` in the
625+
:class:`!Distribution` and implement the abstract methods. Then from
626+
a custom finder, return instances of this derived :class:`!Distribution` in the
580627
``find_distributions()`` method.
581628

582629
Example
@@ -653,8 +700,8 @@ packages served by the ``DatabaseImporter``, assuming that the
653700
``.entry_points`` attributes.
654701

655702
The ``DatabaseDistribution`` may also provide other metadata files, like
656-
``RECORD`` (required for ``Distribution.files``) or override the
657-
implementation of ``Distribution.files``. See the source for more inspiration.
703+
``RECORD`` (required for :attr:`!Distribution.files`) or override the
704+
implementation of :attr:`!Distribution.files`. See the source for more inspiration.
658705

659706

660707
.. _`entry point API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points

Lib/importlib/metadata/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
'DistributionFinder',
4242
'PackageMetadata',
4343
'PackageNotFoundError',
44+
'PackagePath',
4445
'SimplePath',
4546
'distribution',
4647
'distributions',

0 commit comments

Comments
 (0)