Mypy: class inside a class

Created on 21 Aug 2017  路  7Comments  路  Source: python/mypy

I am trying to use mypy on an existing django project. In Django models can have a special sub-class Meta and the Models can inherit from each other. Therefore I have a situation like this one:

class Foo:
    class Meta:
        pass

class Bar:
    class Meta:
        pass

class FooBar(Foo, Bar):
    pass

mypy reports an error on the FooBar class definition:

Cannot determine type of 'Meta' in base class 'Foo'
Cannot determine type of 'Meta' in base class 'Bar'

I am not sure if a missed a feature that would solve this. I think there should be a way to define the type sub class. For example with:

class Foo:
    class Meta:  # type: object
        pass
bug priority-1-normal topic-usability

Most helpful comment

Also for those who don't want to use the Django mypy plugin, or if you want to silence this error for other reason you can either just put # type: ignore on the subclass definition, or use this pattern:

Unsafe: Any = object

class A:
    class Sub(Unsafe):
        pass

class B:
    class Sub(Unsafe):
        pass

class C(A, B):  # no complains from mypy
    pass

Note however it will disable many checks for A.Sub and B.Sub.

All 7 comments

Hm, interesting. There is an ongoing project writing stubs for django (https://github.com/machinalis/mypy-django) -- maybe that has a solution already, or maybe someone on that project can help you if you file an issue there?

Thank you for the tip. I opened an issue on there project.

But I think this problem is not django specific. I don't know if classes in classes is a good style, but another projects may also use them.

It's pretty uncommon outside Django's patterns.

This one is actually quite straightforward to fix. The symbol table nodes for nested classes are created in the first pass (when little is known) so that their types are set to None. They are however never updated in the second pass. I would propose to update the types to either Type[Nested] or CallableType[<signature of __init__>, Nested]. Both versions have their pluses and minuses, so I am not sure here.

FYI, similar issues #2871 #4956

This is closed by #5926 that emits a better error message, and accepts safe use cases (e.g. when one nested class is a subclass of another nested class).

Note that mypy still emits an error on the original example, because it is technically unsafe. Note however that @mkurnikov works on a mypy plugin for Django that will suppress this error for Django specific use cases.

Also for those who don't want to use the Django mypy plugin, or if you want to silence this error for other reason you can either just put # type: ignore on the subclass definition, or use this pattern:

Unsafe: Any = object

class A:
    class Sub(Unsafe):
        pass

class B:
    class Sub(Unsafe):
        pass

class C(A, B):  # no complains from mypy
    pass

Note however it will disable many checks for A.Sub and B.Sub.

Was this page helpful?
0 / 5 - 0 ratings