summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/abc.rst17
-rw-r--r--Lib/abc.py14
-rw-r--r--Lib/test/test_abc.py3
3 files changed, 34 insertions, 0 deletions
diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst
index 27abb60..1f21b57 100644
--- a/Doc/library/abc.rst
+++ b/Doc/library/abc.rst
@@ -58,6 +58,10 @@ This module provides the following classes:
.. versionchanged:: 3.3
Returns the registered subclass, to allow usage as a class decorator.
+ .. versionchanged:: 3.4
+ To detect calls to :meth:`register`, you can use the
+ :func:`get_cache_token` function.
+
You can also override this method in an abstract base class:
.. method:: __subclasshook__(subclass)
@@ -308,6 +312,19 @@ The :mod:`abc` module also provides the following decorators:
:func:`abstractmethod`, making this decorator redundant.
+The :mod:`abc` module also provides the following functions:
+
+.. function:: get_cache_token()
+
+ Returns the current abstract base class cache token.
+
+ The token is an opaque integer identifying the current version of the
+ abstract base class cache for virtual subclasses. This number changes
+ with every call to :meth:`ABCMeta.register` on any ABC.
+
+ .. versionadded:: 3.4
+
+
.. rubric:: Footnotes
.. [#] C++ programmers should note that Python's virtual base class
diff --git a/Lib/abc.py b/Lib/abc.py
index e807895..264c60c 100644
--- a/Lib/abc.py
+++ b/Lib/abc.py
@@ -5,6 +5,7 @@
from _weakrefset import WeakSet
+
def abstractmethod(funcobj):
"""A decorator indicating abstract methods.
@@ -124,6 +125,8 @@ class ABCMeta(type):
# 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):
@@ -227,8 +230,19 @@ class ABCMeta(type):
cls._abc_negative_cache.add(subclass)
return False
+
class ABC(metaclass=ABCMeta):
"""Helper class that provides a standard way to create an ABC using
inheritance.
"""
pass
+
+
+def get_cache_token():
+ """Returns the current ABC cache token.
+
+ The token is an opaque integer identifying the current version of
+ the ABC cache for virtual subclasses. This number changes with
+ every call to ``register()`` on any ABC.
+ """
+ return ABCMeta._abc_invalidation_counter
diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py
index 3498524..4b15157 100644
--- a/Lib/test/test_abc.py
+++ b/Lib/test/test_abc.py
@@ -329,7 +329,10 @@ class TestABC(unittest.TestCase):
b = B()
self.assertFalse(isinstance(b, A))
self.assertFalse(isinstance(b, (A,)))
+ token_old = abc.get_cache_token()
A.register(B)
+ token_new = abc.get_cache_token()
+ self.assertNotEqual(token_old, token_new)
self.assertTrue(isinstance(b, A))
self.assertTrue(isinstance(b, (A,)))