mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	bpo-38908: Fix issue when non runtime_protocol failed to raise TypeError (#26067)
This commit is contained in:
		
							parent
							
								
									9b06e4b535
								
							
						
					
					
						commit
						c40486a32d
					
				
					 3 changed files with 23 additions and 2 deletions
				
			
		|  | @ -1422,6 +1422,14 @@ class CustomProtocol(TestCase, Protocol): | |||
|         class CustomContextManager(typing.ContextManager, Protocol): | ||||
|             pass | ||||
| 
 | ||||
|     def test_non_runtime_protocol_isinstance_check(self): | ||||
|         class P(Protocol): | ||||
|             x: int | ||||
| 
 | ||||
|         with self.assertRaisesRegex(TypeError, "@runtime_checkable"): | ||||
|             isinstance(1, P) | ||||
| 
 | ||||
| 
 | ||||
| class GenericTests(BaseTestCase): | ||||
| 
 | ||||
|     def test_basics(self): | ||||
|  |  | |||
|  | @ -1343,14 +1343,14 @@ def _no_init(self, *args, **kwargs): | |||
|         raise TypeError('Protocols cannot be instantiated') | ||||
| 
 | ||||
| 
 | ||||
| def _allow_reckless_class_checks(): | ||||
| def _allow_reckless_class_checks(depth=3): | ||||
|     """Allow instance and class checks for special stdlib modules. | ||||
| 
 | ||||
|     The abc and functools modules indiscriminately call isinstance() and | ||||
|     issubclass() on the whole MRO of a user class, which may contain protocols. | ||||
|     """ | ||||
|     try: | ||||
|         return sys._getframe(3).f_globals['__name__'] in ['abc', 'functools'] | ||||
|         return sys._getframe(depth).f_globals['__name__'] in ['abc', 'functools'] | ||||
|     except (AttributeError, ValueError):  # For platforms without _getframe(). | ||||
|         return True | ||||
| 
 | ||||
|  | @ -1370,6 +1370,14 @@ class _ProtocolMeta(ABCMeta): | |||
|     def __instancecheck__(cls, instance): | ||||
|         # We need this method for situations where attributes are | ||||
|         # assigned in __init__. | ||||
|         if ( | ||||
|             getattr(cls, '_is_protocol', False) and | ||||
|             not getattr(cls, '_is_runtime_protocol', False) and | ||||
|             not _allow_reckless_class_checks(depth=2) | ||||
|         ): | ||||
|             raise TypeError("Instance and class checks can only be used with" | ||||
|                             " @runtime_checkable protocols") | ||||
| 
 | ||||
|         if ((not getattr(cls, '_is_protocol', False) or | ||||
|                 _is_callable_members_only(cls)) and | ||||
|                 issubclass(instance.__class__, cls)): | ||||
|  |  | |||
|  | @ -0,0 +1,5 @@ | |||
| Fix issue where :mod:`typing` protocols without the  ``@runtime_checkable`` | ||||
| decorator did not raise a ``TypeError`` when used with ``issubclass`` and | ||||
| ``isinstance``.  Now, subclassses of ``typing.Protocol`` will raise a | ||||
| ``TypeError`` when used with with those checks. | ||||
| Patch provided by Yurii Karabas. | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Yurii Karabas
						Yurii Karabas