| 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 |  | 
| Raymond Hettinger | 93fa608 | 2008-02-05 00:20:01 +0000 | [diff] [blame] | 6 | from _weakrefset import WeakSet | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 7 |  | 
| Łukasz Langa | eadd8cf | 2013-05-25 18:41:50 +0200 | [diff] [blame] | 8 |  | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 9 | def abstractmethod(funcobj): | 
 | 10 |     """A decorator indicating abstract methods. | 
 | 11 |  | 
 | 12 |     Requires that the metaclass is ABCMeta or derived from it.  A | 
 | 13 |     class that has a metaclass derived from ABCMeta cannot be | 
 | 14 |     instantiated unless all of its abstract methods are overridden. | 
| Walter Dörwald | 6e359bd | 2009-05-04 16:10:10 +0000 | [diff] [blame] | 15 |     The abstract methods can be called using any of the normal | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 16 |     'super' call mechanisms. | 
 | 17 |  | 
 | 18 |     Usage: | 
 | 19 |  | 
 | 20 |         class C(metaclass=ABCMeta): | 
 | 21 |             @abstractmethod | 
 | 22 |             def my_abstract_method(self, ...): | 
 | 23 |                 ... | 
 | 24 |     """ | 
 | 25 |     funcobj.__isabstractmethod__ = True | 
 | 26 |     return funcobj | 
 | 27 |  | 
 | 28 |  | 
| Benjamin Peterson | 45c257f | 2010-08-17 00:52:52 +0000 | [diff] [blame] | 29 | class abstractclassmethod(classmethod): | 
| Benjamin Peterson | bfebb7b | 2011-12-15 15:34:02 -0500 | [diff] [blame] | 30 |     """ | 
 | 31 |     A decorator indicating abstract classmethods. | 
| Benjamin Peterson | 45c257f | 2010-08-17 00:52:52 +0000 | [diff] [blame] | 32 |  | 
 | 33 |     Similar to abstractmethod. | 
 | 34 |  | 
 | 35 |     Usage: | 
 | 36 |  | 
 | 37 |         class C(metaclass=ABCMeta): | 
 | 38 |             @abstractclassmethod | 
 | 39 |             def my_abstract_classmethod(cls, ...): | 
 | 40 |                 ... | 
| Benjamin Peterson | bfebb7b | 2011-12-15 15:34:02 -0500 | [diff] [blame] | 41 |  | 
 | 42 |     'abstractclassmethod' is deprecated. Use 'classmethod' with | 
 | 43 |     'abstractmethod' instead. | 
| Benjamin Peterson | 45c257f | 2010-08-17 00:52:52 +0000 | [diff] [blame] | 44 |     """ | 
 | 45 |  | 
 | 46 |     __isabstractmethod__ = True | 
 | 47 |  | 
 | 48 |     def __init__(self, callable): | 
 | 49 |         callable.__isabstractmethod__ = True | 
 | 50 |         super().__init__(callable) | 
 | 51 |  | 
 | 52 |  | 
 | 53 | class abstractstaticmethod(staticmethod): | 
| Benjamin Peterson | bfebb7b | 2011-12-15 15:34:02 -0500 | [diff] [blame] | 54 |     """ | 
 | 55 |     A decorator indicating abstract staticmethods. | 
| Benjamin Peterson | 45c257f | 2010-08-17 00:52:52 +0000 | [diff] [blame] | 56 |  | 
 | 57 |     Similar to abstractmethod. | 
 | 58 |  | 
 | 59 |     Usage: | 
 | 60 |  | 
 | 61 |         class C(metaclass=ABCMeta): | 
 | 62 |             @abstractstaticmethod | 
 | 63 |             def my_abstract_staticmethod(...): | 
 | 64 |                 ... | 
| Benjamin Peterson | bfebb7b | 2011-12-15 15:34:02 -0500 | [diff] [blame] | 65 |  | 
 | 66 |     'abstractstaticmethod' is deprecated. Use 'staticmethod' with | 
 | 67 |     'abstractmethod' instead. | 
| Benjamin Peterson | 45c257f | 2010-08-17 00:52:52 +0000 | [diff] [blame] | 68 |     """ | 
 | 69 |  | 
 | 70 |     __isabstractmethod__ = True | 
 | 71 |  | 
 | 72 |     def __init__(self, callable): | 
 | 73 |         callable.__isabstractmethod__ = True | 
 | 74 |         super().__init__(callable) | 
 | 75 |  | 
 | 76 |  | 
