Analyze lvalue that is a member expression. Arguments: lval: The target lvalue explicit_type: Assignment has type annotation is_final: Is the target final
(
self, lval: MemberExpr, explicit_type: bool, is_final: bool, has_explicit_value: bool
)
| 4620 | ) |
| 4621 | |
| 4622 | def analyze_member_lvalue( |
| 4623 | self, lval: MemberExpr, explicit_type: bool, is_final: bool, has_explicit_value: bool |
| 4624 | ) -> None: |
| 4625 | """Analyze lvalue that is a member expression. |
| 4626 | |
| 4627 | Arguments: |
| 4628 | lval: The target lvalue |
| 4629 | explicit_type: Assignment has type annotation |
| 4630 | is_final: Is the target final |
| 4631 | """ |
| 4632 | if lval.node: |
| 4633 | # This has been bound already in a previous iteration. |
| 4634 | return |
| 4635 | lval.accept(self) |
| 4636 | if self.is_self_member_ref(lval): |
| 4637 | assert self.type, "Self member outside a class" |
| 4638 | cur_node = self.type.names.get(lval.name) |
| 4639 | node = self.type.get(lval.name) |
| 4640 | if cur_node and is_final: |
| 4641 | # Overrides will be checked in type checker. |
| 4642 | self.fail("Cannot redefine an existing name as final", lval) |
| 4643 | # On first encounter with this definition, if this attribute was defined before |
| 4644 | # with an inferred type and it's marked with an explicit type now, give an error. |
| 4645 | if ( |
| 4646 | not lval.node |
| 4647 | and cur_node |
| 4648 | and isinstance(cur_node.node, Var) |
| 4649 | and cur_node.node.is_inferred |
| 4650 | and explicit_type |
| 4651 | ): |
| 4652 | self.attribute_already_defined(lval.name, lval, cur_node) |
| 4653 | if self.type.is_protocol and has_explicit_value and cur_node is not None: |
| 4654 | # Make this variable non-abstract, it would be safer to do this only if we |
| 4655 | # are inside __init__, but we do this always to preserve historical behaviour. |
| 4656 | if isinstance(cur_node.node, Var): |
| 4657 | cur_node.node.is_abstract_var = False |
| 4658 | if ( |
| 4659 | # If the attribute of self is not defined, create a new Var, ... |
| 4660 | node is None |
| 4661 | # ... or if it is defined as abstract in a *superclass*. |
| 4662 | or (cur_node is None and isinstance(node.node, Var) and node.node.is_abstract_var) |
| 4663 | # ... also an explicit declaration on self also creates a new Var. |
| 4664 | # Note that `explicit_type` might have been erased for bare `Final`, |
| 4665 | # so we also check if `is_final` is passed. |
| 4666 | or (cur_node is None and (explicit_type or is_final)) |
| 4667 | ): |
| 4668 | if self.type.is_protocol and node is None: |
| 4669 | self.fail("Protocol members cannot be defined via assignment to self", lval) |
| 4670 | else: |
| 4671 | # Implicit attribute definition in __init__. |
| 4672 | lval.is_new_def = True |
| 4673 | lval.is_inferred_def = True |
| 4674 | v = Var(lval.name) |
| 4675 | v.set_line(lval) |
| 4676 | v._fullname = self.qualified_name(lval.name) |
| 4677 | v.info = self.type |
| 4678 | v.is_ready = False |
| 4679 | v.explicit_self_type = explicit_type or is_final |
no test coverage detected