(original) (raw)
diff -r 37794a002517 Doc/library/abc.rst --- a/Doc/library/abc.rst Sat May 25 11:33:13 2013 -0400 +++ b/Doc/library/abc.rst Sat May 25 18:26:46 2013 +0200 @@ -58,6 +58,10 @@ .. 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 @@ :func:`abstractmethod`, making this decorator redundant. +The :mod:`abc` module also provides the following functions: + +.. function:: get_cache_token() + + A function returning the current abstract base class cache token. + + Returns an integer representing 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 -r 37794a002517 Lib/abc.py --- a/Lib/abc.py Sat May 25 11:33:13 2013 -0400 +++ b/Lib/abc.py Sat May 25 18:26:46 2013 +0200 @@ -5,6 +5,7 @@ from _weakrefset import WeakSet + def abstractmethod(funcobj): """A decorator indicating abstract methods. @@ -124,6 +125,8 @@ # 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 @@ 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(): + """A function returning the current ABC cache token. + + Returns an integer representing 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 -r 37794a002517 Lib/test/test_abc.py --- a/Lib/test/test_abc.py Sat May 25 11:33:13 2013 -0400 +++ b/Lib/test/test_abc.py Sat May 25 18:26:46 2013 +0200 @@ -329,7 +329,10 @@ 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.assertTrue(token_old < token_new) self.assertTrue(isinstance(b, A)) self.assertTrue(isinstance(b, (A,)))