Home | History | Annotate | Download | only in Lib
      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
    186