From 39ec2b56c0d9cf1fe050c998339a2b735daf4e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Baussart?= Date: Tue, 12 Nov 2024 14:52:53 +0100 Subject: [PATCH 1/6] feat: add any_operator support --- src/ansys/dpf/core/any.py | 6 +++++ src/ansys/dpf/core/dpf_operator.py | 32 ++++++++++++++++++++------ src/ansys/dpf/gate/any_grpcapi.py | 10 ++++++++ src/ansys/dpf/gate/operator_grpcapi.py | 4 ++++ tests/entry/conftest.py | 3 +++ tests/test_any.py | 12 ++++++++++ 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/ansys/dpf/core/any.py b/src/ansys/dpf/core/any.py index fc7d0f4738b..0ae1f8b530e 100644 --- a/src/ansys/dpf/core/any.py +++ b/src/ansys/dpf/core/any.py @@ -123,6 +123,7 @@ def _type_to_new_from_get_as_method(self, obj): custom_type_field, collection, workflow, + dpf_operator, ) if issubclass(obj, int): @@ -196,6 +197,11 @@ def _type_to_new_from_get_as_method(self, obj): self._api.any_new_from_int_collection, self._api.any_get_as_int_collection, ) + elif issubclass(obj, dpf_operator.Operator): + return ( + self._api.any_new_from_operator, + self._api.any_get_as_operator, + ) @staticmethod def new_from(obj, server=None): diff --git a/src/ansys/dpf/core/dpf_operator.py b/src/ansys/dpf/core/dpf_operator.py index ca83d616673..60210791285 100644 --- a/src/ansys/dpf/core/dpf_operator.py +++ b/src/ansys/dpf/core/dpf_operator.py @@ -121,7 +121,7 @@ class Operator: """ - def __init__(self, name, config=None, server=None): + def __init__(self, name=None, operator=None, config=None, server=None): """Initialize the operator with its name by connecting to a stub.""" self.name = name self._internal_obj = None @@ -136,14 +136,32 @@ def __init__(self, name, config=None, server=None): # step 2: get api self._api_instance = None # see _api property - # step3: init environment - self._api.init_operator_environment(self) # creates stub when gRPC - # step4: if object exists: take instance, else create it (server) - if self._server.has_client(): - self._internal_obj = self._api.operator_new_on_client(self.name, self._server.client) + # step2: if object exists, take the instance, else create it + if operator is not None: + if isinstance(operator, Operator): + self._server = operator._server + self._api = self._server.get_api_for_type( + capi=operator_capi.OperatorCAPI, + grpcapi=operator_grpcapi.OperatorGRPCAPI, + ) + # step3: init environment + self._api.init_operator_environment(self) # creates stub when gRPC + core_api = self._server.get_api_for_type( + capi=data_processing_capi.DataProcessingCAPI, + grpcapi=data_processing_grpcapi.DataProcessingGRPCAPI, + ) + core_api.init_data_processing_environment(self) + self._internal_obj = core_api.data_processing_duplicate_object_reference(operator) + self.name = operator.name + else: + self._internal_obj = operator + self.name = self._api.operator_name(self) else: - self._internal_obj = self._api.operator_new(self.name) + if self._server.has_client(): + self._internal_obj = self._api.operator_new_on_client(self.name, self._server.client) + else: + self._internal_obj = self._api.operator_new(self.name) if self._internal_obj is None: raise KeyError( diff --git a/src/ansys/dpf/gate/any_grpcapi.py b/src/ansys/dpf/gate/any_grpcapi.py index 69e178d98c6..c263e904ffa 100644 --- a/src/ansys/dpf/gate/any_grpcapi.py +++ b/src/ansys/dpf/gate/any_grpcapi.py @@ -42,6 +42,7 @@ def _type_to_message_type(): custom_type_field, collection_base, workflow, + dpf_operator, ) return [(int, base_pb2.Type.INT), @@ -58,6 +59,7 @@ def _type_to_message_type(): (workflow.Workflow, base_pb2.Type.WORKFLOW), (collection_base.CollectionBase, base_pb2.Type.COLLECTION, base_pb2.Type.ANY), (dpf_vector.DPFVectorInt, base_pb2.Type.COLLECTION, base_pb2.Type.INT), + (dpf_operator.Operator, base_pb2.Type.OPERATOR), ] @staticmethod @@ -145,6 +147,10 @@ def any_get_as_int_collection(any): def any_get_as_workflow(any): return AnyGRPCAPI._get_as(any).workflow + @staticmethod + def any_get_as_operator(any): + return AnyGRPCAPI._get_as(any).operator + @staticmethod def _new_from(any, client=None): from ansys.grpc.dpf import dpf_any_pb2 @@ -230,3 +236,7 @@ def any_new_from_data_tree(any): @staticmethod def any_new_from_workflow(any): return AnyGRPCAPI._new_from(any, any._server) + + @staticmethod + def any_new_from_operator(any): + return AnyGRPCAPI._new_from(any, any._server) diff --git a/src/ansys/dpf/gate/operator_grpcapi.py b/src/ansys/dpf/gate/operator_grpcapi.py index 2f42d451e93..7eaad43aed5 100644 --- a/src/ansys/dpf/gate/operator_grpcapi.py +++ b/src/ansys/dpf/gate/operator_grpcapi.py @@ -51,6 +51,10 @@ def get_list(op): def operator_get_config(op): return OperatorGRPCAPI.get_list(op).config + @staticmethod + def operator_name(op): + return OperatorGRPCAPI.get_list(op).op_name + @staticmethod def update_init(op, pin): from ansys.grpc.dpf import operator_pb2 diff --git a/tests/entry/conftest.py b/tests/entry/conftest.py index 027c1ca64ed..b289a504f46 100644 --- a/tests/entry/conftest.py +++ b/tests/entry/conftest.py @@ -70,6 +70,9 @@ def _get_test_files_directory(): "/tmp/test_files" ) +SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0 = meets_version( + get_server_version(core._global_server()), "10.0" +) SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_8_1 = meets_version( get_server_version(core._global_server()), "8.1" ) diff --git a/tests/test_any.py b/tests/test_any.py index 5ec94862828..2ad90264665 100644 --- a/tests/test_any.py +++ b/tests/test_any.py @@ -132,3 +132,15 @@ def test_cast_workflow_any(server_type): new_entity = any_dpf.cast() assert new_entity.input_names == [] + + +@pytest.mark.skipif( + not conftest.SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0, + reason="any does not support operator below 8.0", +) +def test_cast_operator_any(server_type): + entity = dpf.Operator(server=server_type, name="U") + any_dpf = dpf.Any.new_from(entity) + new_entity = any_dpf.cast() + + assert entity.name == new_entity.name From bd3d5e97e50ea308421fe941793a7f98914541bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Baussart?= Date: Mon, 18 Nov 2024 14:16:14 +0100 Subject: [PATCH 2/6] fix: change param order in Operator.__init__() for retro-compatibility fix: apply style checks --- src/ansys/dpf/core/dpf_operator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ansys/dpf/core/dpf_operator.py b/src/ansys/dpf/core/dpf_operator.py index 60210791285..594a3907acf 100644 --- a/src/ansys/dpf/core/dpf_operator.py +++ b/src/ansys/dpf/core/dpf_operator.py @@ -121,7 +121,7 @@ class Operator: """ - def __init__(self, name=None, operator=None, config=None, server=None): + def __init__(self, name=None, config=None, server=None, operator=None): """Initialize the operator with its name by connecting to a stub.""" self.name = name self._internal_obj = None @@ -136,7 +136,6 @@ def __init__(self, name=None, operator=None, config=None, server=None): # step 2: get api self._api_instance = None # see _api property - # step2: if object exists, take the instance, else create it if operator is not None: if isinstance(operator, Operator): @@ -159,7 +158,9 @@ def __init__(self, name=None, operator=None, config=None, server=None): self.name = self._api.operator_name(self) else: if self._server.has_client(): - self._internal_obj = self._api.operator_new_on_client(self.name, self._server.client) + self._internal_obj = self._api.operator_new_on_client( + self.name, self._server.client + ) else: self._internal_obj = self._api.operator_new(self.name) From dd9d36834199512499efb5bc10b377daeccb422f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Baussart?= Date: Thu, 21 Nov 2024 10:44:23 +0100 Subject: [PATCH 3/6] fix: fix server version check --- tests/conftest.py | 3 +++ tests/entry/conftest.py | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 458a5db4232..73c3f59ce9e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -328,6 +328,9 @@ def return_ds(server=None): return return_ds +SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0 = meets_version( + get_server_version(core._global_server()), "10.0" +) SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_9_1 = meets_version( get_server_version(core._global_server()), "9.1" ) diff --git a/tests/entry/conftest.py b/tests/entry/conftest.py index b289a504f46..027c1ca64ed 100644 --- a/tests/entry/conftest.py +++ b/tests/entry/conftest.py @@ -70,9 +70,6 @@ def _get_test_files_directory(): "/tmp/test_files" ) -SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0 = meets_version( - get_server_version(core._global_server()), "10.0" -) SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_8_1 = meets_version( get_server_version(core._global_server()), "8.1" ) From b898cf17479ed727355f9b5ae55065fc16985754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Baussart?= Date: Fri, 22 Nov 2024 13:05:31 +0100 Subject: [PATCH 4/6] fix: add missing `init_operator_environment()` in `Operator.__init__(operator=None)` --- src/ansys/dpf/core/dpf_operator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ansys/dpf/core/dpf_operator.py b/src/ansys/dpf/core/dpf_operator.py index 594a3907acf..93bb68d3c84 100644 --- a/src/ansys/dpf/core/dpf_operator.py +++ b/src/ansys/dpf/core/dpf_operator.py @@ -157,6 +157,9 @@ def __init__(self, name=None, config=None, server=None, operator=None): self._internal_obj = operator self.name = self._api.operator_name(self) else: + # step3: init environment + self._api.init_operator_environment(self) # creates stub when gRPC + if self._server.has_client(): self._internal_obj = self._api.operator_new_on_client( self.name, self._server.client From 1a43b0af65b11ea6084f59a0ed73d3ecb6cfb307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Baussart?= Date: Fri, 22 Nov 2024 14:04:13 +0100 Subject: [PATCH 5/6] fix: fix Operator copy construction --- src/ansys/dpf/core/dpf_operator.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/ansys/dpf/core/dpf_operator.py b/src/ansys/dpf/core/dpf_operator.py index 93bb68d3c84..b0e2add66b5 100644 --- a/src/ansys/dpf/core/dpf_operator.py +++ b/src/ansys/dpf/core/dpf_operator.py @@ -136,16 +136,12 @@ def __init__(self, name=None, config=None, server=None, operator=None): # step 2: get api self._api_instance = None # see _api property - # step2: if object exists, take the instance, else create it + # step 3: init environment + self._api.init_operator_environment(self) # creates stub when gRPC + + # step 4: if object exists, take the instance, else create it if operator is not None: if isinstance(operator, Operator): - self._server = operator._server - self._api = self._server.get_api_for_type( - capi=operator_capi.OperatorCAPI, - grpcapi=operator_grpcapi.OperatorGRPCAPI, - ) - # step3: init environment - self._api.init_operator_environment(self) # creates stub when gRPC core_api = self._server.get_api_for_type( capi=data_processing_capi.DataProcessingCAPI, grpcapi=data_processing_grpcapi.DataProcessingGRPCAPI, @@ -157,9 +153,6 @@ def __init__(self, name=None, config=None, server=None, operator=None): self._internal_obj = operator self.name = self._api.operator_name(self) else: - # step3: init environment - self._api.init_operator_environment(self) # creates stub when gRPC - if self._server.has_client(): self._internal_obj = self._api.operator_new_on_client( self.name, self._server.client From 0ba1344cde1d580876563704165223bb99df4cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Baussart?= Date: Fri, 22 Nov 2024 14:52:44 +0100 Subject: [PATCH 6/6] feat: add test for Operator copy construction --- tests/test_operator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_operator.py b/tests/test_operator.py index 7dc3d617155..8cfadd185b7 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -54,6 +54,12 @@ def test_create_operator(server_type): assert op._internal_obj +def test_create_operator_from_operator(server_type): + op = dpf.core.Operator("min_max", server=server_type) + op2 = dpf.core.Operator(operator=op, server=server_type) + assert op2._internal_obj + + def test_invalid_operator_name(server_type): # with pytest.raises(errors.DPFServerException): with pytest.raises(Exception):