8
8
import sys
9
9
from glob import iglob
10
10
from pathlib import Path
11
- from typing import TYPE_CHECKING , MutableMapping
11
+ from typing import TYPE_CHECKING , List , MutableMapping , NoReturn , Tuple , Union , overload
12
12
13
13
from more_itertools import partition , unique_everseen
14
14
from packaging .markers import InvalidMarker , Marker
21
21
command as _ , # noqa: F401 # imported for side-effects
22
22
)
23
23
from ._importlib import metadata
24
+ from ._reqs import _StrOrIter
24
25
from .config import pyprojecttoml , setupcfg
25
26
from .discovery import ConfigDiscovery
26
27
from .monkey import get_unpatched
36
37
from distutils .fancy_getopt import translate_longopt
37
38
from distutils .util import strtobool
38
39
40
+ if TYPE_CHECKING :
41
+ from typing_extensions import TypeAlias
42
+
39
43
__all__ = ['Distribution' ]
40
44
41
45
sequence = tuple , list
46
+ """
47
+ Supported iterable types that are known to be:
48
+ - ordered (which `set` isn't)
49
+ - not match a str (which `Sequence[str]` does)
50
+ - not imply a nested type (like `dict`)
51
+ for use with `isinstance`.
52
+ """
53
+ _Sequence : TypeAlias = Union [Tuple [str , ...], List [str ]]
54
+ # This is how stringifying _Sequence would look in Python 3.10
55
+ _requence_type_repr = "tuple[str, ...] | list[str]"
42
56
43
57
44
58
def check_importable (dist , attr , value ):
@@ -51,7 +65,7 @@ def check_importable(dist, attr, value):
51
65
) from e
52
66
53
67
54
- def assert_string_list (dist , attr , value ) :
68
+ def assert_string_list (dist , attr : str , value : _Sequence ) -> None :
55
69
"""Verify that value is a string list"""
56
70
try :
57
71
# verify that value is a list or tuple to exclude unordered
@@ -61,7 +75,7 @@ def assert_string_list(dist, attr, value):
61
75
assert '' .join (value ) != value
62
76
except (TypeError , ValueError , AttributeError , AssertionError ) as e :
63
77
raise DistutilsSetupError (
64
- "%r must be a list of strings (got %r)" % ( attr , value )
78
+ f" { attr !r } must be of type < { _requence_type_repr } > (got { value !r } )"
65
79
) from e
66
80
67
81
@@ -138,18 +152,22 @@ def invalid_unless_false(dist, attr, value):
138
152
raise DistutilsSetupError (f"{ attr } is invalid." )
139
153
140
154
141
- def check_requirements (dist , attr , value ):
155
+ @overload
156
+ def check_requirements (dist , attr : str , value : set | dict ) -> NoReturn : ...
157
+ @overload
158
+ def check_requirements (dist , attr : str , value : _StrOrIter ) -> None : ...
159
+ def check_requirements (dist , attr : str , value : _StrOrIter ) -> None :
142
160
"""Verify that install_requires is a valid requirements list"""
143
161
try :
144
162
list (_reqs .parse (value ))
145
163
if isinstance (value , (dict , set )):
146
164
raise TypeError ("Unordered types are not allowed" )
147
165
except (TypeError , ValueError ) as error :
148
166
tmpl = (
149
- "{attr!r} must be a string or list of strings "
150
- "containing valid project/version requirement specifiers; {error}"
167
+ f "{ attr !r} must be a string or iterable of strings "
168
+ f "containing valid project/version requirement specifiers; { error } "
151
169
)
152
- raise DistutilsSetupError (tmpl . format ( attr = attr , error = error ) ) from error
170
+ raise DistutilsSetupError (tmpl ) from error
153
171
154
172
155
173
def check_specifier (dist , attr , value ):
@@ -767,11 +785,11 @@ def has_contents_for(self, package):
767
785
768
786
return False
769
787
770
- def _exclude_misc (self , name , value ) :
788
+ def _exclude_misc (self , name : str , value : _Sequence ) -> None :
771
789
"""Handle 'exclude()' for list/tuple attrs without a special handler"""
772
790
if not isinstance (value , sequence ):
773
791
raise DistutilsSetupError (
774
- "%s : setting must be a list or tuple (%r)" % ( name , value )
792
+ f" { name } : setting must be of type < { _requence_type_repr } > (got { value !r } )"
775
793
)
776
794
try :
777
795
old = getattr (self , name )
@@ -784,11 +802,13 @@ def _exclude_misc(self, name, value):
784
802
elif old :
785
803
setattr (self , name , [item for item in old if item not in value ])
786
804
787
- def _include_misc (self , name , value ) :
805
+ def _include_misc (self , name : str , value : _Sequence ) -> None :
788
806
"""Handle 'include()' for list/tuple attrs without a special handler"""
789
807
790
808
if not isinstance (value , sequence ):
791
- raise DistutilsSetupError ("%s: setting must be a list (%r)" % (name , value ))
809
+ raise DistutilsSetupError (
810
+ f"{ name } : setting must be of type <{ _requence_type_repr } > (got { value !r} )"
811
+ )
792
812
try :
793
813
old = getattr (self , name )
794
814
except AttributeError as e :
@@ -801,7 +821,7 @@ def _include_misc(self, name, value):
801
821
)
802
822
else :
803
823
new = [item for item in value if item not in old ]
804
- setattr (self , name , old + new )
824
+ setattr (self , name , list ( old ) + new )
805
825
806
826
def exclude (self , ** attrs ):
807
827
"""Remove items from distribution that are named in keyword arguments
@@ -826,10 +846,10 @@ def exclude(self, **attrs):
826
846
else :
827
847
self ._exclude_misc (k , v )
828
848
829
- def _exclude_packages (self , packages ) :
849
+ def _exclude_packages (self , packages : _Sequence ) -> None :
830
850
if not isinstance (packages , sequence ):
831
851
raise DistutilsSetupError (
832
- "packages: setting must be a list or tuple (%r)" % ( packages ,)
852
+ f "packages: setting must be of type < { _requence_type_repr } > (got { packages !r } )"
833
853
)
834
854
list (map (self .exclude_package , packages ))
835
855
0 commit comments