Skip to content

Type declarations of base class attributes not carried over to subclasses if None is present #2022

Closed

Description

@Vgr255

Simplest repro:

class BaseClass:
    my_attr = () # type: tuple

class Subclass(BaseClass):
    my_attr = None

Output:

testing.py: note: In class "Subclass":
testing.py:5: error: Need type annotation for variable

However, if None isn't the sole value but part of something else, this is likely not the desired behaviour. Consider this:

from typing import Tuple, Any

class BaseClass:
    my_attr = ( ("", None), ) # type: Tuple[Tuple[str, Any]]

class Subclass(BaseClass):
    my_attr = (
        ("one",  set ),
        ("two",  str ),
        ("three",None),
    )

Output:

testing.py: note: In class "Subclass":
testing.py:8: error: Need type annotation for variable

Changing None for anything else, adding a # type: ignore comment on the ("one", set), line (but not on any other line of the assignment) silences the error. This is somewhat related to #1338 (and, to a lesser extent, #1032).

Activity

  1. added this to the milestone on Aug 13, 2016
  2. gvanrossum commented on Aug 13, 2016

    @gvanrossum
    Member

    Yeah, definitely a bug. I think it's related to #1338, the type of class attributes is just not checked against the base classes at all (unlike methods).

  3. gvanrossum commented on Jan 27, 2017

    @gvanrossum
    Member

    Looking into this again (now that #2510 has been merged) I think there's still something fishy here: I think the first example (in the absence of --strict-optional) should be silent, since it's essentially equivalent to

    x = None  # type: int
    x = None

    which is silent.

    (However the second example contains an error, since the subclass uses attr instead of my_attr. Fixing that, the example correctly complains that the top-level Tuple type in the subclass (of three items) is incompatible with the type from the base class (of 1 item).)

  4. Vgr255 commented on Jan 28, 2017

    @Vgr255
    Author

    Whoops, I probably messed up when I copied the repro over. Edited the comment to correct this. I sadly no longer have a use case for this, as the affected code is gone. I still think it's worth fixing, though, and I hope you figure it out. Cheers!

  5. removed this from the milestone on Mar 29, 2017
  6. AlexWaygood commented on Mar 27, 2022

    @AlexWaygood
    Member

    The example code no longer causes a mypy error if you use the --no-strict-optional option (which was the default at the time of the bug being filed). If you don't use the --no-strict-optional option, you just need to change the annotations to this:

    class BaseClass:
        my_attr = () # type: tuple | None
    
    class Subclass(BaseClass):
        my_attr = None

    And mypy is fine with it.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions