-
-
Notifications
You must be signed in to change notification settings - Fork 382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deferred type annotations are evaluated in the wrong execution context #593
Comments
I'm not sure that's something we can achieve TBH. |
I'm having the same problem. Is there any workaround in which the original Also, is there any way to know if a |
PS. You can workaround it with:
or
|
Thanks @euresti for the proposals 👍 . Unfortunately, I think they won't work for me: First proposal: get_type_hints(C.__init__, sys.modules[C.__module__].__dict__) I need to obtain the hints only from the assert get_cls_from_attrs_init(C.__init__) == C Second proposal get_type_hints(C.__init__, globalns=globals()) The problem with this proposal is that the globals obtained from Thank you! |
You don't need the class. You only need the module:
|
Thanks, @euresti 👍 . That is very helpful, serves for most of my cases, thanks. But it is not working for the case of classes defined within functions. The following fails with import sys
from typing import get_type_hints
import attr
def hints(method):
return get_type_hints(method, sys.modules[method.__module__].__dict__)
def resolve():
@attr.s(auto_attribs=True)
class A:
b: 'B'
@attr.s(auto_attribs=True)
class B:
pass
return hints(A.__init__)
resolve() Any idea if there is any workaround for that? By the other hand, I have discovered that this issue will get worse in future python 4.0, where posponed evaluation of annotations will be the default. The following fails with from __future__ import annotations
from typing import get_type_hints
import attr
class B:
pass
@attr.s(auto_attribs=True)
class A:
b: B
get_type_hints(A.__init__) Hope this is hepful. |
It doesn't cover all the possible cases because there are limitations in attrs itself. See python-attrs/attrs#593 Enabled py35 in Travis
Local scopes are very hard to remember. Do you need to pass around
That's because in python 4 this
is actually
|
@euresti some context: a library inspects signature of functions ( So if we have For this it needs to be able to retrieve typing information reliably, at runtime; this breaks for attr.s classes. |
So there are 2 places where these values are stored.
Otherwise you have to do something like this:
In the end we just decided the simplest solution was to enforce that all classes are created at module scope and then |
To clarify using your example:
You could even use |
I learned today that Basically on class creation they save the class module dict, |
Is that a gut feeling or do you see blockers? |
I haven't looked deep at the attrs code. I notice that dataclasses just uses exec whereas attrs uses compile + eval. Basically since the code is not identical I couldn't say that it would 100% work to do the same as dataclasses. |
Hmhm. FWIW, we used to use compile/exec until…this happened #87 (comment). |
It would be nice to move this forward because we are already in Python 3.10 alpha 5 and our possibilities to change something big are limited in beta releases. |
Euresti is on it but wouldn’t be it just fine for you to disable the relevant tests on Python 3.10 for now? |
We definitely can do that but this early testing of the next Python release gives us a possibility to find regressions or bad implementation in the Python itself so it's preferred to adapt to the new version early. |
To reproduce, run the following program:
Expected result
Actual result
This annotation should be evaluated in the context of the module where it's defined, where
List
is in globals.Version info
The text was updated successfully, but these errors were encountered: