1

I am developing a Python3.8 project with usage of typing and dataclasses, and automatic tests include mypy. This brings me in a strange behavior that I do not really understand...

In short: Mypy seems not to understand dataclass attributes mechanics that, to my understanding, make them instance attributes.

Here's a minimal example, with a package and two modules:

  • __init__.py: void
  • app_events.py:
class AppEvent:
    pass
  • main.py:
import dataclasses
import typing

from . import app_events


class B:
    """Class with *app_events* as instance attribute."""
    def __init__(self):
        self.app_events: typing.List[app_events.AppEvent] = []

    def bar(self) -> app_events.AppEvent:
        # no mypy complaint here: the import is correctly distinguished
        # from the attribute
        ...


class C:
    """Class with *app_events* as class attribute."""
    app_events: List[app_events.AppEvent]

    def chew(self) -> app_events.AppEvent:
        # mypy considers app_events to be the class attribute
        ...

@dataclasses.dataclass
class D:
    app_events: typing.List[app_events.AppEvent] = \
        dataclasses.field(default_factory=list)

    def doo(self) -> app_events.AppEvent:
        # same here: mypy considers app_events to be the class attribute
        ...

And the typecheck result:

  • PyCharm complains, for methods C.chew and D.doo: Unresolved attribute reference 'AppEvent' for class 'list'
  • mypy complains, still for methods C.chew and D.doo, that error: Name 'app_events.AppEvent' is not defined.

No issue for B.bar as written, though if app_events attribute is declared as a class attribute (instead of being defined in self.__init__, then mypy raise the same complaint.)

-> any idea how to understand/solve/circumvent this elegantly?

I'd really like not to rename my module and attributes, but if you have nice names in mind, please do not hesitate to propose :-)

Joël
  • 2,723
  • 18
  • 36
  • 1
    Maybe import the class directly: `from .app_events import AppEvent`. This can also be done for all the `typing` and `dataclasses` import. – Wombatz Jan 28 '21 at 12:17
  • mmh, nice idea! Even if it does not really fit my usage, due to multiple import from this module, plus an additional, unwanted import loop. I may find my way by solving the latter first though :-) – Joël Feb 01 '21 at 13:14

0 Answers0