mirror of https://github.com/python/cpython
Add tests for using PEP560 with classes implemented in C. (#4883)
Based on tests from #4878
This commit is contained in:
parent
9c19b02024
commit
45700fb757
|
@ -1,4 +1,5 @@
|
||||||
import unittest
|
import unittest
|
||||||
|
from test import support
|
||||||
|
|
||||||
|
|
||||||
class TestMROEntry(unittest.TestCase):
|
class TestMROEntry(unittest.TestCase):
|
||||||
|
@ -248,5 +249,22 @@ class TestClassGetitem(unittest.TestCase):
|
||||||
self.assertEqual(C[int], 'from metaclass')
|
self.assertEqual(C[int], 'from metaclass')
|
||||||
|
|
||||||
|
|
||||||
|
@support.cpython_only
|
||||||
|
class CAPITest(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_c_class(self):
|
||||||
|
from _testcapi import Generic, GenericAlias
|
||||||
|
self.assertIsInstance(Generic.__class_getitem__(Generic, int), GenericAlias)
|
||||||
|
|
||||||
|
IntGeneric = Generic[int]
|
||||||
|
self.assertIs(type(IntGeneric), GenericAlias)
|
||||||
|
self.assertEqual(IntGeneric.__mro_entries__(()), (int,))
|
||||||
|
class C(IntGeneric):
|
||||||
|
pass
|
||||||
|
self.assertEqual(C.__bases__, (int,))
|
||||||
|
self.assertEqual(C.__orig_bases__, (IntGeneric,))
|
||||||
|
self.assertEqual(C.__mro__, (C, int, object))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -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 = {
|
static struct PyModuleDef _testcapimodule = {
|
||||||
PyModuleDef_HEAD_INIT,
|
PyModuleDef_HEAD_INIT,
|
||||||
"_testcapi",
|
"_testcapi",
|
||||||
|
@ -5094,6 +5169,16 @@ PyInit__testcapi(void)
|
||||||
Py_INCREF(&awaitType);
|
Py_INCREF(&awaitType);
|
||||||
PyModule_AddObject(m, "awaitType", (PyObject *)&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;
|
PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception;
|
||||||
if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) {
|
if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue