diff --git a/mypy/semanal.py b/mypy/semanal.py index d18cc4298fed..1eb14e499e4d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1744,6 +1744,10 @@ def analyze_namedtuple_classdef( self.setup_type_vars(defn, tvar_defs) self.setup_alias_type_vars(defn) with self.scope.class_scope(defn.info): + for deco in defn.decorators: + deco.accept(self) + if isinstance(deco, RefExpr) and deco.fullname in FINAL_DECORATOR_NAMES: + info.is_final = True with self.named_tuple_analyzer.save_namedtuple_body(info): self.analyze_class_body_common(defn) return True diff --git a/mypyc/test-data/run-tuples.test b/mypyc/test-data/run-tuples.test index f6c92b9c720f..0851c15e57fd 100644 --- a/mypyc/test-data/run-tuples.test +++ b/mypyc/test-data/run-tuples.test @@ -98,6 +98,7 @@ assert f(Sub(3, 2)) == 3 -- Ref: https://github.com/mypyc/mypyc/issues/924 [case testNamedTupleClassSyntax] from typing import Dict, List, NamedTuple, Optional, Tuple, Union +from typing_extensions import final class FuncIR: pass @@ -121,6 +122,11 @@ class Record(NamedTuple): # Ref: https://github.com/mypyc/mypyc/issues/938 class ClassIR: pass +# Ref: https://github.com/mypyc/mypyc/issues/927 +@final +class Inextensible(NamedTuple): + x: int + [file driver.py] from typing import ForwardRef, Optional from native import ClassIR, FuncIR, Record diff --git a/test-data/unit/semanal-namedtuple.test b/test-data/unit/semanal-namedtuple.test index df1d5679c892..f396f799028f 100644 --- a/test-data/unit/semanal-namedtuple.test +++ b/test-data/unit/semanal-namedtuple.test @@ -225,3 +225,23 @@ class B(A): pass [out] main:2: error: Unsupported dynamic base class "NamedTuple" main:2: error: Name "NamedTuple" is not defined + +[case testNamedTupleWithDecorator] +from typing import final, NamedTuple + +@final +class A(NamedTuple("N", [("x", int)])): + pass +[builtins fixtures/tuple.pyi] +[out] +MypyFile:1( + ImportFrom:1(typing, [final, NamedTuple]) + ClassDef:4( + A + TupleType( + Tuple[builtins.int, fallback=__main__.N@4]) + Decorators( + NameExpr(final [typing.final])) + BaseType( + __main__.N@4) + PassStmt:5()))