Skip to content

gh-155503: Add more PyType C API tests - #155505

Open
vstinner wants to merge 4 commits into
python:mainfrom
vstinner:limited_type
Open

gh-155503: Add more PyType C API tests#155505
vstinner wants to merge 4 commits into
python:mainfrom
vstinner:limited_type

Conversation

@vstinner

@vstinner vstinner commented Aug 10, 2026

Copy link
Copy Markdown
Member

Add tests on functions:

  • PyType_ClearCache()
  • PyType_GetFlags()
  • PyType_IsSubtype()
  • PyType_Ready()

Move PyType limited C API tests from _testcapi to _testlimitedcapi. Add a new Modules/_testlimitedcapi/type.c file.

Add tests on functions:

* PyType_ClearCache()
* PyType_GetFlags()
* PyType_IsSubtype()
* PyType_Ready()

Move PyType limited C API tests from _testcapi to _testlimitedcapi.
Add a new Modules/_testlimitedcapi/type.c file.
@vstinner

Copy link
Copy Markdown
Member Author

Keep PyType_GetSlot() test in _testcapi since it does access directly PyTypeObject members (excluded from the limited C API).

@vstinner

Copy link
Copy Markdown
Member Author

cc @serhiy-storchaka

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add tests for non-type arguments and NULL.

Comment thread Modules/_testlimitedcapi/type.c Outdated
Comment thread Modules/_testlimitedcapi/type.c Outdated


static int
check_type_arg(PyObject *arg)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely not. You should not check the type of the argument. Use NULLABLE() instead.

If the tested API accepts non-type or NULL -- fine, you will add a test. If it crashes -- just add the commented out call to denote that such corner case was considered, but cannot be tested.

{
PyTypeObject *type1, *type2;
if (!PyArg_ParseTuple(args, "O!O!",
&PyType_Type, &type1,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not enforce the type of arguments. Add tests for non-type arguments.

Comment thread Modules/_testlimitedcapi/type.c Outdated
* Accept None: treat None as NULL
* Fix typo in _PyTestLimitedCAPI_Init_Type(): return -1 on error.
* Add test_type_modified().
* Move PyType_IsSubtype() result check to Python.
@vstinner

Copy link
Copy Markdown
Member Author

@serhiy-storchaka: I addressed your review. Please review the updated PR.

If the tested API accepts non-type or NULL -- fine, you will add a test. If it crashes -- just add the commented out call to denote that such corner case was considered, but cannot be tested.

Ok, I modified the test wrappers to treat None as NULL. I added "CRASHES func(NULL)" comments: all tested PyType functions crash when NULL is passed.

Add tests for non-type arguments and NULL.

The PyType C API is special: the first argument type is PyTypeObject*, not PyObject*. If you pass a non-type, it will likely crash (or worse :-)), I don't see the purpose of testing that.

If you call a PyType C API with a PyObject*, the compiler fails with an error. Example with return PyType_GetName((PyObject*)type);:

./Modules/_testlimitedcapi/type.c: In function 'get_type_name':
./Modules/_testlimitedcapi/type.c:55:27: error: passing argument 1 of 'PyType_GetName' from incompatible pointer type [-Wincompatible-pointer-types]
   55 |     return PyType_GetName((PyObject*)type);

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove type checks. If non-types are not supported, just do not pass non-types in tests. If they are supported, they could be tested. We should not accidentally test a TypeError raised by the wrapper.

For example, it looks to me that PyType_IsSubtype(a, b) works if b is a non-type or even NULL (the code only compares pointers).

@vstinner

Copy link
Copy Markdown
Member Author

Remove type checks. If non-types are not supported, just do not pass non-types in tests. If they are supported, they could be tested. We should not accidentally test a TypeError raised by the wrapper.

I removed PyType_Check() checks.

For example, it looks to me that PyType_IsSubtype(a, b) works if b is a non-type or even NULL (the code only compares pointers).

I don't think that we should test this in test_capi. It looks like an implementation detail accident, not something that we want to test.

@serhiy-storchaka

Copy link
Copy Markdown
Member

We should test implementation detail accidents in test_capi, this is one of purposes of the tests. There is a large chance that there is a code that depends on this, even if by accident. If we change that detail in future, we should be aware what we do and properly document the change. You can gate it as CPython implementation detail.

@vstinner

Copy link
Copy Markdown
Member Author

We should test implementation detail accidents in test_capi, this is one of purposes of the tests. There is a large chance that there is a code that depends on this, even if by accident. If we change that detail in future, we should be aware what we do and properly document the change. You can gate it as CPython implementation detail.

I disagree. As I wrote previously, if you pass a PyObject* to PyType_Is_Subclass(), you get a compiler error. If a project pass (PyTypeObject*)b as the second argument of PyType_Is_Subclass() where b is a PyObject*, IMO it's a bug in the project, not something that we should support.

@vstinner

Copy link
Copy Markdown
Member Author

I added "CRASHES ...: argument must be a type" comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants