/src/cpython/Objects/genericaliasobject.c
Line | Count | Source |
1 | | // types.GenericAlias -- used to represent e.g. list[int]. |
2 | | |
3 | | #include "Python.h" |
4 | | #include "pycore_ceval.h" // _PyEval_GetBuiltin() |
5 | | #include "pycore_modsupport.h" // _PyArg_NoKeywords() |
6 | | #include "pycore_object.h" |
7 | | #include "pycore_typevarobject.h" // _Py_typing_type_repr |
8 | | #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() |
9 | | #include "pycore_unionobject.h" // _Py_union_type_or, _PyGenericAlias_Check |
10 | | #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() |
11 | | |
12 | | |
13 | | #include <stdbool.h> |
14 | | |
15 | | typedef struct { |
16 | | PyObject_HEAD |
17 | | PyObject *origin; |
18 | | PyObject *args; |
19 | | PyObject *parameters; |
20 | | PyObject *weakreflist; |
21 | | // Whether we're a starred type, e.g. *tuple[int]. |
22 | | bool starred; |
23 | | vectorcallfunc vectorcall; |
24 | | } gaobject; |
25 | | |
26 | | typedef struct { |
27 | | PyObject_HEAD |
28 | | PyObject *obj; /* Set to NULL when iterator is exhausted */ |
29 | | } gaiterobject; |
30 | | |
31 | | static void |
32 | | ga_dealloc(PyObject *self) |
33 | 151 | { |
34 | 151 | gaobject *alias = (gaobject *)self; |
35 | | |
36 | 151 | _PyObject_GC_UNTRACK(self); |
37 | 151 | FT_CLEAR_WEAKREFS(self, alias->weakreflist); |
38 | 151 | Py_XDECREF(alias->origin); |
39 | 151 | Py_XDECREF(alias->args); |
40 | 151 | Py_XDECREF(alias->parameters); |
41 | 151 | Py_TYPE(self)->tp_free(self); |
42 | 151 | } |
43 | | |
44 | | static int |
45 | | ga_traverse(PyObject *self, visitproc visit, void *arg) |
46 | 44.5k | { |
47 | 44.5k | gaobject *alias = (gaobject *)self; |
48 | 44.5k | Py_VISIT(alias->origin); |
49 | 44.5k | Py_VISIT(alias->args); |
50 | 44.5k | Py_VISIT(alias->parameters); |
51 | 44.5k | return 0; |
52 | 44.5k | } |
53 | | |
54 | | static int |
55 | | ga_repr_items_list(PyUnicodeWriter *writer, PyObject *p) |
56 | 0 | { |
57 | 0 | assert(PyList_CheckExact(p)); |
58 | |
|
59 | 0 | Py_ssize_t len = PyList_GET_SIZE(p); |
60 | |
|
61 | 0 | if (PyUnicodeWriter_WriteChar(writer, '[') < 0) { |
62 | 0 | return -1; |
63 | 0 | } |
64 | | |
65 | 0 | for (Py_ssize_t i = 0; i < len; i++) { |
66 | 0 | if (i > 0) { |
67 | 0 | if (PyUnicodeWriter_WriteASCII(writer, ", ", 2) < 0) { |
68 | 0 | return -1; |
69 | 0 | } |
70 | 0 | } |
71 | 0 | PyObject *item = PyList_GetItemRef(p, i); |
72 | 0 | if (item == NULL) { |
73 | 0 | return -1; // list can be mutated in a callback |
74 | 0 | } |
75 | 0 | if (_Py_typing_type_repr(writer, item) < 0) { |
76 | 0 | Py_DECREF(item); |
77 | 0 | return -1; |
78 | 0 | } |
79 | 0 | Py_DECREF(item); |
80 | 0 | } |
81 | | |
82 | 0 | if (PyUnicodeWriter_WriteChar(writer, ']') < 0) { |
83 | 0 | return -1; |
84 | 0 | } |
85 | | |
86 | 0 | return 0; |
87 | 0 | } |
88 | | |
89 | | static PyObject * |
90 | | ga_repr(PyObject *self) |
91 | 28 | { |
92 | 28 | gaobject *alias = (gaobject *)self; |
93 | 28 | Py_ssize_t len = PyTuple_GET_SIZE(alias->args); |
94 | | |
95 | | // Estimation based on the shortest format: "int[int, int, int]" |
96 | 28 | Py_ssize_t estimate = (len <= PY_SSIZE_T_MAX / 5) ? len * 5 : len; |
97 | 28 | estimate = 3 + 1 + estimate + 1; |
98 | 28 | PyUnicodeWriter *writer = PyUnicodeWriter_Create(estimate); |
99 | 28 | if (writer == NULL) { |
100 | 0 | return NULL; |
101 | 0 | } |
102 | | |
103 | 28 | if (alias->starred) { |
104 | 0 | if (PyUnicodeWriter_WriteChar(writer, '*') < 0) { |
105 | 0 | goto error; |
106 | 0 | } |
107 | 0 | } |
108 | 28 | if (_Py_typing_type_repr(writer, alias->origin) < 0) { |
109 | 0 | goto error; |
110 | 0 | } |
111 | 28 | if (PyUnicodeWriter_WriteChar(writer, '[') < 0) { |
112 | 0 | goto error; |
113 | 0 | } |
114 | 74 | for (Py_ssize_t i = 0; i < len; i++) { |
115 | 46 | if (i > 0) { |
116 | 18 | if (PyUnicodeWriter_WriteASCII(writer, ", ", 2) < 0) { |
117 | 0 | goto error; |
118 | 0 | } |
119 | 18 | } |
120 | 46 | PyObject *p = PyTuple_GET_ITEM(alias->args, i); |
121 | 46 | if (PyList_CheckExact(p)) { |
122 | | // Looks like we are working with ParamSpec's list of type args: |
123 | 0 | if (ga_repr_items_list(writer, p) < 0) { |
124 | 0 | goto error; |
125 | 0 | } |
126 | 0 | } |
127 | 46 | else if (_Py_typing_type_repr(writer, p) < 0) { |
128 | 0 | goto error; |
129 | 0 | } |
130 | 46 | } |
131 | 28 | if (len == 0) { |
132 | | // for something like tuple[()] we should print a "()" |
133 | 0 | if (PyUnicodeWriter_WriteASCII(writer, "()", 2) < 0) { |
134 | 0 | goto error; |
135 | 0 | } |
136 | 0 | } |
137 | 28 | if (PyUnicodeWriter_WriteChar(writer, ']') < 0) { |
138 | 0 | goto error; |
139 | 0 | } |
140 | 28 | return PyUnicodeWriter_Finish(writer); |
141 | | |
142 | 0 | error: |
143 | 0 | PyUnicodeWriter_Discard(writer); |
144 | 0 | return NULL; |
145 | 28 | } |
146 | | |
147 | | // Index of item in self[:len], or -1 if not found (self is a tuple) |
148 | | static Py_ssize_t |
149 | | tuple_index(PyObject *self, Py_ssize_t len, PyObject *item) |
150 | 20 | { |
151 | 24 | for (Py_ssize_t i = 0; i < len; i++) { |
152 | 4 | if (PyTuple_GET_ITEM(self, i) == item) { |
153 | 0 | return i; |
154 | 0 | } |
155 | 4 | } |
156 | 20 | return -1; |
157 | 20 | } |
158 | | |
159 | | static int |
160 | | tuple_add(PyObject *self, Py_ssize_t len, PyObject *item) |
161 | 20 | { |
162 | 20 | if (tuple_index(self, len, item) < 0) { |
163 | 20 | PyTuple_SET_ITEM(self, len, Py_NewRef(item)); |
164 | 20 | return 1; |
165 | 20 | } |
166 | 0 | return 0; |
167 | 20 | } |
168 | | |
169 | | static Py_ssize_t |
170 | | tuple_extend(PyObject **dst, Py_ssize_t dstindex, |
171 | | PyObject **src, Py_ssize_t count) |
172 | 0 | { |
173 | 0 | assert(count >= 0); |
174 | 0 | if (_PyTuple_Resize(dst, PyTuple_GET_SIZE(*dst) + count - 1) != 0) { |
175 | 0 | return -1; |
176 | 0 | } |
177 | 0 | assert(dstindex + count <= PyTuple_GET_SIZE(*dst)); |
178 | 0 | for (Py_ssize_t i = 0; i < count; ++i) { |
179 | 0 | PyObject *item = src[i]; |
180 | 0 | PyTuple_SET_ITEM(*dst, dstindex + i, Py_NewRef(item)); |
181 | 0 | } |
182 | 0 | return dstindex + count; |
183 | 0 | } |
184 | | |
185 | | PyObject * |
186 | | _Py_make_parameters(PyObject *args) |
187 | 52 | { |
188 | 52 | assert(PyTuple_Check(args) || PyList_Check(args)); |
189 | 52 | const bool is_args_list = PyList_Check(args); |
190 | 52 | PyObject *tuple_args = NULL; |
191 | 52 | if (is_args_list) { |
192 | 0 | args = tuple_args = PySequence_Tuple(args); |
193 | 0 | if (args == NULL) { |
194 | 0 | return NULL; |
195 | 0 | } |
196 | 0 | } |
197 | 52 | Py_ssize_t nargs = PyTuple_GET_SIZE(args); |
198 | 52 | Py_ssize_t len = nargs; |
199 | 52 | PyObject *parameters = PyTuple_New(len); |
200 | 52 | if (parameters == NULL) { |
201 | 0 | Py_XDECREF(tuple_args); |
202 | 0 | return NULL; |
203 | 0 | } |
204 | 52 | Py_ssize_t iparam = 0; |
205 | 152 | for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { |
206 | 100 | PyObject *t = PyTuple_GET_ITEM(args, iarg); |
207 | | // We don't want __parameters__ descriptor of a bare Python class. |
208 | 100 | if (PyType_Check(t)) { |
209 | 46 | continue; |
210 | 46 | } |
211 | 54 | int rc = PyObject_HasAttrWithError(t, &_Py_ID(__typing_subst__)); |
212 | 54 | if (rc < 0) { |
213 | 0 | Py_DECREF(parameters); |
214 | 0 | Py_XDECREF(tuple_args); |
215 | 0 | return NULL; |
216 | 0 | } |
217 | 54 | if (rc) { |
218 | 20 | iparam += tuple_add(parameters, iparam, t); |
219 | 20 | } |
220 | 34 | else { |
221 | 34 | PyObject *subparams; |
222 | 34 | if (PyObject_GetOptionalAttr(t, &_Py_ID(__parameters__), |
223 | 34 | &subparams) < 0) { |
224 | 0 | Py_DECREF(parameters); |
225 | 0 | Py_XDECREF(tuple_args); |
226 | 0 | return NULL; |
227 | 0 | } |
228 | 34 | if (!subparams && (PyTuple_Check(t) || PyList_Check(t))) { |
229 | | // Recursively call _Py_make_parameters for lists/tuples and |
230 | | // add the results to the current parameters. |
231 | 0 | subparams = _Py_make_parameters(t); |
232 | 0 | if (subparams == NULL) { |
233 | 0 | Py_DECREF(parameters); |
234 | 0 | Py_XDECREF(tuple_args); |
235 | 0 | return NULL; |
236 | 0 | } |
237 | 0 | } |
238 | 34 | if (subparams && PyTuple_Check(subparams)) { |
239 | 20 | Py_ssize_t len2 = PyTuple_GET_SIZE(subparams); |
240 | 20 | Py_ssize_t needed = len2 - 1 - (iarg - iparam); |
241 | 20 | if (needed > 0) { |
242 | 0 | len += needed; |
243 | 0 | if (_PyTuple_Resize(¶meters, len) < 0) { |
244 | 0 | Py_DECREF(subparams); |
245 | 0 | Py_DECREF(parameters); |
246 | 0 | Py_XDECREF(tuple_args); |
247 | 0 | return NULL; |
248 | 0 | } |
249 | 0 | } |
250 | 20 | for (Py_ssize_t j = 0; j < len2; j++) { |
251 | 0 | PyObject *t2 = PyTuple_GET_ITEM(subparams, j); |
252 | 0 | iparam += tuple_add(parameters, iparam, t2); |
253 | 0 | } |
254 | 20 | } |
255 | 34 | Py_XDECREF(subparams); |
256 | 34 | } |
257 | 54 | } |
258 | 52 | if (iparam < len) { |
259 | 38 | if (_PyTuple_Resize(¶meters, iparam) < 0) { |
260 | 0 | Py_XDECREF(parameters); |
261 | 0 | Py_XDECREF(tuple_args); |
262 | 0 | return NULL; |
263 | 0 | } |
264 | 38 | } |
265 | 52 | Py_XDECREF(tuple_args); |
266 | 52 | return parameters; |
267 | 52 | } |
268 | | |
269 | | /* If obj is a generic alias, substitute type variables params |
270 | | with substitutions argitems. For example, if obj is list[T], |
271 | | params is (T, S), and argitems is (str, int), return list[str]. |
272 | | If obj doesn't have a __parameters__ attribute or that's not |
273 | | a non-empty tuple, return a new reference to obj. */ |
274 | | static PyObject * |
275 | | subs_tvars(PyObject *obj, PyObject *params, |
276 | | PyObject **argitems, Py_ssize_t nargs) |
277 | 0 | { |
278 | 0 | PyObject *subparams; |
279 | 0 | if (PyObject_GetOptionalAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) { |
280 | 0 | return NULL; |
281 | 0 | } |
282 | 0 | if (subparams && PyTuple_Check(subparams) && PyTuple_GET_SIZE(subparams)) { |
283 | 0 | Py_ssize_t nparams = PyTuple_GET_SIZE(params); |
284 | 0 | Py_ssize_t nsubargs = PyTuple_GET_SIZE(subparams); |
285 | 0 | PyObject *subargs = PyTuple_New(nsubargs); |
286 | 0 | if (subargs == NULL) { |
287 | 0 | Py_DECREF(subparams); |
288 | 0 | return NULL; |
289 | 0 | } |
290 | 0 | Py_ssize_t j = 0; |
291 | 0 | for (Py_ssize_t i = 0; i < nsubargs; ++i) { |
292 | 0 | PyObject *arg = PyTuple_GET_ITEM(subparams, i); |
293 | 0 | Py_ssize_t iparam = tuple_index(params, nparams, arg); |
294 | 0 | if (iparam >= 0) { |
295 | 0 | PyObject *param = PyTuple_GET_ITEM(params, iparam); |
296 | 0 | arg = argitems[iparam]; |
297 | 0 | if (Py_TYPE(param)->tp_iter && PyTuple_Check(arg)) { // TypeVarTuple |
298 | 0 | j = tuple_extend(&subargs, j, |
299 | 0 | &PyTuple_GET_ITEM(arg, 0), |
300 | 0 | PyTuple_GET_SIZE(arg)); |
301 | 0 | if (j < 0) { |
302 | 0 | return NULL; |
303 | 0 | } |
304 | 0 | continue; |
305 | 0 | } |
306 | 0 | } |
307 | 0 | PyTuple_SET_ITEM(subargs, j, Py_NewRef(arg)); |
308 | 0 | j++; |
309 | 0 | } |
310 | 0 | assert(j == PyTuple_GET_SIZE(subargs)); |
311 | |
|
312 | 0 | obj = PyObject_GetItem(obj, subargs); |
313 | |
|
314 | 0 | Py_DECREF(subargs); |
315 | 0 | } |
316 | 0 | else { |
317 | 0 | Py_INCREF(obj); |
318 | 0 | } |
319 | 0 | Py_XDECREF(subparams); |
320 | 0 | return obj; |
321 | 0 | } |
322 | | |
323 | | static int |
324 | | _is_unpacked_typevartuple(PyObject *arg) |
325 | 0 | { |
326 | 0 | PyObject *tmp; |
327 | 0 | if (PyType_Check(arg)) { // TODO: Add test |
328 | 0 | return 0; |
329 | 0 | } |
330 | 0 | int res = PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_is_unpacked_typevartuple__), &tmp); |
331 | 0 | if (res > 0) { |
332 | 0 | res = PyObject_IsTrue(tmp); |
333 | 0 | Py_DECREF(tmp); |
334 | 0 | } |
335 | 0 | return res; |
336 | 0 | } |
337 | | |
338 | | static PyObject * |
339 | | _unpacked_tuple_args(PyObject *arg) |
340 | 0 | { |
341 | 0 | PyObject *result; |
342 | 0 | assert(!PyType_Check(arg)); |
343 | | // Fast path |
344 | 0 | if (_PyGenericAlias_Check(arg) && |
345 | 0 | ((gaobject *)arg)->starred && |
346 | 0 | ((gaobject *)arg)->origin == (PyObject *)&PyTuple_Type) |
347 | 0 | { |
348 | 0 | result = ((gaobject *)arg)->args; |
349 | 0 | return Py_NewRef(result); |
350 | 0 | } |
351 | | |
352 | 0 | if (PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_unpacked_tuple_args__), &result) > 0) { |
353 | 0 | if (result == Py_None) { |
354 | 0 | Py_DECREF(result); |
355 | 0 | return NULL; |
356 | 0 | } |
357 | 0 | return result; |
358 | 0 | } |
359 | 0 | return NULL; |
360 | 0 | } |
361 | | |
362 | | static PyObject * |
363 | | _unpack_args(PyObject *item) |
364 | 0 | { |
365 | 0 | PyObject *newargs = PyList_New(0); |
366 | 0 | if (newargs == NULL) { |
367 | 0 | return NULL; |
368 | 0 | } |
369 | 0 | int is_tuple = PyTuple_Check(item); |
370 | 0 | Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1; |
371 | 0 | PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item; |
372 | 0 | for (Py_ssize_t i = 0; i < nitems; i++) { |
373 | 0 | item = argitems[i]; |
374 | 0 | if (!PyType_Check(item)) { |
375 | 0 | PyObject *subargs = _unpacked_tuple_args(item); |
376 | 0 | if (subargs != NULL && |
377 | 0 | PyTuple_Check(subargs) && |
378 | 0 | !(PyTuple_GET_SIZE(subargs) && |
379 | 0 | PyTuple_GET_ITEM(subargs, PyTuple_GET_SIZE(subargs)-1) == Py_Ellipsis)) |
380 | 0 | { |
381 | 0 | if (PyList_SetSlice(newargs, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, subargs) < 0) { |
382 | 0 | Py_DECREF(subargs); |
383 | 0 | Py_DECREF(newargs); |
384 | 0 | return NULL; |
385 | 0 | } |
386 | 0 | Py_DECREF(subargs); |
387 | 0 | continue; |
388 | 0 | } |
389 | 0 | Py_XDECREF(subargs); |
390 | 0 | if (PyErr_Occurred()) { |
391 | 0 | Py_DECREF(newargs); |
392 | 0 | return NULL; |
393 | 0 | } |
394 | 0 | } |
395 | 0 | if (PyList_Append(newargs, item) < 0) { |
396 | 0 | Py_DECREF(newargs); |
397 | 0 | return NULL; |
398 | 0 | } |
399 | 0 | } |
400 | 0 | Py_SETREF(newargs, PySequence_Tuple(newargs)); |
401 | 0 | return newargs; |
402 | 0 | } |
403 | | |
404 | | PyObject * |
405 | | _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObject *item) |
406 | 0 | { |
407 | 0 | Py_ssize_t nparams = PyTuple_GET_SIZE(parameters); |
408 | 0 | if (nparams == 0) { |
409 | 0 | return PyErr_Format(PyExc_TypeError, |
410 | 0 | "%R is not a generic class", |
411 | 0 | self); |
412 | 0 | } |
413 | 0 | item = _unpack_args(item); |
414 | 0 | for (Py_ssize_t i = 0; i < nparams; i++) { |
415 | 0 | PyObject *param = PyTuple_GET_ITEM(parameters, i); |
416 | 0 | PyObject *prepare, *tmp; |
417 | 0 | if (PyObject_GetOptionalAttr(param, &_Py_ID(__typing_prepare_subst__), &prepare) < 0) { |
418 | 0 | Py_DECREF(item); |
419 | 0 | return NULL; |
420 | 0 | } |
421 | 0 | if (prepare && prepare != Py_None) { |
422 | 0 | if (PyTuple_Check(item)) { |
423 | 0 | tmp = PyObject_CallFunction(prepare, "OO", self, item); |
424 | 0 | } |
425 | 0 | else { |
426 | 0 | tmp = PyObject_CallFunction(prepare, "O(O)", self, item); |
427 | 0 | } |
428 | 0 | Py_DECREF(prepare); |
429 | 0 | Py_SETREF(item, tmp); |
430 | 0 | if (item == NULL) { |
431 | 0 | return NULL; |
432 | 0 | } |
433 | 0 | } |
434 | 0 | } |
435 | 0 | int is_tuple = PyTuple_Check(item); |
436 | 0 | Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1; |
437 | 0 | PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item; |
438 | 0 | if (nitems != nparams) { |
439 | 0 | Py_DECREF(item); |
440 | 0 | return PyErr_Format(PyExc_TypeError, |
441 | 0 | "Too %s arguments for %R; actual %zd, expected %zd", |
442 | 0 | nitems > nparams ? "many" : "few", |
443 | 0 | self, nitems, nparams); |
444 | 0 | } |
445 | | /* Replace all type variables (specified by parameters) |
446 | | with corresponding values specified by argitems. |
447 | | t = list[T]; t[int] -> newargs = [int] |
448 | | t = dict[str, T]; t[int] -> newargs = [str, int] |
449 | | t = dict[T, list[S]]; t[str, int] -> newargs = [str, list[int]] |
450 | | t = list[[T]]; t[str] -> newargs = [[str]] |
451 | | */ |
452 | 0 | assert (PyTuple_Check(args) || PyList_Check(args)); |
453 | 0 | const bool is_args_list = PyList_Check(args); |
454 | 0 | PyObject *tuple_args = NULL; |
455 | 0 | if (is_args_list) { |
456 | 0 | args = tuple_args = PySequence_Tuple(args); |
457 | 0 | if (args == NULL) { |
458 | 0 | return NULL; |
459 | 0 | } |
460 | 0 | } |
461 | 0 | Py_ssize_t nargs = PyTuple_GET_SIZE(args); |
462 | 0 | PyObject *newargs = PyTuple_New(nargs); |
463 | 0 | if (newargs == NULL) { |
464 | 0 | Py_DECREF(item); |
465 | 0 | Py_XDECREF(tuple_args); |
466 | 0 | return NULL; |
467 | 0 | } |
468 | 0 | for (Py_ssize_t iarg = 0, jarg = 0; iarg < nargs; iarg++) { |
469 | 0 | PyObject *arg = PyTuple_GET_ITEM(args, iarg); |
470 | 0 | if (PyType_Check(arg)) { |
471 | 0 | PyTuple_SET_ITEM(newargs, jarg, Py_NewRef(arg)); |
472 | 0 | jarg++; |
473 | 0 | continue; |
474 | 0 | } |
475 | | // Recursively substitute params in lists/tuples. |
476 | 0 | if (PyTuple_Check(arg) || PyList_Check(arg)) { |
477 | 0 | PyObject *subargs = _Py_subs_parameters(self, arg, parameters, item); |
478 | 0 | if (subargs == NULL) { |
479 | 0 | Py_DECREF(newargs); |
480 | 0 | Py_DECREF(item); |
481 | 0 | Py_XDECREF(tuple_args); |
482 | 0 | return NULL; |
483 | 0 | } |
484 | 0 | if (PyTuple_Check(arg)) { |
485 | 0 | PyTuple_SET_ITEM(newargs, jarg, subargs); |
486 | 0 | } |
487 | 0 | else { |
488 | | // _Py_subs_parameters returns a tuple. If the original arg was a list, |
489 | | // convert subargs to a list as well. |
490 | 0 | PyObject *subargs_list = PySequence_List(subargs); |
491 | 0 | Py_DECREF(subargs); |
492 | 0 | if (subargs_list == NULL) { |
493 | 0 | Py_DECREF(newargs); |
494 | 0 | Py_DECREF(item); |
495 | 0 | Py_XDECREF(tuple_args); |
496 | 0 | return NULL; |
497 | 0 | } |
498 | 0 | PyTuple_SET_ITEM(newargs, jarg, subargs_list); |
499 | 0 | } |
500 | 0 | jarg++; |
501 | 0 | continue; |
502 | 0 | } |
503 | 0 | int unpack = _is_unpacked_typevartuple(arg); |
504 | 0 | if (unpack < 0) { |
505 | 0 | Py_DECREF(newargs); |
506 | 0 | Py_DECREF(item); |
507 | 0 | Py_XDECREF(tuple_args); |
508 | 0 | return NULL; |
509 | 0 | } |
510 | 0 | PyObject *subst; |
511 | 0 | if (PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) { |
512 | 0 | Py_DECREF(newargs); |
513 | 0 | Py_DECREF(item); |
514 | 0 | Py_XDECREF(tuple_args); |
515 | 0 | return NULL; |
516 | 0 | } |
517 | 0 | if (subst) { |
518 | 0 | Py_ssize_t iparam = tuple_index(parameters, nparams, arg); |
519 | 0 | assert(iparam >= 0); |
520 | 0 | arg = PyObject_CallOneArg(subst, argitems[iparam]); |
521 | 0 | Py_DECREF(subst); |
522 | 0 | } |
523 | 0 | else { |
524 | 0 | arg = subs_tvars(arg, parameters, argitems, nitems); |
525 | 0 | } |
526 | 0 | if (arg == NULL) { |
527 | 0 | Py_DECREF(newargs); |
528 | 0 | Py_DECREF(item); |
529 | 0 | Py_XDECREF(tuple_args); |
530 | 0 | return NULL; |
531 | 0 | } |
532 | 0 | if (unpack) { |
533 | 0 | if (!PyTuple_Check(arg)) { |
534 | 0 | Py_DECREF(newargs); |
535 | 0 | Py_DECREF(item); |
536 | 0 | Py_XDECREF(tuple_args); |
537 | 0 | PyObject *original = PyTuple_GET_ITEM(args, iarg); |
538 | 0 | PyErr_Format(PyExc_TypeError, |
539 | 0 | "expected __typing_subst__ of %T objects to return a tuple, not %T", |
540 | 0 | original, arg); |
541 | 0 | Py_DECREF(arg); |
542 | 0 | return NULL; |
543 | 0 | } |
544 | 0 | jarg = tuple_extend(&newargs, jarg, |
545 | 0 | &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg)); |
546 | 0 | Py_DECREF(arg); |
547 | 0 | if (jarg < 0) { |
548 | 0 | Py_DECREF(item); |
549 | 0 | Py_XDECREF(tuple_args); |
550 | 0 | assert(newargs == NULL); |
551 | 0 | return NULL; |
552 | 0 | } |
553 | 0 | } |
554 | 0 | else { |
555 | 0 | PyTuple_SET_ITEM(newargs, jarg, arg); |
556 | 0 | jarg++; |
557 | 0 | } |
558 | 0 | } |
559 | | |
560 | 0 | Py_DECREF(item); |
561 | 0 | Py_XDECREF(tuple_args); |
562 | 0 | return newargs; |
563 | 0 | } |
564 | | |
565 | | PyDoc_STRVAR(genericalias__doc__, |
566 | | "GenericAlias(origin, args, /)\n" |
567 | | "--\n\n" |
568 | | "Represent a PEP 585 generic type\n" |
569 | | "\n" |
570 | | "E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,)."); |
571 | | |
572 | | static PyObject * |
573 | | ga_getitem(PyObject *self, PyObject *item) |
574 | 0 | { |
575 | 0 | gaobject *alias = (gaobject *)self; |
576 | | // Populate __parameters__ if needed. |
577 | 0 | if (alias->parameters == NULL) { |
578 | 0 | alias->parameters = _Py_make_parameters(alias->args); |
579 | 0 | if (alias->parameters == NULL) { |
580 | 0 | return NULL; |
581 | 0 | } |
582 | 0 | } |
583 | | |
584 | 0 | PyObject *newargs = _Py_subs_parameters(self, alias->args, alias->parameters, item); |
585 | 0 | if (newargs == NULL) { |
586 | 0 | return NULL; |
587 | 0 | } |
588 | | |
589 | 0 | PyObject *res = Py_GenericAlias(alias->origin, newargs); |
590 | 0 | if (res == NULL) { |
591 | 0 | Py_DECREF(newargs); |
592 | 0 | return NULL; |
593 | 0 | } |
594 | 0 | ((gaobject *)res)->starred = alias->starred; |
595 | |
|
596 | 0 | Py_DECREF(newargs); |
597 | 0 | return res; |
598 | 0 | } |
599 | | |
600 | | static PyMappingMethods ga_as_mapping = { |
601 | | .mp_subscript = ga_getitem, |
602 | | }; |
603 | | |
604 | | static Py_hash_t |
605 | | ga_hash(PyObject *self) |
606 | 368 | { |
607 | 368 | gaobject *alias = (gaobject *)self; |
608 | | // TODO: Hash in the hash for the origin |
609 | 368 | Py_hash_t h0 = PyObject_Hash(alias->origin); |
610 | 368 | if (h0 == -1) { |
611 | 0 | return -1; |
612 | 0 | } |
613 | 368 | Py_hash_t h1 = PyObject_Hash(alias->args); |
614 | 368 | if (h1 == -1) { |
615 | 0 | return -1; |
616 | 0 | } |
617 | 368 | return h0 ^ h1; |
618 | 368 | } |
619 | | |
620 | | static inline PyObject * |
621 | | set_orig_class(PyObject *obj, PyObject *self) |
622 | 0 | { |
623 | 0 | if (obj != NULL) { |
624 | 0 | if (PyObject_SetAttr(obj, &_Py_ID(__orig_class__), self) < 0) { |
625 | 0 | if (!PyErr_ExceptionMatches(PyExc_AttributeError) && |
626 | 0 | !PyErr_ExceptionMatches(PyExc_TypeError)) |
627 | 0 | { |
628 | 0 | Py_DECREF(obj); |
629 | 0 | return NULL; |
630 | 0 | } |
631 | 0 | PyErr_Clear(); |
632 | 0 | } |
633 | 0 | } |
634 | 0 | return obj; |
635 | 0 | } |
636 | | |
637 | | static PyObject * |
638 | | ga_call(PyObject *self, PyObject *args, PyObject *kwds) |
639 | 0 | { |
640 | 0 | gaobject *alias = (gaobject *)self; |
641 | 0 | PyObject *obj = PyObject_Call(alias->origin, args, kwds); |
642 | 0 | return set_orig_class(obj, self); |
643 | 0 | } |
644 | | |
645 | | static PyObject * |
646 | | ga_vectorcall(PyObject *self, PyObject *const *args, |
647 | | size_t nargsf, PyObject *kwnames) |
648 | 0 | { |
649 | 0 | gaobject *alias = (gaobject *) self; |
650 | 0 | PyObject *obj = PyVectorcall_Function(alias->origin)(alias->origin, args, nargsf, kwnames); |
651 | 0 | return set_orig_class(obj, self); |
652 | 0 | } |
653 | | |
654 | | static const char* const attr_exceptions[] = { |
655 | | "__class__", |
656 | | "__origin__", |
657 | | "__args__", |
658 | | "__unpacked__", |
659 | | "__parameters__", |
660 | | "__typing_unpacked_tuple_args__", |
661 | | "__mro_entries__", |
662 | | "__reduce_ex__", // needed so we don't look up object.__reduce_ex__ |
663 | | "__reduce__", |
664 | | NULL, |
665 | | }; |
666 | | |
667 | | static const char* const attr_blocked[] = { |
668 | | "__bases__", |
669 | | "__copy__", |
670 | | "__deepcopy__", |
671 | | NULL, |
672 | | }; |
673 | | |
674 | | static PyObject * |
675 | | ga_getattro(PyObject *self, PyObject *name) |
676 | 620 | { |
677 | 620 | gaobject *alias = (gaobject *)self; |
678 | 620 | if (PyUnicode_Check(name)) { |
679 | | // When we check blocked attrs, we don't allow to proxy them to `__origin__`. |
680 | | // Otherwise, we can break existing code. |
681 | 2.48k | for (const char * const *p = attr_blocked; ; p++) { |
682 | 2.48k | if (*p == NULL) { |
683 | 620 | break; |
684 | 620 | } |
685 | 1.86k | if (_PyUnicode_EqualToASCIIString(name, *p)) { |
686 | 0 | goto generic_getattr; |
687 | 0 | } |
688 | 1.86k | } |
689 | | |
690 | | // When we see own attrs, it has a priority over `__origin__`'s attr. |
691 | 1.70k | for (const char * const *p = attr_exceptions; ; p++) { |
692 | 1.70k | if (*p == NULL) { |
693 | 90 | return PyObject_GetAttr(alias->origin, name); |
694 | 90 | } |
695 | 1.61k | if (_PyUnicode_EqualToASCIIString(name, *p)) { |
696 | 530 | goto generic_getattr; |
697 | 530 | } |
698 | 1.61k | } |
699 | 620 | } |
700 | | |
701 | 530 | generic_getattr: |
702 | 530 | return PyObject_GenericGetAttr(self, name); |
703 | 620 | } |
704 | | |
705 | | static PyObject * |
706 | | ga_richcompare(PyObject *a, PyObject *b, int op) |
707 | 76 | { |
708 | 76 | if (!_PyGenericAlias_Check(b) || |
709 | 12 | (op != Py_EQ && op != Py_NE)) |
710 | 64 | { |
711 | 64 | Py_RETURN_NOTIMPLEMENTED; |
712 | 64 | } |
713 | | |
714 | 12 | if (op == Py_NE) { |
715 | 0 | PyObject *eq = ga_richcompare(a, b, Py_EQ); |
716 | 0 | if (eq == NULL) |
717 | 0 | return NULL; |
718 | 0 | Py_DECREF(eq); |
719 | 0 | if (eq == Py_True) { |
720 | 0 | Py_RETURN_FALSE; |
721 | 0 | } |
722 | 0 | else { |
723 | 0 | Py_RETURN_TRUE; |
724 | 0 | } |
725 | 0 | } |
726 | | |
727 | 12 | gaobject *aa = (gaobject *)a; |
728 | 12 | gaobject *bb = (gaobject *)b; |
729 | 12 | if (aa->starred != bb->starred) { |
730 | 0 | Py_RETURN_FALSE; |
731 | 0 | } |
732 | 12 | int eq = PyObject_RichCompareBool(aa->origin, bb->origin, Py_EQ); |
733 | 12 | if (eq < 0) { |
734 | 0 | return NULL; |
735 | 0 | } |
736 | 12 | if (!eq) { |
737 | 0 | Py_RETURN_FALSE; |
738 | 0 | } |
739 | 12 | return PyObject_RichCompare(aa->args, bb->args, Py_EQ); |
740 | 12 | } |
741 | | |
742 | | static PyObject * |
743 | | ga_mro_entries(PyObject *self, PyObject *args) |
744 | 6 | { |
745 | 6 | gaobject *alias = (gaobject *)self; |
746 | 6 | return PyTuple_Pack(1, alias->origin); |
747 | 6 | } |
748 | | |
749 | | static PyObject * |
750 | | ga_instancecheck(PyObject *self, PyObject *Py_UNUSED(ignored)) |
751 | 0 | { |
752 | 0 | PyErr_SetString(PyExc_TypeError, |
753 | 0 | "isinstance() argument 2 cannot be a parameterized generic"); |
754 | 0 | return NULL; |
755 | 0 | } |
756 | | |
757 | | static PyObject * |
758 | | ga_subclasscheck(PyObject *self, PyObject *Py_UNUSED(ignored)) |
759 | 0 | { |
760 | 0 | PyErr_SetString(PyExc_TypeError, |
761 | 0 | "issubclass() argument 2 cannot be a parameterized generic"); |
762 | 0 | return NULL; |
763 | 0 | } |
764 | | |
765 | | static PyObject * |
766 | | ga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) |
767 | 0 | { |
768 | 0 | gaobject *alias = (gaobject *)self; |
769 | 0 | if (alias->starred) { |
770 | 0 | PyObject *tmp = Py_GenericAlias(alias->origin, alias->args); |
771 | 0 | if (tmp != NULL) { |
772 | 0 | Py_SETREF(tmp, PyObject_GetIter(tmp)); |
773 | 0 | } |
774 | 0 | if (tmp == NULL) { |
775 | 0 | return NULL; |
776 | 0 | } |
777 | 0 | return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(next)), tmp); |
778 | 0 | } |
779 | 0 | return Py_BuildValue("O(OO)", Py_TYPE(alias), |
780 | 0 | alias->origin, alias->args); |
781 | 0 | } |
782 | | |
783 | | static PyObject * |
784 | | ga_dir(PyObject *self, PyObject *Py_UNUSED(ignored)) |
785 | 0 | { |
786 | 0 | gaobject *alias = (gaobject *)self; |
787 | 0 | PyObject *dir = PyObject_Dir(alias->origin); |
788 | 0 | if (dir == NULL) { |
789 | 0 | return NULL; |
790 | 0 | } |
791 | | |
792 | 0 | PyObject *dir_entry = NULL; |
793 | 0 | for (const char * const *p = attr_exceptions; ; p++) { |
794 | 0 | if (*p == NULL) { |
795 | 0 | break; |
796 | 0 | } |
797 | 0 | else { |
798 | 0 | dir_entry = PyUnicode_FromString(*p); |
799 | 0 | if (dir_entry == NULL) { |
800 | 0 | goto error; |
801 | 0 | } |
802 | 0 | int contains = PySequence_Contains(dir, dir_entry); |
803 | 0 | if (contains < 0) { |
804 | 0 | goto error; |
805 | 0 | } |
806 | 0 | if (contains == 0 && PyList_Append(dir, dir_entry) < 0) { |
807 | 0 | goto error; |
808 | 0 | } |
809 | | |
810 | 0 | Py_CLEAR(dir_entry); |
811 | 0 | } |
812 | 0 | } |
813 | 0 | return dir; |
814 | | |
815 | 0 | error: |
816 | 0 | Py_DECREF(dir); |
817 | 0 | Py_XDECREF(dir_entry); |
818 | 0 | return NULL; |
819 | 0 | } |
820 | | |
821 | | static PyMethodDef ga_methods[] = { |
822 | | {"__mro_entries__", ga_mro_entries, METH_O}, |
823 | | {"__instancecheck__", ga_instancecheck, METH_O}, |
824 | | {"__subclasscheck__", ga_subclasscheck, METH_O}, |
825 | | {"__reduce__", ga_reduce, METH_NOARGS}, |
826 | | {"__dir__", ga_dir, METH_NOARGS}, |
827 | | {0} |
828 | | }; |
829 | | |
830 | | static PyMemberDef ga_members[] = { |
831 | | {"__origin__", _Py_T_OBJECT, offsetof(gaobject, origin), Py_READONLY}, |
832 | | {"__args__", _Py_T_OBJECT, offsetof(gaobject, args), Py_READONLY}, |
833 | | {"__unpacked__", Py_T_BOOL, offsetof(gaobject, starred), Py_READONLY}, |
834 | | {0} |
835 | | }; |
836 | | |
837 | | static PyObject * |
838 | | ga_parameters(PyObject *self, void *unused) |
839 | 42 | { |
840 | 42 | gaobject *alias = (gaobject *)self; |
841 | 42 | if (alias->parameters == NULL) { |
842 | 40 | alias->parameters = _Py_make_parameters(alias->args); |
843 | 40 | if (alias->parameters == NULL) { |
844 | 0 | return NULL; |
845 | 0 | } |
846 | 40 | } |
847 | 42 | return Py_NewRef(alias->parameters); |
848 | 42 | } |
849 | | |
850 | | static PyObject * |
851 | | ga_unpacked_tuple_args(PyObject *self, void *unused) |
852 | 0 | { |
853 | 0 | gaobject *alias = (gaobject *)self; |
854 | 0 | if (alias->starred && alias->origin == (PyObject *)&PyTuple_Type) { |
855 | 0 | return Py_NewRef(alias->args); |
856 | 0 | } |
857 | 0 | Py_RETURN_NONE; |
858 | 0 | } |
859 | | |
860 | | static PyGetSetDef ga_properties[] = { |
861 | | {"__parameters__", ga_parameters, NULL, PyDoc_STR("Type variables in the GenericAlias."), NULL}, |
862 | | {"__typing_unpacked_tuple_args__", ga_unpacked_tuple_args, NULL, NULL}, |
863 | | {0} |
864 | | }; |
865 | | |
866 | | /* A helper function to create GenericAlias' args tuple and set its attributes. |
867 | | * Returns 1 on success, 0 on failure. |
868 | | */ |
869 | | static inline int |
870 | 1.29k | setup_ga(gaobject *alias, PyObject *origin, PyObject *args) { |
871 | 1.29k | if (!PyTuple_Check(args)) { |
872 | 1.10k | args = PyTuple_Pack(1, args); |
873 | 1.10k | if (args == NULL) { |
874 | 0 | return 0; |
875 | 0 | } |
876 | 1.10k | } |
877 | 184 | else { |
878 | 184 | Py_INCREF(args); |
879 | 184 | } |
880 | | |
881 | 1.29k | alias->origin = Py_NewRef(origin); |
882 | 1.29k | alias->args = args; |
883 | 1.29k | alias->parameters = NULL; |
884 | 1.29k | alias->weakreflist = NULL; |
885 | | |
886 | 1.29k | if (PyVectorcall_Function(origin) != NULL) { |
887 | 1.15k | alias->vectorcall = ga_vectorcall; |
888 | 1.15k | } |
889 | 132 | else { |
890 | 132 | alias->vectorcall = NULL; |
891 | 132 | } |
892 | | |
893 | 1.29k | return 1; |
894 | 1.29k | } |
895 | | |
896 | | static PyObject * |
897 | | ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
898 | 126 | { |
899 | 126 | if (!_PyArg_NoKeywords("GenericAlias", kwds)) { |
900 | 0 | return NULL; |
901 | 0 | } |
902 | 126 | if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) { |
903 | 0 | return NULL; |
904 | 0 | } |
905 | 126 | PyObject *origin = PyTuple_GET_ITEM(args, 0); |
906 | 126 | PyObject *arguments = PyTuple_GET_ITEM(args, 1); |
907 | 126 | gaobject *self = (gaobject *)type->tp_alloc(type, 0); |
908 | 126 | if (self == NULL) { |
909 | 0 | return NULL; |
910 | 0 | } |
911 | 126 | if (!setup_ga(self, origin, arguments)) { |
912 | 0 | Py_DECREF(self); |
913 | 0 | return NULL; |
914 | 0 | } |
915 | 126 | return (PyObject *)self; |
916 | 126 | } |
917 | | |
918 | | static PyNumberMethods ga_as_number = { |
919 | | .nb_or = _Py_union_type_or, // Add __or__ function |
920 | | }; |
921 | | |
922 | | static PyObject * |
923 | | ga_iternext(PyObject *op) |
924 | 0 | { |
925 | 0 | gaiterobject *gi = (gaiterobject*)op; |
926 | 0 | if (gi->obj == NULL) { |
927 | 0 | PyErr_SetNone(PyExc_StopIteration); |
928 | 0 | return NULL; |
929 | 0 | } |
930 | 0 | gaobject *alias = (gaobject *)gi->obj; |
931 | 0 | PyObject *starred_alias = Py_GenericAlias(alias->origin, alias->args); |
932 | 0 | if (starred_alias == NULL) { |
933 | 0 | return NULL; |
934 | 0 | } |
935 | 0 | ((gaobject *)starred_alias)->starred = true; |
936 | 0 | Py_SETREF(gi->obj, NULL); |
937 | 0 | return starred_alias; |
938 | 0 | } |
939 | | |
940 | | static void |
941 | | ga_iter_dealloc(PyObject *op) |
942 | 0 | { |
943 | 0 | gaiterobject *gi = (gaiterobject*)op; |
944 | 0 | PyObject_GC_UnTrack(gi); |
945 | 0 | Py_XDECREF(gi->obj); |
946 | 0 | PyObject_GC_Del(gi); |
947 | 0 | } |
948 | | |
949 | | static int |
950 | | ga_iter_traverse(PyObject *op, visitproc visit, void *arg) |
951 | 0 | { |
952 | 0 | gaiterobject *gi = (gaiterobject*)op; |
953 | 0 | Py_VISIT(gi->obj); |
954 | 0 | return 0; |
955 | 0 | } |
956 | | |
957 | | static int |
958 | | ga_iter_clear(PyObject *self) |
959 | 0 | { |
960 | 0 | gaiterobject *gi = (gaiterobject *)self; |
961 | 0 | Py_CLEAR(gi->obj); |
962 | 0 | return 0; |
963 | 0 | } |
964 | | |
965 | | static PyObject * |
966 | | ga_iter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) |
967 | 0 | { |
968 | 0 | PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter)); |
969 | 0 | gaiterobject *gi = (gaiterobject *)self; |
970 | | |
971 | | /* _PyEval_GetBuiltin can invoke arbitrary code, |
972 | | * call must be before access of iterator pointers. |
973 | | * see issue #101765 */ |
974 | |
|
975 | 0 | if (gi->obj) |
976 | 0 | return Py_BuildValue("N(O)", iter, gi->obj); |
977 | 0 | else |
978 | 0 | return Py_BuildValue("N(())", iter); |
979 | 0 | } |
980 | | |
981 | | static PyMethodDef ga_iter_methods[] = { |
982 | | {"__reduce__", ga_iter_reduce, METH_NOARGS}, |
983 | | {0} |
984 | | }; |
985 | | |
986 | | // gh-91632: _Py_GenericAliasIterType is exported to be cleared |
987 | | // in _PyTypes_FiniTypes. |
988 | | PyTypeObject _Py_GenericAliasIterType = { |
989 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
990 | | .tp_name = "generic_alias_iterator", |
991 | | .tp_basicsize = sizeof(gaiterobject), |
992 | | .tp_iter = PyObject_SelfIter, |
993 | | .tp_iternext = ga_iternext, |
994 | | .tp_traverse = ga_iter_traverse, |
995 | | .tp_methods = ga_iter_methods, |
996 | | .tp_dealloc = ga_iter_dealloc, |
997 | | .tp_clear = ga_iter_clear, |
998 | | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
999 | | }; |
1000 | | |
1001 | | static PyObject * |
1002 | 0 | ga_iter(PyObject *self) { |
1003 | 0 | gaiterobject *gi = PyObject_GC_New(gaiterobject, &_Py_GenericAliasIterType); |
1004 | 0 | if (gi == NULL) { |
1005 | 0 | return NULL; |
1006 | 0 | } |
1007 | 0 | gi->obj = Py_NewRef(self); |
1008 | 0 | PyObject_GC_Track(gi); |
1009 | 0 | return (PyObject *)gi; |
1010 | 0 | } |
1011 | | |
1012 | | // TODO: |
1013 | | // - argument clinic? |
1014 | | // - cache? |
1015 | | PyTypeObject Py_GenericAliasType = { |
1016 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1017 | | .tp_name = "types.GenericAlias", |
1018 | | .tp_doc = genericalias__doc__, |
1019 | | .tp_basicsize = sizeof(gaobject), |
1020 | | .tp_dealloc = ga_dealloc, |
1021 | | .tp_repr = ga_repr, |
1022 | | .tp_as_number = &ga_as_number, // allow X | Y of GenericAlias objs |
1023 | | .tp_as_mapping = &ga_as_mapping, |
1024 | | .tp_hash = ga_hash, |
1025 | | .tp_call = ga_call, |
1026 | | .tp_getattro = ga_getattro, |
1027 | | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL, |
1028 | | .tp_traverse = ga_traverse, |
1029 | | .tp_richcompare = ga_richcompare, |
1030 | | .tp_weaklistoffset = offsetof(gaobject, weakreflist), |
1031 | | .tp_methods = ga_methods, |
1032 | | .tp_members = ga_members, |
1033 | | .tp_alloc = PyType_GenericAlloc, |
1034 | | .tp_new = ga_new, |
1035 | | .tp_free = PyObject_GC_Del, |
1036 | | .tp_getset = ga_properties, |
1037 | | .tp_iter = ga_iter, |
1038 | | .tp_vectorcall_offset = offsetof(gaobject, vectorcall), |
1039 | | }; |
1040 | | |
1041 | | PyObject * |
1042 | | Py_GenericAlias(PyObject *origin, PyObject *args) |
1043 | 1.16k | { |
1044 | 1.16k | gaobject *alias = (gaobject*) PyType_GenericAlloc( |
1045 | 1.16k | (PyTypeObject *)&Py_GenericAliasType, 0); |
1046 | 1.16k | if (alias == NULL) { |
1047 | 0 | return NULL; |
1048 | 0 | } |
1049 | 1.16k | if (!setup_ga(alias, origin, args)) { |
1050 | 0 | Py_DECREF(alias); |
1051 | 0 | return NULL; |
1052 | 0 | } |
1053 | 1.16k | return (PyObject *)alias; |
1054 | 1.16k | } |