diff --git a/src/ansys/fluent/core/services/settings.py b/src/ansys/fluent/core/services/settings.py index a11d3529f9e1..e5feab9c19ff 100644 --- a/src/ansys/fluent/core/services/settings.py +++ b/src/ansys/fluent/core/services/settings.py @@ -352,3 +352,8 @@ def get_attrs(self, path: str, attrs: List[str], recursive=False) -> Any: def has_wildcard(self, name: str) -> bool: """Checks whether a name has a wildcard pattern.""" return self._scheme_eval.scheme_eval(f'(has-wild-card? "{name}")') + + @_trace + def is_interactive_mode(self) -> bool: + """Checks whether commands can be executed interactively.""" + return False diff --git a/src/ansys/fluent/core/solver/flobject.py b/src/ansys/fluent/core/solver/flobject.py index 1f48ad3c60e4..7a22b6680a29 100644 --- a/src/ansys/fluent/core/solver/flobject.py +++ b/src/ansys/fluent/core/solver/flobject.py @@ -169,11 +169,13 @@ def get_attr(self, attr, attr_type_or_types=None) -> Any: def is_active(self) -> bool: """Whether the object is active.""" - return self.get_attr("active?", bool) + attr = self.get_attr("active?") + return False if attr is False else True def is_read_only(self) -> bool: """Whether the object is read-only.""" - return self.get_attr("read-only?", bool) + attr = self.get_attr("read-only?") + return False if attr is None else attr def __setattr__(self, name, value): raise AttributeError(name) @@ -455,6 +457,32 @@ def get_active_query_names(self): ret.append(query) return ret + def get_completer_info(self, prefix=""): + """Return list of [name, type, doc]""" + ret = [] + for child_name in self.child_names: + if child_name.startswith(prefix): + child = getattr(self, child_name) + if child.is_active(): + ret.append( + [ + child_name, + child.__class__.__bases__[0].__name__, + child.__doc__, + ] + ) + for command_name in self.command_names: + if command_name.startswith(prefix): + command = getattr(self, command_name) + if command.is_active(): + ret.append([command_name, Command.__name__, command.__doc__]) + for query_name in self.query_names: + if query_name.startswith(prefix): + query = getattr(self, query_name) + if query.is_active(): + ret.append([query_name, Query.__name__, query.__doc__]) + return ret + def _get_parent_of_active_child_names(self, name): parents = "" for parent in self.get_active_child_names(): @@ -488,7 +516,7 @@ def __setattr__(self, name: str, value): attr = None try: attr = getattr(self, name) - except BaseException as ex: + except AttributeError as ex: raise AttributeError( allowed_name_error_message( "Settings objects", name, super().__getattribute__("child_names") @@ -544,7 +572,11 @@ def __getattr__(self, name: str): self._state_cls, child_settings_cls, ) - raise AttributeError(name) + raise KeyError( + allowed_name_error_message( + "Settings objects", name, self.get_object_names() + ) + ) def to_scheme_keys(self, value): """Convert value to have keys with scheme names.""" @@ -841,6 +873,22 @@ def arguments(self) -> Any: raise RuntimeError(f"{self.__class__.__name__} is not active") return attrs["arguments"] if attrs else None + def get_completer_info(self, prefix="", excluded=None): + """Return list of [name, type, doc]""" + excluded = excluded or [] + ret = [] + for argument_name in self.argument_names: + if argument_name not in excluded and argument_name.startswith(prefix): + argument = getattr(self, argument_name) + ret.append( + [ + argument_name + "=", + argument.__class__.__bases__[0].__name__, + argument.__doc__, + ] + ) + return ret + class Command(Action): """Command object.""" @@ -848,6 +896,19 @@ class Command(Action): def __call__(self, **kwds): """Call a query with the specified keyword arguments.""" newkwds = _get_new_keywords(self, kwds) + if self.flproxy.is_interactive_mode(): + prompt = self.flproxy.get_command_confirmation_prompt( + self._parent.path, self.obj_name, **newkwds + ) + if prompt: + while True: + response = input(prompt + ": y[es]/n[o] ") + if response in ["y", "Y", "n", "N", "yes", "no"]: + break + else: + print("Enter y[es]/n[o]") + if response in ["n", "N", "no"]: + return return self.flproxy.execute_cmd(self._parent.path, self.obj_name, **newkwds) @@ -900,7 +961,7 @@ class _ChildNamedObjectAccessorMixin(collections.abc.MutableMapping): The following can be used: for name, boundary in setup.boundary_conditions.items(): - print (name, boundary()) + print (name, boundary()) even though actual boundary conditions are stored one level lower to boundary_conditions. @@ -951,7 +1012,7 @@ def __len__(self): class _CreatableNamedObjectMixin(collections.abc.MutableMapping, Generic[ChildTypeT]): - def create(self, name: str) -> ChildTypeT: + def create(self, name: str = "") -> ChildTypeT: """Create a named object. Parameters diff --git a/tests/test_flobject.py b/tests/test_flobject.py index 38aad0eb51dd..ec933206ce61 100644 --- a/tests/test_flobject.py +++ b/tests/test_flobject.py @@ -396,6 +396,9 @@ def get_attrs(self, path, attrs, recursive=False): def get_static_info(cls): return cls.root.get_static_info() + def is_interactive_mode(self): + return False + def test_primitives(): r = flobject.get_root(Proxy()) @@ -657,7 +660,10 @@ def test_accessor_methods_on_settings_object(load_static_mixer_case): existing = solver.file.read.file_type.get_attr("read-only?", bool) modified = solver.file.read.file_type.is_read_only() - assert existing == modified + if solver.get_fluent_version() < "23.2.0": + assert existing == modified + else: + assert existing == None and modified == False existing = solver.setup.boundary_conditions.velocity_inlet.get_attr( "user-creatable?", bool