@@ -1969,6 +1969,15 @@ static PyObject *
19691969ga_getitem (PyObject * self , PyObject * item )
19701970{
19711971 gaobject * alias = (gaobject * )self ;
1972+ // do a lookup for __parameters__ so it gets populated (if not already)
1973+ if (alias -> parameters == NULL ) {
1974+ _Py_IDENTIFIER (__parameters__ );
1975+ PyObject * params = _PyObject_GetAttrId (self , & PyId___parameters__ );
1976+ if (params == NULL ) {
1977+ return NULL ;
1978+ }
1979+ Py_DECREF (params );
1980+ }
19721981 Py_ssize_t nparams = PyTuple_GET_SIZE (alias -> parameters );
19731982 if (nparams == 0 ) {
19741983 return PyErr_Format (PyExc_TypeError ,
@@ -2031,7 +2040,6 @@ static const char* const attr_exceptions[] = {
20312040 "__mro_entries__" ,
20322041 "__reduce_ex__" , // needed so we don't look up object.__reduce_ex__
20332042 "__reduce__" ,
2034- "__setstate__" ,
20352043 NULL ,
20362044};
20372045
@@ -2118,29 +2126,37 @@ ga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
21182126 alias -> origin , alias -> args );
21192127}
21202128
2121- static PyObject *
2122- ga_setstate (PyObject * self , PyObject * state )
2123- {
2124- gaobject * alias = (gaobject * )self ;
2125- PyObject * parameters = make_parameters (alias -> args );
2126- Py_INCREF (parameters );
2127- alias -> parameters = parameters ;
2128- Py_RETURN_NONE ;
2129- }
2130-
21312129static PyMethodDef ga_methods [] = {
21322130 {"__mro_entries__" , ga_mro_entries , METH_O },
21332131 {"__instancecheck__" , ga_instancecheck , METH_O },
21342132 {"__subclasscheck__" , ga_subclasscheck , METH_O },
21352133 {"__reduce__" , ga_reduce , METH_NOARGS },
2136- {"__setstate__" , ga_setstate , METH_O },
21372134 {0 }
21382135};
21392136
21402137static PyMemberDef ga_members [] = {
21412138 {"__origin__" , T_OBJECT , offsetof(gaobject , origin ), READONLY },
21422139 {"__args__" , T_OBJECT , offsetof(gaobject , args ), READONLY },
2143- {"__parameters__" , T_OBJECT , offsetof(gaobject , parameters ), READONLY },
2140+ {0 }
2141+ };
2142+
2143+ static PyObject *
2144+ ga_parameters (PyObject * self , void * unused )
2145+ {
2146+ gaobject * alias = (gaobject * )self ;
2147+ if (alias -> parameters == NULL ) {
2148+ alias -> parameters = make_parameters (alias -> args );
2149+ if (alias -> parameters == NULL ) {
2150+ Py_DECREF (alias -> parameters );
2151+ return NULL ;
2152+ }
2153+ }
2154+ Py_INCREF (alias -> parameters );
2155+ return alias -> parameters ;
2156+ }
2157+
2158+ static PyGetSetDef ga_properties [] = {
2159+ {"__parameters__" , ga_parameters , (setter )NULL , "Type variables in the GenericAlias." , NULL },
21442160 {0 }
21452161};
21462162
@@ -2179,6 +2195,7 @@ PyTypeObject Py_GenericAliasType = {
21792195 .tp_alloc = PyType_GenericAlloc ,
21802196 .tp_new = ga_new ,
21812197 .tp_free = PyObject_GC_Del ,
2198+ .tp_getset = ga_properties ,
21822199};
21832200
21842201PyObject *
@@ -2203,12 +2220,7 @@ Py_GenericAlias(PyObject *origin, PyObject *args)
22032220 Py_INCREF (origin );
22042221 alias -> origin = origin ;
22052222 alias -> args = args ;
2206- // TODO: Make __parameters__ a lazy attribute
2207- alias -> parameters = make_parameters (args );
2208- if (alias -> parameters == NULL ) {
2209- Py_DECREF (alias );
2210- return NULL ;
2211- }
2223+ alias -> parameters = NULL ;
22122224 _PyObject_GC_TRACK (alias );
22132225 return (PyObject * )alias ;
22142226}
0 commit comments