From 11a802773eae6a67a69aae9b81f2ddd050be3dc6 Mon Sep 17 00:00:00 2001 From: Giorgos Papoutsakis Date: Fri, 31 May 2024 21:54:28 +0300 Subject: [PATCH 1/2] Fix false positive in Final local scope variable --- mypy/semanal.py | 3 ++- test-data/unit/check-final.test | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 0689d5416efe..fe600b25029e 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3505,7 +3505,8 @@ def unwrap_final(self, s: AssignmentStmt) -> bool: if self.loop_depth[-1] > 0: self.fail("Cannot use Final inside a loop", s) if self.type and self.type.is_protocol: - self.msg.protocol_members_cant_be_final(s) + if self.is_class_scope(): + self.msg.protocol_members_cant_be_final(s) if ( isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs diff --git a/test-data/unit/check-final.test b/test-data/unit/check-final.test index 26a0d0782503..271c7772dffe 100644 --- a/test-data/unit/check-final.test +++ b/test-data/unit/check-final.test @@ -301,6 +301,37 @@ class P(Protocol): pass [out] +[case testFinalInProtocol] +from typing import Protocol, Final, final, ClassVar + +class P(Protocol): + var1 : Final[int] = 0 # E: Protocol member cannot be final + + @final # E: Protocol member cannot be final + def meth1(self) -> None: + var2: Final = 0 + + def meth2(self) -> None: + var3: Final = 0 + +[out] + +[case testFinalWithClassVarInProtocol] +from typing import Protocol, Final, final, ClassVar + +class P(Protocol): + var1 : Final[ClassVar[int]] = 0 # E: Variable should not be annotated with both ClassVar and Final + var2: ClassVar[int] = 1 + + @final # E: Protocol member cannot be final + def meth1(self) -> None: + ... + + def meth2(self) -> None: + var3: Final[ClassVar[int]] = 0 # E: Variable should not be annotated with both ClassVar and Final # E: ClassVar can only be used for assignments in class body + +[out] + [case testFinalNotInLoops] from typing import Final From 4a33469286ff8551341d800c92e097bddc9a2655 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 4 Jun 2024 12:15:32 -0700 Subject: [PATCH 2/2] Add test case Co-Authored-By: Stanislav Terliakov --- test-data/unit/check-final.test | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test-data/unit/check-final.test b/test-data/unit/check-final.test index 271c7772dffe..dadf76a283b0 100644 --- a/test-data/unit/check-final.test +++ b/test-data/unit/check-final.test @@ -302,7 +302,7 @@ class P(Protocol): [out] [case testFinalInProtocol] -from typing import Protocol, Final, final, ClassVar +from typing import Final, Protocol, final class P(Protocol): var1 : Final[int] = 0 # E: Protocol member cannot be final @@ -314,6 +314,19 @@ class P(Protocol): def meth2(self) -> None: var3: Final = 0 + def meth3(self) -> None: + class Inner: + var3: Final = 0 # OK + + @final + def inner(self) -> None: ... + + class Inner: + var3: Final = 0 # OK + + @final + def inner(self) -> None: ... + [out] [case testFinalWithClassVarInProtocol]