diff --git a/modelon/impact/client/experiment_definition/modifiers.py b/modelon/impact/client/experiment_definition/modifiers.py index ad19de20..725be888 100644 --- a/modelon/impact/client/experiment_definition/modifiers.py +++ b/modelon/impact/client/experiment_definition/modifiers.py @@ -2,7 +2,9 @@ import enum from typing import Any, Union -Scalar = Union[bool, int, float, str] +from modelon.impact.client.entities.file_uri import FileURI + +Scalar = Union[bool, int, float, str, FileURI] class DataType(enum.Enum): @@ -11,6 +13,7 @@ class DataType(enum.Enum): REAL = "REAL" STRING = "STRING" ENUMERATION = "ENUMERATION" + FILEURI = "FILEURI" class Modifier(abc.ABC): @@ -33,7 +36,9 @@ def to_dict(self, name: str) -> dict[str, Any]: return { "kind": "value", "name": name, - "value": self.value, + "value": str(self.value) + if self.data_type == DataType.FILEURI + else self.value, "dataType": self.data_type.value, } @@ -55,6 +60,8 @@ def data_type_from_value(value: Scalar) -> DataType: return DataType.REAL elif isinstance(value, str): return DataType.STRING + elif isinstance(value, FileURI): + return DataType.FILEURI raise ValueError(f"Unsupported type for modifier value {value}") diff --git a/modelon/impact/client/experiment_definition/operators.py b/modelon/impact/client/experiment_definition/operators.py index afa23fa3..45282e38 100644 --- a/modelon/impact/client/experiment_definition/operators.py +++ b/modelon/impact/client/experiment_definition/operators.py @@ -5,6 +5,11 @@ from dataclasses import dataclass from typing import Any, Optional, Union +from modelon.impact.client.entities.file_uri import ( + CustomArtifactURI, + ModelicaResourceURI, + get_resource_URI_from_str, +) from modelon.impact.client.experiment_definition.modifiers import ( DataType, Enumeration, @@ -143,16 +148,26 @@ def __str__(self) -> str: return f"choices({', '.join(map(str, self.values))})" def to_dict(self, name: str) -> dict[str, Any]: + values = ( + list(map(str, self.values)) + if self.data_type == DataType.FILEURI + else list(self.values) + ) return { "kind": "choices", "name": name, - "values": list(self.values), + "values": values, "dataType": self.data_type.value, } @classmethod def from_dict(cls, data: dict[str, Any]) -> Choices: - return Choices(*data["values"], data_type=DataType(data["dataType"])) + data_type = DataType(data["dataType"]) + values = [ + get_resource_URI_from_str(value) if data_type == DataType.FILEURI else value + for value in data["values"] + ] + return Choices(*values, data_type=data_type) @dataclass @@ -294,7 +309,20 @@ def from_dict(cls, data: dict[str, Any]) -> Normal: def get_operator_from_dict( data: dict[str, Any] -) -> Union[Range, Choices, Uniform, Beta, Normal, Enumeration, int, float, bool, str]: +) -> Union[ + Range, + Choices, + Uniform, + Beta, + Normal, + Enumeration, + int, + float, + bool, + str, + ModelicaResourceURI, + CustomArtifactURI, +]: kind = data["kind"] if kind == "range": return Range.from_dict(data) @@ -310,6 +338,8 @@ def get_operator_from_dict( data_type = DataType(data["dataType"]) if data_type == DataType.ENUMERATION: return Enumeration(data["value"]) + elif data_type == DataType.FILEURI: + return get_resource_URI_from_str(data["value"]) else: return data["value"] raise ValueError(f"Unsupported operator kind: {kind}!") diff --git a/tests/impact/client/entities/test_case.py b/tests/impact/client/entities/test_case.py index 5f188050..ddfc9361 100644 --- a/tests/impact/client/entities/test_case.py +++ b/tests/impact/client/entities/test_case.py @@ -262,7 +262,6 @@ def test_get_custom_artifact(self, experiment): artifact_stream = artifact.get_data() assert artifact_stream == b"\x00\x00\x00\x00" - @pytest.mark.experimental def test_get_custom_artifact_uri(self, experiment): case = experiment.entity.get_case(IDs.CASE_ID_PRIMARY) artifact = case.get_artifact(IDs.CUSTOM_ARTIFACT_ID) diff --git a/tests/impact/client/entities/test_custom_function.py b/tests/impact/client/entities/test_custom_function.py index 7ba3b0e3..50282b85 100644 --- a/tests/impact/client/entities/test_custom_function.py +++ b/tests/impact/client/entities/test_custom_function.py @@ -22,7 +22,6 @@ def _get_dynamic_cf(self, client_helper): dynamic = workspace.get_custom_function("dynamic") return dynamic - @pytest.mark.experimental def test_custom_function_with_parameters_ok(self, custom_function): workspace = create_workspace_entity(IDs.WORKSPACE_ID_PRIMARY) experiment = create_experiment_entity( diff --git a/tests/impact/client/entities/test_workspace.py b/tests/impact/client/entities/test_workspace.py index f58d9337..476e6857 100644 --- a/tests/impact/client/entities/test_workspace.py +++ b/tests/impact/client/entities/test_workspace.py @@ -117,7 +117,6 @@ def test_revoke_group_access_for_published_workspace(self): IDs.PUBLISHED_WORKSPACE_ID, IDs.GROUP_NAME ) - @pytest.mark.experimental def test_get_modelica_resource_uri(self): service = mock.MagicMock() workspace = create_workspace_entity(IDs.WORKSPACE_ID_PRIMARY, service=service) diff --git a/tests/impact/client/test_client.py b/tests/impact/client/test_client.py index 7e7850f4..ba96bbfc 100644 --- a/tests/impact/client/test_client.py +++ b/tests/impact/client/test_client.py @@ -233,7 +233,6 @@ def test_get_me(self, client_helper: ClientHelper): assert user.last_name is None assert user.email == IDs.MOCK_EMAIL - @pytest.mark.experimental @pytest.mark.vcr() def test_get_case_by_reference(self, client_helper: ClientHelper): case_ref = create_case_reference( @@ -244,7 +243,6 @@ def test_get_case_by_reference(self, client_helper: ClientHelper): case = client_helper.client.get_case_by_reference(case_ref) assert isinstance(case, Case) - @pytest.mark.experimental @pytest.mark.vcr() def test_get_experiment_by_reference(self, client_helper: ClientHelper): experiment_ref = create_experiment_reference(