Here is a minimal sample example. You can replace GeneratorDict with django's MultiValueDict to get the same result.
from typeguard import typechecked
@typechecked
def a(b: dict[str, list[str]]):
...
class GeneratorDict(dict):
def items(self):
for key in self:
yield key, self[key]
a(GeneratorDict())
Running this code causes the following backtrace:
Traceback (most recent call last):
File "/.../test.py", line 15, in
a(MultiValueDict())
File "/.../test.py", line 5, in a
def a(b: dict[str, list[str]]) -> None:
File "/.../venv/lib/python3.11/site-packages/typeguard/_functions.py", line 138, in check_argument_types
check_type_internal(value, annotation, memo)
File "/.../venv/lib/python3.11/site-packages/typeguard/_checkers.py", line 759, in check_type_internal
checker(value, origin_type, args, memo)
File "/.../venv/lib/python3.11/site-packages/typeguard/_checkers.py", line 220, in check_mapping
samples = memo.config.collection_check_strategy.iterate_samples(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../venv/lib/python3.11/site-packages/typeguard/_config.py", line 54, in iterate_samples
if len(collection):
^^^^^^^^^^^^^^^
TypeError: object of type 'generator' has no len()
Things to check first
[X] I have searched the existing issues and didn't find my bug already reported there
[X] I have checked that my bug is still present in the latest release
Typeguard version
4.1.5
Python version
3.10 / 3.11
What happened?
Using django's
MultiValueDict
causes a crash because its.items()
is a Generator. See django source.check_mapping
passes this generator totypeguard._config.CollectionCheckStrategy.iterate_samples
: https://github.com/agronholm/typeguard/blob/128909a30e9ee4ff7b5cdd8218b7403f6cc4d0eb/src/typeguard/_checkers.py#L220-L222This crashes it here, because generators have no
len()
: https://github.com/agronholm/typeguard/blob/128909a30e9ee4ff7b5cdd8218b7403f6cc4d0eb/src/typeguard/_config.py#L52-L59How can we reproduce the bug?
Here is a minimal sample example. You can replace
GeneratorDict
with django'sMultiValueDict
to get the same result.Running this code causes the following backtrace: