Skip to content

Commit 236aa80

Browse files
committed
Fix Object TTL schema export to match server json
1 parent 420b1d0 commit 236aa80

3 files changed

Lines changed: 152 additions & 7 deletions

File tree

integration/test_collection_config.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import weaviate
88
import weaviate.classes as wvc
99
from integration.conftest import (
10+
ClientFactory,
1011
CollectionFactory,
1112
OpenAICollection,
1213
_sanitize_collection_name,
@@ -1950,3 +1951,91 @@ def test_object_ttl_update(collection_factory: CollectionFactory) -> None:
19501951
)
19511952
conf = collection.config.get()
19521953
assert conf.object_ttl_config is None
1954+
1955+
1956+
def test_object_ttl_roundtrip_from_dict(
1957+
collection_factory: CollectionFactory, client_factory: ClientFactory
1958+
) -> None:
1959+
dummy = collection_factory("dummy")
1960+
if dummy._connection._weaviate_version.is_lower_than(1, 35, 0):
1961+
pytest.skip("object ttl is not supported in Weaviate versions lower than 1.35.0")
1962+
1963+
client = client_factory()
1964+
1965+
# (schema_to_create, expected_object_ttl_config_dict)
1966+
test_cases = [
1967+
# deleteOn: _creationTimeUnix
1968+
(
1969+
{
1970+
"class": "CollectionTTLRoundtripCreation",
1971+
"objectTtlConfig": {
1972+
"enabled": True,
1973+
"defaultTtl": 60,
1974+
"deleteOn": "_creationTimeUnix",
1975+
"filterExpiredObjects": True,
1976+
},
1977+
},
1978+
{
1979+
"enabled": True,
1980+
"defaultTtl": 60,
1981+
"deleteOn": "_creationTimeUnix",
1982+
"filterExpiredObjects": True,
1983+
},
1984+
),
1985+
# deleteOn: _lastUpdateTimeUnix
1986+
(
1987+
{
1988+
"class": "CollectionTTLRoundtripUpdate",
1989+
"objectTtlConfig": {
1990+
"enabled": True,
1991+
"defaultTtl": 3600,
1992+
"deleteOn": "_lastUpdateTimeUnix",
1993+
"filterExpiredObjects": True,
1994+
},
1995+
},
1996+
{
1997+
"enabled": True,
1998+
"defaultTtl": 3600,
1999+
"deleteOn": "_lastUpdateTimeUnix",
2000+
"filterExpiredObjects": True,
2001+
},
2002+
),
2003+
# deleteOn: custom date property
2004+
(
2005+
{
2006+
"class": "CollectionTTLRoundtripDateProp",
2007+
"properties": [
2008+
{
2009+
"name": "reference_date",
2010+
"dataType": ["date"],
2011+
}
2012+
],
2013+
"objectTtlConfig": {
2014+
"enabled": True,
2015+
"defaultTtl": 123,
2016+
"deleteOn": "reference_date",
2017+
"filterExpiredObjects": True,
2018+
},
2019+
},
2020+
{
2021+
"enabled": True,
2022+
"defaultTtl": 123,
2023+
"deleteOn": "reference_date",
2024+
"filterExpiredObjects": True,
2025+
},
2026+
),
2027+
]
2028+
2029+
for schema, expected_ttl_dict in test_cases:
2030+
name = schema["class"]
2031+
client.collections.delete(name)
2032+
try:
2033+
client.collections.create_from_dict(schema)
2034+
config = client.collections.export_config(name)
2035+
assert config.object_ttl_config is not None, f"object_ttl_config is None for {name}"
2036+
assert config.object_ttl_config.to_dict() == expected_ttl_dict, (
2037+
f"Round-trip mismatch for {name}: "
2038+
f"got {config.object_ttl_config.to_dict()}, expected {expected_ttl_dict}"
2039+
)
2040+
finally:
2041+
client.collections.delete(name)

