55import sys
66import zipp
77import email
8+ import inspect
89import pathlib
910import operator
1011import textwrap
1415import posixpath
1516import contextlib
1617import collections
17- import inspect
1818
1919from . import _adapters , _meta , _py39compat
2020from ._collections import FreezableDefaultDict , Pair
3131from importlib import import_module
3232from importlib .abc import MetaPathFinder
3333from 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' ,
5354class 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
130131class 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):
327331class 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
343351class 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
792802class 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
0 commit comments