Skip to content

Commit 05b164b

Browse files
fix(simint): retrieve(..) overloads and enable mypy checks (#2315)
Co-authored-by: erlendvollset <erlendvollset@gmail.com>
1 parent 7a3c785 commit 05b164b

15 files changed

Lines changed: 295 additions & 343 deletions

File tree

.pre-commit-config.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ repos:
2929
hooks:
3030
- id: mypy
3131
name: mypy
32-
# Eventually we want to run mypy on the whole test code base. But for now we only enable it for data modeling tests.
32+
# Eventually we want to run mypy on the whole test code base. But for now we only enable it for data modeling, simulators and datapoints
3333
entry: |
3434
poetry run dmypy run -- cognite tests/tests_integration/test_api/test_data_modeling
3535
tests/tests_unit/test_data_classes/test_data_models
3636
tests/tests_unit/test_utils/test_time.py
3737
tests/tests_integration/test_api/test_datapoints.py
38+
tests/tests_integration/test_api/test_simulators
39+
tests/tests_unit/test_api/test_simulators
40+
tests/tests_unit/test_data_classes/test_simulators.py
3841
files: ^.*.(py|pyi)$
3942
language: system
4043
pass_filenames: false

cognite/client/_api/simulators/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ def __call__(
7070
limit=limit,
7171
)
7272

73-
def list(self, limit: int = DEFAULT_LIMIT_READ) -> SimulatorList:
73+
def list(self, limit: int | None = DEFAULT_LIMIT_READ) -> SimulatorList:
7474
"""`List all simulators <https://developer.cognite.com/api#tag/Simulators/operation/filter_simulators_simulators_list_post>`_
7575
7676
Args:
77-
limit (int): Maximum number of results to return. Defaults to 25. Set to -1, float(“inf”) or None to return all items.
77+
limit (int | None): Maximum number of results to return. Defaults to 25. Set to -1, float(“inf”) or None to return all items.
7878
7979
Returns:
8080
SimulatorList: List of simulators

cognite/client/_api/simulators/models.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from collections.abc import Iterator, Sequence
4-
from typing import TYPE_CHECKING, NoReturn, overload
4+
from typing import TYPE_CHECKING, overload
55

66
from cognite.client._api.simulators.models_revisions import SimulatorModelRevisionsAPI
77
from cognite.client._api_client import APIClient
@@ -37,7 +37,7 @@ def __init__(self, config: ClientConfig, api_version: str | None, cognite_client
3737

3838
def list(
3939
self,
40-
limit: int = DEFAULT_LIMIT_READ,
40+
limit: int | None = DEFAULT_LIMIT_READ,
4141
simulator_external_ids: str | SequenceNotStr[str] | None = None,
4242
sort: PropertySort | None = None,
4343
) -> SimulatorModelList:
@@ -46,7 +46,7 @@ def list(
4646
Retrieves a list of simulator models that match the given criteria.
4747
4848
Args:
49-
limit (int): Maximum number of results to return. Defaults to 25. Set to -1, float(“inf”) or None to return all items.
49+
limit (int | None): Maximum number of results to return. Defaults to 25. Set to -1, float(“inf”) or None to return all items.
5050
simulator_external_ids (str | SequenceNotStr[str] | None): Filter by simulator external id(s).
5151
sort (PropertySort | None): The criteria to sort by.
5252
@@ -82,27 +82,20 @@ def list(
8282
)
8383

8484
@overload
85-
def retrieve(self, ids: None = None, external_ids: None = None) -> NoReturn: ...
85+
def retrieve(self, *, ids: int) -> SimulatorModel | None: ...
8686

8787
@overload
88-
def retrieve(self, ids: int, external_ids: None = None) -> SimulatorModel | None: ...
88+
def retrieve(self, *, external_ids: str) -> SimulatorModel | None: ...
8989

9090
@overload
91-
def retrieve(
92-
self,
93-
ids: None,
94-
external_ids: str,
95-
) -> SimulatorModel | None: ...
91+
def retrieve(self, *, ids: Sequence[int]) -> SimulatorModelList: ...
9692

9793
@overload
98-
def retrieve(
99-
self,
100-
ids: Sequence[int] | None = None,
101-
external_ids: SequenceNotStr[str] | None = None,
102-
) -> SimulatorModelList | None: ...
94+
def retrieve(self, *, external_ids: SequenceNotStr[str]) -> SimulatorModelList: ...
10395

10496
def retrieve(
10597
self,
98+
*,
10699
ids: int | Sequence[int] | None = None,
107100
external_ids: str | SequenceNotStr[str] | None = None,
108101
) -> SimulatorModel | SimulatorModelList | None:

cognite/client/_api/simulators/models_revisions.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from collections.abc import Iterator, Sequence
4-
from typing import TYPE_CHECKING, NoReturn, overload
4+
from typing import TYPE_CHECKING, overload
55

66
from cognite.client._api_client import APIClient
77
from cognite.client._constants import DEFAULT_LIMIT_READ
@@ -90,27 +90,20 @@ def list(
9090
)
9191

9292
@overload
93-
def retrieve(self, ids: None = None, external_ids: None = None) -> NoReturn: ...
93+
def retrieve(self, *, ids: int) -> SimulatorModelRevision | None: ...
9494

9595
@overload
96-
def retrieve(self, ids: int, external_ids: None = None) -> SimulatorModelRevision | None: ...
96+
def retrieve(self, *, external_ids: str) -> SimulatorModelRevision | None: ...
9797

9898
@overload
99-
def retrieve(
100-
self,
101-
ids: None,
102-
external_ids: str,
103-
) -> SimulatorModelRevision | None: ...
99+
def retrieve(self, *, ids: Sequence[int]) -> SimulatorModelRevisionList: ...
104100

105101
@overload
106-
def retrieve(
107-
self,
108-
ids: int | Sequence[int] | None = None,
109-
external_ids: str | SequenceNotStr[str] | None = None,
110-
) -> SimulatorModelRevision | SimulatorModelRevisionList | None: ...
102+
def retrieve(self, *, external_ids: SequenceNotStr[str]) -> SimulatorModelRevisionList: ...
111103

112104
def retrieve(
113105
self,
106+
*,
114107
ids: int | Sequence[int] | None = None,
115108
external_ids: str | SequenceNotStr[str] | None = None,
116109
) -> SimulatorModelRevision | SimulatorModelRevisionList | None:

cognite/client/_api/simulators/routine_revisions.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from collections.abc import Iterator, Sequence
4-
from typing import TYPE_CHECKING, NoReturn, overload
4+
from typing import TYPE_CHECKING, overload
55

66
from cognite.client._api_client import APIClient
77
from cognite.client.data_classes.shared import TimestampRange
@@ -127,27 +127,20 @@ def __call__(
127127
)
128128

129129
@overload
130-
def retrieve(self, ids: None = None, external_ids: None = None) -> NoReturn: ...
130+
def retrieve(self, *, ids: int) -> SimulatorRoutineRevision | None: ...
131131

132132
@overload
133-
def retrieve(self, ids: int, external_ids: None = None) -> SimulatorRoutineRevision | None: ...
133+
def retrieve(self, *, external_ids: str) -> SimulatorRoutineRevision | None: ...
134134

135135
@overload
136-
def retrieve(
137-
self,
138-
ids: None,
139-
external_ids: str,
140-
) -> SimulatorRoutineRevision | None: ...
136+
def retrieve(self, *, ids: Sequence[int]) -> SimulatorRoutineRevisionList: ...
141137

142138
@overload
143-
def retrieve(
144-
self,
145-
ids: Sequence[int] | None = None,
146-
external_ids: SequenceNotStr[str] | None = None,
147-
) -> SimulatorRoutineRevisionList | None: ...
139+
def retrieve(self, *, external_ids: SequenceNotStr[str]) -> SimulatorRoutineRevisionList: ...
148140

149141
def retrieve(
150142
self,
143+
*,
151144
ids: int | Sequence[int] | None = None,
152145
external_ids: str | SequenceNotStr[str] | None = None,
153146
) -> SimulatorRoutineRevision | SimulatorRoutineRevisionList | None:

tests/tests_integration/test_api/test_simulators/conftest.py

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,31 @@
44
import time
55
from collections.abc import Iterator
66
from pathlib import Path
7-
from typing import Any
87

98
import pytest
109

1110
from cognite.client._cognite_client import CogniteClient
1211
from cognite.client.data_classes.data_sets import DataSetWrite
1312
from cognite.client.data_classes.files import FileMetadata
1413
from cognite.client.data_classes.simulators import SimulatorModelWrite
15-
from cognite.client.data_classes.simulators.routine_revisions import SimulatorRoutineRevisionWrite
16-
from cognite.client.data_classes.simulators.routines import SimulatorRoutineWrite
14+
from cognite.client.data_classes.simulators.models import SimulatorModel
15+
from cognite.client.data_classes.simulators.routine_revisions import (
16+
SimulatorRoutineRevision,
17+
SimulatorRoutineRevisionWrite,
18+
)
19+
from cognite.client.data_classes.simulators.routines import (
20+
SimulatorRoutine,
21+
SimulatorRoutineList,
22+
SimulatorRoutineWrite,
23+
)
24+
from cognite.client.utils._text import to_snake_case
1725
from tests.tests_integration.test_api.test_simulators.seed.data import (
1826
RESOURCES,
1927
SIMULATOR,
2028
SIMULATOR_INTEGRATION,
2129
SIMULATOR_MODEL,
2230
SIMULATOR_ROUTINE,
23-
SIMULATOR_ROUTINE_REVISION_OBJ,
31+
SIMULATOR_ROUTINE_REVISION,
2432
ResourceNames,
2533
)
2634
from tests.tests_integration.test_api.test_simulators.utils import update_logs
@@ -44,12 +52,14 @@ def seed_resource_names(cognite_client: CogniteClient) -> ResourceNames:
4452
def upload_file(cognite_client: CogniteClient, filename: str, external_id: str, data_set_id: int) -> FileMetadata:
4553
file = cognite_client.files.retrieve(external_id=external_id)
4654
if not file:
47-
return cognite_client.files.upload(
48-
path=SEED_DIR / filename,
55+
uploaded_file = cognite_client.files.upload(
56+
path=str(SEED_DIR / filename),
4957
external_id=external_id,
5058
name=filename,
5159
data_set_id=data_set_id,
5260
)
61+
assert isinstance(uploaded_file, FileMetadata)
62+
return uploaded_file
5363

5464
return file
5565

@@ -70,46 +80,47 @@ def seed_model_revision_file(
7080

7181

7282
@pytest.fixture(scope="session")
73-
def seed_simulator(cognite_client: CogniteClient, seed_resource_names: ResourceNames) -> Iterator[None]:
83+
def seed_simulator(cognite_client: CogniteClient, seed_resource_names: ResourceNames) -> None:
7484
simulator_external_id = seed_resource_names.simulator_external_id
7585
simulators = cognite_client.simulators.list(limit=None)
7686
seeded_simulator = simulators.get(external_id=simulator_external_id)
7787
fields_to_compare = ["fileExtensionTypes", "modelTypes", "modelDependencies", "stepFields", "unitQuantities"]
78-
seeded_simulator_dump = seeded_simulator.dump() if seeded_simulator else None
7988

8089
if not seeded_simulator:
8190
cognite_client.simulators._post("/simulators", json={"items": [SIMULATOR]})
8291
# if any field in simulator is different from the current seeded simulator, update it
83-
elif any(seeded_simulator_dump.get(field) != SIMULATOR[field] for field in fields_to_compare if field in SIMULATOR):
92+
elif any(getattr(seeded_simulator, to_snake_case(field)) != SIMULATOR.get(field) for field in fields_to_compare):
8493
simulator_update = {
8594
"id": seeded_simulator.id,
86-
"update": {field: {"set": SIMULATOR[field]} for field in fields_to_compare},
95+
"update": {field: {"set": SIMULATOR.get(field)} for field in fields_to_compare},
8796
}
8897
cognite_client.simulators._post("/simulators/update", json={"items": [simulator_update]})
8998

9099

91100
@pytest.fixture(scope="session")
92101
def seed_simulator_integration(
93102
cognite_client: CogniteClient, seed_simulator: None, seed_resource_names: ResourceNames
94-
) -> Iterator[None]:
103+
) -> None:
95104
log_id = None
96105
timestamp = int(time.time() * 1000)
97106
simulator_integrations = cognite_client.simulators.integrations.list(limit=None)
98-
if not simulator_integrations.get(external_id=SIMULATOR_INTEGRATION["externalId"]):
99-
SIMULATOR_INTEGRATION["heartbeat"] = timestamp
100-
SIMULATOR_INTEGRATION["dataSetId"] = seed_resource_names.simulator_test_data_set_id
107+
existing_integration = simulator_integrations.get(external_id=seed_resource_names.simulator_integration_external_id)
108+
if not existing_integration:
109+
new_integration = {
110+
**SIMULATOR_INTEGRATION,
111+
"heartbeat": timestamp,
112+
"dataSetId": seed_resource_names.simulator_test_data_set_id,
113+
}
101114
res = cognite_client.simulators._post(
102115
"/simulators/integrations",
103-
json={"items": [SIMULATOR_INTEGRATION]},
116+
json={"items": [new_integration]},
104117
)
105118
log_id = res.json()["items"][0]["logId"]
106119
else:
107-
integration = simulator_integrations.get(external_id=SIMULATOR_INTEGRATION["externalId"])
108-
if integration is not None:
109-
log_id = integration.log_id
120+
log_id = existing_integration.log_id
110121
cognite_client.simulators.integrations._post(
111122
"/simulators/integrations/update",
112-
json={"items": [{"id": integration.id, "update": {"heartbeat": {"set": timestamp}}}]},
123+
json={"items": [{"id": existing_integration.id, "update": {"heartbeat": {"set": timestamp}}}]},
113124
)
114125

115126
if log_id:
@@ -123,35 +134,33 @@ def seed_simulator_integration(
123134
@pytest.fixture(scope="session")
124135
def seed_simulator_models(
125136
cognite_client: CogniteClient, seed_simulator_integration: None, seed_resource_names: ResourceNames
126-
) -> Iterator[dict[str, Any]]:
137+
) -> Iterator[SimulatorModel]:
127138
model_unique_external_id = seed_resource_names.simulator_model_external_id
128139
models = cognite_client.simulators.models.list(limit=None)
129-
model_exists = models.get(external_id=model_unique_external_id)
130-
131-
if not model_exists:
132-
SIMULATOR_MODEL["dataSetId"] = seed_resource_names.simulator_test_data_set_id
133-
SIMULATOR_MODEL["externalId"] = model_unique_external_id
140+
model = models.get(external_id=model_unique_external_id)
134141

135-
model = SimulatorModelWrite._load(
142+
if not model:
143+
new_model = SimulatorModelWrite._load(
136144
{
137-
"externalId": SIMULATOR_MODEL["externalId"],
138-
"simulatorExternalId": SIMULATOR_MODEL["simulatorExternalId"],
139-
"dataSetId": SIMULATOR_MODEL["dataSetId"],
140-
"name": SIMULATOR_MODEL["name"],
141-
"type": SIMULATOR_MODEL["type"],
142-
"description": SIMULATOR_MODEL["description"],
145+
**SIMULATOR_MODEL.dump(),
146+
"dataSetId": seed_resource_names.simulator_test_data_set_id,
147+
"externalId": model_unique_external_id,
143148
}
144149
)
145-
cognite_client.simulators.models.create(model)
146-
147-
yield SIMULATOR_MODEL
150+
res = cognite_client.simulators.models.create(new_model)
151+
yield res
152+
else:
153+
yield model
148154

149155
cognite_client.simulators.models.delete(external_ids=model_unique_external_id)
150156

151157

152158
@pytest.fixture(scope="session")
153159
def seed_simulator_model_revisions(
154-
cognite_client: CogniteClient, seed_simulator_models, seed_model_revision_file, seed_resource_names: ResourceNames
160+
cognite_client: CogniteClient,
161+
seed_simulator_models: SimulatorModel,
162+
seed_model_revision_file: FileMetadata,
163+
seed_resource_names: ResourceNames,
155164
) -> None:
156165
model_unique_external_id = seed_resource_names.simulator_model_external_id
157166
model_revision_unique_external_id = seed_resource_names.simulator_model_revision_external_id
@@ -179,22 +188,24 @@ def seed_simulator_model_revisions(
179188

180189

181190
@pytest.fixture(scope="session")
182-
def seed_simulator_routines(cognite_client: CogniteClient, seed_simulator_model_revisions):
191+
def seed_simulator_routines(
192+
cognite_client: CogniteClient, seed_simulator_model_revisions: None
193+
) -> Iterator[SimulatorRoutineList]:
183194
model_unique_external_id = RESOURCES.simulator_model_external_id
184195
simulator_routine_unique_external_id = RESOURCES.simulator_routine_external_id
185196

186197
routines = cognite_client.simulators.routines.create(
187198
[
188199
SimulatorRoutineWrite.load(
189200
{
190-
**SIMULATOR_ROUTINE,
201+
**SIMULATOR_ROUTINE.dump(),
191202
"modelExternalId": model_unique_external_id,
192203
"externalId": simulator_routine_unique_external_id,
193204
}
194205
),
195206
SimulatorRoutineWrite.load(
196207
{
197-
**SIMULATOR_ROUTINE,
208+
**SIMULATOR_ROUTINE.dump(),
198209
"modelExternalId": model_unique_external_id,
199210
"externalId": simulator_routine_unique_external_id + "_1",
200211
}
@@ -211,21 +222,24 @@ def seed_simulator_routines(cognite_client: CogniteClient, seed_simulator_model_
211222

212223
def seed_simulator_routine_revision(
213224
cognite_client: CogniteClient, routine_external_id: str, version: str
214-
) -> dict[str, Any]:
225+
) -> SimulatorRoutineRevision:
215226
routine_revs = cognite_client.simulators.routines.revisions.list(routine_external_ids=[routine_external_id])
216227
rev_external_id = f"{routine_external_id}_{version}"
217-
routine_rev_exists = routine_revs.get(external_id=rev_external_id)
228+
revision = routine_revs.get(external_id=rev_external_id)
218229

219-
revision = {**SIMULATOR_ROUTINE_REVISION_OBJ, "externalId": rev_external_id}
220-
221-
if not routine_rev_exists:
222-
cognite_client.simulators.routines.revisions.create(SimulatorRoutineRevisionWrite.load(revision))
230+
if not revision:
231+
revision_write = SimulatorRoutineRevisionWrite.load(
232+
{**SIMULATOR_ROUTINE_REVISION.dump(), "externalId": rev_external_id}
233+
)
234+
return cognite_client.simulators.routines.revisions.create(revision_write)
223235

224236
return revision
225237

226238

227239
@pytest.fixture(scope="session")
228-
def seed_simulator_routine_revisions(cognite_client: CogniteClient, seed_simulator_routines):
240+
def seed_simulator_routine_revisions(
241+
cognite_client: CogniteClient, seed_simulator_routines: list[SimulatorRoutine]
242+
) -> Iterator[tuple[SimulatorRoutineRevision, SimulatorRoutineRevision]]:
229243
simulator_routine_external_id = RESOURCES.simulator_routine_external_id
230244

231245
rev1 = seed_simulator_routine_revision(cognite_client, simulator_routine_external_id, "v1")

0 commit comments

Comments
 (0)