3434import types
3535from typing import (
3636 Any ,
37- Iterator ,
3837 Literal ,
38+ Dict ,
39+ Iterator ,
3940 Mapping ,
4041 MutableSequence ,
4142 NamedTuple ,
4748 Callable ,
4849 Iterable ,
4950 TypeVar ,
50- Optional ,
51- Dict ,
5251 overload ,
5352)
5453import zipfile
101100
102101if TYPE_CHECKING :
103102 from _typeshed import BytesPath , StrPath , StrOrBytesPath
103+ from typing_extensions import Self
104104
105105warnings .warn (
106106 "pkg_resources is deprecated as an API. "
115115# Type aliases
116116_NestedStr = Union [str , Iterable [Union [str , Iterable ["_NestedStr" ]]]]
117117_InstallerTypeT = Callable [["Requirement" ], "_DistributionT" ]
118- _InstallerType = Callable [["Requirement" ], Optional ["Distribution" ]]
118+ _InstallerType = Callable [["Requirement" ], Union ["Distribution" , None ]]
119119_PkgReqType = Union [str , "Requirement" ]
120120_EPDistType = Union ["Distribution" , _PkgReqType ]
121- _MetadataType = Optional ["IResourceProvider" ]
121+ _MetadataType = Union ["IResourceProvider" , None ]
122122_ResolvedEntryPoint = Any # Can be any attribute in the module
123123_ResourceStream = Any # TODO / Incomplete: A readable file-like object
124124# Any object works, but let's indicate we expect something like a module (optionally has __loader__ or __file__)
125125_ModuleLike = Any
126126_ProviderFactoryType = Callable [[_ModuleLike ], "IResourceProvider" ]
127127_DistFinderType = Callable [[_T , str , bool ], Iterable ["Distribution" ]]
128- _NSHandlerType = Callable [[_T , str , str , types .ModuleType ], Optional [str ]]
128+ _NSHandlerType = Callable [[_T , str , str , types .ModuleType ], Union [str , None ]]
129129_AdapterT = TypeVar (
130130 "_AdapterT" , _DistFinderType [Any ], _ProviderFactoryType , _NSHandlerType [Any ]
131131)
@@ -161,15 +161,15 @@ def _declare_state(vartype: str, varname: str, initial_value: _T) -> _T:
161161 return initial_value
162162
163163
164- def __getstate__ ():
164+ def __getstate__ () -> dict [ str , Any ] :
165165 state = {}
166166 g = globals ()
167167 for k , v in _state_vars .items ():
168168 state [k ] = g ['_sget_' + v ](g [k ])
169169 return state
170170
171171
172- def __setstate__ (state ) :
172+ def __setstate__ (state : dict [ str , Any ]) -> dict [ str , Any ] :
173173 g = globals ()
174174 for k , v in state .items ():
175175 g ['_sset_' + _state_vars [k ]](k , g [k ], v )
@@ -324,11 +324,11 @@ class VersionConflict(ResolutionError):
324324 _template = "{self.dist} is installed but {self.req} is required"
325325
326326 @property
327- def dist (self ):
327+ def dist (self ) -> Distribution :
328328 return self .args [0 ]
329329
330330 @property
331- def req (self ):
331+ def req (self ) -> Requirement :
332332 return self .args [1 ]
333333
334334 def report (self ):
@@ -354,7 +354,7 @@ class ContextualVersionConflict(VersionConflict):
354354 _template = VersionConflict ._template + ' by {self.required_by}'
355355
356356 @property
357- def required_by (self ):
357+ def required_by (self ) -> set [ str ] :
358358 return self .args [2 ]
359359
360360
@@ -367,11 +367,11 @@ class DistributionNotFound(ResolutionError):
367367 )
368368
369369 @property
370- def req (self ):
370+ def req (self ) -> Requirement :
371371 return self .args [0 ]
372372
373373 @property
374- def requirers (self ):
374+ def requirers (self ) -> set [ str ] | None :
375375 return self .args [1 ]
376376
377377 @property
@@ -696,11 +696,11 @@ def add_entry(self, entry: str):
696696 for dist in find_distributions (entry , True ):
697697 self .add (dist , entry , False )
698698
699- def __contains__ (self , dist : Distribution ):
699+ def __contains__ (self , dist : Distribution ) -> bool :
700700 """True if `dist` is the active distribution for its project"""
701701 return self .by_key .get (dist .key ) == dist
702702
703- def find (self , req : Requirement ):
703+ def find (self , req : Requirement ) -> Distribution | None :
704704 """Find a distribution matching requirement `req`
705705
706706 If there is an active distribution for the requested project, this
@@ -746,7 +746,7 @@ def run_script(self, requires: str, script_name: str):
746746 ns ['__name__' ] = name
747747 self .require (requires )[0 ].run_script (script_name , ns )
748748
749- def __iter__ (self ):
749+ def __iter__ (self ) -> Iterator [ Distribution ] :
750750 """Yield distributions for non-duplicate projects in the working set
751751
752752 The yield order is the order in which the items' path entries were
@@ -1186,7 +1186,7 @@ def scan(self, search_path: Iterable[str] | None = None):
11861186 for dist in find_distributions (item ):
11871187 self .add (dist )
11881188
1189- def __getitem__ (self , project_name : str ):
1189+ def __getitem__ (self , project_name : str ) -> list [ Distribution ] :
11901190 """Return a newest-to-oldest list of distributions for `project_name`
11911191
11921192 Uses case-insensitive `project_name` comparison, assuming all the
@@ -1290,7 +1290,7 @@ def obtain(
12901290 to the `installer` argument."""
12911291 return installer (requirement ) if installer else None
12921292
1293- def __iter__ (self ):
1293+ def __iter__ (self ) -> Iterator [ str ] :
12941294 """Yield the unique project names of the available distributions"""
12951295 for key in self ._distmap .keys ():
12961296 if self [key ]:
@@ -1523,7 +1523,7 @@ def cleanup_resources(self, force: bool = False) -> list[str]:
15231523 return []
15241524
15251525
1526- def get_default_cache ():
1526+ def get_default_cache () -> str :
15271527 """
15281528 Return the ``PYTHON_EGG_CACHE`` environment variable
15291529 or a platform-relevant user cache dir for an app
@@ -1615,7 +1615,7 @@ def invalid_marker(text: str):
16151615 return False
16161616
16171617
1618- def evaluate_marker (text : str , extra : str | None = None ):
1618+ def evaluate_marker (text : str , extra : str | None = None ) -> bool :
16191619 """
16201620 Evaluate a PEP 508 environment marker.
16211621 Return a boolean indicating the marker result in this environment.
@@ -1923,7 +1923,7 @@ class ZipManifests(Dict[str, "MemoizedZipManifests.manifest_mod"]):
19231923 zip manifest builder
19241924 """
19251925
1926- # `path` could be `Union[" StrPath", IO[bytes] ]` but that violates the LSP for `MemoizedZipManifests.load`
1926+ # `path` could be `StrPath | IO[bytes]` but that violates the LSP for `MemoizedZipManifests.load`
19271927 @classmethod
19281928 def build (cls , path : str ):
19291929 """
@@ -1955,7 +1955,7 @@ class manifest_mod(NamedTuple):
19551955 manifest : dict [str , zipfile .ZipInfo ]
19561956 mtime : float
19571957
1958- def load (self , path : str ): # type: ignore[override] # ZipManifests.load is a classmethod
1958+ def load (self , path : str ) -> dict [ str , zipfile . ZipInfo ] : # type: ignore[override] # ZipManifests.load is a classmethod
19591959 """
19601960 Load a manifest at path or return a suitable manifest already loaded.
19611961 """
@@ -2247,7 +2247,7 @@ def find_distributions(path_item: str, only: bool = False):
22472247
22482248def find_eggs_in_zip (
22492249 importer : zipimport .zipimporter , path_item : str , only : bool = False
2250- ):
2250+ ) -> Iterator [ Distribution ] :
22512251 """
22522252 Find eggs in zip files; possibly multiple nested eggs.
22532253 """
@@ -2340,7 +2340,7 @@ def __call__(self, fullpath):
23402340 return iter (())
23412341
23422342
2343- def safe_listdir (path ):
2343+ def safe_listdir (path : StrOrBytesPath ):
23442344 """
23452345 Attempt to list contents of path, but suppress some exceptions.
23462346 """
@@ -2356,13 +2356,13 @@ def safe_listdir(path):
23562356 return ()
23572357
23582358
2359- def distributions_from_metadata (path ):
2359+ def distributions_from_metadata (path : str ):
23602360 root = os .path .dirname (path )
23612361 if os .path .isdir (path ):
23622362 if len (os .listdir (path )) == 0 :
23632363 # empty metadata dir; skip
23642364 return
2365- metadata = PathMetadata (root , path )
2365+ metadata : _MetadataType = PathMetadata (root , path )
23662366 else :
23672367 metadata = FileMetadata (path )
23682368 entry = os .path .basename (path )
@@ -2817,7 +2817,7 @@ def parse_group(
28172817 """Parse an entry point group"""
28182818 if not MODULE (group ):
28192819 raise ValueError ("Invalid group name" , group )
2820- this = {}
2820+ this : dict [ str , Self ] = {}
28212821 for line in yield_lines (lines ):
28222822 ep = cls .parse (line , dist )
28232823 if ep .name in this :
@@ -2832,11 +2832,12 @@ def parse_map(
28322832 dist : Distribution | None = None ,
28332833 ):
28342834 """Parse a map of entry point groups"""
2835+ _data : Iterable [tuple [str | None , str | Iterable [str ]]]
28352836 if isinstance (data , dict ):
28362837 _data = data .items ()
28372838 else :
28382839 _data = split_sections (data )
2839- maps : dict [str , dict [str , EntryPoint ]] = {}
2840+ maps : dict [str , dict [str , Self ]] = {}
28402841 for group , lines in _data :
28412842 if group is None :
28422843 if not lines :
@@ -2895,7 +2896,7 @@ def from_location(
28952896 basename : StrPath ,
28962897 metadata : _MetadataType = None ,
28972898 ** kw : int , # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
2898- ):
2899+ ) -> Distribution :
28992900 project_name , version , py_version , platform = [None ] * 4
29002901 basename , ext = os .path .splitext (basename )
29012902 if ext .lower () in _distributionImpl :
@@ -3034,14 +3035,14 @@ def _dep_map(self):
30343035 return self .__dep_map
30353036
30363037 @staticmethod
3037- def _filter_extras (dm ):
3038+ def _filter_extras (dm : dict [ str | None , list [ Requirement ]] ):
30383039 """
30393040 Given a mapping of extras to dependencies, strip off
30403041 environment markers and filter out any dependencies
30413042 not matching the markers.
30423043 """
30433044 for extra in list (filter (None , dm )):
3044- new_extra = extra
3045+ new_extra : str | None = extra
30453046 reqs = dm .pop (extra )
30463047 new_extra , _ , marker = extra .partition (':' )
30473048 fails_marker = marker and (
@@ -3064,7 +3065,7 @@ def _build_dep_map(self):
30643065 def requires (self , extras : Iterable [str ] = ()):
30653066 """List of Requirements needed for this distro if `extras` are used"""
30663067 dm = self ._dep_map
3067- deps = []
3068+ deps : list [ Requirement ] = []
30683069 deps .extend (dm .get (None , ()))
30693070 for ext in extras :
30703071 try :
@@ -3365,11 +3366,11 @@ def _dep_map(self):
33653366 self .__dep_map = self ._compute_dependencies ()
33663367 return self .__dep_map
33673368
3368- def _compute_dependencies (self ):
3369+ def _compute_dependencies (self ) -> dict [ str | None , list [ Requirement ]] :
33693370 """Recompute this distribution's dependencies."""
3370- dm = self .__dep_map = {None : []}
3371+ self .__dep_map : dict [ str | None , list [ Requirement ]] = {None : []}
33713372
3372- reqs = []
3373+ reqs : list [ Requirement ] = []
33733374 # Including any condition expressions
33743375 for req in self ._parsed_pkg_info .get_all ('Requires-Dist' ) or []:
33753376 reqs .extend (parse_requirements (req ))
@@ -3380,13 +3381,15 @@ def reqs_for_extra(extra):
33803381 yield req
33813382
33823383 common = types .MappingProxyType (dict .fromkeys (reqs_for_extra (None )))
3383- dm [None ].extend (common )
3384+ self . __dep_map [None ].extend (common )
33843385
33853386 for extra in self ._parsed_pkg_info .get_all ('Provides-Extra' ) or []:
33863387 s_extra = safe_extra (extra .strip ())
3387- dm [s_extra ] = [r for r in reqs_for_extra (extra ) if r not in common ]
3388+ self .__dep_map [s_extra ] = [
3389+ r for r in reqs_for_extra (extra ) if r not in common
3390+ ]
33883391
3389- return dm
3392+ return self . __dep_map
33903393
33913394
33923395_distributionImpl = {
@@ -3447,7 +3450,7 @@ def __eq__(self, other: object):
34473450 def __ne__ (self , other ):
34483451 return not self == other
34493452
3450- def __contains__ (self , item : Distribution | str | tuple [str , ...]):
3453+ def __contains__ (self , item : Distribution | str | tuple [str , ...]) -> bool :
34513454 if isinstance (item , Distribution ):
34523455 if item .key != self .key :
34533456 return False
@@ -3511,7 +3514,7 @@ def _bypass_ensure_directory(path):
35113514 pass
35123515
35133516
3514- def split_sections (s : _NestedStr ):
3517+ def split_sections (s : _NestedStr ) -> Iterator [ tuple [ str | None , list [ str ]]] :
35153518 """Split a string or iterable thereof into (section, content) pairs
35163519
35173520 Each ``section`` is a stripped version of the section header ("[section]")
0 commit comments