Skip to content

Commit 1bbce9d

Browse files
committed
make basic things work
1 parent 5f08ccf commit 1bbce9d

14 files changed

+76
-12
lines changed

mypy/checkexpr.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
OpExpr, UnaryExpr, IndexExpr, CastExpr, RevealExpr, TypeApplication, ListExpr,
2929
TupleExpr, DictExpr, LambdaExpr, SuperExpr, SliceExpr, Context, Expression,
3030
ListComprehension, GeneratorExpr, SetExpr, MypyFile, Decorator,
31-
ConditionalExpr, ComparisonExpr, TempNode, SetComprehension,
31+
ConditionalExpr, ComparisonExpr, TempNode, SetComprehension, AssignmentExpr,
3232
DictionaryComprehension, ComplexExpr, EllipsisExpr, StarExpr, AwaitExpr, YieldExpr,
3333
YieldFromExpr, TypedDictExpr, PromoteExpr, NewTypeExpr, NamedTupleExpr, TypeVarExpr,
3434
TypeAliasExpr, BackquoteExpr, EnumCallExpr, TypeAlias, SymbolNode, PlaceholderNode,
@@ -2421,6 +2421,11 @@ def check_list_multiply(self, e: OpExpr) -> Type:
24212421
e.method_type = method_type
24222422
return result
24232423

2424+
def visit_assignment_expr(self, e: AssignmentExpr) -> Type:
2425+
value = self.accept(e.value)
2426+
self.chk.check_assignment(e.target, e.value)
2427+
return value
2428+
24242429
def visit_unary_expr(self, e: UnaryExpr) -> Type:
24252430
"""Type check an unary operation ('not', '-', '+' or '~')."""
24262431
operand_type = self.accept(e.expr)

mypy/fastparse.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr,
2323
DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr,
2424
FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr,
25-
UnaryExpr, LambdaExpr, ComparisonExpr,
25+
UnaryExpr, LambdaExpr, ComparisonExpr, AssignmentExpr,
2626
StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension,
2727
SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument,
2828
AwaitExpr, TempNode, Expression, Statement,
@@ -718,10 +718,6 @@ def visit_AugAssign(self, n: ast3.AugAssign) -> OperatorAssignmentStmt:
718718
self.visit(n.value))
719719
return self.set_line(s, n)
720720

721-
def visit_NamedExpr(self, n: NamedExpr) -> None:
722-
self.fail("assignment expressions are not yet supported", n.lineno, n.col_offset)
723-
return None
724-
725721
# For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
726722
def visit_For(self, n: ast3.For) -> ForStmt:
727723
if n.type_comment is not None:
@@ -883,6 +879,10 @@ def visit_Continue(self, n: ast3.Continue) -> ContinueStmt:
883879

884880
# --- expr ---
885881

882+
def visit_NamedExpr(self, n: NamedExpr) -> AssignmentExpr:
883+
s = AssignmentExpr(self.visit(n.target), self.visit(n.value))
884+
return self.set_line(s, n)
885+
886886
# BoolOp(boolop op, expr* values)
887887
def visit_BoolOp(self, n: ast3.BoolOp) -> OpExpr:
888888
# mypy translates (1 and 2 and 3) as (1 and (2 and 3))

mypy/literals.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
ConditionalExpr, EllipsisExpr, YieldFromExpr, YieldExpr, RevealExpr, SuperExpr,
88
TypeApplication, LambdaExpr, ListComprehension, SetComprehension, DictionaryComprehension,
99
GeneratorExpr, BackquoteExpr, TypeVarExpr, TypeAliasExpr, NamedTupleExpr, EnumCallExpr,
10-
TypedDictExpr, NewTypeExpr, PromoteExpr, AwaitExpr, TempNode,
10+
TypedDictExpr, NewTypeExpr, PromoteExpr, AwaitExpr, TempNode, AssignmentExpr,
1111
)
1212
from mypy.visitor import ExpressionVisitor
1313

@@ -159,6 +159,9 @@ def visit_index_expr(self, e: IndexExpr) -> Optional[Key]:
159159
return ('Index', literal_hash(e.base), literal_hash(e.index))
160160
return None
161161

162+
def visit_assignment_expr(self, e: AssignmentExpr) -> None:
163+
return None
164+
162165
def visit_call_expr(self, e: CallExpr) -> None:
163166
return None
164167

mypy/newsemanal/semanal.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
PlaceholderNode, COVARIANT, CONTRAVARIANT, INVARIANT,
7474
nongen_builtins, get_member_expr_fullname, REVEAL_TYPE,
7575
REVEAL_LOCALS, is_final_node, TypedDictExpr, type_aliases_target_versions,
76-
EnumCallExpr
76+
EnumCallExpr, AssignmentExpr,
7777
)
7878
from mypy.tvar_scope import TypeVarScope
7979
from mypy.typevars import fill_typevars
@@ -1832,6 +1832,10 @@ def visit_import_all(self, i: ImportAll) -> None:
18321832
# Assignment
18331833
#
18341834

