diff --git a/tests/utils/test_sentinel.py b/tests/utils/test_sentinel.py index ebf06be0..dea22cf8 100644 --- a/tests/utils/test_sentinel.py +++ b/tests/utils/test_sentinel.py @@ -17,7 +17,13 @@ class SentinelTestCase(TestCase): self.assertEqual(sentinel('a', 'b').__doc__, 'b') def test_doc_differentiates(self): - self.assertIsNot(sentinel('a', 'b'), sentinel('a', 'c')) + a = sentinel('sentinel-name', 'original-doc') + with self.assertRaises(ValueError) as e: + sentinel(a.__name__, 'new-doc') + + msg = str(e.exception) + self.assertIn(a.__name__, msg) + self.assertIn(a.__doc__, msg) def test_memo(self): self.assertIs(sentinel('a'), sentinel('a')) diff --git a/zipline/utils/sentinel.py b/zipline/utils/sentinel.py index bcccca2d..db03122c 100644 --- a/zipline/utils/sentinel.py +++ b/zipline/utils/sentinel.py @@ -8,9 +8,17 @@ import sys def sentinel(name, doc=None): try: - return sentinel._cache[name, doc] # memoized + value = sentinel._cache[name] # memoized except KeyError: pass + else: + if doc == value.__doc__: + return value + + raise ValueError( + 'attempted to create sentinel with a used name and a different' + ' docstring: %r\noriginal docstring:\n%s' % (name, value.__doc__), + ) @object.__new__ # bind a single instance to the name 'Sentinel' class Sentinel(object): @@ -41,6 +49,6 @@ def sentinel(name, doc=None): # Couldn't get the name from the calling scope, just use None. cls.__module__ = None - sentinel._cache[name, doc] = Sentinel # cache result + sentinel._cache[name] = Sentinel # cache result return Sentinel sentinel._cache = {}