File tree 3 files changed +38
-4
lines changed
Filter options
3 files changed +38
-4
lines changed
Original file line number Diff line number Diff line change @@ -4554,6 +4554,33 @@ class Commentable(Protocol):
4554
4554
)
4555
4555
self .assertIs (type (exc .__cause__ ), CustomError )
4556
4556
4557
+ def test_isinstance_with_deferred_evaluation_of_annotations (self ):
4558
+ @runtime_checkable
4559
+ class P (Protocol ):
4560
+ def meth (self ):
4561
+ ...
4562
+
4563
+ class DeferredClass :
4564
+ x : undefined
4565
+
4566
+ class DeferredClassImplementingP :
4567
+ x : undefined | int
4568
+
4569
+ def __init__ (self ):
4570
+ self .x = 0
4571
+
4572
+ def meth (self ):
4573
+ ...
4574
+
4575
+ # override meth with a non-method attribute to make it part of __annotations__ instead of __dict__
4576
+ class SubProtocol (P , Protocol ):
4577
+ meth : undefined
4578
+
4579
+
4580
+ self .assertIsSubclass (SubProtocol , P )
4581
+ self .assertNotIsInstance (DeferredClass (), P )
4582
+ self .assertIsInstance (DeferredClassImplementingP (), P )
4583
+
4557
4584
def test_deferred_evaluation_of_annotations (self ):
4558
4585
class DeferredProto (Protocol ):
4559
4586
x : DoesNotExist
Original file line number Diff line number Diff line change @@ -2020,10 +2020,13 @@ def _proto_hook(cls, other):
2020
2020
break
2021
2021
2022
2022
# ...or in annotations, if it is a sub-protocol.
2023
- annotations = getattr (base , '__annotations__' , {})
2024
- if (isinstance (annotations , collections .abc .Mapping ) and
2025
- attr in annotations and
2026
- issubclass (other , Generic ) and getattr (other , '_is_protocol' , False )):
2023
+ if (
2024
+ issubclass (other , Generic )
2025
+ and getattr (other , "_is_protocol" , False )
2026
+ and attr in _lazy_annotationlib .get_annotations (
2027
+ base , format = _lazy_annotationlib .Format .FORWARDREF
2028
+ )
2029
+ ):
2027
2030
break
2028
2031
else :
2029
2032
return NotImplemented
Original file line number Diff line number Diff line change
1
+ :class: `typing.Protocol ` now uses :func: `annotationlib.get_annotations ` when
2
+ checking whether or not an instance implements the protocol with
3
+ :func: `isinstance `. This enables support for ``isinstance `` checks against
4
+ classes with deferred annotations.
You can’t perform that action at this time.
0 commit comments