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

Function generate_setter

mypyc/codegen/emitclass.py:1176–1231  ·  view source on GitHub ↗
(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter)

Source from the content-addressed store, hash-verified

1174
1175
1176def generate_setter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> None:
1177 attr_field = emitter.attr(attr)
1178 emitter.emit_line("static int")
1179 emitter.emit_line(
1180 "{}({} *self, PyObject *value, void *closure)".format(
1181 setter_name(cl, attr, emitter.names), cl.struct_name(emitter.names)
1182 )
1183 )
1184 emitter.emit_line("{")
1185
1186 deletable = cl.is_deletable(attr)
1187 if not deletable:
1188 emitter.emit_line("if (value == NULL) {")
1189 emitter.emit_line("PyErr_SetString(PyExc_AttributeError,")
1190 emitter.emit_line(
1191 f' "{repr(cl.name)} object attribute {repr(attr)} cannot be deleted");'
1192 )
1193 emitter.emit_line("return -1;")
1194 emitter.emit_line("}")
1195
1196 # HACK: Don't consider refcounted values as always defined, since it's possible to
1197 # access uninitialized values via 'gc.get_objects()'. Accessing non-refcounted
1198 # values is benign.
1199 always_defined = cl.is_always_defined(attr) and not rtype.is_refcounted
1200
1201 if rtype.is_refcounted:
1202 attr_expr = f"self->{attr_field}"
1203 if not always_defined:
1204 emitter.emit_undefined_attr_check(rtype, attr_expr, "!=", "self", attr, cl)
1205 emitter.emit_dec_ref(f"self->{attr_field}", rtype)
1206 if not always_defined:
1207 emitter.emit_line("}")
1208
1209 if deletable:
1210 emitter.emit_line("if (value != NULL) {")
1211
1212 if rtype.is_unboxed:
1213 emitter.emit_unbox("value", "tmp", rtype, error=ReturnHandler("-1"), declare_dest=True)
1214 elif is_same_type(rtype, object_rprimitive):
1215 emitter.emit_line("PyObject *tmp = value;")
1216 else:
1217 emitter.emit_cast("value", "tmp", rtype, declare_dest=True)
1218 emitter.emit_lines("if (!tmp)", " return -1;")
1219 emitter.emit_inc_ref("tmp", rtype)
1220 emitter.emit_line(f"self->{attr_field} = tmp;")
1221 if rtype.error_overlap and not always_defined:
1222 emitter.emit_attr_bitmap_set("tmp", "self", rtype, cl, attr)
1223
1224 if deletable:
1225 emitter.emit_line("} else {")
1226 emitter.set_undefined_value(f"self->{attr_field}", rtype)
1227 if rtype.error_overlap:
1228 emitter.emit_attr_bitmap_clear("self", rtype, cl, attr)
1229 emitter.emit_line("}")
1230 emitter.emit_line("return 0;")
1231 emitter.emit_line("}")
1232
1233

Callers 1

generate_getsetersFunction · 0.85

Calls 15

ReturnHandlerClass · 0.90
is_same_typeFunction · 0.90
setter_nameFunction · 0.85
reprFunction · 0.85
attrMethod · 0.80
is_deletableMethod · 0.80
is_always_definedMethod · 0.80
emit_unboxMethod · 0.80
emit_castMethod · 0.80
emit_attr_bitmap_setMethod · 0.80
set_undefined_valueMethod · 0.80

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…