MCPcopy Create free account
hub / github.com/python/mypy / store_final_status

Method store_final_status

mypy/semanal.py:3829–3886  ·  view source on GitHub ↗

If this is a locally valid final declaration, set the corresponding flag on `Var`.

(self, s: AssignmentStmt)

Source from the content-addressed store, hash-verified

3827 return
3828
3829 def store_final_status(self, s: AssignmentStmt) -> None:
3830 """If this is a locally valid final declaration, set the corresponding flag on `Var`."""
3831 if s.is_final_def:
3832 if len(s.lvalues) == 1 and isinstance(s.lvalues[0], RefExpr):
3833 node = s.lvalues[0].node
3834 if isinstance(node, Var):
3835 node.is_final = True
3836 if s.type:
3837 node.final_value = constant_fold_expr(s.rvalue, self.cur_mod_id)
3838 if self.is_class_scope() and (
3839 isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs
3840 ):
3841 node.final_unset_in_class = True
3842 else:
3843 for lval in self.flatten_lvalues(s.lvalues):
3844 # Special case: we are working with an `Enum`:
3845 #
3846 # class MyEnum(Enum):
3847 # key = 'some value'
3848 #
3849 # Here `key` is implicitly final. In runtime, code like
3850 #
3851 # MyEnum.key = 'modified'
3852 #
3853 # will fail with `AttributeError: Cannot reassign members.`
3854 # That's why we need to replicate this.
3855 if (
3856 isinstance(lval, NameExpr)
3857 and isinstance(self.type, TypeInfo)
3858 and self.type.is_enum
3859 ):
3860 cur_node = self.type.names.get(lval.name, None)
3861 if (
3862 cur_node
3863 and isinstance(cur_node.node, Var)
3864 and not (isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs)
3865 ):
3866 # Double underscored members are writable on an `Enum`.
3867 # (Except read-only `__members__` but that is handled in type checker)
3868 cur_node.node.is_final = s.is_final_def = not is_dunder(cur_node.node.name)
3869
3870 # Special case: deferred initialization of a final attribute in __init__.
3871 # In this case we just pretend this is a valid final definition to suppress
3872 # errors about assigning to final attribute.
3873 if isinstance(lval, MemberExpr) and self.is_self_member_ref(lval):
3874 assert self.type, "Self member outside a class"
3875 cur_node = self.type.names.get(lval.name, None)
3876 if cur_node and isinstance(cur_node.node, Var) and cur_node.node.is_final:
3877 assert self.function_stack
3878 current_function = self.function_stack[-1]
3879 if (
3880 current_function.name == "__init__"
3881 and cur_node.node.final_unset_in_class
3882 and not cur_node.node.final_set_in_init
3883 and not (isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs)
3884 ):
3885 cur_node.node.final_set_in_init = True
3886 s.is_final_def = True

Callers 1

visit_assignment_stmtMethod · 0.95

Calls 8

is_class_scopeMethod · 0.95
flatten_lvaluesMethod · 0.95
is_self_member_refMethod · 0.95
constant_fold_exprFunction · 0.90
is_dunderFunction · 0.90
lenFunction · 0.85
isinstanceFunction · 0.85
getMethod · 0.45

Tested by

no test coverage detected