-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#20] * Added configurable postprocessing, that allows to modify valu…
…e retrieved from the cache * Added built-in implementation, that applies deep-copy * Fix MANIFEST.in
- Loading branch information
Showing
9 changed files
with
159 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
include requirements.txt | ||
include README.rst | ||
include CHANGELOG.md | ||
include CHANGELOG.rst |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import copy | ||
from abc import ABCMeta, abstractmethod | ||
from typing import Any | ||
|
||
ValueType = Any | ||
|
||
|
||
class Postprocessing(metaclass=ABCMeta): | ||
@abstractmethod | ||
def apply(self, original: ValueType) -> ValueType: | ||
"""Transforms value just before returning from the cache.""" | ||
raise NotImplementedError() | ||
|
||
|
||
class NoPostprocessing(Postprocessing): | ||
def apply(self, original: ValueType) -> ValueType: | ||
"""Applies no postprocessing (returns original value).""" | ||
return original | ||
|
||
|
||
class DeepcopyPostprocessing(Postprocessing): | ||
def apply(self, original: ValueType) -> ValueType: | ||
""" | ||
Performs deep copy of the value. Useful when you want to prevent modifying the value cached in memory | ||
(so callers could modify their copies safely). | ||
Have in mind that this operation may be expensive, | ||
and may not be suitable for all types of values (see docs on copy.deepcopy). | ||
""" | ||
return copy.deepcopy(original) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ def prepare_description(): | |
|
||
setup( | ||
name='py-memoize', | ||
version='2.0.0', | ||
version='2.1.0', | ||
author='Michal Zmuda', | ||
author_email='[email protected]', | ||
url='https://github.com/DreamLab/memoize', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
from memoize.postprocessing import DeepcopyPostprocessing | ||
from tests.py310workaround import fix_python_3_10_compatibility | ||
|
||
fix_python_3_10_compatibility() | ||
|
||
from unittest.mock import Mock | ||
|
||
from tornado import gen | ||
from tornado.testing import AsyncTestCase, gen_test | ||
|
||
from memoize.configuration import MutableCacheConfiguration, DefaultInMemoryCacheConfiguration | ||
from memoize.wrapper import memoize | ||
|
||
|
||
class KeyExtractorInteractionsTests(AsyncTestCase): | ||
|
||
@gen_test | ||
def test_postprocessing_is_applied(self): | ||
# given | ||
postprocessing = Mock() | ||
postprocessing.apply = Mock(return_value='overridden-by-postprocessing') | ||
|
||
@memoize( | ||
configuration=MutableCacheConfiguration | ||
.initialized_with(DefaultInMemoryCacheConfiguration()) | ||
.set_postprocessing(postprocessing) | ||
) | ||
@gen.coroutine | ||
def sample_method(arg): | ||
return f"value-for-{arg}" | ||
|
||
# when | ||
result = yield sample_method('test') | ||
|
||
# then | ||
postprocessing.apply.assert_called_once() | ||
postprocessing.apply.assert_called_once_with('value-for-test') | ||
self.assertEqual(result, 'overridden-by-postprocessing') | ||
|
||
@gen_test | ||
def test_postprocessing_based_on_deepcopy_prevents_modifying_value_cached_in_memory(self): | ||
# given | ||
|
||
@memoize( | ||
configuration=MutableCacheConfiguration | ||
.initialized_with(DefaultInMemoryCacheConfiguration()) | ||
.set_postprocessing(DeepcopyPostprocessing()) | ||
) | ||
@gen.coroutine | ||
def sample_method(arg): | ||
return {'arg': arg, 'list': [4, 5, 1, 2, 3]} # unsorted | ||
|
||
# when | ||
result1 = yield sample_method('test') | ||
result2 = yield sample_method('test') | ||
result1['list'].sort() | ||
|
||
# then | ||
self.assertEqual(result1, {'arg': 'test', 'list': [1, 2, 3, 4, 5]}) # sorted in-place | ||
self.assertEqual(result2, {'arg': 'test', 'list': [4, 5, 1, 2, 3]}) # still unsorted |