diff --git a/doc/changelog.d/3490.added.md b/doc/changelog.d/3490.added.md new file mode 100644 index 0000000000..93351e68ee --- /dev/null +++ b/doc/changelog.d/3490.added.md @@ -0,0 +1 @@ +refactor: `__init__` file \ No newline at end of file diff --git a/src/ansys/mapdl/core/__init__.py b/src/ansys/mapdl/core/__init__.py index 05842784a0..dd8981461b 100644 --- a/src/ansys/mapdl/core/__init__.py +++ b/src/ansys/mapdl/core/__init__.py @@ -20,102 +20,89 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# Importing logging +import importlib.metadata as importlib_metadata + +############################################################################### +# Imports +# ======= +# import logging import os import sys +from typing import Dict, List, Tuple from warnings import warn -import platformdirs - -# Setup data directory -USER_DATA_PATH = platformdirs.user_data_dir( - appname="ansys_mapdl_core", appauthor="Ansys" -) -if not os.path.exists(USER_DATA_PATH): # pragma: no cover - os.makedirs(USER_DATA_PATH) - -DEPRECATING_MINIMUM_PYTHON_VERSION = True -MINIMUM_PYTHON_VERSION = (3, 10) - -first_time_file = os.path.join(USER_DATA_PATH, ".firstime") -if not os.path.exists(first_time_file): # pragma: no cover - py_ver = f"{sys.version_info[0]}.{sys.version_info[1]}" - py_ver_min = f"{MINIMUM_PYTHON_VERSION[0]}.{MINIMUM_PYTHON_VERSION[1]}" - - if ( - sys.version_info[1] == MINIMUM_PYTHON_VERSION[1] - and DEPRECATING_MINIMUM_PYTHON_VERSION - ): - warn( - f"Support for Python {py_ver} will be dropped in the next minor " "release." - ) - - if sys.version_info[1] <= MINIMUM_PYTHON_VERSION[1]: - warn( - f"Python {py_ver} is not being tested or officially supported. " - "It is recommended you use a newer version of Python. " - f"The mininimum supported and tested version is {py_ver_min}.\n\n" - "**This warning is shown only the first time you run PyMAPDL.**\n" - ) - - with open(first_time_file, "w") as fid: - fid.write("") - -EXAMPLES_PATH = os.path.join(USER_DATA_PATH, "examples") +from platformdirs import user_data_dir +############################################################################### +# Logging +# ======= +# from ansys.mapdl.core.logging import Logger LOG = Logger(level=logging.ERROR, to_file=False, to_stdout=True) LOG.debug("Loaded logging module as LOG") +############################################################################### +# Globals +# ======= +# +from ansys.mapdl.core.helpers import is_installed, run_every_import, run_first_time -BUILDING_GALLERY = False -RUNNING_TESTS = False - -if RUNNING_TESTS: # pragma: no cover - LOG.debug("Running tests on Pytest") - -_LOCAL_PORTS = [] - +__version__: str = importlib_metadata.version(__name__.replace(".", "-")) -try: - from ansys.tools.visualization_interface import Plotter +# A dictionary relating PyMAPDL server versions with the unified install ones +VERSION_MAP: Dict[Tuple[int, int, int], str] = { + (0, 0, 0): "2020R2", + (0, 3, 0): "2021R1", + (0, 4, 0): "2021R2", + (0, 4, 1): "2021R2", + (0, 5, 0): "2022R1", + (0, 5, 1): "2022R2", +} - _HAS_VISUALIZER = True -except ModuleNotFoundError: # pragma: no cover - LOG.debug("The module 'ansys-tools-visualization_interface' is not installed.") - _HAS_VISUALIZER = False +BUILDING_GALLERY: bool = False +RUNNING_TESTS: bool = False -try: - import pyvista as pv +DEPRECATING_MINIMUM_PYTHON_VERSION: bool = True +MINIMUM_PYTHON_VERSION: Tuple[int, int] = (3, 10) - _HAS_PYVISTA = True -except ModuleNotFoundError: # pragma: no cover - LOG.debug("The module 'pyvista' is not installed.") - _HAS_PYVISTA = False +# Import related globals +_HAS_ATP: bool = is_installed("ansys.tools.path") +_HAS_PIM: bool = is_installed("ansys.platform.instancemanagement") +_HAS_PYANSYS_REPORT: bool = is_installed("ansys.tools.report") +_HAS_PYVISTA: bool = is_installed("pyvista") +_HAS_TQDM: bool = is_installed("tqdm") +_HAS_VISUALIZER: bool = is_installed("ansys.tools.visualization_interface") +# Setup directories +USER_DATA_PATH: str = user_data_dir(appname="ansys_mapdl_core", appauthor="Ansys") +EXAMPLES_PATH = os.path.join(USER_DATA_PATH, "examples") -try: - import importlib.metadata as importlib_metadata -except ModuleNotFoundError: # pragma: no cover - import importlib_metadata +# Store local ports +_LOCAL_PORTS: List[int] = [] -__version__ = importlib_metadata.version(__name__.replace(".", "-")) +############################################################################### +# First time +# ========== +# +# This function runs only the first time PyMAPDL is importad after it is installed. +# It creates the required directories and raise Python version related warnings. +# +run_first_time() -try: - from ansys.tools.path.path import ( - change_default_ansys_path, - find_ansys, - get_ansys_path, - get_available_ansys_installations, - save_ansys_path, - ) -except: - # We don't really use these imports in the library. They are here for - # convenience. - pass +############################################################################### +# Runs every time +# =============== +# +# This function runs every time that PyMAPDL is imported. +# +run_every_import() +############################################################################### +# Library imports +# =============== +# from ansys.mapdl.core._version import SUPPORTED_ANSYS_VERSIONS from ansys.mapdl.core.convert import convert_apdl_block, convert_script from ansys.mapdl.core.launcher import close_all_local_instances @@ -131,23 +118,19 @@ from ansys.mapdl.core.misc import Report, _check_has_ansys from ansys.mapdl.core.pool import MapdlPool -_HAS_ANSYS = _check_has_ansys() +############################################################################### +# Convenient imports +# ================== +# +# For compatibility with other versions or for convenience +if _HAS_ATP: + from ansys.tools.path.path import ( + change_default_ansys_path, + find_ansys, + get_ansys_path, + get_available_ansys_installations, + save_ansys_path, + ) if _HAS_VISUALIZER: - from ansys.mapdl.core.plotting.theme import _apply_default_theme - - _apply_default_theme() - -BUILDING_GALLERY = False -RUNNING_TESTS = False - - -VERSION_MAP = { - (0, 0, 0): "2020R2", - (0, 3, 0): "2021R1", - (0, 4, 0): "2021R2", - (0, 4, 1): "2021R2", - (0, 5, 0): "2022R1", - (0, 5, 1): "2022R2", # as of 21 Mar 2022 unreleased -} -"""A dictionary relating PyMAPDL server versions with the unified install ones.""" + from ansys.tools.visualization_interface import Plotter diff --git a/src/ansys/mapdl/core/helpers.py b/src/ansys/mapdl/core/helpers.py new file mode 100644 index 0000000000..edb29704ab --- /dev/null +++ b/src/ansys/mapdl/core/helpers.py @@ -0,0 +1,102 @@ +# Copyright (C) 2016 - 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Module for helper functions""" + +import importlib +import os +import sys +from warnings import warn + +from ansys.mapdl.core import LOG + + +def is_installed(package_name: str) -> bool: + """Check if a package is installed""" + + if os.name == "nt": + package_name = package_name.replace("-", ".") + + try: + importlib.import_module(package_name) + + return True + except ModuleNotFoundError: # pragma: no cover + LOG.debug(f"The module '{package_name}' is not installed.") + return False + + +def run_first_time() -> None: + """Run this function the first time PyMAPDL is imported""" + from ansys.mapdl.core import ( + DEPRECATING_MINIMUM_PYTHON_VERSION, + MINIMUM_PYTHON_VERSION, + USER_DATA_PATH, + ) + + first_time_file: str = os.path.join(USER_DATA_PATH, ".firstime") + + # Run the first time only + if not os.path.exists(first_time_file): # pragma: no cover + + # Create USER_DATA_PATH directory + if not os.path.exists(USER_DATA_PATH): # pragma: no cover + os.makedirs(USER_DATA_PATH) + + # Show warning about Python compatibility + py_ver = f"{sys.version_info[0]}.{sys.version_info[1]}" + py_ver_min = f"{MINIMUM_PYTHON_VERSION[0]}.{MINIMUM_PYTHON_VERSION[1]}" + + if ( + sys.version_info[1] == MINIMUM_PYTHON_VERSION[1] + and DEPRECATING_MINIMUM_PYTHON_VERSION + ): + warn( + f"Support for Python {py_ver} will be dropped in the next minor " + "release." + ) + + if sys.version_info[1] <= MINIMUM_PYTHON_VERSION[1]: + warn( + f"Python {py_ver} is not being tested or officially supported. " + "It is recommended you use a newer version of Python. " + f"The mininimum supported and tested version is {py_ver_min}.\n\n" + "**This warning is shown only the first time you run PyMAPDL.**\n" + ) + + with open(first_time_file, "w") as fid: + fid.write("") + + +def run_every_import() -> None: + # Run every time we import PyMAPDL + from ansys.mapdl.core import _HAS_VISUALIZER, RUNNING_TESTS + + # Apply custom theme + if _HAS_VISUALIZER: + from ansys.mapdl.core.plotting.theme import _apply_default_theme + + _apply_default_theme() + + # In case we want to do something specific for testing. + if RUNNING_TESTS: # pragma: no cover + LOG.debug("Running tests on Pytest") diff --git a/src/ansys/mapdl/core/launcher.py b/src/ansys/mapdl/core/launcher.py index 83d74453be..047404f64c 100644 --- a/src/ansys/mapdl/core/launcher.py +++ b/src/ansys/mapdl/core/launcher.py @@ -36,23 +36,8 @@ import psutil -try: - import ansys.platform.instancemanagement as pypim - - _HAS_PIM = True - -except ModuleNotFoundError: # pragma: no cover - _HAS_PIM = False - -try: - from ansys.tools.path import find_ansys, get_ansys_path, version_from_path - - _HAS_ATP = True -except ModuleNotFoundError: - _HAS_ATP = False - from ansys.mapdl import core as pymapdl -from ansys.mapdl.core import LOG +from ansys.mapdl.core import _HAS_ATP, _HAS_PIM, LOG from ansys.mapdl.core._version import SUPPORTED_ANSYS_VERSIONS from ansys.mapdl.core.errors import ( LockFileException, @@ -72,6 +57,12 @@ threaded, ) +if _HAS_PIM: + import ansys.platform.instancemanagement as pypim + +if _HAS_ATP: + from ansys.tools.path import find_ansys, get_ansys_path, version_from_path + if TYPE_CHECKING: # pragma: no cover from ansys.mapdl.core.mapdl_console import MapdlConsole diff --git a/src/ansys/mapdl/core/licensing.py b/src/ansys/mapdl/core/licensing.py index 8740084ca9..28c68bea3b 100644 --- a/src/ansys/mapdl/core/licensing.py +++ b/src/ansys/mapdl/core/licensing.py @@ -27,19 +27,13 @@ import subprocess import time -from ansys.mapdl.core import LOG +from ansys.mapdl.core import _HAS_ATP, LOG from ansys.mapdl.core.errors import LicenseServerConnectionError from ansys.mapdl.core.misc import threaded_daemon -try: +if _HAS_ATP: from ansys.tools.path import get_ansys_path, version_from_path - _HAS_ATP = True - -except ModuleNotFoundError: - _HAS_ATP = False - - LOCALHOST = "127.0.0.1" LIC_PATH_ENVAR = "ANSYSLIC_DIR" LIC_FILE_ENVAR = "ANSYSLMD_LICENSE_FILE" diff --git a/src/ansys/mapdl/core/mapdl_grpc.py b/src/ansys/mapdl/core/mapdl_grpc.py index 72f4b9e054..28210b8f40 100644 --- a/src/ansys/mapdl/core/mapdl_grpc.py +++ b/src/ansys/mapdl/core/mapdl_grpc.py @@ -64,7 +64,7 @@ except ImportError: # pragma: no cover raise ImportError(MSG_IMPORT) -from ansys.mapdl.core import _LOCAL_PORTS, __version__ +from ansys.mapdl.core import _HAS_TQDM, __version__ from ansys.mapdl.core.common_grpc import ( ANSYS_VALUE_TYPE, DEFAULT_CHUNKSIZE, @@ -92,13 +92,9 @@ # Checking if tqdm is installed. # If it is, the default value for progress_bar is true. -try: +if _HAS_TQDM: from tqdm import tqdm - _HAS_TQDM = True -except ModuleNotFoundError: # pragma: no cover - _HAS_TQDM = False - if TYPE_CHECKING: # pragma: no cover from queue import Queue @@ -1125,8 +1121,8 @@ def exit(self, save=False, force=False, **kwargs): self._remove_temp_dir_on_exit(mapdl_path) - if self._local and self._port in _LOCAL_PORTS: - _LOCAL_PORTS.remove(self._port) + if self._local and self._port in pymapdl._LOCAL_PORTS: + pymapdl._LOCAL_PORTS.remove(self._port) def _remove_temp_dir_on_exit(self, path=None): """Removes the temporary directory created by the launcher. diff --git a/src/ansys/mapdl/core/misc.py b/src/ansys/mapdl/core/misc.py index 28609486ea..efbc53295a 100644 --- a/src/ansys/mapdl/core/misc.py +++ b/src/ansys/mapdl/core/misc.py @@ -36,25 +36,17 @@ from typing import Union from warnings import warn -try: - from ansys.tools.path import get_available_ansys_installations - - _HAS_ATP = True -except ModuleNotFoundError: - _HAS_ATP = False - import numpy as np from ansys.mapdl import core as pymapdl -from ansys.mapdl.core import _HAS_PYVISTA, LOG +from ansys.mapdl.core import _HAS_ATP, _HAS_PYANSYS_REPORT, _HAS_PYVISTA, LOG -try: +if _HAS_ATP: + from ansys.tools.path import get_available_ansys_installations + +if _HAS_PYANSYS_REPORT: import ansys.tools.report as pyansys_report - _HAS_PYANSYS_REPORT = True -except ModuleNotFoundError: # pragma: no cover - LOG.debug("The package 'pyansys-tools-report' is not installed.") - _HAS_PYANSYS_REPORT = False # path of this module MODULE_PATH = os.path.dirname(inspect.getfile(inspect.currentframe())) diff --git a/src/ansys/mapdl/core/pool.py b/src/ansys/mapdl/core/pool.py index 49b0d4903c..8e45a424a9 100755 --- a/src/ansys/mapdl/core/pool.py +++ b/src/ansys/mapdl/core/pool.py @@ -29,7 +29,7 @@ import warnings import weakref -from ansys.mapdl.core import LOG, launch_mapdl +from ansys.mapdl.core import _HAS_ATP, _HAS_TQDM, LOG, launch_mapdl from ansys.mapdl.core.errors import MapdlDidNotStart, MapdlRuntimeError, VersionError from ansys.mapdl.core.launcher import ( LOCALHOST, @@ -38,16 +38,11 @@ get_start_instance, port_in_use, ) -from ansys.mapdl.core.mapdl_grpc import _HAS_TQDM from ansys.mapdl.core.misc import create_temp_dir, threaded, threaded_daemon -try: +if _HAS_ATP: from ansys.tools.path import get_ansys_path, version_from_path - _HAS_ATP = True -except ModuleNotFoundError: - _HAS_ATP = False - if _HAS_TQDM: from tqdm import tqdm diff --git a/tests/conftest.py b/tests/conftest.py index d531594fdd..b0434fe308 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,6 +33,7 @@ import psutil import pytest +from ansys.mapdl.core.helpers import is_installed as has_dependency from ansys.mapdl.core.launcher import is_ansys_process from common import ( Element, @@ -135,23 +136,6 @@ ] -def import_module(requirement): - from importlib import import_module - - if os.name == "nt": - requirement = requirement.replace("-", ".") - return import_module(requirement) - - -def has_dependency(requirement): - try: - requirement = requirement.replace("-", ".") - import_module(requirement) - return True - except ModuleNotFoundError: - return False - - def requires(requirement: str): """Check requirements""" requirement = requirement.lower() @@ -239,7 +223,7 @@ def requires_dependency(dependency: str): from ansys.mapdl.core.examples import vmfiles from ansys.mapdl.core.launcher import get_start_instance, launch_mapdl -if has_dependency("ansys-tools-visualization-interface"): +if has_dependency("ansys-tools-visualization_interface"): import ansys.tools.visualization_interface as viz_interface viz_interface.TESTING_MODE = True