bpo-31333: Re-implement ABCMeta in C (#5273)

This adds C versions of methods used by ABCMeta that
improve performance of various ABC operations.
diff --git a/Lib/abc.py b/Lib/abc.py
index 9bdc36d..7094141 100644
--- a/Lib/abc.py
+++ b/Lib/abc.py
@@ -3,8 +3,6 @@
 
 """Abstract Base Classes (ABCs) according to PEP 3119."""
 
-from _weakrefset import WeakSet
-
 
 def abstractmethod(funcobj):
     """A decorator indicating abstract methods.
@@ -27,8 +25,7 @@
 
 
 class abstractclassmethod(classmethod):
-    """
-    A decorator indicating abstract classmethods.
+    """A decorator indicating abstract classmethods.
 
     Similar to abstractmethod.
 
@@ -51,8 +48,7 @@
 
 
 class abstractstaticmethod(staticmethod):
-    """
-    A decorator indicating abstract staticmethods.
+    """A decorator indicating abstract staticmethods.
 
     Similar to abstractmethod.
 
@@ -75,8 +71,7 @@
 
 
 class abstractproperty(property):
-    """
-    A decorator indicating abstract properties.
+    """A decorator indicating abstract properties.
 
     Requires that the metaclass is ABCMeta or derived from it.  A
     class that has a metaclass derived from ABCMeta cannot be
@@ -106,131 +101,66 @@
     __isabstractmethod__ = True
 
 
-class ABCMeta(type):
+try:
+    from _abc import (get_cache_token, _abc_init, _abc_register,
+                      _abc_instancecheck, _abc_subclasscheck, _get_dump,
+                      _reset_registry, _reset_caches)
+except ImportError:
+    from _py_abc import ABCMeta, get_cache_token
+    ABCMeta.__module__ = 'abc'
+else:
+    class ABCMeta(type):
+        """Metaclass for defining Abstract Base Classes (ABCs).
 
-    """Metaclass for defining Abstract Base Classes (ABCs).
-
-    Use this metaclass to create an ABC.  An ABC can be subclassed
-    directly, and then acts as a mix-in class.  You can also register
-    unrelated concrete classes (even built-in classes) and unrelated
-    ABCs as 'virtual subclasses' -- these and their descendants will
-    be considered subclasses of the registering ABC by the built-in
-    issubclass() function, but the registering ABC won't show up in
-    their MRO (Method Resolution Order) nor will method
-    implementations defined by the registering ABC be callable (not
-    even via super()).
-
-    """
-
-    # A global counter that is incremented each time a class is
-    # registered as a virtual subclass of anything.  It forces the
-    # negative cache to be cleared before its next use.
-    # Note: this counter is private. Use `abc.get_cache_token()` for
-    #       external code.
-    _abc_invalidation_counter = 0
-
-    def __new__(mcls, name, bases, namespace, **kwargs):
-        cls = super().__new__(mcls, name, bases, namespace, **kwargs)
-        # Compute set of abstract method names
-        abstracts = {name
-                     for name, value in namespace.items()
-                     if getattr(value, "__isabstractmethod__", False)}
-        for base in bases:
-            for name in getattr(base, "__abstractmethods__", set()):
-                value = getattr(cls, name, None)
-                if getattr(value, "__isabstractmethod__", False):
-                    abstracts.add(name)
-        cls.__abstractmethods__ = frozenset(abstracts)
-        # Set up inheritance registry
-        cls._abc_registry = WeakSet()
-        cls._abc_cache = WeakSet()
-        cls._abc_negative_cache = WeakSet()
-        cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
-        return cls
-
-    def register(cls, subclass):
-        """Register a virtual subclass of an ABC.
-
-        Returns the subclass, to allow usage as a class decorator.
+        Use this metaclass to create an ABC.  An ABC can be subclassed
+        directly, and then acts as a mix-in class.  You can also register
+        unrelated concrete classes (even built-in classes) and unrelated
+        ABCs as 'virtual subclasses' -- these and their descendants will
+        be considered subclasses of the registering ABC by the built-in
+        issubclass() function, but the registering ABC won't show up in
+        their MRO (Method Resolution Order) nor will method
+        implementations defined by the registering ABC be callable (not
+        even via super()).
         """
-        if not isinstance(subclass, type):
-            raise TypeError("Can only register classes")
-        if issubclass(subclass, cls):
-            return subclass  # Already a subclass
-        # Subtle: test for cycles *after* testing for "already a subclass";
-        # this means we allow X.register(X) and interpret it as a no-op.
-        if issubclass(cls, subclass):
-            # This would create a cycle, which is bad for the algorithm below
-            raise RuntimeError("Refusing to create an inheritance cycle")
-        cls._abc_registry.add(subclass)
-        ABCMeta._abc_invalidation_counter += 1  # Invalidate negative cache
-        return subclass
+        def __new__(mcls, name, bases, namespace, **kwargs):
+            cls = super().__new__(mcls, name, bases, namespace, **kwargs)
+            _abc_init(cls)
+            return cls
 
-    def _dump_registry(cls, file=None):
-        """Debug helper to print the ABC registry."""
-        print("Class: %s.%s" % (cls.__module__, cls.__qualname__), file=file)
-        print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file)
-        for name in cls.__dict__:
-            if name.startswith("_abc_"):
-                value = getattr(cls, name)
-                if isinstance(value, WeakSet):
-                    value = set(value)
-                print("%s: %r" % (name, value), file=file)
+        def register(cls, subclass):
+            """Register a virtual subclass of an ABC.
 
-    def __instancecheck__(cls, instance):
-        """Override for isinstance(instance, cls)."""
-        # Inline the cache checking
-        subclass = instance.__class__
-        if subclass in cls._abc_cache:
-            return True
-        subtype = type(instance)
-        if subtype is subclass:
-            if (cls._abc_negative_cache_version ==
-                ABCMeta._abc_invalidation_counter and
-                subclass in cls._abc_negative_cache):
-                return False
-            # Fall back to the subclass check.
-            return cls.__subclasscheck__(subclass)
-        return any(cls.__subclasscheck__(c) for c in {subclass, subtype})
+            Returns the subclass, to allow usage as a class decorator.
+            """
+            return _abc_register(cls, subclass)
 
