Skip to content

Commit

Permalink
[PyROOT] Use GetOptional family of C Python API where necessary
Browse files Browse the repository at this point in the history
With Python 3.13, some lookup methods like `PyMapping_GetItemString` and
`PyObject_GetAttrString` became more strict. They are now always
throwing an exception in case the attribute is not found.

To make these optional lookups work again, the `GetOptional` family of
functions needs to be used.

See:
  * https://docs.python.org/3/c-api/object.html#c.PyObject_GetOptionalAttrString
  * https://docs.python.org/3/c-api/mapping.html#c.PyMapping_GetOptionalItemString
  • Loading branch information
guitargeek committed Nov 7, 2024
1 parent 9b95c37 commit 0a823d9
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 0 deletions.
5 changes: 5 additions & 0 deletions bindings/pyroot/cppyy/CPyCppyy/src/Dispatcher.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,12 @@ bool CPyCppyy::InsertDispatcher(CPPScope* klass, PyObject* bases, PyObject* dct,
// Python class to keep the inheritance tree intact)
for (const auto& name : protected_names) {
PyObject* disp_dct = PyObject_GetAttr(disp_proxy, PyStrings::gDict);
#if PY_VERSION_HEX < 0x30d00f0
PyObject* pyf = PyMapping_GetItemString(disp_dct, (char*)name.c_str());
#else
PyObject* pyf = nullptr;
PyMapping_GetOptionalItemString(disp_dct, (char*)name.c_str(), &pyf);
#endif
if (pyf) {
PyObject_SetAttrString((PyObject*)klass, (char*)name.c_str(), pyf);
Py_DECREF(pyf);
Expand Down
5 changes: 5 additions & 0 deletions bindings/tpython/src/TPyClassGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ TClass *TPyClassGenerator::GetClass(const char *name, Bool_t load, Bool_t silent
std::string func_name = PyUnicode_AsUTF8(key);

// figure out number of variables required
#if PY_VERSION_HEX < 0x30d00f0
PyObject *func_code = PyObject_GetAttrString(attr, (char *)"func_code");
#else
PyObject *func_code = nullptr;
PyObject_GetOptionalAttrString(attr, (char *)"func_code", &func_code);
#endif
PyObject *var_names = func_code ? PyObject_GetAttrString(func_code, (char *)"co_varnames") : NULL;
int nVars = var_names ? PyTuple_GET_SIZE(var_names) : 0 /* TODO: probably large number, all default? */;
if (nVars < 0)
Expand Down

0 comments on commit 0a823d9

Please sign in to comment.