gh-92898: Enhance _testcppext test on cast to PyObject* (GH-93111)

* Add StrongRef class.
* Rename and reformat functions of the _Py_CAST() implementation.
(cherry picked from commit 20d30ba2cc)

Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Miss Islington (bot) 2022-05-26 16:39:28 -07:00 committed by GitHub
parent 33336e46da
commit 9303a5ac30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 33 deletions

View file

@ -23,6 +23,26 @@ _testcppext_add(PyObject *Py_UNUSED(module), PyObject *args)
}
// Class to test operator casting an object to PyObject*
class StrongRef
{
public:
StrongRef(PyObject *obj) : m_obj(obj) {
Py_INCREF(this->m_obj);
}
~StrongRef() {
Py_DECREF(this->m_obj);
}
// Cast to PyObject*: get a borrowed reference
inline operator PyObject*() const { return this->m_obj; }
private:
PyObject *m_obj; // Strong reference
};
static PyObject *
test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
@ -30,6 +50,8 @@ test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
if (obj == nullptr) {
return nullptr;
}
Py_ssize_t refcnt = Py_REFCNT(obj);
assert(refcnt >= 1);
// gh-92138: For backward compatibility, functions of Python C API accepts
// "const PyObject*". Check that using it does not emit C++ compiler
@ -38,22 +60,20 @@ test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
Py_INCREF(const_obj);
Py_DECREF(const_obj);
PyTypeObject *type = Py_TYPE(const_obj);
assert(Py_REFCNT(const_obj) >= 1);
struct PyObjectProxy {
PyObject* obj;
operator PyObject *() { return obj; }
} proxy_obj = { obj };
Py_INCREF(proxy_obj);
Py_DECREF(proxy_obj);
assert(Py_REFCNT(proxy_obj) >= 1);
assert(Py_REFCNT(const_obj) == refcnt);
assert(type == &PyTuple_Type);
assert(PyTuple_GET_SIZE(const_obj) == 2);
PyObject *one = PyTuple_GET_ITEM(const_obj, 0);
assert(PyLong_AsLong(one) == 1);
// gh-92898: StrongRef doesn't inherit from PyObject but has an operator to
// cast to PyObject*.
StrongRef strong_ref(obj);
assert(Py_TYPE(strong_ref) == &PyTuple_Type);
assert(Py_REFCNT(strong_ref) == (refcnt + 1));
Py_INCREF(strong_ref);
Py_DECREF(strong_ref);
Py_DECREF(obj);
Py_RETURN_NONE;
}