You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have an issue with circular imports that I am having trouble resolving.
Here is a simple repro case which is similar to what I am doing:
$ tree
.
└── circular
├── a.py
├── b.py
├── c.py
└── main.py
1 directory, 4 files
$ cat circular/a.py
# from circular import b
import circular.b as b
class A:
def __init__(self):
print(f'A.__init__ {id(self)=}')
$ cat circular/b.py
from injector import inject, Injector
import circular.c as c
class B:
@inject
def __init__(self, injector: Injector):
print(f'B.__init__ {id(self)=} {id(injector)=}')
$ cat circular/c.py
from injector import inject
import circular.b as b
class C:
@inject
def __init__(self, b: 'b.B'):
print(f'C.__init__ {id(self)=} {id(b)=}')
$ cat circular/main.py
# add to path to make this runnable from anywhere
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from injector import Injector
import circular.b as b
def main():
injector = Injector()
b_inst = injector.get(b.B)
if __name__ == '__main__':
main()
When I run this, I get an AttributeError related to circular imports caused by a call to get_type_hints. I hoped this would defer, due to the use of a forward reference in c.py and module imports, but maybe I am misunderstanding?
Traceback (most recent call last):
File "inj\circular\main.py", line 8, in <module>
import circular.b as b
File "inj\circular\b.py", line 3, in <module>
import circular.c as c
File "inj\circular\c.py", line 6, in <module>
class C:
File "inj\circular\c.py", line 8, in C
def __init__(self, b: 'b.B'):
File "[venv]\lib\site-packages\injector\__init__.py", line 1367, in inject
bindings = _infer_injected_bindings(function, only_explicit_bindings=False)
File "[venv]\lib\site-packages\injector\__init__.py", line 1176, in _infer_injected_bindings
bindings = get_type_hints(callable, include_extras=True)
File "[venv]\lib\site-packages\typing_extensions.py", line 1880, in get_type_hints
hint = typing.get_type_hints(obj, globalns=globalns, localns=localns)
File "[python]\Python38\lib\typing.py", line 1261, in get_type_hints
value = _eval_type(value, globalns, localns)
File "[python]\Python38\lib\typing.py", line 270, in _eval_type
return t._evaluate(globalns, localns)
File "[python]\Python38\lib\typing.py", line 518, in _evaluate
eval(self.__forward_code__, globalns, localns),
File "<string>", line 1, in <module>
AttributeError: partially initialized module 'circular.b' has no attribute 'B' (most likely due to a circular import)
Since I don't have a full understanding of Injector internals, I tried a longshot of adding AttributeError to the try/except (in addition to NameError that's already caught) in _infer_injected_bindings at line 1164. This actually works for both the simplified repro and my actual application. However, I don't know what other implications this change might have and I wanted to seek you advice.
Thanks!
The text was updated successfully, but these errors were encountered:
As much I don't really want to encourage people using circular imports I believe you're correct in narrowing down the underlying issue and this seems like a sensible change, I'll happily accept a PR implementing this as long as there's a test provided (will require a test package with a circular import to replicate the situation).
I have an issue with circular imports that I am having trouble resolving.
Here is a simple repro case which is similar to what I am doing:
When I run this, I get an
AttributeError
related to circular imports caused by a call toget_type_hints
. I hoped this would defer, due to the use of a forward reference inc.py
and module imports, but maybe I am misunderstanding?Since I don't have a full understanding of
Injector
internals, I tried a longshot of addingAttributeError
to the try/except (in addition toNameError
that's already caught) in_infer_injected_bindings
at line 1164. This actually works for both the simplified repro and my actual application. However, I don't know what other implications this change might have and I wanted to seek you advice.Thanks!
The text was updated successfully, but these errors were encountered: