diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index 1035f25c49a3..b4a9cceb17a4 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -704,15 +704,6 @@ def __init__( self.path = path self.parent_arg = parent_arg - def __getattr__(self, attr): - arg = self.parent_arg.info.parameters[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) - ) - def get_state(self) -> Any: parent_state = self.parent.get_state() try: @@ -766,9 +757,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): @@ -835,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.""" @@ -849,7 +860,7 @@ class AccessorModes(Enum): ["Bool", "Logical", "Logical List"], PyParameterCommandArgumentsSubItem, ) - GENERIC = ([], PyCommandArgumentsSubItem) + MODELOBJECT = (["ModelObject"], PySingletonCommandArgumentsSubItem) @staticmethod def get_mode(mode: str) -> "AccessorModes": @@ -858,32 +869,7 @@ def get_mode(mode: str) -> "AccessorModes": if mode in m.value[0]: return m else: - 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() + raise TypeError(f"The specified mode: {mode} was not found.") class PyMenuGeneric(PyMenu): diff --git a/src/ansys/fluent/core/workflow.py b/src/ansys/fluent/core/workflow.py index 2177b4d68d9e..2c31da8f2e6c 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,16 @@ 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)) + ) + setattr(cmd, item, _MakeReadOnly(getattr(cmd, item))) + return cmd def _command(self): if not self._cmd: @@ -98,3 +107,29 @@ 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: + if attr in returned_list: + returned_list.remove(attr) + return returned_list + + def __call__(self): + return self._cmd() diff --git a/tests/test_meshing_workflow.py b/tests/test_meshing_workflow.py index 9a9908c719d6..472bbf7a0b33 100644 --- a/tests/test_meshing_workflow.py +++ b/tests/test_meshing_workflow.py @@ -287,10 +287,30 @@ 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] + == "'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] + == "'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] + == "'PyTextualCommandArgumentsSubItem' object has no attribute 'min'" + ) @pytest.mark.dev @@ -303,12 +323,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