Issue inferring type with circular imports/future annotations
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Hey! I ran into something which I think is a bug, although its a very small use case and can be fixed pretty easily. This is my first time reporting an issue so let me know if I need to supply anything more info, or if this isn't actually a bug
Bug Report
using future annotations with this circular import seems to cause issues with recognizing types
To reproduce:
create the following structure:
src
├──my_directory
├── __init__.py
├──a.py
├──__init__.py
├──b.py
with the following code in the files:
src/my_directory/init.py:
from .a import OBJECT_FACTORY, Object
src/my_directory/a.py
from .. import b
class Object():
pass
class ObjectFactory:
def make_object(self) -> Object:
pass
OBJECT_FACTORY = ObjectFactory()
src/init.py
# empty file
src/b.py
from __future__ import annotations
from . import my_directory
def func(bar: Bar):
print(bar.object)
class Bar:
def __init__(
self,
_: str, # if you delete this type annotation there will no longer be an error
):
self.object = my_directory.OBJECT_FACTORY.make_object()
then run:
mypy src
Expected Behavior:
Should be able to infer that the type of bar.object is Object from the type annotation of the make_object method.
Actual Behavior
src/b.py:5: error: Cannot determine type of "object"
Found 1 error in 1 file (checked 4 source files)
Some interesting behaviors:
- if you delete the str type annotation in the Bar class, mypy passes with no issues
- defining func after Bar class passes with no issues
- deleting the 'from .. import b' in a.py passes with no issues
- using a static function make_object with the same annotation instead of in OBJECT_FACTORY will pass with no issues
- running mypy src/b.py instead of mypy src will pass with no issues
- subsequently, now running mypy src will actually pass without issues (likely due to .mypy_cache, deleting the cache will re-instate the bug)
- you can fix this issue if you add the type annotation my_directory.Object to self.object in class Bar
My Environment:
mypy --version
mypy 0.960 (compiled: yes)
python --version
Python 3.8.6
- Mypy command-line flags: no flags
- OS: Windows 10
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the report using the files under src/my_directory/a.py, src/b.py, and the package init.py files, then run mypy src with the cache removed. Compare the behavior when the constructor annotation, circular import, or future annotations are changed. Done means the reported example infers bar.object as Object without adding a redundant annotation and still reports no errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100