|
51 | 51 |
|
52 | 52 | from test.support import ( |
53 | 53 | captured_stderr, cpython_only, requires_docstrings, import_helper, run_code, |
54 | | - EqualToForwardRef, |
| 54 | + subTests, EqualToForwardRef, |
55 | 55 | ) |
56 | 56 | from test.typinganndata import ( |
57 | 57 | ann_module695, mod_generics_cache, _typed_dict_helper, |
@@ -3885,8 +3885,8 @@ def meth(self): pass |
3885 | 3885 | self.assertIsNot(get_protocol_members(PR), P.__protocol_attrs__) |
3886 | 3886 |
|
3887 | 3887 | acceptable_extra_attrs = { |
3888 | | - '_is_protocol', '_is_runtime_protocol', '__parameters__', |
3889 | | - '__init__', '__annotations__', '__subclasshook__', '__annotate__', |
| 3888 | + '_is_protocol', '_is_runtime_protocol', '_is_deprecated_inherited_runtime_protocol', |
| 3889 | + '__parameters__', '__init__', '__annotations__', '__subclasshook__', '__annotate__', |
3890 | 3890 | '__annotations_cache__', '__annotate_func__', |
3891 | 3891 | } |
3892 | 3892 | self.assertLessEqual(vars(NonP).keys(), vars(C).keys() | acceptable_extra_attrs) |
@@ -4458,6 +4458,68 @@ class P(Protocol): |
4458 | 4458 | with self.assertRaisesRegex(TypeError, "@runtime_checkable"): |
4459 | 4459 | isinstance(1, P) |
4460 | 4460 |
|
| 4461 | + @subTests(['check_obj', 'check_func'], ([42, isinstance], [frozenset, issubclass])) |
| 4462 | + def test_inherited_runtime_protocol_deprecated(self, check_obj, check_func): |
| 4463 | + """See GH-132604.""" |
| 4464 | + |
| 4465 | + class BareProto(Protocol): |
| 4466 | + """I am runtime uncheckable.""" |
| 4467 | + |
| 4468 | + @runtime_checkable |
| 4469 | + class RCProto1(Protocol): |
| 4470 | + """I am runtime-checkable.""" |
| 4471 | + |
| 4472 | + @runtime_checkable |
| 4473 | + class RCProto3(BareProto, Protocol): |
| 4474 | + """Bare -> explicit RC.""" |
| 4475 | + |
| 4476 | + class InheritedRCProto1(RCProto1, Protocol): |
| 4477 | + """Bare, but runtime-checkability is "inherited".""" |
| 4478 | + |
| 4479 | + @runtime_checkable |
| 4480 | + class RCProto2(InheritedRCProto1, Protocol): |
| 4481 | + """Explicit RC -> inherited RC -> explicit RC.""" |
| 4482 | + |
| 4483 | + class InheritedRCProto2(RCProto3, Protocol): |
| 4484 | + """Bare -> explicit RC -> inherited RC.""" |
| 4485 | + |
| 4486 | + class InheritedRCProto3(RCProto2, Protocol): |
| 4487 | + """Explicit RC -> inherited RC -> explicit RC -> inherited RC.""" |
| 4488 | + |
| 4489 | + class Concrete1(BareProto): |
| 4490 | + pass |
| 4491 | + |
| 4492 | + class Concrete2(InheritedRCProto3): |
| 4493 | + pass |
| 4494 | + |
| 4495 | + class Concrete3(InheritedRCProto3): |
| 4496 | + pass |
| 4497 | + |
| 4498 | + depr_message_re = ( |
| 4499 | + r"<class .+\.InheritedRCProto\d'> isn't explicitly decorated " |
| 4500 | + r"with @runtime_checkable but it is used in issubclass\(\) or " |
| 4501 | + r"isinstance\(\). Instance and class checks can only be used with " |
| 4502 | + r"@runtime_checkable protocols. This may stop working in Python 3.20." |
| 4503 | + ) |
| 4504 | + |
| 4505 | + for inherited_runtime_proto in InheritedRCProto1, InheritedRCProto2, InheritedRCProto3: |
| 4506 | + with self.assertWarnsRegex(DeprecationWarning, depr_message_re): |
| 4507 | + isinstance(object(), inherited_runtime_proto) |
| 4508 | + |
| 4509 | + # Don't warn for explicitly checkable protocols and concrete implementations. |
| 4510 | + with warnings.catch_warnings(): |
| 4511 | + warnings.simplefilter("error", DeprecationWarning) |
| 4512 | + |
| 4513 | + for explicit_runtime_proto in RCProto1, RCProto2, RCProto3, Concrete1, Concrete2, Concrete3: |
| 4514 | + isinstance(object(), explicit_runtime_proto) |
| 4515 | + |
| 4516 | + # Don't warn for uncheckable protocols. |
| 4517 | + with warnings.catch_warnings(): |
| 4518 | + warnings.simplefilter("error", DeprecationWarning) |
| 4519 | + |
| 4520 | + with self.assertRaises(TypeError): # Self-test. Protocol below can't be runtime-checkable. |
| 4521 | + isinstance(object(), BareProto) |
| 4522 | + |
4461 | 4523 | def test_super_call_init(self): |
4462 | 4524 | class P(Protocol): |
4463 | 4525 | x: int |
|
0 commit comments