Skip to content

Commit 9a4a5aa

Browse files
authored
Process NamedTuple decorators in semantic analyzer (#15513)
1 parent fca4cae commit 9a4a5aa

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

mypy/semanal.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,10 @@ def analyze_namedtuple_classdef(
17441744
self.setup_type_vars(defn, tvar_defs)
17451745
self.setup_alias_type_vars(defn)
17461746
with self.scope.class_scope(defn.info):
1747+
for deco in defn.decorators:
1748+
deco.accept(self)
1749+
if isinstance(deco, RefExpr) and deco.fullname in FINAL_DECORATOR_NAMES:
1750+
info.is_final = True
17471751
with self.named_tuple_analyzer.save_namedtuple_body(info):
17481752
self.analyze_class_body_common(defn)
17491753
return True

mypyc/test-data/run-tuples.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ assert f(Sub(3, 2)) == 3
9898
-- Ref: https://github.com/mypyc/mypyc/issues/924
9999
[case testNamedTupleClassSyntax]
100100
from typing import Dict, List, NamedTuple, Optional, Tuple, Union
101+
from typing_extensions import final
101102

102103
class FuncIR: pass
103104

@@ -121,6 +122,11 @@ class Record(NamedTuple):
121122
# Ref: https://github.com/mypyc/mypyc/issues/938
122123
class ClassIR: pass
123124

125+
# Ref: https://github.com/mypyc/mypyc/issues/927
126+
@final
127+
class Inextensible(NamedTuple):
128+
x: int
129+
124130
[file driver.py]
125131
from typing import ForwardRef, Optional
126132
from native import ClassIR, FuncIR, Record

test-data/unit/semanal-namedtuple.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,23 @@ class B(A): pass
225225
[out]
226226
main:2: error: Unsupported dynamic base class "NamedTuple"
227227
main:2: error: Name "NamedTuple" is not defined
228+
229+
[case testNamedTupleWithDecorator]
230+
from typing import final, NamedTuple
231+
232+
@final
233+
class A(NamedTuple("N", [("x", int)])):
234+
pass
235+
[builtins fixtures/tuple.pyi]
236+
[out]
237+
MypyFile:1(
238+
ImportFrom:1(typing, [final, NamedTuple])
239+
ClassDef:4(
240+
A
241+
TupleType(
242+
Tuple[builtins.int, fallback=__main__.N@4])
243+
Decorators(
244+
NameExpr(final [typing.final]))
245+
BaseType(
246+
__main__.N@4)
247+
PassStmt:5()))

0 commit comments

Comments
 (0)