python / python/mypy

Mypy misunderstands class-level namespace (spurious `Variable "module.Class.attribute" is not valid as a type`)

Open
#12,570 5 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-runtime-semantics topic-variable-scope
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Consider the following:

from typing import Any

@dataclass
class C:
  dict:object # This attribute name shadows `dict` type, but it should not shadow the name inside of the `class` lexical scope; that's not how python works.
  d:dict # This attribute is annotated as `dict`. The interpreter does not pick up the previous shadowed attribute, but mypy does.

c = C(dict={'a':1}, d={'b':2})
print(c.__annotations__)
assert c.__annotations__['d'] is dict # This proves that mypy is misunderstanding the name `dict`.

mypy 0.942 output:

$ mypy property_name_shadows_type.py
property_name_shadows_type.py:11: error: Variable "property_name_shadows_type.C.dict" is not valid as a type
property_name_shadows_type.py:11: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)

Ill-advised as this naming may seem, mypy is making a semantic mistake here. The dict:object line should not alter the namespace in which d:dict is evaluated (I hope that's the correct terminology!). I ran across this case when a machine-generated dataclass used a builtin type name for an attribute name.

Some notes:

  • This is not specific to dict; it happens for all builtin type names as well as imported type names.
  • If you change the first declaration to dict:Any, then the problem goes away. This seems indicative of a deeper problem in mypy.
  • Whether or not the class is decorated as dataclass seems irrelevant; it's just here for ease of constructing the example instance.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided Python example with mypy and compare the diagnostics for the class attribute named dict and the following d:dict annotation. Done means the example no longer reports the spurious "not valid as a type" error while preserving the stated annotation behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.