blob: 05ac7e451f8b6f76d0a8b9131fb87b0f4461ced9 [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.
14 The abstract methods can be called using any of the the normal
15 '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
Guido van Rossumb31339f2007-08-01 17:32:28 +000028class abstractproperty(property):
29 """A decorator indicating abstract properties.
30
31 Requires that the metaclass is ABCMeta or derived from it. A
32 class that has a metaclass derived from ABCMeta cannot be
33 instantiated unless all of its abstract properties are overridden.
Guido van Rossum70d2b892007-08-01 17:52:23 +000034 The abstract properties can be called using any of the the normal
35 'super' call mechanisms.
Guido van Rossumb31339f2007-08-01 17:32:28 +000036
37 Usage:
38
39 class C(metaclass=ABCMeta):
40 @abstractproperty
41 def my_abstract_property(self):
42 ...
43
44 This defines a read-only property; you can also define a read-write
45 abstract property using the 'long' form of property declaration:
46
47 class C(metaclass=ABCMeta):
48 def getx(self): ...
49 def setx(self, value): ...
50 x = abstractproperty(getx, setx)
51 """
52 __isabstractmethod__ = True
53
54
Guido van Rossum8518bdc2007-06-14 00:03:37 +000055class ABCMeta(type):
56
57 """Metaclass for defining Abstract Base Classes (ABCs).
58
59 Use this metaclass to create an ABC. An ABC can be subclassed
60 directly, and then acts as a mix-in class. You can also register
61 unrelated concrete classes (even built-in classes) and unrelated
62 ABCs as 'virtual subclasses' -- these and their descendants will
63 be considered subclasses of the registering ABC by the built-in
64 issubclass() function, but the registering ABC won't show up in
65 their MRO (Method Resolution Order) nor will method
66 implementations defined by the registering ABC be callable (not
67 even via super()).
68
69 """
70
71 # A global counter that is incremented each time a class is
72 # registered as a virtual subclass of anything. It forces the
73 # negative cache to be cleared before its next use.
Guido van Rossumc1e315d2007-08-20 19:29:24 +000074 _abc_invalidation_counter = 0
Guido van Rossum8518bdc2007-06-14 00:03:37 +000075
76 def __new__(mcls, name, bases, namespace):
Guido van Rossumbb5f5902007-06-14 03:27:55 +000077 cls = super().__new__(mcls, name, bases, namespace)
Guido van Rossum8518bdc2007-06-14 00:03:37 +000078 # Compute set of abstract method names
79 abstracts = {name
80 for name, value in namespace.items()
81 if getattr(value, "__isabstractmethod__", False)}
82 for base in bases:
83 for name in getattr(base, "__abstractmethods__", set()):
84 value = getattr(cls, name, None)
85 if getattr(value, "__isabstractmethod__", False):
86 abstracts.add(name)
Christian Heimes9e7f1d22008-02-28 12:27:11 +000087 cls.__abstractmethods__ = frozenset(abstracts)
Guido van Rossum8518bdc2007-06-14 00:03:37 +000088 # Set up inheritance registry
Georg Brandl3b8cb172007-10-23 06:26:46 +000089 cls._abc_registry = WeakSet()
90 cls._abc_cache = WeakSet()
91 cls._abc_negative_cache = WeakSet()
Guido van Rossumc1e315d2007-08-20 19:29:24 +000092 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
Guido van Rossum8518bdc2007-06-14 00:03:37 +000093 return cls
94
Christian Heimes45031df2007-11-30 15:13:13 +000095 def register(cls, subclass):
Guido van Rossum8518bdc2007-06-14 00:03:37 +000096 """Register a virtual subclass of an ABC."""
97 if not isinstance(cls, type):
98 raise TypeError("Can only register classes")
99 if issubclass(subclass, cls):
100 return # Already a subclass
101 # Subtle: test for cycles *after* testing for "already a subclass";
102 # this means we allow X.register(X) and interpret it as a no-op.
103 if issubclass(cls, subclass):
104 # This would create a cycle, which is bad for the algorithm below
105 raise RuntimeError("Refusing to create an inheritance cycle")
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000106 cls._abc_registry.add(subclass)
107 ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000108
109 def _dump_registry(cls, file=None):
110 """Debug helper to print the ABC registry."""
111 print("Class: %s.%s" % (cls.__module__, cls.__name__), file=file)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000112 print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000113 for name in sorted(cls.__dict__.keys()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000114 if name.startswith("_abc_"):
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000115 value = getattr(cls, name)
116 print("%s: %r" % (name, value), file=file)
117
118 def __instancecheck__(cls, instance):
119 """Override for isinstance(instance, cls)."""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000120 # Inline the cache checking
121 subclass = instance.__class__
122 if subclass in cls._abc_cache:
123 return True
124 subtype = type(instance)
125 if subtype is subclass:
126 if (cls._abc_negative_cache_version ==
127 ABCMeta._abc_invalidation_counter and
128 subclass in cls._abc_negative_cache):
129 return False
130 # Fall back to the subclass check.
131 return cls.__subclasscheck__(subclass)
132 return any(cls.__subclasscheck__(c) for c in {subclass, subtype})
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000133
134 def __subclasscheck__(cls, subclass):
135 """Override for issubclass(subclass, cls)."""
136 # Check cache
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000137 if subclass in cls._abc_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000138 return True
139 # Check negative cache; may have to invalidate
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000140 if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000141 # Invalidate the negative cache
Georg Brandl3b8cb172007-10-23 06:26:46 +0000142 cls._abc_negative_cache = WeakSet()
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000143 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
144 elif subclass in cls._abc_negative_cache:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000145 return False
146 # Check the subclass hook
147 ok = cls.__subclasshook__(subclass)
148 if ok is not NotImplemented:
149 assert isinstance(ok, bool)
150 if ok:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000151 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000152 else:
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000153 cls._abc_negative_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000154 return ok
155 # Check if it's a direct subclass
Christian Heimes043d6f62008-01-07 17:19:16 +0000156 if cls in getattr(subclass, '__mro__', ()):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000157 cls._abc_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000158 return True
159 # Check if it's a subclass of a registered class (recursive)
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000160 for rcls in cls._abc_registry:
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000161 if issubclass(subclass, rcls):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000162 cls._abc_registry.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000163 return True
164 # Check if it's a subclass of a subclass (recursive)
165 for scls in cls.__subclasses__():
166 if issubclass(subclass, scls):
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000167 cls._abc_registry.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000168 return True
169 # No dice; update negative cache
Guido van Rossumc1e315d2007-08-20 19:29:24 +0000170 cls._abc_negative_cache.add(subclass)
Guido van Rossum8518bdc2007-06-14 00:03:37 +0000171 return False