@@ -64,7 +64,7 @@ def _reconstruct_alias(alias: _T, parameters: Iterator[TypeVar]) -> _T:
64
64
args .append (value )
65
65
66
66
cls = type (alias )
67
- return cls (alias .__origin__ , tuple (args ))
67
+ return cls (alias .__origin__ , tuple (args ), alias . __unpacked__ )
68
68
69
69
70
70
class _GenericAlias :
@@ -80,7 +80,14 @@ class _GenericAlias:
80
80
81
81
"""
82
82
83
- __slots__ = ("__weakref__" , "_origin" , "_args" , "_parameters" , "_hash" )
83
+ __slots__ = (
84
+ "__weakref__" ,
85
+ "_origin" ,
86
+ "_args" ,
87
+ "_parameters" ,
88
+ "_hash" ,
89
+ "_starred" ,
90
+ )
84
91
85
92
@property
86
93
def __origin__ (self ) -> type :
@@ -95,25 +102,38 @@ def __parameters__(self) -> tuple[TypeVar, ...]:
95
102
"""Type variables in the ``GenericAlias``."""
96
103
return super ().__getattribute__ ("_parameters" )
97
104
105
+ @property
106
+ def __unpacked__ (self ) -> bool :
107
+ return super ().__getattribute__ ("_starred" )
108
+
109
+ @property
110
+ def __typing_unpacked_tuple_args__ (self ) -> tuple [object , ...] | None :
111
+ # NOTE: This should return `__args__` if `__origin__` is a tuple,
112
+ # which should never be the case with how `_GenericAlias` is used
113
+ # within numpy
114
+ return None
115
+
98
116
def __init__ (
99
117
self ,
100
118
origin : type ,
101
119
args : object | tuple [object , ...],
120
+ starred : bool = False ,
102
121
) -> None :
103
122
self ._origin = origin
104
123
self ._args = args if isinstance (args , tuple ) else (args ,)
105
124
self ._parameters = tuple (_parse_parameters (self .__args__ ))
125
+ self ._starred = starred
106
126
107
127
@property
108
128
def __call__ (self ) -> type [Any ]:
109
129
return self .__origin__
110
130
111
131
def __reduce__ (self : _T ) -> tuple [
112
132
type [_T ],
113
- tuple [type [Any ], tuple [object , ...]],
133
+ tuple [type [Any ], tuple [object , ...], bool ],
114
134
]:
115
135
cls = type (self )
116
- return cls , (self .__origin__ , self .__args__ )
136
+ return cls , (self .__origin__ , self .__args__ , self . __unpacked__ )
117
137
118
138
def __mro_entries__ (self , bases : Iterable [object ]) -> tuple [type [Any ]]:
119
139
return (self .__origin__ ,)
@@ -130,7 +150,11 @@ def __hash__(self) -> int:
130
150
try :
131
151
return super ().__getattribute__ ("_hash" )
132
152
except AttributeError :
133
- self ._hash : int = hash (self .__origin__ ) ^ hash (self .__args__ )
153
+ self ._hash : int = (
154
+ hash (self .__origin__ ) ^
155
+ hash (self .__args__ ) ^
156
+ hash (self .__unpacked__ )
157
+ )
134
158
return super ().__getattribute__ ("_hash" )
135
159
136
160
def __instancecheck__ (self , obj : object ) -> NoReturn :
@@ -147,7 +171,8 @@ def __repr__(self) -> str:
147
171
"""Return ``repr(self)``."""
148
172
args = ", " .join (_to_str (i ) for i in self .__args__ )
149
173
origin = _to_str (self .__origin__ )
150
- return f"{ origin } [{ args } ]"
174
+ prefix = "*" if self .__unpacked__ else ""
175
+ return f"{ prefix } { origin } [{ args } ]"
151
176
152
177
def __getitem__ (self : _T , key : object | tuple [object , ...]) -> _T :
153
178
"""Return ``self[key]``."""
@@ -169,9 +194,17 @@ def __eq__(self, value: object) -> bool:
169
194
return NotImplemented
170
195
return (
171
196
self .__origin__ == value .__origin__ and
172
- self .__args__ == value .__args__
197
+ self .__args__ == value .__args__ and
198
+ self .__unpacked__ == getattr (
199
+ value , "__unpacked__" , self .__unpacked__
200
+ )
173
201
)
174
202
203
+ def __iter__ (self : _T ) -> Generator [_T , None , None ]:
204
+ """Return ``iter(self)``."""
205
+ cls = type (self )
206
+ yield cls (self .__origin__ , self .__args__ , True )
207
+
175
208
_ATTR_EXCEPTIONS : ClassVar [frozenset [str ]] = frozenset ({
176
209
"__origin__" ,
177
210
"__args__" ,
@@ -181,6 +214,8 @@ def __eq__(self, value: object) -> bool:
181
214
"__reduce_ex__" ,
182
215
"__copy__" ,
183
216
"__deepcopy__" ,
217
+ "__unpacked__" ,
218
+ "__typing_unpacked_tuple_args__" ,
184
219
})
185
220
186
221
def __getattribute__ (self , name : str ) -> Any :
0 commit comments