Skip to content
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

Inspection errors on valid union syntax for Python < 3.10 #737

Closed
ofek opened this issue Sep 18, 2024 · 7 comments
Closed

Inspection errors on valid union syntax for Python < 3.10 #737

ofek opened this issue Sep 18, 2024 · 7 comments

Comments

@ofek
Copy link
Contributor

ofek commented Sep 18, 2024

Description

The following code:

from __future__ import annotations
from msgspec import Struct, inspect

class Bug(Struct):
    field: str | int = 0

inspect.type_info(Bug)

produces the following:

Traceback (most recent call last):
  File "C:\Users\ofek\Desktop\rf\m.py", line 7, in <module>
    inspect.type_info(Bug)
  File "C:\Users\ofek\AppData\Local\Programs\Python\Python39\lib\site-packages\msgspec\inspect.py", line 629, in type_info
    return multi_type_info([type])[0]
  File "C:\Users\ofek\AppData\Local\Programs\Python\Python39\lib\site-packages\msgspec\inspect.py", line 598, in multi_type_info
    return _Translator(types).run()
  File "C:\Users\ofek\AppData\Local\Programs\Python\Python39\lib\site-packages\msgspec\inspect.py", line 744, in run
    MsgpackDecoder(Tuple[self.types])
  File "C:\Users\ofek\AppData\Local\Programs\Python\Python39\lib\site-packages\msgspec\_utils.py", line 130, in get_class_annotations
    value = typing._eval_type(value, cls_locals, cls_globals)
  File "C:\Users\ofek\AppData\Local\Programs\Python\Python39\lib\typing.py", line 292, in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
  File "C:\Users\ofek\AppData\Local\Programs\Python\Python39\lib\typing.py", line 554, in _evaluate
    eval(self.__forward_code__, globalns, localns),
  File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'type' and 'type'

The following code is a workaround but limits what users are allowed to do when providing a library that extends msgspec:

from __future__ import annotations
from typing import Union
from msgspec import Struct, inspect

class Bug(Struct):
    field: Union[str, int] = 0

inspect.type_info(Bug)
@chuckwondo
Copy link

Using a pipe for type unions was introduced in Python 3.10, so anybody running an earlier version of Python shouldn't be surprised by this. If you want to "extend" msgspec and use the pipe syntax, then your extension must require python >= 3.10. If you want to support use of earlier versions of Python, then you must use the Union syntax, not the pipe syntax.

@ofek
Copy link
Contributor Author

ofek commented Sep 18, 2024

Doesn't from __future__ import annotations allow for that syntax though?

@ofek
Copy link
Contributor Author

ofek commented Sep 18, 2024

It looks like the reason the syntax error goes away is only due to the lazy computation. Thanks Chuck!

@ofek ofek closed this as completed Sep 18, 2024
@chuckwondo
Copy link

Doesn't from __future__ import annotations allow for that syntax though?

No, that only allows for postponed evaluation of annotations.

@ofek
Copy link
Contributor Author

ofek commented Sep 19, 2024

Yes thanks, I added a note for users earlier today! https://ofek.dev/msgspec-click/usage/#caveats

@ashb
Copy link

ashb commented Nov 12, 2024

Pydantic handles this via https://github.com/alexmojaki/eval_type_backport -- is there any appetite for doing the same in msgspec? Happy to PR it if that it'd be supported.

@jcrist What would your appetite for it be?

@jcrist
Copy link
Owner

jcrist commented Nov 15, 2024

Thanks for the comment - I'd be open to doing something like that. I've opened #771 to track this, lets continue discussion there :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants