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