| Guido van Rossum | b31339f | 2007-08-01 17:32:28 +0000 | [diff] [blame] | 77 | class abstractproperty(property): | 
| Benjamin Peterson | bfebb7b | 2011-12-15 15:34:02 -0500 | [diff] [blame] | 78 |     """ | 
 | 79 |     A decorator indicating abstract properties. | 
| Guido van Rossum | b31339f | 2007-08-01 17:32:28 +0000 | [diff] [blame] | 80 |  | 
 | 81 |     Requires that the metaclass is ABCMeta or derived from it.  A | 
 | 82 |     class that has a metaclass derived from ABCMeta cannot be | 
 | 83 |     instantiated unless all of its abstract properties are overridden. | 
| Walter Dörwald | 6e359bd | 2009-05-04 16:10:10 +0000 | [diff] [blame] | 84 |     The abstract properties can be called using any of the normal | 
| Guido van Rossum | 70d2b89 | 2007-08-01 17:52:23 +0000 | [diff] [blame] | 85 |     'super' call mechanisms. | 
| Guido van Rossum | b31339f | 2007-08-01 17:32:28 +0000 | [diff] [blame] | 86 |  | 
 | 87 |     Usage: | 
 | 88 |  | 
 | 89 |         class C(metaclass=ABCMeta): | 
 | 90 |             @abstractproperty | 
 | 91 |             def my_abstract_property(self): | 
 | 92 |                 ... | 
 | 93 |  | 
 | 94 |     This defines a read-only property; you can also define a read-write | 
 | 95 |     abstract property using the 'long' form of property declaration: | 
 | 96 |  | 
 | 97 |         class C(metaclass=ABCMeta): | 
 | 98 |             def getx(self): ... | 
 | 99 |             def setx(self, value): ... | 
 | 100 |             x = abstractproperty(getx, setx) | 
| Benjamin Peterson | bfebb7b | 2011-12-15 15:34:02 -0500 | [diff] [blame] | 101 |  | 
 | 102 |     'abstractproperty' is deprecated. Use 'property' with 'abstractmethod' | 
 | 103 |     instead. | 
| Guido van Rossum | b31339f | 2007-08-01 17:32:28 +0000 | [diff] [blame] | 104 |     """ | 
| Benjamin Peterson | bfebb7b | 2011-12-15 15:34:02 -0500 | [diff] [blame] | 105 |  | 
| Guido van Rossum | b31339f | 2007-08-01 17:32:28 +0000 | [diff] [blame] | 106 |     __isabstractmethod__ = True | 
 | 107 |  | 
 | 108 |  | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 109 | class ABCMeta(type): | 
 | 110 |  | 
 | 111 |     """Metaclass for defining Abstract Base Classes (ABCs). | 
 | 112 |  | 
 | 113 |     Use this metaclass to create an ABC.  An ABC can be subclassed | 
 | 114 |     directly, and then acts as a mix-in class.  You can also register | 
 | 115 |     unrelated concrete classes (even built-in classes) and unrelated | 
 | 116 |     ABCs as 'virtual subclasses' -- these and their descendants will | 
 | 117 |     be considered subclasses of the registering ABC by the built-in | 
 | 118 |     issubclass() function, but the registering ABC won't show up in | 
 | 119 |     their MRO (Method Resolution Order) nor will method | 
 | 120 |     implementations defined by the registering ABC be callable (not | 
 | 121 |     even via super()). | 
 | 122 |  | 
 | 123 |     """ | 
 | 124 |  | 
 | 125 |     # A global counter that is incremented each time a class is | 
 | 126 |     # registered as a virtual subclass of anything.  It forces the | 
 | 127 |     # negative cache to be cleared before its next use. | 
| Łukasz Langa | eadd8cf | 2013-05-25 18:41:50 +0200 | [diff] [blame] | 128 |     # Note: this counter is private. Use `abc.get_cache_token()` for | 
 | 129 |     #       external code. | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 130 |     _abc_invalidation_counter = 0 | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 131 |  | 
 | 132 |     def __new__(mcls, name, bases, namespace): | 