1835+
def visit_assignment_expr(self, s: AssignmentExpr) -> None:
1836+
s.value.accept(self)
1837+
self.analyze_lvalue(s.target)
1838+
18351839
def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
18361840
tag = self.track_incomplete_refs()
18371841
s.rvalue.accept(self)

mypy/nodes.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,17 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
15811581
return visitor.visit_unary_expr(self)
15821582

15831583

1584+
class AssignmentExpr(Expression):
1585+
"""Assignment expressions in Python 3.8+, like "a := 2"."""
1586+
def __init__(self, target: Expression, value: Expression) -> None:
1587+
super().__init__()
1588+
self.target = target
1589+
self.value = value
1590+
1591+
def accept(self, visitor: ExpressionVisitor[T]) -> T:
1592+
return visitor.visit_assignment_expr(self)
1593+
1594+
15841595
# Map from binary operator id to related method name (in Python 3).
15851596
op_methods = {
15861597
'+': '__add__',

mypy/semanal.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
GlobalDecl, SuperExpr, DictExpr, CallExpr, RefExpr, OpExpr, UnaryExpr,
4949
SliceExpr, CastExpr, RevealExpr, TypeApplication, Context, SymbolTable,
5050
SymbolTableNode, ListComprehension, GeneratorExpr,
51-
LambdaExpr, MDEF, Decorator, SetExpr, TypeVarExpr,
51+
LambdaExpr, MDEF, Decorator, SetExpr, TypeVarExpr, AssignmentExpr,
5252
StrExpr, BytesExpr, PrintStmt, ConditionalExpr, PromoteExpr,
5353
ComparisonExpr, StarExpr, ARG_POS, ARG_NAMED, type_aliases,
5454
YieldFromExpr, NamedTupleExpr, NonlocalDecl, SymbolNode,
@@ -1780,6 +1780,10 @@ def add_type_alias_deps(self, aliases_used: Iterable[str],
17801780
target = self.scope.current_target()
17811781
self.cur_mod_node.alias_deps[target].update(aliases_used)
17821782

1783+
def visit_assignment_expr(self, e: AssignmentExpr) -> None:
1784+
self.analyze_lvalue(e.target)
1785+
e.value.accept(self)
1786+
17831787
def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
17841788
s.is_final_def = self.unwrap_final(s)
17851789
self.analyze_lvalues(s)

mypy/semanal_pass1.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ def visit_block(self, b: Block) -> None:
154154
node.accept(self)
155155
self.sem.block_depth[-1] -= 1
156156

157+
def visit_assignment_expr(self, s: AssignmentStmt) -> None:
158+
if self.sem.is_module_scope():
159+
self.analyze_lvalue(s.target)
160+
157161
def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
158162
if self.sem.is_module_scope():
159163
for lval in s.lvalues:
@@ -333,6 +337,8 @@ def visit_decorator(self, d: Decorator) -> None:
333337

334338
def visit_if_stmt(self, s: IfStmt) -> None:
335339
infer_reachability_of_if_statement(s, self.sem.options)
340+
for expr in s.expr:
341+
expr.accept(self)
336342
for node in s.body:
337343
node.accept(self)
338344
if s.else_body:

mypy/server/subexpr.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
SliceExpr, CastExpr, RevealExpr, UnaryExpr, ListExpr, TupleExpr, DictExpr, SetExpr,
88
IndexExpr, GeneratorExpr, ListComprehension, SetComprehension, DictionaryComprehension,
99
ConditionalExpr, TypeApplication, LambdaExpr, StarExpr, BackquoteExpr, AwaitExpr,
10+
AssignmentExpr,
1011
)
1112
from mypy.traverser import TraverserVisitor
1213

@@ -102,6 +103,10 @@ def visit_reveal_expr(self, e: RevealExpr) -> None:
102103
self.add(e)
103104
super().visit_reveal_expr(e)
104105

106+
def visit_assignment_expr(self, e: AssignmentExpr) -> None:
107+
self.add(e)
108+
super().visit_assignment_expr(e)
109+
105110
def visit_unary_expr(self, e: UnaryExpr) -> None:
106111
self.add(e)
107112
super().visit_unary_expr(e)

mypy/stats.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
from mypy import nodes
1616
from mypy.nodes import (
1717
Expression, FuncDef, TypeApplication, AssignmentStmt, NameExpr, CallExpr, MypyFile,
18-
MemberExpr, OpExpr, ComparisonExpr, IndexExpr, UnaryExpr, YieldFromExpr, RefExpr, ClassDef
18+
MemberExpr, OpExpr, ComparisonExpr, IndexExpr, UnaryExpr, YieldFromExpr, RefExpr, ClassDef,
19+
AssignmentExpr,
1920
)
2021

2122
MYPY = False
@@ -167,6 +168,10 @@ def visit_index_expr(self, o: IndexExpr) -> None:
167168
self.process_node(o)
168169
super().visit_index_expr(o)
169170

171+
def visit_assignment_expr(self, o: AssignmentExpr) -> None:
172+
self.process_node(o)
173+
super().visit_assignment_expr(o)
174+
170175
def visit_unary_expr(self, o: UnaryExpr) -> None:
171176
self.process_node(o)
172177
super().visit_unary_expr(o)

mypy/strconv.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,9 @@ def visit_reveal_expr(self, o: 'mypy.nodes.RevealExpr') -> str:
425425
# REVEAL_LOCALS
426426
return self.dump([o.local_nodes], o)
427427

428+
def visit_assignment_expr(self, o: 'mypy.nodes.AssignmentExpr') -> str:
429+
return self.dump([o.target, o.value], o)
430+
428431
def visit_unary_expr(self, o: 'mypy.nodes.UnaryExpr') -> str:
429432
return self.dump([o.op, o.expr], o)
430433

mypy/traverser.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
ExpressionStmt, AssignmentStmt, OperatorAssignmentStmt, WhileStmt,
77
ForStmt, ReturnStmt, AssertStmt, DelStmt, IfStmt, RaiseStmt,
88
TryStmt, WithStmt, NameExpr, MemberExpr, OpExpr, SliceExpr, CastExpr, RevealExpr,
9-
UnaryExpr, ListExpr, TupleExpr, DictExpr, SetExpr, IndexExpr,
9+
UnaryExpr, ListExpr, TupleExpr, DictExpr, SetExpr, IndexExpr, AssignmentExpr,
1010
GeneratorExpr, ListComprehension, SetComprehension, DictionaryComprehension,
1111
ConditionalExpr, TypeApplication, ExecStmt, Import, ImportFrom,
1212
LambdaExpr, ComparisonExpr, OverloadedFuncDef, YieldFromExpr,
@@ -193,6 +193,10 @@ def visit_reveal_expr(self, o: RevealExpr) -> None:
193193
# RevealLocalsExpr doesn't have an inner expression
194194
pass
195195

196+
def visit_assignment_expr(self, o: AssignmentExpr) -> None:
197+
o.target.accept(self)
198+
o.value.accept(self)
199+
196200
def visit_unary_expr(self, o: UnaryExpr) -> None:
197201
o.expr.accept(self)
198202

mypy/treetransform.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
ComparisonExpr, TempNode, StarExpr, Statement, Expression,
2020
YieldFromExpr, NamedTupleExpr, TypedDictExpr, NonlocalDecl, SetComprehension,
2121
DictionaryComprehension, ComplexExpr, TypeAliasExpr, EllipsisExpr,
22-
YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr,
22+
YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, AssignmentExpr,
2323
OverloadPart, EnumCallExpr, REVEAL_TYPE
2424
)
2525
from mypy.types import Type, FunctionLike
@@ -407,6 +407,9 @@ def visit_super_expr(self, node: SuperExpr) -> SuperExpr:
407407
new.info = node.info
408408
return new
409409

