1*cda5da8dSAndroid Build Coastguard Worker# Copyright 2007 Google, Inc. All Rights Reserved. 2*cda5da8dSAndroid Build Coastguard Worker# Licensed to PSF under a Contributor Agreement. 3*cda5da8dSAndroid Build Coastguard Worker 4*cda5da8dSAndroid Build Coastguard Worker"""Abstract Base Classes (ABCs) according to PEP 3119.""" 5*cda5da8dSAndroid Build Coastguard Worker 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Workerdef abstractmethod(funcobj): 8*cda5da8dSAndroid Build Coastguard Worker """A decorator indicating abstract methods. 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard Worker Requires that the metaclass is ABCMeta or derived from it. A 11*cda5da8dSAndroid Build Coastguard Worker class that has a metaclass derived from ABCMeta cannot be 12*cda5da8dSAndroid Build Coastguard Worker instantiated unless all of its abstract methods are overridden. 13*cda5da8dSAndroid Build Coastguard Worker The abstract methods can be called using any of the normal 14*cda5da8dSAndroid Build Coastguard Worker 'super' call mechanisms. abstractmethod() may be used to declare 15*cda5da8dSAndroid Build Coastguard Worker abstract methods for properties and descriptors. 16*cda5da8dSAndroid Build Coastguard Worker 17*cda5da8dSAndroid Build Coastguard Worker Usage: 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard Worker class C(metaclass=ABCMeta): 20*cda5da8dSAndroid Build Coastguard Worker @abstractmethod 21*cda5da8dSAndroid Build Coastguard Worker def my_abstract_method(self, arg1, arg2, argN): 22*cda5da8dSAndroid Build Coastguard Worker ... 23*cda5da8dSAndroid Build Coastguard Worker """ 24*cda5da8dSAndroid Build Coastguard Worker funcobj.__isabstractmethod__ = True 25*cda5da8dSAndroid Build Coastguard Worker return funcobj 26*cda5da8dSAndroid Build Coastguard Worker 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard Workerclass abstractclassmethod(classmethod): 29*cda5da8dSAndroid Build Coastguard Worker """A decorator indicating abstract classmethods. 30*cda5da8dSAndroid Build Coastguard Worker 31*cda5da8dSAndroid Build Coastguard Worker Deprecated, use 'classmethod' with 'abstractmethod' instead: 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker class C(ABC): 34*cda5da8dSAndroid Build Coastguard Worker @classmethod 35*cda5da8dSAndroid Build Coastguard Worker @abstractmethod 36*cda5da8dSAndroid Build Coastguard Worker def my_abstract_classmethod(cls, ...): 37*cda5da8dSAndroid Build Coastguard Worker ... 38*cda5da8dSAndroid Build Coastguard Worker 39*cda5da8dSAndroid Build Coastguard Worker """ 40*cda5da8dSAndroid Build Coastguard Worker 41*cda5da8dSAndroid Build Coastguard Worker __isabstractmethod__ = True 42*cda5da8dSAndroid Build Coastguard Worker 43*cda5da8dSAndroid Build Coastguard Worker def __init__(self, callable): 44*cda5da8dSAndroid Build Coastguard Worker callable.__isabstractmethod__ = True 45*cda5da8dSAndroid Build Coastguard Worker super().__init__(callable) 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker 48*cda5da8dSAndroid Build Coastguard Workerclass abstractstaticmethod(staticmethod): 49*cda5da8dSAndroid Build Coastguard Worker """A decorator indicating abstract staticmethods. 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Worker Deprecated, use 'staticmethod' with 'abstractmethod' instead: 52*cda5da8dSAndroid Build Coastguard Worker 53*cda5da8dSAndroid Build Coastguard Worker class C(ABC): 54*cda5da8dSAndroid Build Coastguard Worker @staticmethod 55*cda5da8dSAndroid Build Coastguard Worker @abstractmethod 56*cda5da8dSAndroid Build Coastguard Worker def my_abstract_staticmethod(...): 57*cda5da8dSAndroid Build Coastguard Worker ... 58*cda5da8dSAndroid Build Coastguard Worker 59*cda5da8dSAndroid Build Coastguard Worker """ 60*cda5da8dSAndroid Build Coastguard Worker 61*cda5da8dSAndroid Build Coastguard Worker __isabstractmethod__ = True 62*cda5da8dSAndroid Build Coastguard Worker 63*cda5da8dSAndroid Build Coastguard Worker def __init__(self, callable): 64*cda5da8dSAndroid Build Coastguard Worker callable.__isabstractmethod__ = True 65*cda5da8dSAndroid Build Coastguard Worker super().__init__(callable) 66*cda5da8dSAndroid Build Coastguard Worker 67*cda5da8dSAndroid Build Coastguard Worker 68*cda5da8dSAndroid Build Coastguard Workerclass abstractproperty(property): 69*cda5da8dSAndroid Build Coastguard Worker """A decorator indicating abstract properties. 70*cda5da8dSAndroid Build Coastguard Worker 71*cda5da8dSAndroid Build Coastguard Worker Deprecated, use 'property' with 'abstractmethod' instead: 72*cda5da8dSAndroid Build Coastguard Worker 73*cda5da8dSAndroid Build Coastguard Worker class C(ABC): 74*cda5da8dSAndroid Build Coastguard Worker @property 75*cda5da8dSAndroid Build Coastguard Worker @abstractmethod 76*cda5da8dSAndroid Build Coastguard Worker def my_abstract_property(self): 77*cda5da8dSAndroid Build Coastguard Worker ... 78*cda5da8dSAndroid Build Coastguard Worker 79*cda5da8dSAndroid Build Coastguard Worker """ 80*cda5da8dSAndroid Build Coastguard Worker 81*cda5da8dSAndroid Build Coastguard Worker __isabstractmethod__ = True 82*cda5da8dSAndroid Build Coastguard Worker 83*cda5da8dSAndroid Build Coastguard Worker 84*cda5da8dSAndroid Build Coastguard Workertry: 85*cda5da8dSAndroid Build Coastguard Worker from _abc import (get_cache_token, _abc_init, _abc_register, 86*cda5da8dSAndroid Build Coastguard Worker _abc_instancecheck, _abc_subclasscheck, _get_dump, 87*cda5da8dSAndroid Build Coastguard Worker _reset_registry, _reset_caches) 88*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 89*cda5da8dSAndroid Build Coastguard Worker from _py_abc import ABCMeta, get_cache_token 90*cda5da8dSAndroid Build Coastguard Worker ABCMeta.__module__ = 'abc' 91*cda5da8dSAndroid Build Coastguard Workerelse: 92*cda5da8dSAndroid Build Coastguard Worker class ABCMeta(type): 93*cda5da8dSAndroid Build Coastguard Worker """Metaclass for defining Abstract Base Classes (ABCs). 94*cda5da8dSAndroid Build Coastguard Worker 95*cda5da8dSAndroid Build Coastguard Worker Use this metaclass to create an ABC. An ABC can be subclassed 96*cda5da8dSAndroid Build Coastguard Worker directly, and then acts as a mix-in class. You can also register 97*cda5da8dSAndroid Build Coastguard Worker unrelated concrete classes (even built-in classes) and unrelated 98*cda5da8dSAndroid Build Coastguard Worker ABCs as 'virtual subclasses' -- these and their descendants will 99*cda5da8dSAndroid Build Coastguard Worker be considered subclasses of the registering ABC by the built-in 100*cda5da8dSAndroid Build Coastguard Worker issubclass() function, but the registering ABC won't show up in 101*cda5da8dSAndroid Build Coastguard Worker their MRO (Method Resolution Order) nor will method 102*cda5da8dSAndroid Build Coastguard Worker implementations defined by the registering ABC be callable (not 103*cda5da8dSAndroid Build Coastguard Worker even via super()). 104*cda5da8dSAndroid Build Coastguard Worker """ 105*cda5da8dSAndroid Build Coastguard Worker def __new__(mcls, name, bases, namespace, /, **kwargs): 106*cda5da8dSAndroid Build Coastguard Worker cls = super().__new__(mcls, name, bases, namespace, **kwargs) 107*cda5da8dSAndroid Build Coastguard Worker _abc_init(cls) 108*cda5da8dSAndroid Build Coastguard Worker return cls 109*cda5da8dSAndroid Build Coastguard Worker 110*cda5da8dSAndroid Build Coastguard Worker def register(cls, subclass): 111*cda5da8dSAndroid Build Coastguard Worker """Register a virtual subclass of an ABC. 112*cda5da8dSAndroid Build Coastguard Worker 113*cda5da8dSAndroid Build Coastguard Worker Returns the subclass, to allow usage as a class decorator. 114*cda5da8dSAndroid Build Coastguard Worker """ 115*cda5da8dSAndroid Build Coastguard Worker return _abc_register(cls, subclass) 116*cda5da8dSAndroid Build Coastguard Worker 117*cda5da8dSAndroid Build Coastguard Worker def __instancecheck__(cls, instance): 118*cda5da8dSAndroid Build Coastguard Worker """Override for isinstance(instance, cls).""" 119*cda5da8dSAndroid Build Coastguard Worker return _abc_instancecheck(cls, instance) 120*cda5da8dSAndroid Build Coastguard Worker 121*cda5da8dSAndroid Build Coastguard Worker def __subclasscheck__(cls, subclass): 122*cda5da8dSAndroid Build Coastguard Worker """Override for issubclass(subclass, cls).""" 123*cda5da8dSAndroid Build Coastguard Worker return _abc_subclasscheck(cls, subclass) 124*cda5da8dSAndroid Build Coastguard Worker 125*cda5da8dSAndroid Build Coastguard Worker def _dump_registry(cls, file=None): 126*cda5da8dSAndroid Build Coastguard Worker """Debug helper to print the ABC registry.""" 127*cda5da8dSAndroid Build Coastguard Worker print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) 128*cda5da8dSAndroid Build Coastguard Worker print(f"Inv. counter: {get_cache_token()}", file=file) 129*cda5da8dSAndroid Build Coastguard Worker (_abc_registry, _abc_cache, _abc_negative_cache, 130*cda5da8dSAndroid Build Coastguard Worker _abc_negative_cache_version) = _get_dump(cls) 131*cda5da8dSAndroid Build Coastguard Worker print(f"_abc_registry: {_abc_registry!r}", file=file) 132*cda5da8dSAndroid Build Coastguard Worker print(f"_abc_cache: {_abc_cache!r}", file=file) 133*cda5da8dSAndroid Build Coastguard Worker print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file) 134*cda5da8dSAndroid Build Coastguard Worker print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}", 135*cda5da8dSAndroid Build Coastguard Worker file=file) 136*cda5da8dSAndroid Build Coastguard Worker 137*cda5da8dSAndroid Build Coastguard Worker def _abc_registry_clear(cls): 138*cda5da8dSAndroid Build Coastguard Worker """Clear the registry (for debugging or testing).""" 139*cda5da8dSAndroid Build Coastguard Worker _reset_registry(cls) 140*cda5da8dSAndroid Build Coastguard Worker 141*cda5da8dSAndroid Build Coastguard Worker def _abc_caches_clear(cls): 142*cda5da8dSAndroid Build Coastguard Worker """Clear the caches (for debugging or testing).""" 143*cda5da8dSAndroid Build Coastguard Worker _reset_caches(cls) 144*cda5da8dSAndroid Build Coastguard Worker 145*cda5da8dSAndroid Build Coastguard Worker 146*cda5da8dSAndroid Build Coastguard Workerdef update_abstractmethods(cls): 147*cda5da8dSAndroid Build Coastguard Worker """Recalculate the set of abstract methods of an abstract class. 148*cda5da8dSAndroid Build Coastguard Worker 149*cda5da8dSAndroid Build Coastguard Worker If a class has had one of its abstract methods implemented after the 150*cda5da8dSAndroid Build Coastguard Worker class was created, the method will not be considered implemented until 151*cda5da8dSAndroid Build Coastguard Worker this function is called. Alternatively, if a new abstract method has been 152*cda5da8dSAndroid Build Coastguard Worker added to the class, it will only be considered an abstract method of the 153*cda5da8dSAndroid Build Coastguard Worker class after this function is called. 154*cda5da8dSAndroid Build Coastguard Worker 155*cda5da8dSAndroid Build Coastguard Worker This function should be called before any use is made of the class, 156*cda5da8dSAndroid Build Coastguard Worker usually in class decorators that add methods to the subject class. 157*cda5da8dSAndroid Build Coastguard Worker 158*cda5da8dSAndroid Build Coastguard Worker Returns cls, to allow usage as a class decorator. 159*cda5da8dSAndroid Build Coastguard Worker 160*cda5da8dSAndroid Build Coastguard Worker If cls is not an instance of ABCMeta, does nothing. 161*cda5da8dSAndroid Build Coastguard Worker """ 162*cda5da8dSAndroid Build Coastguard Worker if not hasattr(cls, '__abstractmethods__'): 163*cda5da8dSAndroid Build Coastguard Worker # We check for __abstractmethods__ here because cls might by a C 164*cda5da8dSAndroid Build Coastguard Worker # implementation or a python implementation (especially during 165*cda5da8dSAndroid Build Coastguard Worker # testing), and we want to handle both cases. 166*cda5da8dSAndroid Build Coastguard Worker return cls 167*cda5da8dSAndroid Build Coastguard Worker 168*cda5da8dSAndroid Build Coastguard Worker abstracts = set() 169*cda5da8dSAndroid Build Coastguard Worker # Check the existing abstract methods of the parents, keep only the ones 170*cda5da8dSAndroid Build Coastguard Worker # that are not implemented. 171*cda5da8dSAndroid Build Coastguard Worker for scls in cls.__bases__: 172*cda5da8dSAndroid Build Coastguard Worker for name in getattr(scls, '__abstractmethods__', ()): 173*cda5da8dSAndroid Build Coastguard Worker value = getattr(cls, name, None) 174*cda5da8dSAndroid Build Coastguard Worker if getattr(value, "__isabstractmethod__", False): 175*cda5da8dSAndroid Build Coastguard Worker abstracts.add(name) 176*cda5da8dSAndroid Build Coastguard Worker # Also add any other newly added abstract methods. 177*cda5da8dSAndroid Build Coastguard Worker for name, value in cls.__dict__.items(): 178*cda5da8dSAndroid Build Coastguard Worker if getattr(value, "__isabstractmethod__", False): 179*cda5da8dSAndroid Build Coastguard Worker abstracts.add(name) 180*cda5da8dSAndroid Build Coastguard Worker cls.__abstractmethods__ = frozenset(abstracts) 181*cda5da8dSAndroid Build Coastguard Worker return cls 182*cda5da8dSAndroid Build Coastguard Worker 183*cda5da8dSAndroid Build Coastguard Worker 184*cda5da8dSAndroid Build Coastguard Workerclass ABC(metaclass=ABCMeta): 185*cda5da8dSAndroid Build Coastguard Worker """Helper class that provides a standard way to create an ABC using 186*cda5da8dSAndroid Build Coastguard Worker inheritance. 187*cda5da8dSAndroid Build Coastguard Worker """ 188*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 189