Skip to content

Commit

Permalink
Merge branch 'main' into release/0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuelopez-ansys committed May 16, 2024
2 parents 3a9b625 + dba020c commit 078e247
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 19 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ jobs:
pytest -v -m rest_api --cov --cov-append
- name: Test utils
timeout-minutes: 5
run: |
.\.venv\Scripts\Activate.ps1
pytest -v -m utils --cov --cov-append
- name: "Combine coverage files"
run: |
.\.venv\Scripts\Activate.ps1
Expand Down Expand Up @@ -278,6 +285,13 @@ jobs:
source .venv_linux/bin/activate
pytest -v -m rest_api
- name: Test utils
timeout-minutes: 5
run: |
export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH
source .venv_linux/bin/activate
pytest -v -m utils
build-library:
name: "Build library artifacts"
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions doc/source/getting_started/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ To install both the backend and UI methods, run this command:

.. code:: bash
pip install pyaedt-toolkits-common[all]
pip install ansys-aedt-toolkits-common[all]
If you only need the common API, install only the backend methods with this
command:

.. code:: bash
pip install pyaedt-toolkits-common
pip install ansys-aedt-toolkits-common
2 changes: 0 additions & 2 deletions examples/ui/default_ui_example/default_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

# Common windows
from ansys.aedt.toolkits.common.ui.main_window.main_window_layout import MainWindowLayout
from ansys.aedt.toolkits.common.ui.common_windows.home_menu import HomeMenu
from ansys.aedt.toolkits.common.ui.common_windows.settings_column import SettingsMenu


class ApplicationWindow(QMainWindow):
Expand Down
4 changes: 3 additions & 1 deletion src/ansys/aedt/toolkits/common/backend/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,9 @@ def open_project(self, project_name=None):
self.release_aedt()
if not self.connect_aedt(): # pragma: no cover
return False
if not project_name and self.properties.active_project and os.path.exists(self.properties.active_project):
if (
not project_name and self.properties.active_project and os.path.exists(self.properties.active_project)
): # pragma: no cover
project_name = os.path.abspath(self.properties.active_project)
if not os.path.exists(project_name + ".lock") and self.desktop and project_name:
self.desktop.odesktop.OpenProject(project_name)
Expand Down
3 changes: 2 additions & 1 deletion src/ansys/aedt/toolkits/common/ui/actions_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,8 @@ def update_design_names(self, active_project=None):
if not design_list:
design_list = ["No Design"]
be_properties["active_design"] = "No Design"
be_properties["design_list"] = {active_project: design_list}
else:
be_properties["active_design"] = design_list[0]
self.set_properties(be_properties)
return design_list

Expand Down
8 changes: 6 additions & 2 deletions src/ansys/aedt/toolkits/common/ui/common_windows/home_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ def setup(self):
success = self.app.check_connection()
if success:
backend_properties = self.app.get_properties()
if backend_properties.get("active_project") and backend_properties.get("active_design"):
if (
backend_properties.get("active_project")
and backend_properties.get("active_design")
or backend_properties.get("selected_process") != 0
):
self.update_project()
self.update_design()

Expand All @@ -119,7 +123,7 @@ def update_project(self):

def update_design(self):
self.project_combobox.blockSignals(True)
design_list = self.app.update_design_names()
design_list = self.app.update_design_names(self.main_window.home_menu.project_combobox.currentText())
self.main_window.home_menu.design_combobox.clear()
self.main_window.home_menu.design_combobox.addItems(design_list)
self.project_combobox.blockSignals(False)
22 changes: 11 additions & 11 deletions src/ansys/aedt/toolkits/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import requests


def download_file(url, local_filename):
def download_file(url, local_filename): # pragma: no cover
"""Download a file from a URL into a local file."""
with requests.get(url, stream=True) as r:
r.raise_for_status()
Expand All @@ -45,7 +45,7 @@ def download_file(url, local_filename):
return local_filename


