Skip to content

Commit 308825d

Browse files
Samuelopez-ansysmarwane rachadSMoraisAnsyspyansys-ci-botAlberto-DM
authored
FEAT: Add AEDT File Management tests (#5879)
Co-authored-by: marwane rachad <[email protected]> Co-authored-by: Sébastien Morais <[email protected]> Co-authored-by: pyansys-ci-bot <[email protected]> Co-authored-by: Alberto Di Maria <[email protected]>
1 parent 8eee019 commit 308825d

File tree

4 files changed

+211
-112
lines changed

4 files changed

+211
-112
lines changed

doc/changelog.d/5879.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add AEDT File Management tests

src/ansys/aedt/core/application/aedt_file_management.py

Lines changed: 115 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,25 @@
2222
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323
# SOFTWARE.
2424

25-
import csv
26-
import os
25+
import logging
26+
from pathlib import Path
2727
import re
2828
import shutil
29+
from typing import Union
30+
import warnings
2931

30-
from ansys.aedt.core.generic.file_utils import open_file
32+
from ansys.aedt.core.generic.errors import AEDTRuntimeError
33+
from ansys.aedt.core.generic.file_utils import read_csv
3134
from ansys.aedt.core.generic.general_methods import pyaedt_function_handler
3235

3336

3437
@pyaedt_function_handler()
35-
def read_info_fromcsv(projdir, name):
38+
def read_info_fromcsv(projdir, name): # pragma: no cover
3639
"""Read information from a CSV file and return a list.
3740
41+
.. deprecated:: 0.15.1
42+
This method is deprecated. Use the ``ansys.aedt.core.generic.file_utils.read_csv`` method instead.
43+
3844
Parameters
3945
----------
4046
projdir : str
@@ -47,125 +53,131 @@ def read_info_fromcsv(projdir, name):
4753
list
4854
4955
"""
50-
51-
filename = projdir + "//" + name
52-
listmcad = []
53-
with open_file(filename, "rb") as csvfile:
54-
reader = csv.reader(csvfile, delimiter=",")
55-
for row in reader:
56-
listmcad.append(row)
57-
return listmcad
56+
warnings.warn(
57+
"`read_info_fromcsv` is deprecated. Use `ansys.aedt.core.generic.file_utils.read_csv` instead.",
58+
DeprecationWarning,
59+
)
60+
# Construct the filename using pathlib.
61+
filename = str(Path(projdir) / name)
62+
return read_csv(filename)
5863

5964

60-
@pyaedt_function_handler()
61-
def clean_proj_folder(dir, name):
65+
@pyaedt_function_handler(dir="input_dir")
66+
def clean_proj_folder(input_dir): # pragma: no cover
6267
"""Delete all project name-related folders.
6368
69+
.. deprecated:: 0.15.1
70+
This method is deprecated. Use the ``ansys.aedt.core.application.clean_proj_folder`` method instead.
71+
6472
Parameters
6573
----------
66-
dir : str
74+
input_dir : str or :class:`pathlib.Path`
6775
Full path to the project directory.
68-
name : str
69-
Name of the project.
7076
7177
Returns
7278
-------
7379
bool
7480
``True`` when successful, ``False`` when failed.
7581
"""
76-
if os.path.exists(dir):
77-
shutil.rmtree(dir, True)
78-
os.mkdir(dir)
82+
warnings.warn(
83+
"`clean_proj_folder` is deprecated. Use `ansys.aedt.core.application.clean_proj_folder` instead.",
84+
DeprecationWarning,
85+
)
86+
input_dir_path = Path(input_dir)
87+
if input_dir_path.exists():
88+
shutil.rmtree(input_dir_path, True)
89+
input_dir_path.mkdir()
7990
return True
8091

8192

82-
@pyaedt_function_handler()
83-
def create_output_folder(ProjectDir):
93+
@pyaedt_function_handler(ProjectDir="input_dir")
94+
def create_output_folder(input_dir: Union[str, Path]) -> tuple:
8495
"""Create the output folders starting from the project directory.
8596
8697
Parameters
8798
----------
88-
ProjectDir : str
99+
input_dir : str or :class:`pathlib.Path`
89100
Name of the project directory.
90101
91102
Returns
92103
-------
93-
type
94-
PicturePath, ResultsPath
104+
tuple
105+
Picture path, Results path
95106
96107
"""
97-
npath = os.path.normpath(ProjectDir)
98-
99-
# set pathname for the Output
100-
OutputPath = os.path.join(npath, os.path.basename(npath))
101-
# set pathname for the images
102-
PicturePath = os.path.join(npath, os.path.basename(npath), "Pictures")
103-
# set pathname for the files
104-
ResultsPath = os.path.join(npath, os.path.basename(npath), "Results")
105-
106-
# Add folders for outputs
107-
if not os.path.exists(OutputPath):
108-
os.mkdir(OutputPath)
109-
if not os.path.exists(PicturePath):
110-
os.mkdir(PicturePath)
111-
if not os.path.exists(ResultsPath):
112-
os.mkdir(ResultsPath)
113-
return PicturePath, ResultsPath
114-
115-
116-
@pyaedt_function_handler()
117-
def change_objects_visibility(origfile, solid_list):
108+
warnings.warn(
109+
"`create_output_folder` is deprecated.",
110+
DeprecationWarning,
111+
)
112+
npath = Path(input_dir)
113+
base = npath.name
114+
115+
# Set pathnames for the output folders.
116+
output_path = npath / base
117+
picture_path = output_path / "Pictures"
118+
results_path = output_path / "Results"
119+
120+
# Create directories using a loop.
121+
for directory in [output_path, picture_path, results_path]:
122+
directory.mkdir(parents=True, exist_ok=True)
123+
return str(picture_path), str(results_path)
124+
125+
126+
@pyaedt_function_handler(origfile="input_file", solid_list="assignment")
127+
def change_objects_visibility(input_file: Union[str, Path], assignment: list) -> bool:
118128
"""Edit the project file to make only the solids that are specified visible.
119129
120130
Parameters
121131
----------
122-
origfile : str
123-
Full path to the project file, which has an ``.aedt`` extension.
124-
solid_list : list
125-
List of names for the solid to make visible. All other solides are hidden.
132+
input_file : str or :class:`pathlib.Path`
133+
Full path to the project file, which has an ``.aedt`` extension.
134+
assignment : list
135+
List of names for the solid to make visible. All other solids are hidden.
126136
127137
Returns
128138
-------
129139
bool
130140
``True`` when successful, ``False`` when failed.
131141
"""
132-
path, filename = os.path.split(origfile)
133-
newfile = os.path.join(path, "aedttmp.tmp")
134-
135-
if not os.path.isfile(origfile + ".lock"): # check if the project is closed
136-
with open(origfile, "rb") as f, open(newfile, "wb") as n:
137-
# Reading file content
138-
content = f.read()
139-
140-
# Searching file content for pattern
141-
pattern = re.compile(
142-
r"(\$begin 'EditorWindow'\n.+)(Drawings\[.+\])(.+\n\s*\$end 'EditorWindow')", re.UNICODE
143-
)
144-
# Replacing string
145-
# fmt: off
146-
view_str = u"Drawings[" + str(len(solid_list)) + u": " + str(solid_list).strip("[")
147-
s = pattern.sub(r"\1" + view_str + r"\3", content)
148-
# fmt: on
149-
# writing file content
150-
n.write(str(s))
151-
152-
# renaming files and deleting temp
153-
154-
os.remove(origfile)
155-
os.rename(newfile, origfile)
156-
157-
else: # project is locked
158-
print("change_objects_visibility: Project %s is still locked." % origfile)
159-
160-
161-
@pyaedt_function_handler()
162-
def change_model_orientation(origfile, bottom_dir):
142+
path = Path(input_file).parent
143+
newfile = path / "aedttmp.tmp"
144+
145+
if not (Path(input_file).with_suffix(".lock")).is_file(): # check if the project is closed
146+
try:
147+
# Using text mode with explicit encoding instead of binary mode.
148+
with open(str(input_file), "rb") as f, open(str(newfile), "wb") as n:
149+
# Reading file content
150+
content = f.read()
151+
# Searching file content for pattern
152+
search_str = r"(\$begin 'EditorWindow'\n.+)(Drawings\[.+\])(.+\n\s*\$end 'EditorWindow')"
153+
# Replacing string
154+
view_str = "Drawings[" + str(len(assignment)) + ": " + str(assignment).strip("[")
155+
sub_str = r"\1" + view_str + r"\3"
156+
s = re.sub(search_str.encode("utf-8"), sub_str.encode("utf-8"), content)
157+
# Writing file content
158+
n.write(s)
159+
# Renaming files and deleting temporary file
160+
Path(input_file).unlink()
161+
newfile.rename(input_file)
162+
return True
163+
except Exception: # pragma: no cover
164+
# Cleanup temporary file if exists.
165+
newfile.unlink(missing_ok=True)
166+
raise AEDTRuntimeError("Failed to restrict visibility to specified solids.")
167+
168+
else: # pragma: no cover
169+
logging.error("change_objects_visibility: Project %s is still locked.", str(input_file))
170+
return False
171+
172+
173+
@pyaedt_function_handler(origfile="input_file")
174+
def change_model_orientation(input_file: Union[str, Path], bottom_dir: str) -> bool:
163175
"""Edit the project file to change the model orientation.
164176
165177
Parameters
166178
----------
167-
origfile : str
168-
Full path to the project file, which has an ``.aedt`` extension.
179+
input_file : str or :class:`pathlib.Path`
180+
Full path to the project file, which has an ``.aedt`` extension.
169181
bottom_dir : str
170182
Bottom direction as specified in the properties file.
171183
@@ -174,10 +186,11 @@ def change_model_orientation(origfile, bottom_dir):
174186
bool
175187
``True`` when successful, ``False`` when failed.
176188
"""
177-
path, filename = os.path.split(origfile)
178-
newfile = os.path.join(path, "aedttmp.tmp")
189+
input_path = Path(input_file)
190+
newfile = input_path.parent / "aedttmp.tmp"
191+
lock_file = input_path.with_suffix(".aedt.lock")
179192

180-
# directory of u, v vectors for view orientation
193+
# Directory of u, v vectors for view orientation
181194
orientation = {
182195
"+X": "OrientationMatrix(0, -0.816496610641479, -0.577350318431854, 0, 0.70710676908493, -0.40824830532074, "
183196
"0.577350318431854, 0, -0.70710676908493, -0.40824830532074, 0.577350318431854, 0, 0, 0, 0, 1, 0, -100, "
@@ -199,26 +212,23 @@ def change_model_orientation(origfile, bottom_dir):
199212
"-100, 100, -100, 100, -100, 100) ",
200213
}
201214

202-
if not os.path.isfile(origfile + ".lock"): # check if the project is closed
203-
# Opening files
204-
with open(origfile, "rb") as f, open(newfile, "wb") as n:
205-
# Reading file content
206-
content = f.read()
215+
if lock_file.exists(): # pragma: no cover
216+
logging.error(f"change_model_orientation: Project {input_file} is still locked.")
217+
return False
207218

208-
# Searching file content for pattern
209-
pattern = re.compile(
210-
r"(\$begin 'EditorWindow'\n.+?)(OrientationMatrix\(.+?\))(.+\n\s*\$end 'EditorWindow')", re.UNICODE
211-
)
219+
try:
220+
with input_path.open("rb") as f, newfile.open("wb") as n:
221+
content = f.read()
222+
search_str = r"(\\$begin 'EditorWindow'\\n.+?)(OrientationMatrix\\(.+?\\))(.+\\n\\s*\\$end 'EditorWindow')"
212223
# Replacing string
213224
orientation_str = orientation[bottom_dir]
214-
s = pattern.sub(r"\1" + orientation_str + r"\3", content)
215-
225+
sub_str = r"\1" + orientation_str + r"\3"
226+
s = re.sub(search_str.encode("utf-8"), sub_str.encode("utf-8"), content)
216227
# Writing file content
217-
n.write(str(s))
218-
219-
# Renaming files and deleting temp
220-
os.remove(origfile)
221-
os.rename(newfile, origfile)
222-
223-
else: # Project is locked
224-
print("change_model_orientation: Project %s is still locked." % origfile)
228+
n.write(s)
229+
input_path.unlink()
230+
newfile.rename(input_path)
231+
return True
232+
except Exception as e: # pragma: no cover
233+
newfile.unlink(missing_ok=True)
234+
raise AEDTRuntimeError(f"change_model_orientation: Error encountered - {e}")

src/ansys/aedt/core/application/design.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import gc
3535
import json
3636
import os
37+
from pathlib import Path
3738
import random
3839
import re
3940
import shutil
@@ -3189,7 +3190,7 @@ def clean_proj_folder(self, directory=None, name=None):
31893190
31903191
Parameters
31913192
----------
3192-
directory : str, optionl
3193+
directory : str or :class:`pathlib.Path`, optional
31933194
Name of the directory. The default is ``None``, in which case the active project is
31943195
deleted from the ``aedtresults`` directory.
31953196
name : str, optional
@@ -3202,15 +3203,17 @@ def clean_proj_folder(self, directory=None, name=None):
32023203
``True`` when successful, ``False`` when failed.
32033204
32043205
"""
3205-
if not name:
3206+
if name is None:
32063207
name = self.project_name
3207-
if not directory:
3208+
if directory is None:
32083209
directory = self.results_directory
32093210
self.logger.info("Cleanup folder %s from project %s", directory, name)
3210-
if os.path.exists(directory):
3211-
shutil.rmtree(directory, True)
3212-
if not os.path.exists(directory):
3213-
os.makedirs(directory)
3211+
3212+
input_dir_path = Path(directory)
3213+
if input_dir_path.exists():
3214+
shutil.rmtree(input_dir_path, True)
3215+
if not input_dir_path.exists():
3216+
input_dir_path.mkdir()
32143217
self.logger.info("Project Directory cleaned")
32153218
return True
32163219

0 commit comments

Comments
 (0)