From e3d9f183274c67d592496f8c58988b86a198e39b Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Wed, 26 Oct 2022 21:15:01 +0530 Subject: [PATCH 1/8] Fixed set_state to be applicable only to CommandArguments --- src/ansys/fluent/core/services/datamodel_se.py | 8 ++------ src/ansys/fluent/core/workflow.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index 1035f25c49a3..cdf04f6bdcf3 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -709,9 +709,7 @@ def __getattr__(self, attr): mode = AccessorModes.get_mode(arg.type) py_class = mode.value[1] - return MakeReadOnly( - py_class(self, attr, self.service, self.rules, self.path, arg) - ) + return py_class(self, attr, self.service, self.rules, self.path, arg) def get_state(self) -> Any: parent_state = self.parent.get_state() @@ -766,9 +764,7 @@ def __getattr__(self, attr): if arg.name == attr: mode = AccessorModes.get_mode(arg.type) py_class = mode.value[1] - return MakeReadOnly( - py_class(self, attr, self.service, self.rules, self.path, arg) - ) + return py_class(self, attr, self.service, self.rules, self.path, arg) class PyTextualCommandArgumentsSubItem(PyCommandArgumentsSubItem, PyTextual): diff --git a/src/ansys/fluent/core/workflow.py b/src/ansys/fluent/core/workflow.py index 2177b4d68d9e..eba8e3c7a54f 100644 --- a/src/ansys/fluent/core/workflow.py +++ b/src/ansys/fluent/core/workflow.py @@ -56,7 +56,17 @@ def _refreshed_command(self): cmd = self._command() if task_arg_state: cmd.set_state(task_arg_state) - return MakeReadOnly(cmd) + return MakeReadOnly(self._cmd_sub_items_read_only(cmd)) + + def _cmd_sub_items_read_only(self, cmd): + for item in cmd(): + if type(getattr(cmd, item).get_state()) == dict: + setattr( + cmd, item, self._cmd_sub_items_read_only(getattr(cmd, item)) + ) + # cmd = self._cmd_sub_items_read_only(getattr(cmd, item)) + setattr(cmd, item, MakeReadOnly(getattr(cmd, item))) + return cmd def _command(self): if not self._cmd: From 97c402031251f08bd643ec153e6c9866c18d4a2a Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Thu, 27 Oct 2022 10:51:10 +0530 Subject: [PATCH 2/8] Moved MakeReadOnly from datamodel_se to workflow.py and made it private --- .../fluent/core/services/datamodel_se.py | 25 --------------- src/ansys/fluent/core/workflow.py | 32 ++++++++++++++++--- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index cdf04f6bdcf3..8f7e0e2da979 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -857,31 +857,6 @@ def get_mode(mode: str) -> "AccessorModes": return AccessorModes.GENERIC -class MakeReadOnly: - """Removes 'set_state()' attribute to implement read-only behaviour.""" - - _unwanted_attr = ["set_state", "setState"] - - def __init__(self, cmd): - self._cmd = cmd - - def __getattr__(self, attr): - if attr in MakeReadOnly._unwanted_attr: - raise AttributeError("Command Arguments are read-only.") - return getattr(self._cmd, attr) - - def __dir__(self): - returned_list = sorted( - set(list(self.__dict__.keys()) + dir(type(self)) + dir(self._cmd)) - ) - for attr in MakeReadOnly._unwanted_attr: - returned_list.remove(attr) - return returned_list - - def __call__(self): - return self._cmd() - - class PyMenuGeneric(PyMenu): attrs = ("service", "rules", "path") diff --git a/src/ansys/fluent/core/workflow.py b/src/ansys/fluent/core/workflow.py index eba8e3c7a54f..cd091b702db0 100644 --- a/src/ansys/fluent/core/workflow.py +++ b/src/ansys/fluent/core/workflow.py @@ -1,4 +1,4 @@ -from ansys.fluent.core.services.datamodel_se import MakeReadOnly, PyCallableStateObject +from ansys.fluent.core.services.datamodel_se import PyCallableStateObject def _new_command_for_task(task, session): @@ -56,7 +56,7 @@ def _refreshed_command(self): cmd = self._command() if task_arg_state: cmd.set_state(task_arg_state) - return MakeReadOnly(self._cmd_sub_items_read_only(cmd)) + return _MakeReadOnly(self._cmd_sub_items_read_only(cmd)) def _cmd_sub_items_read_only(self, cmd): for item in cmd(): @@ -64,8 +64,7 @@ def _cmd_sub_items_read_only(self, cmd): setattr( cmd, item, self._cmd_sub_items_read_only(getattr(cmd, item)) ) - # cmd = self._cmd_sub_items_read_only(getattr(cmd, item)) - setattr(cmd, item, MakeReadOnly(getattr(cmd, item))) + setattr(cmd, item, _MakeReadOnly(getattr(cmd, item))) return cmd def _command(self): @@ -108,3 +107,28 @@ def __dir__(self): def __call__(self): return self._workflow() + + +class _MakeReadOnly: + """Removes 'set_state()' attribute to implement read-only behaviour.""" + + _unwanted_attr = ["set_state", "setState"] + + def __init__(self, cmd): + self._cmd = cmd + + def __getattr__(self, attr): + if attr in _MakeReadOnly._unwanted_attr: + raise AttributeError("Command Arguments are read-only.") + return getattr(self._cmd, attr) + + def __dir__(self): + returned_list = sorted( + set(list(self.__dict__.keys()) + dir(type(self)) + dir(self._cmd)) + ) + for attr in _MakeReadOnly._unwanted_attr: + returned_list.remove(attr) + return returned_list + + def __call__(self): + return self._cmd() From 20759ccc0a88d019f703af1ae89e99d1070febf6 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Thu, 27 Oct 2022 12:37:55 +0530 Subject: [PATCH 3/8] Updated test coverage --- src/ansys/fluent/core/workflow.py | 3 ++- tests/test_meshing_workflow.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ansys/fluent/core/workflow.py b/src/ansys/fluent/core/workflow.py index cd091b702db0..2c31da8f2e6c 100644 --- a/src/ansys/fluent/core/workflow.py +++ b/src/ansys/fluent/core/workflow.py @@ -127,7 +127,8 @@ def __dir__(self): set(list(self.__dict__.keys()) + dir(type(self)) + dir(self._cmd)) ) for attr in _MakeReadOnly._unwanted_attr: - returned_list.remove(attr) + if attr in returned_list: + returned_list.remove(attr) return returned_list def __call__(self): diff --git a/tests/test_meshing_workflow.py b/tests/test_meshing_workflow.py index 9a9908c719d6..13944c243ecb 100644 --- a/tests/test_meshing_workflow.py +++ b/tests/test_meshing_workflow.py @@ -303,12 +303,25 @@ def test_read_only_behaviour_of_command_arguments(new_mesh_session): assert "set_state" not in dir(w.task("Import Geometry").CommandArguments) assert "set_state" not in dir(w.task("Import Geometry").CommandArguments.LengthUnit) + assert "set_state" not in dir( + w.task("Import Geometry").CommandArguments.CadImportOptions + ) + assert "set_state" not in dir( + w.task("Import Geometry").CommandArguments.CadImportOptions.OneZonePer + ) with pytest.raises(AttributeError) as msg: w.task("Import Geometry").CommandArguments.MeshUnit.set_state("in") assert msg.value.args[0] == "Command Arguments are read-only." + with pytest.raises(AttributeError) as msg: + w.task( + "Import Geometry" + ).CommandArguments.CadImportOptions.OneZonePer.set_state(None) + assert msg.value.args[0] == "Command Arguments are read-only." + assert "set_state" in dir(m.ImportGeometry.new()) + assert "set_state" in dir(m.ImportGeometry.new().NumParts) @pytest.mark.dev From 6c510e464d3f168e70bc1edeec816f937273fbe6 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Thu, 27 Oct 2022 15:42:11 +0530 Subject: [PATCH 4/8] Raise attribute error for PyCommandArguments accessor methods --- src/ansys/fluent/core/services/datamodel_se.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index 8f7e0e2da979..73e6bc57790f 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -714,6 +714,9 @@ def __getattr__(self, attr): def get_state(self) -> Any: parent_state = self.parent.get_state() try: + # TODO: check if a better implementation is possible. + if self.name in dir(PyTextual) + dir(PyNumerical) + dir(PyDictionary): + raise AttributeError(f"Attribute name '{self.name}' not found.") return parent_state[self.name] except KeyError: pass From 1ca67c1db3ed0e5a3ed49769a2f1e54693e256c3 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Thu, 27 Oct 2022 16:39:22 +0530 Subject: [PATCH 5/8] Updated tests --- src/ansys/fluent/core/services/datamodel_se.py | 11 ++++++++--- tests/test_meshing_workflow.py | 13 ++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index 73e6bc57790f..e5fec7358c51 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -705,6 +705,7 @@ def __init__( self.parent_arg = parent_arg def __getattr__(self, attr): + self._raise_attr_error_for_common_accessor_methods(attr) arg = self.parent_arg.info.parameters[attr] mode = AccessorModes.get_mode(arg.type) @@ -714,15 +715,19 @@ def __getattr__(self, attr): def get_state(self) -> Any: parent_state = self.parent.get_state() try: - # TODO: check if a better implementation is possible. - if self.name in dir(PyTextual) + dir(PyNumerical) + dir(PyDictionary): - raise AttributeError(f"Attribute name '{self.name}' not found.") + self._raise_attr_error_for_common_accessor_methods(self.name) return parent_state[self.name] except KeyError: pass getState = get_state + @staticmethod + def _raise_attr_error_for_common_accessor_methods(attr): + # TODO: check if a better implementation is possible. + if attr in dir(PyTextual) + dir(PyNumerical) + dir(PyDictionary): + raise AttributeError(f"Attribute name '{attr}' not found.") + def get_attrib_value(self, attrib: str) -> Any: attrib_path = f"{self.name}/{attrib}" return self.parent.get_attrib_value(attrib_path) diff --git a/tests/test_meshing_workflow.py b/tests/test_meshing_workflow.py index 13944c243ecb..186885802ae0 100644 --- a/tests/test_meshing_workflow.py +++ b/tests/test_meshing_workflow.py @@ -287,10 +287,21 @@ def test_accessors_for_argument_sub_items(new_mesh_session): ) # Test intended to fail in numerical type (allowed_values() only available in string types) - with pytest.raises(AttributeError): + with pytest.raises(AttributeError) as msg: assert w.task( "Import Geometry" ).CommandArguments.CadImportOptions.FeatureAngle.allowed_values() + assert msg.value.args[0] == "Attribute name 'allowed_values' not found." + + # Test intended to fail in numerical type (allowed_values() only available in string types) + with pytest.raises(AttributeError) as msg: + assert w.task("Import Geometry").CommandArguments.NumParts.allowed_values() + assert msg.value.args[0] == "Attribute name 'allowed_values' not found." + + # Test intended to fail in string type (min() only available in numerical types) + with pytest.raises(AttributeError) as msg: + assert w.task("Import Geometry").CommandArguments.LengthUnit.min() + assert msg.value.args[0] == "Attribute name 'min' not found." @pytest.mark.dev From e84a23ae4b8bd74eb76f52e9fc161146da641149 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Mon, 31 Oct 2022 17:34:58 +0530 Subject: [PATCH 6/8] Handle Model Objects via. PySingletonCommandArgumnetSubItems --- .../fluent/core/services/datamodel_se.py | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index e5fec7358c51..6222855dc95d 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -704,30 +704,15 @@ def __init__( self.path = path self.parent_arg = parent_arg - def __getattr__(self, attr): - self._raise_attr_error_for_common_accessor_methods(attr) - arg = self.parent_arg.info.parameters[attr] - - mode = AccessorModes.get_mode(arg.type) - py_class = mode.value[1] - return py_class(self, attr, self.service, self.rules, self.path, arg) - def get_state(self) -> Any: parent_state = self.parent.get_state() try: - self._raise_attr_error_for_common_accessor_methods(self.name) return parent_state[self.name] except KeyError: pass getState = get_state - @staticmethod - def _raise_attr_error_for_common_accessor_methods(attr): - # TODO: check if a better implementation is possible. - if attr in dir(PyTextual) + dir(PyNumerical) + dir(PyDictionary): - raise AttributeError(f"Attribute name '{attr}' not found.") - def get_attrib_value(self, attrib: str) -> Any: attrib_path = f"{self.name}/{attrib}" return self.parent.get_attrib_value(attrib_path) @@ -839,6 +824,28 @@ def __init__( PyParameter.__init__(self, service, rules, path) +class PySingletonCommandArgumentsSubItem(PyCommandArgumentsSubItem): + def __init__( + self, + parent, + attr, + service: DatamodelService, + rules: str, + path: Path, + arg, + ): + PyCommandArgumentsSubItem.__init__( + self, parent, attr, service, rules, path, arg + ) + + def __getattr__(self, attr): + arg = self.parent_arg.info.parameters[attr] + + mode = AccessorModes.get_mode(arg.type) + py_class = mode.value[1] + return py_class(self, attr, self.service, self.rules, self.path, arg) + + class AccessorModes(Enum): """Provides the standard Fluent launch modes.""" @@ -853,6 +860,7 @@ class AccessorModes(Enum): ["Bool", "Logical", "Logical List"], PyParameterCommandArgumentsSubItem, ) + MODELOBJECT = (["ModelObject"], PySingletonCommandArgumentsSubItem) GENERIC = ([], PyCommandArgumentsSubItem) @staticmethod From 93f0600862f982f998cc42721ed81ce837b4df11 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Mon, 31 Oct 2022 17:51:42 +0530 Subject: [PATCH 7/8] Updated the error message --- tests/test_meshing_workflow.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/test_meshing_workflow.py b/tests/test_meshing_workflow.py index 186885802ae0..472bbf7a0b33 100644 --- a/tests/test_meshing_workflow.py +++ b/tests/test_meshing_workflow.py @@ -291,17 +291,26 @@ def test_accessors_for_argument_sub_items(new_mesh_session): assert w.task( "Import Geometry" ).CommandArguments.CadImportOptions.FeatureAngle.allowed_values() - assert msg.value.args[0] == "Attribute name 'allowed_values' not found." + assert ( + msg.value.args[0] + == "'PyNumericalCommandArgumentsSubItem' object has no attribute 'allowed_values'" + ) # Test intended to fail in numerical type (allowed_values() only available in string types) with pytest.raises(AttributeError) as msg: assert w.task("Import Geometry").CommandArguments.NumParts.allowed_values() - assert msg.value.args[0] == "Attribute name 'allowed_values' not found." + assert ( + msg.value.args[0] + == "'PyNumericalCommandArgumentsSubItem' object has no attribute 'allowed_values'" + ) # Test intended to fail in string type (min() only available in numerical types) with pytest.raises(AttributeError) as msg: assert w.task("Import Geometry").CommandArguments.LengthUnit.min() - assert msg.value.args[0] == "Attribute name 'min' not found." + assert ( + msg.value.args[0] + == "'PyTextualCommandArgumentsSubItem' object has no attribute 'min'" + ) @pytest.mark.dev From 825899e5a98503d955c9598d72d44a863a115d91 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Tue, 1 Nov 2022 12:50:38 +0530 Subject: [PATCH 8/8] Raise exception if type does not match requirement. --- src/ansys/fluent/core/services/datamodel_se.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index 6222855dc95d..b4a9cceb17a4 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -861,7 +861,6 @@ class AccessorModes(Enum): PyParameterCommandArgumentsSubItem, ) MODELOBJECT = (["ModelObject"], PySingletonCommandArgumentsSubItem) - GENERIC = ([], PyCommandArgumentsSubItem) @staticmethod def get_mode(mode: str) -> "AccessorModes": @@ -870,7 +869,7 @@ def get_mode(mode: str) -> "AccessorModes": if mode in m.value[0]: return m else: - return AccessorModes.GENERIC + raise TypeError(f"The specified mode: {mode} was not found.") class PyMenuGeneric(PyMenu):