File: usage.rst

package info (click to toggle)
python-dist-meta 0.9.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,964 kB
  • sloc: python: 2,944; makefile: 9
file content (276 lines) | stat: -rw-r--r-- 9,058 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
===========================
Using :mod:`dist_meta`
===========================

.. module:: dist_meta

:mod:`dist_meta` is a library that provides for access to installed package metadata,
and parsers for ``METADATA`` and ``entry_points.txt`` files.
The library provides similar functionality to :mod:`importlib.metadata`, entrypoints_, and :mod:`email.parser`

Overview
------------

This example demonstrates how to obtain information about an installed distribution, such as its version number,
summary and requirements.

First, create a fresh virtual environment [1]_ and install wheel_:

.. inline-tab:: Unix/macOS

	.. prompt:: bash

		python3 -m virtualenv example
		source example/bin/activate

.. inline-tab:: Windows

	.. code-block:: powershell

		py -m virtualenv example
		.\\example\\Scripts\\activate.ps1

.. [1] See the `Python Packaging User Guide`_ for more details.

.. code-block:: bash

	(example) $ pip install wheel

You can get the :class:`dist_meta.distributions.Distribution` object for ``wheel``
with the :func:`dist_meta.distributions.get_distribution` function:

.. inline-tab:: Unix/macOS

	.. prompt:: bash

		python3

.. inline-tab:: Windows

	.. code-block:: powershell

		py

.. code-block:: pycon

	>>> from dist_meta.distributions import get_distribution
	>>> wheel_dist = get_distribution("wheel")
	>>> wheel_dist
	<Distribution('wheel', <Version('0.36.2')>)>
	>>> wheel_dist.name
	'wheel'
	>>> wheel_dist.version
	<Version('0.36.2')>

Metadata
^^^^^^^^^^

The metadata_ for ``wheel`` can then be obtained as follows:

.. code-block:: pycon

	>>> meta = wheel_dist.get_metadata()
	>>> meta
	<MetadataMapping({'Metadata-Version': '2.1', 'Name': 'wheel', 'Version': '0.36.2', ...})>
	>>> meta["Name"]
	'wheel'
	>>> meta["Version"]
	'0.36.2'
	>>> meta["License"]
	'MIT'
	>>> meta["Summary"]
	'A built-package format for Python'

This is a :class:`dist_meta.metadata_mapping.MetadataMapping` object.
See the `Python Packaging User Guide <metadata>`__ for details of all supported fields.

Some fields may have only a placeholder value [2]_, and others may be absent:

.. code-block:: pycon

	>>> meta["Platform"]
	'UNKNOWN'
	>>> meta["Obsoletes-Dist"]
	Traceback (most recent call last):
	KeyError: 'Obsoletes-Dist'

.. [2] This is a convention followed by some build tools and not part of :pep:`566`


Requirements
^^^^^^^^^^^^^^^^^^^^

The distribution's requirements (if any) can be obtained from the ``'Requires-Dist'`` field:

