diff --git a/doc/changelog.d/1881.added.md b/doc/changelog.d/1881.added.md new file mode 100644 index 0000000000..0684c579d2 --- /dev/null +++ b/doc/changelog.d/1881.added.md @@ -0,0 +1 @@ +add tracker v0 \ No newline at end of file diff --git a/src/ansys/geometry/core/tools/problem_areas.py b/src/ansys/geometry/core/tools/problem_areas.py index bea39b436d..ec67d2677f 100644 --- a/src/ansys/geometry/core/tools/problem_areas.py +++ b/src/ansys/geometry/core/tools/problem_areas.py @@ -48,6 +48,7 @@ ) from ansys.geometry.core.misc.checks import check_type_all_elements_in_iterable from ansys.geometry.core.tools.repair_tool_message import RepairToolMessage +from ansys.geometry.core.tools.tracker_response_message import TrackerResponseMessage if TYPE_CHECKING: # pragma: no cover from ansys.geometry.core.designer.body import Body @@ -135,6 +136,7 @@ def fix(self) -> RepairToolMessage: response.result.success, response.result.created_bodies_monikers, response.result.modified_bodies_monikers, + tracked_changes=TrackerResponseMessage(response.result.complete_command_response), ) return message @@ -190,6 +192,7 @@ def fix(self) -> RepairToolMessage: response.result.success, response.result.created_bodies_monikers, response.result.modified_bodies_monikers, + tracked_changes=TrackerResponseMessage(response.result.complete_command_response), ) return message @@ -244,6 +247,7 @@ def fix(self) -> RepairToolMessage: response.result.success, response.result.created_bodies_monikers, response.result.modified_bodies_monikers, + tracked_changes=TrackerResponseMessage(response.result.complete_command_response), ) return message @@ -297,6 +301,7 @@ def fix(self) -> RepairToolMessage: response.result.success, response.result.created_bodies_monikers, response.result.modified_bodies_monikers, + tracked_changes=TrackerResponseMessage(response.result.complete_command_response), ) return message @@ -398,15 +403,16 @@ def fix(self) -> RepairToolMessage: if not self.faces: return RepairToolMessage(False, [], []) - parent_design = get_design_from_face(self.faces[0]) + # parent_design = get_design_from_face(self.faces[0]) response = self._repair_stub.FixSmallFaces( FixSmallFacesRequest(small_face_problem_area_id=self._grpc_id) ) - parent_design._update_design_inplace() + # parent_design._update_design_inplace() message = RepairToolMessage( response.result.success, response.result.created_bodies_monikers, response.result.modified_bodies_monikers, + tracked_changes=TrackerResponseMessage(response.result.complete_command_response), ) return message @@ -461,6 +467,7 @@ def fix(self) -> RepairToolMessage: response.result.success, response.result.created_bodies_monikers, response.result.modified_bodies_monikers, + tracked_changes=TrackerResponseMessage(response.result.complete_command_response), ) return message diff --git a/src/ansys/geometry/core/tools/repair_tool_message.py b/src/ansys/geometry/core/tools/repair_tool_message.py index 4329c7d7f7..4192a31933 100644 --- a/src/ansys/geometry/core/tools/repair_tool_message.py +++ b/src/ansys/geometry/core/tools/repair_tool_message.py @@ -21,6 +21,8 @@ # SOFTWARE. """Module for repair tool message.""" +from ansys.geometry.core.tools.tracker_response_message import TrackerResponseMessage + class RepairToolMessage: """Provides return message for the repair tool methods.""" @@ -32,6 +34,7 @@ def __init__( modified_bodies: list[str], found: int = -1, repaired: int = -1, + tracked_changes: TrackerResponseMessage = None, ): """Initialize a new instance of the extra edge problem area class. @@ -49,7 +52,8 @@ def __init__( repaired: int, default: -1 Number of problem areas repaired during the repair operation. If default, the operation does not provide the number of fixed problem areas. - + tracked_changes: TrackerResponseChanges, default: None + The tracked changes from the repair operation. """ self._success = success @@ -57,6 +61,7 @@ def __init__( self._modified_bodies = modified_bodies self._found = found self._repaired = repaired + self._tracked_changes = tracked_changes @property def success(self) -> bool: @@ -82,3 +87,8 @@ def found(self) -> int: def repaired(self) -> int: """Number of problem areas repaired during the repair operation.""" return self._repaired + + @property + def tracked_changes(self) -> TrackerResponseMessage: + """The tracked changes from the repair operation.""" + return self._tracked_changes diff --git a/src/ansys/geometry/core/tools/tracker_response_message.py b/src/ansys/geometry/core/tools/tracker_response_message.py new file mode 100644 index 0000000000..eb2c1fa006 --- /dev/null +++ b/src/ansys/geometry/core/tools/tracker_response_message.py @@ -0,0 +1,142 @@ +# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +"""Module for tracker response message.""" + +# from typing import TYPE_CHECKING + +# if TYPE_CHECKING: # pragma: no cover +# from ansys.geometry.core.designer.body import Body + +from ansys.api.geometry.v0.models_pb2 import TrackerCommandResponse + + +class TrackerResponseMessage: + """Provides response for tracked functionality.""" + + # def __init__( + # self, + # success: bool, + # created_bodies: list[str], + # modified_bodies: list[str], + # deleted_bodies: list[str], + # created_components: list[str], + # modified_components: list[str], + # deleted_components: list[str], + # ): + # """Initialize the TrackerResponseMessage instance. + + # Parameters + # ---------- + # success: bool + # True if the tracking was successful, false if it is not. + # created_bodies: list[str] + # List of bodies created during tracked operation. + # modified_bodies: list[str] + # List of bodies modified during tracked operation. + # deleted_bodies: list[str] + # List of bodies deleted during tracked operation. + # created_components: list[str] + # List of components created during tracked operation. + # modified_components: list[str] + # List of components modified during tracked operation. + # deleted_components: list[str] + # List of components deleted during tracked operation. + + # """ + # self._success = success + # self._created_bodies = created_bodies + # self._modified_bodies = modified_bodies + # self._deleted_bodies = deleted_bodies + # self._created_components = created_components + # self._modified_components = modified_components + # self._deleted_components = deleted_components + + def __init__( + self, + message: TrackerCommandResponse, + ): + """Initialize the TrackerResponseMessage instance from another message.""" + self._success = message.success + created_body_list = [] + for body in message.created_bodies: + created_body_list.append(body.id) + self._created_bodies = created_body_list + + modified_body_list = [] + for body in message.modified_bodies: + modified_body_list.append(body.id) + self._modified_bodies = modified_body_list + + deleted_body_list = [] + for body in message.deleted_bodies: + deleted_body_list.append(body.id) + self._deleted_bodies = deleted_body_list + + created_component_list = [] + for component in message.created_components: + created_component_list.append(component.id) + self._created_components = created_component_list + + modified_component_list = [] + for component in message.modified_components: + modified_component_list.append(component.id) + self._modified_components = modified_component_list + + deleted_component_list = [] + for component in message.deleted_components: + deleted_component_list.append(component.id) + self._deleted_components = deleted_component_list + + @property + def success(self) -> bool: + """Return success status.""" + return self._success + + @property + def created_bodies(self) -> list[str]: + """Return list of created bodies.""" + return self._created_bodies + + @property + def modified_bodies(self) -> list[str]: + """Return list of modified bodies.""" + return self._modified_bodies + + @property + def deleted_bodies(self) -> list[str]: + """Return list of deleted bodies.""" + return self._deleted_bodies + + @property + def created_components(self) -> list[str]: + """Return list of created components.""" + return self._created_components + + @property + def modified_components(self) -> list[str]: + """Return list of modified components.""" + return self._modified_components + + @property + def deleted_components(self) -> list[str]: + """Return list of deleted components.""" + return self._deleted_components diff --git a/tests/integration/test_repair_tools.py b/tests/integration/test_repair_tools.py index 4317691149..c7ac41ebdf 100644 --- a/tests/integration/test_repair_tools.py +++ b/tests/integration/test_repair_tools.py @@ -51,7 +51,9 @@ def test_fix_split_edge(modeler: Modeler): """Test to find and fix split edge problem areas.""" design = modeler.open_file(FILES_DIR / "SplitEdgeDesignTest.scdocx") problem_areas = modeler.repair_tools.find_split_edges(design.bodies, 25, 150) - assert problem_areas[0].fix().success is True + message = problem_areas[0].fix() + assert message.success is True + assert len(message.tracked_changes.modified_components) == 1 def test_find_extra_edges(modeler: Modeler): @@ -82,7 +84,9 @@ def test_fix_extra_edge(modeler: Modeler): """Test to find and fix extra edge problem areas.""" design = modeler.open_file(FILES_DIR / "ExtraEdgesDesignBefore.scdocx") problem_areas = modeler.repair_tools.find_extra_edges(design.bodies) - assert problem_areas[0].fix().success is True + message = problem_areas[0].fix() + assert message.success is True + assert len(message.tracked_changes.modified_components) == 1 def test_find_inexact_edges(modeler: Modeler): @@ -114,7 +118,9 @@ def test_fix_inexact_edge(modeler: Modeler): """ design = modeler.open_file(FILES_DIR / "InExactEdgesBefore.scdocx") problem_areas = modeler.repair_tools.find_inexact_edges(design.bodies) - assert problem_areas[0].fix().success is True + message = problem_areas[0].fix() + assert message.success is True + assert len(message.tracked_changes.modified_components) == 1 def test_find_missing_faces(modeler: Modeler): @@ -146,7 +152,10 @@ def test_fix_missing_face(modeler: Modeler): """ design = modeler.open_file(FILES_DIR / "MissingFacesDesignBefore.scdocx") problem_areas = modeler.repair_tools.find_missing_faces(design.bodies) - assert problem_areas[0].fix().success is True + message = problem_areas[0].fix() + assert message.success is True + assert len(message.tracked_changes.modified_bodies) == 1 + assert len(message.tracked_changes.modified_components) == 1 def test_find_duplicate_faces(modeler: Modeler): @@ -178,7 +187,10 @@ def test_fix_duplicate_face(modeler: Modeler): """ design = modeler.open_file(FILES_DIR / "DuplicateFacesDesignBefore.scdocx") problem_areas = modeler.repair_tools.find_duplicate_faces(design.bodies) - assert problem_areas[0].fix().success is True + message = problem_areas[0].fix() + assert message.success is True + assert len(message.tracked_changes.deleted_bodies) == 1 + assert len(message.tracked_changes.modified_components) == 1 def test_find_small_faces(modeler: Modeler): @@ -208,7 +220,10 @@ def test_find_small_face_faces(modeler: Modeler): ) # Skip test on CoreService design = modeler.open_file(FILES_DIR / "SmallFacesBefore.scdocx") problem_areas = modeler.repair_tools.find_small_faces(design.bodies) - assert len(problem_areas[0].faces) > 0 + assert len(problem_areas[0].faces) == 1 + assert len(problem_areas[1].faces) == 1 + assert len(problem_areas[2].faces) == 1 + assert len(problem_areas[3].faces) == 1 def test_fix_small_face(modeler: Modeler): @@ -217,7 +232,25 @@ def test_fix_small_face(modeler: Modeler): skip_if_core_service(modeler, test_fix_small_face.__name__, "repair_tools") design = modeler.open_file(FILES_DIR / "SmallFacesBefore.scdocx") problem_areas = modeler.repair_tools.find_small_faces(design.bodies) - assert problem_areas[0].fix().success is True + result = problem_areas[0].fix() + assert result.success is True + # There's a potential bug here. The test model can't remove it's small faces. Regardless, + # think we need to revisit some of the logic in this tool (and maybe the repair tools in + # general). + # assert len(result.tracked_changes.modified_bodies) == 1, "Modified bodies should be 1" + # assert len(result.tracked_changes.modified_components) == 1, "Modified components should be 1" + # result = problem_areas[1].fix() + # assert result.success is True + # assert len(result.tracked_changes.modified_bodies) == 1, "Modified bodies should be 1" + # assert len(result.tracked_changes.modified_components) == 1, "Modified components should be 1" + # result = problem_areas[2].fix() + # assert result.success is True + # assert len(result.tracked_changes.modified_bodies) == 1, "Modified bodies should be 1" + # assert len(result.tracked_changes.modified_components) == 1, "Modified components should be 1" + # result = problem_areas[3].fix() + # assert result.success is True + # assert len(result.tracked_changes.modified_bodies) == 1, "Modified bodies should be 1" + # assert len(result.tracked_changes.modified_components) == 1, "Modified components should be 1" def test_find_stitch_faces(modeler: Modeler):