(
ctx: mypy.plugin.ClassDefContext, attrs: list[tuple[str, Type | None]]
)
| 908 | |
| 909 | |
| 910 | def _add_attrs_magic_attribute( |
| 911 | ctx: mypy.plugin.ClassDefContext, attrs: list[tuple[str, Type | None]] |
| 912 | ) -> None: |
| 913 | any_type = AnyType(TypeOfAny.explicit) |
| 914 | attributes_types: list[Type] = [ |
| 915 | ctx.api.named_type_or_none("attr.Attribute", [attr_type or any_type]) or any_type |
| 916 | for _, attr_type in attrs |
| 917 | ] |
| 918 | fallback_type = ctx.api.named_type( |
| 919 | "builtins.tuple", [ctx.api.named_type_or_none("attr.Attribute", [any_type]) or any_type] |
| 920 | ) |
| 921 | |
| 922 | attr_name = MAGIC_ATTR_CLS_NAME_TEMPLATE.format(ctx.cls.fullname.replace(".", "_")) |
| 923 | ti = ctx.api.basic_new_typeinfo(attr_name, fallback_type, 0) |
| 924 | for (name, _), attr_type in zip(attrs, attributes_types): |
| 925 | var = Var(name, attr_type) |
| 926 | var._fullname = name |
| 927 | var.is_property = True |
| 928 | proper_type = get_proper_type(attr_type) |
| 929 | if isinstance(proper_type, Instance): |
| 930 | var.info = proper_type.type |
| 931 | ti.names[name] = SymbolTableNode(MDEF, var, plugin_generated=True) |
| 932 | attributes_type = Instance(ti, []) |
| 933 | |
| 934 | # We need to stash the type of the magic attribute so it can be |
| 935 | # loaded on cached runs. |
| 936 | ctx.cls.info.names[attr_name] = SymbolTableNode(MDEF, ti, plugin_generated=True) |
| 937 | |
| 938 | add_attribute_to_class( |
| 939 | ctx.api, |
| 940 | ctx.cls, |
| 941 | MAGIC_ATTR_NAME, |
| 942 | TupleType(attributes_types, fallback=attributes_type), |
| 943 | fullname=f"{ctx.cls.fullname}.{MAGIC_ATTR_NAME}", |
| 944 | override_allow_incompatible=True, |
| 945 | is_classvar=True, |
| 946 | ) |
| 947 | |
| 948 | |
| 949 | def _add_slots(ctx: mypy.plugin.ClassDefContext, attributes: list[Attribute]) -> None: |
no test coverage detected
searching dependent graphs…