Skip to content

Commit 25a6a4c

Browse files
FEAT: Add an App method to print project tree for embedding scenario (#779)
Co-authored-by: pyansys-ci-bot <[email protected]>
1 parent c39b405 commit 25a6a4c

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

doc/changelog.d/779.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FEAT: Add an App method to print project tree for embedding scenario

src/ansys/mechanical/core/embedding/app.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,78 @@ def update_globals(
330330
def _update_all_globals(self) -> None:
331331
for scope in self._updated_scopes:
332332
scope.update(global_entry_points(self))
333+
334+
def _print_tree(self, node, max_lines, lines_count, indentation):
335+
"""Recursively print till provided maximum lines limit.
336+
337+
Parameters
338+
----------
339+
lines_count: int, optional
340+
The current count of lines printed. Default is 0.
341+
indentation: str, optional
342+
The indentation string used for printing the tree structure. Default is "".
343+
"""
344+
if lines_count >= max_lines and max_lines != -1:
345+
print(f"... truncating after {max_lines} lines")
346+
return lines_count
347+
348+
if not hasattr(node, "Name"):
349+
raise AttributeError("Object must have a 'Name' attribute")
350+
351+
node_name = node.Name
352+
if hasattr(node, "Suppressed") and node.Suppressed is True:
353+
node_name += " (Suppressed)"
354+
print(f"{indentation}├── {node.Name}")
355+
lines_count += 1
356+
357+
if hasattr(node, "Children") and node.Children is not None and node.Children.Count > 0:
358+
for child in node.Children:
359+
_lines_count = self._print_tree(child, max_lines, lines_count, indentation + "| ")
360+
if _lines_count >= max_lines and max_lines != -1:
361+
break
362+
363+
return lines_count
364+
365+
def print_tree(self, node, max_lines=80, lines_count=0, indentation=""):
366+
"""
367+
Print the hierarchical tree representation of the Mechanical project structure.
368+
369+
Each object in the tree is expected to have the following attributes:
370+
- Name: The name of the object.
371+
- Suppressed : Print as suppressed, if object is suppressed.
372+
- Children: Checks if object have children.
373+
Each child node is expected to have the all these attributes.
374+
375+
Parameters
376+
----------
377+
node: ExtAPI object
378+
The starting object of the tree.
379+
max_lines: int, optional
380+
The maximum number of lines to print. Default is 80. If set to -1, no limit is applied.
381+
382+
Raises
383+
------
384+
AttributeError
385+
If the node does not have the required attributes.
386+
387+
Examples
388+
--------
389+
>>> import ansys.mechanical.core as mech
390+
>>> app = mech.App()
391+
>>> app.update_globals(globals())
392+
>>> app.print_tree(DataModel.Project)
393+
... ├── Project
394+
... | ├── Model
395+
... | | ├── Geometry Imports
396+
... | | ├── Geometry
397+
... | | ├── Materials
398+
... | | ├── Coordinate Systems
399+
... | | | ├── Global Coordinate System
400+
... | | ├── Remote Points
401+
... | | ├── Mesh
402+
403+
>>> app.print_tree(DataModel.Project, 1)
404+
... ├── Project
405+
... ... truncating after 1 lines
406+
"""
407+
self._print_tree(node, max_lines, lines_count, indentation)

tests/embedding/test_app.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,28 @@ def test_nonblock_sleep(embedded_app):
103103
assert (t2 - t1) >= 1
104104

105105

106+
@pytest.mark.embedding
107+
def test_app_print_tree(embedded_app, capsys, assets):
108+
"""Test printing hierarchical tree of Mechanical ExtAPI object"""
109+
embedded_app.update_globals(globals())
110+
geometry_file = os.path.join(assets, "Eng157.x_t")
111+
geometry_import = Model.GeometryImportGroup.AddGeometryImport()
112+
geometry_import.Import(geometry_file)
113+
allbodies = Model.GetChildren(DataModelObjectCategory.Body, True)
114+
allbodies[0].Suppressed = True
115+
embedded_app.print_tree(DataModel.Project, 1)
116+
captured = capsys.readouterr()
117+
printed_output = captured.out.strip()
118+
assert "Project" in printed_output
119+
embedded_app.print_tree(DataModel.Project, 2)
120+
captured = capsys.readouterr()
121+
printed_output = captured.out.strip()
122+
assert "Model" in printed_output
123+
124+
with pytest.raises(AttributeError):
125+
embedded_app.print_tree(DataModel)
126+
127+
106128
@pytest.mark.embedding
107129
def test_app_poster(embedded_app):
108130
"""The getters of app should be usable after a new().

0 commit comments

Comments
 (0)