Skip to content

Commit 6955586

Browse files
authored
Merge pull request #263 from FFY00/typed-metadata
importlib_metadata: define protocol for Distribution.metadata
2 parents 96cc328 + e15726d commit 6955586

File tree

6 files changed

+75
-6
lines changed

6 files changed

+75
-6
lines changed

.github/workflows/automerge.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: automerge
2+
on:
3+
pull_request:
4+
types:
5+
- labeled
6+
- unlabeled
7+
- synchronize
8+
- opened
9+
- edited
10+
- ready_for_review
11+
- reopened
12+
- unlocked
13+
pull_request_review:
14+
types:
15+
- submitted
16+
check_suite:
17+
types:
18+
- completed
19+
status: {}
20+
jobs:
21+
automerge:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: automerge
25+
uses: "pascalgn/[email protected]"
26+
env:
27+
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

CHANGES.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
v3.2.0
2+
======
3+
4+
* The object returned by ``metadata()`` now has a
5+
formally-defined protocol called ``PackageMetadata``
6+
with declared support for the ``.get_all()`` method.
7+
Fixes #126.
8+
19
v3.1.1
210
======
311

docs/using.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ Every distribution includes some metadata, which you can extract using the
108108

109109
>>> wheel_metadata = metadata('wheel')
110110

111-
The keys of the returned data structure [#f1]_ name the metadata keywords, and
112-
their values are returned unparsed from the distribution metadata::
111+
The keys of the returned data structure, a ``PackageMetadata``,
112+
name the metadata keywords, and
113+
the values are returned unparsed from the distribution metadata::
113114

114115
>>> wheel_metadata['Requires-Python']
115116
'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'

importlib_metadata/__init__.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
NullFinder,
1717
PyPy_repr,
1818
install,
19+
Protocol,
1920
)
2021

2122
from configparser import ConfigParser
2223
from contextlib import suppress
2324
from importlib import import_module
2425
from importlib.abc import MetaPathFinder
2526
from itertools import starmap
27+
from typing import Any, List, TypeVar, Union
2628

2729

2830
__all__ = [
@@ -161,6 +163,25 @@ def __repr__(self):
161163
return '<FileHash mode: {} value: {}>'.format(self.mode, self.value)
162164

163165

166+
_T = TypeVar("_T")
167+
168+
169+
class PackageMetadata(Protocol):
170+
def __len__(self) -> int:
171+
... # pragma: no cover
172+
173+
def __contains__(self, item: str) -> bool:
174+
... # pragma: no cover
175+
176+
def __getitem__(self, key: str) -> str:
177+
... # pragma: no cover
178+
179+
def get_all(self, name: str, failobj: _T = ...) -> Union[List[Any], _T]:
180+
"""
181+
Return all values associated with a possibly multi-valued key.
182+
"""
183+
184+
164185
class Distribution:
165186
"""A Python distribution package."""
166187

@@ -245,7 +266,7 @@ def _local(cls, root='.'):
245266
return PathDistribution(zipp.Path(meta.build_as_zip(builder)))
246267

247268
@property
248-
def metadata(self):
269+
def metadata(self) -> PackageMetadata:
249270
"""Return the parsed metadata for this Distribution.
250271
251272
The returned object will have keys that name the various bits of
@@ -576,11 +597,11 @@ def distributions(**kwargs):
576597
return Distribution.discover(**kwargs)
577598

578599

579-
def metadata(distribution_name):
600+
def metadata(distribution_name) -> PackageMetadata:
580601
"""Get the metadata for the named package.
581602
582603
:param distribution_name: The name of the distribution package to query.
583-
:return: An email.Message containing the parsed metadata.
604+
:return: A PackageMetadata containing the parsed metadata.
584605
"""
585606
return Distribution.from_name(distribution_name).metadata
586607

importlib_metadata/_compat.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import sys
22

33

4-
__all__ = ['install', 'NullFinder', 'PyPy_repr']
4+
__all__ = ['install', 'NullFinder', 'PyPy_repr', 'Protocol']
5+
6+
7+
try:
8+
from typing import Protocol
9+
except ImportError: # pragma: no cover
10+
"""
11+
pytest-mypy complains here because:
12+
error: Incompatible import of "Protocol" (imported name has type
13+
"typing_extensions._SpecialForm", local name has type "typing._SpecialForm")
14+
"""
15+
from typing_extensions import Protocol # type: ignore
516

617

718
def install(cls):

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ include_package_data = true
1919
python_requires = >=3.6
2020
install_requires =
2121
zipp>=0.5
22+
typing-extensions>=3.6.4; python_version < "3.8"
2223
setup_requires = setuptools_scm[toml] >= 3.4.1
2324

2425
[options.packages.find]

0 commit comments

Comments
 (0)