Skip to content
This repository was archived by the owner on Nov 17, 2025. It is now read-only.
47 changes: 21 additions & 26 deletions src/ansys/tools/path/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@

def _get_installed_windows_versions(
supported_versions: SUPPORTED_VERSIONS_TYPE = SUPPORTED_ANSYS_VERSIONS,
):
): # pragma: no cover
"""Get the AWP_ROOT environment variable values for supported versions."""

# The student version overwrites the AWP_ROOT env var
Expand Down Expand Up @@ -108,7 +108,7 @@ def _get_default_linux_base_path():
return None # pragma: no cover


def _get_default_windows_base_path():
def _get_default_windows_base_path(): # pragma: no cover
"""Get the default base path of the Ansys unified install on windows."""

base_path = os.path.join(os.environ["PROGRAMFILES"], "ANSYS INC")
Expand Down Expand Up @@ -279,7 +279,7 @@ def find_mechanical(
ans_path, version = _get_unified_install_base_for_version(version, supported_versions)
if not ans_path or not version:
return "", ""
if is_windows():
if is_windows(): # pragma: no cover
mechanical_bin = os.path.join(ans_path, "aisol", "bin", "winx64", f"AnsysWBU.exe")
else:
mechanical_bin = os.path.join(ans_path, "aisol", ".workbench")
Expand Down Expand Up @@ -369,7 +369,7 @@ def is_valid_executable_path(product: PRODUCT_TYPE, exe_loc: str):
and re.search(r"ansys\d\d\d", os.path.basename(os.path.normpath(exe_loc))) is not None
)
elif product == "mechanical":
if is_windows():
if is_windows(): # pragma: no cover
return (
os.path.isfile(exe_loc)
and re.search("AnsysWBU.exe", os.path.basename(os.path.normpath(exe_loc)))
Expand All @@ -386,42 +386,38 @@ def _is_common_executable_path(product: PRODUCT_TYPE, exe_loc: str) -> bool:
if product == "mapdl":
path = os.path.normpath(exe_loc)
path = path.split(os.sep)
if (
re.search(r"v(\d\d\d)", exe_loc) is not None
and re.search(r"ansys(\d\d\d)", exe_loc) is not None
):
equal_version = (
re.search(r"v(\d\d\d)", exe_loc)[1] == re.search(r"ansys(\d\d\d)", exe_loc)[1]
)
else:
equal_version = False

# Look for all v(\d\d\d) to catch the last one
# in case the user has placed the installation folder inside a folder called for example (/ansys/v211)
v_version = re.findall(r"v(\d\d\d)", exe_loc)
ansys_version = re.findall(r"ansys(\d\d\d)", exe_loc, re.IGNORECASE)
return (
is_valid_executable_path("mapdl", exe_loc)
and re.search(r"v\d\d\d", exe_loc)
len(v_version) != 0
and len(ansys_version) != 0
and v_version[-1] == ansys_version[-1]
and is_valid_executable_path("mapdl", exe_loc)
and "ansys" in path
and "bin" in path
and equal_version
)

elif product == "mechanical":
path = os.path.normpath(exe_loc)
path = path.split(os.sep)

is_valid_path = is_valid_executable_path(exe_loc)
is_valid_path = is_valid_executable_path("mechanical", exe_loc)

if is_windows():
if is_windows(): # pragma: no cover
return (
is_valid_path
and re.search(r"v\d\d\d", exe_loc)
and re.search(r"v\d\d\d", exe_loc) is not None
and "aisol" in path
and "bin" in path
and ("bin" in path or "Bin" in path)
and "winx64" in path
and "AnsysWBU.exe" in path
and ("AnsysWBU.exe" in path or "ANSYSWBU.exe" in path)
)

return (
is_valid_path
and re.search(r"v\d\d\d", exe_loc)
and re.search(r"v\d\d\d", exe_loc) is not None
and "aisol" in path
and ".workbench" in path
)
Expand Down Expand Up @@ -515,9 +511,8 @@ def _save_path(
_change_default_path(product, exe_loc)
return exe_loc

if exe_loc is not None:
if is_valid_executable_path(product, exe_loc):
return exe_loc
if is_valid_executable_path(product, exe_loc):
return exe_loc
if allow_prompt:
exe_loc = _prompt_path(product)
return exe_loc
Expand Down
89 changes: 89 additions & 0 deletions tests/test_path.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import sys

import appdirs
import pytest
Expand All @@ -7,7 +8,9 @@
from ansys.tools.path.path import (
_check_uncommon_executable_path,
_clear_config_file,
_is_common_executable_path,
change_default_mapdl_path,
find_mechanical,
get_available_ansys_installations,
get_mapdl_path,
is_valid_executable_path,
Expand All @@ -18,10 +21,36 @@
paths = [
("/usr/dir_v2019.1/slv/ansys_inc/v211/ansys/bin/ansys211", 211),
("C:/Program Files/ANSYS Inc/v202/ansys/bin/win64/ANSYS202.exe", 202),
("C:\\Program Files\\ANSYS Inc\\v202\\ansys\\bin\\win64\\ANSYS202.exe", 202),
("/usr/ansys_inc/v211/ansys/bin/mapdl", 211),
pytest.param(("/usr/ansys_inc/ansys/bin/mapdl", 211), marks=pytest.mark.xfail),
]

mechanical_paths = [
("/usr/install/ansys_inc/v211/ansys/aisol/.workbench", 211),
("C:\\Program Files\\ANSYS Inc\\v202\\aisol\\Bin\\winx64\\ANSYSWBU.exe", 202),
("C:/Program Files/ANSYS Inc/v202/aisol/Bin/winx64/ANSYSWBU.exe", 202),
]

linux_mapdl_executable_paths = [
("/usr/dir_v2019.1/slv/ansys_inc/v211/ansys/bin/ansys211", True),
("/usr/ansys_inc/v211/ansys/bin/mapdl", False),
]

windows_mapdl_executable_paths = [
("C:/Program Files/ANSYS Inc/v202/ansys/bin/win64/ANSYS202.exe", True),
("C:\\Program Files\\ANSYS Inc\\v202\\ansys\\bin\\win64\\ANSYS202.exe", True),
]

windows_mechanical_executable_paths = [
("C:\\Program Files\\ANSYS Inc\\v221\\aisol\\Bin\\winx64\\ANSYSWBU.exe", True),
("C:/Program Files/ANSYS Inc/v221/aisol/Bin/winx64/ANSYSWBU.exe", True),
]

linux_mechanical_executable_paths = [
("/usr/install/ansys_inc/v211/ansys/aisol/.workbench", True),
]


skip_if_ansys_not_local = pytest.mark.skipif(
os.environ.get("ANSYS_LOCAL", "").upper() != "TRUE", reason="Skipping on CI"
Expand All @@ -34,6 +63,11 @@ def test_mapdl_version_from_path(path_data):
assert version_from_path("mapdl", exec_file) == version


@pytest.mark.parametrize("exec_file,version", mechanical_paths)
def test_mechanical_version_from_path(exec_file, version):
assert version_from_path("mechanical", exec_file) == version


@skip_if_ansys_not_local
def test_find_mapdl_linux():
# assuming Ansys MAPDL is installed, should be able to find it on linux
Expand Down Expand Up @@ -107,3 +141,58 @@ def test_warn_uncommon_executable_path():
def test_get_mapdl_path():
assert get_mapdl_path()
assert get_mapdl_path(version=222)


@pytest.fixture
def mock_is_valid_executable_path(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr("ansys.tools.path.path.is_valid_executable_path", lambda _1, _2: True)


@pytest.mark.skipif(sys.platform != "win32", reason="Test only available on windows")
@pytest.mark.parametrize("path,expected", windows_mapdl_executable_paths)
def test_windows_is_common_executable_path_mapdl(mock_is_valid_executable_path, path, expected):
assert _is_common_executable_path("mapdl", path) == expected


@pytest.mark.skipif(sys.platform != "linux", reason="Test only available on linux")
@pytest.mark.parametrize("path,expected", linux_mapdl_executable_paths)
def test_linux_is_common_executable_path_mapdl(mock_is_valid_executable_path, path, expected):
assert _is_common_executable_path("mapdl", path) == expected


@pytest.mark.skipif(sys.platform != "win32", reason="Test only available on windows")
@pytest.mark.parametrize("path,expected", windows_mechanical_executable_paths)
def test_windows_is_common_executable_path_mechanical(
mock_is_valid_executable_path, path, expected
):
assert _is_common_executable_path("mechanical", path) == expected


@pytest.mark.skipif(sys.platform != "linux", reason="Test only available on linux")
@pytest.mark.parametrize("path,expected", linux_mechanical_executable_paths)
def test_linux_is_common_executable_path_mechanical(mock_is_valid_executable_path, path, expected):
assert _is_common_executable_path("mechanical", path) == expected


@pytest.fixture
def mock_default_linux_base_path(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr("os.path.isdir", lambda x: (x == "/usr/ansys_inc"))
monkeypatch.setattr("ansys.tools.path.path.glob", lambda _: ["/usr/ansys_inc/v221"])


@pytest.fixture
def mock_empty_linux_base_path(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr("os.path.isdir", lambda x: (x == "/usr/ansys_inc"))
monkeypatch.setattr("ansys.tools.path.path.glob", lambda _: [])


def test_get_available_ansys_installation(mock_default_linux_base_path):
assert get_available_ansys_installations() == {221: "/usr/ansys_inc/v221"}


def test_empty_ansys_inttallation(mock_empty_linux_base_path):
assert get_available_ansys_installations() == {}


def test_find_mechanical(mock_default_linux_base_path):
assert find_mechanical() == ("/usr/ansys_inc/v221/aisol/.workbench", 22.1)