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 from _weakrefset import WeakSet
      7 
      8 
      9 def abstractmethod(funcobj):
     10     """A decorator indicating abstract methods.
     11 
     12     Requires that the metaclass is ABCMeta or derived from it.  A
     13     class that has a metaclass derived from ABCMeta cannot be
     14     instantiated unless all of its abstract methods are overridden.
     15     The abstract methods can be called using any of the normal
     16     'super' call mechanisms.
     17 
     18     Usage:
     19 
     20         class C(metaclass=ABCMeta):
     21             @abstractmethod
     22             def my_abstract_method(self, ...):
     23                 ...
     24     """
     25     funcobj.__isabstractmethod__ = True
     26     return funcobj
     27 
     28 
     29 class abstractclassmethod(classmethod):
     30     """
     31     A decorator indicating abstract classmethods.
     32 
     33     Similar to abstractmethod.
     34 
     35     Usage:
     36 
     37         class C(metaclass=ABCMeta):
     38             @abstractclassmethod
     39             def my_abstract_classmethod(cls, ...):
     40                 ...
     41 
     42     'abstractclassmethod' is deprecated. Use 'classmethod' with
     43     'abstractmethod' instead.
     44     """
     45 
     46     __isabstractmethod__ = True
     47 
     48     def __init__(self, callable):
     49         callable.__isabstractmethod__ = True
     50         super().__init__(callable)
     51 
     52 
     53 class abstractstaticmethod(staticmethod):
     54     """
     55     A decorator indicating abstract staticmethods.
     56 
     57     Similar to abstractmethod.
     58 
     59     Usage:
     60 
     61         class C(metaclass=ABCMeta):
     62             @abstractstaticmethod
     63             def my_abstract_staticmethod(...):
     64                 ...
     65 
     66     'abstractstaticmethod' is deprecated. Use 'staticmethod' with
     67     'abstractmethod' instead.
     68     """
     69 
     70     __isabstractmethod__ = True
     71 
     72     def __init__(self, callable):
     73         callable.__isabstractmethod__ = True
     74         super().__init__(callable)
     75 
     76 
     77 class abstractproperty(property):
     78     """
     79     A decorator indicating abstract properties.
     80 
     81     Requires that the metaclass is ABCMeta or derived from it.  A
     82     class that has a metaclass derived from ABCMeta cannot be
     83     instantiated unless all of its abstract properties are overridden.
     84     The abstract properties can be called using any of the normal
     85     'super' call mechanisms.
     86 
     87     Usage:
     88 
     89         class C(metaclass=ABCMeta):
     90             @abstractproperty
     91             def my_abstract_property(self):
     92                 ...
     93 
     94     This defines a read-only property; you can also define a read-write
     95     abstract property using the 'long' form of property declaration:
     96 
     97         class C(metaclass=ABCMeta):
     98             def getx(self): ...
     99             def setx(self, value): ...
    100             x = abstractproperty(getx, setx)
    101 
    102     'abstractproperty' is deprecated. Use 'property' with 'abstractmethod'
    103     instead.
    104     """
    105 
    106     __isabstractmethod__ = True
    107 
    108 
    109 class ABCMeta(type):
    110 
    111     """Metaclass for defining Abstract Base Classes (ABCs).
    112 
    113     Use this metaclass to create an ABC.  An ABC can be subclassed
    114     directly, and then acts as a mix-in class.  You can also register
    115     unrelated concrete classes (even built-in classes) and unrelated
    116     ABCs as 'virtual subclasses' -- these and their descendants will
    117     be considered subclasses of the registering ABC by the built-in
    118     issubclass() function, but the registering ABC won't show up in
    119     their MRO (Method Resolution Order) nor will method
    120     implementations defined by the registering ABC be callable (not
    121     even via super()).
    122 
    123     """
    124 
    125     # A global counter that is incremented each time a class is
    126     # registered as a virtual subclass of anything.  It forces the
    127     # negative cache to be cleared before its next use.
    128     # Note: this counter is private. Use `abc.get_cache_token()` for
    129     #       external code.
    130     _abc_invalidation_counter = 0
    131 
    132     def __new__(mcls, name, bases, namespace):
    133         cls = super().__new__(mcls, name, bases, namespace)
    134         # Compute set of abstract method names
    135         abstracts = {name
    136                      for name, value in namespace.items()
    137                      if getattr(value, "__isabstractmethod__", False)}
    138         for base in bases:
    139             for name in getattr(base, "__abstractmethods__", set()):
    140                 value = getattr(cls, name, None)
    141                 if getattr(value, "__isabstractmethod__", False):
    142                     abstracts.add(name)
    143         cls.__abstractmethods__ = frozenset(abstracts)
    144         # Set up inheritance registry
    145         cls._abc_registry = WeakSet()
    146         cls._abc_cache = WeakSet()
    147         cls._abc_negative_cache = WeakSet()
    148         cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
    149         return cls
    150 
    151     def register(cls, subclass):
    152         """Register a virtual subclass of an ABC.
    153 
    154         Returns the subclass, to allow usage as a class decorator.
    155         """
    156         if not isinstance(subclass, type):
    157             raise TypeError("Can only register classes")
    158         if issubclass(subclass, cls):
    159             return subclass  # Already a subclass
    160         # Subtle: test for cycles *after* testing for "already a subclass";
    161         # this means we allow X.register(X) and interpret it as a no-op.
    162         if issubclass(cls, subclass):
    163             # This would create a cycle, which is bad for the algorithm below
    164             raise RuntimeError("Refusing to create an inheritance cycle")
    165         cls._abc_registry.add(subclass)
    166         ABCMeta._abc_invalidation_counter += 1  # Invalidate negative cache
    167         return subclass
    168 
    169     def _dump_registry(cls, file=None):
    170         """Debug helper to print the ABC registry."""
    171         print("Class: %s.%s" % (cls.__module__, cls.__qualname__), file=file)
    172         print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file)
    173         for name in sorted(cls.__dict__.keys()):
    174             if name.startswith("_abc_"):
    175                 value = getattr(cls, name)
    176                 print("%s: %r" % (name, value), file=file)
    177 
    178     def __instancecheck__(cls, instance):
    179         """Override for isinstance(instance, cls)."""
    180         # Inline the cache checking
    181         subclass = instance.__class__
    182         if subclass in cls._abc_cache:
    183             return True
    184         subtype = type(instance)
    185         if subtype is subclass:
    186             if (cls._abc_negative_cache_version ==
    187                 ABCMeta._abc_invalidation_counter and
    188                 subclass in cls._abc_negative_cache):
    189                 return False
    190             # Fall back to the subclass check.
    191             return cls.__subclasscheck__(subclass)
    192         return any(cls.__subclasscheck__(c) for c in {subclass, subtype})
    193 
    194     def __subclasscheck__(cls, subclass):
    195         """Override for issubclass(subclass, cls)."""
    196         # Check cache
    197         if subclass in cls._abc_cache:
    198             return True
    199         # Check negative cache; may have to invalidate
    200         if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
    201             # Invalidate the negative cache
    202             cls._abc_negative_cache = WeakSet()
    203             cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
    204         elif subclass in cls._abc_negative_cache:
    205             return False
    206         # Check the subclass hook
    207         ok = cls.__subclasshook__(subclass)
    208         if ok is not NotImplemented:
    209             assert isinstance(ok, bool)
    210             if ok:
    211                 cls._abc_cache.add(subclass)
    212             else:
    213                 cls._abc_negative_cache.add(subclass)
    214             return ok
    215         # Check if it's a direct subclass
    216         if cls in getattr(subclass, '__mro__', ()):
    217             cls._abc_cache.add(subclass)
    218             return True
    219         # Check if it's a subclass of a registered class (recursive)
    220         for rcls in cls._abc_registry:
    221             if issubclass(subclass, rcls):
    222                 cls._abc_cache.add(subclass)
    223                 return True
    224         # Check if it's a subclass of a subclass (recursive)
    225         for scls in cls.__subclasses__():
    226             if issubclass(subclass, scls):
    227                 cls._abc_cache.add(subclass)
    228                 return True
    229         # No dice; update negative cache
    230         cls._abc_negative_cache.add(subclass)
    231         return False
    232 
    233 
    234 class ABC(metaclass=ABCMeta):
    235     """Helper class that provides a standard way to create an ABC using
    236     inheritance.
    237     """
    238     pass
    239 
    240 
    241 def get_cache_token():
    242     """Returns the current ABC cache token.
    243 
    244     The token is an opaque object (supporting equality testing) identifying the
    245     current version of the ABC cache for virtual subclasses. The token changes
    246     with every call to ``register()`` on any ABC.
    247     """
    248     return ABCMeta._abc_invalidation_counter
    249