diff --git a/cognite/client/_api/transformations/schema.py b/cognite/client/_api/transformations/schema.py index 0582b4f7f8..627a2973c2 100644 --- a/cognite/client/_api/transformations/schema.py +++ b/cognite/client/_api/transformations/schema.py @@ -7,6 +7,7 @@ TransformationSchemaColumn, TransformationSchemaColumnList, ) +from cognite.client.data_classes.transformations.common import DataModelInstances class TransformationSchemaAPI(APIClient): @@ -35,27 +36,18 @@ def retrieve( """ url_path = utils._auxiliary.interpolate_and_url_encode(self._RESOURCE_PATH + "/{}", str(destination.type)) - other_params = {"conflictMode": conflict_mode} if conflict_mode else None + filter = destination.dump(True) + filter.pop("type") + + if isinstance(destination, DataModelInstances): + filter["externalId"] = filter.pop("modelExternalId") + filter.pop("instanceSpaceExternalId") + if conflict_mode: + filter["conflictMode"] = conflict_mode return self._list( list_cls=TransformationSchemaColumnList, resource_cls=TransformationSchemaColumn, method="GET", resource_path=url_path, - filter=other_params, - ) - - def _alpha_retrieve_data_model_schema( - self, modelExternalId: str = None, spaceExternalId: str = None, instanceExternalId: str = None - ) -> TransformationSchemaColumnList: - url_path = utils._auxiliary.interpolate_and_url_encode(self._RESOURCE_PATH + "/{}", "alphadatamodelinstances") - return self._list( - list_cls=TransformationSchemaColumnList, - resource_cls=TransformationSchemaColumn, - method="GET", - resource_path=url_path, - filter={ - "externalId": modelExternalId, - "spaceExternalId": spaceExternalId, - "instanceExternalId": instanceExternalId, - }, + filter=filter, ) diff --git a/cognite/client/_version.py b/cognite/client/_version.py index 9b139df561..730a386e40 100644 --- a/cognite/client/_version.py +++ b/cognite/client/_version.py @@ -1,2 +1,2 @@ -__version__ = "4.6.0" +__version__ = "4.6.1" __api_subversion__ = "V20220125" diff --git a/cognite/client/data_classes/transformations/__init__.py b/cognite/client/data_classes/transformations/__init__.py index 9ebebbf6de..01f52dfec2 100644 --- a/cognite/client/data_classes/transformations/__init__.py +++ b/cognite/client/data_classes/transformations/__init__.py @@ -10,8 +10,8 @@ ) from cognite.client.data_classes.iam import ClientCredentials from cognite.client.data_classes.shared import TimestampRange -from cognite.client.data_classes.transformations._alphatypes import AlphaDataModelInstances from cognite.client.data_classes.transformations.common import ( + DataModelInstances, NonceCredentials, OidcCredentials, RawTable, @@ -246,8 +246,8 @@ def _load(cls, resource: Union[Dict, str], cognite_client: "CogniteClient" = Non destination_type = snake_dict.pop("type") if destination_type == "raw": instance.destination = RawTable(**snake_dict) - elif destination_type == "alpha_data_model_instances": - instance.destination = AlphaDataModelInstances(**snake_dict) + elif destination_type == "data_model_instances": + instance.destination = DataModelInstances(**snake_dict) elif destination_type == "sequence_rows": instance.destination = SequenceRows(**snake_dict) else: @@ -291,7 +291,7 @@ def dump(self, camel_case: bool = False) -> Dict[str, Any]: ret = super().dump(camel_case=camel_case) for (name, prop) in ret.items(): - if isinstance(prop, (OidcCredentials, NonceCredentials, AlphaDataModelInstances, SequenceRows)): + if isinstance(prop, (OidcCredentials, NonceCredentials, TransformationDestination)): ret[name] = prop.dump(camel_case=camel_case) return ret @@ -372,7 +372,7 @@ def dump(self, camel_case: bool = True) -> Dict[str, Any]: for update in obj.get("update", {}).values(): item = update.get("set") - if isinstance(item, (AlphaDataModelInstances, SequenceRows, OidcCredentials, NonceCredentials)): + if isinstance(item, (TransformationDestination, OidcCredentials, NonceCredentials)): update["set"] = item.dump(camel_case=camel_case) return obj diff --git a/cognite/client/data_classes/transformations/_alphatypes.py b/cognite/client/data_classes/transformations/_alphatypes.py deleted file mode 100644 index cc94d058ed..0000000000 --- a/cognite/client/data_classes/transformations/_alphatypes.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import Any, Dict - -from cognite.client import utils -from cognite.client.data_classes.transformations.common import TransformationDestination - - -class AlphaDataModelInstances(TransformationDestination): - """To be used when the transformation is meant to produce data model instances. - Flexible Data Models resource type is on `alpha` version currently and the API may change. - - Args: - model_external_id (str): external_id of the flexible data model. - space_external_id (str): space external_id of the flexible data model. - instance_space_external_id (str): space external_id of the flexible data model instance. - Returns: - TransformationDestination pointing to the target flexible data model. - """ - - def __init__( - self, model_external_id: str = None, space_external_id: str = None, instance_space_external_id: str = None - ): - super().__init__(type="alpha_data_model_instances") - self.model_external_id = model_external_id - self.space_external_id = space_external_id - self.instance_space_external_id = instance_space_external_id - - def __hash__(self) -> int: - return hash((self.type, self.model_external_id, self.space_external_id, self.instance_space_external_id)) - - def __eq__(self, other: Any) -> bool: - return isinstance(other, AlphaDataModelInstances) and hash(other) == hash(self) - - def dump(self, camel_case: bool = False) -> Dict[str, Any]: - ret = { - "model_external_id": self.model_external_id, - "type": self.type, - "space_external_id": self.space_external_id, - "instance_space_external_id": self.instance_space_external_id, - } - if camel_case: - return {utils._auxiliary.to_camel_case(key): value for key, value in ret.items()} - return ret diff --git a/cognite/client/data_classes/transformations/common.py b/cognite/client/data_classes/transformations/common.py index 0e3011eb9e..940cd69558 100644 --- a/cognite/client/data_classes/transformations/common.py +++ b/cognite/client/data_classes/transformations/common.py @@ -1,3 +1,4 @@ +import warnings from typing import Any, Dict, Optional from cognite.client import utils @@ -19,6 +20,12 @@ def __hash__(self) -> int: def __eq__(self, other: Any) -> bool: return isinstance(other, TransformationDestination) and hash(other) == hash(self) + def dump(self, camel_case: bool = False) -> Dict[str, Any]: + ret = self.__dict__ + if camel_case: + return {utils._auxiliary.to_camel_case(key): value for key, value in ret.items()} + return ret + @staticmethod def assets() -> "TransformationDestination": """To be used when the transformation is meant to produce assets.""" @@ -99,6 +106,26 @@ def sequence_rows(external_id: str = "") -> "SequenceRows": """ return SequenceRows(external_id=external_id) + @staticmethod + def data_model_instances( + model_external_id: str = "", space_external_id: str = "", instance_space_external_id: str = "" + ) -> "DataModelInstances": + """To be used when the transformation is meant to produce data model instances. + Flexible Data Models resource type is on `beta` version currently. + + Args: + model_external_id (str): external_id of the flexible data model. + space_external_id (str): space external_id of the flexible data model. + instance_space_external_id (str): space external_id of the flexible data model instance. + Returns: + TransformationDestination pointing to the target flexible data model. + """ + return DataModelInstances( + model_external_id=model_external_id, + space_external_id=space_external_id, + instance_space_external_id=instance_space_external_id, + ) + class RawTable(TransformationDestination): def __init__(self, database: str = None, table: str = None): @@ -124,11 +151,34 @@ def __hash__(self) -> int: def __eq__(self, other: Any) -> bool: return isinstance(other, SequenceRows) and hash(other) == hash(self) - def dump(self, camel_case: bool = False) -> Dict[str, Any]: - ret = {"external_id": self.external_id, "type": self.type} - if camel_case: - return {utils._auxiliary.to_camel_case(key): value for key, value in ret.items()} - return ret + +class DataModelInstances(TransformationDestination): + _warning_shown = False + + @classmethod + def _show_warning(cls) -> bool: + if not cls._warning_shown: + warnings.warn( + "Feature DataModeStorage is in beta and still in development. Breaking changes can happen in between patch versions." + ) + cls._warning_shown = True + return True + return False + + def __init__( + self, model_external_id: str = None, space_external_id: str = None, instance_space_external_id: str = None + ): + DataModelInstances._show_warning() + super().__init__(type="data_model_instances") + self.model_external_id = model_external_id + self.space_external_id = space_external_id + self.instance_space_external_id = instance_space_external_id + + def __hash__(self) -> int: + return hash((self.type, self.model_external_id, self.space_external_id, self.instance_space_external_id)) + + def __eq__(self, other: Any) -> bool: + return isinstance(other, DataModelInstances) and hash(other) == hash(self) class OidcCredentials: diff --git a/cognite/client/data_classes/transformations/jobs.py b/cognite/client/data_classes/transformations/jobs.py index da7adfccc8..363fe8bfc4 100644 --- a/cognite/client/data_classes/transformations/jobs.py +++ b/cognite/client/data_classes/transformations/jobs.py @@ -5,8 +5,12 @@ from cognite.client import utils from cognite.client.data_classes._base import CogniteFilter, CogniteResource, CogniteResourceList -from cognite.client.data_classes.transformations._alphatypes import AlphaDataModelInstances -from cognite.client.data_classes.transformations.common import RawTable, SequenceRows, TransformationDestination +from cognite.client.data_classes.transformations.common import ( + DataModelInstances, + RawTable, + SequenceRows, + TransformationDestination, +) if TYPE_CHECKING: from cognite.client import CogniteClient @@ -250,17 +254,15 @@ def _load(cls, resource: Union[Dict, str], cognite_client: "CogniteClient" = Non instance = super(TransformationJob, cls)._load(resource, cognite_client) if isinstance(instance.destination, Dict): snake_dict = {utils._auxiliary.to_snake_case(key): value for (key, value) in instance.destination.items()} - if instance.destination.get("type") == "raw": - snake_dict.pop("type") + destination_type = snake_dict.pop("type") + if destination_type == "raw": instance.destination = RawTable(**snake_dict) - elif instance.destination.get("type") == "alpha_data_model_instances": - snake_dict.pop("type") - instance.destination = AlphaDataModelInstances(**snake_dict) - elif instance.destination.get("type") == "sequence_rows": - snake_dict.pop("type") + elif destination_type == "data_model_instances": + instance.destination = DataModelInstances(**snake_dict) + elif destination_type == "sequence_rows": instance.destination = SequenceRows(**snake_dict) else: - instance.destination = TransformationDestination(**snake_dict) + instance.destination = TransformationDestination(destination_type) return instance def __hash__(self) -> int: diff --git a/pyproject.toml b/pyproject.toml index 77df40ed5a..553070b8e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "cognite-sdk" -version = "4.6.0" +version = "4.6.1" description = "Cognite Python SDK" readme = "README.md" diff --git a/tests/tests_integration/test_api/test_transformations/test_jobs.py b/tests/tests_integration/test_api/test_transformations/test_jobs.py index 91c442c817..060f9148e3 100644 --- a/tests/tests_integration/test_api/test_transformations/test_jobs.py +++ b/tests/tests_integration/test_api/test_transformations/test_jobs.py @@ -91,7 +91,6 @@ async def other_running_transformation(other_transformation): yield transform -@pytest.mark.skip class TestTransformationJobsAPI: @pytest.mark.asyncio async def test_run_without_wait(self, cognite_client, new_running_transformation): diff --git a/tests/tests_integration/test_api/test_transformations/test_schema.py b/tests/tests_integration/test_api/test_transformations/test_schema.py index dfc0e0e310..02033540c7 100644 --- a/tests/tests_integration/test_api/test_transformations/test_schema.py +++ b/tests/tests_integration/test_api/test_transformations/test_schema.py @@ -1,7 +1,5 @@ import os -import pytest - from cognite.client.data_classes import TransformationDestination @@ -36,8 +34,7 @@ def test_asset_hierarchy(self, cognite_client): assert len(asset_columns) > 0 assert len([col for col in asset_columns if col.name == "externalId"]) > 0 - @pytest.mark.skip - def test_alpha_data_model_schema(self, cognite_client): + def test_data_model_schema(self, cognite_client): project_name = os.environ["COGNITE_PROJECT"] dm_name = "python-sdk-test-dm" space_name = "test-space" @@ -67,15 +64,12 @@ def test_alpha_data_model_schema(self, cognite_client): params={}, headers={"cdf-version": "alpha"}, ) - model_cols = cognite_client.transformations.schema._alpha_retrieve_data_model_schema( - dm_name, space_name, space_name + model_cols = cognite_client.transformations.schema.retrieve( + TransformationDestination.data_model_instances(dm_name, space_name, space_name) ) - assert len(model_cols) == 6 + assert len(model_cols) == 3 assert [col for col in model_cols if col.name == "externalId"][0].type.type == "string" assert [col for col in model_cols if col.name == "test"][0].type.type == "string" - assert [col for col in model_cols if col.name == "description"][0].type.type == "string" - assert [col for col in model_cols if col.name == "type"][0].type.type == "string" - assert [col for col in model_cols if col.name == "name"][0].type.type == "string" assert [col for col in model_cols if col.name == "test2"][0].type.type == "long" # cognite_client.post( diff --git a/tests/tests_integration/test_api/test_transformations/test_transformations.py b/tests/tests_integration/test_api/test_transformations/test_transformations.py index 69abcf4402..9fcb0bd49e 100644 --- a/tests/tests_integration/test_api/test_transformations/test_transformations.py +++ b/tests/tests_integration/test_api/test_transformations/test_transformations.py @@ -5,7 +5,6 @@ from cognite.client.credentials import OAuthClientCredentials from cognite.client.data_classes import DataSet, Transformation, TransformationDestination, TransformationUpdate -from cognite.client.data_classes.transformations._alphatypes import AlphaDataModelInstances from cognite.client.data_classes.transformations.common import NonceCredentials, OidcCredentials, SequenceRows @@ -112,13 +111,12 @@ def test_create_string_datapoints_transformation(self, cognite_client): ts = cognite_client.transformations.create(transform) cognite_client.transformations.delete(id=ts.id) - @pytest.mark.skip - def test_create_alpha_dmi_transformation(self, cognite_client): + def test_create_dmi_transformation(self, cognite_client): prefix = "".join(random.choice(string.ascii_letters) for i in range(6)) transform = Transformation( name="any", external_id=f"{prefix}-transformation", - destination=AlphaDataModelInstances( + destination=TransformationDestination.data_model_instances( model_external_id="testInstance", space_external_id="test-space", instance_space_external_id="test-space", @@ -126,7 +124,7 @@ def test_create_alpha_dmi_transformation(self, cognite_client): ) ts = cognite_client.transformations.create(transform) assert ( - ts.destination.type == "alpha_data_model_instances" + ts.destination.type == "data_model_instances" and ts.destination.model_external_id == "testInstance" and ts.destination.space_external_id == "test-space" and ts.destination.instance_space_external_id == "test-space" @@ -260,16 +258,21 @@ def test_preview_to_string(self, cognite_client): # just make sure it doesnt raise exceptions str(query_result) - @pytest.mark.skip - def test_update_dmi_alpha(self, cognite_client, new_transformation): - new_transformation.destination = AlphaDataModelInstances("myTest", "test-space", "test-space") + def test_update_dmi(self, cognite_client, new_transformation): + new_transformation.destination = TransformationDestination.data_model_instances( + "myTest", "test-space", "test-space" + ) partial_update = TransformationUpdate(id=new_transformation.id).destination.set( - AlphaDataModelInstances("myTest2", "test-space", "test-space") + TransformationDestination.data_model_instances("myTest2", "test-space", "test-space") ) updated_transformation = cognite_client.transformations.update(new_transformation) - assert updated_transformation.destination == AlphaDataModelInstances("myTest", "test-space", "test-space") + assert updated_transformation.destination == TransformationDestination.data_model_instances( + "myTest", "test-space", "test-space" + ) partial_updated = cognite_client.transformations.update(partial_update) - assert partial_updated.destination == AlphaDataModelInstances("myTest2", "test-space", "test-space") + assert partial_updated.destination == TransformationDestination.data_model_instances( + "myTest2", "test-space", "test-space" + ) def test_update_sequence_rows_update(self, cognite_client, new_transformation): new_transformation.destination = SequenceRows("myTest")