blob: a6c2dc48779d6ab339db70a21a81f56607b89856 [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):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000136 """Register a virtual subclass of an ABC."""
Benjamin Petersond6326642010-01-27 02:25:58 +0000137 if not isinstance(subclass, type):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000138 raise TypeError("Can only register classes")
139 if issubclass(subclass, cls):
140 return # Already a subclass
141 # Subtle: test for cycles *after* testing for "already a subclass";
142 # this means we allow X.register(X) and interpret it as a no-op.
143 if issubclass(cls, subclass):
144 # This would create a cycle, which is bad for the algorithm below
145 raise RuntimeError("Refusing to create an inheritance cycle")
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000146 cls._abc_registry.add(subclass)
147 ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000148
149 def _dump_registry(cls, file=None):
150 """Debug helper to print the ABC registry."""
151 print("Class: %s.%s" % (cls.__module__, cls.__name__), file=file)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000152 print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000153 for name in sorted(cls.__dict__.keys()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000154 if name.startswith("_abc_"):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000155 value = getattr(cls, name)
156 print("%s: %r" % (name, value), file=file)
157
158 def __instancecheck__(cls, instance):
159 """Override for isinstance(instance, cls)."""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000160 # Inline the cache checking
161 subclass = instance.__class__
162 if subclass in cls._abc_cache:
163 return True
164 subtype = type(instance)
165 if subtype is subclass:
166 if (cls._abc_negative_cache_version ==
167 ABCMeta._abc_invalidation_counter and
168 subclass in cls._abc_negative_cache):
169 return False
170 # Fall back to the subclass check.
171 return cls.__subclasscheck__(subclass)
172 return any(cls.__subclasscheck__(c) for c in {subclass, subtype})
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000173
174 def __subclasscheck__(cls, subclass):
175 """Override for issubclass(subclass, cls)."""
176 # Check cache
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000177 if subclass in cls._abc_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000178 return True
179 # Check negative cache; may have to invalidate
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000180 if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000181 # Invalidate the negative cache
Georg Brandl3b8cb172007-10-23 06:26:46 +0000182 cls._abc_negative_cache = WeakSet()
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000183 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
184 elif subclass in cls._abc_negative_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000185 return False
186 # Check the subclass hook
187 ok = cls.__subclasshook__(subclass)
188 if ok is not NotImplemented:
189 assert isinstance(ok, bool)
190 if ok:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000191 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000192 else:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000193 cls._abc_negative_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000194 return ok
195 # Check if it's a direct subclass
Christian Heimes043d6f62008-01-07 17:19:16 +0000196 if cls in getattr(subclass, '__mro__', ()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000197 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000198 return True
199 # Check if it's a subclass of a registered class (recursive)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000200 for rcls in cls._abc_registry:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000201 if issubclass(subclass, rcls):
Nick Coghlan33794a72008-09-02 10:43:28 +0000202 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000203 return True
204 # Check if it's a subclass of a subclass (recursive)
205 for scls in cls.__subclasses__():
206 if issubclass(subclass, scls):
Nick Coghlan33794a72008-09-02 10:43:28 +0000207 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000208 return True
209 # No dice; update negative cache
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 False