Skip to content

Tuple unpacking raises an incorrect TypeCheckError at runtime #535

@yilei

Description

@yilei

Things to check first

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

Typeguard version

4.4.4

Python version

3.11.13, 3.13.7, 3.14.0

What happened?

Here is an example use of @typechecked:

from typeguard import typechecked


@typechecked
def demo(arg: str | None = None) -> None:
    if arg is None:
        (arg,) = ("abc",)
    print(f"{type(arg)=}, {arg=}")
    return None


demo()

Failure:

Traceback (most recent call last):
  File "/tmp/t.py", line 14, in <module>
    demo()
    ~~~~^^
  File "/tmp/t.py", line 9, in demo
    (arg,) = ("abc",)
  File "typeguard/_functions.py", line 283, in check_variable_assignment
    check_type_internal(val, annotation, memo)
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "typeguard/_checkers.py", line 960, in check_type_internal
    checker(value, origin_type, args, memo)
    ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "typeguard/_checkers.py", line 454, in check_uniontype
    raise TypeCheckError(f"did not match any element in the union:\n{formatted_errors}")
typeguard.TypeCheckError: value assigned to arg (tuple) did not match any element in the union:
  str: is not an instance of str
  NoneType: is not an instance of NoneType

If we remove the decorator, it outputs type(arg)=<class 'str'>, arg='abc'.

I think typeguard is confused by the tuple unpacking (arg,) = ("abc",) and thinks arg is a tuple while it should be str.

How can we reproduce the bug?

Run the above example

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions