Skip to content

Commit c83144a

Browse files
committed
[python] Ensure locals() is modified with numba wrapper
Python 3.13 changes the semantics of the builtin `locals()` function, see https://docs.python.org/3/library/functions.html#locals. For our case, it means that the call to `locals()` that happens at function-scope in the Numba decorator will not modify the `locals()` dictionary, thus the JITted pywrapper function will not appear in the dictionary. Ensure this happens by binding `locals()` to a local variable, which is actually modified by `exec()`.
1 parent a72f81a commit c83144a

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

bindings/pyroot/pythonizations/python/ROOT/_numbadeclare.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,22 @@ def pywrapper({SIGNATURE}):
265265

266266
# Execute the pywrapper code and generate the wrapper function
267267
# which calls the jitted C function
268-
exec(pywrappercode, glob, locals()) in {}
269-
270-
if not 'pywrapper' in locals():
268+
# Python 3.13 changes the semantics of the `locals()` builtin function
269+
# such that in optimized scopes (e.g. at function scope as it is
270+
# happening right now) the dictionary is not updated when changed. Bind
271+
# the `locals()` dictionary to a temporary object. This way, the call
272+
# to `exec()` will actually change the dictionary and the pywrapper
273+
# function will be found. Note that this change is backwards-compatible.
274+
local_objects = locals()
275+
exec(pywrappercode, glob, local_objects)
276+
277+
if not 'pywrapper' in local_objects:
271278
raise Exception('Failed to create Python wrapper function:\n{}'.format(pywrappercode))
272279

273280
# Jit the Python wrapper code
274281
c_return_type, c_input_types = get_c_signature(input_types, return_type)
275282
try:
276-
nbcfunc = nb.cfunc(c_return_type(*c_input_types), nopython=True)(locals()['pywrapper'])
283+
nbcfunc = nb.cfunc(c_return_type(*c_input_types), nopython=True)(local_objects['pywrapper'])
277284
except:
278285
raise Exception('Failed to jit Python wrapper with numba.cfunc')
279286
func.__py_wrapper__ = pywrappercode

0 commit comments

Comments
 (0)