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

Function generate_set_del_item_wrapper

mypyc/codegen/emitwrapper.py:630–697  ·  view source on GitHub ↗

Generates a wrapper for native __setitem__ method (also works for __delitem__). This is used with the mapping protocol slot. Arguments are taken as *PyObjects and we return a negative C int on error. Create a separate wrapper function for __delitem__ as needed and have the __setite

(cl: ClassIR, fn: FuncIR, emitter: Emitter)

Source from the content-addressed store, hash-verified

628
629
630def generate_set_del_item_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:
631 """Generates a wrapper for native __setitem__ method (also works for __delitem__).
632
633 This is used with the mapping protocol slot. Arguments are taken as *PyObjects and we
634 return a negative C int on error.
635
636 Create a separate wrapper function for __delitem__ as needed and have the
637 __setitem__ wrapper call it if the value is NULL. Return the name
638 of the outer (__setitem__) wrapper.
639 """
640 method_cls = cl.get_method_and_class("__delitem__")
641 del_name = None
642 if method_cls and method_cls[1] == cl:
643 # Generate a separate wrapper for __delitem__
644 del_name = generate_del_item_wrapper(cl, method_cls[0], emitter)
645
646 args = fn.args
647 if fn.name == "__delitem__":
648 # Add an extra argument for value that we expect to be NULL.
649 args = list(args) + [RuntimeArg("___value", object_rprimitive, ARG_POS)]
650
651 name = "{}{}{}".format(DUNDER_PREFIX, "__setitem__", cl.name_prefix(emitter.names))
652 input_args = ", ".join(f"PyObject *obj_{arg.name}" for arg in args)
653 emitter.emit_line(f"static int {name}({input_args}) {{")
654
655 # First check if this is __delitem__
656 emitter.emit_line(f"if (obj_{args[2].name} == NULL) {{")
657 if del_name is not None:
658 # We have a native implementation, so call it
659 emitter.emit_line(f"return {del_name}(obj_{args[0].name}, obj_{args[1].name});")
660 else:
661 # Try to call superclass method instead
662 emitter.emit_line(f"PyObject *super = CPy_Super(CPyModule_builtins, obj_{args[0].name});")
663 emitter.emit_line("if (super == NULL) return -1;")
664 emitter.emit_line(
665 'PyObject *result = PyObject_CallMethod(super, "__delitem__", "O", obj_{});'.format(
666 args[1].name
667 )
668 )
669 emitter.emit_line("Py_DECREF(super);")
670 emitter.emit_line("Py_XDECREF(result);")
671 emitter.emit_line("return result == NULL ? -1 : 0;")
672 emitter.emit_line("}")
673
674 method_cls = cl.get_method_and_class("__setitem__")
675 if method_cls and method_cls[1] == cl:
676 generate_set_del_item_wrapper_inner(fn, emitter, args)
677 else:
678 emitter.emit_line(f"PyObject *super = CPy_Super(CPyModule_builtins, obj_{args[0].name});")
679 emitter.emit_line("if (super == NULL) return -1;")
680 emitter.emit_line("PyObject *result;")
681
682 if method_cls is None and cl.builtin_base is None:
683 msg = f"'{cl.name}' object does not support item assignment"
684 emitter.emit_line(f'PyErr_SetString(PyExc_TypeError, "{msg}");')
685 emitter.emit_line("result = NULL;")
686 else:
687 # A base class may have __setitem__

Callers

nothing calls this directly

Calls 9

RuntimeArgClass · 0.90
listClass · 0.85
get_method_and_classMethod · 0.80
name_prefixMethod · 0.80
formatMethod · 0.45
joinMethod · 0.45
emit_lineMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…