Background
I have two modules. Module 1 (example) defines TestClass. Module 2 (example2) defines functions change_var which takes an argument TestClass. example has a method change which calls change_var from example2 and passes self as argument.
example2 uses TYPE_CHECKING from typing to ensure cyclic import does not appear at run-time, but still allows MYPY to check types.
At the call to change_var from within change, MYPY gives the error Argument 1 to "change_var" has incompatible type "__main__.TestClass"; expected "example.TestClass".
Python Version: 3.7.3,
MYPY Version: 0.701
Example Code
example.py
from example2 import change_var
class TestClass:
def __init__(self) -> None:
self.test_var = 1
def change(self) -> None:
change_var(self)
example2.py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from example import TestClass
def change_var(obj: "TestClass") -> None:
obj.test_var = 2
This code is a minimal example of the actual problem I am experiencing in a larger python project.
What I Expect this to do
These types should match as they are (as far as I can tell) the same.
My intuition as to why this doesn't work is that TestClass, at the point of calling to change_var isn't fully defined? For the same reason I can't refer to TestClass as a type within TestClass itself, I can't pass a TestClass object to a function that expects a TestClass object from withing the class itself. To MYPY, this is not a full class yet so it uses some kind of placeholder type. This is only an intuition though.
Questions
- What exactly is the problem here?
- What is the best work around to achieve this general code structure (two modules, class in one, function that takes class in other, method calls to function) while still making MYPY happy?
I am also open to refactoring this example entirely but I'd like to try to stick to this general structure.