@@ -1818,14 +1818,17 @@ def __init__(cls, *args, **kwargs):
1818
1818
def __subclasscheck__ (cls , other ):
1819
1819
if cls is Protocol :
1820
1820
return type .__subclasscheck__ (cls , other )
1821
- if not isinstance (other , type ):
1822
- # Same error message as for issubclass(1, int).
1823
- raise TypeError ('issubclass() arg 1 must be a class' )
1824
1821
if (
1825
1822
getattr (cls , '_is_protocol' , False )
1826
1823
and not _allow_reckless_class_checks ()
1827
1824
):
1828
- if not cls .__callable_proto_members_only__ :
1825
+ if not isinstance (other , type ):
1826
+ # Same error message as for issubclass(1, int).
1827
+ raise TypeError ('issubclass() arg 1 must be a class' )
1828
+ if (
1829
+ not cls .__callable_proto_members_only__
1830
+ and cls .__dict__ .get ("__subclasshook__" ) is _proto_hook
1831
+ ):
1829
1832
raise TypeError (
1830
1833
"Protocols with non-method members don't support issubclass()"
1831
1834
)
@@ -1869,6 +1872,30 @@ def __instancecheck__(cls, instance):
1869
1872
return False
1870
1873
1871
1874
1875
+ @classmethod
1876
+ def _proto_hook (cls , other ):
1877
+ if not cls .__dict__ .get ('_is_protocol' , False ):
1878
+ return NotImplemented
1879
+
1880
+ for attr in cls .__protocol_attrs__ :
1881
+ for base in other .__mro__ :
1882
+ # Check if the members appears in the class dictionary...
1883
+ if attr in base .__dict__ :
1884
+ if base .__dict__ [attr ] is None :
1885
+ return NotImplemented
1886
+ break
1887
+
1888
+ # ...or in annotations, if it is a sub-protocol.
1889
+ annotations = getattr (base , '__annotations__' , {})
1890
+ if (isinstance (annotations , collections .abc .Mapping ) and
1891
+ attr in annotations and
1892
+ issubclass (other , Generic ) and getattr (other , '_is_protocol' , False )):
1893
+ break
1894
+ else :
1895
+ return NotImplemented
1896
+ return True
<
6D40
/code>
1897
+
1898
+
1872
1899
class Protocol (Generic , metaclass = _ProtocolMeta ):
1873
1900
"""Base class for protocol classes.
1874
1901
@@ -1914,37 +1941,11 @@ def __init_subclass__(cls, *args, **kwargs):
1914
1941
cls ._is_protocol = any (b is Protocol for b in cls .__bases__ )
1915
1942
1916
1943
# Set (or override) the protocol subclass hook.
1917
- def _proto_hook (other ):
1918
- if not cls .__dict__ .get ('_is_protocol' , False ):
1919
- return NotImplemented
1920
-
1921
- for attr in cls .__protocol_attrs__ :
1922
- for base in other .__mro__ :
1923
- # Check if the members appears in the class dictionary...
1924
- if attr in base .__dict__ :
1925
- if base .__dict__ [attr ] is None :
1926
- return NotImplemented
1927
- break
1928
-
1929
- # ...or in annotations, if it is a sub-protocol.
1930
- annotations = getattr (base , '__annotations__' , {})
1931
- if (isinstance (annotations , collections .abc .Mapping ) and
1932
- attr in annotations and
1933
- issubclass (other , Generic ) and getattr (other , '_is_protocol' , False )):
1934
- break
1935
- else :
1936
- return NotImplemented
1937
- return True
1938
-
1939
1944
if '__subclasshook__' not in cls .__dict__ :
1940
1945
cls .__subclasshook__ = _proto_hook
1941
1946
1942
- # We have nothing more to do for non-protocols...
1943
- if not cls ._is_protocol :
1944
- return
1945
-
1946
- # ... otherwise prohibit instantiation.
1947
- if cls .__init__ is Protocol .__init__ :
1947
+ # Prohibit instantiation for protocol classes
1948
+ if cls ._is_protocol and cls .__init__ is Protocol .__init__ :
1948
1949
cls .__init__ = _no_init_or_replace_init
1949
1950
1950
1951
0 commit comments