test/collection/test_config.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
_RerankerProvider,
1717
_VectorizerConfigCreate,
1818
)
19+
from weaviate.collections.classes.config_methods import _get_object_ttl_config
1920
from weaviate.collections.classes.config_named_vectors import _NamedVectorConfigCreate
2021
from weaviate.collections.classes.config_vectorizers import (
2122
Multi2VecField,
@@ -2621,9 +2622,9 @@ def test_config_with_vectors(vector_config: List[_VectorConfigCreate], expected:
26212622
),
26222623
{
26232624
"enabled": True,
2624-
"timeToLive": 86400,
2625+
"defaultTtl": 86400,
26252626
"filterExpiredObjects": True,
2626-
"deleteOn": "creationTime",
2627+
"deleteOn": "_creationTimeUnix",
26272628
},
26282629
),
26292630
# delete_by_update_time
@@ -2636,9 +2637,9 @@ def test_config_with_vectors(vector_config: List[_VectorConfigCreate], expected:
26362637
),
26372638
{
26382639
"enabled": True,
2639-
"timeToLive": 604800,
2640+
"defaultTtl": 604800,
26402641
"filterExpiredObjects": False,
2641-
"deleteOn": "updateTime",
2642+
"deleteOn": "_lastUpdateTimeUnix",
26422643
},
26432644
),
26442645
# delete_by_date_property
@@ -2651,7 +2652,7 @@ def test_config_with_vectors(vector_config: List[_VectorConfigCreate], expected:
26512652
),
26522653
{
26532654
"enabled": True,
2654-
"timeToLive": 5400,
2655+
"defaultTtl": 5400,
26552656
"filterExpiredObjects": True,
26562657
"deleteOn": "releaseDate",
26572658
},
@@ -2667,7 +2668,7 @@ def test_config_with_vectors(vector_config: List[_VectorConfigCreate], expected:
26672668
{
26682669
"enabled": True,
26692670
"filterExpiredObjects": False,
2670-
"deleteOn": "creationTime",
2671+
"deleteOn": "_creationTimeUnix",
26712672
},
26722673
),
26732674
# negative offset (delete_by_date_property with offset before date)
@@ -2680,7 +2681,7 @@ def test_config_with_vectors(vector_config: List[_VectorConfigCreate], expected:
26802681
),
26812682
{
26822683
"enabled": True,
2683-
"timeToLive": -3600,
2684+
"defaultTtl": -3600,
26842685
"filterExpiredObjects": True,
26852686
"deleteOn": "eventDate",
26862687
},
@@ -2694,6 +2695,45 @@ def test_object_ttl_config_to_dict(ttl_config: _ObjectTTLConfig, expected: dict)
26942695
assert ttl_config.to_dict() == expected
26952696

26962697

2698+
TEST_OBJECT_TTL_ROUNDTRIP_PARAMETERS = [
2699+
# _creationTimeUnix round-trip
2700+
{
2701+
"objectTtlConfig": {
2702+
"enabled": True,
2703+
"defaultTtl": 60,
2704+
"deleteOn": "_creationTimeUnix",
2705+
"filterExpiredObjects": True,
2706+
}
2707+
},
2708+
# _lastUpdateTimeUnix round-trip
2709+
{
2710+
"objectTtlConfig": {
2711+
"enabled": True,
2712+
"defaultTtl": 3600,
2713+
"deleteOn": "_lastUpdateTimeUnix",
2714+
"filterExpiredObjects": True,
2715+
}
2716+
},
2717+
# custom date property round-trip
2718+
{
2719+
"objectTtlConfig": {
2720+
"enabled": True,
2721+
"defaultTtl": 123,
2722+
"deleteOn": "reference_date",
2723+
"filterExpiredObjects": True,
2724+
}
2725+
},
2726+
]
2727+
2728+
2729+
@pytest.mark.parametrize("schema", TEST_OBJECT_TTL_ROUNDTRIP_PARAMETERS)
2730+
def test_object_ttl_config_roundtrip(schema: dict) -> None:
2731+
"""Test that deserializing an objectTtlConfig and calling to_dict() produces the original dict."""
2732+
ttl_config = _get_object_ttl_config(schema)
2733+
assert ttl_config is not None
2734+
assert ttl_config.to_dict() == schema["objectTtlConfig"]
2735+
2736+
26972737
def test_nested_property_with_id_name_is_allowed() -> None:
26982738
"""A nested property named 'id' must not raise — only top-level 'id' is reserved."""
26992739
prop = Property(

weaviate/collections/classes/config.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,22 @@ class _ObjectTTLConfig(_ConfigBase):
19381938
filter_expired_objects: bool
19391939
delete_on: Union[str, Literal["updateTime"], Literal["creationTime"]]
19401940

1941+
def to_dict(self) -> dict:
1942+
delete_on = self.delete_on
1943+
if delete_on == "creationTime":
1944+
delete_on = "_creationTimeUnix"
1945+
elif delete_on == "updateTime":
1946+
delete_on = "_lastUpdateTimeUnix"
1947+
1948+
out: dict = {
1949+
"enabled": self.enabled,
1950+
"filterExpiredObjects": self.filter_expired_objects,
1951+
"deleteOn": delete_on,
1952+
}
1953+
if self.time_to_live is not None:
1954+
out["defaultTtl"] = int(self.time_to_live.total_seconds())
1955+
return out
1956+
19411957

19421958
ObjectTTLConfig = _ObjectTTLConfig
19431959

0 commit comments

Comments
 (0)