18
18
"""
19
19
20
20
import sys
21
+
22
+ if sys .version_info < (3 , 8 ):
23
+ raise RuntimeError ("Python 3.8 or later is required" )
24
+
21
25
import os
22
26
import io
23
27
import time
24
28
import re
25
29
import types
30
+ from typing import Protocol
26
31
import zipfile
27
32
import zipimport
28
33
import warnings
41
46
import ntpath
42
47
import posixpath
43
48
import importlib
49
+ import importlib .machinery
44
50
from pkgutil import get_importer
45
51
46
- try :
47
- import _imp
48
- except ImportError :
49
- # Python 3.2 compatibility
50
- import imp as _imp
51
-
52
- try :
53
- FileExistsError
54
- except NameError :
55
- FileExistsError = OSError
52
+ import _imp
56
53
57
54
# capture these to bypass sandboxing
58
55
from os import utime
68
65
from os import open as os_open
69
66
from os .path import isdir , split
70
67
71
- try :
72
- import importlib .machinery as importlib_machinery
73
-
74
- # access attribute to force import under delayed import mechanisms.
75
- importlib_machinery .__name__
76
- except ImportError :
77
- importlib_machinery = None
78
-
79
68
from pip ._internal .utils ._jaraco_text import (
80
69
yield_lines ,
81
70
drop_comment ,
91
80
__import__ ('pip._vendor.packaging.markers' )
92
81
__import__ ('pip._vendor.packaging.utils' )
93
82
94
- if sys .version_info < (3 , 5 ):
95
- raise RuntimeError ("Python 3.5 or later is required" )
96
-
97
83
# declare some globals that will be defined later to
98
84
# satisfy the linters.
99
85
require = None
119
105
"pkg_resources is deprecated as an API. "
120
106
"See https://setuptools.pypa.io/en/latest/pkg_resources.html" ,
121
107
DeprecationWarning ,
122
- stacklevel = 2
108
+ stacklevel = 2 ,
123
109
)
124
110
125
111
@@ -407,20 +393,18 @@ def get_provider(moduleOrReq):
407
393
return _find_adapter (_provider_factories , loader )(module )
408
394
409
395
410
- def _macos_vers (_cache = []):
411
- if not _cache :
412
- version = platform .mac_ver ()[0 ]
413
- # fallback for MacPorts
414
- if version == '' :
415
- plist = '/System/Library/CoreServices/SystemVersion.plist'
416
- if os .path .exists (plist ):
417
- if hasattr (plistlib , 'readPlist' ):
418
- plist_content = plistlib .readPlist (plist )
419
- if 'ProductVersion' in plist_content :
420
- version = plist_content ['ProductVersion' ]
421
-
422
- _cache .append (version .split ('.' ))
423
- return _cache [0 ]
396
+ @functools .lru_cache (maxsize = None )
397
+ def _macos_vers ():
398
+ version = platform .mac_ver ()[0 ]
399
+ # fallback for MacPorts
400
+ if version == '' :
401
+ plist = '/System/Library/CoreServices/SystemVersion.plist'
402
+ if os .path .exists (plist ):
403
+ with open (plist , 'rb' ) as fh :
404
+ plist_content = plistlib .load (fh )
405
+ if 'ProductVersion' in plist_content :
406
+ version = plist_content ['ProductVersion' ]
407
+ return version .split ('.' )
424
408
425
409
426
410
def _macos_arch (machine ):
@@ -546,54 +530,54 @@ def get_entry_info(dist, group, name):
546
530
return get_distribution (dist ).get_entry_info (group , name )
547
531
548
532
549
- class IMetadataProvider :
550
- def has_metadata (name ):
533
+ class IMetadataProvider ( Protocol ) :
534
+ def has_metadata (self , name ):
551
535
"""Does the package's distribution contain the named metadata?"""
552
536
553
- def get_metadata (name ):
537
+ def get_metadata (self , name ):
554
538
"""The named metadata resource as a string"""
555
539
556
- def get_metadata_lines (name ):
540
+ def get_metadata_lines (self , name ):
557
541
"""Yield named metadata resource as list of non-blank non-comment lines
558
542
559
543
Leading and trailing whitespace is stripped from each line, and lines
560
544
with ``#`` as the first non-blank character are omitted."""
561
545
562
- def metadata_isdir (name ):
546
+ def metadata_isdir (self , name ):
563
547
"""Is the named metadata a directory? (like ``os.path.isdir()``)"""
564
548
565
- def metadata_listdir (name ):
549
+ def metadata_listdir (self , name ):
566
550
"""List of metadata names in the directory (like ``os.listdir()``)"""
567
551
568
- def run_script (script_name , namespace ):
552
+ def run_script (self , script_name , namespace ):
569
553
"""Execute the named script in the supplied namespace dictionary"""
570
554
571
555
572
- class IResourceProvider (IMetadataProvider ):
556
+ class IResourceProvider (IMetadataProvider , Protocol ):
573
557
"""An object that provides access to package resources"""
574
558
575
- def get_resource_filename (manager , resource_name ):
559
+ def get_resource_filename (self , manager , resource_name ):
576
560
"""Return a true filesystem path for `resource_name`
577
561
578
562
`manager` must be an ``IResourceManager``"""
579
563
580
- def get_resource_stream (manager , resource_name ):
564
+ def get_resource_stream (self , manager , resource_name ):
581
565
"""Return a readable file-like object for `resource_name`
582
566
583
567
`manager` must be an ``IResourceManager``"""
584
568
585
- def get_resource_string (manager , resource_name ):
569
+ def get_resource_string (self , manager , resource_name ):
586
570
"""Return a string containing the contents of `resource_name`
587
571
588
572
`manager` must be an ``IResourceManager``"""
589
573
590
- def has_resource (resource_name ):
574
+ def has_resource (self , resource_name ):
591
575
"""Does the package contain the named resource?"""
592
576
593
- def resource_isdir (resource_name ):
577
+ def resource_isdir (self , resource_name ):
594
578
"""Is the named resource a directory? (like ``os.path.isdir()``)"""
595
579
596
- def resource_listdir (resource_name ):
580
+ def resource_listdir (self , resource_name ):
597
581
"""List of resource names in the directory (like ``os.listdir()``)"""
598
582
599
583
@@ -1143,8 +1127,7 @@ def obtain(self, requirement, installer=None):
1143
1127
None is returned instead. This method is a hook that allows subclasses
1144
1128
to attempt other ways of obtaining a distribution before falling back
1145
1129
to the `installer` argument."""
1146
- if installer is not None :
1147
- return installer (requirement )
1130
+ return installer (requirement ) if installer else None
1148
1131
1149
1132
def __iter__ (self ):
1150
1133
"""Yield the unique project names of the available distributions"""
@@ -1418,7 +1401,7 @@ def _forgiving_version(version):
1418
1401
match = _PEP440_FALLBACK .search (version )
1419
1402
if match :
1420
1403
safe = match ["safe" ]
1421
- rest = version [len (safe ):]
1404
+ rest = version [len (safe ) :]
1422
1405
else :
1423
1406
safe = "0"
1424
1407
rest = version
@@ -1734,7 +1717,7 @@ def _register(cls):
1734
1717
'SourcelessFileLoader' ,
1735
1718
)
1736
1719
for name in loader_names :
1737
- loader_cls = getattr (importlib_machinery , name , type (None ))
1720
+ loader_cls = getattr (importlib . machinery , name , type (None ))
1738
1721
register_loader_type (loader_cls , cls )
1739
1722
1740
1723
@@ -1874,7 +1857,7 @@ def _extract_resource(self, manager, zip_path): # noqa: C901
1874
1857
timestamp , size = self ._get_date_and_size (self .zipinfo [zip_path ])
1875
1858
1876
1859
if not WRITE_SUPPORT :
1877
- raise IOError (
1860
+ raise OSError (
1878
1861
'"os.rename" and "os.unlink" are not supported ' 'on this platform'
1879
1862
)
1880
1863
try :
@@ -1895,7 +1878,7 @@ def _extract_resource(self, manager, zip_path): # noqa: C901
1895
1878
try :
1896
1879
rename (tmpnam , real_path )
1897
1880
1898
- except os . error :
1881
+ except OSError :
1899
1882
if os .path .isfile (real_path ):
1900
1883
if self ._is_current (real_path , zip_path ):
1901
1884
# the file became current since it was checked above,
@@ -1908,7 +1891,7 @@ def _extract_resource(self, manager, zip_path): # noqa: C901
1908
1891
return real_path
1909
1892
raise
1910
1893
1911
- except os . error :
1894
+ except OSError :
1912
1895
# report a user-friendly error
1913
1896
manager .extraction_error ()
1914
1897
@@ -2001,7 +1984,7 @@ def get_metadata(self, name):
2001
1984
if name != 'PKG-INFO' :
2002
1985
raise KeyError ("No metadata except PKG-INFO is available" )
2003
1986
2004
- with io . open (self .path , encoding = 'utf-8' , errors = "replace" ) as f :
1987
+ with open (self .path , encoding = 'utf-8' , errors = "replace" ) as f :
2005
1988
metadata = f .read ()
2006
1989
self ._warn_on_replacement (metadata )
2007
1990
return metadata
@@ -2095,8 +2078,7 @@ def find_eggs_in_zip(importer, path_item, only=False):
2095
2078
if _is_egg_path (subitem ):
2096
2079
subpath = os .path .join (path_item , subitem )
2097
2080
dists = find_eggs_in_zip (zipimport .zipimporter (subpath ), subpath )
2098
- for dist in dists :
2099
- yield dist
2081
+ yield from dists
2100
2082
elif subitem .lower ().endswith (('.dist-info' , '.egg-info' )):
2101
2083
subpath = os .path .join (path_item , subitem )
2102
2084
submeta = EggMetadata (zipimport .zipimporter (subpath ))
@@ -2131,8 +2113,7 @@ def find_on_path(importer, path_item, only=False):
2131
2113
for entry in sorted (entries ):
2132
2114
fullpath = os .path .join (path_item , entry )
2133
2115
factory = dist_factory (path_item , entry , only )
2134
- for dist in factory (fullpath ):
2135
- yield dist
2116
+ yield from factory (fullpath )
2136
2117
2137
2118
2138
2119
def dist_factory (path_item , entry , only ):
@@ -2231,7 +2212,7 @@ def resolve_egg_link(path):
2231
2212
if hasattr (pkgutil , 'ImpImporter' ):
2232
2213
register_finder (pkgutil .ImpImporter , find_on_path )
2233
2214
2234
- register_finder (importlib_machinery .FileFinder , find_on_path )
2215
+ register_finder (importlib . machinery .FileFinder , find_on_path )
2235
2216
2236
2217
_declare_state ('dict' , _namespace_handlers = {})
2237
2218
_declare_state ('dict' , _namespace_packages = {})
@@ -2398,7 +2379,7 @@ def file_ns_handler(importer, path_item, packageName, module):
2398
2379
register_namespace_handler (pkgutil .ImpImporter , file_ns_handler )
2399
2380
2400
2381
register_namespace_handler (zipimport .zipimporter , file_ns_handler )
2401
- register_namespace_handler (importlib_machinery .FileFinder , file_ns_handler )
2382
+ register_namespace_handler (importlib . machinery .FileFinder , file_ns_handler )
2402
2383
2403
2384
2404
2385
def null_ns_handler (importer , path_item , packageName , module ):
@@ -2424,12 +2405,9 @@ def _cygwin_patch(filename): # pragma: nocover
2424
2405
return os .path .abspath (filename ) if sys .platform == 'cygwin' else filename
2425
2406
2426
2407
2427
- def _normalize_cached (filename , _cache = {}):
2428
- try :
2429
- return _cache [filename ]
2430
- except KeyError :
2431
- _cache [filename ] = result = normalize_path (filename )
2432
- return result
2408
+ @functools .lru_cache (maxsize = None )
2409
+ def _normalize_cached (filename ):
2410
+ return normalize_path (filename )
2433
2411
2434
2412
2435
2413
def _is_egg_path (path ):
@@ -2850,14 +2828,11 @@ def _get_metadata_path_for_display(self, name):
2850
2828
2851
2829
def _get_metadata (self , name ):
2852
2830
if self .has_metadata (name ):
2853
- for line in self .get_metadata_lines (name ):
2854
- yield line
2831
+ yield from self .get_metadata_lines (name )
2855
2832
2856
2833
def _get_version (self ):
2857
2834
lines = self ._get_metadata (self .PKG_INFO )
2858
- version = _version_from_file (lines )
2859
-
2860
- return version
2835
+ return _version_from_file (lines )
2861
2836
2862
2837
def activate (self , path = None , replace = False ):
2863
2838
"""Ensure distribution is importable on `path` (default=sys.path)"""
@@ -2904,7 +2879,7 @@ def __getattr__(self, attr):
2904
2879
2905
2880
def __dir__ (self ):
2906
2881
return list (
2907
- set (super (Distribution , self ).__dir__ ())
2882
+ set (super ().__dir__ ())
2908
2883
| set (attr for attr in self ._provider .__dir__ () if not attr .startswith ('_' ))
2909
2884
)
2910
2885
@@ -3171,7 +3146,7 @@ class RequirementParseError(packaging.requirements.InvalidRequirement):
3171
3146
class Requirement (packaging .requirements .Requirement ):
3172
3147
def __init__ (self , requirement_string ):
3173
3148
"""DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!"""
3174
- super (Requirement , self ).__init__ (requirement_string )
3149
+ super ().__init__ (requirement_string )
3175
3150
self .unsafe_name = self .name
3176
3151
project_name = safe_name (self .name )
3177
3152
self .project_name , self .key = project_name , project_name .lower ()
@@ -3232,6 +3207,7 @@ def _find_adapter(registry, ob):
3232
3207
for t in types :
3233
3208
if t in registry :
3234
3209
return registry [t ]
3210
+ return None
3235
3211
3236
3212
3237
3213
def ensure_directory (path ):
@@ -3243,7 +3219,7 @@ def ensure_directory(path):
3243
3219
def _bypass_ensure_directory (path ):
3244
3220
"""Sandbox-bypassing version of ensure_directory()"""
3245
3221
if not WRITE_SUPPORT :
3246
- raise IOError ('"os.mkdir" not supported on this platform.' )
3222
+ raise OSError ('"os.mkdir" not supported on this platform.' )
3247
3223
dirname , filename = split (path )
3248
3224
if dirname and filename and not isdir (dirname ):
3249
3225
_bypass_ensure_directory (dirname )
0 commit comments