Skip to content

Commit d9c956f

Browse files
Issue #20804: The unittest.mock.sentinel attributes now preserve their
identity when they are copied or pickled.
1 parent d4f5001 commit d9c956f

5 files changed

Lines changed: 33 additions & 0 deletions

File tree

Doc/library/unittest.mock.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,10 @@ sentinel
18311831
the same attribute will always return the same object. The objects
18321832
returned have a sensible repr so that test failure messages are readable.
18331833

1834+
.. versionchanged:: 3.7
1835+
The ``sentinel`` attributes now preserve their identity when they are
1836+
:mod:`copied <copy>` or :mod:`pickled <pickle>`.
1837+
18341838
Sometimes when testing you need to test that a specific object is passed as an
18351839
argument to another method, or returned. It can be common to create named
18361840
sentinel objects to test this. :data:`sentinel` provides a convenient way of

Doc/whatsnew/3.7.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ New Modules
9393
Improved Modules
9494
================
9595

96+
unittest.mock
97+
-------------
98+
99+
The :const:`~unittest.mock.sentinel` attributes now preserve their identity
100+
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`.
101+
(Contributed by Serhiy Storchaka in :issue:`20804`.)
102+
96103

97104
Optimizations
98105
=============

Lib/unittest/mock.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ def __init__(self, name):
238238
def __repr__(self):
239239
return 'sentinel.%s' % self.name
240240

241+
def __reduce__(self):
242+
return 'sentinel.%s' % self.name
243+
241244

242245
class _Sentinel(object):
243246
"""Access attributes to return a named object, usable as a sentinel."""
@@ -250,6 +253,9 @@ def __getattr__(self, name):
250253
raise AttributeError
251254
return self._sentinels.setdefault(name, _SentinelObject(name))
252255

256+
def __reduce__(self):
257+
return 'sentinel'
258+
253259

254260
sentinel = _Sentinel()
255261

Lib/unittest/test/testmock/testsentinel.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import unittest
2+
import copy
3+
import pickle
24
from unittest.mock import sentinel, DEFAULT
35

46

@@ -23,6 +25,17 @@ def testBases(self):
2325
# If this doesn't raise an AttributeError then help(mock) is broken
2426
self.assertRaises(AttributeError, lambda: sentinel.__bases__)
2527

28+
def testPickle(self):
29+
for proto in range(pickle.HIGHEST_PROTOCOL+1):
30+
with self.subTest(protocol=proto):
31+
pickled = pickle.dumps(sentinel.whatever, proto)
32+
unpickled = pickle.loads(pickled)
33+
self.assertIs(unpickled, sentinel.whatever)
34+
35+
def testCopy(self):
36+
self.assertIs(copy.copy(sentinel.whatever), sentinel.whatever)
37+
self.assertIs(copy.deepcopy(sentinel.whatever), sentinel.whatever)
38+
2639

2740
if __name__ == '__main__':
2841
unittest.main()

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ Core and Builtins
212212
Library
213213
-------
214214

215+
- Issue #20804: The unittest.mock.sentinel attributes now preserve their
216+
identity when they are copied or pickled.
217+
215218
- Issue #29142: In urllib.request, suffixes in no_proxy environment variable with
216219
leading dots could match related hostnames again (e.g. .b.c matches a.b.c).
217220
Patch by Milan Oberkirch.

0 commit comments

Comments
 (0)