mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-10-09 16:06:40 +00:00
fix(cache): distinguish callables in the shared EMS cache
Include the function object in cache keys so methods of one interpolator cannot reuse a probability as a power value. Cover both call orders, keyword arguments, cache hits and separate closures with identical qualified names.
This commit is contained in:
@@ -228,6 +228,9 @@ def cache_energy_management(
|
|||||||
|
|
||||||
cached_wrapper = cachebox.cached(
|
cached_wrapper = cachebox.cached(
|
||||||
cache=CacheEnergyManagementStore().cache,
|
cache=CacheEnergyManagementStore().cache,
|
||||||
|
# This store is shared by all decorated callables, including methods
|
||||||
|
# on the same instance. Arguments alone cannot identify their results.
|
||||||
|
key_maker=lambda *args, **kwargs: cachebox.make_key(func, *args, **kwargs),
|
||||||
callback=cache_energy_management_store_callback,
|
callback=cache_energy_management_store_callback,
|
||||||
)(wrapper)
|
)(wrapper)
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,55 @@ class TestCacheUntilUpdateDecorators:
|
|||||||
assert CacheEnergyManagementStore.hit_count == 1
|
assert CacheEnergyManagementStore.hit_count == 1
|
||||||
assert result1 == result2
|
assert result1 == result2
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("reverse", [False, True])
|
||||||
|
@pytest.mark.parametrize("use_kwargs", [False, True])
|
||||||
|
def test_methods_with_identical_arguments_keep_separate_results(
|
||||||
|
self, cache_energy_management_store, reverse, use_kwargs
|
||||||
|
):
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
class Model:
|
||||||
|
@cache_energy_management
|
||||||
|
def fraction(self, value):
|
||||||
|
calls.append("fraction")
|
||||||
|
return value / 1000
|
||||||
|
|
||||||
|
@cache_energy_management
|
||||||
|
def energy(self, value):
|
||||||
|
calls.append("energy")
|
||||||
|
return value * 1000
|
||||||
|
|
||||||
|
model = Model()
|
||||||
|
cases = [(model.fraction, 0.005), (model.energy, 5000)]
|
||||||
|
if reverse:
|
||||||
|
cases.reverse()
|
||||||
|
for _ in range(2):
|
||||||
|
for method, expected in cases:
|
||||||
|
result = method(value=5) if use_kwargs else method(5)
|
||||||
|
assert result == expected
|
||||||
|
assert sorted(calls) == ["energy", "fraction"]
|
||||||
|
assert CacheEnergyManagementStore.miss_count == 2
|
||||||
|
assert CacheEnergyManagementStore.hit_count == 2
|
||||||
|
|
||||||
|
def test_distinct_closures_with_same_name_do_not_share_results(
|
||||||
|
self, cache_energy_management_store
|
||||||
|
):
|
||||||
|
def make_function(factor):
|
||||||
|
@cache_energy_management
|
||||||
|
def compute(value):
|
||||||
|
return value * factor
|
||||||
|
return compute
|
||||||
|
|
||||||
|
double = make_function(2)
|
||||||
|
triple = make_function(3)
|
||||||
|
assert double.__qualname__ == triple.__qualname__
|
||||||
|
assert double(4) == 8
|
||||||
|
assert triple(4) == 12
|
||||||
|
assert double(4) == 8
|
||||||
|
assert triple(4) == 12
|
||||||
|
assert CacheEnergyManagementStore.miss_count == 2
|
||||||
|
assert CacheEnergyManagementStore.hit_count == 2
|
||||||
|
|
||||||
def test_cache_energy_management(self, cache_energy_management_store):
|
def test_cache_energy_management(self, cache_energy_management_store):
|
||||||
"""Test that cache_energy_management caches function results."""
|
"""Test that cache_energy_management caches function results."""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user