upgrade_pythoncapi.py script¶
upgrade_pythoncapi.py
requires Python 3.6 or newer.
Usage¶
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.
Select operations¶
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 Operations¶
upgrade_pythoncapi.py
implements the following operations:
Py_TYPE¶
Replace
op->ob_type
withPy_TYPE(op)
.
Py_SIZE¶
Replace
op->ob_size
withPy_SIZE(op)
.
Py_REFCNT¶
Replace
op->ob_refcnt
withPy_REFCNT(op)
.
Py_SET_TYPE¶
Replace
obj->ob_type = type;
withPy_SET_TYPE(obj, type);
.Replace
Py_TYPE(obj) = type;
withPy_SET_TYPE(obj, type);
.
Py_SET_SIZE¶
Replace
obj->ob_size = size;
withPy_SET_SIZE(obj, size);
.Replace
Py_SIZE(obj) = size;
withPy_SET_SIZE(obj, size);
.
Py_SET_REFCNT¶
Replace
obj->ob_refcnt = refcnt;
withPy_SET_REFCNT(obj, refcnt);
.Replace
Py_REFCNT(obj) = refcnt;
withPy_SET_REFCNT(obj, refcnt);
.
Py_Is¶
Replace
x == Py_None
withPy_IsNone(x)
.Replace
x == Py_True
withPy_IsTrue(x)
.Replace
x == Py_False
withPy_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)
.
PyObject_NEW¶
Replace
PyObject_NEW(...)
withPyObject_New(...)
.Replace
PyObject_NEW_VAR(...)
withPyObject_NewVar(...)
.
PyMem_MALLOC¶
Replace
PyMem_MALLOC(n)
withPyMem_Malloc(n)
.Replace
PyMem_REALLOC(ptr, n)
withPyMem_Realloc(ptr, n)
.Replace
PyMem_FREE(ptr)
,PyMem_DEL(ptr)
andPyMem_Del(ptr)
. withPyMem_Free(n)
.
PyObject_MALLOC¶
Replace
PyObject_MALLOC(n)
withPyObject_Malloc(n)
.Replace
PyObject_REALLOC(ptr, n)
withPyObject_Realloc(ptr, n)
.Replace
PyObject_FREE(ptr)
,PyObject_DEL(ptr)
andPyObject_Del(ptr)
. withPyObject_Free(n)
.
PyFrame_GetBack¶
Replace
frame->f_back
with_PyFrame_GetBackBorrow(frame)
.
PyFrame_GetCode¶
Replace
frame->f_code
with_PyFrame_GetCodeBorrow(frame)
.
PyThreadState_GetInterpreter¶
Replace
tstate->interp
withPyThreadState_GetInterpreter(tstate)
.
PyThreadState_GetFrame¶
Replace
tstate->frame
with_PyThreadState_GetFrameBorrow(tstate)
.
Experimental operations¶
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;
withreturn Py_NewRef(res);
Replace
x = y; Py_INCREF(x);
withx = Py_NewRef(y);
Replace
x = y; Py_INCREF(y);
withx = Py_NewRef(y);
Replace
Py_INCREF(y); x = y;
withx = Py_NewRef(y);
Py_CLEAR
:Replace
Py_XDECREF(var); var = NULL;
withPy_CLEAR(var);
Py_SETREF
:Replace
Py_DECREF(x); x = y;
withPy_SETREF(x, y);
Replace
Py_XDECREF(x); x = y;
withPy_XSETREF(x, y);