Analyze access to an attribute via a Var node. This is conceptually part of analyze_member_access and the arguments are similar. itype is the instance type in which attribute should be looked up original_type is the type of E in the expression E.var if implicit is True, the original
(
name: str,
var: Var,
itype: Instance,
mx: MemberContext,
*,
implicit: bool = False,
is_trivial_self: bool = False,
)
| 855 | |
| 856 | |
| 857 | def analyze_var( |
| 858 | name: str, |
| 859 | var: Var, |
| 860 | itype: Instance, |
| 861 | mx: MemberContext, |
| 862 | *, |
| 863 | implicit: bool = False, |
| 864 | is_trivial_self: bool = False, |
| 865 | ) -> Type: |
| 866 | """Analyze access to an attribute via a Var node. |
| 867 | |
| 868 | This is conceptually part of analyze_member_access and the arguments are similar. |
| 869 | itype is the instance type in which attribute should be looked up |
| 870 | original_type is the type of E in the expression E.var |
| 871 | if implicit is True, the original Var was created as an assignment to self |
| 872 | if is_trivial_self is True, we can use fast path for bind_self(). |
| 873 | """ |
| 874 | # Found a member variable. |
| 875 | original_itype = itype |
| 876 | itype = map_instance_to_supertype(itype, var.info) |
| 877 | if var.is_settable_property and mx.is_lvalue: |
| 878 | typ: Type | None = var.setter_type |
| 879 | if typ is None and var.is_ready: |
| 880 | # Existing synthetic properties may not set setter type. Fall back to getter. |
| 881 | typ = var.type |
| 882 | else: |
| 883 | typ = var.type |
| 884 | if typ: |
| 885 | if isinstance(typ, PartialType): |
| 886 | return mx.chk.handle_partial_var_type(typ, mx.is_lvalue, var, mx.context) |
| 887 | if mx.is_lvalue and not mx.suppress_errors: |
| 888 | if var.is_property and not var.is_settable_property: |
| 889 | mx.msg.read_only_property(name, itype.type, mx.context) |
| 890 | if var.is_classvar: |
| 891 | mx.msg.cant_assign_to_classvar(name, mx.context) |
| 892 | # This is the most common case for variables, so start with this. |
| 893 | result = expand_without_binding(typ, var, itype, original_itype, mx) |
| 894 | |
| 895 | # A non-None value indicates that we should actually bind self for this variable. |
| 896 | call_type: ProperType | None = None |
| 897 | if var.is_initialized_in_class and (not is_instance_var(var) or mx.is_operator): |
| 898 | typ = get_proper_type(typ) |
| 899 | if isinstance(typ, FunctionLike) and not typ.is_type_obj(): |
| 900 | call_type = typ |
| 901 | elif var.is_property: |
| 902 | deco_mx = mx.copy_modified(original_type=typ, self_type=typ, is_lvalue=False) |
| 903 | call_type = get_proper_type(_analyze_member_access("__call__", typ, deco_mx)) |
| 904 | else: |
| 905 | call_type = typ |
| 906 | |
| 907 | # Bound variables with callable types are treated like methods |
| 908 | # (these are usually method aliases like __rmul__ = __mul__). |
| 909 | if isinstance(call_type, FunctionLike) and not call_type.is_type_obj(): |
| 910 | if mx.is_lvalue and not var.is_property and not mx.suppress_errors: |
| 911 | mx.msg.cant_assign_to_method(mx.context) |
| 912 | |
| 913 | # Bind the self type for each callable component (when needed). |
| 914 | if call_type and not var.is_staticmethod: |
no test coverage detected
searching dependent graphs…