Search code examples
pythonpython-typingmypy

Type annotate inside loop


The mypy error is

Need type annotation for "args"  [var-annotated]
Need type annotation for "kwargs"  [var-annotated]

and here is the piece of code

expected_args: Optional[Sequence[Tuple[Any, ...]]]
expected_kwargs: Optional[Sequence[Dict[str, Any]]]

...
expected_args_iter = iter(expected_args or ())
expected_kwargs_iter = iter(expected_kwargs or ())

...
for args, kwargs in itertools.zip_longest(
    expected_args_iter, expected_kwargs_iter, fillvalue={})

Where can I annotate "args" and "kwargs"?


Solution

  • This appears to be a bug in mypy v1.14.0. For some reason, any iteration over itertools.zip_longest() with an empty sequence* in fillvalue will cause a similar issue. This is the simplest example I could construct:

    import itertools
    
    seq_a: list
    seq_b: list
    
    for a, b in itertools.zip_longest(seq_a, seq_b, fillvalue=[]): ...
    

    This is specific to both mypy and empty sequences. Non-empty sequences, non-sequences, and using Pyright are all fine.

    In your particular case, you can work around this issue by leaving fillvalue as its default (None) and hard-coding an exception into your comprehension.

    pretty_unused_args = [
        ', '.join(itertools.chain(
            (repr(a) for a in args) if args is not None else [],
            ('%s=%r' % kwarg for kwarg in kwargs.items()) if kwargs is not None else []))
        for args, kwargs in itertools.zip_longest(
            expected_args_iter, expected_kwargs_iter)
    ]
    

    *Besides (), but including tuple()