diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-12-16 09:25:56 (GMT) |
---|---|---|
committer | Ivan Levkivskyi <levkivskyi@gmail.com> | 2017-12-16 09:25:56 (GMT) |
commit | 45700fb757591a672e9d25b8252971c2a2caeaf2 (patch) | |
tree | 80af830fb9a999bca2665b53488e3ee00ad0f747 /Modules | |
parent | 9c19b020249c451891affd81751947321a1e6957 (diff) | |
download | cpython-45700fb757591a672e9d25b8252971c2a2caeaf2.zip cpython-45700fb757591a672e9d25b8252971c2a2caeaf2.tar.gz cpython-45700fb757591a672e9d25b8252971c2a2caeaf2.tar.bz2 |
Add tests for using PEP560 with classes implemented in C. (#4883)
Based on tests from #4878
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_testcapimodule.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 4bb3e82..47b5064 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5053,6 +5053,81 @@ recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds) } +/* Test PEP 560 */ + +typedef struct { + PyObject_HEAD + PyObject *item; +} PyGenericAliasObject; + +static void +generic_alias_dealloc(PyGenericAliasObject *self) +{ + Py_CLEAR(self->item); +} + +static PyObject * +generic_alias_mro_entries(PyGenericAliasObject *self, PyObject *bases) +{ + return PyTuple_Pack(1, self->item); +} + +static PyMethodDef generic_alias_methods[] = { + {"__mro_entries__", (PyCFunction) generic_alias_mro_entries, METH_O, NULL}, + {NULL} /* sentinel */ +}; + +PyTypeObject GenericAlias_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GenericAlias", + sizeof(PyGenericAliasObject), + 0, + .tp_dealloc = (destructor)generic_alias_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_methods = generic_alias_methods, +}; + +static PyObject * +generic_alias_new(PyObject *item) +{ + PyGenericAliasObject *o = PyObject_New(PyGenericAliasObject, &GenericAlias_Type); + if (o == NULL) { + return NULL; + } + Py_INCREF(item); + o->item = item; + return (PyObject*) o; +} + +typedef struct { + PyObject_HEAD +} PyGenericObject; + +static PyObject * +generic_class_getitem(PyObject *self, PyObject *args) +{ + PyObject *type, *item; + if (!PyArg_UnpackTuple(args, "__class_getitem__", 2, 2, &type, &item)) { + return NULL; + } + return generic_alias_new(item); +} + +static PyMethodDef generic_methods[] = { + {"__class_getitem__", generic_class_getitem, METH_VARARGS|METH_STATIC, NULL}, + {NULL} /* sentinel */ +}; + +PyTypeObject Generic_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Generic", + sizeof(PyGenericObject), + 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_methods = generic_methods, +}; + + static struct PyModuleDef _testcapimodule = { PyModuleDef_HEAD_INIT, "_testcapi", @@ -5094,6 +5169,16 @@ PyInit__testcapi(void) Py_INCREF(&awaitType); PyModule_AddObject(m, "awaitType", (PyObject *)&awaitType); + if (PyType_Ready(&GenericAlias_Type) < 0) + return NULL; + Py_INCREF(&GenericAlias_Type); + PyModule_AddObject(m, "GenericAlias", (PyObject *)&GenericAlias_Type); + + if (PyType_Ready(&Generic_Type) < 0) + return NULL; + Py_INCREF(&Generic_Type); + PyModule_AddObject(m, "Generic", (PyObject *)&Generic_Type); + PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception; if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) { return NULL; |