gh-98624 Add mutex to unittest.mock.NonCallableMock (#98688)

* Added lock to NonCallableMock in unittest.mock

* Add blurb

* Nitpick blurb

* Edit comment based on @Jason-Y-Z's review

* Add link to GH issue
This commit is contained in:
noah-weingarden 2022-10-28 03:51:18 -04:00 committed by GitHub
parent fbcafa6eee
commit 0346eddbe9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 27 deletions

View file

@ -35,6 +35,7 @@ from asyncio import iscoroutinefunction
from types import CodeType, ModuleType, MethodType
from unittest.util import safe_repr
from functools import wraps, partial
from threading import RLock
class InvalidSpecError(Exception):
@ -402,6 +403,14 @@ class Base(object):
class NonCallableMock(Base):
"""A non-callable version of `Mock`"""
# Store a mutex as a class attribute in order to protect concurrent access
# to mock attributes. Using a class attribute allows all NonCallableMock
# instances to share the mutex for simplicity.
#
# See https://github.com/python/cpython/issues/98624 for why this is
# necessary.
_lock = RLock()
def __new__(cls, /, *args, **kw):
# every instance has its own class
# so we can create magic methods on the
@ -644,6 +653,7 @@ class NonCallableMock(Base):
f"{name!r} is not a valid assertion. Use a spec "
f"for the mock if {name!r} is meant to be an attribute.")
with NonCallableMock._lock:
result = self._mock_children.get(name)
if result is _deleted:
raise AttributeError(name)

View file

@ -0,0 +1,2 @@
Add a mutex to unittest.mock.NonCallableMock to protect concurrent access
to mock attributes.