(original) (raw)

changeset: 106095:98f061402fcf user: Serhiy Storchaka storchaka@gmail.com date: Wed Jan 11 20:13:03 2017 +0200 files: Doc/library/unittest.mock.rst Doc/whatsnew/3.7.rst Lib/unittest/mock.py Lib/unittest/test/testmock/testsentinel.py Misc/NEWS description: Issue #20804: The unittest.mock.sentinel attributes now preserve their identity when they are copied or pickled. diff -r a76eed0baa0f -r 98f061402fcf Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst Wed Jan 11 17:44:07 2017 +0000 +++ b/Doc/library/unittest.mock.rst Wed Jan 11 20:13:03 2017 +0200 @@ -1831,6 +1831,10 @@ the same attribute will always return the same object. The objects returned have a sensible repr so that test failure messages are readable. + .. versionchanged:: 3.7 + The ``sentinel`` attributes now preserve their identity when they are + :mod:`copied ` or :mod:`pickled `. + Sometimes when testing you need to test that a specific object is passed as an argument to another method, or returned. It can be common to create named sentinel objects to test this. :data:`sentinel` provides a convenient way of diff -r a76eed0baa0f -r 98f061402fcf Doc/whatsnew/3.7.rst --- a/Doc/whatsnew/3.7.rst Wed Jan 11 17:44:07 2017 +0000 +++ b/Doc/whatsnew/3.7.rst Wed Jan 11 20:13:03 2017 +0200 @@ -93,6 +93,13 @@ Improved Modules ================ +unittest.mock +------------- + +The :const:`~unittest.mock.sentinel` attributes now preserve their identity +when they are :mod:`copied ` or :mod:`pickled `. +(Contributed by Serhiy Storchaka in :issue:`20804`.) + Optimizations ============= diff -r a76eed0baa0f -r 98f061402fcf Lib/unittest/mock.py --- a/Lib/unittest/mock.py Wed Jan 11 17:44:07 2017 +0000 +++ b/Lib/unittest/mock.py Wed Jan 11 20:13:03 2017 +0200 @@ -238,6 +238,9 @@ def __repr__(self): return 'sentinel.%s' % self.name + def __reduce__(self): + return 'sentinel.%s' % self.name + class _Sentinel(object): """Access attributes to return a named object, usable as a sentinel.""" @@ -250,6 +253,9 @@ raise AttributeError return self._sentinels.setdefault(name, _SentinelObject(name)) + def __reduce__(self): + return 'sentinel' + sentinel = _Sentinel() diff -r a76eed0baa0f -r 98f061402fcf Lib/unittest/test/testmock/testsentinel.py --- a/Lib/unittest/test/testmock/testsentinel.py Wed Jan 11 17:44:07 2017 +0000 +++ b/Lib/unittest/test/testmock/testsentinel.py Wed Jan 11 20:13:03 2017 +0200 @@ -1,4 +1,6 @@ import unittest +import copy +import pickle from unittest.mock import sentinel, DEFAULT @@ -23,6 +25,17 @@ # If this doesn't raise an AttributeError then help(mock) is broken self.assertRaises(AttributeError, lambda: sentinel.__bases__) + def testPickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL+1): + with self.subTest(protocol=proto): + pickled = pickle.dumps(sentinel.whatever, proto) + unpickled = pickle.loads(pickled) + self.assertIs(unpickled, sentinel.whatever) + + def testCopy(self): + self.assertIs(copy.copy(sentinel.whatever), sentinel.whatever) + self.assertIs(copy.deepcopy(sentinel.whatever), sentinel.whatever) + if __name__ == '__main__': unittest.main() diff -r a76eed0baa0f -r 98f061402fcf Misc/NEWS --- a/Misc/NEWS Wed Jan 11 17:44:07 2017 +0000 +++ b/Misc/NEWS Wed Jan 11 20:13:03 2017 +0200 @@ -212,6 +212,9 @@ Library ------- +- Issue #20804: The unittest.mock.sentinel attributes now preserve their + identity when they are copied or pickled. + - Issue #29142: In urllib.request, suffixes in no_proxy environment variable with leading dots could match related hostnames again (e.g. .b.c matches a.b.c). Patch by Milan Oberkirch./storchaka@gmail.com