mirror of
https://github.com/python/cpython
synced 2024-09-15 23:57:10 +00:00
gh-112345: typing.Protocol
: Let failed subclasscheck show non-method members (#112344)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
d9fc15222e
commit
e9d1360c9a
|
@ -4091,6 +4091,22 @@ def method(self) -> None: ...
|
|||
self.assertIsInstance(Foo(), ProtocolWithMixedMembers)
|
||||
self.assertNotIsInstance(42, ProtocolWithMixedMembers)
|
||||
|
||||
def test_protocol_issubclass_error_message(self):
|
||||
class Vec2D(Protocol):
|
||||
x: float
|
||||
y: float
|
||||
|
||||
def square_norm(self) -> float:
|
||||
return self.x ** 2 + self.y ** 2
|
||||
|
||||
self.assertEqual(Vec2D.__protocol_attrs__, {'x', 'y', 'square_norm'})
|
||||
expected_error_message = (
|
||||
"Protocols with non-method members don't support issubclass()."
|
||||
" Non-method members: 'x', 'y'."
|
||||
)
|
||||
with self.assertRaisesRegex(TypeError, re.escape(expected_error_message)):
|
||||
issubclass(int, Vec2D)
|
||||
|
||||
|
||||
class GenericTests(BaseTestCase):
|
||||
|
||||
|
|
|
@ -1828,8 +1828,13 @@ def __subclasscheck__(cls, other):
|
|||
not cls.__callable_proto_members_only__
|
||||
and cls.__dict__.get("__subclasshook__") is _proto_hook
|
||||
):
|
||||
non_method_attrs = sorted(
|
||||
attr for attr in cls.__protocol_attrs__
|
||||
if not callable(getattr(cls, attr, None))
|
||||
)
|
||||
raise TypeError(
|
||||
"Protocols with non-method members don't support issubclass()"
|
||||
"Protocols with non-method members don't support issubclass()."
|
||||
f" Non-method members: {str(non_method_attrs)[1:-1]}."
|
||||
)
|
||||
if not getattr(cls, '_is_runtime_protocol', False):
|
||||
raise TypeError(
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Improve error message when trying to call :func:`issubclass` against a
|
||||
:class:`typing.Protocol` that has non-method members.
|
||||
Patch by Randolf Scholz.
|
Loading…
Reference in a new issue