Description
Bug report
Example program:
a: int
a: int = 0
(a): int
(a): int = 0
a.b: int
a.b: int = 0
`ast.parse() for this module results in
Module(
body=[
AnnAssign(
target=Name(id='a', ctx=Store()), (OK)
annotation=Name(id='int', ctx=Load()),
simple=1),
AnnAssign(
target=Name(id='a', ctx=Store()),
annotation=Name(id='int', ctx=Load()),
value=Constant(value=0),
simple=1),
AnnAssign(
target=Name(id='a', ctx=Store()), <--
annotation=Name(id='int', ctx=Load()),
simple=0),
AnnAssign(
target=Name(id='a', ctx=Store()),
annotation=Name(id='int', ctx=Load()),
value=Constant(value=0),
simple=0),
AnnAssign(
target=Attribute(
value=Name(id='a', ctx=Load()),
attr='b',
ctx=Store()), <--
annotation=Name(id='int', ctx=Load()),
simple=0),
AnnAssign(
target=Attribute(
value=Name(id='a', ctx=Load()),
attr='b',
ctx=Store()),
annotation=Name(id='int', ctx=Load()),
value=Constant(value=0),
simple=0)],
type_ignores=[])
In the two cases marked with <--
, there is no assignment made to the target, so IMHO, the ctx should be Load()
, not Store()
.
In fact, in
a = 10
b = 20
class C:
(a): int
b: int
print(locals())
print(a, b)
b = 2
print(locals())
print(a, b)
def f():
(a): int
b: int
print(locals())
b = 2
print(locals())
print(a, b)
f()
The output is
{'__module__': '__main__', '__qualname__': 'C', '__annotations__': {'b': <class 'int'>}}
--- C locals, b is missing
10 20 --- C.a, C.b = the global a and b
{'__module__': '__main__', '__qualname__': 'C', '__annotations__': {'b': <class 'int'>}, 'b': 2}
--- C locals after assign to b, b is now present
10 2 --- C.a, C.b = global a, local b
{} --- f locals
{'b': 2} --- f.locals after assign to b
10 2 --- a, b = global a, local b
(a): int
does not make a
a local variable in f
or C
. In fact, it generates no code at all.
b: int
does make b
a local variable
Another example:
(a): int
global a # OK
b: int
global b # SyntaxError: annotated name 'b' can't be global
Impact
I have a code analysis tool that walks through the ast
syntax tree. It finds Name
nodes and records that the name is a local variable when the ctx=Store()
.
In an AnnAssign
statement, with simple=0
, I have to make a special case and ignore the ctx=Store()
.
With a.b: int; print(a.b)
, this does not affect my tool (at present), but it may confuse a static typing tool like mypy
into thinking that a.b
has a value, rather than reporting the print(a.b)
as an error.
Your environment
- CPython versions tested on: 3.9.6