diff options
Diffstat (limited to 'Lib/abc.py')
-rw-r--r-- | Lib/abc.py | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/Lib/abc.py b/Lib/abc.py index 02e48a1bb32..a6c2dc48779 100644 --- a/Lib/abc.py +++ b/Lib/abc.py @@ -3,15 +3,8 @@ """Abstract Base Classes (ABCs) according to PEP 3119.""" -import types - from _weakrefset import WeakSet -# Instance of old-style class -class _C: pass -_InstanceType = type(_C()) - - def abstractmethod(funcobj): """A decorator indicating abstract methods. @@ -23,8 +16,7 @@ def abstractmethod(funcobj): Usage: - class C: - __metaclass__ = ABCMeta + class C(metaclass=ABCMeta): @abstractmethod def my_abstract_method(self, ...): ... @@ -33,6 +25,46 @@ def abstractmethod(funcobj): return funcobj +class abstractclassmethod(classmethod): + """A decorator indicating abstract classmethods. + + Similar to abstractmethod. + + Usage: + + class C(metaclass=ABCMeta): + @abstractclassmethod + def my_abstract_classmethod(cls, ...): + ... + """ + + __isabstractmethod__ = True + + def __init__(self, callable): + callable.__isabstractmethod__ = True + super().__init__(callable) + + +class abstractstaticmethod(staticmethod): + """A decorator indicating abstract staticmethods. + + Similar to abstractmethod. + + Usage: + + class C(metaclass=ABCMeta): + @abstractstaticmethod + def my_abstract_staticmethod(...): + ... + """ + + __isabstractmethod__ = True + + def __init__(self, callable): + callable.__isabstractmethod__ = True + super().__init__(callable) + + class abstractproperty(property): """A decorator indicating abstract properties. @@ -44,8 +76,7 @@ class abstractproperty(property): Usage: - class C: - __metaclass__ = ABCMeta + class C(metaclass=ABCMeta): @abstractproperty def my_abstract_property(self): ... @@ -53,8 +84,7 @@ class abstractproperty(property): This defines a read-only property; you can also define a read-write abstract property using the 'long' form of property declaration: - class C: - __metaclass__ = ABCMeta + class C(metaclass=ABCMeta): def getx(self): ... def setx(self, value): ... x = abstractproperty(getx, setx) @@ -84,11 +114,11 @@ class ABCMeta(type): _abc_invalidation_counter = 0 def __new__(mcls, name, bases, namespace): - cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace) + cls = super().__new__(mcls, name, bases, namespace) # Compute set of abstract method names - abstracts = set(name + abstracts = {name for name, value in namespace.items() - if getattr(value, "__isabstractmethod__", False)) + if getattr(value, "__isabstractmethod__", False)} for base in bases: for name in getattr(base, "__abstractmethods__", set()): value = getattr(cls, name, None) @@ -104,7 +134,7 @@ class ABCMeta(type): def register(cls, subclass): """Register a virtual subclass of an ABC.""" - if not isinstance(subclass, (type, types.ClassType)): + if not isinstance(subclass, type): raise TypeError("Can only register classes") if issubclass(subclass, cls): return # Already a subclass @@ -118,32 +148,28 @@ class ABCMeta(type): def _dump_registry(cls, file=None): """Debug helper to print the ABC registry.""" - print >> file, "Class: %s.%s" % (cls.__module__, cls.__name__) - print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter + print("Class: %s.%s" % (cls.__module__, cls.__name__), file=file) + print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file) for name in sorted(cls.__dict__.keys()): if name.startswith("_abc_"): value = getattr(cls, name) - print >> file, "%s: %r" % (name, value) + print("%s: %r" % (name, value), file=file) def __instancecheck__(cls, instance): """Override for isinstance(instance, cls).""" - # Inline the cache checking when it's simple. - subclass = getattr(instance, '__class__', None) - if subclass is not None and subclass in cls._abc_cache: + # Inline the cache checking + subclass = instance.__class__ + if subclass in cls._abc_cache: return True subtype = type(instance) - # Old-style instances - if subtype is _InstanceType: - subtype = subclass - if subtype is subclass or subclass is None: + if subtype is subclass: if (cls._abc_negative_cache_version == ABCMeta._abc_invalidation_counter and - subtype in cls._abc_negative_cache): + subclass in cls._abc_negative_cache): return False # Fall back to the subclass check. - return cls.__subclasscheck__(subtype) - return (cls.__subclasscheck__(subclass) or - cls.__subclasscheck__(subtype)) + return cls.__subclasscheck__(subclass) + return any(cls.__subclasscheck__(c) for c in {subclass, subtype}) def __subclasscheck__(cls, subclass): """Override for issubclass(subclass, cls).""" |