From 8c592a13c2a6032d9dddd879bc4f6edcd763cd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Morais?= <146729917+SMoraisAnsys@users.noreply.github.com> Date: Tue, 21 Jan 2025 15:40:59 +0100 Subject: [PATCH] REFACTOR: General improvements (#5674) --- src/ansys/aedt/core/generic/data_handlers.py | 4 +- .../aedt/core/modeler/cad/components_3d.py | 4 +- src/ansys/aedt/core/modeler/cad/modeler.py | 39 ++++------ src/ansys/aedt/core/modeler/cad/object_3d.py | 4 +- src/ansys/aedt/core/modeler/cad/polylines.py | 10 ++- tests/unit/test_object_3d.py | 50 ++++++++++++ tests/unit/test_polyline.py | 76 +++++++++++++++++++ 7 files changed, 154 insertions(+), 33 deletions(-) create mode 100644 tests/unit/test_object_3d.py create mode 100644 tests/unit/test_polyline.py diff --git a/src/ansys/aedt/core/generic/data_handlers.py b/src/ansys/aedt/core/generic/data_handlers.py index df6cc7cfc23..70b897b64e9 100644 --- a/src/ansys/aedt/core/generic/data_handlers.py +++ b/src/ansys/aedt/core/generic/data_handlers.py @@ -24,8 +24,8 @@ from decimal import Decimal import math -import random import re +import secrets import string import unicodedata @@ -272,7 +272,7 @@ def random_string(length=6, only_digits=False, char_set=None): char_set = string.digits else: char_set = string.ascii_uppercase + string.digits - random_str = "".join(random.choice(char_set) for _ in range(int(length))) + random_str = "".join(secrets.choice(char_set) for _ in range(int(length))) return random_str diff --git a/src/ansys/aedt/core/modeler/cad/components_3d.py b/src/ansys/aedt/core/modeler/cad/components_3d.py index 10cc88351fd..75096fcaacf 100644 --- a/src/ansys/aedt/core/modeler/cad/components_3d.py +++ b/src/ansys/aedt/core/modeler/cad/components_3d.py @@ -25,8 +25,8 @@ from __future__ import absolute_import import os -import random import re +import secrets import warnings from ansys.aedt.core.edb import Edb @@ -172,7 +172,7 @@ def __init__(self, primitives, name=None, props=None, component_type=None): "MaterialDefinitionParameters": {"VariableOrders": {}}, "MapInstanceParameters": "DesignVariable", "UniqueDefinitionIdentifier": "89d26167-fb77-480e-a7ab-" - + "".join(random.choice("abcdef0123456789") for _ in range(int(12))), + + "".join(secrets.choice("abcdef0123456789") for _ in range(int(12))), "OriginFilePath": "", "IsLocal": False, "ChecksumString": "", diff --git a/src/ansys/aedt/core/modeler/cad/modeler.py b/src/ansys/aedt/core/modeler/cad/modeler.py index 796d23029cf..3f5dd29059b 100644 --- a/src/ansys/aedt/core/modeler/cad/modeler.py +++ b/src/ansys/aedt/core/modeler/cad/modeler.py @@ -302,7 +302,7 @@ def _get_coordinates_data(self): self._props = CsProps(self, props) break except Exception: - pass + self._modeler._app.logger.debug(f"Failed to get coordinate data using {ds}") @pyaedt_function_handler() def _dim_arg(self, value, units=None): @@ -431,11 +431,8 @@ def __init__(self, modeler, props=None, name=None, face_id=None): self._props = None if props: self._props = CsProps(self, props) - try: # pragma: no cover - if "KernelVersion" in self.props: - del self.props["KernelVersion"] - except Exception: - pass + if "KernelVersion" in self.props: + del self.props["KernelVersion"] @property def props(self): @@ -703,11 +700,8 @@ def __init__(self, modeler, props=None, name=None): self._props = None if props: self._props = CsProps(self, props) - try: # pragma: no cover - if "KernelVersion" in self.props: - del self.props["KernelVersion"] - except Exception: - pass + if "KernelVersion" in self.props: + del self.props["KernelVersion"] self._ref_cs = None self._quaternion = None self._mode = None @@ -717,15 +711,13 @@ def mode(self): """Coordinate System mode.""" if self._mode: return self._mode - try: - if "Axis" in self.props["Mode"]: - self._mode = "axis" - elif "ZXZ" in self.props["Mode"]: - self._mode = "zxz" - elif "ZYZ" in self.props["Mode"]: - self._mode = "zyz" - except Exception: - pass + mode_parameter = self.props.get("Mode", "") + if "Axis" in mode_parameter: + self._mode = "axis" + if "ZXZ" in mode_parameter: + self._mode = "zxz" + elif "ZYZ" in mode_parameter: + self._mode = "zyz" return self._mode @mode.setter @@ -1235,11 +1227,8 @@ def __init__(self, modeler, props=None, name=None, entity_id=None): self._props = None if props: self._props = CsProps(self, props) - try: # pragma: no cover - if "KernelVersion" in self.props: - del self.props["KernelVersion"] - except Exception: - pass + if "KernelVersion" in self.props: + del self.props["KernelVersion"] self._ref_cs = None @property diff --git a/src/ansys/aedt/core/modeler/cad/object_3d.py b/src/ansys/aedt/core/modeler/cad/object_3d.py index 14e07b7d6db..ce6291f71ad 100644 --- a/src/ansys/aedt/core/modeler/cad/object_3d.py +++ b/src/ansys/aedt/core/modeler/cad/object_3d.py @@ -39,6 +39,7 @@ from ansys.aedt.core.generic.checks import min_aedt_version from ansys.aedt.core.generic.constants import AEDT_UNITS +from ansys.aedt.core.generic.errors import AEDTRuntimeError from ansys.aedt.core.generic.general_methods import _to_boolean from ansys.aedt.core.generic.general_methods import _uname from ansys.aedt.core.generic.general_methods import clamp @@ -1758,7 +1759,8 @@ def clone(self): """ new_obj_tuple = self._primitives.clone(self.id) success = new_obj_tuple[0] - assert success, f"Could not clone the object {self.name}." + if not success: + raise AEDTRuntimeError(f"Could not clone the object {self.name}") new_name = new_obj_tuple[1][0] return self._primitives[new_name] diff --git a/src/ansys/aedt/core/modeler/cad/polylines.py b/src/ansys/aedt/core/modeler/cad/polylines.py index 27cfdc55c3c..9c7d46bb9ac 100644 --- a/src/ansys/aedt/core/modeler/cad/polylines.py +++ b/src/ansys/aedt/core/modeler/cad/polylines.py @@ -30,6 +30,7 @@ from ansys.aedt.core.application.variables import decompose_variable_value from ansys.aedt.core.generic.constants import PLANE from ansys.aedt.core.generic.constants import unit_converter +from ansys.aedt.core.generic.errors import AEDTRuntimeError from ansys.aedt.core.generic.general_methods import _dim_arg from ansys.aedt.core.generic.general_methods import pyaedt_function_handler from ansys.aedt.core.modeler.cad.object_3d import Object3d @@ -504,8 +505,10 @@ def _convert_points(p_in, dest_unit): else: nn_segments = None nn_points = None - assert len(segments) == nn_segments, "Error getting the polyline segments from AEDT." - assert len(points) == nn_points, "Error getting the polyline points from AEDT." + if len(segments) != nn_segments: + raise AEDTRuntimeError("Failed to get the polyline segments from AEDT.") + if len(points) != nn_points: + raise AEDTRuntimeError("Failed to get the polyline points from AEDT.") # if succeeded save the result self._segment_types = segments self._positions = points @@ -740,7 +743,8 @@ def _segment_array(self, segment_data, start_index=0, start_point=None): if segment_data.type == "AngularArc": # from start-point and angle, calculate the mid- and end-points - assert start_point, "Start-point must be defined for an AngularArc Segment" + if not start_point: + raise ValueError("Start point must be defined for segment of type Angular Arc") self._evaluate_arc_angle_extra_points(segment_data, start_point) mod_units = self._primitives.model_units diff --git a/tests/unit/test_object_3d.py b/tests/unit/test_object_3d.py new file mode 100644 index 00000000000..db746127af3 --- /dev/null +++ b/tests/unit/test_object_3d.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2021 - 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. + +from unittest.mock import MagicMock +from unittest.mock import patch + +from ansys.aedt.core.generic.errors import AEDTRuntimeError +from ansys.aedt.core.modeler.cad.object_3d import Object3d +import pytest + + +@pytest.fixture +def object_3d_setup(): + """Fixture used to mock the creation of a Object3d instance.""" + with patch("ansys.aedt.core.modeler.cad.object_3d.Object3d.__init__", lambda x: None): + mock_instance = MagicMock(spec=Object3d) + yield mock_instance + + +def test_clone_failure(object_3d_setup): + mock_primitives = MagicMock() + mock_primitives.clone.return_value = [False] + object_3d = Object3d() + object_3d._primitives = mock_primitives + object_3d._m_name = "dummy" + object_3d._id = 12 + + with pytest.raises(AEDTRuntimeError, match="Could not clone the object dummy"): + object_3d.clone() diff --git a/tests/unit/test_polyline.py b/tests/unit/test_polyline.py new file mode 100644 index 00000000000..fad288c9e52 --- /dev/null +++ b/tests/unit/test_polyline.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2021 - 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. + +from unittest.mock import MagicMock +from unittest.mock import patch + +from ansys.aedt.core.generic.errors import AEDTRuntimeError +from ansys.aedt.core.modeler.cad.polylines import Polyline +import pytest + + +@pytest.fixture +def polyline_setup(): + """Fixture used to mock the creation of a Polyline instance.""" + with patch("ansys.aedt.core.modeler.cad.polylines.Polyline.__init__", lambda x: None): + mock_instance = MagicMock(spec=Polyline) + yield mock_instance + + +def test_segment_array_failure_for_segment_type_angular_arc(polyline_setup): + mock_segmenta_data = MagicMock() + mock_segmenta_data.num_points = 12 + mock_segmenta_data.type = "AngularArc" + polyline = Polyline() + + with pytest.raises(ValueError, match="Start point must be defined for segment of type Angular Arc"): + polyline._segment_array(mock_segmenta_data) + + +@patch("ansys.aedt.core.modeler.cad.polylines.Polyline.history") +def test_segment_update_segments_and_points_array_failure_on_segment(mock_history, polyline_setup): + properties = {"Number of curves": 42, "Number of points": 0} + custom_history = MagicMock() + custom_history.segments = None + custom_history.properties = properties + mock_history.return_value = custom_history + polyline = Polyline() + polyline.history = mock_history + + with pytest.raises(AEDTRuntimeError, match="Failed to get the polyline segments from AEDT."): + polyline._update_segments_and_points() + + +@patch("ansys.aedt.core.modeler.cad.polylines.Polyline.history") +def test_segment_update_segments_and_points_array_failure_on_points(mock_history, polyline_setup): + properties = {"Number of curves": 0, "Number of points": 42} + custom_history = MagicMock() + custom_history.segments = None + custom_history.properties = properties + mock_history.return_value = custom_history + polyline = Polyline() + polyline.history = mock_history + + with pytest.raises(AEDTRuntimeError, match="Failed to get the polyline points from AEDT."): + polyline._update_segments_and_points()