Skip to content

Commit e54c6eb

Browse files
feat(simulators): Add created_time and simulation_time filters to simulation runs list method (#2274)
Co-authored-by: Luis Pereira <91738660+lpereiracgn@users.noreply.github.com>
1 parent 15bc400 commit e54c6eb

4 files changed

Lines changed: 84 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ As of 2025-08-29, changes are grouped as follows
2121
### Added
2222
- Add `timezone` as an optional param to the WorkflowScheduledTriggerRule.
2323

24+
## [Unreleased]
25+
### Added
26+
- [alpha] Support for `created_time` and `simulation_time` filters in `client.simulators.runs.list()` to filter simulation runs by timestamp ranges.
27+
2428
## [7.82.1] - 2025-08-28
2529
### Fixed
2630
- Fix documentation of files.upload_content. It does not support directories. Use more meaningful errors when the path is not a file.

cognite/client/_api/simulators/runs.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from cognite.client._api_client import APIClient
77
from cognite.client._constants import DEFAULT_LIMIT_READ
8+
from cognite.client.data_classes.shared import TimestampRange
89
from cognite.client.data_classes.simulators.filters import SimulatorRunsFilter
910
from cognite.client.data_classes.simulators.runs import (
1011
SimulationRun,
@@ -64,6 +65,8 @@ def __call__(
6465
routine_external_ids: SequenceNotStr[str] | None = None,
6566
routine_revision_external_ids: SequenceNotStr[str] | None = None,
6667
model_revision_external_ids: SequenceNotStr[str] | None = None,
68+
created_time: TimestampRange | None = None,
69+
simulation_time: TimestampRange | None = None,
6770
) -> Iterator[SimulationRunList]: ...
6871

6972
@overload
@@ -79,6 +82,8 @@ def __call__(
7982
routine_external_ids: SequenceNotStr[str] | None = None,
8083
routine_revision_external_ids: SequenceNotStr[str] | None = None,
8184
model_revision_external_ids: SequenceNotStr[str] | None = None,
85+
created_time: TimestampRange | None = None,
86+
simulation_time: TimestampRange | None = None,
8287
) -> Iterator[SimulationRun]: ...
8388

8489
def __call__(
@@ -93,6 +98,8 @@ def __call__(
9398
routine_external_ids: SequenceNotStr[str] | None = None,
9499
routine_revision_external_ids: SequenceNotStr[str] | None = None,
95100
model_revision_external_ids: SequenceNotStr[str] | None = None,
101+
created_time: TimestampRange | None = None,
102+
simulation_time: TimestampRange | None = None,
96103
) -> Iterator[SimulationRun] | Iterator[SimulationRunList]:
97104
"""Iterate over simulation runs
98105
@@ -109,6 +116,8 @@ def __call__(
109116
routine_external_ids (SequenceNotStr[str] | None): Filter by routine external ids
110117
routine_revision_external_ids (SequenceNotStr[str] | None): Filter by routine revision external ids
111118
model_revision_external_ids (SequenceNotStr[str] | None): Filter by model revision external ids
119+
created_time (TimestampRange | None): Filter by created time
120+
simulation_time (TimestampRange | None): Filter by simulation time
112121
113122
Returns:
114123
Iterator[SimulationRun] | Iterator[SimulationRunList]: yields Simulation Run one by one if chunk is not specified, else SimulatorRunsList objects.
@@ -123,6 +132,8 @@ def __call__(
123132
routine_external_ids=routine_external_ids,
124133
routine_revision_external_ids=routine_revision_external_ids,
125134
model_revision_external_ids=model_revision_external_ids,
135+
created_time=created_time,
136+
simulation_time=simulation_time,
126137
)
127138

128139
return self._list_generator(
@@ -145,6 +156,8 @@ def list(
145156
routine_external_ids: SequenceNotStr[str] | None = None,
146157
routine_revision_external_ids: SequenceNotStr[str] | None = None,
147158
model_revision_external_ids: SequenceNotStr[str] | None = None,
159+
created_time: TimestampRange | None = None,
160+
simulation_time: TimestampRange | None = None,
148161
) -> SimulationRunList:
149162
"""`Filter simulation runs <https://developer.cognite.com/api#tag/Simulation-Runs/operation/filter_simulation_runs_simulators_runs_list_post>`_
150163
@@ -160,6 +173,8 @@ def list(
160173
routine_external_ids (SequenceNotStr[str] | None): Filter by routine external ids
161174
routine_revision_external_ids (SequenceNotStr[str] | None): Filter by routine revision external ids
162175
model_revision_external_ids (SequenceNotStr[str] | None): Filter by model revision external ids
176+
created_time (TimestampRange | None): Filter by created time
177+
simulation_time (TimestampRange | None): Filter by simulation time
163178
164179
Returns:
165180
SimulationRunList: List of simulation runs
@@ -175,6 +190,13 @@ def list(
175190
... simulator_external_ids=["PROSPER", "DWSIM"],
176191
... status="success"
177192
... )
193+
194+
Filter runs by time ranges:
195+
>>> from cognite.client.data_classes.shared import TimestampRange
196+
>>> res = client.simulators.runs.list(
197+
... created_time=TimestampRange(min=0, max=1_700_000_000_000),
198+
... simulation_time=TimestampRange(min=0, max=1_700_000_000_000),
199+
... )
178200
"""
179201

180202
filter_runs = SimulatorRunsFilter(
@@ -186,6 +208,8 @@ def list(
186208
routine_external_ids=routine_external_ids,
187209
routine_revision_external_ids=routine_revision_external_ids,
188210
model_revision_external_ids=model_revision_external_ids,
211+
created_time=created_time,
212+
simulation_time=simulation_time,
189213
)
190214
self._warning.warn()
191215
return self._list(

cognite/client/data_classes/simulators/filters.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ def __init__(
6363
routine_external_ids: str | SequenceNotStr[str] | None = None,
6464
routine_revision_external_ids: str | SequenceNotStr[str] | None = None,
6565
model_revision_external_ids: str | SequenceNotStr[str] | None = None,
66+
created_time: TimestampRange | None = None,
67+
simulation_time: TimestampRange | None = None,
6668
) -> None:
6769
self.model_external_ids = _parse_str_or_sequence(model_external_ids)
6870
self.simulator_integration_external_ids = _parse_str_or_sequence(simulator_integration_external_ids)
@@ -72,6 +74,8 @@ def __init__(
7274
self.model_revision_external_ids = _parse_str_or_sequence(model_revision_external_ids)
7375
self.status = status
7476
self.run_type = run_type
77+
self.created_time = created_time
78+
self.simulation_time = simulation_time
7579

7680

7781
class SimulatorRoutinesFilter(CogniteFilter):

tests/tests_integration/test_api/test_simulators/test_runs.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55

66
from cognite.client._cognite_client import CogniteClient
7+
from cognite.client.data_classes import TimestampRange
78
from cognite.client.data_classes.simulators.runs import (
89
SimulationInput,
910
SimulationOutput,
@@ -123,6 +124,57 @@ def test_create_run(
123124
assert created_runs[0].routine_external_id == routine_external_id
124125
assert created_runs[0].id is not None
125126

127+
def test_list_filtering_timestamp_ranges(
128+
self, cognite_client: CogniteClient, seed_resource_names: ResourceNames
129+
) -> None:
130+
routine_external_id = seed_resource_names.simulator_routine_external_id
131+
132+
# Create a run to ensure we have something to filter
133+
created_run = cognite_client.simulators.runs.create(
134+
[
135+
SimulationRunWrite(
136+
run_type="external",
137+
routine_external_id=routine_external_id,
138+
)
139+
]
140+
)
141+
created_run_time = created_run[0].created_time
142+
143+
# Set a specific simulation time for our test run
144+
test_simulation_time = int(time.time() * 1000) - 5000 # 5 seconds ago
145+
cognite_client.simulators._post(
146+
"/simulators/run/callback",
147+
json={
148+
"items": [
149+
{
150+
"id": created_run[0].id,
151+
"status": "success",
152+
"simulationTime": test_simulation_time,
153+
}
154+
]
155+
},
156+
)
157+
158+
# Test filtering by created_time and simulation_time - use a narrow range around the created run
159+
runs_filtered_both = cognite_client.simulators.runs.list(
160+
routine_external_ids=[routine_external_id],
161+
created_time=TimestampRange(min=created_run_time - 1000, max=created_run_time + 1000),
162+
simulation_time=TimestampRange(min=test_simulation_time - 1000, max=test_simulation_time + 1000),
163+
limit=100,
164+
)
165+
assert len(runs_filtered_both) > 0
166+
assert created_run[0].id in [run.id for run in runs_filtered_both]
167+
168+
# Test with empty time range for created_time and simulation_time (should return no results)
169+
current_time_ms = int(time.time() * 1000)
170+
runs_empty_range = cognite_client.simulators.runs.list(
171+
routine_external_ids=[routine_external_id],
172+
created_time=TimestampRange(min=current_time_ms + 20000, max=current_time_ms + 30000),
173+
simulation_time=TimestampRange(min=current_time_ms + 20000, max=current_time_ms + 30000),
174+
limit=5,
175+
)
176+
assert len(runs_empty_range) == 0
177+
126178
def test_list_run_data(self, cognite_client: CogniteClient, seed_resource_names: ResourceNames) -> None:
127179
routine_external_id = seed_resource_names.simulator_routine_external_id
128180
created_run = cognite_client.simulators.runs.create(

0 commit comments

Comments
 (0)