blob: 40f88b92c0507a0565485327c4db4806cf6528b7 [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):
29 """A decorator indicating abstract classmethods.
30
31 Similar to abstractmethod.
32
33 Usage:
34
35 class C(metaclass=ABCMeta):
36 @abstractclassmethod
37 def my_abstract_classmethod(cls, ...):
38 ...
39 """
40
41 __isabstractmethod__ = True
42
43 def __init__(self, callable):
44 callable.__isabstractmethod__ = True
45 super().__init__(callable)
46
47
48class abstractstaticmethod(staticmethod):
49 """A decorator indicating abstract staticmethods.
50
51 Similar to abstractmethod.
52
53 Usage:
54
55 class C(metaclass=ABCMeta):
56 @abstractstaticmethod
57 def my_abstract_staticmethod(...):
58 ...
59 """
60
61 __isabstractmethod__ = True
62
63 def __init__(self, callable):
64 callable.__isabstractmethod__ = True
65 super().__init__(callable)
66
67
Guido van Rossumb31339f2007-08-01 17:32:28 +000068class abstractproperty(property):
69 """A decorator indicating abstract properties.
70
71 Requires that the metaclass is ABCMeta or derived from it. A
72 class that has a metaclass derived from ABCMeta cannot be
73 instantiated unless all of its abstract properties are overridden.
Walter Dörwald6e359bd2009-05-04 16:10:10 +000074 The abstract properties can be called using any of the normal
Guido van Rossum70d2b892007-08-01 17:52:23 +000075 'super' call mechanisms.
Guido van Rossumb31339f2007-08-01 17:32:28 +000076
77 Usage:
78
79 class C(metaclass=ABCMeta):
80 @abstractproperty
81 def my_abstract_property(self):
82 ...
83
84 This defines a read-only property; you can also define a read-write
85 abstract property using the 'long' form of property declaration:
86
87 class C(metaclass=ABCMeta):
88 def getx(self): ...
89 def setx(self, value): ...
90 x = abstractproperty(getx, setx)
91 """
92 __isabstractmethod__ = True
93
94
Guido van Rossum8518bdc2007-06-14 00:03:37 +000095class ABCMeta(type):
96
97 """Metaclass for defining Abstract Base Classes (ABCs).
98
99 Use this metaclass to create an ABC. An ABC can be subclassed
100 directly, and then acts as a mix-in class. You can also register
101 unrelated concrete classes (even built-in classes) and unrelated
102 ABCs as 'virtual subclasses' -- these and their descendants will
103 be considered subclasses of the registering ABC by the built-in
104 issubclass() function, but the registering ABC won't show up in
105 their MRO (Method Resolution Order) nor will method
106 implementations defined by the registering ABC be callable (not
107 even via super()).
108
109 """
110
111 # A global counter that is incremented each time a class is
112 # registered as a virtual subclass of anything. It forces the
113 # negative cache to be cleared before its next use.
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000114 _abc_invalidation_counter = 0
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000115
116 def __new__(mcls, name, bases, namespace):
Guido van Rossumbb5f5902007-06-14 03:27:55 +0000117 cls = super().__new__(mcls, name, bases, namespace)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000118 # Compute set of abstract method names
119 abstracts = {name
120 for name, value in namespace.items()
121 if getattr(value, "__isabstractmethod__", False)}
122 for base in bases:
123 for name in getattr(base, "__abstractmethods__", set()):
124 value = getattr(cls, name, None)
125 if getattr(value, "__isabstractmethod__", False):
126 abstracts.add(name)
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000127 cls.__abstractmethods__ = frozenset(abstracts)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000128 # Set up inheritance registry
Georg Brandl3b8cb172007-10-23 06:26:46 +0000129 cls._abc_registry = WeakSet()
130 cls._abc_cache = WeakSet()
131 cls._abc_negative_cache = WeakSet()
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000132 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000133 return cls
134
Christian Heimes45031df2007-11-30 15:13:13 +0000135 def register(cls, subclass):
Éric Araujo6c3787c2011-02-24 18:03:10 +0000136 """Register a virtual subclass of an ABC.
137
138 Returns the subclass, to allow usage as a class decorator.
139 """
Benjamin Petersond6326642010-01-27 02:25:58 +0000140 if not isinstance(subclass, type):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000141 raise TypeError("Can only register classes")
142 if issubclass(subclass, cls):
Éric Araujo6c3787c2011-02-24 18:03:10 +0000143 return subclass # Already a subclass
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000144 # Subtle: test for cycles *after* testing for "already a subclass";
145 # this means we allow X.register(X) and interpret it as a no-op.
146 if issubclass(cls, subclass):
147 # This would create a cycle, which is bad for the algorithm below
148 raise RuntimeError("Refusing to create an inheritance cycle")
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000149 cls._abc_registry.add(subclass)
150 ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
Éric Araujo6c3787c2011-02-24 18:03:10 +0000151 return subclass
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000152
153 def _dump_registry(cls, file=None):
154 """Debug helper to print the ABC registry."""
155 print("Class: %s.%s" % (cls.__module__, cls.__name__), file=file)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000156 print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000157 for name in sorted(cls.__dict__.keys()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000158 if name.startswith("_abc_"):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000159 value = getattr(cls, name)
160 print("%s: %r" % (name, value), file=file)
161
162 def __instancecheck__(cls, instance):
163 """Override for isinstance(instance, cls)."""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000164 # Inline the cache checking
165 subclass = instance.__class__
166 if subclass in cls._abc_cache:
167 return True
168 subtype = type(instance)
169 if subtype is subclass:
170 if (cls._abc_negative_cache_version ==
171 ABCMeta._abc_invalidation_counter and
172 subclass in cls._abc_negative_cache):
173 return False
174 # Fall back to the subclass check.
175 return cls.__subclasscheck__(subclass)
176 return any(cls.__subclasscheck__(c) for c in {subclass, subtype})
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000177
178 def __subclasscheck__(cls, subclass):
179 """Override for issubclass(subclass, cls)."""
180 # Check cache
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000181 if subclass in cls._abc_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000182 return True
183 # Check negative cache; may have to invalidate
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000184 if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000185 # Invalidate the negative cache
Georg Brandl3b8cb172007-10-23 06:26:46 +0000186 cls._abc_negative_cache = WeakSet()
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000187 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
188 elif subclass in cls._abc_negative_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000189 return False
190 # Check the subclass hook
191 ok = cls.__subclasshook__(subclass)
192 if ok is not NotImplemented:
193 assert isinstance(ok, bool)
194 if ok:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000195 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000196 else:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000197 cls._abc_negative_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000198 return ok
199 # Check if it's a direct subclass
Christian Heimes043d6f62008-01-07 17:19:16 +0000200 if cls in getattr(subclass, '__mro__', ()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000201 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000202 return True
203 # Check if it's a subclass of a registered class (recursive)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000204 for rcls in cls._abc_registry:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000205 if issubclass(subclass, rcls):
Nick Coghlan33794a72008-09-02 10:43:28 +0000206 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000207 return True
208 # Check if it's a subclass of a subclass (recursive)
209 for scls in cls.__subclasses__():
210 if issubclass(subclass, scls):
Nick Coghlan33794a72008-09-02 10:43:28 +0000211 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000212 return True
213 # No dice; update negative cache
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000214 cls._abc_negative_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000215 return False