Skip to content

Commit 19f9c58

Browse files
committed
Fix targeted clear coverage and pickle flow
1 parent 37ac0b1 commit 19f9c58

8 files changed

Lines changed: 87 additions & 5 deletions

File tree

src/cachier/cores/pickle.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,14 @@ async def _aset_entry(self, key: str, func_res: Any) -> bool:
272272
return self._set_entry(key, func_res)
273273

274274
def mark_entry_being_calculated_separate_files(self, key: str) -> None:
275-
self._save_cache(
276-
CacheEntry(value=None, time=datetime.now(), stale=False, _processing=True),
277-
separate_file_key=key,
275+
entry = self._load_cache_by_key(key) or CacheEntry(
276+
value=None,
277+
time=datetime.now(),
278+
stale=False,
279+
_processing=False,
278280
)
281+
entry._processing = True
282+
self._save_cache(entry, separate_file_key=key)
279283

280284
def _mark_entry_not_calculated_separate_files(self, key: str) -> None:
281285
_, entry = self.get_entry_by_key(key)

tests/mongo_tests/clients.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,11 @@ async def delete_many(self, query=None, **kwargs):
6969
del self._docs[key]
7070
deleted += 1
7171
return {"deleted_count": deleted}
72+
73+
async def delete_one(self, query=None, **kwargs):
74+
if query is None:
75+
query = kwargs.get("filter", {})
76+
key = (query.get("func"), query.get("key"))
77+
existed = key in self._docs
78+
self._docs.pop(key, None)
79+
return {"deleted_count": int(existed)}

tests/mongo_tests/test_async_mongo_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ async def test_async_mongo_core_mark_clear_and_stale_paths():
152152

153153
await core.amark_entry_being_calculated("fresh")
154154
await core.amark_entry_not_calculated("fresh")
155+
await core.aclear_cache_entry("fresh")
156+
assert (core._func_str, "fresh") not in collection._docs
157+
158+
await core.aset_entry("fresh", 2)
155159
await core.aclear_being_calculated()
156160
await core.adelete_stale_entries(timedelta(hours=1))
157161

tests/pickle_tests/test_pickle_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def test_being_calc_next_time(separate_files):
287287
separate_files=separate_files,
288288
)
289289
_being_calc_next_time_decorated.clear_cache()
290-
_being_calc_next_time(0.13, 0.02)
290+
_being_calc_next_time_decorated(0.13, 0.02)
291291
sleep(1.1)
292292
res_queue = queue.Queue()
293293
thread1 = threading.Thread(

tests/redis_tests/test_async_redis_core.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,14 @@ async def test_async_redis_core_mark_and_clear_paths():
224224
assert clean1._processing is False
225225
assert clean2._processing is False
226226

227+
await core.aclear_cache_entry("cleanup-1")
228+
_, cleared_one = await core.aget_entry_by_key("cleanup-1")
229+
_, kept = await core.aget_entry_by_key("cleanup-2")
230+
assert cleared_one is None
231+
assert kept is not None
232+
227233
await core.aclear_cache()
228-
_, cleared = await core.aget_entry_by_key("cleanup-1")
234+
_, cleared = await core.aget_entry_by_key("cleanup-2")
229235
assert cleared is None
230236

231237
await core.aclear_cache()
@@ -252,6 +258,11 @@ async def test_async_redis_core_mark_and_clear_exceptions():
252258
with pytest.warns(UserWarning, match="Redis clear_cache failed"):
253259
await core.aclear_cache()
254260

261+
client.fail_keys = False
262+
client.fail_delete = True
263+
with pytest.warns(UserWarning, match="Redis clear_cache_entry failed"):
264+
await core.aclear_cache_entry("k")
265+
255266

256267
@pytest.mark.redis
257268
@pytest.mark.asyncio

tests/redis_tests/test_redis_core_exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ def test_clear_cache_exceptions(self, core, mock_redis):
9696
with pytest.warns(UserWarning, match="Redis clear_cache failed"):
9797
core.clear_cache()
9898

99+
def test_clear_cache_entry_exceptions(self, core, mock_redis):
100+
"""Test clear_cache_entry Redis delete exception handling."""
101+
mock_redis.delete.side_effect = Exception("Redis error")
102+
with pytest.warns(UserWarning, match="Redis clear_cache_entry failed"):
103+
core.clear_cache_entry("key")
104+
99105
def test_clear_being_calculated_exceptions(self, core, mock_redis):
100106
"""Test clear_being_calculated Redis keys exception handling."""
101107
mock_redis.keys.side_effect = Exception("Redis error")

tests/s3_tests/test_s3_core.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,16 @@ def _dummy(x):
699699
core.clear_cache()
700700
assert client.delete_objects.call_count == 2
701701

702+
client.delete_object = Mock(return_value=None)
703+
core.clear_cache_entry("k")
704+
assert client.delete_object.called
705+
706+
client.delete_object = Mock(side_effect=RuntimeError("delete failed"))
707+
with warnings.catch_warnings(record=True) as caught:
708+
warnings.simplefilter("always")
709+
core.clear_cache_entry("k")
710+
assert any("clear_cache_entry failed" in str(w.message) for w in caught)
711+
702712
client.get_paginator = Mock(side_effect=RuntimeError("paginate failed"))
703713
with warnings.catch_warnings(record=True) as caught:
704714
warnings.simplefilter("always")

tests/sql_tests/test_async_sql_core.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,45 @@ async def test_sqlcore_async_session_requires_async_engine():
138138
await core._get_async_session()
139139

140140

141+
@pytest.mark.sql
142+
@pytest.mark.asyncio
143+
async def test_async_sql_clear_cache_entry_executes_delete(monkeypatch):
144+
core = _SQLCore.__new__(_SQLCore)
145+
core._func_str = "test_func"
146+
147+
class FakeSession:
148+
def __init__(self):
149+
self.executed = []
150+
self.committed = False
151+
152+
async def __aenter__(self):
153+
return self
154+
155+
async def __aexit__(self, exc_type, exc, tb):
156+
return None
157+
158+
async def execute(self, stmt):
159+
self.executed.append(stmt)
160+
161+
async def commit(self):
162+
self.committed = True
163+
164+
session = FakeSession()
165+
166+
def session_factory():
167+
return session
168+
169+
async def fake_get_async_session():
170+
return session_factory
171+
172+
monkeypatch.setattr(core, "_get_async_session", fake_get_async_session)
173+
174+
await core.aclear_cache_entry("one-key")
175+
176+
assert session.executed
177+
assert session.committed is True
178+
179+
141180
@pytest.mark.sql
142181
@pytest.mark.asyncio
143182
async def test_sqlcore_async_session_creates_tables_once(async_sql_engine):

0 commit comments

Comments
 (0)