Skip to content

Commit 791e45a

Browse files
committed
type annotations
1 parent d390898 commit 791e45a

File tree

3 files changed

+60
-46
lines changed

3 files changed

+60
-46
lines changed

docs/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464
nitpick_ignore = [
6565
# Workaround for #316
6666
('py:class', 'importlib_metadata.EntryPoints'),
67+
('py:class', 'importlib_metadata.PackagePath'),
68+
('py:class', 'importlib_metadata.PathDistribution'),
6769
('py:class', 'importlib_metadata.SelectableGroups'),
6870
('py:class', 'importlib_metadata._meta._T'),
6971
# Workaround for #435

importlib_metadata/__init__.py

Lines changed: 57 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import zipp
77
import email
8+
import inspect
89
import pathlib
910
import operator
1011
import textwrap
@@ -14,7 +15,6 @@
1415
import posixpath
1516
import contextlib
1617
import collections
17-
import inspect
1818

1919
from . import _adapters, _meta, _py39compat
2020
from ._collections import FreezableDefaultDict, Pair
@@ -31,8 +31,9 @@
3131
from importlib import import_module
3232
from importlib.abc import MetaPathFinder
3333
from itertools import starmap
34-
from typing import List, Mapping, Optional, cast
34+
from typing import Iterator, List, Mapping, Optional, Set, Union, cast
3535

36+
StrPath = Union[str, "os.PathLike[str]"]
3637

3738
__all__ = [
3839
'Distribution',
@@ -53,11 +54,11 @@
5354
class PackageNotFoundError(ModuleNotFoundError):
5455
"""The package was not found."""
5556

56-
def __str__(self):
57+
def __str__(self) -> str:
5758
return f"No package metadata was found for {self.name}"
5859

5960
@property
60-
def name(self):
61+
def name(self) -> str: # type: ignore[override]
6162
(name,) = self.args
6263
return name
6364

@@ -123,8 +124,8 @@ def read(text, filter_=None):
123124
yield Pair(name, value)
124125

125126
@staticmethod
126-
def valid(line):
127-
return line and not line.startswith('#')
127+
def valid(line: str) -> bool:
128+
return bool(line) and not line.startswith('#')
128129

129130

130131
class DeprecatedTuple:
@@ -198,7 +199,7 @@ class EntryPoint(DeprecatedTuple):
198199

199200
dist: Optional['Distribution'] = None
200201

201-
def __init__(self, name, value, group):
202+
def __init__(self, name: str, value: str, group: str) -> None:
202203
vars(self).update(name=name, value=value, group=group)
203204

204205
def load(self):
@@ -212,18 +213,21 @@ def load(self):
212213
return functools.reduce(getattr, attrs, module)
213214

214215
@property
215-
def module(self):
216+
def module(self) -> str:
216217
match = self.pattern.match(self.value)
218+
assert match is not None
217219
return match.group('module')
218220

219221
@property
220-
def attr(self):
222+
def attr(self) -> str:
221223
match = self.pattern.match(self.value)
224+
assert match is not None
222225
return match.group('attr')
223226

224227
@property
225-
def extras(self):
228+
def extras(self) -> List[str]:
226229
match = self.pattern.match(self.value)
230+
assert match is not None
227231
return re.findall(r'\w+', match.group('extras') or '')
228232

229233
def _for(self, dist):
@@ -271,7 +275,7 @@ def __repr__(self):
271275
f'group={self.group!r})'
272276
)
273277

274-
def __hash__(self):
278+
def __hash__(self) -> int:
275279
return hash(self._key())
276280

277281

@@ -282,7 +286,7 @@ class EntryPoints(tuple):
282286

283287
__slots__ = ()
284288

285-
def __getitem__(self, name): # -> EntryPoint:
289+
def __getitem__(self, name: str) -> EntryPoint: # type: ignore[override]
286290
"""
287291
Get the EntryPoint in self matching name.
288292
"""
@@ -299,14 +303,14 @@ def select(self, **params):
299303
return EntryPoints(ep for ep in self if _py39compat.ep_matches(ep, **params))
300304

301305
@property
302-
def names(self):
306+
def names(self) -> Set[str]:
303307
"""
304308
Return the set of all names of all entry points.
305309
"""
306310
return {ep.name for ep in self}
307311

308312
@property
309-
def groups(self):
313+
def groups(self) -> Set[str]:
310314
"""
311315
Return the set of all groups of all entry points.
312316
"""
@@ -327,24 +331,28 @@ def _from_text(text):
327331
class PackagePath(pathlib.PurePosixPath):
328332
"""A reference to a path in a package"""
329333

330-
def read_text(self, encoding='utf-8'):
334+
hash: Optional["FileHash"]
335+
size: int
336+
dist: "Distribution"
337+
338+
def read_text(self, encoding: str = 'utf-8') -> str: # type: ignore[override]
331339
with self.locate().open(encoding=encoding) as stream:
332340
return stream.read()
333341

334-
def read_binary(self):
342+
def read_binary(self) -> bytes:
335343
with self.locate().open('rb') as stream:
336344
return stream.read()
337345

338-
def locate(self):
346+
def locate(self) -> pathlib.Path:
339347
"""Return a path-like object for this path"""
340348
return self.dist.locate_file(self)
341349

342350

343351
class FileHash:
344-
def __init__(self, spec):
352+
def __init__(self, spec: str) -> None:
345353
self.mode, _, self.value = spec.partition('=')
346354

347-
def __repr__(self):
355+
def __repr__(self) -> str:
348356
return f'<FileHash mode: {self.mode} value: {self.value}>'
349357

350358

@@ -360,14 +368,14 @@ def read_text(self, filename) -> Optional[str]:
360368
"""
361369

362370
@abc.abstractmethod
363-
def locate_file(self, path):
371+
def locate_file(self, path: StrPath) -> pathlib.Path:
364372
"""
365373
Given a path to a file in this distribution, return a path
366374
to it.
367375
"""
368376

369377
@classmethod
370-
def from_name(cls, name: str):
378+
def from_name(cls, name: str) -> "Distribution":
371379
"""Return the Distribution for the given package name.
372380
373381
:param name: The name of the distribution package to search for.
@@ -385,14 +393,14 @@ def from_name(cls, name: str):
385393
raise PackageNotFoundError(name)
386394

387395
@classmethod
388-
def discover(cls, **kwargs):
389-
"""Return an iterable of Distribution objects for all packages.
396+
def discover(cls, **kwargs) -> Iterator["Distribution"]:
397+
"""Return an iterator of Distribution objects for all packages.
390398
391399
Pass a ``context`` or pass keyword arguments for constructing
392400
a context.
393401
394402
:context: A ``DistributionFinder.Context`` object.
395-
:return: Iterable of Distribution objects for all packages.
403+
:return: Iterator of Distribution objects for all packages.
396404
"""
397405
context = kwargs.pop('context', None)
398406
if context and kwargs:
@@ -403,7 +411,7 @@ def discover(cls, **kwargs):
403411
)
404412

405413
@staticmethod
406-
def at(path):
414+
def at(path: StrPath) -> "PathDistribution":
407415
"""Return a Distribution for the indicated metadata path
408416
409417
:param path: a string or path-like object
@@ -438,7 +446,7 @@ def metadata(self) -> _meta.PackageMetadata:
438446
return _adapters.Message(email.message_from_string(text))
439447

440448
@property
441-
def name(self):
449+
def name(self) -> str:
442450
"""Return the 'Name' metadata for the distribution package."""
443451
return self.metadata['Name']
444452

@@ -448,16 +456,16 @@ def _normalized_name(self):
448456
return Prepared.normalize(self.name)
449457

450458
@property
451-
def version(self):
459+
def version(self) -> str:
452460
"""Return the 'Version' metadata for the distribution package."""
453461
return self.metadata['Version']
454462

455463
@property
456-
def entry_points(self):
464+
def entry_points(self) -> EntryPoints:
457465
return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self)
458466