| Guido van Rossum | bb5f590 | 2007-06-14 03:27:55 +0000 | [diff] [blame] | 133 |         cls = super().__new__(mcls, name, bases, namespace) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 134 |         # Compute set of abstract method names | 
 | 135 |         abstracts = {name | 
 | 136 |                      for name, value in namespace.items() | 
 | 137 |                      if getattr(value, "__isabstractmethod__", False)} | 
 | 138 |         for base in bases: | 
 | 139 |             for name in getattr(base, "__abstractmethods__", set()): | 
 | 140 |                 value = getattr(cls, name, None) | 
 | 141 |                 if getattr(value, "__isabstractmethod__", False): | 
 | 142 |                     abstracts.add(name) | 
| Christian Heimes | 9e7f1d2 | 2008-02-28 12:27:11 +0000 | [diff] [blame] | 143 |         cls.__abstractmethods__ = frozenset(abstracts) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 144 |         # Set up inheritance registry | 
| Georg Brandl | 3b8cb17 | 2007-10-23 06:26:46 +0000 | [diff] [blame] | 145 |         cls._abc_registry = WeakSet() | 
 | 146 |         cls._abc_cache = WeakSet() | 
 | 147 |         cls._abc_negative_cache = WeakSet() | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 148 |         cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 149 |         return cls | 
 | 150 |  | 
| Christian Heimes | 45031df | 2007-11-30 15:13:13 +0000 | [diff] [blame] | 151 |     def register(cls, subclass): | 
| Éric Araujo | 6c3787c | 2011-02-24 18:03:10 +0000 | [diff] [blame] | 152 |         """Register a virtual subclass of an ABC. | 
 | 153 |  | 
 | 154 |         Returns the subclass, to allow usage as a class decorator. | 
 | 155 |         """ | 
| Benjamin Peterson | d632664 | 2010-01-27 02:25:58 +0000 | [diff] [blame] | 156 |         if not isinstance(subclass, type): | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 157 |             raise TypeError("Can only register classes") | 
 | 158 |         if issubclass(subclass, cls): | 
| Éric Araujo | 6c3787c | 2011-02-24 18:03:10 +0000 | [diff] [blame] | 159 |             return subclass  # Already a subclass | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 160 |         # Subtle: test for cycles *after* testing for "already a subclass"; | 
 | 161 |         # this means we allow X.register(X) and interpret it as a no-op. | 
 | 162 |         if issubclass(cls, subclass): | 
 | 163 |             # This would create a cycle, which is bad for the algorithm below | 
 | 164 |             raise RuntimeError("Refusing to create an inheritance cycle") | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 165 |         cls._abc_registry.add(subclass) | 
 | 166 |         ABCMeta._abc_invalidation_counter += 1  # Invalidate negative cache | 
| Éric Araujo | 6c3787c | 2011-02-24 18:03:10 +0000 | [diff] [blame] | 167 |         return subclass | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 168 |  | 
 | 169 |     def _dump_registry(cls, file=None): | 
 | 170 |         """Debug helper to print the ABC registry.""" | 
 | 171 |         print("Class: %s.%s" % (cls.__module__, cls.__name__), file=file) | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 172 |         print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 173 |         for name in sorted(cls.__dict__.keys()): | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 174 |             if name.startswith("_abc_"): | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 175 |                 value = getattr(cls, name) | 
 | 176 |                 print("%s: %r" % (name, value), file=file) | 
 | 177 |  | 
 | 178 |     def __instancecheck__(cls, instance): | 
 | 179 |         """Override for isinstance(instance, cls).""" | 
