| 
									
										
										
										
											2007-06-14 00:03:37 +00:00
										 |  |  | # Copyright 2007 Google, Inc. All Rights Reserved. | 
					
						
							|  |  |  | # Licensed to PSF under a Contributor Agreement. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """Abstract Base Classes (ABCs) according to PEP 3119.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-25 18:41:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-14 00:03:37 +00:00
										 |  |  | def abstractmethod(funcobj): | 
					
						
							|  |  |  |     """A decorator indicating abstract methods.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Requires that the metaclass is ABCMeta or derived from it.  A | 
					
						
							|  |  |  |     class that has a metaclass derived from ABCMeta cannot be | 
					
						
							|  |  |  |     instantiated unless all of its abstract methods are overridden. | 
					
						
							| 
									
										
										
										
											2009-05-04 16:10:10 +00:00
										 |  |  |     The abstract methods can be called using any of the normal | 
					
						
							| 
									
										
										
										
											2018-12-31 09:56:21 +02:00
										 |  |  |     'super' call mechanisms.  abstractmethod() may be used to declare | 
					
						
							|  |  |  |     abstract methods for properties and descriptors. | 
					
						
							| 
									
										
										
										
											2007-06-14 00:03:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Usage: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class C(metaclass=ABCMeta): | 
					
						
							|  |  |  |             @abstractmethod | 
					
						
							|  |  |  |             def my_abstract_method(self, ...): | 
					
						
							|  |  |  |                 ... | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     funcobj.__isabstractmethod__ = True | 
					
						
							|  |  |  |     return funcobj | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-17 00:52:52 +00:00
										 |  |  | class abstractclassmethod(classmethod): | 
					
						
							| 
									
										
										
										
											2018-02-18 12:41:58 +00:00
										 |  |  |     """A decorator indicating abstract classmethods.
 | 
					
						
							| 
									
										
										
										
											2010-08-17 00:52:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 09:56:21 +02:00
										 |  |  |     Deprecated, use 'classmethod' with 'abstractmethod' instead. | 
					
						
							| 
									
										
										
										
											2010-08-17 00:52:52 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __isabstractmethod__ = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, callable): | 
					
						
							|  |  |  |         callable.__isabstractmethod__ = True | 
					
						
							|  |  |  |         super().__init__(callable) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class abstractstaticmethod(staticmethod): | 
					
						
							| 
									
										
										
										
											2018-02-18 12:41:58 +00:00
										 |  |  |     """A decorator indicating abstract staticmethods.
 | 
					
						
							| 
									
										
										
										
											2010-08-17 00:52:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 09:56:21 +02:00
										 |  |  |     Deprecated, use 'staticmethod' with 'abstractmethod' instead. | 
					
						
							| 
									
										
										
										
											2010-08-17 00:52:52 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __isabstractmethod__ = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, callable): | 
					
						
							|  |  |  |         callable.__isabstractmethod__ = True | 
					
						
							|  |  |  |         super().__init__(callable) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-01 17:32:28 +00:00
										 |  |  | class abstractproperty(property): | 
					
						
							| 
									
										
										
										
											2018-02-18 12:41:58 +00:00
										 |  |  |     """A decorator indicating abstract properties.
 | 
					
						
							| 
									
										
										
										
											2007-08-01 17:32:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 09:56:21 +02:00
										 |  |  |     Deprecated, use 'property' with 'abstractmethod' instead. | 
					
						
							| 
									
										
										
										
											2007-08-01 17:32:28 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2011-12-15 15:34:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-01 17:32:28 +00:00
										 |  |  |     __isabstractmethod__ = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-18 12:41:58 +00:00
										 |  |  | try: | 
					
						
							|  |  |  |     from _abc import (get_cache_token, _abc_init, _abc_register, | 
					
						
							|  |  |  |                       _abc_instancecheck, _abc_subclasscheck, _get_dump, | 
					
						
							|  |  |  |                       _reset_registry, _reset_caches) | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     from _py_abc import ABCMeta, get_cache_token | 
					
						
							|  |  |  |     ABCMeta.__module__ = 'abc' | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     class ABCMeta(type): | 
					
						
							|  |  |  |         """Metaclass for defining Abstract Base Classes (ABCs).
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Use this metaclass to create an ABC.  An ABC can be subclassed | 
					
						
							|  |  |  |         directly, and then acts as a mix-in class.  You can also register | 
					
						
							|  |  |  |         unrelated concrete classes (even built-in classes) and unrelated | 
					
						
							|  |  |  |         ABCs as 'virtual subclasses' -- these and their descendants will | 
					
						
							|  |  |  |         be considered subclasses of the registering ABC by the built-in | 
					
						
							|  |  |  |         issubclass() function, but the registering ABC won't show up in | 
					
						
							|  |  |  |         their MRO (Method Resolution Order) nor will method | 
					
						
							|  |  |  |         implementations defined by the registering ABC be callable (not | 
					
						
							|  |  |  |         even via super()). | 
					
						
							| 
									
										
										
										
											2011-02-24 18:03:10 +00:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2018-02-18 12:41:58 +00:00
										 |  |  |         def __new__(mcls, name, bases, namespace, **kwargs): | 
					
						
							|  |  |  |             cls = super().__new__(mcls, name, bases, namespace, **kwargs) | 
					
						
							|  |  |  |             _abc_init(cls) | 
					
						
							|  |  |  |             return cls | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def register(cls, subclass): | 
					
						
							|  |  |  |             """Register a virtual subclass of an ABC.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Returns the subclass, to allow usage as a class decorator. | 
					
						
							|  |  |  |             """
 | 
					
						
							|  |  |  |             return _abc_register(cls, subclass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __instancecheck__(cls, instance): | 
					
						
							|  |  |  |             """Override for isinstance(instance, cls).""" | 
					
						
							|  |  |  |             return _abc_instancecheck(cls, instance) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __subclasscheck__(cls, subclass): | 
					
						
							|  |  |  |             """Override for issubclass(subclass, cls).""" | 
					
						
							|  |  |  |             return _abc_subclasscheck(cls, subclass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def _dump_registry(cls, file=None): | 
					
						
							|  |  |  |             """Debug helper to print the ABC registry.""" | 
					
						
							|  |  |  |             print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) | 
					
						
							|  |  |  |             print(f"Inv. counter: {get_cache_token()}", file=file) | 
					
						
							|  |  |  |             (_abc_registry, _abc_cache, _abc_negative_cache, | 
					
						
							|  |  |  |              _abc_negative_cache_version) = _get_dump(cls) | 
					
						
							|  |  |  |             print(f"_abc_registry: {_abc_registry!r}", file=file) | 
					
						
							|  |  |  |             print(f"_abc_cache: {_abc_cache!r}", file=file) | 
					
						
							|  |  |  |             print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file) | 
					
						
							|  |  |  |             print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}", | 
					
						
							|  |  |  |                   file=file) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def _abc_registry_clear(cls): | 
					
						
							|  |  |  |             """Clear the registry (for debugging or testing).""" | 
					
						
							|  |  |  |             _reset_registry(cls) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def _abc_caches_clear(cls): | 
					
						
							|  |  |  |             """Clear the caches (for debugging or testing).""" | 
					
						
							|  |  |  |             _reset_caches(cls) | 
					
						
							| 
									
										
										
										
											2012-12-13 19:09:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-25 18:41:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 20:40:50 +03:00
										 |  |  | def update_abstractmethods(cls): | 
					
						
							|  |  |  |     """Recalculate the set of abstract methods of an abstract class.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If a class has had one of its abstract methods implemented after the | 
					
						
							|  |  |  |     class was created, the method will not be considered implemented until | 
					
						
							|  |  |  |     this function is called. Alternatively, if a new abstract method has been | 
					
						
							|  |  |  |     added to the class, it will only be considered an abstract method of the | 
					
						
							|  |  |  |     class after this function is called. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This function should be called before any use is made of the class, | 
					
						
							|  |  |  |     usually in class decorators that add methods to the subject class. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Returns cls, to allow usage as a class decorator. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If cls is not an instance of ABCMeta, does nothing. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not hasattr(cls, '__abstractmethods__'): | 
					
						
							|  |  |  |         # We check for __abstractmethods__ here because cls might by a C | 
					
						
							|  |  |  |         # implementation or a python implementation (especially during | 
					
						
							|  |  |  |         # testing), and we want to handle both cases. | 
					
						
							|  |  |  |         return cls | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     abstracts = set() | 
					
						
							|  |  |  |     # Check the existing abstract methods of the parents, keep only the ones | 
					
						
							|  |  |  |     # that are not implemented. | 
					
						
							|  |  |  |     for scls in cls.__bases__: | 
					
						
							|  |  |  |         for name in getattr(scls, '__abstractmethods__', ()): | 
					
						
							|  |  |  |             value = getattr(cls, name, None) | 
					
						
							|  |  |  |             if getattr(value, "__isabstractmethod__", False): | 
					
						
							|  |  |  |                 abstracts.add(name) | 
					
						
							|  |  |  |     # Also add any other newly added abstract methods. | 
					
						
							|  |  |  |     for name, value in cls.__dict__.items(): | 
					
						
							|  |  |  |         if getattr(value, "__isabstractmethod__", False): | 
					
						
							|  |  |  |             abstracts.add(name) | 
					
						
							|  |  |  |     cls.__abstractmethods__ = frozenset(abstracts) | 
					
						
							|  |  |  |     return cls | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-13 19:09:33 +02:00
										 |  |  | class ABC(metaclass=ABCMeta): | 
					
						
							|  |  |  |     """Helper class that provides a standard way to create an ABC using
 | 
					
						
							|  |  |  |     inheritance. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2017-06-06 15:34:57 -04:00
										 |  |  |     __slots__ = () |