python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.18k stars 2.77k forks source link

`"object" has no attribute "append"` when adding list to untyped dict #15768

Open LordAro opened 1 year ago

LordAro commented 1 year ago

Bug Report

Given an existing data structure that contains arbitrary data, mypy only uses the initial information at initialisation to infer the type. If some code later alters the data structure with different types, mypy complains that the type is incorrect (attr-defined)

This is (naturally) within legacy code that does not have full type coverage. Ideally mypy should be fine with that, as there's nothing especially wrong with that behaviour. I realise I could add # type: ignore or even just the actual type signature to the code, but I'm not sure I should have to for what was otherwise perfectly correct Python code.

Results in the error:

(A clear and concise description of what the bug is.)

To Reproduce

data = {
    "foo": 1,
    "bar": "flibble",
}

data["baz"] = []
data["baz"].append("frobnicate")

https://mypy-play.net/?mypy=latest&python=3.11&gist=93080ccd2ecba6728a23eb531f9ef384

Expected Behavior

No errors, mypy should, given no other information, assume that data's type is dict[Any, Any]

Actual Behavior

main.py:10: error: "object" has no attribute "append"  [attr-defined]

Your Environment

LordAro commented 1 year ago

I've done a little more playing, and reading of https://mypy.readthedocs.io/en/stable/type_inference_and_annotations.html#type-inference

And using reveal_type I get:

main.py:9: note: Revealed type is "builtins.dict[builtins.str, builtins.object]"

why is it that mypy uses builtins.object rather than typing.Any ? Just because object is builtin?

I've got this following example, which is perhaps a better example of what I'm seeing, and doesn't involve changing the type after initialising the dict:

def foo(value: str):
    data = {
        "foo": 1,
        "bar": "flibble",
        "baz": [],
    }
    data["baz"].append(value)

main.py:7: error: "object" has no attribute "append" [attr-defined]

tmke8 commented 1 year ago

It's the old join-v-union error: https://github.com/python/mypy/labels/topic-join-v-union

The work-around is to add an explicit annotation.

Mte90 commented 9 months ago

I have the same error with a similar code:

context = {'content': [], 'is_tag': False}

    for item in items:
        context['content'].append({})

I wasn't able to find a way to add an exception or ignore that line.

outp1 commented 1 month ago

+1 same issue