diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57cdf09c73..f4033be08b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ on: - main schedule: # * is a special character in YAML so you have to quote this string - - cron: '30 4 * * 1,3,5' + - cron: '30 4 * * *' env: PROJECT_NAME: 'PyMAPDL' @@ -805,7 +805,7 @@ jobs: release: if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - needs: [smoke-tests, docs-build, build-test, build-test-ubuntu] + needs: [smoke-tests, docs-build, build-test, build-test-ubuntu, build-test-ubuntu-minimal] runs-on: ubuntu-latest steps: - name: Set up Python diff --git a/doc/source/api/mapdl.rst b/doc/source/api/mapdl.rst index 430cd88fd6..97b0fef458 100644 --- a/doc/source/api/mapdl.rst +++ b/doc/source/api/mapdl.rst @@ -29,6 +29,7 @@ Mapdl.open_apdl_log Mapdl.open_gui Mapdl.parameters + Mapdl.remove_temp_dir_on_exit Mapdl.result Mapdl.run Mapdl.run_multiline diff --git a/src/ansys/mapdl/core/mapdl_grpc.py b/src/ansys/mapdl/core/mapdl_grpc.py index 2f92dd42fa..a0eaba8132 100644 --- a/src/ansys/mapdl/core/mapdl_grpc.py +++ b/src/ansys/mapdl/core/mapdl_grpc.py @@ -210,15 +210,6 @@ def save_chunks_to_file( return file_size -class RepeatingTimer(threading.Timer): - """Run a function repeately""" - - def run(self): - while not self.finished.is_set(): - self.function(*self.args, **self.kwargs) - self.finished.wait(self.interval) - - class MapdlGrpc(MapdlBase): """This class connects to a GRPC MAPDL server and allows commands to be passed to a persistent session. @@ -383,7 +374,7 @@ def __init__( self._locked: bool = False # being used within MapdlPool self._stub: Optional[mapdl_grpc.MapdlServiceStub] = None self._cleanup: bool = cleanup_on_exit - self.__remove_temp_dir_on_exit: bool = remove_temp_dir_on_exit + self.remove_temp_dir_on_exit: bool = remove_temp_dir_on_exit self._jobname: str = start_parm.get("jobname", "file") self._path: str = start_parm.get("run_location", None) self._busy: bool = False # used to check if running a command on the server @@ -650,7 +641,7 @@ def _raise_custom_stds_errors(self, errs_message): raise MapdlConnectionError( f"A process is already running on the specified port ({self._port}).\n" "Only one usage of each socket address (protocol/network address/port) is normally permitted.\n" - f"\nFull error message:\n{errs_message.split('########',1)[0]}" + f"\nFull error message:\n{errs_message.split('########', 1)[0]}" ) else: @@ -728,7 +719,7 @@ def __repr__(self): info = super().__repr__() return info - def _connect(self, timeout=5, enable_health_check=False): + def _connect(self, timeout=5): """Establish a gRPC channel to a remote or local MAPDL instance. Parameters @@ -761,10 +752,6 @@ def _connect(self, timeout=5, enable_health_check=False): self._timer.daemon = True self._timer.start() - # enable health check - if enable_health_check: - self._enable_health_check() - return True @property @@ -800,54 +787,6 @@ def _get_server_version(self): sver = version_string_as_tuple(verstr) return sver - def _enable_health_check(self): - """Places the status of the health check in _health_response_queue""" - # lazy imports here to speed up module load - from grpc_health.v1 import health_pb2, health_pb2_grpc - - def _consume_responses(response_iterator, response_queue): - try: - for response in response_iterator: - response_queue.put(response) - # NOTE: we're doing absolutely nothing with this as - # this point since the server side health check - # doesn't change state. - except Exception as err: - if self._exiting: - return - self._exited = True - raise MapdlExitedError("Lost connection with MAPDL server") from None - - # enable health check - from queue import Queue - - request = health_pb2.HealthCheckRequest() - self._health_stub = health_pb2_grpc.HealthStub(self._channel) - rendezvous = self._health_stub.Watch(request) - - # health check feature implemented after 2020R2 - try: - status = rendezvous.next() - except Exception as err: - if err.code().name != "UNIMPLEMENTED": - raise err - return - - if status.status != health_pb2.HealthCheckResponse.SERVING: - raise MapdlRuntimeError( - "Unable to enable health check and/or connect to" " the MAPDL server" - ) - - self._health_response_queue = Queue() - - # allow main process to exit by setting daemon to true - thread = threading.Thread( - target=_consume_responses, - args=(rendezvous, self._health_response_queue), - daemon=True, - ) - thread.start() - def _launch(self, start_parm, timeout=10): """Launch a local session of MAPDL in gRPC mode. @@ -1101,15 +1040,15 @@ def exit(self, save=False, force=False): if self._local and self._port in _LOCAL_PORTS: _LOCAL_PORTS.remove(self._port) - def _remove_temp_dir_on_exit(self): + def _remove_temp_dir_on_exit(self, path=None): """Removes the temporary directory created by the launcher. This only runs if the current working directory of MAPDL is within the user temporary directory. """ - if self.__remove_temp_dir_on_exit and self._local: - path = self.directory + if self.remove_temp_dir_on_exit and self._local: + path = path or self.directory tmp_dir = tempfile.gettempdir() ans_temp_dir = os.path.join(tmp_dir, "ansys_") if path.startswith(ans_temp_dir): diff --git a/tests/conftest.py b/tests/conftest.py index 46ab6960c1..9af2dc41ea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -390,6 +390,16 @@ def is_exited(mapdl): assert False # this will fail the test +@pytest.fixture(autouse=True, scope="function") +def run_before_and_after_tests_2(request, mapdl): + """Make sure we are not changing these properties in tests""" + prev = mapdl.is_local + + yield + + assert prev == mapdl.is_local + + @pytest.fixture(scope="session") def mapdl_console(request): if os.name != "posix": @@ -461,7 +471,7 @@ def mapdl(request, tmpdir_factory): ########################################################################### if START_INSTANCE: mapdl._local = True - mapdl.exit() + mapdl.exit(save=True, force=True) assert mapdl._exited assert "MAPDL exited" in str(mapdl) diff --git a/tests/test_grpc.py b/tests/test_grpc.py index 1cc17d7f27..927bf29919 100644 --- a/tests/test_grpc.py +++ b/tests/test_grpc.py @@ -429,11 +429,21 @@ def test_download_result(mapdl, cleared, tmpdir): assert os.path.exists(os.path.join(target_dir, "file.rst")) assert not os.path.exists("file.rst") - mapdl.download_result() # with default argument + mapdl.download_result(preference="rst") # with default argument assert os.path.exists("file.rst") os.remove("file.rst") + mapdl.download_result(preference="rth") + try: + os.remove("file.rst") + except Exception: + pass + try: + os.remove("file.rth") + except Exception: + pass + def test__channel_str(mapdl): assert mapdl._channel_str is not None @@ -548,3 +558,13 @@ def test_input_compatibility_api_change(mapdl): with pytest.raises(ValueError, match="A file name must be supplied."): mapdl.input() + + +@requires("grpc") +@requires("local") +def test__check_stds(mapdl): + """Test that the standard input is checked.""" + + mapdl._read_stds() + assert mapdl._stdout is not None + assert mapdl._stderr is not None diff --git a/tests/test_launcher.py b/tests/test_launcher.py index f11877b6ea..247809b22e 100644 --- a/tests/test_launcher.py +++ b/tests/test_launcher.py @@ -528,3 +528,13 @@ def test_cpu_checks(): machine_cores = psutil.cpu_count(logical=False) with pytest.raises(NotEnoughResources): launch_mapdl(nproc=machine_cores + 2) + + +def test_fail_channel_port(): + with pytest.raises(ValueError): + launch_mapdl(channel="something", port="something") + + +def test_fail_channel_ip(): + with pytest.raises(ValueError): + launch_mapdl(channel="something", ip="something") diff --git a/tests/test_mapdl.py b/tests/test_mapdl.py index d466fba513..ed539abb07 100644 --- a/tests/test_mapdl.py +++ b/tests/test_mapdl.py @@ -26,6 +26,7 @@ from pathlib import Path import re import shutil +import tempfile import time import grpc @@ -2309,3 +2310,26 @@ def test_use_vtk(mapdl): mapdl.eplot() mapdl.use_vtk = prev + + +@requires("local") +def test_remove_temp_dir_on_exit(mapdl, tmpdir): + path = os.path.join(tempfile.gettempdir(), "ansys_" + random_string()) + os.makedirs(path) + filename = os.path.join(path, "file.txt") + with open(filename, "w") as f: + f.write("Hello World") + assert os.path.exists(filename) + + prev = mapdl.remove_temp_dir_on_exit + mapdl.remove_temp_dir_on_exit = True + mapdl._local = True # Sanity check + mapdl._remove_temp_dir_on_exit(path) + mapdl.remove_temp_dir_on_exit = prev + + assert os.path.exists(filename) is False + assert os.path.exists(path) is False + + +def test_sys(mapdl): + assert "hi" in mapdl.sys("echo 'hi'") diff --git a/tests/test_misc.py b/tests/test_misc.py index f46dd03250..eeb71ad0c5 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -283,9 +283,10 @@ def test_load_file_local(mapdl, tmpdir, file_): load_file(mapdl, file_path, priority_mapdl_file=False) if mapdl._local: - with open(os.path.join(mapdl.directory, file_), "r") as fid: + file_name__ = os.path.join(mapdl.directory, file_) + with open(file_name__, "r") as fid: assert "not that empty" in fid.read() - os.remove(file_) + os.remove(file_name__) else: mapdl.download(file_) with open(os.path.join(file_), "r") as fid: