MCPcopy Index your code
hub / github.com/python/mypy / generate_legacy_wrapper_function

Function generate_legacy_wrapper_function

mypyc/codegen/emitwrapper.py:227–284  ·  view source on GitHub ↗

Generates a CPython-compatible legacy wrapper for a native function. In particular, this handles unboxing the arguments, calling the native function, and then boxing the return value.

(
    fn: FuncIR, emitter: Emitter, source_path: str, module_name: str
)

Source from the content-addressed store, hash-verified

225
226
227def generate_legacy_wrapper_function(
228 fn: FuncIR, emitter: Emitter, source_path: str, module_name: str
229) -> None:
230 """Generates a CPython-compatible legacy wrapper for a native function.
231
232 In particular, this handles unboxing the arguments, calling the native function, and
233 then boxing the return value.
234 """
235 emitter.emit_line(f"{legacy_wrapper_function_header(fn, emitter.names)} {{")
236
237 # If fn is a method, then the first argument is a self param
238 real_args = list(fn.args)
239 if fn.sig.num_bitmap_args:
240 real_args = real_args[: -fn.sig.num_bitmap_args]
241 if fn.class_name and (fn.decl.name == "__new__" or fn.decl.kind != FUNC_STATICMETHOD):
242 arg = real_args.pop(0)
243 emitter.emit_line(f"PyObject *obj_{arg.name} = self;")
244
245 # Need to order args as: required, optional, kwonly optional, kwonly required
246 # This is because CPyArg_ParseTupleAndKeywords format string requires
247 # them grouped in that way.
248 groups = make_arg_groups(real_args)
249 reordered_args = reorder_arg_groups(groups)
250
251 emitter.emit_line(make_static_kwlist(reordered_args))
252 for arg in real_args:
253 emitter.emit_line(
254 "PyObject *obj_{}{};".format(arg.name, " = NULL" if arg.optional else "")
255 )
256
257 cleanups = [f"CPy_DECREF(obj_{arg.name});" for arg in groups[ARG_STAR] + groups[ARG_STAR2]]
258
259 arg_ptrs: list[str] = []
260 if groups[ARG_STAR] or groups[ARG_STAR2]:
261 arg_ptrs += [f"&obj_{groups[ARG_STAR][0].name}" if groups[ARG_STAR] else "NULL"]
262 arg_ptrs += [f"&obj_{groups[ARG_STAR2][0].name}" if groups[ARG_STAR2] else "NULL"]
263 arg_ptrs += [f"&obj_{arg.name}" for arg in reordered_args]
264
265 emitter.emit_lines(
266 'if (!CPyArg_ParseTupleAndKeywords(args, kw, "{}", "{}", kwlist{})) {{'.format(
267 make_format_string(None, groups), fn.name, "".join(", " + n for n in arg_ptrs)
268 ),
269 "return NULL;",
270 "}",
271 )
272 for i in range(fn.sig.num_bitmap_args):
273 name = bitmap_name(i)
274 emitter.emit_line(f"{BITMAP_TYPE} {name} = 0;")
275 traceback_code = generate_traceback_code(fn, emitter, source_path, module_name)
276 generate_wrapper_core(
277 fn,
278 emitter,
279 groups[ARG_OPT] + groups[ARG_NAMED_OPT],
280 cleanups=cleanups,
281 traceback_code=traceback_code,
282 )
283
284 emitter.emit_line("}")

Callers 1

Calls 15

bitmap_nameFunction · 0.90
listClass · 0.85
make_arg_groupsFunction · 0.85
reorder_arg_groupsFunction · 0.85
make_static_kwlistFunction · 0.85
make_format_stringFunction · 0.85
rangeClass · 0.85
generate_traceback_codeFunction · 0.85
generate_wrapper_coreFunction · 0.85
emit_lineMethod · 0.45
popMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…