Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions mypy/nativeparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,14 +715,14 @@ def read_class_def(state: State, data: ReadBuffer) -> ClassDef:
keywords.append((key, value))

metaclass = dict(keywords).get("metaclass") if keywords else None
filtered_keywords = [(k, v) for k, v in keywords if k != "metaclass"] if keywords else None

class_def = ClassDef(
name,
body,
base_type_exprs=base_type_exprs if base_type_exprs else None,
metaclass=metaclass,
keywords=filtered_keywords,
# Note we keep metaclass in keywords as well, to match the old parser.
keywords=keywords if keywords else None,
type_args=type_params,
)
class_def.decorators = decorators
Expand Down Expand Up @@ -1329,15 +1329,16 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
op = bool_ops[read_int(data)]
values = read_expression_list(state, data)
# Convert list of values to nested OpExpr nodes
# E.g., [a, b, c] with "and" becomes OpExpr("and", OpExpr("and", a, b), c)
# E.g., [a, b, c] with "and" becomes OpExpr("and", a, OpExpr("and", b, c))
# This matches the old parser behavior, on which we may implicitly rely.
assert len(values) >= 2
result = values[0]
for val in values[1:]:
result = OpExpr(op, result, val)
result.line = values[0].line
result.column = values[0].column
result.end_line = val.end_line
result.end_column = val.end_column
result = last = values[-1]
for val in values[-2::-1]:
result = OpExpr(op, val, result)
result.line = val.line
result.column = val.column
result.end_line = last.end_line
result.end_column = last.end_column
read_loc(data, result)
expect_end_tag(data)
return result
Expand Down
2 changes: 1 addition & 1 deletion mypy/plugins/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ def collect_attributes(self) -> list[DataclassAttribute] | None:

# Allow bare x: Final[int] in class body, since it will be set in the generated
# __init__() method (unless it is an InitVar), to match regular class semantics.
if node.is_final and not node.is_classvar and node.final_unset_in_class:
if node.is_final and node.final_unset_in_class:
if is_init_var:
self._api.fail("InitVar cannot be final", stmt.rvalue)
else:
Expand Down
12 changes: 12 additions & 0 deletions test-data/unit/check-flags.test
Original file line number Diff line number Diff line change
Expand Up @@ -2705,3 +2705,15 @@ reveal_type(fx) # N: Revealed type is "def [Ts] (int, *args: *tuple[*Ts, int])
x = 1
[out]
main:1: error: --allow-redefinition-old and --allow-redefinition should not be used together

[case testRedundantExpressionMultiline]
# mypy: enable-error-code="redundant-expr"
x: int
y: int
z: int
if (
x is None # E: Left operand of "or" is always false
or y is None # E: Left operand of "or" is always false
or z is None
):
pass
13 changes: 7 additions & 6 deletions test-data/unit/native-parser.test
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,11 @@ MypyFile:1(
ExpressionStmt:2(
OpExpr:2(
and
NameExpr(a)
OpExpr:2(
and
NameExpr(a)
NameExpr(b))
NameExpr(c))))
NameExpr(b)
NameExpr(c)))))

[case testBoolOpOr]
x or y
Expand All @@ -280,11 +280,11 @@ MypyFile:1(
ExpressionStmt:2(
OpExpr:2(
or
IntExpr(1)
OpExpr:2(
or
IntExpr(1)
IntExpr(2))
IntExpr(3))))
IntExpr(2)
IntExpr(3)))))

[case testComparisonSimple]
a < b
Expand Down Expand Up @@ -1980,6 +1980,7 @@ class Foo(metaclass=Bar): pass
MypyFile:1(
ClassDef:1(
Foo
Keywords(metaclass=NameExpr(Bar))
Metaclass(NameExpr(Bar))
PassStmt:1()))

Expand Down
Loading