mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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): |         class CustomContextManager(typing.ContextManager, Protocol): | ||||||
|             pass |             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): | class GenericTests(BaseTestCase): | ||||||
| 
 | 
 | ||||||
|     def test_basics(self): |     def test_basics(self): | ||||||
|  |  | ||||||
|  | @ -1343,14 +1343,14 @@ def _no_init(self, *args, **kwargs): | ||||||
|         raise TypeError('Protocols cannot be instantiated') |         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. |     """Allow instance and class checks for special stdlib modules. | ||||||
| 
 | 
 | ||||||
|     The abc and functools modules indiscriminately call isinstance() and |     The abc and functools modules indiscriminately call isinstance() and | ||||||
|     issubclass() on the whole MRO of a user class, which may contain protocols. |     issubclass() on the whole MRO of a user class, which may contain protocols. | ||||||
|     """ |     """ | ||||||
|     try: |     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(). |     except (AttributeError, ValueError):  # For platforms without _getframe(). | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
|  | @ -1370,6 +1370,14 @@ class _ProtocolMeta(ABCMeta): | ||||||
|     def __instancecheck__(cls, instance): |     def __instancecheck__(cls, instance): | ||||||
|         # We need this method for situations where attributes are |         # We need this method for situations where attributes are | ||||||
|         # assigned in __init__. |         # 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 |         if ((not getattr(cls, '_is_protocol', False) or | ||||||
|                 _is_callable_members_only(cls)) and |                 _is_callable_members_only(cls)) and | ||||||
|                 issubclass(instance.__class__, cls)): |                 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