diff --git a/doc/changelog.d/6367.miscellaneous.md b/doc/changelog.d/6367.miscellaneous.md new file mode 100644 index 00000000000..9dc25369ff6 --- /dev/null +++ b/doc/changelog.d/6367.miscellaneous.md @@ -0,0 +1 @@ +Pathlib in multiple files \ No newline at end of file diff --git a/src/ansys/aedt/core/application/analysis_3d.py b/src/ansys/aedt/core/application/analysis_3d.py index a88851c5083..0e291e38352 100644 --- a/src/ansys/aedt/core/application/analysis_3d.py +++ b/src/ansys/aedt/core/application/analysis_3d.py @@ -53,7 +53,7 @@ class FieldAnalysis3D(Analysis, object): ---------- 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 @@ -113,7 +113,7 @@ def __init__( Analysis.__init__( self, application, - projectname, + str(projectname), designname, solution_type, setup_name, @@ -341,7 +341,9 @@ def get_component_variables(self, name: Union[str, Path]) -> dict: 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: return read_component_file(name) else: return read_component_file(self.components3d[name]) diff --git a/src/ansys/aedt/core/application/design.py b/src/ansys/aedt/core/application/design.py index c611232d5d4..88edf491876 100644 --- a/src/ansys/aedt/core/application/design.py +++ b/src/ansys/aedt/core/application/design.py @@ -102,8 +102,8 @@ def load_aedt_thread(project_path) -> None: Path to the AEDT project file. """ pp = load_entire_aedt_file(project_path) - inner_project_settings.properties[os.path.normpath(project_path)] = pp - inner_project_settings.time_stamp = os.path.getmtime(project_path) + inner_project_settings.properties[Path(project_path)] = pp + inner_project_settings.time_stamp = Path(project_path).stat().st_mtime class Design(AedtObjects): @@ -176,11 +176,13 @@ def __init__( self._project_name: Optional[str] = None self._project_path: Optional[str] = None self.__t: Optional[threading.Thread] = None + if isinstance(project_name, Path): + project_name = str(project_name) if ( is_windows and project_name - and os.path.exists(project_name) - and (os.path.splitext(project_name)[1] == ".aedt" or os.path.splitext(project_name)[1] == ".a3dcomp") + and Path(project_name).exists() + and (Path(project_name).suffix == ".aedt" or Path(project_name).suffix == ".a3dcomp") ): self.__t = threading.Thread(target=load_aedt_thread, args=(project_name,), daemon=True) self.__t.start() @@ -240,7 +242,7 @@ def __init__( self._logger.odesign = self.odesign AedtObjects.__init__(self, self._desktop_class, self.oproject, self.odesign, is_inherithed=True) self.logger.info("Aedt Objects correctly read") - if is_windows and not self.__t and not settings.lazy_load and os.path.exists(self.project_file): + if is_windows and not self.__t and not settings.lazy_load and Path(self.project_file).exists(): self.__t = threading.Thread(target=load_aedt_thread, args=(self.project_file,), daemon=True) self.__t.start() @@ -624,29 +626,27 @@ def project_properties(self) -> Dict[str, dict]: self.__t = None start = time.time() if self.project_timestamp_changed or ( - os.path.exists(self.project_file) - and os.path.normpath(self.project_file) not in inner_project_settings.properties + Path(self.project_file).exists() + and Path(self.project_file).resolve() not in inner_project_settings.properties ): - inner_project_settings.properties[os.path.normpath(self.project_file)] = load_entire_aedt_file( + inner_project_settings.properties[str(Path(self.project_file).resolve())] = load_entire_aedt_file( self.project_file ) self._logger.info(f"aedt file load time {time.time() - start}") elif ( - os.path.normpath(self.project_file) not in inner_project_settings.properties + Path(self.project_file).resolve() not in inner_project_settings.properties and settings.remote_rpc_session and settings.remote_rpc_session.filemanager.pathexists(self.project_file) ): file_path = check_and_download_file(self.project_file) try: - inner_project_settings.properties[os.path.normpath(self.project_file)] = load_entire_aedt_file( - file_path - ) + inner_project_settings.properties[str(Path(self.project_file))] = load_entire_aedt_file(file_path) except Exception: self._logger.info("Failed to load AEDT file.") else: self._logger.info(f"Time to load AEDT file: {time.time() - start}.") - if os.path.normpath(self.project_file) in inner_project_settings.properties: - return inner_project_settings.properties[os.path.normpath(self.project_file)] + if str(Path(self.project_file).resolve()) in inner_project_settings.properties: + return inner_project_settings.properties[str(Path(self.project_file))] return {} @property @@ -845,8 +845,8 @@ def project_path(self) -> Optional[str]: @property def project_time_stamp(self) -> Union[int, float]: """Return Project time stamp.""" - if os.path.exists(self.project_file): - inner_project_settings.time_stamp = os.path.getmtime(self.project_file) + if Path(self.project_file).exists(): + inner_project_settings.time_stamp = Path(self.project_file).stat().st_mtime else: inner_project_settings.time_stamp = 0 return inner_project_settings.time_stamp @@ -868,7 +868,7 @@ def project_file(self) -> Optional[str]: """ if self.project_path: - return os.path.join(self.project_path, self.project_name + ".aedt") + return str(Path(self.project_path) / (self.project_name + ".aedt")) @property def lock_file(self) -> Optional[str]: @@ -881,7 +881,7 @@ def lock_file(self) -> Optional[str]: """ if self.project_path: - return os.path.join(self.project_path, self.project_name + ".aedt.lock") + return str(Path(self.project_path) / (self.project_name + ".aedt.lock")) @property def results_directory(self) -> Optional[str]: @@ -894,7 +894,7 @@ def results_directory(self) -> Optional[str]: """ if self.project_path: - return os.path.join(self.project_path, self.project_name + ".aedtresults") + return str(Path(self.project_path) / (self.project_name + ".aedtresults")) @property def solution_type(self) -> Optional[str]: @@ -996,7 +996,7 @@ def src_dir(self) -> str: Full absolute path for the ``python`` directory. """ - return os.path.dirname(os.path.realpath(__file__)) + return str(Path(__file__).parent.resolve()) @property def pyaedt_dir(self) -> str: @@ -1008,7 +1008,7 @@ def pyaedt_dir(self) -> str: Full absolute path for the ``pyaedt`` directory. """ - return os.path.realpath(os.path.join(self.src_dir, "..")) + return str(Path(self.src_dir).parent.resolve()) @property def library_list(self) -> List[str]: @@ -1048,7 +1048,7 @@ def toolkit_directory(self) -> str: name = self.project_name.replace(" ", "_") else: name = generate_unique_name("prj") - toolkit_directory = os.path.join(self.project_path, name + ".pyaedt") + toolkit_directory = Path(self.project_path) / (name + ".pyaedt") if settings.remote_rpc_session: toolkit_directory = self.project_path + "/" + name + ".pyaedt" try: @@ -1057,7 +1057,7 @@ def toolkit_directory(self) -> str: toolkit_directory = settings.remote_rpc_session.filemanager.temp_dir() + "/" + name + ".pyaedt" elif settings.remote_api or settings.remote_rpc_session: toolkit_directory = self.results_directory - elif not os.path.isdir(toolkit_directory): + elif not Path(toolkit_directory).is_dir(): try: os.makedirs(toolkit_directory) except FileNotFoundError: @@ -1080,16 +1080,16 @@ def working_directory(self) -> str: name = self.design_name.replace(" ", "_") else: name = generate_unique_name("prj") - working_directory = os.path.join(os.path.normpath(self.toolkit_directory), name) + working_directory = (Path(self.toolkit_directory) / name).resolve() if settings.remote_rpc_session: working_directory = self.toolkit_directory + "/" + name settings.remote_rpc_session.filemanager.makedirs(working_directory) - elif not os.path.isdir(working_directory): + elif not Path(working_directory).is_dir(): try: - os.makedirs(working_directory) + Path(working_directory).mkdir() except FileNotFoundError: - working_directory = os.path.join(self.toolkit_directory, name + ".results") - return working_directory + working_directory = Path(self.toolkit_directory) / (name + ".results") + return str(working_directory) @property def default_solution_type(self) -> str: @@ -1251,13 +1251,13 @@ def oproject(self, proj_name=None): self._oproject = self.desktop_class.active_project(proj_name) self._add_handler() self.logger.info("Project %s set to active.", proj_name) - elif os.path.exists(proj_name) or ( + elif Path(proj_name).exists() or ( settings.remote_rpc_session and settings.remote_rpc_session.filemanager.pathexists(proj_name) ): if ".aedtz" in proj_name: name = self._generate_unique_project_name() - path = os.path.dirname(proj_name) - self.odesktop.RestoreProjectArchive(proj_name, os.path.join(path, name), True, True) + path = Path(proj_name).parent + self.odesktop.RestoreProjectArchive(proj_name, str(Path(path) / name), True, True) time.sleep(0.5) proj_name = name[:-5] self._oproject = self.desktop_class.active_project(proj_name) @@ -1265,15 +1265,15 @@ def oproject(self, proj_name=None): self.logger.info(f"Archive {proj_name} has been restored to project {self._oproject.GetName()}") elif ".def" in proj_name or proj_name[-5:] == ".aedb": if ".def" in proj_name: - project = os.path.dirname(proj_name)[:-5] + ".aedt" + project = str(Path(proj_name).parent)[:-5] + ".aedt" else: project = proj_name[:-5] + ".aedt" - if os.path.exists(project) and self.check_if_project_is_loaded(project): + if Path(project).exists() and self.check_if_project_is_loaded(project): pname = self.check_if_project_is_loaded(project) self._oproject = self.desktop_class.active_project(pname) self._add_handler() self.logger.info("Project %s set to active.", pname) - elif os.path.exists(project): + elif Path(project).exists(): if is_project_locked(project): if self._remove_lock: # pragma: no cover self.logger.warning("Project is locked. Removing it and opening.") @@ -1290,7 +1290,7 @@ def oproject(self, proj_name=None): if ".def" in proj_name: oTool.ImportEDB(proj_name) else: - oTool.ImportEDB(os.path.join(proj_name, "edb.def")) + oTool.ImportEDB(str(Path(proj_name) / "edb.def")) self._oproject = self.desktop_class.active_project() self._oproject.Save() self._add_handler() @@ -1328,7 +1328,7 @@ def oproject(self, proj_name=None): if proj_name.endswith(".aedt"): self._oproject.Rename(proj_name, True) elif not proj_name.endswith(".aedtz"): - self._oproject.Rename(os.path.join(self.project_path, proj_name + ".aedt"), True) + self._oproject.Rename(str(Path(self.project_path) / (proj_name + ".aedt")), True) self._add_handler() self.logger.info("Project %s has been created.", self._oproject.GetName()) if not self._oproject: @@ -1355,7 +1355,7 @@ def _add_handler(self): if f"pyaedt_{self._oproject.GetName()}.log" in str(handler): return self._logger = self._global_logger.add_file_logger( - os.path.join(self.toolkit_directory, f"pyaedt_{self._oproject.GetName()}.log"), + Path(self.toolkit_directory) / f"pyaedt_{self._oproject.GetName()}.log", project_name=self.project_name, ) @@ -1565,7 +1565,7 @@ def export_profile(self, setup, variation="", output_file=None): >>> oDesign.ExportProfile """ if not output_file: - output_file = os.path.join(self.working_directory, generate_unique_name("Profile") + ".prof") + output_file = Path(self.working_directory) / (generate_unique_name("Profile") + ".prof") if not variation: val_str = [] nominal_variation = self.available_variations.get_independent_nominal_values() @@ -1579,32 +1579,34 @@ def export_profile(self, setup, variation="", output_file=None): for s in self.setups: if s.name == setup: if "CGDataBlock" in s.props: - output_file = os.path.splitext(output_file)[0] + "CG" + os.path.splitext(output_file)[1] - self.odesign.ExportProfile(setup, variation, "CG", output_file, True) + output_file = Path(output_file).stem + "CG" + Path(output_file).suffix + self.odesign.ExportProfile(setup, variation, "CG", str(output_file), True) self.logger.info(f"Exported Profile to file {output_file}") if "RLDataBlock" in s.props: - output_file = os.path.splitext(output_file)[0] + "RL" + os.path.splitext(output_file)[1] - self.odesign.ExportProfile(setup, variation, "RL", output_file, True) + output_file = Path(output_file).stem + "RL" + Path(output_file).suffix + self.odesign.ExportProfile(setup, variation, "RL", str(output_file), True) self.logger.info(f"Exported Profile to file {output_file}") break elif self.design_type == "Q3D Extractor": for s in self.setups: if s.name == setup: if "Cap" in s.props: - output_file = os.path.splitext(output_file)[0] + "CG" + os.path.splitext(output_file)[1] - self.odesign.ExportProfile(setup, variation, "CG", output_file, True) + output_file = Path(output_file).stem + "CG" + Path(output_file).suffix + self.odesign.ExportProfile(setup, variation, "CG", str(output_file), True) self.logger.info(f"Exported Profile to file {output_file}") if "AC" in s.props: - output_file = os.path.splitext(output_file)[0] + "ACRL" + os.path.splitext(output_file)[1] - self.odesign.ExportProfile(setup, variation, "AC RL", output_file, True) + output_file = Path(output_file).stem + "ACRL" + Path(output_file).suffix + self.odesign.ExportProfile(setup, variation, "AC RL", str(output_file), True) self.logger.info(f"Exported Profile to file {output_file}") if "DC" in s.props: - output_file = os.path.splitext(output_file)[0] + "DC" + os.path.splitext(output_file)[1] - self.odesign.ExportProfile(setup, variation, "DC RL", output_file, True) + output_file = Path(output_file).stem + "DC" + Path(output_file).suffix + self.odesign.ExportProfile(setup, variation, "DC RL", str(output_file), True) self.logger.info(f"Exported Profile to file {output_file}") break else: try: + if isinstance(output_file, Path): + output_file = str(output_file) self.odesign.ExportProfile(setup, variation, output_file) except Exception: self.odesign.ExportProfile(setup, variation, output_file, True) @@ -2650,10 +2652,10 @@ def generate_temp_project_directory(self, name): self.logger.error("Input argument 'subdir' must be a string") return False dir_name = generate_unique_name(name) - project_dir = os.path.join(base_path, dir_name) + project_dir = Path(base_path) / dir_name try: - if not os.path.exists(project_dir): - os.makedirs(project_dir) + if not Path(project_dir).exists(): + Path(project_dir).mkdir() return project_dir except OSError: return False @@ -2879,7 +2881,7 @@ def import_dataset1d(self, input_file, name=None, is_project_dataset=True, sort= ylist.append(float(item.split()[1])) if not name: - name = os.path.basename(os.path.splitext(input_file)[0]) + name = Path(input_file).stem if name[0] == "$": name = name[1:] @@ -2962,7 +2964,7 @@ def import_dataset3d(self, input_file, name=None, encoding="utf-8-sig", is_proje cont += 1 if not name: - name = os.path.basename(os.path.splitext(input_file)[0]) + name = Path(input_file).stem if name[0] == "$": name = name[1:] @@ -3070,11 +3072,9 @@ def dataset_exists(self, name, is_project_dataset=True): if is_project_dataset and "$" + name in self.project_datasets: self.logger.info("Dataset %s$ exists.", name) return True - # self.oproject.ExportDataSet("$"+name, os.path.join(self.temp_directory, "ds.tab")) elif not is_project_dataset and name in self.design_datasets: self.logger.info("Dataset %s exists.", name) return True - # self.odesign.ExportDataSet(name, os.path.join(self.temp_directory, "ds.tab")) self.logger.info("Dataset %s doesn't exist.", name) return False @@ -3253,7 +3253,7 @@ def copy_project(self, destination, name): """ self.logger.info("Copy AEDT Project ") self.oproject.Save() - self.oproject.SaveAs(os.path.join(destination, name + ".aedt"), True) + self.oproject.SaveAs(str(Path(destination) / (name + ".aedt")), True) return True @pyaedt_function_handler(proj_name="name") @@ -3314,7 +3314,7 @@ def close_project(self, name=None, save=True): self.logger.info(f"Closing the AEDT Project {name}") oproj = self.desktop_class.active_project(name) proj_path = oproj.GetPath() - proj_file = os.path.join(proj_path, name + ".aedt") + proj_file = Path(proj_path) / (name + ".aedt") if save: oproj.Save() if name == legacy_name: @@ -3335,7 +3335,7 @@ def close_project(self, name=None, save=True): i = 0 timeout = 10 while True: - if not os.path.exists(os.path.join(proj_path, name + ".aedt.lock")): + if not (Path(proj_path) / (name + ".aedt.lock")).exists(): self.logger.info(f"Project {name} closed correctly") break elif i > timeout: @@ -3345,8 +3345,8 @@ def close_project(self, name=None, save=True): i += 0.2 time.sleep(0.2) - if os.path.normpath(proj_file) in inner_project_settings.properties: - del inner_project_settings.properties[os.path.normpath(proj_file)] + if str(Path(proj_file)) in inner_project_settings.properties: + del inner_project_settings.properties[str(Path(proj_file))] return True @pyaedt_function_handler() @@ -3624,7 +3624,7 @@ def copy_design_from(self, project, design, save_project=True, set_active_design """ self.save_project() # open the origin project - if os.path.exists(project): + if Path(project).exists(): proj_from = self.odesktop.OpenProject(project) proj_from_name = proj_from.GetName() else: @@ -3781,7 +3781,7 @@ def read_design_data(self): Dictionary of the design data. """ - design_file = os.path.join(self.working_directory, "design_data.json") + design_file = Path(self.working_directory) / "design_data.json" with open_file(design_file, "r") as fps: design_data = json.load(fps) return design_data @@ -3811,11 +3811,13 @@ def save_project(self, file_name=None, overwrite=True, refresh_ids=False): >>> oProject.SaveAs """ if file_name: - file_parent_dir = os.path.dirname(os.path.normpath(file_name)) - if settings.remote_rpc_session and not settings.remote_rpc_session.filemanager.pathexists(file_parent_dir): - settings.remote_rpc_session.filemanager.makedirs(file_parent_dir) - elif not settings.remote_rpc_session and not os.path.isdir(file_parent_dir): - os.makedirs(file_parent_dir) + file_parent_dir = Path(file_name).parent.resolve() + if settings.remote_rpc_session and not settings.remote_rpc_session.filemanager.pathexists( + str(file_parent_dir) + ): + settings.remote_rpc_session.filemanager.makedirs(str(file_parent_dir)) + elif not settings.remote_rpc_session and not file_parent_dir.is_dir(): + file_parent_dir.mkdir() self.oproject.SaveAs(file_name, overwrite) self._add_handler() else: @@ -3869,10 +3871,10 @@ def archive_project( msg_text = f"Saving {self.project_name} Project" self.logger.info(msg_text) if not project_path: - project_path = os.path.join(self.project_path, self.project_name + ".aedtz") + project_path = Path(self.project_path) / (self.project_name + ".aedtz") self.oproject.Save() self.oproject.SaveProjectArchive( - project_path, include_external_files, include_results_file, additional_files, notes + str(project_path), include_external_files, include_results_file, additional_files, notes ) return True @@ -4185,7 +4187,7 @@ def check_if_project_is_loaded(self, input_file): Project name if loaded in Desktop. """ for p in self.odesktop.GetProjects(): - if os.path.normpath(os.path.join(p.GetPath(), p.GetName()) + ".aedt") == os.path.normpath(input_file): + if (Path(p.GetPath()) / (p.GetName() + ".aedt")).resolve() == Path(input_file).resolve(): return p.GetName() return False diff --git a/src/ansys/aedt/core/generic/file_utils.py b/src/ansys/aedt/core/generic/file_utils.py index afce9d3c03c..0bffaf49e26 100644 --- a/src/ansys/aedt/core/generic/file_utils.py +++ b/src/ansys/aedt/core/generic/file_utils.py @@ -371,23 +371,20 @@ def open_file( Opened file object or ``None`` if the file or folder does not exist. """ - file_path = str(file_path) - file_path = file_path.replace("\\", "/") if file_path[0] != "\\" else file_path - file_path = Path(file_path) - dir_name = file_path.parent + if "r" in file_options: if file_path.exists(): - return open(file_path, file_options, encoding=encoding) + return open(str(file_path), file_options, encoding=encoding) elif settings.remote_rpc_session and settings.remote_rpc_session.filemanager.pathexists( str(file_path) ): # pragma: no cover local_file = Path(tempfile.gettempdir()) / file_path.name settings.remote_rpc_session.filemanager.download_file(str(file_path), str(local_file)) - return open(local_file, file_options, encoding=encoding) + return open(str(local_file), file_options, encoding=encoding) elif dir_name.exists(): - return open(file_path, file_options, encoding=encoding) + return open(str(file_path), file_options, encoding=encoding) elif settings.remote_rpc_session and settings.remote_rpc_session.filemanager.pathexists(str(dir_name)): if "w" in file_options: return settings.remote_rpc_session.create_file( diff --git a/src/ansys/aedt/core/internal/filesystem.py b/src/ansys/aedt/core/internal/filesystem.py index f1d319c7785..d231c55e6be 100644 --- a/src/ansys/aedt/core/internal/filesystem.py +++ b/src/ansys/aedt/core/internal/filesystem.py @@ -23,6 +23,7 @@ # SOFTWARE. import os +from pathlib import Path import secrets import shutil import string @@ -42,14 +43,13 @@ def search_files(dirname, pattern="*"): ------- 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)] def my_location(): """ """ - return os.path.normpath(os.path.dirname(__file__)) + return Path(__file__).parent.resolve(strict=False) class Scratch: @@ -70,15 +70,15 @@ def __init__(self, local_path, permission=0o777, volatile=False): 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) @@ -86,7 +86,6 @@ def __init__(self, local_path, permission=0o777, volatile=False): 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}") @@ -98,9 +97,9 @@ def copyfile(self, src_file, dst_filename=None): Parameters ---------- - src_file : str + src_file : str or :class:`pathlib.Path` Source file with fullpath. - dst_filename : str, optional + dst_filename : str or :class:`pathlib.Path`, optional Destination filename with the extension. The default is ``None``, in which case the destination file is given the same name as the source file. @@ -111,12 +110,12 @@ def copyfile(self, src_file, dst_filename=None): 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 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(): try: - os.unlink(dst_file) + dst_file.unlink() except OSError: # pragma: no cover pass try: @@ -124,7 +123,7 @@ def copyfile(self, src_file, dst_filename=None): except FileNotFoundError as fnf_error: print(fnf_error) - return dst_file + return str(dst_file) def copyfolder(self, src_folder, destfolder): """ @@ -169,16 +168,17 @@ def get_json_files(start_folder): 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 diff --git a/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py b/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py index d47994ad934..10d8882ada0 100644 --- a/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py +++ b/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py @@ -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 @@ -266,11 +267,9 @@ 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: @@ -278,25 +277,22 @@ def __init__(self, pathDir): 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 @@ -305,7 +301,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"') diff --git a/src/ansys/aedt/core/internal/load_aedt_file.py b/src/ansys/aedt/core/internal/load_aedt_file.py index 9d8dc2f8620..25a15252bce 100644 --- a/src/ansys/aedt/core/internal/load_aedt_file.py +++ b/src/ansys/aedt/core/internal/load_aedt_file.py @@ -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 @@ -48,7 +48,7 @@ def load_entire_aedt_file(filename): """ 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)) settings.logger.info_timer(f"File {filename} correctly loaded.") return f_d diff --git a/src/ansys/aedt/core/modeler/cad/primitives_3d.py b/src/ansys/aedt/core/modeler/cad/primitives_3d.py index 15cef9d6a71..2cd77e23988 100644 --- a/src/ansys/aedt/core/modeler/cad/primitives_3d.py +++ b/src/ansys/aedt/core/modeler/cad/primitives_3d.py @@ -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 @@ -1410,22 +1411,21 @@ def _create_reference_cs_from_3dcomp(self, assignment, password): 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) + / self._app.design_name / generate_unique_name("temp_folder")) + temp_folder.mkdir() + 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") 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() for name in dirs: - os.rmdir(os.path.join(root, name)) - os.rmdir(temp_folder) + (Path(root) / name).rmdir() + temp_folder.rmdir() 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]: @@ -1448,7 +1448,7 @@ def __create_temp_project(app): """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) ipkapp_temp.delete_design(ipkapp_temp.design_name) app.oproject.CopyDesign(app.design_name) ipkapp_temp.oproject.Paste() @@ -1568,6 +1568,8 @@ def insert_3d_component( ---------- >>> oEditor.Insert3DComponent """ + if isinstance(input_file, Path): + input_file = str(input_file) if password is None: password = os.getenv("PYAEDT_ENCRYPTED_PASSWORD", "") if not input_file.endswith(".a3dcomp"): @@ -1668,7 +1670,7 @@ def insert_3d_component( 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_") 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()]) @@ -1781,7 +1783,7 @@ def insert_layout_component( 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 aedt_component_name = component_name if component_name not in self._app.ocomponent_manager.GetNames(): compInfo = ["NAME:" + str(component_name), "Info:=", []] @@ -1814,11 +1816,10 @@ def insert_layout_component( # 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) / + "LayoutComponents" / aedt_component_name / (aedt_component_name + ".aedb")) aedb_component_path = normalize_path(aedb_component_path) is_edb_open = False @@ -1988,7 +1989,7 @@ def get_3d_component_object_list(self, name): @pyaedt_function_handler() def _check_actor_folder(self, actor_folder): - if not os.path.exists(actor_folder): + if not Path(actor_folder).exists(): 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( @@ -3338,8 +3339,8 @@ def check_choke_values(self, input_dir, create_another_file=True): 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 + with open_file(new_path, "w") as outfile: json.dump(values, outfile) else: diff --git a/src/ansys/aedt/core/visualization/advanced/farfield_visualization.py b/src/ansys/aedt/core/visualization/advanced/farfield_visualization.py index aebb9eff080..a1479811778 100644 --- a/src/ansys/aedt/core/visualization/advanced/farfield_visualization.py +++ b/src/ansys/aedt/core/visualization/advanced/farfield_visualization.py @@ -25,6 +25,7 @@ import json import math import os +from pathlib import Path import shutil import sys @@ -90,10 +91,10 @@ class FfdSolutionData(object): def __init__( self, input_file, frequency=None, variation=None, model_info=None, incident_power=None, touchstone_file=None ): - input_file_format = os.path.basename(input_file).split(".")[1] + input_file_format = str(Path(input_file).suffix).strip(".") # Public - self.output_dir = os.path.dirname(input_file) + self.output_dir = str(Path(input_file).parent) if input_file_format in ["txt", "xml"]: if not variation: @@ -117,7 +118,7 @@ def __init__( # Protected self._mesh = None - if not os.path.isfile(input_file): # pragma: no cover + if not Path(input_file).is_file(): # pragma: no cover raise Exception("JSON file does not exist.") # Private @@ -160,7 +161,7 @@ def __init__( elements = self.metadata["element_pattern"] for element_name, element_props in elements.items(): location = element_props["location"] - pattern_file = os.path.join(self.output_dir, element_props["file_name"]) + pattern_file = Path(self.output_dir) / element_props["file_name"] incident_power = element_props["incident_power"] accepted_power = element_props["accepted_power"] radiated_power = element_props["radiated_power"] @@ -223,12 +224,12 @@ def __init__( raise Exception("Farfield information from ffd files can not be loaded.") # Load touchstone data - metadata_touchstone = os.path.join(self.output_dir, self.metadata.get("touchstone_file", None)) + metadata_touchstone = Path(self.output_dir) / self.metadata.get("touchstone_file", None) if not touchstone_file: touchstone_file = metadata_touchstone - if touchstone_file and os.path.isfile(touchstone_file): + if Path(touchstone_file).exists() and Path(touchstone_file).exists(): self.__touchstone_data = read_touchstone(touchstone_file) required_array_keys = ["array_dimension", "component_objects", "lattice_vector", "cell_position"] @@ -938,6 +939,8 @@ def plot_cut( >>> data.plot_cut(theta=20) """ + if isinstance(output_file, Path): + output_file = str(output_file) data = self.combine_farfield(phi, theta) if quantity not in data: # pragma: no cover raise Exception("Far field quantity not available.") @@ -1317,7 +1320,7 @@ def __init_ffd(self, element_info): for element, element_data in element_info.items(): self.__raw_data[element] = {} self.__frequencies = [] - if os.path.exists(element_data["pattern_file"]): + if Path(element_data["pattern_file"]).exists(): # Extract ports with open_file(element_data["pattern_file"], "r") as reader: theta = [int(i) for i in reader.readline().split()] @@ -1423,10 +1426,10 @@ def __get_geometry(self, off_screen=False): if component_obj in non_array_geometry: del non_array_geometry[component_obj] - cad_path = os.path.join(self.output_dir, model_info[component_obj][0]) - if os.path.exists(cad_path): + cad_path = Path(self.output_dir) / model_info[component_obj][0] + if cad_path.exists(): model_pv.add_object( - cad_path, + str(cad_path), model_info[component_obj][1], model_info[component_obj][2], model_info[component_obj][3], @@ -1476,10 +1479,10 @@ def __get_geometry(self, off_screen=False): self.__model_units = first_value[3] model_pv.off_screen = off_screen for object_in in non_array_geometry.values(): - cad_path = os.path.join(self.output_dir, object_in[0]) - if os.path.exists(cad_path): + cad_path = Path(self.output_dir) / object_in[0] + if cad_path.exists(): model_pv.add_object( - cad_path, + str(cad_path), object_in[1], object_in[2], object_in[3], @@ -1654,10 +1657,10 @@ def export_pyaedt_antenna_metadata( if not touchstone_file: touchstone_file = "" - pyaedt_metadata_file = os.path.join(output_dir, "pyaedt_antenna_metadata.json") + pyaedt_metadata_file = Path(output_dir) / "pyaedt_antenna_metadata.json" items = {"variation": variation, "element_pattern": {}, "touchstone_file": touchstone_file} - if os.path.isfile(input_file) and os.path.basename(input_file).split(".")[1] == "xml": + if Path(input_file).is_file() and Path(input_file).suffix == ".xml": # Metadata available from 2024.1 antenna_metadata = antenna_metadata_from_xml(input_file) @@ -1668,14 +1671,14 @@ def export_pyaedt_antenna_metadata( if ffd_files: # Move ffd files to main directory for ffd_file in ffd_files: - output_file = os.path.join(output_dir, ffd_file) - pattern_file = os.path.join(dir_path, ffd_file) + output_file = Path(output_dir) / ffd_file + pattern_file = Path(dir_path) / ffd_file shutil.move(pattern_file, output_file) if sNp_files and not touchstone_file: # Only one Touchstone allowed sNp_name, sNp_path = next(iter(sNp_files.items())) - output_file = os.path.join(output_dir, sNp_name) - exported_touchstone_file = os.path.join(sNp_path) + output_file = Path(output_dir) / sNp_name + exported_touchstone_file = Path(sNp_path) shutil.move(exported_touchstone_file, output_file) items["touchstone_file"] = sNp_name @@ -1716,19 +1719,19 @@ def export_pyaedt_antenna_metadata( } items["element_pattern"][metadata["name"]] = pattern - pattern_file = os.path.join(output_dir, metadata["file_name"]) - if not os.path.isfile(pattern_file): # pragma: no cover + pattern_file = Path(output_dir) / metadata["file_name"] + if not pattern_file.is_file(): # pragma: no cover return False - elif os.path.isfile(input_file) and os.path.basename(input_file).split(".")[1] == "txt": + elif Path(input_file).is_file() and Path(input_file).suffix == ".txt": # Find all ffd files and move them to main directory for dir_path, _, _ in os.walk(output_dir): sNp_files = find_touchstone_files(dir_path) if sNp_files and not touchstone_file: # Only one Touchstone allowed sNp_name, sNp_path = next(iter(sNp_files.items())) - output_file = os.path.join(output_dir, sNp_name) - exported_touchstone_file = os.path.join(sNp_path) + output_file = Path(output_dir) / sNp_name + exported_touchstone_file = Path(sNp_path) shutil.move(exported_touchstone_file, output_file) items["touchstone_file"] = sNp_name break diff --git a/src/ansys/aedt/core/visualization/post/compliance.py b/src/ansys/aedt/core/visualization/post/compliance.py index d436b2d5a5e..203dd5c4db2 100644 --- a/src/ansys/aedt/core/visualization/post/compliance.py +++ b/src/ansys/aedt/core/visualization/post/compliance.py @@ -316,7 +316,7 @@ def add_erl_parameters( ---------- design_name : str Design name. - config_file : str + config_file : str or :class:`pathlib.Path` Full path to ``cfg`` file. traces : list List of traces to compute com parameters. @@ -337,7 +337,7 @@ def add_erl_parameters( pars = { "name": name, "design_name": design_name, - "config": config_file, + "config": str(config_file), "traces": traces, "trace_pins": pins, "pass_fail": pass_fail, @@ -357,7 +357,7 @@ def add_report_derived_parameter( ---------- design_name : str Design name. - config_file : str + config_file : str or :class:`pathlib.Path` Full path to ``cfg`` file. parameter: str, Parameter name. Allowed value are ``"skew"``. @@ -377,7 +377,7 @@ def add_report_derived_parameter( "name": name, "design_name": design_name, "type": report_type, - "config": config_file, + "config": str(config_file), "traces": traces, "pass_fail": True, "pass_fail_criteria": pass_fail_criteria, @@ -430,7 +430,7 @@ def add_report_from_folder(self, input_folder, design_name, group_plots=False, p Parameters ---------- - input_folder : str + input_folder : str or :class:`pathlib.Path` Full path to the folder containing configuration files. design_name : str Name of design to apply the configuration. @@ -449,7 +449,7 @@ def add_report_from_folder(self, input_folder, design_name, group_plots=False, p name = conf.get("plot_name", generate_unique_name("Report")) self.add_report( design_name, - input_report, + str(input_report), traces=expr, report_type=rep_type, pass_fail=pass_fail, @@ -464,7 +464,7 @@ def save_configuration(self, output_file): Parameters ---------- - output_file : str + output_file : str or :class:`pathlib.Path` Full path of the output file. Returns @@ -553,7 +553,7 @@ class VirtualCompliance: ---------- desktop : :class:``ansys.aedt.core.desktop.Desktop`` Desktop object. - template : str + template : str or :class:`pathlib.Path` Full path to the template. Supported formats are JSON and TOML. """ @@ -565,7 +565,7 @@ def __init__(self, desktop, template): self._use_portrait = True self._template = template self._template_name = "Compliance" - self._template_folder = os.path.dirname(template) + self._template_folder = Path(template).parent self._project_file = None self._reports = {} self._reports_parameters = {} diff --git a/src/ansys/aedt/core/visualization/post/post_common_3d.py b/src/ansys/aedt/core/visualization/post/post_common_3d.py index 845a26c4db8..401179394bf 100644 --- a/src/ansys/aedt/core/visualization/post/post_common_3d.py +++ b/src/ansys/aedt/core/visualization/post/post_common_3d.py @@ -30,7 +30,7 @@ """ import os -import pathlib +from pathlib import Path import secrets import string from typing import Dict @@ -514,15 +514,15 @@ def get_scalar_field_value( variation.extend(intrinsics) - file_name = os.path.join(self._app.working_directory, generate_unique_name("temp_fld") + ".fld") - self.ofieldsreporter.CalculatorWrite(file_name, ["Solution:=", solution], variation) + file_name = Path(self._app.working_directory) / (generate_unique_name("temp_fld") + ".fld") + self.ofieldsreporter.CalculatorWrite(str(file_name), ["Solution:=", solution], variation) value = None - if os.path.exists(file_name) or settings.remote_rpc_session: + if file_name.exists() or settings.remote_rpc_session: with open_file(file_name, "r") as f: lines = f.readlines() lines = [line.strip() for line in lines] value = lines[-1] - os.remove(file_name) + file_name.unlink() self.ofieldsreporter.CalcStack("clear") return float(value) @@ -646,9 +646,9 @@ def export_field_file_on_grid( if not solution: solution = self._app.existing_analysis_sweeps[0] if not file_name: - file_name = os.path.join(self._app.working_directory, f"{quantity}_{solution.replace(' : ', '_')}.fld") - elif os.path.isdir(file_name): - file_name = os.path.join(file_name, f"{quantity}_{solution.replace(' : ', '_')}.fld") + file_name = Path(self._app.working_directory, f"{quantity}_{solution.replace(' : ', '_')}.fld") + elif Path(file_name).is_dir(): + file_name = Path(file_name) / f"{quantity}_{solution.replace(' : ', '_')}.fld" self.ofieldsreporter.CalcStack("clear") try: self.ofieldsreporter.EnterQty(quantity) @@ -715,7 +715,7 @@ def export_field_file_on_grid( grid_center, False, ) - if os.path.exists(file_name): + if Path(file_name).exists(): return file_name return False # pragma: no cover @@ -840,9 +840,9 @@ def export_field_file( if not output_file: appendix = "" ext = ".fld" - output_file = os.path.join(self._app.working_directory, solution.replace(" : ", "_") + appendix + ext) + output_file = Path(self._app.working_directory) / (solution.replace(" : ", "_") + appendix + ext) else: - output_file = output_file.replace("//", "/").replace("\\", "/") + output_file = Path(output_file).resolve() self.ofieldsreporter.CalcStack("clear") try: self.ofieldsreporter.EnterQty(quantity) @@ -874,7 +874,7 @@ def export_field_file( args = ["Solution:=", solution, "Geometry:=", assignment, "GeometryType:=", objects_type] else: args = ["Solution:=", solution] - self.ofieldsreporter.CalculatorWrite(output_file, args, variation) + self.ofieldsreporter.CalculatorWrite(str(output_file), args, variation) elif sample_points_file: export_options = [ "NAME:ExportOption", @@ -888,14 +888,14 @@ def export_field_file( export_field_in_reference, ] self.ofieldsreporter.ExportToFile( - output_file, - sample_points_file, + str(output_file), + str(sample_points_file), solution, variation, export_options, ) else: - sample_points_file = os.path.join(self._app.working_directory, "temp_points.pts") + sample_points_file = Path(self._app.working_directory) / "temp_points.pts" with open_file(sample_points_file, "w") as f: f.write(f"Unit={self.model_units}\n") for point in sample_points: @@ -912,14 +912,14 @@ def export_field_file( export_field_in_reference, ] self.ofieldsreporter.ExportToFile( - output_file, - sample_points_file, + str(output_file), + str(sample_points_file), solution, variation, export_options, ) - if os.path.exists(output_file): + if Path(output_file).exists(): return output_file return False # pragma: no cover @@ -952,11 +952,11 @@ def export_field_plot(self, plot_name, output_dir, file_name="", file_format="ae """ if not file_name: file_name = plot_name - output_dir = os.path.join(output_dir, file_name + "." + file_format) + output_dir = Path(output_dir) / (file_name + "." + file_format) try: self.ofieldsreporter.ExportFieldPlot(plot_name, False, output_dir) if settings.remote_rpc_session_temp_folder: # pragma: no cover - local_path = os.path.join(settings.remote_rpc_session_temp_folder, file_name + "." + file_format) + local_path = Path(settings.remote_rpc_session_temp_folder) / (file_name + "." + file_format) output_dir = check_and_download_file(local_path, output_dir) return output_dir except Exception: # pragma: no cover @@ -1553,14 +1553,14 @@ def export_model_picture( -------- >>> from ansys.aedt.core import Q3d >>> q3d = Q3d(non_graphical=False) - >>> output_file = q3d.post.export_model_picture(full_name=os.path.join(q3d.working_directory, "images1.jpg")) + >>> output_file = q3d.post.export_model_picture(full_name=Path(q3d.working_directory) / "images1.jpg") """ if selections: selections = self._app.modeler.convert_to_selections(selections, False) else: selections = "" if not full_name: - full_name = os.path.join(self._app.working_directory, generate_unique_name(self._app.design_name) + ".jpg") + full_name = Path(self._app.working_directory) / (generate_unique_name(self._app.design_name) + ".jpg") # open the 3D modeler and remove the selection on other objects if not self._app.desktop_class.non_graphical: # pragma: no cover @@ -1641,7 +1641,7 @@ def export_model_obj(self, assignment=None, export_path=None, export_as_multiple assignment = [assignment] if self._app._aedt_version < "2021.2": raise RuntimeError("Object is supported from AEDT 2021 R2.") # pragma: no cover - if not export_path or isinstance(export_path, pathlib.Path) and not export_path.name: + if not export_path or isinstance(export_path, Path) and not export_path.name: export_path = self._app.working_directory if not assignment: self._app.modeler.refresh_all_ids() @@ -1660,8 +1660,8 @@ def export_model_obj(self, assignment=None, export_path=None, export_as_multiple if export_as_multiple_objects: files_exported = [] for el in assignment: - fname = os.path.join(export_path, f"{el}.obj") - self._app.modeler.oeditor.ExportModelMeshToFile(fname, [el]) + fname = Path(export_path) / f"{el}.obj" + self._app.modeler.oeditor.ExportModelMeshToFile(str(fname), [el]) fname = check_and_download_file(fname) @@ -1675,10 +1675,10 @@ def export_model_obj(self, assignment=None, export_path=None, export_as_multiple files_exported.append([fname, self._app.modeler[el].color, 0.05]) return files_exported else: - if os.path.isdir(export_path): - fname = os.path.join(export_path, "Model_AllObjs_AllMats.obj") + if Path(export_path).is_dir(): + fname = Path(export_path) / "Model_AllObjs_AllMats.obj" else: - fname = export_path + fname = Path(export_path) self._app.modeler.oeditor.ExportModelMeshToFile(fname, assignment) return [[fname, "aquamarine", 0.3]] @@ -2133,7 +2133,7 @@ def plot_field_from_fieldplot( model.range_min = scale_min model.range_max = scale_max if project_path: - model.plot(os.path.join(project_path, plot_name + "." + image_format)) + model.plot(Path(project_path) / (plot_name + "." + image_format)) elif show: model.plot() return model @@ -2424,7 +2424,7 @@ def plot_animated_field( if fields_to_add: model.add_frames_from_file(fields_to_add, log_scale=log_scale) if export_gif: - model.gif_file = os.path.join(self._app.working_directory, self._app.project_name + ".gif") + model.gif_file = Path(self._app.working_directory) / (self._app.project_name + ".gif") if view != "isometric" and view in ["xy", "xz", "yz"]: model.camera_position = view elif view != "isometric": @@ -2527,7 +2527,7 @@ def animate_fields_from_aedtplt( if fields_to_add: model.add_frames_from_file(fields_to_add) if export_gif: - model.gif_file = os.path.join(self._app.working_directory, self._app.project_name + ".gif") + model.gif_file = Path(self._app.working_directory) / (self._app.project_name + ".gif") if show or export_gif: model.animate(show=show) @@ -2623,7 +2623,7 @@ def plot_scene( Returns ------- """ - if isinstance(frames, str) and os.path.exists(frames): + if isinstance(frames, str) and Path(frames).exists(): with open_file(frames, "r") as f: lines = f.read() temp_list = lines.splitlines() diff --git a/tests/system/solvers/conftest.py b/tests/system/solvers/conftest.py index 69582cc69c0..bc54de7ea5c 100644 --- a/tests/system/solvers/conftest.py +++ b/tests/system/solvers/conftest.py @@ -44,6 +44,7 @@ import json import os +from pathlib import Path import random import shutil import string @@ -71,8 +72,8 @@ settings.wait_for_license = True settings.enable_pandas_output = True -local_path = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(local_path) +local_path = Path(__file__).parent +sys.path.append(str(local_path)) # Initialize default desktop configuration default_version = "2025.1" @@ -96,8 +97,8 @@ } # Check for the local config file, override defaults if found -local_config_file = os.path.join(local_path, "local_config.json") -if os.path.exists(local_config_file): +local_config_file = Path(local_path) / "local_config.json" +if local_config_file.exists(): try: with open(local_config_file) as f: local_config = json.load(f) @@ -128,7 +129,7 @@ def generate_random_ident(): @pytest.fixture(scope="session", autouse=True) def init_scratch(): test_folder_name = "unit_test" + generate_random_ident() - test_folder = os.path.join(tempfile.gettempdir(), test_folder_name) + test_folder = Path(tempfile.gettempdir()) / test_folder_name try: os.makedirs(test_folder, mode=0o777) except FileExistsError as e: @@ -167,17 +168,17 @@ def _method( project_name=None, design_name=None, solution_type=None, application=None, subfolder="", just_open=False ): if project_name and not just_open: - example_project = os.path.join(local_path, "example_models", subfolder, project_name + ".aedt") - example_folder = os.path.join(local_path, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_project): - test_project = local_scratch.copyfile(example_project) - elif os.path.exists(example_project + "z"): - example_project = example_project + "z" - test_project = local_scratch.copyfile(example_project) + example_project = Path(local_path) / "example_models" / subfolder / (project_name + ".aedt") + example_folder = Path(local_path) / "example_models" / subfolder / (project_name + ".aedb") + if example_project.exists(): + test_project = local_scratch.copyfile(str(example_project)) + elif example_project.with_suffix(".aedtz").exists(): + example_project = example_project.with_suffix(".aedtz") + test_project = local_scratch.copyfile(str(example_project)) else: - test_project = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") + test_project = Path(local_scratch.path) / (project_name + ".aedt") + if example_folder.exists(): + target_folder = local_scratch.path / (project_name + ".aedb") local_scratch.copyfolder(example_folder, target_folder) elif project_name and just_open: test_project = project_name @@ -199,10 +200,10 @@ def _method( def test_project_file(local_scratch): def _method(project_name=None, subfolder=None): if subfolder: - project_file = os.path.join(local_path, "example_models", subfolder, project_name + ".aedt") + project_file = Path(local_path) / "example_models" / subfolder / (project_name + ".aedt") else: - project_file = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(project_file): + project_file = Path(local_scratch.path) / (project_name + ".aedt") + if project_file.exists(): return project_file else: return None @@ -214,14 +215,14 @@ def _method(project_name=None, subfolder=None): def add_edb(local_scratch): def _method(project_name=None, subfolder=""): if project_name: - example_folder = os.path.join(local_path, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") + example_folder = Path(local_path) / "example_models" / subfolder / (project_name + ".aedb") + if example_folder.exists(): + target_folder = local_scratch.path / (project_name + ".aedb") local_scratch.copyfolder(example_folder, target_folder) else: - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") + target_folder = local_scratch.path / (project_name + ".aedb") else: - target_folder = os.path.join(local_scratch.path, generate_unique_name("TestEdb") + ".aedb") + target_folder = local_scratch.path / (generate_unique_name("TestEdb") + ".aedb") return Edb( target_folder, edbversion=desktop_version, diff --git a/tests/system/solvers/test_00_analyze.py b/tests/system/solvers/test_00_analyze.py index 978c2e2c68d..ebbfecfaf63 100644 --- a/tests/system/solvers/test_00_analyze.py +++ b/tests/system/solvers/test_00_analyze.py @@ -23,7 +23,6 @@ # SOFTWARE. import csv -import os from pathlib import Path import sys import time @@ -193,10 +192,10 @@ def test_01b_sbr_link_array(self, sbr_platform_solved): title=f"Azimuth at {ffdata.farfield_data.frequency}Hz", quantity_format="dB10", show=False, - output_file=os.path.join(self.local_scratch.path, "2d1_array.jpg"), + output_file=Path(self.local_scratch.path) / "2d1_array.jpg", ) - assert os.path.exists(os.path.join(self.local_scratch.path, "2d1_array.jpg")) - assert os.path.isfile(ffdata2.metadata_file) + assert (Path(self.local_scratch.path) / "2d1_array.jpg").exists() + assert Path(ffdata2.metadata_file).is_file() def test_01b_sbr_create_vrt(self, sbr_app): sbr_app.rename_design("vtr") @@ -235,13 +234,13 @@ def test_02_hfss_export_results(self, hfss_app): from ansys.aedt.core.generic.file_utils import read_json if desktop_version > "2023.1": - dict_in = read_json(os.path.join(local_path, "example_models", test_subfolder, "array_simple_232.json")) - dict_in["Circ_Patch_5GHz_232_1"] = os.path.join(local_path, "example_models", test_subfolder, component) + dict_in = read_json(Path(local_path) / "example_models" / test_subfolder / "array_simple_232.json") + dict_in["Circ_Patch_5GHz_232_1"] = Path(local_path) / "example_models" / test_subfolder / component dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz_232_1"} dict_in["cells"][(3, 3)]["rotation"] = 90 else: - dict_in = read_json(os.path.join(local_path, "example_models", test_subfolder, "array_simple.json")) - dict_in["Circ_Patch_5GHz1"] = os.path.join(local_path, "example_models", test_subfolder, component) + dict_in = read_json(Path(local_path) / "example_models" / test_subfolder / "array_simple.json") + dict_in["Circ_Patch_5GHz1"] = Path(local_path) / "example_models" / test_subfolder / component dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz1"} dict_in["cells"][(3, 3)]["rotation"] = 90 hfss_app.create_3d_component_array(dict_in) @@ -259,25 +258,25 @@ def test_02_hfss_export_results(self, hfss_app): matrix_type="Y", ) assert len(exported_files) > 0 - fld_file1 = os.path.join(self.local_scratch.path, "test_fld_hfss1.fld") + fld_file1 = Path(self.local_scratch.path) / "test_fld_hfss1.fld" assert hfss_app.post.export_field_file( quantity="Mag_E", output_file=fld_file1, assignment="Box1", intrinsics=solve_freq, phase="5deg" ) - assert os.path.exists(fld_file1) - fld_file2 = os.path.join(self.local_scratch.path, "test_fld_hfss2.fld") + assert fld_file1.exists() + fld_file2 = Path(self.local_scratch.path) / "test_fld_hfss2.fld" assert hfss_app.post.export_field_file( quantity="Mag_E", output_file=fld_file2, assignment="Box1", intrinsics={"frequency": solve_freq} ) - assert os.path.exists(fld_file2) - fld_file2 = os.path.join(self.local_scratch.path, "test_fld_hfss3.fld") + assert fld_file2.exists() + fld_file2 = Path(self.local_scratch.path) / "test_fld_hfss3.fld" assert hfss_app.post.export_field_file( quantity="Mag_E", output_file=fld_file2, assignment="Box1", intrinsics={"frequency": solve_freq, "phase": "30deg"}, ) - assert os.path.exists(fld_file2) - fld_file2 = os.path.join(self.local_scratch.path, "test_fld_hfss4.fld") + assert fld_file2.exists() + fld_file2 = Path(self.local_scratch.path) / "test_fld_hfss4.fld" assert hfss_app.post.export_field_file( quantity="Mag_E", output_file=fld_file2, @@ -285,18 +284,18 @@ def test_02_hfss_export_results(self, hfss_app): intrinsics={"frequency": solve_freq}, phase="30deg", ) - assert os.path.exists(fld_file2) - fld_file2 = os.path.join(self.local_scratch.path, "test_fld_hfss5.fld") + assert fld_file2.exists() + fld_file2 = Path(self.local_scratch.path) / "test_fld_hfss5.fld" assert hfss_app.post.export_field_file( quantity="Mag_E", output_file=fld_file2, assignment="Box1", ) - assert os.path.exists(fld_file2) - fld_file2 = os.path.join(self.local_scratch.path, "test_fld_hfss6.fld") + assert fld_file2.exists() + fld_file2 = Path(self.local_scratch.path) / "test_fld_hfss6.fld" with pytest.raises(TypeError): hfss_app.post.export_field_file(quantity="Mag_E", output_file=fld_file2, assignment="Box1", intrinsics=[]) - assert not os.path.exists(fld_file2) + assert not fld_file2.exists() hfss_app.variable_manager.set_variable(name="dummy", expression=1, is_post_processing=True) hfss_app.parametrics.add(variable="dummy", start_point=0, end_point=1, step=2) @@ -321,7 +320,7 @@ def test_03a_icepak_analyze_and_export_summary(self, icepak_solved): ("B_Temperature.csv", ["box", "Region"]), ("C_Temperature.csv", ["box"]), ]: - with open(os.path.join(icepak_solved.working_directory, file_name), "r", newline="") as csv_file: + with open(Path(icepak_solved.working_directory) / file_name, "r", newline="") as csv_file: csv_reader = csv.reader(csv_file) for _ in range(4): _ = next(csv_reader) @@ -331,9 +330,9 @@ def test_03a_icepak_analyze_and_export_summary(self, icepak_solved): assert all(e in csv_entities for e in entities) box = [i.id for i in icepak_solved.modeler["box"].faces] - assert os.path.exists( + assert Path( icepak_solved.eval_surface_quantity_from_field_summary(box, savedir=icepak_solved.working_directory) - ) + ).exists() opening = [i for i in icepak_solved.boundaries if i.type == "Opening"][0] # new post class out = icepak_solved.post.evaluate_faces_quantity(box, "HeatFlowRate") @@ -374,14 +373,14 @@ def test_03c_icepak_get_monitor_output(self, icepak_solved): assert icepak_solved.monitor.all_monitors["test_monitor2"].value(quantity="HeatFlowRate") def test_03d_icepak_eval_tempc(self, icepak_solved): - assert os.path.exists( + assert Path( icepak_solved.eval_volume_quantity_from_field_summary( ["box"], "Temperature", savedir=icepak_solved.working_directory ) - ) + ).exists() def test_03e_icepak_ExportFLDFil(self, icepak_solved): - fld_file = os.path.join(self.local_scratch.path, "test_fld.fld") + fld_file = Path(self.local_scratch.path) / "test_fld.fld" icepak_solved.post.export_field_file( quantity="Temp", solution=icepak_solved.nominal_sweep, @@ -389,9 +388,9 @@ def test_03e_icepak_ExportFLDFil(self, icepak_solved): output_file=fld_file, assignment="box", ) - assert os.path.exists(fld_file) - fld_file_1 = os.path.join(self.local_scratch.path, "test_fld_1.fld") - sample_points_file = os.path.join(local_path, "example_models", test_subfolder, "temp_points.pts") + assert fld_file.exists() + fld_file_1 = Path(self.local_scratch.path) / "test_fld_1.fld" + sample_points_file = Path(local_path) / "example_models" / test_subfolder / "temp_points.pts" icepak_solved.available_variations.independent = True icepak_solved.post.export_field_file( quantity="Temp", @@ -401,8 +400,8 @@ def test_03e_icepak_ExportFLDFil(self, icepak_solved): assignment="box", sample_points_file=sample_points_file, ) - assert os.path.exists(fld_file_1) - fld_file_2 = os.path.join(self.local_scratch.path, "test_fld_2.fld") + assert fld_file_1.exists() + fld_file_2 = Path(self.local_scratch.path) / "test_fld_2.fld" icepak_solved.post.export_field_file( quantity="Temp", solution=icepak_solved.nominal_sweep, @@ -411,9 +410,9 @@ def test_03e_icepak_ExportFLDFil(self, icepak_solved): assignment="box", sample_points=[[0, 0, 0], [3, 6, 8], [4, 7, 9]], ) - assert os.path.exists(fld_file_2) + assert fld_file_2.exists() cs = icepak_solved.modeler.create_coordinate_system() - fld_file_3 = os.path.join(self.local_scratch.path, "test_fld_3.fld") + fld_file_3 = Path(self.local_scratch.path) / "test_fld_3.fld" icepak_solved.post.export_field_file( quantity="Temp", solution=icepak_solved.nominal_sweep, @@ -425,19 +424,19 @@ def test_03e_icepak_ExportFLDFil(self, icepak_solved): export_in_si_system=False, export_field_in_reference=False, ) - assert os.path.exists(fld_file_3) + assert fld_file_3.exists() def test_04c_3dl_analyze_setup(self, hfss3dl_solved): - assert os.path.exists(hfss3dl_solved.export_profile("Setup1")) - assert os.path.exists(hfss3dl_solved.export_mesh_stats("Setup1")) + assert Path(hfss3dl_solved.export_profile("Setup1")).exists() + assert Path(hfss3dl_solved.export_mesh_stats("Setup1")).exists() @pytest.mark.skipif(is_linux, reason="To be investigated on linux.") def test_04d_3dl_export_touchstone(self, hfss3dl_solved): - filename = os.path.join(self.local_scratch.path, "touchstone.s2p") + filename = Path(self.local_scratch.path) / "touchstone.s2p" solution_name = "Setup1" sweep_name = "Sweep1" assert hfss3dl_solved.export_touchstone(solution_name, sweep_name, filename) - assert os.path.exists(filename) + assert filename.exists() assert hfss3dl_solved.export_touchstone(solution_name) sweep_name = None assert hfss3dl_solved.export_touchstone(solution_name, sweep_name) @@ -525,7 +524,7 @@ def test_06_m3d_harmonic_forces(self, m3dtransient): assert m3dtransient.export_element_based_harmonic_force(number_of_frequency=5) def test_07_export_maxwell_fields(self, m3dtransient): - fld_file_3 = os.path.join(self.local_scratch.path, "test_fld_3.fld") + fld_file_3 = Path(self.local_scratch.path) / "test_fld_3.fld" assert m3dtransient.post.export_field_file( quantity="Mag_B", solution=m3dtransient.nominal_sweep, @@ -535,8 +534,8 @@ def test_07_export_maxwell_fields(self, m3dtransient): objects_type="Surf", intrinsics="10ms", ) - assert os.path.exists(fld_file_3) - fld_file_4 = os.path.join(self.local_scratch.path, "test_fld_4.fld") + assert fld_file_3.exists() + fld_file_4 = Path(self.local_scratch.path) / "test_fld_4.fld" m3dtransient.available_variations.independent = True assert not m3dtransient.post.export_field_file( quantity="Mag_B", @@ -581,8 +580,8 @@ def test_09a_compute_com(self, local_scratch, circuit_com): touchstone_file = circuit_com.export_touchstone() spisim = SpiSim(touchstone_file) - report_dir = os.path.join(spisim.working_directory, "50GAUI-1_C2C") - os.mkdir(report_dir) + report_dir = Path(spisim.working_directory) / "50GAUI-1_C2C" + report_dir.mkdir() com = spisim.compute_com( standard=1, out_folder=report_dir, @@ -590,16 +589,12 @@ def test_09a_compute_com(self, local_scratch, circuit_com): assert com def test_09b_compute_com(self, local_scratch): - com_example_file_folder = os.path.join(local_path, "example_models", test_subfolder, "com_unit_test_sparam") - thru_s4p = local_scratch.copyfile(os.path.join(com_example_file_folder, "SerDes_Demo_02_Thru.s4p")) - fext_s4p = local_scratch.copyfile( - os.path.join(com_example_file_folder, "FCI_CC_Long_Link_Pair_2_to_Pair_9_FEXT.s4p") - ) - next_s4p = local_scratch.copyfile( - os.path.join(com_example_file_folder, "FCI_CC_Long_Link_Pair_11_to_Pair_9_NEXT.s4p") - ) - report_dir = os.path.join(local_scratch.path, "custom") - os.mkdir(report_dir) + com_example_file_folder = Path(local_path) / "example_models" / test_subfolder / "com_unit_test_sparam" + thru_s4p = local_scratch.copyfile(Path(com_example_file_folder) / "SerDes_Demo_02_Thru.s4p") + fext_s4p = local_scratch.copyfile(com_example_file_folder / "FCI_CC_Long_Link_Pair_2_to_Pair_9_FEXT.s4p") + next_s4p = local_scratch.copyfile(com_example_file_folder / "FCI_CC_Long_Link_Pair_11_to_Pair_9_NEXT.s4p") + report_dir = Path(local_scratch.path) / "custom" + report_dir.mkdir() spisim = SpiSim(thru_s4p) spisim.working_directory = local_scratch.path @@ -617,13 +612,13 @@ def test_09c_compute_com(self, local_scratch): thru_s4p = local_scratch.copyfile(com_example_file_folder / "SerDes_Demo_02_Thru.s4p") spisim = SpiSim(thru_s4p) - spisim.export_com_configure_file(os.path.join(spisim.working_directory, "custom.json")) + spisim.export_com_configure_file(Path(spisim.working_directory) / "custom.json") from ansys.aedt.core.visualization.post.spisim_com_configuration_files.com_parameters import COMParametersVer3p4 com_param = COMParametersVer3p4() com_param.load( - os.path.join(spisim.working_directory, "custom.json"), + Path(spisim.working_directory) / "custom.json", ) com_param.export_spisim_cfg(str(Path(local_scratch.path) / "test.cfg")) com_0, com_1 = spisim.compute_com(0, Path(local_scratch.path) / "test.cfg") @@ -636,7 +631,7 @@ def test_10_export_to_maxwell(self, add_app): assert m2d.design_type == "Maxwell 2D" m3d = app.create_maxwell_design("Setup1", maxwell_2d=False) assert m3d.design_type == "Maxwell 3D" - config = app.export_configuration(os.path.join(self.local_scratch.path, "assm.json")) + config = app.export_configuration(Path(self.local_scratch.path) / "assm.json") app2 = add_app("assm_test2", application=Rmxprt, solution_type="ASSM") app2.import_configuration(config) assert app2.circuit diff --git a/tests/system/solvers/test_01_pdf.py b/tests/system/solvers/test_01_pdf.py index 713ec086e6b..3978309ef45 100644 --- a/tests/system/solvers/test_01_pdf.py +++ b/tests/system/solvers/test_01_pdf.py @@ -22,7 +22,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +import json import os +from pathlib import Path import pytest @@ -87,52 +89,40 @@ def test_create_pdf_schematic(self, circuit_test): assert report.add_project_info(circuit_test) def test_virtual_compliance(self, local_scratch, aedtapp): - template = os.path.join( - local_path, "example_models", test_subfolder, "compliance", "general_compliance_template.json" + template = ( + Path(local_path) / "example_models" / test_subfolder / "compliance" / "general_compliance_template.json" ) template = local_scratch.copyfile(template) local_scratch.copyfile( - os.path.join(local_path, "example_models", test_subfolder, "compliance", "ContourEyeDiagram_Custom.json") + Path(local_path) / "example_models" / test_subfolder / "compliance" / "ContourEyeDiagram_Custom.json" ) + local_scratch.copyfile(Path(local_path) / "example_models" / test_subfolder / "compliance" / "spisim_erl.cfg") local_scratch.copyfile( - os.path.join(local_path, "example_models", test_subfolder, "compliance", "spisim_erl.cfg") + Path(local_path) / "example_models" / test_subfolder / "compliance" / "Sparameter_Custom.json" ) local_scratch.copyfile( - os.path.join(local_path, "example_models", test_subfolder, "compliance", "Sparameter_Custom.json") + Path(local_path) / "example_models" / test_subfolder / "compliance" / "Sparameter_Insertion_Custom.json" ) local_scratch.copyfile( - os.path.join(local_path, "example_models", test_subfolder, "compliance", "Sparameter_Insertion_Custom.json") + Path(local_path) / "example_models" / test_subfolder / "compliance" / "StatisticalEyeDiagram_Custom.json" ) local_scratch.copyfile( - os.path.join( - local_path, "example_models", test_subfolder, "compliance", "StatisticalEyeDiagram_Custom.json" - ) - ) - local_scratch.copyfile( - os.path.join(local_path, "example_models", test_subfolder, "compliance", "EyeDiagram_Custom.json") + Path(local_path) / "example_models" / test_subfolder / "compliance" / "EyeDiagram_Custom.json" ) - import json - with open(template, "r+") as f: data = json.load(f) - data["general"]["project"] = os.path.join(aedtapp.project_path, aedtapp.project_name + ".aedt") + data["general"]["project"] = str(Path(aedtapp.project_path) / (aedtapp.project_name + ".aedt")) f.seek(0) json.dump(data, f, indent=4) f.truncate() - compliance_folder = os.path.join(local_scratch.path, "vc") + compliance_folder = Path(local_scratch.path) / "vc" os.makedirs(compliance_folder, exist_ok=True) vc = VirtualComplianceGenerator("Test_full", "Diff_Via") - vc.dut_image = os.path.join(local_path, "example_models", test_subfolder, "nets.jpg") + vc.dut_image = Path(local_path) / "example_models" / test_subfolder / "nets.jpg" vc.project_file = aedtapp.project_file - # for plot in aedtapp.post.plots[::]: - # try: - # plot.export_config(f"{compliance_folder}\\report_{plot.plot_name}.json") - # except Exception: - # print(f"Failed to generate {plot.plot_name}") - vc.add_report_from_folder( - os.path.join(local_path, "example_models", test_subfolder, "compliance"), + input_folder=Path(local_path) / "example_models" / test_subfolder / "compliance", design_name="Circuit1", group_plots=True, project=aedtapp.project_file, @@ -140,7 +130,7 @@ def test_virtual_compliance(self, local_scratch, aedtapp): if is_windows: vc.add_erl_parameters( design_name=aedtapp.design_name, - config_file=f"{compliance_folder}\\config.cfg", + config_file=compliance_folder / "config.cfg", traces=["RX1", "RX3"], pins=[ [ @@ -156,21 +146,21 @@ def test_virtual_compliance(self, local_scratch, aedtapp): name="ERL", ) local_scratch.copyfile( - os.path.join(local_path, "example_models", test_subfolder, "compliance", "skew.json"), - os.path.join(compliance_folder, "skew.json"), + Path(local_path) / "example_models" / test_subfolder / "compliance" / "skew.json", + Path(compliance_folder) / "skew.json", ) vc.add_report_derived_parameter( design_name="skew", parameter="skew", - config_file=os.path.join(compliance_folder, "skew.json"), + config_file=compliance_folder / "skew.json", traces=["V(V_Rx)", "V(V_Rx8)"], report_type="time", pass_fail_criteria=0.2, name="Differential Skew", ) - vc.save_configuration(f"{compliance_folder}\\main.json") - assert os.path.exists(os.path.join(compliance_folder, "main.json")) - v = VirtualCompliance(aedtapp.desktop_class, f"{compliance_folder}\\main.json") + vc.save_configuration(compliance_folder / "main.json") + assert (compliance_folder / "main.json").exists() + v = VirtualCompliance(aedtapp.desktop_class, compliance_folder / "main.json") assert v.create_compliance_report() def test_spisim_raw_read(self, local_scratch): diff --git a/tests/unit/test_generic_filesystem.py b/tests/unit/test_generic_filesystem.py index ca23eef11b6..05c1f528614 100644 --- a/tests/unit/test_generic_filesystem.py +++ b/tests/unit/test_generic_filesystem.py @@ -47,9 +47,9 @@ def desktop(): ) def test_is_safe_path(path, allowed_extensions, expected): """Test the is_safe_path function.""" - with mock.patch("os.path.exists", return_value=True), mock.patch("os.path.isfile", return_value=True): + with mock.patch("pathlib.Path.exists", return_value=True), mock.patch("pathlib.Path.is_file", return_value=True): assert is_safe_path(path, allowed_extensions) == expected # Test case for an invalid path - with mock.patch("os.path.exists", return_value=False): + with mock.patch("pathlib.Path.exists", return_value=False): assert not is_safe_path("/invalid/path/file.txt", [".txt"])