From 361dee6dd34ef8095a39b899c0134bb8b3a7d951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Jolovi=C4=87?= Date: Sat, 9 May 2026 00:28:50 +0200 Subject: [PATCH 1/2] Share task timing option parsing --- src/cashet/_client_base.py | 8 ++++++-- src/cashet/_export.py | 11 ++++------- tests/test_export.py | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/cashet/_client_base.py b/src/cashet/_client_base.py index e63b5f2..4045516 100644 --- a/src/cashet/_client_base.py +++ b/src/cashet/_client_base.py @@ -49,12 +49,16 @@ def resolve_task_config( timeout_seconds = ( _timeout if _timeout is not None else getattr(raw_func, "_cashet_timeout", None) ) - timeout = timedelta(seconds=timeout_seconds) if timeout_seconds is not None else None ttl_seconds = _ttl if _ttl is not None else getattr(raw_func, "_cashet_ttl", None) - ttl = timedelta(seconds=ttl_seconds) if ttl_seconds is not None else None + timeout = duration_from_seconds(timeout_seconds) + ttl = duration_from_seconds(ttl_seconds) return raw_func, cache, tags, retries, force, timeout, ttl +def duration_from_seconds(seconds: int | float | None) -> timedelta | None: + return timedelta(seconds=seconds) if seconds else None + + def set_task_metadata( func: Callable[..., Any], task_name: str, diff --git a/src/cashet/_export.py b/src/cashet/_export.py index 0d5a77c..e9c5160 100644 --- a/src/cashet/_export.py +++ b/src/cashet/_export.py @@ -5,11 +5,12 @@ import json import logging import tarfile -from datetime import datetime, timedelta +from datetime import datetime from io import BytesIO from pathlib import Path from typing import Any +from cashet._client_base import duration_from_seconds from cashet.models import Commit, ObjectRef, StorageTier, TaskDef, TaskStatus from cashet.protocols import AsyncStore @@ -59,12 +60,8 @@ def _task_def_to_dict(task_def: TaskDef) -> dict[str, Any]: def _dict_to_task_def(data: dict[str, Any]) -> TaskDef: - timeout: timedelta | None = None - if "timeout" in data and data["timeout"] is not None: - timeout = timedelta(seconds=data["timeout"]) - ttl: timedelta | None = None - if "ttl" in data and data["ttl"] is not None: - ttl = timedelta(seconds=data["ttl"]) + timeout = duration_from_seconds(data.get("timeout")) + ttl = duration_from_seconds(data.get("ttl")) return TaskDef( func_hash=data["func_hash"], func_name=data["func_name"], diff --git a/tests/test_export.py b/tests/test_export.py index a6036d6..9b4a1b2 100644 --- a/tests/test_export.py +++ b/tests/test_export.py @@ -1,6 +1,7 @@ from __future__ import annotations import tarfile +from datetime import timedelta from io import BytesIO from pathlib import Path @@ -76,6 +77,23 @@ def test_import_skips_existing(self, client: Client, tmp_path: Path) -> None: count = client.import_archive(archive) assert count == 0 + def test_export_import_preserves_task_timing_options( + self, client: Client, tmp_path: Path + ) -> None: + ref = client.submit(add, 5, 6, _timeout=1.5, _ttl=900) + assert ref.load() == 11 + + archive = tmp_path / "export.tar.gz" + client.export(archive) + + client2 = Client(store_dir=tmp_path / ".cashet2") + assert client2.import_archive(archive) == 1 + + imported = client2.show(ref.commit_hash) + assert imported is not None + assert imported.task_def.timeout == timedelta(seconds=1.5) + assert imported.task_def.ttl == timedelta(seconds=900) + def test_export_empty_store(self, client: Client, tmp_path: Path) -> None: archive = tmp_path / "empty.tar.gz" client.export(archive) From f035f8df44f9a0c2a6a8089a5fe73e248e336918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Jolovi=C4=87?= Date: Sat, 9 May 2026 00:37:53 +0200 Subject: [PATCH 2/2] Preserve zero-second task durations --- src/cashet/_client_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cashet/_client_base.py b/src/cashet/_client_base.py index 4045516..d28f1e9 100644 --- a/src/cashet/_client_base.py +++ b/src/cashet/_client_base.py @@ -56,7 +56,7 @@ def resolve_task_config( def duration_from_seconds(seconds: int | float | None) -> timedelta | None: - return timedelta(seconds=seconds) if seconds else None + return timedelta(seconds=seconds) if seconds is not None else None def set_task_metadata(