File tree Expand file tree Collapse file tree 2 files changed +55
-1
lines changed
Expand file tree Collapse file tree 2 files changed +55
-1
lines changed Original file line number Diff line number Diff line change @@ -419,6 +419,21 @@ class SubClass(runtime): # type: ignore[misc]
419419 # Examples: ctypes.Array, ctypes._SimpleCData
420420 pass
421421
422+ # Runtime class might be annotated with `@final`:
423+ try :
424+ runtime_final = getattr (runtime , "__final__" , False )
425+ except Exception :
426+ runtime_final = False
427+
428+ if runtime_final and not stub .is_final :
429+ yield Error (
430+ object_path ,
431+ "has `__final__` attribute, but isn't marked with @final in the stub" ,
432+ stub ,
433+ runtime ,
434+ stub_desc = repr (stub ),
435+ )
436+
422437
423438def _verify_metaclass (
424439 stub : nodes .TypeInfo , runtime : type [Any ], object_path : list [str ]
@@ -1339,7 +1354,7 @@ def verify_typealias(
13391354 "__origin__" ,
13401355 "__args__" ,
13411356 "__orig_bases__" ,
1342- "__final__" ,
1357+ "__final__" , # Has a specialized check
13431358 # Consider removing __slots__?
13441359 "__slots__" ,
13451360 }
Original file line number Diff line number Diff line change @@ -1139,6 +1139,45 @@ def test_not_subclassable(self) -> Iterator[Case]:
11391139 error = "CannotBeSubclassed" ,
11401140 )
11411141
1142+ @collect_cases
1143+ def test_has_runtime_final_decorator (self ) -> Iterator [Case ]:
1144+ yield Case (
1145+ stub = "from typing_extensions import final" ,
1146+ runtime = "from typing_extensions import final" ,
1147+ error = None ,
1148+ )
1149+ yield Case (
1150+ stub = """
1151+ @final
1152+ class A: ...
1153+ """ ,
1154+ runtime = """
1155+ @final
1156+ class A: ...
1157+ """ ,
1158+ error = None ,
1159+ )
1160+ yield Case ( # Runtime can miss `@final` decorator
1161+ stub = """
1162+ @final
1163+ class B: ...
1164+ """ ,
1165+ runtime = """
1166+ class B: ...
1167+ """ ,
1168+ error = None ,
1169+ )
1170+ yield Case ( # Stub cannot miss `@final` decorator
1171+ stub = """
1172+ class C: ...
1173+ """ ,
1174+ runtime = """
1175+ @final
1176+ class C: ...
1177+ """ ,
1178+ error = "C" ,
1179+ )
1180+
11421181 @collect_cases
11431182 def test_name_mangling (self ) -> Iterator [Case ]:
11441183 yield Case (
You can’t perform that action at this time.
0 commit comments