459467
@property
460-
def files(self):
468+
def files(self) -> Optional[List[PackagePath]]:
461469
"""Files in this distribution.
462470
463471
:return: List of PackagePath for this distribution or None
@@ -540,7 +548,7 @@ def _read_files_egginfo_sources(self):
540548
return text and map('"{}"'.format, text.splitlines())
541549

542550
@property
543-
def requires(self):
551+
def requires(self) -> Optional[List[str]]:
544552
"""Generated requirements specified for this Distribution"""
545553
reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
546554
return reqs and list(reqs)
@@ -619,7 +627,7 @@ def __init__(self, **kwargs):
619627
vars(self).update(kwargs)
620628

621629
@property
622-
def path(self):
630+
def path(self) -> List[str]:
623631
"""
624632
The sequence of directory path that a distribution finder
625633
should search.
@@ -630,11 +638,11 @@ def path(self):
630638
return vars(self).get('path', sys.path)
631639

632640
@abc.abstractmethod
633-
def find_distributions(self, context=Context()):
641+
def find_distributions(self, context=Context()) -> Iterator[Distribution]:
634642
"""
635643
Find distributions.
636644
637-
Return an iterable of all Distribution instances capable of
645+
Return an iterator of all Distribution instances capable of
638646
loading the metadata for packages matching the ``context``,
639647
a DistributionFinder.Context instance.
640648
"""
@@ -765,11 +773,13 @@ class MetadataPathFinder(NullFinder, DistributionFinder):
765773
of Python that do not have a PathFinder find_distributions().
766774
"""
767775

768-
def find_distributions(self, context=DistributionFinder.Context()):
776+
def find_distributions(
777+
self, context=DistributionFinder.Context()
778+
) -> Iterator["PathDistribution"]:
769779
"""
770780
Find distributions.
771781
772-
Return an iterable of all Distribution instances capable of
782+
Return an iterator of all Distribution instances capable of
773783
loading the metadata for packages matching ``context.name``
774784
(or all names if ``None`` indicated) along the paths in the list
775785
of directories ``context.path``.
@@ -785,19 +795,19 @@ def _search_paths(cls, name, paths):
785795
path.search(prepared) for path in map(FastPath, paths)
786796
)
787797

