netromdk / vermin

Concurrently detect the minimum Python versions needed to run code

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Union types in function return value annotations do not honor `--no-eval-annotations`

FichteFoll opened this issue · comments

Describe the bug
Using type unions with the annotations future import reports a minimum version of 3.10 where it should be 3.7.

To Reproduce

from __future__ import annotations

a: str | None = None


def b(s: str) -> str | None:
    return s


b(a or '')
$ vermin -vvv --no-eval-annotations --no-tips test.py
Detecting python files..
Analyzing using 8 processes..
!2, 3.10    …/test.py
  L1 C5: '__future__' module requires 2.1, 3.0
  L1 C5: '__future__.annotations' member requires !2, 3.7
  L3: variable annotations requires !2, 3.6
  L6: annotations requires !2, 3.0
  L6: union types as `X | Y` requires !2, 3.10

Minimum required versions: 3.10
Incompatible versions:     2

Expected behavior
The union type is ignored because it is annotations should not be evaluated (which is the default).

Environment (please complete the following information):

  • Vermin version or Git commit: 1.4.2
  • Python: 3.10.7

Additional context
I verified that the script parses in 3.7 via docker:

$ docker run -it --rm -v "`pwd`:/data" -w /data python:3.7-alpine
Python 3.7.14 (default, Sep  8 2022, 00:44:25)
[GCC 11.2.1 20220219] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> dir(test)
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'annotations', 'b']
>>> test.annotations
_Feature((3, 7, 0, 'beta', 1), (4, 0, 0, 'alpha', 0), 1048576)
>>> test.__annotations__
{'a': 'str | None'}
>>> test.b.__annotations__
{'s': 'str', 'return': 'str | None'}

Thanks for reporting this! I'll have a look into it soon.

I made a fix in issue-109. It's a good point not to visit the returns AST node when not evaluating annotations.

Now we get:

% ./vermin.py -vvv --no-eval-annotations --no-tips examples/union_type.py
Detecting python files..
Analyzing using 10 processes..
!2, 3.7      examples/union_type.py
  L1 C5: '__future__' module requires 2.1, 3.0
  L1 C5: '__future__.annotations' member requires !2, 3.7
  L3: variable annotations require !2, 3.6
  L5: annotations require !2, 3.0

Minimum required versions: 3.7
Incompatible versions:     2

And:

% ./vermin.py -vvv --eval-annotations --no-tips examples/union_type.py
Detecting python files..
Analyzing using 10 processes..
!2, 3.10     examples/union_type.py
  L1 C5: '__future__' module requires 2.1, 3.0
  L1 C5: '__future__.annotations' member requires !2, 3.7
  L3: union types as `X | Y` require !2, 3.10
  L3: variable annotations require !2, 3.6
  L5: annotations require !2, 3.0
  L5: union types as `X | Y` require !2, 3.10

Minimum required versions: 3.10
Incompatible versions:     2

There we go! I'm in the middle of a larger release so it won't be officially released right away. But you can use via master if you need the fix sooner, of course. Thanks again!