mirror of
https://github.com/python/cpython.git
synced 2025-11-13 07:26:31 +00:00
Fix #16832 - expose cache validity checking support in ABCMeta
This commit is contained in:
parent
b961955e95
commit
eadd8cf507
3 changed files with 34 additions and 0 deletions
|
|
@ -58,6 +58,10 @@ This module provides the following classes:
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
Returns the registered subclass, to allow usage as a class decorator.
|
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:
|
You can also override this method in an abstract base class:
|
||||||
|
|
||||||
.. method:: __subclasshook__(subclass)
|
.. method:: __subclasshook__(subclass)
|
||||||
|
|
@ -308,6 +312,19 @@ The :mod:`abc` module also provides the following decorators:
|
||||||
:func:`abstractmethod`, making this decorator redundant.
|
: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
|
.. rubric:: Footnotes
|
||||||
|
|
||||||
.. [#] C++ programmers should note that Python's virtual base class
|
.. [#] C++ programmers should note that Python's virtual base class
|
||||||
|
|
|
||||||
14
Lib/abc.py
14
Lib/abc.py
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
from _weakrefset import WeakSet
|
from _weakrefset import WeakSet
|
||||||
|
|
||||||
|
|
||||||
def abstractmethod(funcobj):
|
def abstractmethod(funcobj):
|
||||||
"""A decorator indicating abstract methods.
|
"""A decorator indicating abstract methods.
|
||||||
|
|
||||||
|
|
@ -124,6 +125,8 @@ class ABCMeta(type):
|
||||||
# A global counter that is incremented each time a class is
|
# A global counter that is incremented each time a class is
|
||||||
# registered as a virtual subclass of anything. It forces the
|
# registered as a virtual subclass of anything. It forces the
|
||||||
# negative cache to be cleared before its next use.
|
# 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
|
_abc_invalidation_counter = 0
|
||||||
|
|
||||||
def __new__(mcls, name, bases, namespace):
|
def __new__(mcls, name, bases, namespace):
|
||||||
|
|
@ -227,8 +230,19 @@ class ABCMeta(type):
|
||||||
cls._abc_negative_cache.add(subclass)
|
cls._abc_negative_cache.add(subclass)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class ABC(metaclass=ABCMeta):
|
class ABC(metaclass=ABCMeta):
|
||||||
"""Helper class that provides a standard way to create an ABC using
|
"""Helper class that provides a standard way to create an ABC using
|
||||||
inheritance.
|
inheritance.
|
||||||
"""
|
"""
|
||||||
pass
|
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
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,10 @@ class TestABC(unittest.TestCase):
|
||||||
b = B()
|
b = B()
|
||||||
self.assertFalse(isinstance(b, A))
|
self.assertFalse(isinstance(b, A))
|
||||||
self.assertFalse(isinstance(b, (A,)))
|
self.assertFalse(isinstance(b, (A,)))
|
||||||
|
token_old = abc.get_cache_token()
|
||||||
A.register(B)
|
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))
|
||||||
self.assertTrue(isinstance(b, (A,)))
|
self.assertTrue(isinstance(b, (A,)))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue