-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
type alias to union is invalid in runtime context #5354
Comments
I guess this was a result of #5221 ? |
From mypy's point of view it is hard to distinguish whether this is intentional or a mistake. The point is that this change discovered actual errors in real code, so I am not so keen to revert this change even though it was unintentional. On the other hand, such aliases will likely fail at runtime in most scenarios where it is an error quite soon. So the value of discovering them statically is not so big. One possible way is to turn the type aliases into variables by giving them explicit types: X: Type[Any] = Union[A, B, C]
print(X) # OK but then |
see more on python/mypy#5354
I can see your point as far as this being a useful thing to check most of the time. And given that we're relying on private implementation details of typing I know it's my own responsibility to keep up with such changes :). Mainly what I'm looking for here is a non-horrible way forward that translates to something that will be close to a one-day public API. For example, I'm very curious what you mean by
what will make this the case? (previous complaint |
OK, now that I'm actually testing on the correct version:
still says "The type alias to Union is invalid in runtime context", which means any type I want to use in this way needs to be fully typed out twice. |
Is this a workable way to express this for the time being? x = Union[int, str]
x_runtime: Type[Any]
if not TYPE_CHECKING:
x_runtime = x |
What if you do |
After a discussion with @JukkaL I think it is OK to allow the original example. This is however relatively low priority since there are workarounds like using |
FWIW I agree that the priority on this shouldn't be super high; the main thing it makes annoying is testing. In most real code using this system, the |
This required a workaround for python/mypy#5354. Unfortunately this makes TimestampOrNow a runtime type, so if any external code is using it as an annotation it might not work.
python/mypy#5354 They have a bug that disallows type aliases, low priority, so better to just do this.
See python/mypy#5354 for details.
See python/mypy#5354 for details.
Just hit this problem again with Would it be possible to reuse the
which doesn't affect the semantics of |
As I mentioned above, I am fine with allowing type aliases where |
I'm using python 3.7 and I cannot get it working: x = Union[int, str]
x_runtime: Type[Any]
if not TYPE_CHECKING:
x_runtime = x
a = 'a'
if isinstance(a, x_runtime):
pass or x_runtime: Type[Any] = Union[int, str]
a = 'a'
if isinstance(a, x_runtime):
pass Error:
|
@pando85 You can't use a union type in |
Another example: NoneType = type(None)
print(NoneType) |
but it also "discovers" and classifies as errors things that are not errors in real code, which seems very much in the category of "bug". After a much-delayed upgrade, we are now seeing this at my company and it's probably going to force us to downgrade. |
@bwo Can you give an example of where you consider mypy behavior to be a bug? It's possible that error codes (a feature in development) will make it easy to selectively ignore only these errors. However, we may need to more examples where the current behavior is a problem for it to be general enough. |
I'm having trouble getting a small, reliable reproduction. We have code that is morally like this: from typing import Union, TypeVar, Generic
T = TypeVar('T')
convenient_union = Union[int, str]
class Spam(Generic[T]):
def __init__(self, egg: T) -> None:
self.egg = egg
spam = Spam[convenient_union](1) And we get the error on the equivalent of |
More basically, if either of these works, shouldn't both? def spam(u: Type[Union]) -> bytes:
return b''
spam(convenient_union)
spam(Union[int, str]) We have codegen that creates functions that return |
Hello, I'm working on library which helps to create dataclass instances from dict (a bit like pydantic or marshmallow). The main idea is to have funciton like I am working on new feature Minimal exmaple is: from typing import Union, TypeVar, Type, Any
mytype = Union[str, int]
T = TypeVar("T")
def parse(value: T, type_: Type[T]) -> None:
print(type_, value)
parse(1, mytype) # error: The type alias to Union is invalid in runtime context Some code from my library (reagento/adaptix@adc6f53) What can i do with this? |
@Tishka17 The simplest way is to |
Any ideas when it can be fixed? |
As soon as someone submits a PR (i.e. no estimate). |
Any chance we can give this message its own error code instead of |
Can you explain your use where this would be helpful? |
Well If you look at this diff: https://github.com/twisted/klein/pull/301/files, you'll see I added a ton of This is due to a hack @glyph added here to help |
@JukkaL IIRC, there were plans to be able to configure which error codes to ignore -- globally and per module -- so further classification of errors in the "misc" bucket will become even more significant after that feature arrives, since ignoring the entire "misc" error code would be ill advised. There are a handful of errors like this one that fall into the "you used a type object incorrectly at runtime" grouping, which could perhaps share the same error code. |
@chadrik Heh I assumed that feature already existed. :-) |
Fixes #5354 This PR allows using type aliases in runtime context and instead gives them an `object` type (which is the best type that we know). The new error messages are less specific, but the old logic caused annoying false positives for various ORMs that use non-annotation syntax, and for runtime type validation tools. While working on this I found a minor bug in `object_or_any_from_type()` that returned `Any` for `Union[int, Any]` while it should be `object`.
As of MyPy 0.620:
This produces the error:
However, type variables are quite useful in "runtime context" in order to implement things like serialization; for example, https://github.com/Tinche/cattrs makes heavy use of introspecting Union objects to determine which types are valid.
Those of us hacking around code like this have known that the current API for enumerating the members of a Union was private & internal, and not for public consumption, so we've been keeping pace with implementation details while waiting for a public API to get this information to emerge. These errors are super annoying because they imply the only future-looking direction for this type of code will involve manually re-typing the same list of types for every union alias defined anywhere.
Can this change be backed out? If not, is there any guidance for how to define a Union such that it is introspectable?
The text was updated successfully, but these errors were encountered: