mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
gh-93649: Add Modules/_testcapi/type.c file (#129516)
Move PyType C API tests to a new file. Move following tests from test_capi.test_misc to test_capi.test_type: * BuiltinStaticTypesTests * test_get_type_name() * test_get_base_by_token()
This commit is contained in:
parent
881984b41a
commit
5424e3b034
8 changed files with 434 additions and 393 deletions
|
@ -63,5 +63,6 @@ int _PyTestCapi_Init_Object(PyObject *module);
|
|||
int _PyTestCapi_Init_Config(PyObject *mod);
|
||||
int _PyTestCapi_Init_Import(PyObject *mod);
|
||||
int _PyTestCapi_Init_Frame(PyObject *mod);
|
||||
int _PyTestCapi_Init_Type(PyObject *mod);
|
||||
|
||||
#endif // Py_TESTCAPI_PARTS_H
|
||||
|
|
251
Modules/_testcapi/type.c
Normal file
251
Modules/_testcapi/type.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
#include "parts.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
static PyType_Slot HeapTypeNameType_slots[] = {
|
||||
{0},
|
||||
};
|
||||
|
||||
static PyType_Spec HeapTypeNameType_Spec = {
|
||||
.name = "_testcapi.HeapTypeNameType",
|
||||
.basicsize = sizeof(PyObject),
|
||||
.flags = Py_TPFLAGS_DEFAULT,
|
||||
.slots = HeapTypeNameType_slots,
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
get_heaptype_for_name(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
return PyType_FromSpec(&HeapTypeNameType_Spec);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
get_type_name(PyObject *self, PyObject *type)
|
||||
{
|
||||
assert(PyType_Check(type));
|
||||
return PyType_GetName((PyTypeObject *)type);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
get_type_qualname(PyObject *self, PyObject *type)
|
||||
{
|
||||
assert(PyType_Check(type));
|
||||
return PyType_GetQualName((PyTypeObject *)type);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
get_type_fullyqualname(PyObject *self, PyObject *type)
|
||||
{
|
||||
assert(PyType_Check(type));
|
||||
return PyType_GetFullyQualifiedName((PyTypeObject *)type);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
get_type_module_name(PyObject *self, PyObject *type)
|
||||
{
|
||||
assert(PyType_Check(type));
|
||||
return PyType_GetModuleName((PyTypeObject *)type);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
test_get_type_dict(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
/* Test for PyType_GetDict */
|
||||
|
||||
// Assert ints have a `to_bytes` method
|
||||
PyObject *long_dict = PyType_GetDict(&PyLong_Type);
|
||||
assert(long_dict);
|
||||
assert(PyDict_GetItemString(long_dict, "to_bytes")); // borrowed ref
|
||||
Py_DECREF(long_dict);
|
||||
|
||||
// Make a new type, add an attribute to it and assert it's there
|
||||
PyObject *HeapTypeNameType = PyType_FromSpec(&HeapTypeNameType_Spec);
|
||||
assert(HeapTypeNameType);
|
||||
assert(PyObject_SetAttrString(
|
||||
HeapTypeNameType, "new_attr", Py_NewRef(Py_None)) >= 0);
|
||||
PyObject *type_dict = PyType_GetDict((PyTypeObject*)HeapTypeNameType);
|
||||
assert(type_dict);
|
||||
assert(PyDict_GetItemString(type_dict, "new_attr")); // borrowed ref
|
||||
Py_DECREF(HeapTypeNameType);
|
||||
Py_DECREF(type_dict);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new);
|
||||
if (PyLong_Type.tp_new != tp_new) {
|
||||
PyErr_SetString(PyExc_AssertionError, "mismatch: tp_new of long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr);
|
||||
if (PyLong_Type.tp_repr != tp_repr) {
|
||||
PyErr_SetString(PyExc_AssertionError, "mismatch: tp_repr of long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_tp_call);
|
||||
if (tp_call != NULL) {
|
||||
PyErr_SetString(PyExc_AssertionError, "mismatch: tp_call of long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_nb_add);
|
||||
if (PyLong_Type.tp_as_number->nb_add != nb_add) {
|
||||
PyErr_SetString(PyExc_AssertionError, "mismatch: nb_add of long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_mp_length);
|
||||
if (mp_length != NULL) {
|
||||
PyErr_SetString(PyExc_AssertionError, "mismatch: mp_length of long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1);
|
||||
if (over_value != NULL) {
|
||||
PyErr_SetString(PyExc_AssertionError, "mismatch: max+1 of long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tp_new = PyType_GetSlot(&PyLong_Type, 0);
|
||||
if (tp_new != NULL) {
|
||||
PyErr_SetString(PyExc_AssertionError, "mismatch: slot 0 of long");
|
||||
return NULL;
|
||||
}
|
||||
if (PyErr_ExceptionMatches(PyExc_SystemError)) {
|
||||
// This is the right exception
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// Get type->tp_version_tag
|
||||
static PyObject *
|
||||
type_get_version(PyObject *self, PyObject *type)
|
||||
{
|
||||
if (!PyType_Check(type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a type");
|
||||
return NULL;
|
||||
}
|
||||
PyObject *res = PyLong_FromUnsignedLong(
|
||||
((PyTypeObject *)type)->tp_version_tag);
|
||||
if (res == NULL) {
|
||||
assert(PyErr_Occurred());
|
||||
return NULL;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
type_modified(PyObject *self, PyObject *arg)
|
||||
{
|
||||
if (!PyType_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a type");
|
||||
return NULL;
|
||||
}
|
||||
PyTypeObject *type = (PyTypeObject*)arg;
|
||||
|
||||
PyType_Modified(type);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
type_assign_version(PyObject *self, PyObject *arg)
|
||||
{
|
||||
if (!PyType_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a type");
|
||||
return NULL;
|
||||
}
|
||||
PyTypeObject *type = (PyTypeObject*)arg;
|
||||
|
||||
int res = PyUnstable_Type_AssignVersionTag(type);
|
||||
return PyLong_FromLong(res);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
type_get_tp_bases(PyObject *self, PyObject *arg)
|
||||
{
|
||||
if (!PyType_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a type");
|
||||
return NULL;
|
||||
}
|
||||
PyTypeObject *type = (PyTypeObject*)arg;
|
||||
|
||||
PyObject *bases = type->tp_bases;
|
||||
if (bases == NULL) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return Py_NewRef(bases);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
type_get_tp_mro(PyObject *self, PyObject *arg)
|
||||
{
|
||||
if (!PyType_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a type");
|
||||
return NULL;
|
||||
}
|
||||
PyTypeObject *type = (PyTypeObject*)arg;
|
||||
|
||||
PyObject *mro = ((PyTypeObject *)type)->tp_mro;
|
||||
if (mro == NULL) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return Py_NewRef(mro);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
type_freeze(PyObject *module, PyObject *arg)
|
||||
{
|
||||
if (!PyType_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a type");
|
||||
return NULL;
|
||||
}
|
||||
PyTypeObject *type = (PyTypeObject*)arg;
|
||||
|
||||
if (PyType_Freeze(type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef test_methods[] = {
|
||||
{"get_heaptype_for_name", get_heaptype_for_name, METH_NOARGS},
|
||||
{"get_type_name", get_type_name, METH_O},
|
||||
{"get_type_qualname", get_type_qualname, METH_O},
|
||||
{"get_type_fullyqualname", get_type_fullyqualname, METH_O},
|
||||
{"get_type_module_name", get_type_module_name, METH_O},
|
||||
{"test_get_type_dict", test_get_type_dict, METH_NOARGS},
|
||||
{"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS},
|
||||
{"type_get_version", type_get_version, METH_O, PyDoc_STR("type->tp_version_tag")},
|
||||
{"type_modified", type_modified, METH_O, PyDoc_STR("PyType_Modified")},
|
||||
{"type_assign_version", type_assign_version, METH_O, PyDoc_STR("PyUnstable_Type_AssignVersionTag")},
|
||||
{"type_get_tp_bases", type_get_tp_bases, METH_O},
|
||||
{"type_get_tp_mro", type_get_tp_mro, METH_O},
|
||||
{"type_freeze", type_freeze, METH_O},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
int
|
||||
_PyTestCapi_Init_Type(PyObject *m)
|
||||
{
|
||||
return PyModule_AddFunctions(m, test_methods);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue