@@ -1969,6 +1969,15 @@ static PyObject *
1969
1969
ga_getitem (PyObject * self , PyObject * item )
1970
1970
{
1971
1971
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
+ }
1972
1981
Py_ssize_t nparams = PyTuple_GET_SIZE (alias -> parameters );
1973
1982
if (nparams == 0 ) {
1974
1983
return PyErr_Format (PyExc_TypeError ,
@@ -2031,7 +2040,6 @@ static const char* const attr_exceptions[] = {
2031
2040
"__mro_entries__" ,
2032
2041
"__reduce_ex__" , // needed so we don't look up object.__reduce_ex__
2033
2042
"__reduce__" ,
2034
- "__setstate__" ,
2035
2043
NULL ,
2036
2044
};
2037
2045
@@ -2118,29 +2126,37 @@ ga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
2118
2126
alias -> origin , alias -> args );
2119
2127
}
2120
2128
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
-
2131
2129
static PyMethodDef ga_methods [] = {
2132
2130
{"__mro_entries__" , ga_mro_entries , METH_O },
2133
2131
{"__instancecheck__" , ga_instancecheck , METH_O },
2134
2132
{"__subclasscheck__" , ga_subclasscheck , METH_O },
2135
2133
{"__reduce__" , ga_reduce , METH_NOARGS },
2136
- {"__setstate__" , ga_setstate , METH_O },
2137
2134
{0 }
2138
2135
};
2139
2136
2140
2137
static PyMemberDef ga_members [] = {
2141
2138
{"__origin__" , T_OBJECT , offsetof(gaobject , origin ), READONLY },
2142
2139
{"__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 },
2144
2160
{0 }
2145
2161
};
2146
2162
@@ -2179,6 +2195,7 @@ PyTypeObject Py_GenericAliasType = {
2179
2195
.tp_alloc = PyType_GenericAlloc ,
2180
2196
.tp_new = ga_new ,
2181
2197
.tp_free = PyObject_GC_Del ,
2198
+ .tp_getset = ga_properties ,
2182
2199
};
2183
2200
2184
2201
PyObject *
@@ -2203,12 +2220,7 @@ Py_GenericAlias(PyObject *origin, PyObject *args)
2203
2220
Py_INCREF (origin );
2204
2221
alias -> origin = origin ;
2205
2222
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 ;
2212
2224
_PyObject_GC_TRACK (alias );
2213
2225
return (PyObject * )alias ;
2214
2226
}
0 commit comments