upgrade_pythoncapi.py script
upgrade_pythoncapi.py requires Python 3.6 or newer.
Run the with no arguments to display command line options and list available
operations:
python3 upgrade_pythoncapi.py
Select files and directories
To upgrade module.c file, type:
python3 upgrade_pythoncapi.py module.c
To upgrade all C and C++ files (.c, .h, .cc, .cpp, .cxx and
.hpp files) in the directory/ directory, type:
python3 upgrade_pythoncapi.py directory/
Multiple filenames an directories can be specified on the command line.
Files are modified in-place! If a file is modified, a copy of the original file
is created with the .old suffix.
To only replace op->ob_type with Py_TYPE(op), select the Py_TYPE
operation with:
python3 upgrade_pythoncapi.py -o Py_TYPE module.c
Or the opposite, to apply all operations but leave op->ob_type unchanged,
deselect the Py_TYPE operation with:
python3 upgrade_pythoncapi.py -o all,-Py_TYPE module.c
Download pythoncapi_compat.h
Most upgrade_pythoncapi.py operations add #include
"pythoncapi_compat.h". You may have to download the pythoncapi_compat.h
header file to your project. It can be downloaded with:
python3 upgrade_pythoncapi.py --download PATH
upgrade_pythoncapi.py implements the following operations:
- Replace op->ob_type with Py_TYPE(op).
- Replace op->ob_size with Py_SIZE(op).
- Replace op->ob_refcnt with Py_REFCNT(op).
- Replace obj->ob_type = type; with Py_SET_TYPE(obj, type);.
- Replace Py_TYPE(obj) = type; with Py_SET_TYPE(obj, type);.
- Replace obj->ob_size = size; with Py_SET_SIZE(obj, size);.
- Replace Py_SIZE(obj) = size; with Py_SET_SIZE(obj, size);.
- Replace obj->ob_refcnt = refcnt; with Py_SET_REFCNT(obj, refcnt);.
- Replace Py_REFCNT(obj) = refcnt; with Py_SET_REFCNT(obj, refcnt);.
- Replace x == Py_None with Py_IsNone(x).
- Replace x == Py_True with Py_IsTrue(x).
- Replace x == Py_False with Py_IsFalse(x).
- Replace x != Py_None with !Py_IsNone(x).
- Replace x != Py_True with !Py_IsTrue(x).
- Replace x != Py_False with !Py_IsFalse(x).
- Replace PyObject_NEW(...) with PyObject_New(...).
- Replace PyObject_NEW_VAR(...) with PyObject_NewVar(...).
- Replace PyMem_MALLOC(n) with PyMem_Malloc(n).
- Replace PyMem_REALLOC(ptr, n) with PyMem_Realloc(ptr, n).
- Replace PyMem_FREE(ptr), PyMem_DEL(ptr) and PyMem_Del(ptr) .
with PyMem_Free(n).
- Replace PyObject_MALLOC(n) with PyObject_Malloc(n).
- Replace PyObject_REALLOC(ptr, n) with PyObject_Realloc(ptr, n).
- Replace PyObject_FREE(ptr), PyObject_DEL(ptr)
and PyObject_Del(ptr) . with PyObject_Free(n).
- Replace frame->f_back with _PyFrame_GetBackBorrow(frame).
- Replace frame->f_code with _PyFrame_GetCodeBorrow(frame).
PyThreadState_GetInterpreter
- Replace tstate->interp with PyThreadState_GetInterpreter(tstate).
- Replace tstate->frame with _PyThreadState_GetFrameBorrow(tstate).
The following operations are experimental (ex: can introduce compiler warnings)
and so not included in the all group, they have to be selected explicitly.
Example: -o all,Py_SETREF.
Experimental operations:
- Py_NewRef:
- Replace Py_INCREF(res); return res; with return Py_NewRef(res);
- Replace x = y; Py_INCREF(x); with x = Py_NewRef(y);
- Replace x = y; Py_INCREF(y); with x = Py_NewRef(y);
- Replace Py_INCREF(y); x = y; with x = Py_NewRef(y);
- Py_CLEAR:
- Replace Py_XDECREF(var); var = NULL; with Py_CLEAR(var);
- Py_SETREF:
- Replace Py_DECREF(x); x = y; with Py_SETREF(x, y);
- Replace Py_XDECREF(x); x = y; with Py_XSETREF(x, y);