410+
def visit_assignment_expr(self, node: AssignmentExpr) -> AssignmentExpr:
411+
return AssignmentExpr(node.target, node.value)
412+
410413
def visit_unary_expr(self, node: UnaryExpr) -> UnaryExpr:
411414
new = UnaryExpr(node.op, self.expr(node.expr))
412415
new.method_type = self.optional_type(node.method_type)

mypy/visitor.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ def visit_super_expr(self, o: 'mypy.nodes.SuperExpr') -> T:
9090
def visit_unary_expr(self, o: 'mypy.nodes.UnaryExpr') -> T:
9191
pass
9292

93+
@abstractmethod
94+
def visit_assignment_expr(self, o: 'mypy.nodes.AssignmentExpr') -> T:
95+
pass
96+
9397
@abstractmethod
9498
def visit_list_expr(self, o: 'mypy.nodes.ListExpr') -> T:
9599
pass
@@ -473,6 +477,9 @@ def visit_reveal_expr(self, o: 'mypy.nodes.RevealExpr') -> T:
473477
def visit_super_expr(self, o: 'mypy.nodes.SuperExpr') -> T:
474478
pass
475479

480+
def visit_assignment_expr(self, o: 'mypy.nodes.AssignmentExpr') -> T:
481+
pass
482+
476483
def visit_unary_expr(self, o: 'mypy.nodes.UnaryExpr') -> T:
477484
pass
478485

test-data/unit/check-38.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,7 @@ def g(x: int): ...
106106
/
107107
0 # type: ignore
108108
) # type: ignore # E: unused 'type: ignore' comment
109+
110+
[case testWalrus]
111+
if (a := 2):
112+
reveal_type(a) # E: Revealed type is 'builtins.int'

0 commit comments

Comments
 (0)