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]
419
419
# Examples: ctypes.Array, ctypes._SimpleCData
420
420
pass
421
421
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
+
422
437
423
438
def _verify_metaclass (
424
439
stub : nodes .TypeInfo , runtime : type [Any ], object_path : list [str ]
@@ -1339,7 +1354,7 @@ def verify_typealias(
1339
1354
"__origin__" ,
1340
1355
"__args__" ,
1341
1356
"__orig_bases__" ,
1342
- "__final__" ,
1357
+ "__final__" , # Has a specialized check
1343
1358
# Consider removing __slots__?
1344
1359
"__slots__" ,
1345
1360
}
Original file line number Diff line number Diff line change @@ -1139,6 +1139,45 @@ def test_not_subclassable(self) -> Iterator[Case]:
1139
1139
error = "CannotBeSubclassed" ,
1140
1140
)
1141
1141
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
+
1142
1181
@collect_cases
1143
1182
def test_name_mangling (self ) -> Iterator [Case ]:
1144
1183
yield Case (
You can’t perform that action at this time.
0 commit comments