diff --git a/cognite/client/_api/simulators/simulation_runs.py b/cognite/client/_api/simulators/simulation_runs.py index 54642b08a..615b127fc 100644 --- a/cognite/client/_api/simulators/simulation_runs.py +++ b/cognite/client/_api/simulators/simulation_runs.py @@ -5,7 +5,12 @@ from cognite.client._api_client import APIClient from cognite.client._constants import DEFAULT_LIMIT_READ from cognite.client.data_classes.simulators.filters import SimulationRunsFilter -from cognite.client.data_classes.simulators.simulators import SimulationRun, SimulationRunsList, CreatedTimeSort, SimulationTimeSort +from cognite.client.data_classes.simulators.simulators import ( + CreatedTimeSort, + SimulationRun, + SimulationRunsList, + SimulationTimeSort, +) from cognite.client.utils._experimental import FeaturePreviewWarning if TYPE_CHECKING: diff --git a/cognite/client/_api/simulators/simulator_models.py b/cognite/client/_api/simulators/simulator_models.py index 549b303cf..e6f5a194c 100644 --- a/cognite/client/_api/simulators/simulator_models.py +++ b/cognite/client/_api/simulators/simulator_models.py @@ -7,11 +7,11 @@ from cognite.client._constants import DEFAULT_LIMIT_READ from cognite.client.data_classes.simulators.filters import SimulatorModelRevisionsFilter, SimulatorModelsFilter from cognite.client.data_classes.simulators.simulators import ( + CreatedTimeSort, SimulatorModel, SimulatorModelList, SimulatorModelRevision, SimulatorModelRevisionList, - CreatedTimeSort ) from cognite.client.utils._experimental import FeaturePreviewWarning from cognite.client.utils._identifier import IdentifierSequence @@ -34,7 +34,7 @@ def list( self, limit: int = DEFAULT_LIMIT_READ, sort: CreatedTimeSort | None = None, - filter: SimulatorModelRevisionsFilter | dict[str, Any] | None = None + filter: SimulatorModelRevisionsFilter | dict[str, Any] | None = None, ) -> SimulatorModelRevisionList: """`Filter simulator model revisions `_ @@ -108,25 +108,25 @@ def retrieve_multiple( ) -> SimulatorModelRevisionList: """`Retrieve simulator model revisions `_ - Retrieve one or more simulator model revisions by IDs or external IDs. + Retrieve one or more simulator model revisions by IDs or external IDs. - Args: - ids (Sequence[int] | None): IDs - external_ids (SequenceNotStr[str] | None): External IDs - ignore_unknown_ids (bool): Ignore IDs and external IDs that are not found rather than throw an exception. + Args: + ids (Sequence[int] | None): IDs + external_ids (SequenceNotStr[str] | None): External IDs + ignore_unknown_ids (bool): Ignore IDs and external IDs that are not found rather than throw an exception. - Returns: - SimulatorModelRevisionList: Requested simulator model revisions + Returns: + SimulatorModelRevisionList: Requested simulator model revisions - Examples: + Examples: - Get simulator model revisions by ids: - >>> from cognite.client import CogniteClient - >>> client = CogniteClient() - >>> res = client.simulators.models.revisions.retrieve_multiple(ids=[1, 2, 3]) + Get simulator model revisions by ids: + >>> from cognite.client import CogniteClient + >>> client = CogniteClient() + >>> res = client.simulators.models.revisions.retrieve_multiple(ids=[1, 2, 3]) - Get simulator model revisions by external ids: - >>> res = client.simulators.models.revisions.retrieve_multiple(external_ids=["abc", "def"]) + Get simulator model revisions by external ids: + >>> res = client.simulators.models.revisions.retrieve_multiple(external_ids=["abc", "def"]) """ identifiers = IdentifierSequence.load(ids=ids, external_ids=external_ids) return self._retrieve_multiple( diff --git a/cognite/client/_api/simulators/simulator_routines.py b/cognite/client/_api/simulators/simulator_routines.py index 46c1a870b..e80bc8207 100644 --- a/cognite/client/_api/simulators/simulator_routines.py +++ b/cognite/client/_api/simulators/simulator_routines.py @@ -1,17 +1,17 @@ from __future__ import annotations from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, Literal +from typing import TYPE_CHECKING, Any from cognite.client._api_client import APIClient from cognite.client._constants import DEFAULT_LIMIT_READ from cognite.client.data_classes.simulators.filters import SimulatorRoutineRevisionsFilter, SimulatorRoutinesFilter from cognite.client.data_classes.simulators.simulators import ( + CreatedTimeSort, SimulatorRoutine, SimulatorRoutineList, SimulatorRoutineRevision, SimulatorRoutineRevisionsList, - CreatedTimeSort, ) from cognite.client.utils._experimental import FeaturePreviewWarning from cognite.client.utils._identifier import IdentifierSequence @@ -20,6 +20,7 @@ if TYPE_CHECKING: from cognite.client import ClientConfig, CogniteClient + class SimulatorRoutineRevisionsAPI(APIClient): _RESOURCE_PATH = "/simulators/routines/revisions" @@ -31,7 +32,7 @@ def __init__(self, config: ClientConfig, api_version: str | None, cognite_client def list( self, - limit: int = 20, # the maximum number of revisions to return is limited to 20 items. + limit: int = 20, # the maximum number of revisions to return is limited to 20 items. sort: CreatedTimeSort | None = None, filter: SimulatorRoutineRevisionsFilter | dict[str, Any] | None = None, includeAllFields: bool = False, @@ -109,25 +110,25 @@ def retrieve_multiple( ) -> SimulatorRoutineRevisionsList: """`Retrieve simulator routine revisions `_ - Retrieve one or more simulator routine revisions by IDs or external IDs + Retrieve one or more simulator routine revisions by IDs or external IDs - Args: - ids (Sequence[int] | None): IDs - external_ids (SequenceNotStr[str] | None): External IDs - ignore_unknown_ids (bool): Ignore IDs and external IDs that are not found rather than throw an exception. + Args: + ids (Sequence[int] | None): IDs + external_ids (SequenceNotStr[str] | None): External IDs + ignore_unknown_ids (bool): Ignore IDs and external IDs that are not found rather than throw an exception. - Returns: - SimulatorRoutineRevisionsList: Requested simulator routine revisions + Returns: + SimulatorRoutineRevisionsList: Requested simulator routine revisions - Examples: + Examples: - Get simulator routine revisions by id: - >>> from cognite.client import CogniteClient - >>> client = CogniteClient() - >>> res = client.simulators.routines.revisions.retrieve_multiple(ids=[1, 2, 3]) + Get simulator routine revisions by id: + >>> from cognite.client import CogniteClient + >>> client = CogniteClient() + >>> res = client.simulators.routines.revisions.retrieve_multiple(ids=[1, 2, 3]) - Get simulator routine revisions by external id: - >>> res = client.simulators.routines.revisions.retrieve_multiple(external_ids=["abc", "def"]) + Get simulator routine revisions by external id: + >>> res = client.simulators.routines.revisions.retrieve_multiple(external_ids=["abc", "def"]) """ identifiers = IdentifierSequence.load(ids=ids, external_ids=external_ids) return self._retrieve_multiple( @@ -150,7 +151,8 @@ def __init__(self, config: ClientConfig, api_version: str | None, cognite_client def list( self, - limit: int = DEFAULT_LIMIT_READ, filter: SimulatorRoutinesFilter | dict[str, Any] | None = None, + limit: int = DEFAULT_LIMIT_READ, + filter: SimulatorRoutinesFilter | dict[str, Any] | None = None, sort: CreatedTimeSort | None = None, ) -> SimulatorRoutineList: """`Filter simulator routines `_ diff --git a/cognite/client/data_classes/simulators/__init__.py b/cognite/client/data_classes/simulators/__init__.py index 77212f705..16b1e6985 100644 --- a/cognite/client/data_classes/simulators/__init__.py +++ b/cognite/client/data_classes/simulators/__init__.py @@ -56,56 +56,56 @@ ) __all__ = [ + "SimulationRun", + "SimulationRunCore", + "SimulationRunsList", "SimulationValueUnitInput", - "SimulatorRoutineInputTimeseries", - "SimulatorRoutineInputConstant", - "SimulatorRoutineOutput", - "SimulatorRoutineSchedule", - "SimulatorRoutineDataSampling", - "SimulatorRoutineLogicalCheckEnabled", - "SimulatorRoutineSteadyStateDetectionEnabled", - "SimulatorRoutineConfiguration", - "SimulatorRoutineStepArguments", - "SimulatorRoutineStep", - "SimulatorRoutineStage", - "SimulatorUnitEntry", - "SimulatorStepOption", - "SimulatorModelType", - "SimulatorQuantity", - "SimulatorStepField", - "SimulatorStep", - "SimulatorCore", - "SimulatorWrite", "Simulator", + "SimulatorCore", + "SimulatorIntegration", "SimulatorIntegrationCore", + "SimulatorIntegrationList", "SimulatorIntegrationWrite", - "SimulatorIntegration", + "SimulatorIntegrationWriteList", + "SimulatorList", + "SimulatorModel", + "SimulatorModelCore", + "SimulatorModelList", + "SimulatorModelRevision", "SimulatorModelRevisionCore", + "SimulatorModelRevisionList", "SimulatorModelRevisionWrite", - "SimulatorModelRevision", - "SimulatorRoutineRevisionCore", - "SimulatorRoutineRevisionWrite", - "SimulatorRoutineRevision", - "SimulatorModelCore", + "SimulatorModelRevisionWriteList", + "SimulatorModelType", "SimulatorModelWrite", - "SimulatorModel", - "SimulationRunCore", - "SimulationRun", - "SimulatorRoutineCore", - "SimulatorRoutineWrite", + "SimulatorModelWriteList", + "SimulatorQuantity", "SimulatorRoutine", - "SimulatorRoutineRevisionWriteList", - "SimulatorRoutineRevisionList", - "SimulatorRoutineWriteList", + "SimulatorRoutineConfiguration", + "SimulatorRoutineCore", + "SimulatorRoutineDataSampling", + "SimulatorRoutineInputConstant", + "SimulatorRoutineInputTimeseries", "SimulatorRoutineList", + "SimulatorRoutineLogicalCheckEnabled", + "SimulatorRoutineOutput", + "SimulatorRoutineRevision", + "SimulatorRoutineRevisionCore", + "SimulatorRoutineRevisionList", + "SimulatorRoutineRevisionWrite", + "SimulatorRoutineRevisionWriteList", "SimulatorRoutineRevisionsList", + "SimulatorRoutineSchedule", + "SimulatorRoutineStage", + "SimulatorRoutineSteadyStateDetectionEnabled", + "SimulatorRoutineStep", + "SimulatorRoutineStepArguments", + "SimulatorRoutineWrite", + "SimulatorRoutineWriteList", + "SimulatorStep", + "SimulatorStepField", + "SimulatorStepOption", + "SimulatorUnitEntry", + "SimulatorWrite", "SimulatorWriteList", - "SimulatorList", - "SimulatorIntegrationWriteList", - "SimulatorIntegrationList", - "SimulatorModelWriteList", - "SimulatorModelList", - "SimulatorModelRevisionWriteList", - "SimulatorModelRevisionList", - "SimulationRunsList", ] diff --git a/cognite/client/data_classes/simulators/simulators.py b/cognite/client/data_classes/simulators/simulators.py index ee92778f6..a77f16f8e 100644 --- a/cognite/client/data_classes/simulators/simulators.py +++ b/cognite/client/data_classes/simulators/simulators.py @@ -3,8 +3,7 @@ from abc import ABC from collections.abc import Sequence from dataclasses import dataclass -from enum import auto -from typing import TYPE_CHECKING, Any, Literal, TypeAlias +from typing import TYPE_CHECKING, Any, Literal from typing_extensions import Self @@ -12,13 +11,12 @@ CogniteObject, CogniteResource, CogniteResourceList, + CogniteSort, ExternalIDTransformerMixin, IdTransformerMixin, InternalIdTransformerMixin, WriteableCogniteResource, WriteableCogniteResourceList, - EnumProperty, - CogniteSort ) from cognite.client.utils.useful_types import SequenceNotStr @@ -1530,12 +1528,12 @@ def __hash__(self) -> int: class PropertySort(CogniteSort): - def dump(self, camel_case: bool = True) -> dict[str, Any]: dumped = super().dump(camel_case=camel_case) dumped["property"] = self.property return dumped + class CreatedTimeSort(PropertySort): def __init__( self, @@ -1544,6 +1542,7 @@ def __init__( ): super().__init__(property, order) + class SimulationTimeSort(PropertySort): def __init__( self, @@ -1552,6 +1551,7 @@ def __init__( ): super().__init__(property, order) + class SimulatorRoutineRevisionWriteList(CogniteResourceList[SimulatorRoutineRevisionWrite], ExternalIDTransformerMixin): _RESOURCE = SimulatorRoutineRevisionWrite diff --git a/tests/tests_integration/test_api/test_simulators/seed/data.py b/tests/tests_integration/test_api/test_simulators/seed/data.py index 6915628e3..e3f18cde7 100644 --- a/tests/tests_integration/test_api/test_simulators/seed/data.py +++ b/tests/tests_integration/test_api/test_simulators/seed/data.py @@ -1,7 +1,8 @@ import time -data_set_id = 1521375514069 -development_data_set_id = 97552494921583 +# data_set_id = 1521375514069 +# development_data_set_id = 97552494921583 +data_set_id = 97552494921583 resource_names = { "simulator_external_id": "py_sdk_integration_tests", diff --git a/tests/tests_integration/test_api/test_simulators/test_simulators.py b/tests/tests_integration/test_api/test_simulators/test_simulators.py index aa8a7cd6a..d9c2aa90d 100644 --- a/tests/tests_integration/test_api/test_simulators/test_simulators.py +++ b/tests/tests_integration/test_api/test_simulators/test_simulators.py @@ -1,5 +1,6 @@ import random import time +import uuid import pytest @@ -9,7 +10,10 @@ SimulatorIntegrationFilter, SimulatorModelRevisionsFilter, SimulatorModelsFilter, + SimulatorRoutineRevisionsFilter, + SimulatorRoutinesFilter, ) +from cognite.client.data_classes.simulators.simulators import CreatedTimeSort from cognite.client.exceptions import CogniteAPIError from tests.tests_integration.test_api.test_simulators.seed.data import ( data_set_id, @@ -22,7 +26,14 @@ simulator_routine_revision, ) -model_unique_external_id = f"{resource_names['simulator_model_external_id']}_{random.randint(100,500)}" + +def truncated_uuid4(): + return str(uuid.uuid4())[:8] + + +model_unique_external_id = f"{resource_names['simulator_model_external_id']}_{truncated_uuid4()}" +model_revision_unique_external_id = f"{resource_names['simulator_model_revision_external_id']}_{truncated_uuid4()}" +simulator_routine_unique_external_id = f"{resource_names['simulator_routine_external_id']}_{truncated_uuid4()}" @pytest.fixture(scope="class") @@ -82,65 +93,85 @@ def seed_simulator_integration(cognite_client: CogniteClient, seed_simulator) -> @pytest.fixture def seed_simulator_models(cognite_client: CogniteClient, seed_simulator_integration) -> None: models = cognite_client.simulators.models.list() - model_seed = list(filter(lambda x: x.external_id == model_unique_external_id, models)) + model_exists = len(list(filter(lambda x: x.external_id == model_unique_external_id, models))) > 0 - if len(model_seed) > 0: + if not model_exists: cognite_client.post( - f"/api/v1/projects/{cognite_client.config.project}/simulators/models/delete", - json={"items": [{"id": model_seed[0].id}]}, # Post actual simulator models here + f"/api/v1/projects/{cognite_client.config.project}/simulators/models", + json={ + "items": [{**simulator_model, "externalId": model_unique_external_id}] + }, # Post actual simulator models here ) - cognite_client.post( - f"/api/v1/projects/{cognite_client.config.project}/simulators/models", - json={ - "items": [{**simulator_model, "externalId": model_unique_external_id}] - }, # Post actual simulator models here - ) - - yield - - models = cognite_client.simulators.models.list() - model_seed = list(filter(lambda x: x.external_id == model_unique_external_id, models)) - - cognite_client.post( - f"/api/v1/projects/{cognite_client.config.project}/simulators/models/delete", - json={"items": [{"id": model_seed[0].id}]}, # Post actual simulator models here - ) - @pytest.fixture def seed_simulator_model_revisions(cognite_client: CogniteClient, seed_simulator_models, seed_file) -> None: - cognite_client.post( - f"/api/v1/projects/{cognite_client.config.project}/simulators/models/revisions", - json={ - "items": [{**simulator_model_revision, "fileId": seed_file.id, "modelExternalId": model_unique_external_id}] - }, # Post actual simulator models here + model_revisions = cognite_client.simulators.models.revisions.list( + filter=SimulatorModelRevisionsFilter(model_external_ids=[model_unique_external_id]) ) + model_revision_not_exists = ( + len(list(filter(lambda x: x.external_id == model_revision_unique_external_id, model_revisions))) == 0 + ) + + if model_revision_not_exists: + cognite_client.post( + f"/api/v1/projects/{cognite_client.config.project}/simulators/models/revisions", + json={ + "items": [ + { + **simulator_model_revision, + "fileId": seed_file.id, + "modelExternalId": model_unique_external_id, + "externalId": model_revision_unique_external_id, + } + ] + }, + ) @pytest.fixture def seed_simulator_routines(cognite_client: CogniteClient, seed_simulator_model_revisions) -> None: - cognite_client.post( - f"/api/v1/projects/{cognite_client.config.project}/simulators/routines", - json={"items": [{**simulator_routine, "modelExternalId": model_unique_external_id}]}, + routines = cognite_client.simulators.routines.list( + filter=SimulatorRoutinesFilter(model_external_ids=[model_unique_external_id]) ) + routine_not_exists = ( + len(list(filter(lambda x: x.external_id == simulator_routine_unique_external_id, routines))) == 0 + ) + + if routine_not_exists: + cognite_client.post( + f"/api/v1/projects/{cognite_client.config.project}/simulators/routines", + json={ + "items": [ + { + **simulator_routine, + "modelExternalId": model_unique_external_id, + "externalId": simulator_routine_unique_external_id, + } + ] + }, + ) @pytest.fixture def seed_simulator_routine_revisions(cognite_client: CogniteClient, seed_simulator_routines) -> None: - cognite_client.post( - f"/api/v1/projects/{cognite_client.config.project}/simulators/routines/revisions", - json={"items": [simulator_routine_revision]}, + revisions_all = cognite_client.simulators.routines.revisions.list( + filter=SimulatorRoutineRevisionsFilter( + routine_external_ids=[simulator_routine_unique_external_id], all_versions=True + ), ) - -@pytest.fixture -def delete_simulator(cognite_client: CogniteClient, seed_resource_names) -> None: - yield - cognite_client.post( - f"/api/v1/projects/{cognite_client.config.project}/simulators/delete", - json={"items": [{"externalId": seed_resource_names["simulator_external_id"]}]}, - ) + if len(revisions_all) == 0: + for _ in range(10): + revision = { + **simulator_routine_revision, + "externalId": f"{simulator_routine_revision['externalId']}_{truncated_uuid4()}", + "routineExternalId": simulator_routine_unique_external_id, + } + cognite_client.post( + f"/api/v1/projects/{cognite_client.config.project}/simulators/routines/revisions", + json={"items": [revision]}, + ) @pytest.mark.usefixtures("seed_resource_names", "seed_simulator") @@ -194,7 +225,7 @@ def test_retrieve_model(self, cognite_client: CogniteClient, seed_resource_names assert model.external_id == model_unique_external_id def test_list_model_revisions(self, cognite_client: CogniteClient, seed_resource_names) -> None: - revisions = cognite_client.simulators.models.list( + revisions = cognite_client.simulators.models.revisions.list( limit=5, filter=SimulatorModelRevisionsFilter(model_external_ids=[model_unique_external_id]), ) @@ -202,7 +233,7 @@ def test_list_model_revisions(self, cognite_client: CogniteClient, seed_resource def test_retrieve_model_revision(self, cognite_client: CogniteClient, seed_resource_names) -> None: model_revision = cognite_client.simulators.models.revisions.retrieve( - external_id=seed_resource_names["simulator_model_revision_external_id"] + external_id=model_revision_unique_external_id ) assert model_revision is not None assert model_revision.model_external_id == model_unique_external_id @@ -214,8 +245,46 @@ def test_list_routines(self, cognite_client: CogniteClient) -> None: routines = cognite_client.simulators.routines.list(limit=5) assert len(routines) > 0 - def test_list_routine_revisions(self, cognite_client: CogniteClient) -> None: - revisions = cognite_client.simulators.routines.revisions.list(limit=5) - assert revisions[0].configuration is not None - assert revisions[0].script is not None - assert len(revisions) > 0 + def test_list_and_filtering_routine_revisions(self, cognite_client: CogniteClient) -> None: + revisions_all = cognite_client.simulators.routines.revisions.list( + filter=SimulatorRoutineRevisionsFilter( + routine_external_ids=[simulator_routine_unique_external_id], all_versions=True + ), + ) + assert len(revisions_all) > 1 + revisions_filter = cognite_client.simulators.routines.revisions.list( + filter=SimulatorRoutineRevisionsFilter(model_external_ids=[model_unique_external_id], all_versions=True), + ) + assert len(revisions_filter) == 10 + revisions_sort_asc = cognite_client.simulators.routines.revisions.list( + sort=CreatedTimeSort(order="asc", property="createdTime"), + filter=SimulatorRoutineRevisionsFilter( + routine_external_ids=[simulator_routine_unique_external_id], all_versions=True + ), + ) + revisions_sort_desc = cognite_client.simulators.routines.revisions.list( + sort=CreatedTimeSort(order="desc", property="createdTime"), + filter=SimulatorRoutineRevisionsFilter( + routine_external_ids=[simulator_routine_unique_external_id], all_versions=True + ), + ) + assert revisions_sort_asc[0].external_id == revisions_sort_desc[-1].external_id + + def test_retrieve_routine_revision(self, cognite_client: CogniteClient) -> None: + revisions_all = cognite_client.simulators.routines.revisions.list( + filter=SimulatorRoutineRevisionsFilter( + routine_external_ids=[simulator_routine_unique_external_id], all_versions=True + ), + ) + + assert len(revisions_all) > 5 + + rev1 = revisions_all[random.randint(0, 4)] + rev2 = revisions_all[random.randint(0, 4)] + + rev1_retrieve = cognite_client.simulators.routines.revisions.retrieve(external_id=rev1.external_id) + assert rev1_retrieve is not None + assert rev1_retrieve.external_id == rev1.external_id + rev2_retrieve = cognite_client.simulators.routines.revisions.retrieve(external_id=rev2.external_id) + assert rev2_retrieve is not None + assert rev2_retrieve.external_id == rev2.external_id