Skip to content

class inside a class #3855

Closed
Closed

Description

@ostcar

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

Activity

  1. gvanrossum commented on Aug 21, 2017

    @gvanrossum
    Member

    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?

  2. ostcar commented on Aug 21, 2017

    @ostcar
    Author

    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.

  3. gvanrossum commented on Aug 21, 2017

    @gvanrossum
    Member

    It's pretty uncommon outside Django's patterns.

  4. ilevkivskyi commented on Aug 21, 2017

    @ilevkivskyi
    Member

    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.

  5. syenchuk commented on Nov 8, 2018

    @syenchuk

    FYI, similar issues #2871 #4956

  6. ilevkivskyi commented on Jan 9, 2019

    @ilevkivskyi
    Member

    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.

  7. ilevkivskyi commented on Jan 9, 2019

    @ilevkivskyi
    Member

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions