|
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 |
|
6 |
|
7 def abstractmethod(funcobj): |
|
8 """A decorator indicating abstract methods. |
|
9 |
|
10 Requires that the metaclass is ABCMeta or derived from it. A |
|
11 class that has a metaclass derived from ABCMeta cannot be |
|
12 instantiated unless all of its abstract methods are overridden. |
|
13 The abstract methods can be called using any of the the normal |
|
14 'super' call mechanisms. |
|
15 |
|
16 Usage: |
|
17 |
|
18 class C(metaclass=ABCMeta): |
|
19 @abstractmethod |
|
20 def my_abstract_method(self, ...): |
|
21 ... |
|
22 """ |
|
23 funcobj.__isabstractmethod__ = True |
|
24 return funcobj |
|
25 |
|
26 |
|
27 class abstractproperty(property): |
|
28 """A decorator indicating abstract properties. |
|
29 |
|
30 Requires that the metaclass is ABCMeta or derived from it. A |
|
31 class that has a metaclass derived from ABCMeta cannot be |
|
32 instantiated unless all of its abstract properties are overridden. |
|
33 The abstract properties can be called using any of the the normal |
|
34 'super' call mechanisms. |
|
35 |
|
36 Usage: |
|
37 |
|
38 class C(metaclass=ABCMeta): |
|
39 @abstractproperty |
|
40 def my_abstract_property(self): |
|
41 ... |
|
42 |
|
43 This defines a read-only property; you can also define a read-write |
|
44 abstract property using the 'long' form of property declaration: |
|
45 |
|
46 class C(metaclass=ABCMeta): |
|
47 def getx(self): ... |
|
48 def setx(self, value): ... |
|
49 x = abstractproperty(getx, setx) |
|
50 """ |
|
51 __isabstractmethod__ = True |
|
52 |
|
53 |
|
54 class ABCMeta(type): |
|
55 |
|
56 """Metaclass for defining Abstract Base Classes (ABCs). |
|
57 |
|
58 Use this metaclass to create an ABC. An ABC can be subclassed |
|
59 directly, and then acts as a mix-in class. You can also register |
|
60 unrelated concrete classes (even built-in classes) and unrelated |
|
61 ABCs as 'virtual subclasses' -- these and their descendants will |
|
62 be considered subclasses of the registering ABC by the built-in |
|
63 issubclass() function, but the registering ABC won't show up in |
|
64 their MRO (Method Resolution Order) nor will method |
|
65 implementations defined by the registering ABC be callable (not |
|
66 even via super()). |
|
67 |
|
68 """ |
|
69 |
|
70 # A global counter that is incremented each time a class is |
|
71 # registered as a virtual subclass of anything. It forces the |
|
72 # negative cache to be cleared before its next use. |
|
73 _abc_invalidation_counter = 0 |
|
74 |
|
75 def __new__(mcls, name, bases, namespace): |
|
76 cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace) |
|
77 # Compute set of abstract method names |
|
78 abstracts = set(name |
|
79 for name, value in namespace.items() |
|
80 if getattr(value, "__isabstractmethod__", False)) |
|
81 for base in bases: |
|
82 for name in getattr(base, "__abstractmethods__", set()): |
|
83 value = getattr(cls, name, None) |
|
84 if getattr(value, "__isabstractmethod__", False): |
|
85 abstracts.add(name) |
|
86 cls.__abstractmethods__ = frozenset(abstracts) |
|
87 # Set up inheritance registry |
|
88 cls._abc_registry = set() |
|
89 cls._abc_cache = set() |
|
90 cls._abc_negative_cache = set() |
|
91 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter |
|
92 return cls |
|
93 |
|
94 def register(cls, subclass): |
|
95 """Register a virtual subclass of an ABC.""" |
|
96 if not isinstance(cls, type): |
|
97 raise TypeError("Can only register classes") |
|
98 if issubclass(subclass, cls): |
|
99 return # Already a subclass |
|
100 # Subtle: test for cycles *after* testing for "already a subclass"; |
|
101 # this means we allow X.register(X) and interpret it as a no-op. |
|
102 if issubclass(cls, subclass): |
|
103 # This would create a cycle, which is bad for the algorithm below |
|
104 raise RuntimeError("Refusing to create an inheritance cycle") |
|
105 cls._abc_registry.add(subclass) |
|
106 ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache |
|
107 |
|
108 def _dump_registry(cls, file=None): |
|
109 """Debug helper to print the ABC registry.""" |
|
110 print >> file, "Class: %s.%s" % (cls.__module__, cls.__name__) |
|
111 print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter |
|
112 for name in sorted(cls.__dict__.keys()): |
|
113 if name.startswith("_abc_"): |
|
114 value = getattr(cls, name) |
|
115 print >> file, "%s: %r" % (name, value) |
|
116 |
|
117 def __instancecheck__(cls, instance): |
|
118 """Override for isinstance(instance, cls).""" |
|
119 # Inline the cache checking when it's simple. |
|
120 subclass = getattr(instance, '__class__', None) |
|
121 if subclass in cls._abc_cache: |
|
122 return True |
|
123 subtype = type(instance) |
|
124 if subtype is subclass or subclass is None: |
|
125 if (cls._abc_negative_cache_version == |
|
126 ABCMeta._abc_invalidation_counter and |
|
127 subtype in cls._abc_negative_cache): |
|
128 return False |
|
129 # Fall back to the subclass check. |
|
130 return cls.__subclasscheck__(subtype) |
|
131 return (cls.__subclasscheck__(subclass) or |
|
132 cls.__subclasscheck__(subtype)) |
|
133 |
|
134 def __subclasscheck__(cls, subclass): |
|
135 """Override for issubclass(subclass, cls).""" |
|
136 # Check cache |
|
137 if subclass in cls._abc_cache: |
|
138 return True |
|
139 # Check negative cache; may have to invalidate |
|
140 if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: |
|
141 # Invalidate the negative cache |
|
142 cls._abc_negative_cache = set() |
|
143 cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter |
|
144 elif subclass in cls._abc_negative_cache: |
|
145 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: |
|
151 cls._abc_cache.add(subclass) |
|
152 else: |
|
153 cls._abc_negative_cache.add(subclass) |
|
154 return ok |
|
155 # Check if it's a direct subclass |
|
156 if cls in getattr(subclass, '__mro__', ()): |
|
157 cls._abc_cache.add(subclass) |
|
158 return True |
|
159 # Check if it's a subclass of a registered class (recursive) |
|
160 for rcls in cls._abc_registry: |
|
161 if issubclass(subclass, rcls): |
|
162 cls._abc_cache.add(subclass) |
|
163 return True |
|
164 # Check if it's a subclass of a subclass (recursive) |
|
165 for scls in cls.__subclasses__(): |
|
166 if issubclass(subclass, scls): |
|
167 cls._abc_cache.add(subclass) |
|
168 return True |
|
169 # No dice; update negative cache |
|
170 cls._abc_negative_cache.add(subclass) |
|
171 return False |