@@ -125,8 +125,8 @@ Entry points
125125 :meth: `!select ` method for comparison to the attributes of
126126 the individual entry point definitions.
127127
128- Note: it is not currently possible to query for entry points based on
129- their :attr: ` !EntryPoint.dist ` attribute (as different :class: `! Distribution `
128+ Note: to query for entry points based on :attr: ` !EntryPoint.dist ` attribute,
129+ use :meth: ` Distribution.entry_points ` instead (as different :class: `Distribution `
130130 instances do not currently compare equal, even if they have the same attributes)
131131
132132.. class :: EntryPoints
@@ -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
309320The :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.
402412Distributions
403413=============
404414
415+ While the module level API described above is the most common and convenient usage,
416+ all that information is accessible 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+ 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,85 @@ 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=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+ :type: PackageMetadata
430469
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::
470+ There are all kinds of additional metadata available on :class: `!Distribution `
471+ instances as a :class: `PackageMetadata ` instance::
437472
438- >>> from importlib .metadata import distribution # doctest: +SKIP
439- >>> dist = distribution('wheel') # doctest: +SKIP
440- >>> type( dist) # doctest: +SKIP
441- <class 'importlib.metadata.PathDistribution'>
473+ >>> dist .metadata['Requires-Python'] # doctest: +SKIP
474+ '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
475+ >>> dist.metadata['License'] # doctest: +SKIP
476+ 'MIT'
442477
443- Thus, an alternative way to get the version number is through the
444- :class: ` !Distribution ` instance::
478+ The full set of available metadata is not described here.
479+ See the PyPA ` Core metadata specification < https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata >`_ for additional details.
445480
446- >>> dist.version # doctest: +SKIP
447- '0.32.3'
481+ .. attribute :: name
482+ :type: str
483+ .. attribute :: requires
484+ :type: list[str]
485+ .. attribute :: version
486+ :type: str
448487
449- There are all kinds of additional metadata available on :class: `!Distribution `
450- instances::
488+ A few metadata fields are also available as shortcut properties.
451489
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'
490+ .. versionadded :: 3.10
456491
457- For editable packages, an ``origin `` property may present :pep: `610 `
458- metadata::
492+ The ``name `` shortcut was added.
459493
460- >>> dist.origin.url
461- 'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl'
494+ .. attribute :: origin
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+ For editable packages, an ``origin `` property may present :pep: `610 `
497+ metadata (for non-editable packages, ``origin `` is :const: `None `)::
498+
499+ >>> dist.origin.url
500+ 'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl'
501+
502+ The ``origin `` object follows the `Direct URL Data Structure
503+ <https://packaging.python.org/en/latest/specifications/direct-url-data-structure/> `_.
504+
505+ .. versionadded :: 3.13
506+
507+ .. attribute :: entry_points
508+ :type: EntryPoints
509+
510+ The entry points provided by this distribution package.
511+
512+ .. attribute :: files
513+ :type: list[PackagePath] | None
514+
515+ All files contained in this distribution package.
516+ Like :func: `files `, this returns :const: `None ` if there are no records.
517+
518+ The following two abstract methods need to be implemented when implementing-custom-providers _:
519+
520+ .. method :: locate_file(path)
521+
522+ Like :meth: `!PackagePath.locate `, return a :class: `SimplePath ` for the given path.
523+ Takes a :class: `os.PathLike ` or a :class: `str `.
524+
525+ .. method :: read_text(filename)
526+
527+ A shortcut for ``distribution.locate_file(filename).read_text() ``.
465528
466- .. versionadded :: 3.13
467- The ``.origin `` property was added.
529+ .. _distribution-discovery :
468530
469531Distribution Discovery
470532======================
@@ -575,8 +637,8 @@ consumer.
575637
576638In practice, to support finding distribution package
577639metadata 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
640+ :class: ` ! Distribution ` and implement the abstract methods. Then from
641+ a custom finder, return instances of this derived :class: ` ! Distribution ` in the
580642``find_distributions() `` method.
581643
582644Example
@@ -653,8 +715,8 @@ packages served by the ``DatabaseImporter``, assuming that the
653715``.entry_points `` attributes.
654716
655717The ``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.
718+ ``RECORD `` (required for :attr: ` ! Distribution.files `) or override the
719+ implementation of :attr: ` ! Distribution.files `. See the source for more inspiration.
658720
659721
660722.. _`entry point API` : https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points
0 commit comments