From a059d30cad103bc6866ac264ced8feb371ba9fa1 Mon Sep 17 00:00:00 2001 From: Stef Pletinck Date: Mon, 24 Nov 2025 10:39:32 +0100 Subject: [PATCH] Fix: CORE Filter serialization The Filter class' str method would not be called, and the pydantic serialization logic could not deduce it. Add an explicit field serializer to make it str. --- src/obelisk/asynchronous/core.py | 10 +++++++++- src/tests/asynchronous/core_test.py | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/obelisk/asynchronous/core.py b/src/obelisk/asynchronous/core.py index 2007ef8..51f2089 100644 --- a/src/obelisk/asynchronous/core.py +++ b/src/obelisk/asynchronous/core.py @@ -24,6 +24,7 @@ model_validator, SerializerFunctionWrapHandler, WrapSerializer, + field_serializer, ) from typing import ( Annotated, @@ -157,7 +158,7 @@ class QueryParams(BaseModel): """List of Field Names, with their potential prefixes and suffixes, to select ordering. None user server defaults.""" dataType: DataType | None = None """Data type expected to be returned, is mandatory if the `value` field is requested in the `fields` parameter""" - filter_: Annotated[str | Filter | None, Field(serialization_alias="filter")] = None + filter_: Annotated[str | Filter | None, Field(serialization_alias="filter",)] = None """ Obelisk CORE handles filtering in [RSQL format](https://obelisk.pages.ilabt.imec.be/obelisk-core/query.html#rsql-format), to make it easier to also programatically write these filters, we provide the `obelisk.types.core.Filter` option as well. @@ -181,6 +182,13 @@ def to_dict(self) -> dict[str, Any]: exclude_none=True, by_alias=True, mode="json", exclude={"dataset"} ) + @field_serializer('filter_', mode='plain') + def serialize_filter(self, value: Filter | str | None) -> str | None: + if value is None or isinstance(value, str): + return value + + return str(value) + class ChunkedParams(BaseModel): """ diff --git a/src/tests/asynchronous/core_test.py b/src/tests/asynchronous/core_test.py index 7f8c8c2..d7747b0 100644 --- a/src/tests/asynchronous/core_test.py +++ b/src/tests/asynchronous/core_test.py @@ -1,4 +1,5 @@ from obelisk.asynchronous.core import QueryParams +from obelisk.types.core import Filter, Comparison def test_query_param_serialize(): @@ -24,3 +25,14 @@ def test_comma_separate_string(): assert data["groupBy"] == "dataset,timestamp" assert data["orderBy"] == "timestamp,value" + + +def test_filter_serialize(): + filter_ = Filter().add_and(Comparison.equal("metric", "smartphone.acceleration::number[]"), Comparison.greater_equal("timestamp", 123456)) + q = QueryParams( + dataset="83989232", + filter_=filter_, + dataType="number[]", + ) + dump = q.to_dict() + assert "filter" in dump