ansys-fluent-core 0.35.dev0__py3-none-any.whl → 0.36.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ansys-fluent-core might be problematic. Click here for more details.

Files changed (73) hide show
  1. ansys/fluent/core/__init__.py +2 -2
  2. ansys/fluent/core/codegen/__init__.py +1 -0
  3. ansys/fluent/core/codegen/builtin_settingsgen.py +4 -0
  4. ansys/fluent/core/codegen/datamodelgen.py +13 -2
  5. ansys/fluent/core/codegen/settingsgen.py +7 -0
  6. ansys/fluent/core/docker/docker_compose.py +30 -1
  7. ansys/fluent/core/examples/downloads.py +3 -4
  8. ansys/fluent/core/fluent_connection.py +2 -3
  9. ansys/fluent/core/generated/api_tree/api_objects.json +1 -1
  10. ansys/fluent/core/generated/datamodel_231/flicing.py +20 -20
  11. ansys/fluent/core/generated/datamodel_231/meshing.py +236 -236
  12. ansys/fluent/core/generated/datamodel_232/flicing.py +50 -50
  13. ansys/fluent/core/generated/datamodel_232/meshing.py +187 -187
  14. ansys/fluent/core/generated/datamodel_241/flicing.py +45 -45
  15. ansys/fluent/core/generated/datamodel_241/meshing.py +229 -229
  16. ansys/fluent/core/generated/datamodel_242/flicing.py +50 -50
  17. ansys/fluent/core/generated/datamodel_242/meshing.py +275 -275
  18. ansys/fluent/core/generated/datamodel_242/part_management.py +3 -3
  19. ansys/fluent/core/generated/datamodel_251/flicing.py +45 -45
  20. ansys/fluent/core/generated/datamodel_251/meshing.py +417 -417
  21. ansys/fluent/core/generated/datamodel_251/part_management.py +9 -9
  22. ansys/fluent/core/generated/datamodel_252/flicing.py +30 -30
  23. ansys/fluent/core/generated/datamodel_252/meshing.py +418 -418
  24. ansys/fluent/core/generated/datamodel_252/part_management.py +5 -5
  25. ansys/fluent/core/generated/datamodel_261/flicing.py +35 -35
  26. ansys/fluent/core/generated/datamodel_261/meshing.py +481 -425
  27. ansys/fluent/core/generated/datamodel_261/meshing_utilities.py +296 -616
  28. ansys/fluent/core/generated/datamodel_261/meshing_workflow.py +61694 -0
  29. ansys/fluent/core/generated/datamodel_261/part_management.py +10 -10
  30. ansys/fluent/core/generated/datamodel_261/preferences.py +56 -0
  31. ansys/fluent/core/generated/datamodel_261/solver_workflow.py +14 -0
  32. ansys/fluent/core/generated/fluent_version_261.py +3 -3
  33. ansys/fluent/core/generated/meshing/tui_261.py +408 -10
  34. ansys/fluent/core/generated/solver/settings_261.py +15135 -5725
  35. ansys/fluent/core/generated/solver/settings_261.pyi +10252 -3619
  36. ansys/fluent/core/generated/solver/tui_261.py +2632 -834
  37. ansys/fluent/core/launcher/container_launcher.py +12 -3
  38. ansys/fluent/core/launcher/fluent_container.py +7 -1
  39. ansys/fluent/core/launcher/launch_options.py +2 -2
  40. ansys/fluent/core/launcher/launcher.py +2 -6
  41. ansys/fluent/core/launcher/pim_launcher.py +76 -3
  42. ansys/fluent/core/launcher/process_launch_string.py +1 -2
  43. ansys/fluent/core/launcher/slurm_launcher.py +4 -3
  44. ansys/fluent/core/launcher/standalone_launcher.py +3 -2
  45. ansys/fluent/core/module_config.py +10 -10
  46. ansys/fluent/core/report.py +1 -1
  47. ansys/fluent/core/search.py +12 -0
  48. ansys/fluent/core/services/__init__.py +2 -0
  49. ansys/fluent/core/services/datamodel_se.py +4 -1
  50. ansys/fluent/core/services/field_data.py +24 -0
  51. ansys/fluent/core/services/reduction.py +2 -0
  52. ansys/fluent/core/services/settings.py +1 -1
  53. ansys/fluent/core/services/solution_variables.py +92 -0
  54. ansys/fluent/core/session.py +1 -2
  55. ansys/fluent/core/session_base_meshing.py +8 -0
  56. ansys/fluent/core/session_meshing.py +5 -0
  57. ansys/fluent/core/session_pure_meshing.py +6 -0
  58. ansys/fluent/core/session_pure_meshing.pyi +5 -0
  59. ansys/fluent/core/session_solver.py +5 -4
  60. ansys/fluent/core/session_utilities.py +8 -5
  61. ansys/fluent/core/solver/flobject.py +19 -0
  62. ansys/fluent/core/solver/flunits.py +2 -0
  63. ansys/fluent/core/solver/function/reduction.py +2 -0
  64. ansys/fluent/core/ui/__init__.py +64 -0
  65. ansys/fluent/core/ui/jupyter_ui.py +203 -0
  66. ansys/fluent/core/ui/standalone_web_ui.py +296 -0
  67. ansys/fluent/core/ui/utils.py +173 -0
  68. ansys/fluent/core/utils/deprecate.py +1 -0
  69. ansys/fluent/core/utils/networking.py +11 -2
  70. {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info}/METADATA +29 -22
  71. {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info}/RECORD +73 -68
  72. {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info}/WHEEL +1 -1
  73. {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info/licenses}/LICENSE +0 -0
