Skip to content

REFACTOR: Pathlib in multiple files #6367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
90fb9da
refactor: filesystem.py
jvela018 Jul 8, 2025
84aa3d4
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Jul 8, 2025
032ab9b
chore: adding changelog file 6367.miscellaneous.md [dependabot-skip]
pyansys-ci-bot Jul 8, 2025
d1e1da6
refactor: is_safe_path pathlib refactor in filesystem.py
jvela018 Jul 9, 2025
2adbf4d
Merge remote-tracking branch 'origin/refactor/pathlib-multiple-files'…
jvela018 Jul 9, 2025
efedc0c
Merge branch 'main' into refactor/pathlib-multiple-files
jvela018 Jul 9, 2025
2a00151
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Jul 9, 2025
e77f70e
refactor: pathlib - load_aedt_file.py
jvela018 Jul 9, 2025
e3680dd
Merge remote-tracking branch 'origin/refactor/pathlib-multiple-files'…
jvela018 Jul 9, 2025
b47376a
refactor: pathlib - grpc_plugin_dll_class.py
jvela018 Jul 9, 2025
d8ad440
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Jul 9, 2025
a08d226
refactor: pathlib - fix paths in grpc_plugin_dll_class.py
jvela018 Jul 9, 2025
4ab9422
Merge branch 'main' into refactor/pathlib-multiple-files
jvela018 Jul 9, 2025
bf50577
refactor: design.py, farfield_visualization.py, post_common_3d.py, pr…
jvela018 Jul 10, 2025
aadd0b4
refactor: analysis_3d.py, conftest.py
jvela018 Jul 10, 2025
b90a5b4
Merge branch 'main' into refactor/pathlib-multiple-files
jvela018 Jul 10, 2025
c15dd0d
chore: adding changelog file 6367.miscellaneous.md [dependabot-skip]
pyansys-ci-bot Jul 10, 2025
5a5bfea
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Jul 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.d/6367.miscellaneous.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Pathlib in multiple files
8 changes: 5 additions & 3 deletions src/ansys/aedt/core/application/analysis_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
----------
application : str
3D application that is to initialize the call.
projectname : str, optional
projectname : str or :class:`pathlib.Path`, optional
Name of the project to select or the full path to the project
or AEDTZ archive to open. The default is ``None``, in which
case an attempt is made to get an active project. If no
Expand Down Expand Up @@ -113,7 +113,7 @@
Analysis.__init__(
self,
application,
projectname,
str(projectname),
designname,
solution_type,
setup_name,
Expand Down Expand Up @@ -341,7 +341,9 @@
dict
Dictionary of variables in the component file.
"""
if str(name) not in self.components3d:
if isinstance(name, Path):
name = str(name)
if name not in self.components3d:

Check warning on line 346 in src/ansys/aedt/core/application/analysis_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/application/analysis_3d.py#L344-L346

Added lines #L344 - L346 were not covered by tests
return read_component_file(name)
else:
return read_component_file(self.components3d[name])
Expand Down
142 changes: 72 additions & 70 deletions src/ansys/aedt/core/application/design.py

Large diffs are not rendered by default.

32 changes: 16 additions & 16 deletions src/ansys/aedt/core/internal/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# SOFTWARE.

import os
from pathlib import Path
import secrets
import shutil
import string
Expand All @@ -42,14 +43,13 @@
-------
list
"""
import pathlib

return [os.path.abspath(i) for i in pathlib.Path(dirname).glob(pattern)]
return [Path(i).absolute() for i in Path(dirname).glob(pattern)]

Check warning on line 47 in src/ansys/aedt/core/internal/filesystem.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/internal/filesystem.py#L47

Added line #L47 was not covered by tests


def my_location():
""" """
return os.path.normpath(os.path.dirname(__file__))
return Path(__file__).parent.resolve(strict=False)

Check warning on line 52 in src/ansys/aedt/core/internal/filesystem.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/internal/filesystem.py#L52

Added line #L52 was not covered by tests


class Scratch:
Expand All @@ -70,23 +70,22 @@
self._cleaned = True
char_set = string.ascii_uppercase + string.digits
name = "".join(secrets.choice(char_set) for _ in range(6))
self._scratch_path = os.path.normpath(os.path.join(local_path, "scratch" + name))
if os.path.exists(self._scratch_path):
self._scratch_path = (Path(local_path) / ("scratch" + name)).resolve(strict=False)
if self._scratch_path.exists():
try:
self.remove()
except Exception:
self._cleaned = False
if self._cleaned:
try:
os.mkdir(self.path)
self.path.mkdir()
os.chmod(self.path, permission)
except FileNotFoundError as fnf_error: # Raise error if folder doesn't exist.
print(fnf_error)

def remove(self):
""" """
try:
# TODO check why on Anaconda 3.7 get errors with os.path.exists
shutil.rmtree(self._scratch_path, ignore_errors=True)
except Exception:
logger.error(f"An error occurred while removing {self._scratch_path}")
Expand All @@ -111,12 +110,12 @@
Full path and file name of the copied file.
"""
if dst_filename:
dst_file = os.path.join(self.path, dst_filename)
dst_file = self.path / dst_filename

Check warning on line 113 in src/ansys/aedt/core/internal/filesystem.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/internal/filesystem.py#L113

Added line #L113 was not covered by tests
else:
dst_file = os.path.join(self.path, os.path.basename(src_file))
if os.path.exists(dst_file):
dst_file = self.path / Path(src_file).name
if dst_file.exists():

Check warning on line 116 in src/ansys/aedt/core/internal/filesystem.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/internal/filesystem.py#L115-L116

Added lines #L115 - L116 were not covered by tests
try:
os.unlink(dst_file)
dst_file.unlink()

Check warning on line 118 in src/ansys/aedt/core/internal/filesystem.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/internal/filesystem.py#L118

Added line #L118 was not covered by tests
except OSError: # pragma: no cover
pass
try:
Expand Down Expand Up @@ -169,16 +168,17 @@
def is_safe_path(path, allowed_extensions=None):
"""Validate if a path is safe to use."""
# Ensure path is an existing file or directory
if not os.path.exists(path) or not os.path.isfile(path):
path = Path(path)
if not path.exists() or not path.is_file():
return False

# Restrict to allowed file extensions:
# # Restrict to allowed file extensions:
if allowed_extensions:
if not any(path.endswith(extension) for extension in allowed_extensions):
if path.suffix not in allowed_extensions:
return False

# Ensure path does not contain dangerous characters
if any(char in path for char in (";", "|", "&", "$", "<", ">", "`")):
# # Ensure path does not contain dangerous characters
if any(char in str(path) for char in (";", "|", "&", "$", "<", ">", "`")):
return False

return True
28 changes: 12 additions & 16 deletions src/ansys/aedt/core/internal/grpc_plugin_dll_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from ctypes import c_wchar_p
from ctypes import py_object
import os
from pathlib import Path
import re
import types

Expand Down Expand Up @@ -259,37 +260,32 @@ class AEDT:
def __init__(self, pathDir):
is_linux = os.name == "posix"
is_windows = not is_linux
pathDir = Path(pathDir)
self.original_path = pathDir
self.pathDir = pathDir
self.pathDir = os.path.dirname(self.pathDir) # PythonFiles
self.pathDir = os.path.dirname(self.pathDir) # DesktopPlugin or Win64
# dirName = os.path.basename(pathDir)
self.pathDir = pathDir.parents[1]

# Plugin filename depends on OS
if is_linux:
pluginFileName = r"libPyDesktopPlugin.so"
else:
pluginFileName = r"PyDesktopPlugin.dll"

AedtAPIDll_file = os.path.join(self.pathDir, pluginFileName) # install dir
AedtAPIDll_file = self.pathDir / pluginFileName # install dir

if not os.path.isfile(AedtAPIDll_file):
self.pathDir = os.path.dirname(self.pathDir) # lib
self.pathDir = os.path.dirname(self.pathDir) # core
self.pathDir = os.path.dirname(self.pathDir) # view
AedtAPIDll_file = os.path.join(self.pathDir, r"build_output\64Release\PyDesktopPlugin.dll") # develop dir
# AedtAPIDll_file = os.path.join(pathDir, r"PyAedtStub/x64/Debug/PyAedtStub.dll") #develop dir
if not AedtAPIDll_file.is_file():
self.pathDir = self.pathDir.parents[2]
AedtAPIDll_file = self.pathDir / r"build_output\64Release\PyDesktopPlugin.dll" # develop dir

# load dll
if is_windows:
# on windows, modify path
aedtDir = os.path.dirname(AedtAPIDll_file)
aedtDir = AedtAPIDll_file.parent
originalPath = os.environ["PATH"]
os.environ["PATH"] = originalPath + os.pathsep + aedtDir
AedtAPI = PyDLL(AedtAPIDll_file)
os.environ["PATH"] = originalPath + os.pathsep + str(aedtDir)
AedtAPI = PyDLL(str(AedtAPIDll_file))
os.environ["PATH"] = originalPath
else:
AedtAPI = PyDLL(AedtAPIDll_file)
AedtAPI = PyDLL(str(AedtAPIDll_file))
# AedtAPI.SetPyObjCalbacks.argtypes = py_object, py_object, py_object
AedtAPI.SetPyObjCalbacks.restype = None

Expand All @@ -298,7 +294,7 @@ def __init__(self, pathDir):
self.callbackCreateBlock = None
self.callbackGetObjID = None
version = None
with open(os.path.join(self.pathDir, "product.info"), "r") as f:
with open(self.pathDir / "product.info", "r") as f:
for line in f:
if "AnsProductVersion" in line:
version = line.split("=")[1].strip('\n"')
Expand Down
4 changes: 2 additions & 2 deletions src/ansys/aedt/core/internal/load_aedt_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import os.path
from pathlib import Path
import re

from ansys.aedt.core.generic.file_utils import open_file
Expand All @@ -48,7 +48,7 @@
"""
settings.logger.reset_timer()
settings.logger.info(f"Parsing {filename}.")
f_d = _load_entire_aedt_file(os.path.normpath(filename))
f_d = _load_entire_aedt_file(Path(filename).resolve(strict=False))

Check warning on line 51 in src/ansys/aedt/core/internal/load_aedt_file.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/internal/load_aedt_file.py#L51

Added line #L51 was not covered by tests
settings.logger.info_timer(f"File {filename} correctly loaded.")
return f_d

Expand Down
43 changes: 22 additions & 21 deletions src/ansys/aedt/core/modeler/cad/primitives_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from math import sqrt
from math import tan
import os
from pathlib import Path

from ansys.aedt.core import Edb
from ansys.aedt.core.generic.file_utils import generate_unique_name
Expand Down Expand Up @@ -1410,22 +1411,21 @@
app = assignment.edit_definition(password=password)
wcs = app.modeler.get_working_coordinate_system()
if wcs != "Global":
temp_folder = os.path.join(
self._app.toolkit_directory, self._app.design_name, generate_unique_name("temp_folder")
)
os.makedirs(os.path.join(temp_folder))
if not os.path.exists(os.path.join(self._app.toolkit_directory, self._app.design_name)): # pragma: no cover
os.makedirs(os.path.join(self._app.toolkit_directory, self._app.design_name))
new_proj_name = os.path.join(temp_folder, generate_unique_name("project") + ".aedt")
temp_folder = (Path(self._app.toolkit_directory)

Check warning on line 1414 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1414

Added line #L1414 was not covered by tests
/ self._app.design_name / generate_unique_name("temp_folder"))
temp_folder.mkdir()

Check warning on line 1416 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1416

Added line #L1416 was not covered by tests
if not (Path(self._app.toolkit_directory) / self._app.design_name).exists(): # pragma: no cover
(Path(self._app.toolkit_directory) / self._app.design_name).mkdir()
new_proj_name = Path(temp_folder) / (generate_unique_name("project") + ".aedt")

Check warning on line 1419 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1419

Added line #L1419 was not covered by tests
app.save_project(new_proj_name)
o, q = app.modeler.invert_cs(wcs, to_global=True)
app.oproject.Close()
for root, dirs, files in os.walk(temp_folder, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
(Path(root) / name).unlink()

Check warning on line 1425 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1425

Added line #L1425 was not covered by tests
for name in dirs:
os.rmdir(os.path.join(root, name))
os.rmdir(temp_folder)
(Path(root) / name).rmdir()
temp_folder.rmdir()

Check warning on line 1428 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1427-L1428

Added lines #L1427 - L1428 were not covered by tests
phi, theta, psi = q.to_euler('zxz')
cs_name = assignment.name + "_" + wcs + "_ref"
if cs_name not in [i.name for i in self.coordinate_systems]:
Expand All @@ -1448,7 +1448,7 @@
"""Create temporary project with a duplicated design."""
from ansys.aedt.core import Icepak
temp_proj_name = generate_unique_project_name()
ipkapp_temp = Icepak(project=os.path.join(app.toolkit_directory, temp_proj_name))
ipkapp_temp = Icepak(project=Path(app.toolkit_directory) / temp_proj_name)

Check warning on line 1451 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1451

Added line #L1451 was not covered by tests
ipkapp_temp.delete_design(ipkapp_temp.design_name)
app.oproject.CopyDesign(app.design_name)
ipkapp_temp.oproject.Paste()
Expand Down Expand Up @@ -1568,6 +1568,8 @@
----------
>>> oEditor.Insert3DComponent
"""
if isinstance(input_file, Path):
input_file = str(input_file)

Check warning on line 1572 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1571-L1572

Added lines #L1571 - L1572 were not covered by tests
if password is None:
password = os.getenv("PYAEDT_ENCRYPTED_PASSWORD", "")
if not input_file.endswith(".a3dcomp"):
Expand Down Expand Up @@ -1668,7 +1670,7 @@
self._app.configurations.options.unset_all_import()
self._app.configurations.options.import_native_components = True
self._app.configurations.options.import_monitor = True
temp_dict_file = os.path.join(self._app.toolkit_directory, generate_unique_name("tempdict_"))
temp_dict_file = Path(self._app.toolkit_directory) / generate_unique_name("tempdict_")

Check warning on line 1673 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1673

Added line #L1673 was not covered by tests
with open_file(temp_dict_file, "w") as f:
json.dump(temp_dict, f)
exclude_set = set([obj.name for _, obj in self._app.modeler.objects.items()])
Expand Down Expand Up @@ -1780,7 +1782,7 @@
self.logger.warning("Solution type must be terminal in HFSS or APhi in Maxwell")
return False

component_name = os.path.splitext(os.path.basename(input_file))[0]
component_name = Path(input_file).stem

Check warning on line 1785 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1785

Added line #L1785 was not covered by tests
aedt_component_name = component_name
if component_name not in self._app.ocomponent_manager.GetNames():
compInfo = ["NAME:" + str(component_name), "Info:=", []]
Expand Down Expand Up @@ -1813,11 +1815,10 @@

# Open Layout component and get information
aedb_component_path = input_file
if os.path.splitext(os.path.basename(input_file))[1] == ".aedbcomp":
aedb_project_path = os.path.join(self._app.project_path, self._app.project_name + ".aedb")
aedb_component_path = os.path.join(
aedb_project_path, "LayoutComponents", aedt_component_name, aedt_component_name + ".aedb"
)
if Path(input_file).suffix == ".aedbcomp":
aedb_project_path = Path(self._app.project_path) / (self._app.project_name + ".aedb")
aedb_component_path = (Path(aedb_project_path) /

Check warning on line 1820 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1818-L1820

Added lines #L1818 - L1820 were not covered by tests
"LayoutComponents" / aedt_component_name / (aedt_component_name + ".aedb"))
aedb_component_path = normalize_path(aedb_component_path)

is_edb_open = False
Expand Down Expand Up @@ -1987,7 +1988,7 @@

@pyaedt_function_handler()
def _check_actor_folder(self, actor_folder):
if not os.path.exists(actor_folder):
if not Path(actor_folder).exists():

Check warning on line 1991 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L1991

Added line #L1991 was not covered by tests
self.logger.error(f"Folder {actor_folder} does not exist.")
return False
if not any(fname.endswith(".json") for fname in os.listdir(actor_folder)) or not any(
Expand Down Expand Up @@ -3337,8 +3338,8 @@
values["Inner Winding"]["Occupation(%)"] = occ

if create_another_file:
root_path, extension_path = os.path.splitext(input_dir)
new_path = root_path + "_Corrected" + extension_path
new_path = Path(input_dir).stem + "_Corrected" + Path(input_dir).suffix

Check warning on line 3341 in src/ansys/aedt/core/modeler/cad/primitives_3d.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/aedt/core/modeler/cad/primitives_3d.py#L3341

Added line #L3341 was not covered by tests

with open_file(new_path, "w") as outfile:
json.dump(values, outfile)
else:
Expand Down
Loading
Loading