From 2a1f6c35501be5d650247ffbe3c7cf5cc3b1c8f0 Mon Sep 17 00:00:00 2001 From: Jose Luis Franco Arza Date: Thu, 15 Jan 2026 11:20:58 +0100 Subject: [PATCH] Convert from datetime.timedelta to int in objectTTL properties. The objectTTL deltaTTL returns a datetime.timedelta object, therefore, when invoking todict() we need to cast into int so that we are returning a well formed json. --- test/collection/test_config.py | 86 +++++++++++++++++++++ weaviate/collections/classes/config_base.py | 4 + 2 files changed, 90 insertions(+) diff --git a/test/collection/test_config.py b/test/collection/test_config.py index eab0a82b2..ddfdb33fc 100644 --- a/test/collection/test_config.py +++ b/test/collection/test_config.py @@ -1,3 +1,4 @@ +from datetime import timedelta from typing import List, Union import pytest @@ -11,6 +12,7 @@ Vectorizers, _CollectionConfigCreate, _GenerativeProvider, + _ObjectTTLConfig, _RerankerProvider, _VectorizerConfigCreate, ) @@ -2519,3 +2521,87 @@ def test_config_with_vectors(vector_config: List[_VectorConfigCreate], expected: "class": "Test", "vectorConfig": expected, } + + +TEST_OBJECT_TTL_CONFIG_TO_DICT_PARAMETERS = [ + # delete_by_creation_time + ( + _ObjectTTLConfig( + enabled=True, + time_to_live=timedelta(hours=24), + filter_expired_objects=True, + delete_on="creationTime", + ), + { + "enabled": True, + "timeToLive": 86400, + "filterExpiredObjects": True, + "deleteOn": "creationTime", + }, + ), + # delete_by_update_time + ( + _ObjectTTLConfig( + enabled=True, + time_to_live=timedelta(days=7), + filter_expired_objects=False, + delete_on="updateTime", + ), + { + "enabled": True, + "timeToLive": 604800, + "filterExpiredObjects": False, + "deleteOn": "updateTime", + }, + ), + # delete_by_date_property + ( + _ObjectTTLConfig( + enabled=True, + time_to_live=timedelta(hours=1, minutes=30), + filter_expired_objects=True, + delete_on="releaseDate", + ), + { + "enabled": True, + "timeToLive": 5400, + "filterExpiredObjects": True, + "deleteOn": "releaseDate", + }, + ), + # None time_to_live + ( + _ObjectTTLConfig( + enabled=True, + time_to_live=None, + filter_expired_objects=False, + delete_on="creationTime", + ), + { + "enabled": True, + "filterExpiredObjects": False, + "deleteOn": "creationTime", + }, + ), + # negative offset (delete_by_date_property with offset before date) + ( + _ObjectTTLConfig( + enabled=True, + time_to_live=timedelta(seconds=-3600), + filter_expired_objects=True, + delete_on="eventDate", + ), + { + "enabled": True, + "timeToLive": -3600, + "filterExpiredObjects": True, + "deleteOn": "eventDate", + }, + ), +] + + +@pytest.mark.parametrize("ttl_config,expected", TEST_OBJECT_TTL_CONFIG_TO_DICT_PARAMETERS) +def test_object_ttl_config_to_dict(ttl_config: _ObjectTTLConfig, expected: dict) -> None: + """Test that _ObjectTTLConfig.to_dict() properly converts timedelta to seconds.""" + assert ttl_config.to_dict() == expected diff --git a/weaviate/collections/classes/config_base.py b/weaviate/collections/classes/config_base.py index 2ad42bad6..98099e8b1 100644 --- a/weaviate/collections/classes/config_base.py +++ b/weaviate/collections/classes/config_base.py @@ -1,5 +1,6 @@ from abc import abstractmethod from dataclasses import dataclass +from datetime import timedelta from enum import Enum from typing import Any, Dict, cast @@ -59,6 +60,9 @@ def to_dict(self) -> dict: if isinstance(v, Enum): out[key] = v.value continue + if isinstance(v, timedelta): + out[key] = int(v.total_seconds()) + continue if isinstance(v, dict): out[key] = { k: v.to_dict() if isinstance(v, _ConfigBase) else v for k, v in v.items()