Skip to content

Commit 18ed9c5

Browse files
authored
Merge pull request #1106 from hkad98/jkd/bounded-filter
feat: add bounded filter
2 parents f793506 + a3b2ce2 commit 18ed9c5

File tree

6 files changed

+94
-60
lines changed

6 files changed

+94
-60
lines changed

gooddata-pipelines/poetry.lock

Lines changed: 9 additions & 51 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gooddata-sdk/gooddata_sdk/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@
253253
AllMetricValueFilter,
254254
AllTimeFilter,
255255
AttributeFilter,
256+
BoundedFilter,
256257
Filter,
257258
InlineFilter,
258259
MetricValueFilter,

gooddata-sdk/gooddata_sdk/compute/compute_to_sdk_converter.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from gooddata_sdk.compute.model.filter import (
77
AbsoluteDateFilter,
88
AllTimeFilter,
9+
BoundedFilter,
910
Filter,
1011
MetricValueFilter,
1112
NegativeAttributeFilter,
@@ -71,11 +72,22 @@ def convert_filter(filter_dict: dict[str, Any]) -> Filter:
7172
if ("from" not in f) or ("to" not in f):
7273
return AllTimeFilter(ref_extract_obj_id(f["dataset"]))
7374

75+
# Extract bounded filter if present
76+
bounded_filter = None
77+
if "boundedFilter" in f:
78+
bf = f["boundedFilter"]
79+
bounded_filter = BoundedFilter(
80+
granularity=bf["granularity"],
81+
from_shift=bf.get("from"),
82+
to_shift=bf.get("to"),
83+
)
84+
7485
return RelativeDateFilter(
7586
dataset=ref_extract_obj_id(f["dataset"]),
7687
granularity=f["granularity"],
7788
from_shift=f["from"],
7889
to_shift=f["to"],
90+
bounded_filter=bounded_filter,
7991
)
8092

8193
if "absoluteDateFilter" in filter_dict:

gooddata-sdk/gooddata_sdk/compute/model/filter.py

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from importlib.util import find_spec
66
from typing import Any, Optional, Union
77

8+
import attrs
89
from gooddata_api_client.model.inline_filter_definition_inline import InlineFilterDefinitionInline
910

1011
if find_spec("icu") is not None:
@@ -153,8 +154,35 @@ def description(self, labels: dict[str, str], format_locale: Optional[str] = Non
153154
}
154155

155156

157+
@attrs.define
158+
class BoundedFilter:
159+
granularity: str
160+
from_shift: Optional[int] = None
161+
to_shift: Optional[int] = None
162+
163+
def __attrs_post_init__(self) -> None:
164+
# Validate that exactly one of from_shift or to_shift is set
165+
if (self.from_shift is None) == (self.to_shift is None):
166+
raise ValueError("BoundedFilter requires exactly one of `from_shift` or `to_shift` to be set.")
167+
168+
def as_api_model(self) -> afm_models.BoundedFilter:
169+
return afm_models.BoundedFilter(
170+
granularity=self.granularity,
171+
_from=self.from_shift,
172+
to=self.to_shift,
173+
_check_type=False,
174+
)
175+
176+
156177
class RelativeDateFilter(Filter):
157-
def __init__(self, dataset: ObjId, granularity: str, from_shift: int, to_shift: int) -> None:
178+
def __init__(
179+
self,
180+
dataset: ObjId,
181+
granularity: str,
182+
from_shift: int,
183+
to_shift: int,
184+
bounded_filter: Optional[BoundedFilter] = None,
185+
) -> None:
158186
super().__init__()
159187

160188
if granularity not in _GRANULARITY:
@@ -166,6 +194,7 @@ def __init__(self, dataset: ObjId, granularity: str, from_shift: int, to_shift:
166194
self._granularity = granularity
167195
self._from_shift = from_shift
168196
self._to_shift = to_shift
197+
self._bounded_filter = bounded_filter
169198

170199
@property
171200
def dataset(self) -> ObjId:
@@ -183,17 +212,26 @@ def from_shift(self) -> int:
183212
def to_shift(self) -> int:
184213
return self._to_shift
185214

215+
@property
216+
def bounded_filter(self) -> Optional[BoundedFilter]:
217+
return self._bounded_filter
218+
186219
def is_noop(self) -> bool:
187220
return False
188221

189222
def as_api_model(self) -> afm_models.RelativeDateFilter:
190-
body = RelativeDateFilterBody(
191-
dataset=self.dataset.as_afm_id(),
192-
granularity=self.granularity,
193-
_from=self.from_shift,
194-
to=self.to_shift,
195-
_check_type=False,
196-
)
223+
body_params = {
224+
"dataset": self.dataset.as_afm_id(),
225+
"granularity": self.granularity,
226+
"_from": self.from_shift,
227+
"to": self.to_shift,
228+
"_check_type": False,
229+
}
230+
231+
if self.bounded_filter is not None:
232+
body_params["bounded_filter"] = self.bounded_filter.as_api_model()
233+
234+
body = RelativeDateFilterBody(**body_params)
197235
return afm_models.RelativeDateFilter(body)
198236

199237
def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str:

0 commit comments

Comments
 (0)