-    def __subclasscheck__(cls, subclass):
-        """Override for issubclass(subclass, cls)."""
-        # Check cache
-        if subclass in cls._abc_cache:
-            return True
-        # Check negative cache; may have to invalidate
-        if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
-            # Invalidate the negative cache
-            cls._abc_negative_cache = WeakSet()
-            cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
-        elif subclass in cls._abc_negative_cache:
-            return False
-        # Check the subclass hook
-        ok = cls.__subclasshook__(subclass)
-        if ok is not NotImplemented:
-            assert isinstance(ok, bool)
-            if ok:
-                cls._abc_cache.add(subclass)
-            else:
-                cls._abc_negative_cache.add(subclass)
-            return ok
-        # Check if it's a direct subclass
-        if cls in getattr(subclass, '__mro__', ()):
-            cls._abc_cache.add(subclass)
-            return True
-        # Check if it's a subclass of a registered class (recursive)
-        for rcls in cls._abc_registry:
-            if issubclass(subclass, rcls):
-                cls._abc_cache.add(subclass)
-                return True
-        # Check if it's a subclass of a subclass (recursive)
-        for scls in cls.__subclasses__():
-            if issubclass(subclass, scls):
-                cls._abc_cache.add(subclass)
-                return True
-        # No dice; update negative cache
-        cls._abc_negative_cache.add(subclass)
-        return False
+        def __instancecheck__(cls, instance):
+            """Override for isinstance(instance, cls)."""
+            return _abc_instancecheck(cls, instance)
+
+        def __subclasscheck__(cls, subclass):
+            """Override for issubclass(subclass, cls)."""
+            return _abc_subclasscheck(cls, subclass)
+
+        def _dump_registry(cls, file=None):
+            """Debug helper to print the ABC registry."""
+            print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
+            print(f"Inv. counter: {get_cache_token()}", file=file)
+            (_abc_registry, _abc_cache, _abc_negative_cache,
+             _abc_negative_cache_version) = _get_dump(cls)
+            print(f"_abc_registry: {_abc_registry!r}", file=file)
+            print(f"_abc_cache: {_abc_cache!r}", file=file)
+            print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file)
+            print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}",
+                  file=file)
+
+        def _abc_registry_clear(cls):
+            """Clear the registry (for debugging or testing)."""
+            _reset_registry(cls)
+
+        def _abc_caches_clear(cls):
+            """Clear the caches (for debugging or testing)."""
+            _reset_caches(cls)
 
 
 class ABC(metaclass=ABCMeta):
@@ -238,13 +168,3 @@
     inheritance.
     """
     __slots__ = ()
-
-
-def get_cache_token():
-    """Returns the current ABC cache token.
-
-    The token is an opaque object (supporting equality testing) identifying the
-    current version of the ABC cache for virtual subclasses. The token changes
-    with every call to ``register()`` on any ABC.
-    """
-    return ABCMeta._abc_invalidation_counter