def is_server_running(server="localhost", port=5001):
def is_server_running(server="localhost", port=5001): # pragma: no cover
"""Check if port is used."""
result = None
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Expand All @@ -70,16 +70,16 @@ def find_free_port(server="localhost", start_port=5001, max_attempts=50):
s.bind((server, port))
print("Port {} is free.".format(str(port)))
return port
except OSError:
except OSError: # pragma: no cover
print("Port {} is used.".format(str(port)))
except Exception as e:
except Exception as e: # pragma: no cover
print("An error occurred:", e)
return False
port = random.randint(start_port, start_port + 100)
return False
port = random.randint(start_port, start_port + 100) # pragma: no cover
return False # pragma: no cover


def wait_for_server(server="localhost", port=5001, timeout=10.0):
def wait_for_server(server="localhost", port=5001, timeout=10.0): # pragma: no cover
"""Wait for server response."""
start_time = time.time()
first_time = True
Expand All @@ -91,7 +91,7 @@ def wait_for_server(server="localhost", port=5001, timeout=10.0):
sock.close()
print("\nServer is ready.")
return True
except socket.error as e:
except socket.error as e: # pragma: no cover
print(f"Socket error occurred: {e}")
if first_time:
print("Server not ready yet. Retrying...", end="")
Expand Down Expand Up @@ -126,7 +126,7 @@ def server_actions(command, name, is_linux):
return thread


def clean_python_processes(url, port):
def clean_python_processes(url, port): # pragma: no cover
"""Clean up Python processes."""
for conn in psutil.net_connections():
(ip_tmp, port_tmp) = conn.laddr
Expand All @@ -140,7 +140,7 @@ def clean_python_processes(url, port):
print(f"Process {process.pid} on {ip}:{port_tmp} was already killed")


def check_backend_communication(url_call):
def check_backend_communication(url_call): # pragma: no cover
"""Check backend communication."""
try:
response = requests.get(url_call + "/health")
Expand All @@ -150,7 +150,7 @@ def check_backend_communication(url_call):
return False


def process_desktop_properties(is_linux, url_call):
def process_desktop_properties(is_linux, url_call): # pragma: no cover
"""Process desktop properties."""
desktop_pid = None
desktop_version = None
Expand Down
24 changes: 24 additions & 0 deletions tests/backend/tests_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (C) 2023 - 2024 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.

"""Test utils
"""
80 changes: 80 additions & 0 deletions tests/backend/tests_utils/test_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Copyright (C) 2023 - 2024 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.

import pytest

pytestmark = [pytest.mark.utils]

import threading
from unittest.mock import patch, MagicMock

from ansys.aedt.toolkits.common.utils import run_command, server_actions, wait_for_server, find_free_port


@pytest.fixture
def mock_subprocess():
"""Mock subprocess.Popen to avoid actual process execution."""
with patch('subprocess.Popen') as mock_popen:
mock_popen.return_value.communicate.return_value = (b'Test output', b'')
yield mock_popen


@pytest.fixture
def mock_socket():
"""Mock socket.socket to avoid actual network connection."""
with patch('socket.socket') as mock_socket:
mock_socket.return_value.connect_ex.return_value = 0
yield mock_socket


def test_run_command(mock_subprocess):
"""Test run_command function."""
run_command('ls', is_linux=True)
mock_subprocess.assert_called_once()


def test_server_actions(mock_subprocess):
"""Test server_actions function."""
command = ('ls',)
name = 'TestThread'
is_linux = True

thread = server_actions(command, name, is_linux)
assert isinstance(thread, threading.Thread)
assert thread.name == name
assert thread.is_alive()

thread.join()

mock_subprocess.assert_called_once()


def test_wait_for_server(mock_socket):
"""Test wait_for_server function."""
assert wait_for_server('localhost', 5001, timeout=1.0)


def test_find_free_port():
"""Test find_free_port function."""
assert isinstance(find_free_port(server='localhost', start_port=5001), int)

assert isinstance(find_free_port(), int)

0 comments on commit 078e247

Please sign in to comment.