agronholm / typeguard

Run-time type checker for Python
Other
1.55k stars 114 forks source link

`typing.Literal` can not be correctly checked against if it was imported via wildcard import #489

Open xiaosiyu0603 opened 2 months ago

xiaosiyu0603 commented 2 months ago

Things to check first

Typeguard version

4.3.0

Python version

3.11.5

What happened?

My code:

from typing import *
from typeguard import typechecked

@typechecked
def test(string: Literal["hi"] | Literal['hello']):
    return string

print(test("hi"))

Exception raised when running in python:

D:\Home\Desktop>python tgt.py
Traceback (most recent call last):
  File "D:\Home\Desktop\tgt.py", line 11, in <module>
    print(test("hi"))
          ^^^^^^^^^^
  File "D:\Home\Desktop\tgt.py", line 7, in test     
    def test(string: Literal["hi"] | Literal['hello']):
                             ^^^^
NameError: name 'hi' is not defined

How can we reproduce the bug?

Maybe run the code?

agronholm commented 1 month ago

This is caused by the wildcard import, the use of which is bad practice. If instead you do:

from typing import Literal

This works fine. The underlying problem is that the AST transformer looks for typing.Literal and special cases it, but as it can't see where Literal comes from, it doesn't special case Literal, and ends up removing the quotes.

xiaosiyu0603 commented 1 month ago

It works well, thanks a lot! 😀🙏

(It's a little hard for python programmers who lack professional background to discover such mistake.😂 Adding some warnings to the documentation might be helpful.)

agronholm commented 1 month ago

I'll think about that. This is a shortcoming of the library though, and it could some day be fixed. It wll involve nontrivial amounts of work though.