.. code-block:: pycon

	>>> requirements = meta.get_all("Requires-Dist")
	>>> requirements
	["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]

These can be converted into :class:`packaging.requirements.Requirement` or
:class:`shippinglabel.requirements.ComparableRequirement` objects easily:

.. code-block:: pycon

	>>> from packaging.requirements import Requirement
	>>> list(map(Requirement, requirements))
	[<Requirement('pytest>=3.0.0; extra == "test"')>, <Requirement('pytest-cov; extra == "test"')>]

Some distributions have no requirements:

.. code-block:: pycon

	>>> get_distribution("pip").get_metadata().get_all("Requires-Dist", default=[])
	[]


Missing Distributions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If the distribution can't be found, a :class:`dist_meta.distributions.DistributionNotFoundError` is raised:

.. code-block:: pycon

	>>> get_distribution("spamspamspam")
	Traceback (most recent call last):
	dist_meta.distributions.DistributionNotFoundError: spamspamspam

Iterating over Distributions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

All installed distributions can be iterated over using the :func:`dist_meta.distributions.iter_distributions` function.
This can be useful to find distributions which meet a particular criteria.

For example, to find all ``sphinxcontrib*`` distributions:

.. code-block:: pycon

	>>> from dist_meta.distributions import iter_distributions
	>>> for distro in iter_distributions():
	...     if distro.name.startswith("sphinxcontrib"):
	...         print(distro)
	<Distribution('sphinxcontrib_applehelp', <Version('1.0.2')>)>
	<Distribution('sphinxcontrib_htmlhelp', <Version('2.0.0')>)>
	<Distribution('sphinxcontrib_jsmath', <Version('1.0.1')>)>
	<Distribution('sphinxcontrib_serializinghtml', <Version('1.1.5')>)>
	<Distribution('sphinxcontrib_qthelp', <Version('1.0.3')>)>
	<Distribution('sphinxcontrib_devhelp', <Version('1.0.2')>)>


Entry Points
------------------

`Entry points`_ are a mechanism for an installed distribution to advertise components it provides
for discovery and used by other code. For example:

* Distributions can specify console_scripts entry points, each referring to a function. When pip_ installs the distribution, it will create a command-line wrapper for each entry point.
* Applications can use entry points to load plugins; e.g. Pygments (a syntax highlighting tool) can use additional lexers and styles from separately installed packages.

Entry points are arranged into groups, such as ``console_scripts`` or ``whey.builder``.

To obtain the entry points for a :class:`~.Distribution`, call its :meth:`~.DistributionType.get_entry_points` method:

.. code-block:: pycon

	>>> wheel_dist
	<Distribution('wheel', <Version('0.36.2')>)>
	>>> entry_points = wheel_dist.get_entry_points()
	>>> entry_points.keys()
	dict_keys(['console_scripts', 'distutils.commands'])

This returns a mapping of group names (as strings) to a mapping of entry point names to values (both strings):

.. code-block:: pycon

	>>> from pprint import pprint
	>>> pprint(entry_points)
	{'console_scripts': {'wheel': 'wheel.cli:main'},
	 'distutils.commands': {'bdist_wheel': 'wheel.bdist_wheel:bdist_wheel'}}

.. latex:clearpage::

:class:`dist_meta.entry_points.EntryPoint` objects can be constructed as follows:

.. code-block:: pycon

	>>> from dist_meta.entry_points import EntryPoint
	>>> for ep in EntryPoint.from_mapping(entry_points["console_scripts"], group="console_scripts"):
	... 	ep
	EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts', distro=None)

.. TODO: These should be xrefs to the indiv. attributes once fixed in sphinx-toolbox

:class:`dist_meta.entry_points.EntryPoint` objects have attributes for accessing the
``name``, ``module`` and ``attribute`` of the entry point:

.. code-block:: pycon

	>>> ep.name
	'wheel'
	>>> ep.value
	'wheel.cli:main'
	>>> ep.module
	'wheel.cli'
	>>> ep.attr
	'main'
	>>> ep.extras
	[]

The object referred to by the entry point can be loaded using the :meth:`~.EntryPoint.load` method:

.. code-block:: pycon

	>>> main = ep.load()
	>>> main
	<function main at 0x7f4a4bcf94c0>

Entry points for all distributions can be obtained using :func:`dist_meta.entry_points.get_entry_points`
and :func:`dist_meta.entry_points.get_all_entry_points`. The former is used to obtain entry points in a specific group,
while the latter will return all entry points grouped in a dictionary.

.. code-block:: pycon

	>>> from dist_meta.entry_points import get_entry_points, get_all_entry_points
	>>> eps = list(get_entry_points("console_scripts"))
	>>> eps[0]
	EntryPoint(name='tabulate', value='tabulate:_main', group='console_scripts', distro=<Distribution('tabulate', <Version('0.8.9')>)>)
	>>> all_eps = get_all_entry_points()
	>>> all_eps.keys()
	dict_keys(['pytest11', 'console_scripts', 'sphinx.html_themes', 'distutils.commands', 'distutils.setup_keywords', 'babel.checkers', 'babel.extractors', 'flake8.extension', 'flake8.report', 'egg_info.writers', 'setuptools.finalize_distribution_options'])


``RECORD`` files
----------------------

The contents of ``RECORD`` files, which specify the contents of a distribution, can be obtained as follows:

.. code-block:: pycon

	>>> wheel_dist
	<Distribution('wheel', <Version('0.36.2')>)>
	>>> record = wheel_dist.get_record()
	>>> record[2]
	RecordEntry('wheel-0.36.2.dist-info/LICENSE.txt', hash=FileHash(name='sha256', value='zKniDGrx_Pv2lAjzd3aShsvuvN7TNhAMm0o_NfvmNeQ'), size=1125, distro=<Distribution('wheel', <Version('0.36.2')>)>)

``record`` is a list of :class:`dist_meta.record.RecordEntry` objects,
which is a subclasses of :class:`pathlib.PurePosixPath` with additional :attr:`~.RecordEntry.size`,
:attr:`~.RecordEntry.hash` and :attr:`~.RecordEntry.distro` attributes.
The content of a file can be obtained using its :meth:`~.RecordEntry.read_text` or :meth:`~.RecordEntry.read_bytes`:

.. code-block:: pycon

	>>> print(record[2].read_text()[:100])
	"wheel" copyright (c) 2012-2014 Daniel Holth <dholth@fastmail.fm> and
	contributors.
	<BLANKLINE>
	The MIT License

If the ``RECORD`` file is absent, :meth:`~.Distribution.get_record` will return :py:obj:`None`.

.. _metadata: https://packaging.python.org/specifications/core-metadata/
.. _wheel: https://pypi.org/project/wheel/
.. _Python Packaging User Guide: https://packaging.python.org/guides/installing-using-pip-and-virtual-environments
.. _pip: https://pypi.org/project/pip/
.. _entrypoints: https://github.com/takluyver/entrypoints/
.. _Entry points: https://packaging.python.org/specifications/entry-points/?highlight=entry%20points