| Christian Heimes | 68f5fbe | 2008-02-14 08:27:37 +0000 | [diff] [blame] | 180 |         # Inline the cache checking | 
 | 181 |         subclass = instance.__class__ | 
 | 182 |         if subclass in cls._abc_cache: | 
 | 183 |             return True | 
 | 184 |         subtype = type(instance) | 
 | 185 |         if subtype is subclass: | 
 | 186 |             if (cls._abc_negative_cache_version == | 
 | 187 |                 ABCMeta._abc_invalidation_counter and | 
 | 188 |                 subclass in cls._abc_negative_cache): | 
 | 189 |                 return False | 
 | 190 |             # Fall back to the subclass check. | 
 | 191 |             return cls.__subclasscheck__(subclass) | 
 | 192 |         return any(cls.__subclasscheck__(c) for c in {subclass, subtype}) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 193 |  | 
 | 194 |     def __subclasscheck__(cls, subclass): | 
 | 195 |         """Override for issubclass(subclass, cls).""" | 
 | 196 |         # Check cache | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 197 |         if subclass in cls._abc_cache: | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 198 |             return True | 
 | 199 |         # Check negative cache; may have to invalidate | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 200 |         if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 201 |             # Invalidate the negative cache | 
| Georg Brandl | 3b8cb17 | 2007-10-23 06:26:46 +0000 | [diff] [blame] | 202 |             cls._abc_negative_cache = WeakSet() | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 203 |             cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter | 
 | 204 |         elif subclass in cls._abc_negative_cache: | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 205 |             return False | 
 | 206 |         # Check the subclass hook | 
 | 207 |         ok = cls.__subclasshook__(subclass) | 
 | 208 |         if ok is not NotImplemented: | 
 | 209 |             assert isinstance(ok, bool) | 
 | 210 |             if ok: | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 211 |                 cls._abc_cache.add(subclass) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 212 |             else: | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 213 |                 cls._abc_negative_cache.add(subclass) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 214 |             return ok | 
 | 215 |         # Check if it's a direct subclass | 
| Christian Heimes | 043d6f6 | 2008-01-07 17:19:16 +0000 | [diff] [blame] | 216 |         if cls in getattr(subclass, '__mro__', ()): | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 217 |             cls._abc_cache.add(subclass) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 218 |             return True | 
 | 219 |         # Check if it's a subclass of a registered class (recursive) | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 220 |         for rcls in cls._abc_registry: | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 221 |             if issubclass(subclass, rcls): | 
| Nick Coghlan | 33794a7 | 2008-09-02 10:43:28 +0000 | [diff] [blame] | 222 |                 cls._abc_cache.add(subclass) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 223 |                 return True | 
 | 224 |         # Check if it's a subclass of a subclass (recursive) | 
 | 225 |         for scls in cls.__subclasses__(): | 
 | 226 |             if issubclass(subclass, scls): | 
| Nick Coghlan | 33794a7 | 2008-09-02 10:43:28 +0000 | [diff] [blame] | 227 |                 cls._abc_cache.add(subclass) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 228 |                 return True | 
 | 229 |         # No dice; update negative cache | 
| Guido van Rossum | c1e315d | 2007-08-20 19:29:24 +0000 | [diff] [blame] | 230 |         cls._abc_negative_cache.add(subclass) | 
| Guido van Rossum | 8518bdc | 2007-06-14 00:03:37 +0000 | [diff] [blame] | 231 |         return False | 
| Andrew Svetlov | b67596d | 2012-12-13 19:09:33 +0200 | [diff] [blame] | 232 |  | 
| Łukasz Langa | eadd8cf | 2013-05-25 18:41:50 +0200 | [diff] [blame] | 233 |  | 
| Andrew Svetlov | b67596d | 2012-12-13 19:09:33 +0200 | [diff] [blame] | 234 | class ABC(metaclass=ABCMeta): | 
 | 235 |     """Helper class that provides a standard way to create an ABC using | 
 | 236 |     inheritance. | 
 | 237 |     """ | 
 | 238 |     pass | 
| Łukasz Langa | eadd8cf | 2013-05-25 18:41:50 +0200 | [diff] [blame] | 239 |  | 
 | 240 |  | 
 | 241 | def get_cache_token(): | 
 | 242 |     """Returns the current ABC cache token. | 
 | 243 |  | 
| R David Murray | 3edcc78 | 2013-12-24 16:13:32 -0500 | [diff] [blame] | 244 |     The token is an opaque object (supporting equality testing) identifying the | 
 | 245 |     current version of the ABC cache for virtual subclasses. The token changes | 
 | 246 |     with every call to ``register()`` on any ABC. | 
| Łukasz Langa | eadd8cf | 2013-05-25 18:41:50 +0200 | [diff] [blame] | 247 |     """ | 
 | 248 |     return ABCMeta._abc_invalidation_counter |