pytype icon indicating copy to clipboard operation
pytype copied to clipboard

kwargs.update should allow arguments of different types

Open pganssle opened this issue 6 years ago • 3 comments

This is a pretty weird and possibly obscure bug. If you have a function that has an incorrect return type and you pass its return value to kwargs.update in a function that takes **kwargs, pytype will flag wrong-arg-types in dict.update. Here is a minimal working example:

def mistyped_func() -> None:  # Error in the return type
    return "Not none!"

def f(**kwargs):
    kwargs.update(cat=mistyped_func(), dog="dog")

When I run pytype on this file, I get:

$ pytype --version
2019.10.17
$ python --version
Python 3.7.4
$ pytype demo_func.py 
Computing dependencies
Analyzing 1 sources with 0 local dependencies
ninja: Entering directory `/tmp/pytype_demo/.pytype'
[1/1] check demo_func
FAILED: /tmp/pytype_demo/.pytype/pyi/demo_func.pyi 
pytype-single --imports_info /tmp/pytype_demo/.pytype/imports/demo_func.imports --module-name demo_func -V 3.7 -o /tmp/pytype_demo/.pytype/pyi/demo_func.pyi --analyze-annotated --nofail --quick /tmp/pytype_demo/demo_func.py
File "/tmp/pytype_demo/demo_func.py", line 2, in mistyped_func: bad option in return type [bad-return-type]
  Expected: None
  Actually returned: str
File "/tmp/pytype_demo/demo_func.py", line 5, in f: Function dict.update was called with the wrong arguments [wrong-arg-types]
  Expected: (self, cat, dog: None, ...)
  Actually passed: (self, cat, dog: str)

For more details, see https://google.github.io/pytype/errors.html.
ninja: build stopped: subcommand failed.

It is very strange that for kwargs specifically (this is not triggered by updating a random dictionary) it is inferring this signature, since dict.update should have a signature that accepts any value. I will also note that it's clearly induced by mistyped_func(), but the result of mistyped_func() is being passed to cat rather than dog (this is probably something to do with the way dict.update can take either a single positional dictionary or keyword argument pairs).

The ordering there may be random or semi-random, since it doesn't seem consistent if I add more arguments to update.

pganssle avatar Nov 26 '19 17:11 pganssle

Huh. I think the fact the mistyped function and the kwargs error are unrelated, actually. If I run pytype on this code:

def f(**kwargs):
    kwargs.update(cat=None, dog="dog")

it still reports:

File "foo.py", line 2, in f: Function dict.update was called with the wrong arguments [wrong-arg-types]
  Expected: (self, cat, dog: None, ...)
  Actually passed: (self, cat, dog: str)

Seems we expect all the arguments to kwargs.update(...) to have the same type, which is obviously wrong.

rchen152 avatar Nov 26 '19 19:11 rchen152

How's the fix going?

chongkong avatar Apr 24 '20 03:04 chongkong

Unfortunately, we haven't had time to work on this yet.

rchen152 avatar Apr 25 '20 00:04 rchen152