788-
def invalidate_caches(cls):
798+
def invalidate_caches(cls) -> None:
789799
FastPath.__new__.cache_clear()
790800

791801

792802
class PathDistribution(Distribution):
793-
def __init__(self, path: SimplePath):
803+
def __init__(self, path: SimplePath) -> None:
794804
"""Construct a distribution.
795805
796806
:param path: SimplePath indicating the metadata directory.
797807
"""
798808
self._path = path
799809

800-
def read_text(self, filename):
810+
def read_text(self, filename: StrPath) -> Optional[str]:
801811
with suppress(
802812
FileNotFoundError,
803813
IsADirectoryError,
@@ -807,9 +817,11 @@ def read_text(self, filename):
807817
):
808818
return self._path.joinpath(filename).read_text(encoding='utf-8')
809819

820+
return None
821+
810822
read_text.__doc__ = Distribution.read_text.__doc__
811823

812-
def locate_file(self, path):
824+
def locate_file(self, path: StrPath) -> pathlib.Path:
813825
return self._path.parent / path
814826

815827
@property
@@ -842,7 +854,7 @@ def _name_from_stem(stem):
842854
return name
843855

844856

845-
def distribution(distribution_name):
857+
def distribution(distribution_name) -> Distribution:
846858
"""Get the ``Distribution`` instance for the named package.
847859
848860
:param distribution_name: The name of the distribution package as a string.
@@ -851,10 +863,10 @@ def distribution(distribution_name):
851863
return Distribution.from_name(distribution_name)
852864

853865

854-
def distributions(**kwargs):
866+
def distributions(**kwargs) -> Iterator[Distribution]:
855867
"""Get all ``Distribution`` instances in the current environment.
856868
857-
:return: An iterable of ``Distribution`` instances.
869+
:return: An iterator of ``Distribution`` instances.
858870
"""
859871
return Distribution.discover(**kwargs)
860872

@@ -868,7 +880,7 @@ def metadata(distribution_name) -> _meta.PackageMetadata:
868880
return Distribution.from_name(distribution_name).metadata
869881

870882

871-
def version(distribution_name):
883+
def version(distribution_name) -> str:
872884
"""Get the version string for the named package.
873885
874886
:param distribution_name: The name of the distribution package to query.
@@ -902,7 +914,7 @@ def entry_points(**params) -> EntryPoints:
902914
return EntryPoints(eps).select(**params)
903915

904916

905-
def files(distribution_name):
917+
def files(distribution_name) -> Optional[List[PackagePath]]:
906918
"""Return a list of files for the named package.
907919
908920
:param distribution_name: The name of the distribution package to query.
@@ -911,7 +923,7 @@ def files(distribution_name):
911923
return distribution(distribution_name).files
912924

913925

914-
def requires(distribution_name):
926+
def requires(distribution_name) -> Optional[List[str]]:
915927
"""
916928
Return a list of requirements for the named package.
917929

importlib_metadata/_meta.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class SimplePath(Protocol[_T]):
4949
A minimal subset of pathlib.Path required by PathDistribution.
5050
"""
5151

52-
def joinpath(self) -> _T:
52+
def joinpath(self, other: Union[str, _T]) -> _T:
5353
... # pragma: no cover
5454

5555
def __truediv__(self, other: Union[str, _T]) -> _T:

0 commit comments

Comments
 (0)