blob: 09778e8609f73aa8390ba9bc620dcbe138c1199e [file] [log] [blame]
Guido van Rossum8518bdc2007-06-14 00:03:37 +00001# 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 Hettinger93fa6082008-02-05 00:20:01 +00006from _weakrefset import WeakSet
Guido van Rossum8518bdc2007-06-14 00:03:37 +00007
8def abstractmethod(funcobj):
9 """A decorator indicating abstract methods.
10
11 Requires that the metaclass is ABCMeta or derived from it. A
12 class that has a metaclass derived from ABCMeta cannot be
13 instantiated unless all of its abstract methods are overridden.
Walter Dörwald6e359bd2009-05-04 16:10:10 +000014 The abstract methods can be called using any of the normal
Guido van Rossum8518bdc2007-06-14 00:03:37 +000015 'super' call mechanisms.
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 Peterson45c257f2010-08-17 00:52:52 +000028class abstractclassmethod(classmethod):
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050029 """
30 A decorator indicating abstract classmethods.
Benjamin Peterson45c257f2010-08-17 00:52:52 +000031
32 Similar to abstractmethod.
33
34 Usage:
35
36 class C(metaclass=ABCMeta):
37 @abstractclassmethod
38 def my_abstract_classmethod(cls, ...):
39 ...
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050040
41 'abstractclassmethod' is deprecated. Use 'classmethod' with
42 'abstractmethod' instead.
Benjamin Peterson45c257f2010-08-17 00:52:52 +000043 """
44
45 __isabstractmethod__ = True
46
47 def __init__(self, callable):
48 callable.__isabstractmethod__ = True
49 super().__init__(callable)
50
51
52class abstractstaticmethod(staticmethod):
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050053 """
54 A decorator indicating abstract staticmethods.
Benjamin Peterson45c257f2010-08-17 00:52:52 +000055
56 Similar to abstractmethod.
57
58 Usage:
59
60 class C(metaclass=ABCMeta):
61 @abstractstaticmethod
62 def my_abstract_staticmethod(...):
63 ...
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050064
65 'abstractstaticmethod' is deprecated. Use 'staticmethod' with
66 'abstractmethod' instead.
Benjamin Peterson45c257f2010-08-17 00:52:52 +000067 """
68
69 __isabstractmethod__ = True
70
71 def __init__(self, callable):
72 callable.__isabstractmethod__ = True
73 super().__init__(callable)
74
75
Guido van Rossumb31339f2007-08-01 17:32:28 +000076class abstractproperty(property):
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050077 """
78 A decorator indicating abstract properties.
Guido van Rossumb31339f2007-08-01 17:32:28 +000079
80 Requires that the metaclass is ABCMeta or derived from it. A
81 class that has a metaclass derived from ABCMeta cannot be
82 instantiated unless all of its abstract properties are overridden.
Walter Dörwald6e359bd2009-05-04 16:10:10 +000083 The abstract properties can be called using any of the normal
Guido van Rossum70d2b892007-08-01 17:52:23 +000084 'super' call mechanisms.
Guido van Rossumb31339f2007-08-01 17:32:28 +000085
86 Usage:
87
88 class C(metaclass=ABCMeta):
89 @abstractproperty
90 def my_abstract_property(self):
91 ...
92
93 This defines a read-only property; you can also define a read-write
94 abstract property using the 'long' form of property declaration:
95
96 class C(metaclass=ABCMeta):
97 def getx(self): ...
98 def setx(self, value): ...
99 x = abstractproperty(getx, setx)
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500100
101 'abstractproperty' is deprecated. Use 'property' with 'abstractmethod'
102 instead.
Guido van Rossumb31339f2007-08-01 17:32:28 +0000103 """
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500104
Guido van Rossumb31339f2007-08-01 17:32:28 +0000105 __isabstractmethod__ = True
106
107
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000108class ABCMeta(type):
109
110 """Metaclass for defining Abstract Base Classes (ABCs).
111
112 Use this metaclass to create an ABC. An ABC can be subclassed
113 directly, and then acts as a mix-in class. You can also register
114 unrelated concrete classes (even built-in classes) and unrelated
115 ABCs as 'virtual subclasses' -- these and their descendants will
116 be considered subclasses of the registering ABC by the built-in
117 issubclass() function, but the registering ABC won't show up in
118 their MRO (Method Resolution Order) nor will method
119 implementations defined by the registering ABC be callable (not
120 even via super()).
121
122 """
123
124 # A global counter that is incremented each time a class is
125 # registered as a virtual subclass of anything. It forces the
126 # negative cache to be cleared before its next use.
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000127 _abc_invalidation_counter = 0
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000128
129 def __new__(mcls, name, bases, namespace):
Guido van Rossumbb5f5902007-06-14 03:27:55 +0000130 cls = super().__new__(mcls, name, bases, namespace)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000131 # Compute set of abstract method names
132 abstracts = {name
133 for name, value in namespace.items()
134 if getattr(value, "__isabstractmethod__", False)}
135 for base in bases:
136 for name in getattr(base, "__abstractmethods__", set()):
137 value = getattr(cls, name, None)
138 if getattr(value, "__isabstractmethod__", False):
139 abstracts.add(name)
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000140 cls.__abstractmethods__ = frozenset(abstracts)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000141 # Set up inheritance registry
Georg Brandl3b8cb172007-10-23 06:26:46 +0000142 cls._abc_registry = WeakSet()
143 cls._abc_cache = WeakSet()
144 cls._abc_negative_cache = WeakSet()
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000145 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000146 return cls
147
Christian Heimes45031df2007-11-30 15:13:13 +0000148 def register(cls, subclass):
Éric Araujo6c3787c2011-02-24 18:03:10 +0000149 """Register a virtual subclass of an ABC.
150
151 Returns the subclass, to allow usage as a class decorator.
152 """
Benjamin Petersond6326642010-01-27 02:25:58 +0000153 if not isinstance(subclass, type):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000154 raise TypeError("Can only register classes")
155 if issubclass(subclass, cls):
Éric Araujo6c3787c2011-02-24 18:03:10 +0000156 return subclass # Already a subclass
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000157 # Subtle: test for cycles *after* testing for "already a subclass";
158 # this means we allow X.register(X) and interpret it as a no-op.
159 if issubclass(cls, subclass):
160 # This would create a cycle, which is bad for the algorithm below
161 raise RuntimeError("Refusing to create an inheritance cycle")
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000162 cls._abc_registry.add(subclass)
163 ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
Éric Araujo6c3787c2011-02-24 18:03:10 +0000164 return subclass
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000165
166 def _dump_registry(cls, file=None):
167 """Debug helper to print the ABC registry."""
168 print("Class: %s.%s" % (cls.__module__, cls.__name__), file=file)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000169 print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000170 for name in sorted(cls.__dict__.keys()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000171 if name.startswith("_abc_"):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000172 value = getattr(cls, name)
173 print("%s: %r" % (name, value), file=file)
174
175 def __instancecheck__(cls, instance):
176 """Override for isinstance(instance, cls)."""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000177 # Inline the cache checking
178 subclass = instance.__class__
179 if subclass in cls._abc_cache:
180 return True
181 subtype = type(instance)
182 if subtype is subclass:
183 if (cls._abc_negative_cache_version ==
184 ABCMeta._abc_invalidation_counter and
185 subclass in cls._abc_negative_cache):
186 return False
187 # Fall back to the subclass check.
188 return cls.__subclasscheck__(subclass)
189 return any(cls.__subclasscheck__(c) for c in {subclass, subtype})
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000190
191 def __subclasscheck__(cls, subclass):
192 """Override for issubclass(subclass, cls)."""
193 # Check cache
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000194 if subclass in cls._abc_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000195 return True
196 # Check negative cache; may have to invalidate
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000197 if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000198 # Invalidate the negative cache
Georg Brandl3b8cb172007-10-23 06:26:46 +0000199 cls._abc_negative_cache = WeakSet()
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000200 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
201 elif subclass in cls._abc_negative_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000202 return False
203 # Check the subclass hook
204 ok = cls.__subclasshook__(subclass)
205 if ok is not NotImplemented:
206 assert isinstance(ok, bool)
207 if ok:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000208 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000209 else:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000210 cls._abc_negative_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000211 return ok
212 # Check if it's a direct subclass
Christian Heimes043d6f62008-01-07 17:19:16 +0000213 if cls in getattr(subclass, '__mro__', ()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000214 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000215 return True
216 # Check if it's a subclass of a registered class (recursive)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000217 for rcls in cls._abc_registry:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000218 if issubclass(subclass, rcls):
Nick Coghlan33794a72008-09-02 10:43:28 +0000219 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000220 return True
221 # Check if it's a subclass of a subclass (recursive)
222 for scls in cls.__subclasses__():
223 if issubclass(subclass, scls):
Nick Coghlan33794a72008-09-02 10:43:28 +0000224 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000225 return True
226 # No dice; update negative cache
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000227 cls._abc_negative_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000228 return False