@@ -72,6 +72,7 @@ class BaseMeshing:
72
72
  self._fluent_version = fluent_version
73
73
  self._meshing_utilities = None
74
74
  self._old_workflow = None
75
+ self._meshing_workflow = None
75
76
  self._part_management = None
76
77
  self._pm_file_management = None
77
78
  self._preferences = None
@@ -127,6 +128,13 @@ class BaseMeshing:
127
128
  self._old_workflow = _make_datamodel_module(self, "workflow")
128
129
  return self._old_workflow
129
130
 
131
+ @property
132
+ def meshing_workflow(self):
133
+ """Full API to meshing and meshing_workflow."""
134
+ if self._meshing_workflow is None:
135
+ self._meshing_workflow = _make_datamodel_module(self, "meshing_workflow")
136
+ return self._meshing_workflow
137
+
130
138
  def watertight_workflow(self, initialize: bool = True):
131
139
  """Datamodel root of workflow."""
132
140
  self._current_workflow = WorkflowMode.WATERTIGHT_MESHING_MODE.value(
@@ -127,6 +127,11 @@ class Meshing(PureMeshing):
127
127
  """Workflow datamodel root."""
128
128
  return super(Meshing, self).workflow
129
129
 
130
+ @property
131
+ def meshing_workflow(self):
132
+ """Full API to meshing and meshing_workflow."""
133
+ return super(Meshing, self).meshing_workflow
134
+
130
135
  @property
131
136
  def PartManagement(self):
132
137
  """Part management datamodel root."""
@@ -50,6 +50,7 @@ class PureMeshing(BaseSession):
50
50
 
51
51
  _rules = [
52
52
  "workflow",
53
+ "meshing_workflow",
53
54
  "meshing",
54
55
  "MeshingUtilities",
55
56
  "PartManagement",
@@ -146,6 +147,11 @@ class PureMeshing(BaseSession):
146
147
  """Datamodel root of workflow."""
147
148
  return self._base_meshing.workflow
148
149
 
150
+ @property
151
+ def meshing_workflow(self):
152
+ """Full API to meshing and meshing_workflow."""
153
+ return self._base_meshing.meshing_workflow
154
+
149
155
  def watertight(self):
150
156
  """Get a new watertight workflow."""
151
157
  return self._base_meshing.watertight_workflow()
@@ -34,6 +34,9 @@ from ansys.fluent.core.generated.datamodel_252.preferences import (
34
34
  Root as preferences_root,
35
35
  )
36
36
  from ansys.fluent.core.generated.datamodel_252.workflow import Root as workflow_root
37
+ from ansys.fluent.core.generated.datamodel_261.meshing_workflow import (
38
+ Root as meshing_workflow_root,
39
+ )
37
40
  from ansys.fluent.core.generated.meshing.tui_252 import main_menu
38
41
 
39
42
  class PureMeshing:
@@ -45,6 +48,8 @@ class PureMeshing:
45
48
  def meshing_utilities(self) -> meshing_utilities_root: ...
46
49
  @property
47
50
  def workflow(self) -> workflow_root: ...
51
+ @property
52
+ def meshing_workflow(self) -> meshing_workflow_root: ...
48
53
  def watertight(self): ...
49
54
  def fault_tolerant(self): ...
50
55
  def two_dimensional_meshing(self): ...
@@ -160,10 +160,11 @@ class Solver(BaseSession):
160
160
  )
161
161
  #: Manage Fluent's solution monitors.
162
162
  self.monitors = MonitorsManager(fluent_connection._id, monitors_service)
163
- self.events.register_callback(
164
- (SolverEvent.SOLUTION_INITIALIZED, SolverEvent.DATA_LOADED),
165
- self.monitors.refresh,
166
- )
163
+ if not pyfluent.config.disable_monitor_refresh_on_init:
164
+ self.events.register_callback(
165
+ (SolverEvent.SOLUTION_INITIALIZED, SolverEvent.DATA_LOADED),
166
+ self.monitors.refresh,
167
+ )
167
168
 
168
169
  fluent_connection.register_finalizer_cb(self.monitors.stop)
169
170
 
@@ -90,8 +90,9 @@ class SessionBase:
90
90
 
91
91
  Parameters
92
92
  ----------
93
- ui_mode : UIMode
94
- Defines the user interface mode for Fluent. Options correspond to values in the ``UIMode`` enum.
93
+ ui_mode : UIMode or str, optional
94
+ Defines the user interface mode for Fluent. Accepts either a ``UIMode`` value
95
+ or a corresponding string such as ``"no_gui"``, ``"hidden_gui"``, or ``"gui"``.
95
96
  graphics_driver : FluentWindowsGraphicsDriver or FluentLinuxGraphicsDriver
96
97
  Specifies the graphics driver for Fluent. Options are from the ``FluentWindowsGraphicsDriver`` enum
97
98
  (for Windows) or the ``FluentLinuxGraphicsDriver`` enum (for Linux).
@@ -194,8 +195,9 @@ class SessionBase:
194
195
 
195
196
  Parameters
196
197
  ----------
197
- ui_mode : UIMode
198
- Defines the user interface mode for Fluent. Options correspond to values in the ``UIMode`` enum.
198
+ ui_mode : UIMode or str, optional
199
+ Defines the user interface mode for Fluent. Accepts either a ``UIMode`` value
200
+ or a corresponding string such as ``"no_gui"``, ``"hidden_gui"``, or ``"gui"``.
199
201
  graphics_driver : FluentWindowsGraphicsDriver or FluentLinuxGraphicsDriver
200
202
  Specifies the graphics driver for Fluent. Options are from the ``FluentWindowsGraphicsDriver`` enum
201
203
  (for Windows) or the ``FluentLinuxGraphicsDriver`` enum (for Linux).
@@ -287,7 +289,8 @@ class SessionBase:
287
289
  Parameters
288
290
  ----------
289
291
  ui_mode : UIMode or str, optional
290
- Defines the user interface mode for Fluent. Options correspond to values in the ``UIMode`` enum.
292
+ Defines the user interface mode for Fluent. Accepts either a ``UIMode`` value
293
+ or a corresponding string such as ``"no_gui"``, ``"hidden_gui"``, or ``"gui"``.
291
294
  graphics_driver : FluentWindowsGraphicsDriver or FluentLinuxGraphicsDriver
292
295
  Specifies the graphics driver for Fluent. Options are from the ``FluentWindowsGraphicsDriver`` enum
293
296
  (for Windows) or the ``FluentLinuxGraphicsDriver`` enum (for Linux).
@@ -80,6 +80,7 @@ from ansys.fluent.core.variable_strategies import (
80
80
  FluentFieldDataNamingStrategy as naming_strategy,
81
81
  )
82
82
  import ansys.units
83
+ from ansys.units import VariableDescriptor
83
84
 
84
85
  from . import _docstrings
85
86
  from ..pyfluent_warnings import warning_for_fluent_dev_version
@@ -676,7 +677,21 @@ class Textual(Property):
676
677
  Either str or VariableDescriptor.
677
678
  kwargs : Any
678
679
  Keyword arguments.
680
+
681
+ Raises
682
+ ------
683
+ TypeError
684
+ If state is not a string.
679
685
  """
686
+ allowed_types = (str, VariableDescriptor)
687
+
688
+ if not isinstance(state, allowed_types):
689
+ if self._has_migration_adapter:
690
+ return self.base_set_state(state=state, **kwargs)
691
+ raise TypeError(
692
+ f"Expected state to be {' or '.join(t.__name__ for t in allowed_types)}, "
693
+ f"got {type(state).__name__}."
694
+ )
680
695
  return self.base_set_state(state=_to_field_name_str(state), **kwargs)
681
696
 
682
697
 
@@ -2282,6 +2297,10 @@ def get_cls(name, info, parent=None, version=None, parent_taboo=None):
2282
2297
  )
2283
2298
  cls._allowed_values = allowed_values
2284
2299
 
2300
+ has_migration_adapter = info.get("has-migration-adapter?", False)
2301
+ if has_migration_adapter:
2302
+ cls._has_migration_adapter = True
2303
+
2285
2304
  except Exception:
2286
2305
  print(
2287
2306
  f"Unable to construct class for '{name}' of "
@@ -298,6 +298,8 @@ def get_si_unit_for_fluent_quantity(
298
298
  # attribute only for dimensionless variables
299
299
  if quantity is None:
300
300
  return ""
301
+ if isinstance(quantity, list): # real vector
302
+ quantity = quantity[0]
301
303
  if not isinstance(quantity, str):
302
304
  raise InvalidQuantityType(quantity)
303
305
  try:
@@ -211,6 +211,8 @@ def _eval_reduction(
211
211
  weight = "Weight=" + str(weight)
212
212
  locations = str(locations) + ", " + weight
213
213
 
214
+ if hasattr(expr, "definition"):
215
+ expr = expr.definition()
214
216
  expr_str = _expr_to_expr_str(naming_strategy().to_string(expr))
215
217
  if condition:
216
218
  expr_str = expr_str + ", " + condition
@@ -0,0 +1,64 @@
1
+ # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ """Public exposure of ui UI for PyFluent."""
24
+
25
+
26
+ def in_jupyter():
27
+ """Checks if the library is being used in a Jupyter environment."""
28
+ try:
29
+ from IPython import get_ipython
30
+
31
+ return "IPKernelApp" in get_ipython().config
32
+ except (ImportError, AttributeError):
33
+ return False
34
+
35
+
36
+ if in_jupyter():
37
+ from ansys.fluent.core.ui.jupyter_ui import (
38
+ set_auto_refresh,
39
+ settings_ui,
40
+ )
41
+ else:
42
+ from ansys.fluent.core.ui.standalone_web_ui import ( # noqa: F401
43
+ build_settings_view,
44
+ set_auto_refresh,
45
+ )
46
+
47
+
48
+ def ui(settings_obj):
49
+ """PyFluent ui UI wrapper."""
50
+ if in_jupyter():
51
+ import IPython
52
+ from IPython.display import display
53
+
54
+ if hasattr(IPython, "get_ipython") and "ZMQInteractiveShell" in str(
55
+ type(IPython.get_ipython())
56
+ ):
57
+ display(settings_ui(settings_obj))
58
+ else:
59
+ import panel as pn
60
+
61
+ pn.extension()
62
+ view = build_settings_view(settings_obj)
63
+ view.servable()
64
+ pn.serve(view)
@@ -0,0 +1,203 @@
1
+ # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ """Render ui UI in Jupyter notebook."""
24
+
25
+ from ansys.fluent.core.ui.utils import (
26
+ _parse_path,
27
+ _render_widget_from_props_generic,
28
+ _safe_get_properties,
29
+ )
30
+
31
+ try:
32
+ import ipywidgets as widgets
33
+ except ModuleNotFoundError as exc:
34
+ raise ModuleNotFoundError(
35
+ "Missing dependencies, use 'pip install ansys-fluent-core[ui-jupyter]' to install them."
36
+ ) from exc
37
+
38
+ from ansys.fluent.core.solver.flobject import (
39
+ BaseCommand,
40
+ Group,
41
+ NamedObject,
42
+ )
43
+
44
+
45
+ def set_auto_refresh():
46
+ """Refreshes the UI w.r.t. server state for each command execution or parameter invocation."""
47
+ raise NotImplementedError("This is yet to be implemented in jupyter environment.")
48
+
49
+
50
+ def _render_widgets_from_props(settings_obj, label, props):
51
+ """Render widget using pre-fetched props instead of repeated calls."""
52
+ return _render_widget_from_props_generic(settings_obj, label, props, widgets)
53
+
54
+
55
+ def _param_ui(settings_obj, props):
56
+ label = props["python_name"].replace("_", " ").capitalize()
57
+
58
+ def get_fn():
59
+ try:
60
+ return getattr(props["parent"], props["python_name"])
61
+ except AttributeError:
62
+ return props["parent"][props["obj_name"]]
63
+
64
+ def set_fn(v):
65
+ return setattr(settings_obj.parent, props["python_name"], v)
66
+
67
+ widget = _render_widgets_from_props(get_fn(), label, props)
68
+ output = widgets.Output()
69
+ with output:
70
+ output.clear_output()
71
+ print(_parse_path(settings_obj))
72
+ if hasattr(widget, "_is_list_text"):
73
+ typ, parse_csv = widget._is_list_text
74
+
75
+ def commit_text_list(change):
76
+ if change["name"] == "value":
77
+ raw = change["new"]
78
+ vals = (
79
+ [typ(v.strip()) for v in raw.split(",") if v.strip()]
80
+ if parse_csv
81
+ else list(change["new"])
82
+ )
83
+ with output:
84
+ output.clear_output()
85
+ set_fn(vals)
86
+ print(f"{_parse_path(settings_obj)} = {vals}")
87
+
88
+ widget.observe(commit_text_list)
89
+ else:
90
+
91
+ def on_change(change):
92
+ if change["name"] == "value":
93
+ with output:
94
+ output.clear_output()
95
+ try:
96
+ set_fn(change["new"])
97
+ print(f"{_parse_path(settings_obj)} = {change['new']}")
98
+ except Exception as e:
99
+ print(f"Error setting {label}: {e}")
100
+
101
+ widget.observe(on_change)
102
+ return widgets.VBox([widget, output])
103
+
104
+
105
+ def _command_ui(func, props):
106
+ """
107
+ Renders input widgets for function arguments based on .argument_names()
108
+ and executes func(**kwargs) on button click.
109
+ """
110
+
111
+ # Get argument names from the function object
112
+ if not hasattr(func, "argument_names"):
113
+ return widgets.HTML("Command has no 'argument_names()'.")
114
+
115
+ arg_names = func.argument_names
116
+ arg_widgets = {}
117
+ controls = []
118
+ for name in arg_names:
119
+ child_obj = getattr(func, name)
120
+ child_props = _safe_get_properties(child_obj)
121
+ widget = _render_widgets_from_props(child_obj, name, child_props)
122
+ arg_widgets[name] = widget
123
+ controls.append(widget)
124
+
125
+ # Run button
126
+ button = widgets.Button(
127
+ description=f"Run {props['python_name']}", button_style="success"
128
+ )
129
+ output = widgets.Output()
130
+ with output:
131
+ output.clear_output()
132
+ print(_parse_path(func))
133
+
134
+ def on_click(_):
135
+ kwargs = {name: w.value for name, w in arg_widgets.items()}
136
+ with output:
137
+ output.clear_output()
138
+ try:
139
+ func(**kwargs)
140
+ kwargs_str = "("
141
+ for k, v in kwargs.items():
142
+ if type(v) is str:
143
+ if v != "":
144
+ kwargs_str += f"{k}='{v}', "
145
+ else:
146
+ kwargs_str += f"{k}={v}, "
147
+ print(f"{_parse_path(func)}" + kwargs_str.strip()[:-1] + ")")
148
+ except Exception as e:
149
+ print("Error:", e)
150
+
151
+ button.on_click(on_click)
152
+ return widgets.VBox(controls + [button, output])
153
+
154
+
155
+ def settings_ui(obj, indent=0):
156
+ """Render settings objects into ui graphics."""
157
+ props = _safe_get_properties(obj)
158
+ if isinstance(obj, (Group, NamedObject)):
159
+ if isinstance(obj, Group):
160
+ command_names = obj.get_active_command_names()
161
+ child_names = obj.get_active_child_names() + command_names
162
+ else:
163
+ command_names = obj.command_names
164
+ child_names = list(obj) + command_names
165
+ accordions = []
166
+ for child_name in child_names:
167
+
168
+ def lazy_loader(name=child_name, parent=obj, lvl=indent + 1):
169
+ try:
170
+ child_obj = getattr(parent, name)
171
+ except AttributeError:
172
+ child_obj = parent[name]
173
+ return settings_ui(child_obj, lvl)
174
+
175
+ acc = widgets.Accordion(children=[widgets.HTML("Loading...")])
176
+ if child_name in command_names:
177
+ acc.set_title(0, f"⚡ {child_name}")
178
+ else:
179
+ acc.set_title(0, child_name)
180
+
181
+ def on_selected(change, loader=lazy_loader, accordion=acc):
182
+ if change["name"] == "selected_index" and change["new"] == 0:
183
+ if isinstance(accordion.children[0], widgets.HTML):
184
+ accordion.children = [loader()]
185
+
186
+ acc.observe(on_selected, names="selected_index")
187
+ accordions.append(acc)
188
+
189
+ return widgets.VBox(accordions)
190
+
191
+ else:
192
+ if isinstance(obj, BaseCommand):
193
+ return (
194
+ widgets.VBox([_command_ui(obj, props)])
195
+ if props["is_active"]
196
+ else widgets.HTML("")
197
+ )
198
+ else:
199
+ return (
200
+ widgets.VBox([_param_ui(obj, props)])
201
+ if props["is_active"]
202
+ else widgets.HTML("")
203
+ )