Instagram / MonkeyType

A Python library that generates static type annotations by collecting runtime types
Other
4.74k stars 170 forks source link

Avoid failing to trace a call when passed _Protocol or Generic #211

Open pradeep90 opened 3 years ago

pradeep90 commented 3 years ago

Type[foo] raises a TypeError when foo is Generic or typing._Protocol. Here's a repro:

# Source file.
def try_protocol():
    return SupportsInt.__mro__[1]

$ monkeytype -v stub ...

Failed collecting trace
Traceback (most recent call last):
  File "/Users/pradeepkumars/Programs/MonkeyType/monkeytype/tracing.py", line 261, in __call__
    self.handle_return(frame, arg)
  File "/Users/pradeepkumars/Programs/MonkeyType/monkeytype/tracing.py", line 236, in handle_return
    typ = get_type(arg, max_typed_dict_size=self.max_typed_dict_size)
  File "/Users/pradeepkumars/Programs/MonkeyType/monkeytype/typing.py", line 177, in get_type
    return Type[obj]
  File "/opt/homebrew/Cellar/python37/3.7.5_3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 254, in inner
    return func(*args, **kwds)
  File "/opt/homebrew/Cellar/python37/3.7.5_3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 629, in __getitem__
    params = tuple(_type_check(p, msg) for p in params)
  File "/opt/homebrew/Cellar/python37/3.7.5_3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 629, in <genexpr>
    params = tuple(_type_check(p, msg) for p in params)
  File "/opt/homebrew/Cellar/python37/3.7.5_3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 138, in _type_check
    raise TypeError(f"Plain {arg} is not valid as type argument")
TypeError: Plain <class 'typing._Protocol'> is not valid as type argument

It arises from the following lines in typing.py:

https://github.com/Instagram/MonkeyType/blob/master/monkeytype/typing.py#L174-L177

Our best bet is probably to catch the TypeError there and return a default type (probably Any).

This isn't a fatal error right now because we just drop the trace.

jiridanek commented 2 years ago

The error message in Python 3.10 with MonkeyType 22.2.0 has slightly changed, but stacktrace remains essentially in the same form

Failed collecting trace
Traceback (most recent call last):
  File "/home/jdanek/.cache/pypoetry/virtualenvs/skupper-router-7_an9NB3-py3.10/lib/python3.10/site-packages/monkeytype/tracing.py", line 259, in __call__
    self.handle_call(frame)
  File "/home/jdanek/.cache/pypoetry/virtualenvs/skupper-router-7_an9NB3-py3.10/lib/python3.10/site-packages/monkeytype/tracing.py", line 225, in handle_call
    arg_types[name] = get_type(frame.f_locals[name],
  File "/home/jdanek/.cache/pypoetry/virtualenvs/skupper-router-7_an9NB3-py3.10/lib/python3.10/site-packages/monkeytype/typing.py", line 177, in get_type
    return Type[obj]
  File "/usr/lib64/python3.10/typing.py", line 311, in inner
    return func(*args, **kwds)
  File "/usr/lib64/python3.10/typing.py", line 1126, in __getitem__
    params = tuple(_type_check(p, msg) for p in params)
  File "/usr/lib64/python3.10/typing.py", line 1126, in <genexpr>
    params = tuple(_type_check(p, msg) for p in params)
  File "/usr/lib64/python3.10/typing.py", line 171, in _type_check
    raise TypeError(f"Plain {arg} is not valid as type argument")
TypeError: Plain <class 'typing.Protocol'> is not valid as type argument