(builder: IRBuilder, cdef: ClassDef, fdef: FuncDef)
| 476 | |
| 477 | |
| 478 | def handle_ext_method(builder: IRBuilder, cdef: ClassDef, fdef: FuncDef) -> None: |
| 479 | # Perform the function of visit_method for methods inside extension classes. |
| 480 | name = fdef.name |
| 481 | class_ir = builder.mapper.type_to_ir[cdef.info] |
| 482 | sig = builder.mapper.fdef_to_sig(fdef, builder.options.strict_dunders_typing) |
| 483 | func_ir, func_reg = gen_func_item(builder, fdef, name, sig, cdef) |
| 484 | builder.functions.append(func_ir) |
| 485 | |
| 486 | if is_decorated(builder, fdef): |
| 487 | # Obtain the function name in order to construct the name of the helper function. |
| 488 | _, _, name = fdef.fullname.rpartition(".") |
| 489 | # Read the PyTypeObject representing the class, get the callable object |
| 490 | # representing the non-decorated method |
| 491 | typ = builder.load_native_type_object(cdef.fullname) |
| 492 | orig_func = builder.py_get_attr(typ, name, fdef.line) |
| 493 | |
| 494 | # Decorate the non-decorated method |
| 495 | decorated_func = load_decorated_func(builder, fdef, orig_func) |
| 496 | |
| 497 | # Set the callable object representing the decorated method as an attribute of the |
| 498 | # extension class. |
| 499 | builder.primitive_op( |
| 500 | py_setattr_op, [typ, builder.load_str(name), decorated_func], fdef.line |
| 501 | ) |
| 502 | |
| 503 | if fdef.is_property: |
| 504 | # If there is a property setter, it will be processed after the getter, |
| 505 | # We populate the optional setter field with none for now. |
| 506 | assert name not in class_ir.properties |
| 507 | class_ir.properties[name] = (func_ir, None) |
| 508 | |
| 509 | elif fdef in builder.prop_setters: |
| 510 | # The respective property getter must have been processed already |
| 511 | assert name in class_ir.properties |
| 512 | getter_ir, _ = class_ir.properties[name] |
| 513 | class_ir.properties[name] = (getter_ir, func_ir) |
| 514 | |
| 515 | class_ir.methods[func_ir.decl.name] = func_ir |
| 516 | |
| 517 | # If this overrides a parent class method with a different type, we need |
| 518 | # to generate a glue method to mediate between them. |
| 519 | for base in class_ir.mro[1:]: |
| 520 | if ( |
| 521 | name in base.method_decls |
| 522 | and name != "__init__" |
| 523 | and not is_same_method_signature( |
| 524 | class_ir.method_decls[name].sig, base.method_decls[name].sig |
| 525 | ) |
| 526 | ): |
| 527 | # TODO: Support contravariant subtyping in the input argument for |
| 528 | # property setters. Need to make a special glue method for handling this, |
| 529 | # similar to gen_glue_property. |
| 530 | |
| 531 | f = gen_glue(builder, base.method_decls[name].sig, func_ir, class_ir, base, fdef) |
| 532 | class_ir.glue_methods[(base, name)] = f |
| 533 | builder.functions.append(f) |
| 534 | |
| 535 | # If the class allows interpreted children, create glue |
no test coverage detected
searching dependent graphs…