Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/importlib_metadata/docs/using.rst @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 .. _using: | |
| 2 | |
| 3 ================================= | |
| 4 Using :mod:`!importlib_metadata` | |
| 5 ================================= | |
| 6 | |
| 7 ``importlib_metadata`` is a library that provides for access to installed | |
| 8 package metadata. Built in part on Python's import system, this library | |
| 9 intends to replace similar functionality in the `entry point | |
| 10 API`_ and `metadata API`_ of ``pkg_resources``. Along with | |
| 11 :mod:`importlib.resources` in Python 3.7 | |
| 12 and newer (backported as :doc:`importlib_resources <importlib_resources:index>` for older versions of | |
| 13 Python), this can eliminate the need to use the older and less efficient | |
| 14 ``pkg_resources`` package. | |
| 15 | |
| 16 By "installed package" we generally mean a third-party package installed into | |
| 17 Python's ``site-packages`` directory via tools such as `pip | |
| 18 <https://pypi.org/project/pip/>`_. Specifically, | |
| 19 it means a package with either a discoverable ``dist-info`` or ``egg-info`` | |
| 20 directory, and metadata defined by :pep:`566` or its older specifications. | |
| 21 By default, package metadata can live on the file system or in zip archives on | |
| 22 :data:`sys.path`. Through an extension mechanism, the metadata can live almost | |
| 23 anywhere. | |
| 24 | |
| 25 | |
| 26 Overview | |
| 27 ======== | |
| 28 | |
| 29 Let's say you wanted to get the version string for a package you've installed | |
| 30 using ``pip``. We start by creating a virtual environment and installing | |
| 31 something into it:: | |
| 32 | |
| 33 $ python3 -m venv example | |
| 34 $ source example/bin/activate | |
| 35 (example) $ pip install importlib_metadata | |
| 36 (example) $ pip install wheel | |
| 37 | |
| 38 You can get the version string for ``wheel`` by running the following:: | |
| 39 | |
| 40 (example) $ python | |
| 41 >>> from importlib_metadata import version | |
| 42 >>> version('wheel') | |
| 43 '0.32.3' | |
| 44 | |
| 45 You can also get the set of entry points keyed by group, such as | |
| 46 ``console_scripts``, ``distutils.commands`` and others. Each group contains a | |
| 47 sequence of :ref:`EntryPoint <entry-points>` objects. | |
| 48 | |
| 49 You can get the :ref:`metadata for a distribution <metadata>`:: | |
| 50 | |
| 51 >>> list(metadata('wheel')) | |
| 52 ['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'] | |
| 53 | |
| 54 You can also get a :ref:`distribution's version number <version>`, list its | |
| 55 :ref:`constituent files <files>`, and get a list of the distribution's | |
| 56 :ref:`requirements`. | |
| 57 | |
| 58 | |
| 59 Functional API | |
| 60 ============== | |
| 61 | |
| 62 This package provides the following functionality via its public API. | |
| 63 | |
| 64 | |
| 65 .. _entry-points: | |
| 66 | |
| 67 Entry points | |
| 68 ------------ | |
| 69 | |
| 70 The ``entry_points()`` function returns a dictionary of all entry points, | |
| 71 keyed by group. Entry points are represented by ``EntryPoint`` instances; | |
| 72 each ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and | |
| 73 a ``.load()`` method to resolve the value. There are also ``.module``, | |
| 74 ``.attr``, and ``.extras`` attributes for getting the components of the | |
| 75 ``.value`` attribute:: | |
| 76 | |
| 77 >>> eps = entry_points() | |
| 78 >>> list(eps) | |
| 79 ['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation'] | |
| 80 >>> scripts = eps['console_scripts'] | |
| 81 >>> wheel = [ep for ep in scripts if ep.name == 'wheel'][0] | |
| 82 >>> wheel | |
| 83 EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts') | |
| 84 >>> wheel.module | |
| 85 'wheel.cli' | |
| 86 >>> wheel.attr | |
| 87 'main' | |
| 88 >>> wheel.extras | |
| 89 [] | |
| 90 >>> main = wheel.load() | |
| 91 >>> main | |
| 92 <function main at 0x103528488> | |
| 93 | |
| 94 The ``group`` and ``name`` are arbitrary values defined by the package author | |
| 95 and usually a client will wish to resolve all entry points for a particular | |
| 96 group. Read `the setuptools docs | |
| 97 <https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins>`_ | |
| 98 for more information on entry points, their definition, and usage. | |
| 99 | |
| 100 | |
| 101 .. _metadata: | |
| 102 | |
| 103 Distribution metadata | |
| 104 --------------------- | |
| 105 | |
| 106 Every distribution includes some metadata, which you can extract using the | |
| 107 ``metadata()`` function:: | |
| 108 | |
| 109 >>> wheel_metadata = metadata('wheel') | |
| 110 | |
| 111 The keys of the returned data structure [#f1]_ name the metadata keywords, and | |
| 112 their values are returned unparsed from the distribution metadata:: | |
| 113 | |
| 114 >>> wheel_metadata['Requires-Python'] | |
| 115 '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' | |
| 116 | |
| 117 | |
| 118 .. _version: | |
| 119 | |
| 120 Distribution versions | |
| 121 --------------------- | |
| 122 | |
| 123 The ``version()`` function is the quickest way to get a distribution's version | |
| 124 number, as a string:: | |
| 125 | |
| 126 >>> version('wheel') | |
| 127 '0.32.3' | |
| 128 | |
| 129 | |
| 130 .. _files: | |
| 131 | |
| 132 Distribution files | |
| 133 ------------------ | |
| 134 | |
| 135 You can also get the full set of files contained within a distribution. The | |
| 136 ``files()`` function takes a distribution package name and returns all of the | |
| 137 files installed by this distribution. Each file object returned is a | |
| 138 ``PackagePath``, a :class:`pathlib.Path` derived object with additional ``dist``, | |
| 139 ``size``, and ``hash`` properties as indicated by the metadata. For example:: | |
| 140 | |
| 141 >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0] | |
| 142 >>> util | |
| 143 PackagePath('wheel/util.py') | |
| 144 >>> util.size | |
| 145 859 | |
| 146 >>> util.dist | |
| 147 <importlib_metadata._hooks.PathDistribution object at 0x101e0cef0> | |
| 148 >>> util.hash | |
| 149 <FileHash mode: sha256 value: bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI> | |
| 150 | |
| 151 Once you have the file, you can also read its contents:: | |
| 152 | |
| 153 >>> print(util.read_text()) | |
| 154 import base64 | |
| 155 import sys | |
| 156 ... | |
| 157 def as_bytes(s): | |
| 158 if isinstance(s, text_type): | |
| 159 return s.encode('utf-8') | |
| 160 return s | |
| 161 | |
| 162 In the case where the metadata file listing files | |
| 163 (RECORD or SOURCES.txt) is missing, ``files()`` will | |
| 164 return ``None``. The caller may wish to wrap calls to | |
| 165 ``files()`` in `always_iterable | |
| 166 <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.always_iterable>`_ | |
| 167 or otherwise guard against this condition if the target | |
| 168 distribution is not known to have the metadata present. | |
| 169 | |
| 170 .. _requirements: | |
| 171 | |
| 172 Distribution requirements | |
| 173 ------------------------- | |
| 174 | |
| 175 To get the full set of requirements for a distribution, use the ``requires()`` | |
| 176 function:: | |
| 177 | |
| 178 >>> requires('wheel') | |
| 179 ["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"] | |
| 180 | |
| 181 | |
| 182 Distributions | |
| 183 ============= | |
| 184 | |
| 185 While the above API is the most common and convenient usage, you can get all | |
| 186 of that information from the ``Distribution`` class. A ``Distribution`` is an | |
| 187 abstract object that represents the metadata for a Python package. You can | |
| 188 get the ``Distribution`` instance:: | |
| 189 | |
| 190 >>> from importlib_metadata import distribution | |
| 191 >>> dist = distribution('wheel') | |
| 192 | |
| 193 Thus, an alternative way to get the version number is through the | |
| 194 ``Distribution`` instance:: | |
| 195 | |
| 196 >>> dist.version | |
| 197 '0.32.3' | |
| 198 | |
| 199 There are all kinds of additional metadata available on the ``Distribution`` | |
| 200 instance:: | |
| 201 | |
| 202 >>> d.metadata['Requires-Python'] | |
| 203 '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' | |
| 204 >>> d.metadata['License'] | |
| 205 'MIT' | |
| 206 | |
| 207 The full set of available metadata is not described here. See :pep:`566` | |
| 208 for additional details. | |
| 209 | |
| 210 | |
| 211 Extending the search algorithm | |
| 212 ============================== | |
| 213 | |
| 214 Because package metadata is not available through :data:`sys.path` searches, or | |
| 215 package loaders directly, the metadata for a package is found through import | |
| 216 system `finders`_. To find a distribution package's metadata, | |
| 217 ``importlib.metadata`` queries the list of :term:`meta path finders <meta path finder>` on | |
| 218 :data:`sys.meta_path`. | |
| 219 | |
| 220 By default ``importlib_metadata`` installs a finder for distribution packages | |
| 221 found on the file system. This finder doesn't actually find any *packages*, | |
| 222 but it can find the packages' metadata. | |
| 223 | |
| 224 The abstract class :py:class:`importlib.abc.MetaPathFinder` defines the | |
| 225 interface expected of finders by Python's import system. | |
| 226 ``importlib_metadata`` extends this protocol by looking for an optional | |
| 227 ``find_distributions`` callable on the finders from | |
| 228 :data:`sys.meta_path` and presents this extended interface as the | |
| 229 ``DistributionFinder`` abstract base class, which defines this abstract | |
| 230 method:: | |
| 231 | |
| 232 @abc.abstractmethod | |
| 233 def find_distributions(context=DistributionFinder.Context()): | |
| 234 """Return an iterable of all Distribution instances capable of | |
| 235 loading the metadata for packages for the indicated ``context``. | |
| 236 """ | |
| 237 | |
| 238 The ``DistributionFinder.Context`` object provides ``.path`` and ``.name`` | |
| 239 properties indicating the path to search and name to match and may | |
| 240 supply other relevant context. | |
| 241 | |
| 242 What this means in practice is that to support finding distribution package | |
| 243 metadata in locations other than the file system, subclass | |
| 244 ``Distribution`` and implement the abstract methods. Then from | |
| 245 a custom finder, return instances of this derived ``Distribution`` in the | |
| 246 ``find_distributions()`` method. | |
| 247 | |
| 248 | |
| 249 .. _`entry point API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points | |
| 250 .. _`metadata API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#metadata-api | |
| 251 .. _`finders`: https://docs.python.org/3/reference/import.html#finders-and-loaders | |
| 252 | |
| 253 | |
| 254 .. rubric:: Footnotes | |
| 255 | |
| 256 .. [#f1] Technically, the returned distribution metadata object is an | |
| 257 :class:`email.message.EmailMessage` | |
| 258 instance, but this is an implementation detail, and not part of the | |
| 259 stable API. You should only use dictionary-like methods and syntax | |
| 260 to access the metadata contents. |
