66
77
88FORCE_NEWREF = False
9+ FORCE_STEALREF = False
910
1011
1112PYTHONCAPI_COMPAT_URL = ('https://raw.githubusercontent.com/pythoncapi/'
@@ -265,7 +266,42 @@ class Py_INCREF_assign(Operation):
265266 NEED_PYTHONCAPI_COMPAT = True
266267
267268
268- OPERATIONS = (
269+ class Py_DECREF_return (Operation ):
270+ NAME = "Py_DECREF_return"
271+ DOC = ('replace "Py_DECREF(obj); return (obj);" '
272+ 'with "return Py_NewRef(obj);"' )
273+ REPLACE = (
274+ (re .compile (r'Py_DECREF\((%s)\);\s*return \1;' % ID_REGEX ),
275+ r'return _Py_StealRef(\1);' ),
276+ )
277+ # Need _Py_StealRef(): new in Python 3.10
278+ NEED_PYTHONCAPI_COMPAT = True
279+
280+
281+ class Py_DECREF_assign (Operation ):
282+ NAME = "Py_DECREF_assign"
283+ DOC = 'replace "Py_DECREF(obj); var = (obj);" with "var = Py_BorrowRed(obj);"'
284+
285+ def replace2 (regs ):
286+ x = regs .group (1 )
287+ y = regs .group (2 )
288+ if y == 'NULL' :
289+ return regs .group (0 )
290+ return f'{ x } = _Py_StealRef({ y } );'
291+
292+ REPLACE = (
293+ (re .compile (r'Py_DECREF\((%s)\);\s*' % ID_REGEX
294+ + assign_regex_str (r'(%s)' % EXPR_REGEX , r'\1' )),
295+ r'\2 = _Py_StealRef(\1);' ),
296+ (re .compile (assign_regex_str (r'(%s)' % EXPR_REGEX , r'(%s)' % ID_REGEX )
297+ + r"\s*Py_DECREF\((?:\1|\2)\);" ),
298+ replace2 ),
299+ )
300+ # Need Py_Borrowef(): new in Python 3.10
301+ NEED_PYTHONCAPI_COMPAT = True
302+
303+
304+ OPERATIONS = [
269305 Py_SET_TYPE ,
270306 Py_SET_SIZE ,
271307 Py_SET_REFCNT ,
@@ -283,12 +319,17 @@ class Py_INCREF_assign(Operation):
283319
284320 PyThreadState_GetInterpreter ,
285321 PyThreadState_GetFrame ,
286- )
322+ ]
287323if FORCE_NEWREF :
288324 OPERATIONS .extend ((
289325 Py_INCREF_return ,
290326 Py_INCREF_assign ,
291327 ))
328+ if FORCE_STEALREF :
329+ OPERATIONS .extend ((
330+ Py_DECREF_return ,
331+ Py_DECREF_assign ,
332+ ))
292333
293334
294335class Patcher :
0 commit comments