blob: 28ea487a44f55f0f89f12146d1b84c4f0467becc [file] [log] [blame]
Guido van Rossum48b069a2020-04-07 09:50:06 -07001// types.GenericAlias -- used to represent e.g. list[int].
2
3#include "Python.h"
4#include "pycore_object.h"
kj4eb41d02020-11-09 12:00:13 +08005#include "pycore_unionobject.h" // _Py_union_as_number
Victor Stinner4a21e572020-04-15 02:35:41 +02006#include "structmember.h" // PyMemberDef
Guido van Rossum48b069a2020-04-07 09:50:06 -07007
8typedef struct {
9 PyObject_HEAD
10 PyObject *origin;
11 PyObject *args;
12 PyObject *parameters;
13} gaobject;
14
15static void
16ga_dealloc(PyObject *self)
17{
18 gaobject *alias = (gaobject *)self;
19
20 _PyObject_GC_UNTRACK(self);
21 Py_XDECREF(alias->origin);
22 Py_XDECREF(alias->args);
23 Py_XDECREF(alias->parameters);
Victor Stinner8182cc22020-07-10 12:40:38 +020024 Py_TYPE(self)->tp_free(self);
Guido van Rossum48b069a2020-04-07 09:50:06 -070025}
26
27static int
28ga_traverse(PyObject *self, visitproc visit, void *arg)
29{
30 gaobject *alias = (gaobject *)self;
31 Py_VISIT(alias->origin);
32 Py_VISIT(alias->args);
33 Py_VISIT(alias->parameters);
34 return 0;
35}
36
37static int
38ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
39{
40 _Py_IDENTIFIER(__module__);
41 _Py_IDENTIFIER(__qualname__);
42 _Py_IDENTIFIER(__origin__);
43 _Py_IDENTIFIER(__args__);
44 PyObject *qualname = NULL;
45 PyObject *module = NULL;
46 PyObject *r = NULL;
47 PyObject *tmp;
48 int err;
49
50 if (p == Py_Ellipsis) {
51 // The Ellipsis object
52 r = PyUnicode_FromString("...");
53 goto done;
54 }
55
56 if (_PyObject_LookupAttrId(p, &PyId___origin__, &tmp) < 0) {
57 goto done;
58 }
59 if (tmp != NULL) {
60 Py_DECREF(tmp);
61 if (_PyObject_LookupAttrId(p, &PyId___args__, &tmp) < 0) {
62 goto done;
63 }
64 if (tmp != NULL) {
65 Py_DECREF(tmp);
66 // It looks like a GenericAlias
67 goto use_repr;
68 }
69 }
70
71 if (_PyObject_LookupAttrId(p, &PyId___qualname__, &qualname) < 0) {
72 goto done;
73 }
74 if (qualname == NULL) {
75 goto use_repr;
76 }
77 if (_PyObject_LookupAttrId(p, &PyId___module__, &module) < 0) {
78 goto done;
79 }
80 if (module == NULL || module == Py_None) {
81 goto use_repr;
82 }
83
84 // Looks like a class
85 if (PyUnicode_Check(module) &&
86 _PyUnicode_EqualToASCIIString(module, "builtins"))
87 {
88 // builtins don't need a module name
89 r = PyObject_Str(qualname);
90 goto done;
91 }
92 else {
93 r = PyUnicode_FromFormat("%S.%S", module, qualname);
94 goto done;
95 }
96
97use_repr:
98 r = PyObject_Repr(p);
99
100done:
101 Py_XDECREF(qualname);
102 Py_XDECREF(module);
103 if (r == NULL) {
104 // error if any of the above PyObject_Repr/PyUnicode_From* fail
105 err = -1;
106 }
107 else {
108 err = _PyUnicodeWriter_WriteStr(writer, r);
109 Py_DECREF(r);
110 }
111 return err;
112}
113
114static PyObject *
115ga_repr(PyObject *self)
116{
117 gaobject *alias = (gaobject *)self;
118 Py_ssize_t len = PyTuple_GET_SIZE(alias->args);
119
120 _PyUnicodeWriter writer;
121 _PyUnicodeWriter_Init(&writer);
Victor Stinner4a21e572020-04-15 02:35:41 +0200122
Guido van Rossum48b069a2020-04-07 09:50:06 -0700123 if (ga_repr_item(&writer, alias->origin) < 0) {
124 goto error;
125 }
126 if (_PyUnicodeWriter_WriteASCIIString(&writer, "[", 1) < 0) {
127 goto error;
128 }
129 for (Py_ssize_t i = 0; i < len; i++) {
130 if (i > 0) {
131 if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
132 goto error;
133 }
134 }
135 PyObject *p = PyTuple_GET_ITEM(alias->args, i);
136 if (ga_repr_item(&writer, p) < 0) {
137 goto error;
138 }
139 }
140 if (len == 0) {
141 // for something like tuple[()] we should print a "()"
142 if (_PyUnicodeWriter_WriteASCIIString(&writer, "()", 2) < 0) {
143 goto error;
144 }
145 }
146 if (_PyUnicodeWriter_WriteASCIIString(&writer, "]", 1) < 0) {
147 goto error;
148 }
149 return _PyUnicodeWriter_Finish(&writer);
150error:
151 _PyUnicodeWriter_Dealloc(&writer);
152 return NULL;
153}
154
155// isinstance(obj, TypeVar) without importing typing.py.
156// Returns -1 for errors.
157static int
158is_typevar(PyObject *obj)
159{
160 PyTypeObject *type = Py_TYPE(obj);
161 if (strcmp(type->tp_name, "TypeVar") != 0) {
162 return 0;
163 }
164 PyObject *module = PyObject_GetAttrString((PyObject *)type, "__module__");
165 if (module == NULL) {
166 return -1;
167 }
168 int res = PyUnicode_Check(module)
169 && _PyUnicode_EqualToASCIIString(module, "typing");
170 Py_DECREF(module);
171 return res;
172}
173
174// Index of item in self[:len], or -1 if not found (self is a tuple)
175static Py_ssize_t
176tuple_index(PyObject *self, Py_ssize_t len, PyObject *item)
177{
178 for (Py_ssize_t i = 0; i < len; i++) {
179 if (PyTuple_GET_ITEM(self, i) == item) {
180 return i;
181 }
182 }
183 return -1;
184}
185
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300186static int
187tuple_add(PyObject *self, Py_ssize_t len, PyObject *item)
188{
189 if (tuple_index(self, len, item) < 0) {
190 Py_INCREF(item);
191 PyTuple_SET_ITEM(self, len, item);
192 return 1;
193 }
194 return 0;
195}
196
Guido van Rossum48b069a2020-04-07 09:50:06 -0700197static PyObject *
198make_parameters(PyObject *args)
199{
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300200 Py_ssize_t nargs = PyTuple_GET_SIZE(args);
201 Py_ssize_t len = nargs;
Guido van Rossum48b069a2020-04-07 09:50:06 -0700202 PyObject *parameters = PyTuple_New(len);
203 if (parameters == NULL)
204 return NULL;
205 Py_ssize_t iparam = 0;
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300206 for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
Guido van Rossum48b069a2020-04-07 09:50:06 -0700207 PyObject *t = PyTuple_GET_ITEM(args, iarg);
208 int typevar = is_typevar(t);
209 if (typevar < 0) {
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300210 Py_DECREF(parameters);
Guido van Rossum48b069a2020-04-07 09:50:06 -0700211 return NULL;
212 }
213 if (typevar) {
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300214 iparam += tuple_add(parameters, iparam, t);
215 }
216 else {
217 _Py_IDENTIFIER(__parameters__);
218 PyObject *subparams;
219 if (_PyObject_LookupAttrId(t, &PyId___parameters__, &subparams) < 0) {
220 Py_DECREF(parameters);
221 return NULL;
Guido van Rossum48b069a2020-04-07 09:50:06 -0700222 }
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300223 if (subparams && PyTuple_Check(subparams)) {
224 Py_ssize_t len2 = PyTuple_GET_SIZE(subparams);
225 Py_ssize_t needed = len2 - 1 - (iarg - iparam);
226 if (needed > 0) {
227 len += needed;
228 if (_PyTuple_Resize(&parameters, len) < 0) {
229 Py_DECREF(subparams);
230 Py_DECREF(parameters);
231 return NULL;
232 }
233 }
234 for (Py_ssize_t j = 0; j < len2; j++) {
235 PyObject *t2 = PyTuple_GET_ITEM(subparams, j);
236 iparam += tuple_add(parameters, iparam, t2);
237 }
238 }
239 Py_XDECREF(subparams);
Guido van Rossum48b069a2020-04-07 09:50:06 -0700240 }
241 }
242 if (iparam < len) {
243 if (_PyTuple_Resize(&parameters, iparam) < 0) {
244 Py_XDECREF(parameters);
245 return NULL;
246 }
247 }
248 return parameters;
249}
250
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300251/* If obj is a generic alias, substitute type variables params
252 with substitutions argitems. For example, if obj is list[T],
253 params is (T, S), and argitems is (str, int), return list[str].
254 If obj doesn't have a __parameters__ attribute or that's not
255 a non-empty tuple, return a new reference to obj. */
256static PyObject *
257subs_tvars(PyObject *obj, PyObject *params, PyObject **argitems)
258{
259 _Py_IDENTIFIER(__parameters__);
260 PyObject *subparams;
261 if (_PyObject_LookupAttrId(obj, &PyId___parameters__, &subparams) < 0) {
262 return NULL;
263 }
264 if (subparams && PyTuple_Check(subparams) && PyTuple_GET_SIZE(subparams)) {
265 Py_ssize_t nparams = PyTuple_GET_SIZE(params);
266 Py_ssize_t nsubargs = PyTuple_GET_SIZE(subparams);
267 PyObject *subargs = PyTuple_New(nsubargs);
268 if (subargs == NULL) {
269 Py_DECREF(subparams);
270 return NULL;
271 }
272 for (Py_ssize_t i = 0; i < nsubargs; ++i) {
273 PyObject *arg = PyTuple_GET_ITEM(subparams, i);
274 Py_ssize_t iparam = tuple_index(params, nparams, arg);
275 if (iparam >= 0) {
276 arg = argitems[iparam];
277 }
278 Py_INCREF(arg);
279 PyTuple_SET_ITEM(subargs, i, arg);
280 }
281
282 obj = PyObject_GetItem(obj, subargs);
283
284 Py_DECREF(subargs);
285 }
286 else {
287 Py_INCREF(obj);
288 }
289 Py_XDECREF(subparams);
290 return obj;
291}
292
Guido van Rossum48b069a2020-04-07 09:50:06 -0700293static PyObject *
294ga_getitem(PyObject *self, PyObject *item)
295{
296 gaobject *alias = (gaobject *)self;
297 // do a lookup for __parameters__ so it gets populated (if not already)
298 if (alias->parameters == NULL) {
299 alias->parameters = make_parameters(alias->args);
300 if (alias->parameters == NULL) {
301 return NULL;
302 }
303 }
304 Py_ssize_t nparams = PyTuple_GET_SIZE(alias->parameters);
305 if (nparams == 0) {
306 return PyErr_Format(PyExc_TypeError,
307 "There are no type variables left in %R",
308 self);
309 }
310 int is_tuple = PyTuple_Check(item);
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300311 Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
312 PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
313 if (nitems != nparams) {
Guido van Rossum48b069a2020-04-07 09:50:06 -0700314 return PyErr_Format(PyExc_TypeError,
315 "Too %s arguments for %R",
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300316 nitems > nparams ? "many" : "few",
Guido van Rossum48b069a2020-04-07 09:50:06 -0700317 self);
318 }
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300319 /* Replace all type variables (specified by alias->parameters)
320 with corresponding values specified by argitems.
321 t = list[T]; t[int] -> newargs = [int]
322 t = dict[str, T]; t[int] -> newargs = [str, int]
323 t = dict[T, list[S]]; t[str, int] -> newargs = [str, list[int]]
324 */
Guido van Rossum48b069a2020-04-07 09:50:06 -0700325 Py_ssize_t nargs = PyTuple_GET_SIZE(alias->args);
326 PyObject *newargs = PyTuple_New(nargs);
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300327 if (newargs == NULL) {
Guido van Rossum48b069a2020-04-07 09:50:06 -0700328 return NULL;
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300329 }
Guido van Rossum48b069a2020-04-07 09:50:06 -0700330 for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
331 PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg);
332 int typevar = is_typevar(arg);
333 if (typevar < 0) {
334 Py_DECREF(newargs);
335 return NULL;
336 }
337 if (typevar) {
338 Py_ssize_t iparam = tuple_index(alias->parameters, nparams, arg);
339 assert(iparam >= 0);
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300340 arg = argitems[iparam];
341 Py_INCREF(arg);
342 }
343 else {
344 arg = subs_tvars(arg, alias->parameters, argitems);
345 if (arg == NULL) {
346 Py_DECREF(newargs);
347 return NULL;
Guido van Rossum48b069a2020-04-07 09:50:06 -0700348 }
349 }
Guido van Rossum48b069a2020-04-07 09:50:06 -0700350 PyTuple_SET_ITEM(newargs, iarg, arg);
351 }
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300352
Guido van Rossum48b069a2020-04-07 09:50:06 -0700353 PyObject *res = Py_GenericAlias(alias->origin, newargs);
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300354
Guido van Rossum48b069a2020-04-07 09:50:06 -0700355 Py_DECREF(newargs);
356 return res;
357}
358
359static PyMappingMethods ga_as_mapping = {
360 .mp_subscript = ga_getitem,
361};
362
363static Py_hash_t
364ga_hash(PyObject *self)
365{
366 gaobject *alias = (gaobject *)self;
367 // TODO: Hash in the hash for the origin
368 Py_hash_t h0 = PyObject_Hash(alias->origin);
369 if (h0 == -1) {
370 return -1;
371 }
372 Py_hash_t h1 = PyObject_Hash(alias->args);
373 if (h1 == -1) {
374 return -1;
375 }
376 return h0 ^ h1;
377}
378
379static PyObject *
380ga_call(PyObject *self, PyObject *args, PyObject *kwds)
381{
382 gaobject *alias = (gaobject *)self;
383 PyObject *obj = PyObject_Call(alias->origin, args, kwds);
384 if (obj != NULL) {
385 if (PyObject_SetAttrString(obj, "__orig_class__", self) < 0) {
386 if (!PyErr_ExceptionMatches(PyExc_AttributeError) &&
387 !PyErr_ExceptionMatches(PyExc_TypeError))
388 {
389 Py_DECREF(obj);
390 return NULL;
391 }
392 PyErr_Clear();
393 }
394 }
395 return obj;
396}
397
398static const char* const attr_exceptions[] = {
399 "__origin__",
400 "__args__",
401 "__parameters__",
402 "__mro_entries__",
403 "__reduce_ex__", // needed so we don't look up object.__reduce_ex__
404 "__reduce__",
405 NULL,
406};
407
408static PyObject *
409ga_getattro(PyObject *self, PyObject *name)
410{
411 gaobject *alias = (gaobject *)self;
412 if (PyUnicode_Check(name)) {
413 for (const char * const *p = attr_exceptions; ; p++) {
414 if (*p == NULL) {
415 return PyObject_GetAttr(alias->origin, name);
416 }
417 if (_PyUnicode_EqualToASCIIString(name, *p)) {
418 break;
419 }
420 }
421 }
422 return PyObject_GenericGetAttr(self, name);
423}
424
425static PyObject *
426ga_richcompare(PyObject *a, PyObject *b, int op)
427{
Hai Shi5e8ffe12020-05-04 21:31:38 +0800428 if (!Py_IS_TYPE(a, &Py_GenericAliasType) ||
429 !Py_IS_TYPE(b, &Py_GenericAliasType) ||
Guido van Rossum48b069a2020-04-07 09:50:06 -0700430 (op != Py_EQ && op != Py_NE))
431 {
432 Py_RETURN_NOTIMPLEMENTED;
433 }
434
435 if (op == Py_NE) {
436 PyObject *eq = ga_richcompare(a, b, Py_EQ);
437 if (eq == NULL)
438 return NULL;
439 Py_DECREF(eq);
440 if (eq == Py_True) {
441 Py_RETURN_FALSE;
442 }
443 else {
444 Py_RETURN_TRUE;
445 }
446 }
447
448 gaobject *aa = (gaobject *)a;
449 gaobject *bb = (gaobject *)b;
450 int eq = PyObject_RichCompareBool(aa->origin, bb->origin, Py_EQ);
451 if (eq < 0) {
452 return NULL;
453 }
454 if (!eq) {
455 Py_RETURN_FALSE;
456 }
457 return PyObject_RichCompare(aa->args, bb->args, Py_EQ);
458}
459
460static PyObject *
461ga_mro_entries(PyObject *self, PyObject *args)
462{
463 gaobject *alias = (gaobject *)self;
464 return PyTuple_Pack(1, alias->origin);
465}
466
467static PyObject *
468ga_instancecheck(PyObject *self, PyObject *Py_UNUSED(ignored))
469{
470 PyErr_SetString(PyExc_TypeError,
471 "isinstance() argument 2 cannot be a parameterized generic");
472 return NULL;
473}
474
475static PyObject *
476ga_subclasscheck(PyObject *self, PyObject *Py_UNUSED(ignored))
477{
478 PyErr_SetString(PyExc_TypeError,
479 "issubclass() argument 2 cannot be a parameterized generic");
480 return NULL;
481}
482
483static PyObject *
484ga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
485{
486 gaobject *alias = (gaobject *)self;
487 return Py_BuildValue("O(OO)", Py_TYPE(alias),
488 alias->origin, alias->args);
489}
490
Batuhan Taskaya2e877742020-09-16 00:58:32 +0300491static PyObject *
492ga_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
493{
494 gaobject *alias = (gaobject *)self;
495 PyObject *dir = PyObject_Dir(alias->origin);
496 if (dir == NULL) {
497 return NULL;
498 }
499
500 PyObject *dir_entry = NULL;
501 for (const char * const *p = attr_exceptions; ; p++) {
502 if (*p == NULL) {
503 break;
504 }
505 else {
506 dir_entry = PyUnicode_FromString(*p);
507 if (dir_entry == NULL) {
508 goto error;
509 }
510 int contains = PySequence_Contains(dir, dir_entry);
511 if (contains < 0) {
512 goto error;
513 }
514 if (contains == 0 && PyList_Append(dir, dir_entry) < 0) {
515 goto error;
516 }
517
518 Py_CLEAR(dir_entry);
519 }
520 }
521 return dir;
522
523error:
524 Py_DECREF(dir);
525 Py_XDECREF(dir_entry);
526 return NULL;
527}
528
Guido van Rossum48b069a2020-04-07 09:50:06 -0700529static PyMethodDef ga_methods[] = {
530 {"__mro_entries__", ga_mro_entries, METH_O},
531 {"__instancecheck__", ga_instancecheck, METH_O},
532 {"__subclasscheck__", ga_subclasscheck, METH_O},
533 {"__reduce__", ga_reduce, METH_NOARGS},
Batuhan Taskaya2e877742020-09-16 00:58:32 +0300534 {"__dir__", ga_dir, METH_NOARGS},
Guido van Rossum48b069a2020-04-07 09:50:06 -0700535 {0}
536};
537
538static PyMemberDef ga_members[] = {
539 {"__origin__", T_OBJECT, offsetof(gaobject, origin), READONLY},
540 {"__args__", T_OBJECT, offsetof(gaobject, args), READONLY},
541 {0}
542};
543
544static PyObject *
545ga_parameters(PyObject *self, void *unused)
546{
547 gaobject *alias = (gaobject *)self;
548 if (alias->parameters == NULL) {
549 alias->parameters = make_parameters(alias->args);
550 if (alias->parameters == NULL) {
551 return NULL;
552 }
553 }
554 Py_INCREF(alias->parameters);
555 return alias->parameters;
556}
557
558static PyGetSetDef ga_properties[] = {
559 {"__parameters__", ga_parameters, (setter)NULL, "Type variables in the GenericAlias.", NULL},
560 {0}
561};
562
563static PyObject *
564ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
565{
Dong-hee Na02e44842020-04-24 01:25:53 +0900566 if (!_PyArg_NoKwnames("GenericAlias", kwds)) {
Guido van Rossum48b069a2020-04-07 09:50:06 -0700567 return NULL;
568 }
Dong-hee Na02e44842020-04-24 01:25:53 +0900569 if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) {
Guido van Rossum48b069a2020-04-07 09:50:06 -0700570 return NULL;
571 }
572 PyObject *origin = PyTuple_GET_ITEM(args, 0);
573 PyObject *arguments = PyTuple_GET_ITEM(args, 1);
574 return Py_GenericAlias(origin, arguments);
575}
576
kj4eb41d02020-11-09 12:00:13 +0800577static PyNumberMethods ga_as_number = {
578 .nb_or = (binaryfunc)_Py_union_type_or, // Add __or__ function
579};
580
Guido van Rossum48b069a2020-04-07 09:50:06 -0700581// TODO:
582// - argument clinic?
583// - __doc__?
584// - cache?
585PyTypeObject Py_GenericAliasType = {
586 PyVarObject_HEAD_INIT(&PyType_Type, 0)
587 .tp_name = "types.GenericAlias",
588 .tp_doc = "Represent a PEP 585 generic type\n"
589 "\n"
Mikhail Golubev77f0a232020-10-09 00:38:36 +0300590 "E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).",
Guido van Rossum48b069a2020-04-07 09:50:06 -0700591 .tp_basicsize = sizeof(gaobject),
592 .tp_dealloc = ga_dealloc,
593 .tp_repr = ga_repr,
kj4eb41d02020-11-09 12:00:13 +0800594 .tp_as_number = &ga_as_number, // allow X | Y of GenericAlias objs
Guido van Rossum48b069a2020-04-07 09:50:06 -0700595 .tp_as_mapping = &ga_as_mapping,
596 .tp_hash = ga_hash,
597 .tp_call = ga_call,
598 .tp_getattro = ga_getattro,
599 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
600 .tp_traverse = ga_traverse,
601 .tp_richcompare = ga_richcompare,
602 .tp_methods = ga_methods,
603 .tp_members = ga_members,
604 .tp_alloc = PyType_GenericAlloc,
605 .tp_new = ga_new,
606 .tp_free = PyObject_GC_Del,
607 .tp_getset = ga_properties,
608};
609
610PyObject *
611Py_GenericAlias(PyObject *origin, PyObject *args)
612{
613 if (!PyTuple_Check(args)) {
614 args = PyTuple_Pack(1, args);
615 if (args == NULL) {
616 return NULL;
617 }
618 }
619 else {
620 Py_INCREF(args);
621 }
622
623 gaobject *alias = PyObject_GC_New(gaobject, &Py_GenericAliasType);
624 if (alias == NULL) {
625 Py_DECREF(args);
626 return NULL;
627 }
628
629 Py_INCREF(origin);
630 alias->origin = origin;
631 alias->args = args;
632 alias->parameters = NULL;
633 _PyObject_GC_TRACK(alias);
634 return (PyObject *)alias;
635}