From aa841ac9f1344f3cdf08d97361fb2ff1069cfbcf Mon Sep 17 00:00:00 2001 From: Roy Williams Date: Thu, 29 Jun 2017 14:29:31 -0700 Subject: [PATCH 1/2] Allow instances of a class to access inner class definitions on that class. This fixes https://github.com/python/mypy/issues/3635 --- mypy/checkmember.py | 7 +++++++ test-data/unit/check-classes.test | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index c8dc69bdfbe4..4057314c606b 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -227,6 +227,13 @@ def analyze_member_var_access(name: str, itype: Instance, info: TypeInfo, # The associated Var node of a decorator contains the type. v = vv.var + if isinstance(vv, TypeInfo): + # If the associated variable is a TypeInfo synthesize a Var node for + # the purposes of type checking. This enables us to type check things + # like accessing class attributes on an inner class. + v = Var(name, type=type_object_type(vv, builtin_type)) + v.info = info + if isinstance(v, Var): return analyze_var(name, v, itype, info, node, is_lvalue, msg, original_type, not_ready_callback, chk=chk) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index f8f27d3a2178..a17fd745eb9d 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -681,6 +681,16 @@ def produce() -> Bar: reveal_type(Bar().make_int) # E: Revealed type is 'def () -> builtins.int' return Bar() +[case testInnerClassPropertyAccess] +class Foo: + class Meta: + name = 'Bar' + meta = Meta + +reveal_type(Foo.Meta.name) # E: Revealed type is 'builtins.str' +reveal_type(Foo().meta.name) # E: Revealed type is 'builtins.str' +reveal_type(Foo().Meta.name) # E: Revealed type is 'builtins.str' + -- Declaring attribute type in method -- ---------------------------------- From 7531e83d98aa47616e7e3ffb6ffddcc46d6e586e Mon Sep 17 00:00:00 2001 From: Roy Williams Date: Fri, 30 Jun 2017 09:54:17 -0700 Subject: [PATCH 2/2] Add tests suggested by @gvanrossum --- test-data/unit/check-classes.test | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index a17fd745eb9d..499e0611a01f 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -687,7 +687,12 @@ class Foo: name = 'Bar' meta = Meta +reveal_type(Foo.Meta) # E: Revealed type is 'def () -> __main__.Foo.Meta' +reveal_type(Foo.meta) # E: Revealed type is 'def () -> __main__.Foo.Meta' reveal_type(Foo.Meta.name) # E: Revealed type is 'builtins.str' +reveal_type(Foo.meta.name) # E: Revealed type is 'builtins.str' +reveal_type(Foo().Meta) # E: Revealed type is 'def () -> __main__.Foo.Meta' +reveal_type(Foo().meta) # E: Revealed type is 'def () -> __main__.Foo.Meta' reveal_type(Foo().meta.name) # E: Revealed type is 'builtins.str' reveal_type(Foo().Meta.name) # E: Revealed type is 'builtins.str'