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