Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1c866bf

Browse files
authored
Fix whether MemberExpr.expr represent self/cls inside methods (#20480)
Fixes #20479.
1 parent 30b2a2d commit 1c866bf

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

mypy/semanal.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6091,10 +6091,14 @@ def visit_member_expr(self, expr: MemberExpr) -> None:
60916091
elif isinstance(base.node, Var) and self.type and self.function_stack:
60926092
# check for self.bar or cls.bar in method/classmethod
60936093
func_def = self.function_stack[-1]
6094-
if not func_def.is_static and isinstance(func_def.type, CallableType):
6095-
formal_arg = func_def.type.argument_by_name(base.node.name)
6096-
if formal_arg and formal_arg.pos == 0:
6097-
type_info = self.type
6094+
if (
6095+
func_def.has_self_or_cls_argument
6096+
and func_def.info is self.type
6097+
and isinstance(func_def.type, CallableType)
6098+
and func_def.arguments
6099+
and base.node is func_def.arguments[0].variable
6100+
):
6101+
type_info = self.type
60986102
elif isinstance(base.node, TypeAlias) and base.node.no_args:
60996103
assert isinstance(base.node.target, ProperType)
61006104
if isinstance(base.node.target, Instance):

test-data/unit/check-classes.test

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8328,6 +8328,37 @@ reveal_type(Foo.baz) # E: "type[Foo]" has no attribute "baz" \
83288328
foo: int
83298329
def bar(x: int) -> int: ...
83308330

8331+
[case testClassScopeImportAccessibleInMethods]
8332+
class A:
8333+
import mod
8334+
from mod import var
8335+
8336+
def __new__(cls) -> "A":
8337+
reveal_type(cls.mod) # N: Revealed type is "types.ModuleType"
8338+
reveal_type(cls.var) # N: Revealed type is "builtins.int"
8339+
reveal_type(cls.mod.var) # N: Revealed type is "builtins.int"
8340+
return cls()
8341+
8342+
def pos_or_named_self(self) -> None:
8343+
reveal_type(self.mod) # N: Revealed type is "types.ModuleType"
8344+
reveal_type(self.var) # N: Revealed type is "builtins.int"
8345+
reveal_type(self.mod.var) # N: Revealed type is "builtins.int"
8346+
8347+
def pos_only_self(self, /) -> None:
8348+
reveal_type(self.mod) # N: Revealed type is "types.ModuleType"
8349+
reveal_type(self.var) # N: Revealed type is "builtins.int"
8350+
reveal_type(self.mod.var) # N: Revealed type is "builtins.int"
8351+
8352+
@classmethod
8353+
def clsmethod(cls) -> None:
8354+
reveal_type(cls.mod) # N: Revealed type is "types.ModuleType"
8355+
reveal_type(cls.var) # N: Revealed type is "builtins.int"
8356+
reveal_type(cls.mod.var) # N: Revealed type is "builtins.int"
8357+
8358+
[file mod.py]
8359+
var = 1
8360+
[builtins fixtures/module.pyi]
8361+
83318362
[case testClassScopeImportFunctionNested]
83328363
class Foo:
83338364
class Bar:

test-data/unit/check-functions.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,19 @@ class A:
782782
# type: () -> None
783783
pass
784784

785+
[case testNestedFunctionInMethodCannotAccessEnclosingClassAttributes]
786+
class A:
787+
var: int
788+
import mod
789+
class B: ...
790+
791+
def method(self) -> None:
792+
def f1(arg: object) -> None:
793+
arg.var # E: "object" has no attribute "var"
794+
arg.mod # E: "object" has no attribute "mod"
795+
arg.B # E: "object" has no attribute "B"
796+
[file mod.py]
797+
785798
[case testDeepNestedFunctionWithTooFewArgumentsInTypeComment]
786799
class A:
787800
def f(self):

0 commit comments

Comments
 (0)