shawwn / get-annotations

A backport of Python 3.10's `inspect.get_annotations()` function
Other
2 stars 0 forks source link

`eval_str` is defunct on Python 3.9 #1

Open flying-sheep opened 2 years ago

flying-sheep commented 2 years ago

https://github.com/shawwn/get-annotations/blob/8ef2d4e1d9f60a68c9f3a79118e99080ec9f181d/get_annotations/__init__.py#L117-L119

With Python 3.9 and from __future__ import annotations, I get a dict[str, typing.ForwardRef] no matter if I specify eval_str=True or not.

isinstance(value, str) is of course False for ForwardRefs …

You should setup CI for all supported Python versions to make sure it works!

sphuber commented 1 year ago

I am not exactly sure if the following is the same bug, but I also have trouble running this with Python 3.8.

Running the following script

#!/usr/bin/env python
from __future__ import annotations

from get_annotations import get_annotations

def function(a: str | int):
    pass

print(get_annotations(function, eval_str=True))

yields the exception:

Traceback (most recent call last):
  File "annotations.py", line 10, in <module>
    print(get_annotations(function, eval_str=True))
  File "/home/sph/.virtualenvs/aiida_dev/lib/python3.8/site-packages/get_annotations/__init__.py", line 117, in get_annotations
    return_value = {key:
  File "/home/sph/.virtualenvs/aiida_dev/lib/python3.8/site-packages/get_annotations/__init__.py", line 118, in <dictcomp>
    value if not isinstance(value, str) else eval(value, globals, locals)
  File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'type' and 'type'

The declaration of the function itself works perfectly fine, due to the from __future__ import annotations. So not quite sure why this failing in the get_annotations call.

ajskateboarder commented 1 year ago

TypeError: unsupported operand type(s) for |: 'type' and 'type'

This type syntax: str | int is not supported until Python 3.10. You should use typing.Union instead In previous versions, it's just a bitwise or

sphuber commented 1 year ago

I think I see where my confusion come from now: it is possible to use str | int in Python 3.7 and up, as long as from __future__ import annotations is added, as this enables the postponed evaluation of annotations [PEP 563]. In this case, the type hints are simply stored as strings and not actually evaluated. This is why str | int becomes "valid" in Python older than 3.10. If the expression is evaluated, it needs support for the new union type syntax of PEP 604, which was released with Python 3.10 as you say. TL:DR my post above can indeed be ignored.