From 13cf83b529547e46612ac088f8ec291238c4bb03 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:51:10 +0100 Subject: [PATCH 1/6] tests: removing redundant test --- tests/test_launcher.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tests/test_launcher.py b/tests/test_launcher.py index 167006d497..764d838250 100644 --- a/tests/test_launcher.py +++ b/tests/test_launcher.py @@ -1951,22 +1951,6 @@ def test_check_has_mapdl_failed(): @requires("local") @requires("nostudent") -def test_mapdl_output(tmpdir): - mapdl_output = os.path.join(tmpdir, "apdl.out") - mapdl = launch_mapdl(mapdl_output=mapdl_output) - - assert os.path.exists(mapdl_output) - - with open(mapdl_output, "r") as fid: - content = fid.read() - - assert "Beta activation of the GRPC server." in content - assert "### START GRPC SERVER ###" in content - assert " Server listening on" in content - - mapdl.exit() - - def test_mapdl_output_patch(tmpdir): def submitter(**kwargs): from _io import FileIO From 44a43e9595c9d78613ec87e657911d8ab774b02c Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:09:26 +0000 Subject: [PATCH 2/6] chore: adding changelog file 3596.miscellaneous.md [dependabot-skip] --- doc/changelog.d/3596.miscellaneous.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/3596.miscellaneous.md diff --git a/doc/changelog.d/3596.miscellaneous.md b/doc/changelog.d/3596.miscellaneous.md new file mode 100644 index 0000000000..c39f8cea4f --- /dev/null +++ b/doc/changelog.d/3596.miscellaneous.md @@ -0,0 +1 @@ +feat: redirect MAPDL console output to a file \ No newline at end of file From c99c48bdf3230da25fd62b776e8a18ffdc3b9226 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Mon, 9 Dec 2024 19:10:55 +0100 Subject: [PATCH 3/6] revert: "revert: "Merge branches 'feat/piping-MAPDL-output-to-a-given-file', 'main' and 'main' of https://github.com/ansys/pymapdl" (#3607)" This reverts commit afad43efc8b5ea0bac4f71d9a462e08a1071259a. --- doc/changelog.d/3596.miscellaneous.md | 1 + src/ansys/mapdl/core/launcher.py | 49 +++++++++++++++++++++------ src/ansys/mapdl/core/mapdl_grpc.py | 4 +-- tests/test_launcher.py | 4 +-- 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 doc/changelog.d/3596.miscellaneous.md diff --git a/doc/changelog.d/3596.miscellaneous.md b/doc/changelog.d/3596.miscellaneous.md new file mode 100644 index 0000000000..c39f8cea4f --- /dev/null +++ b/doc/changelog.d/3596.miscellaneous.md @@ -0,0 +1 @@ +feat: redirect MAPDL console output to a file \ No newline at end of file diff --git a/src/ansys/mapdl/core/launcher.py b/src/ansys/mapdl/core/launcher.py index 650ba4a252..83b4dc9ce9 100644 --- a/src/ansys/mapdl/core/launcher.py +++ b/src/ansys/mapdl/core/launcher.py @@ -35,7 +35,7 @@ import subprocess # nosec B404 import threading import time -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union import warnings import psutil @@ -115,6 +115,7 @@ def version_from_path(*args, **kwargs): "license_type", "log_apdl", "loglevel", + "mapdl_output", "mode", "nproc", "override", @@ -437,6 +438,7 @@ def launch_grpc( run_location: str = None, env_vars: Optional[Dict[str, str]] = None, launch_on_hpc: bool = False, + mapdl_output: Optional[str] = None, ) -> subprocess.Popen: """Start MAPDL locally in gRPC mode. @@ -456,6 +458,9 @@ def launch_grpc( If running on an HPC, this needs to be :class:`True` to avoid the temporary file creation on Windows. + mapdl_output : str, optional + Whether redirect MAPDL console output (stdout and stderr) to a file. + Returns ------- subprocess.Popen @@ -487,6 +492,13 @@ def launch_grpc( "\n============" ) + if mapdl_output: + stdout = open(str(mapdl_output), "wb", 0) + stderr = subprocess.STDOUT + else: + stdout = subprocess.PIPE + stderr = subprocess.PIPE + if os.name == "nt": # getting tmp file name if not launch_on_hpc: @@ -505,8 +517,8 @@ def launch_grpc( shell=shell, # sbatch does not work without shell. cwd=run_location, stdin=subprocess.DEVNULL, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + stdout=stdout, + stderr=stderr, env_vars=env_vars, ) @@ -554,7 +566,7 @@ def check_mapdl_launch( if os.name == "posix" and not ON_WSL: LOG.debug("Checking if gRPC server is alive.") - _check_server_is_alive(stdout_queue, run_location, timeout) + _check_server_is_alive(stdout_queue, timeout) except MapdlDidNotStart as e: # pragma: no cover msg = ( @@ -596,7 +608,11 @@ def _check_file_error_created(run_location, timeout): raise MapdlDidNotStart(msg) -def _check_server_is_alive(stdout_queue, run_location, timeout): +def _check_server_is_alive(stdout_queue, timeout): + if not stdout_queue: + LOG.debug("No STDOUT queue. Not checking MAPDL this way.") + return + t0 = time.time() empty_attemps = 3 empty_i = 0 @@ -629,6 +645,9 @@ def _check_server_is_alive(stdout_queue, run_location, timeout): def _get_std_output(std_queue, timeout=1): + if not std_queue: + return [None] + lines = [] reach_empty = False t0 = time.time() @@ -642,10 +661,15 @@ def _get_std_output(std_queue, timeout=1): return lines -def _create_queue_for_std(std): +def _create_queue_for_std( + std: subprocess.PIPE, +) -> Tuple[Optional[Queue[str]], Optional[threading.Thread]]: """Create a queue and thread objects for a given PIPE std""" + if not std: + LOG.debug("No STDOUT. Not checking MAPDL this way.") + return None, None - def enqueue_output(out, queue): + def enqueue_output(out: subprocess.PIPE, queue: Queue[str]) -> None: try: for line in iter(out.readline, b""): queue.put(line) @@ -655,8 +679,8 @@ def enqueue_output(out, queue): # ValueError: PyMemoryView_FromBuffer(): info -> buf must not be NULL pass - q = Queue() - t = threading.Thread(target=enqueue_output, args=(std, q)) + q: Queue[str] = Queue() + t: threading.Thread = threading.Thread(target=enqueue_output, args=(std, q)) t.daemon = True # thread dies with the program t.start() @@ -664,7 +688,7 @@ def enqueue_output(out, queue): def launch_remote_mapdl( - version: str = None, + version: Optional[str] = None, cleanup_on_exit: bool = True, ) -> MapdlGrpc: """Start MAPDL remotely using the product instance management API. @@ -1020,6 +1044,7 @@ def launch_mapdl( version: Optional[Union[int, str]] = None, running_on_hpc: bool = True, launch_on_hpc: bool = False, + mapdl_output: Optional[str] = None, **kwargs: Dict[str, Any], ) -> Union[MapdlGrpc, "MapdlConsole"]: """Start MAPDL locally. @@ -1205,6 +1230,9 @@ def launch_mapdl( to specify the scheduler arguments as a string or as a dictionary. For more information, see :ref:`ref_hpc_slurm`. + mapdl_output : str, optional + Redirect the MAPDL console output to a given file. + kwargs : dict, Optional These keyword arguments are interface-specific or for development purposes. For more information, see Notes. @@ -1575,6 +1603,7 @@ def launch_mapdl( run_location=args["run_location"], env_vars=env_vars, launch_on_hpc=args.get("launch_on_hpc"), + mapdl_output=args.get("mapdl_output"), ) if args["launch_on_hpc"]: diff --git a/src/ansys/mapdl/core/mapdl_grpc.py b/src/ansys/mapdl/core/mapdl_grpc.py index a15982ce12..a3fe1caa54 100644 --- a/src/ansys/mapdl/core/mapdl_grpc.py +++ b/src/ansys/mapdl/core/mapdl_grpc.py @@ -650,7 +650,7 @@ def _read_stds(self): _get_std_output, # Avoid circular import error ) - if self._mapdl_process is None: + if self._mapdl_process is None or not self._mapdl_process.stdout: return self._log.debug("Reading stdout") @@ -2691,7 +2691,7 @@ def _download_as_raw(self, target_name: str) -> str: @property def is_alive(self) -> bool: """True when there is an active connect to the gRPC server""" - if self.channel_state not in ["IDLE", "READY"]: + if self.channel_state not in ["IDLE", "READY", None]: self._log.debug( "MAPDL instance is not alive because the channel is not 'IDLE' o 'READY'." ) diff --git a/tests/test_launcher.py b/tests/test_launcher.py index 806676eb7c..8d5296a828 100644 --- a/tests/test_launcher.py +++ b/tests/test_launcher.py @@ -1951,7 +1951,7 @@ def test_check_has_mapdl_failed(): @requires("local") @requires("nostudent") -def test_mapdl_output_patch(tmpdir): +def test_mapdl_output(tmpdir): def submitter(**kwargs): from _io import FileIO @@ -1975,6 +1975,6 @@ def submitter(**kwargs): assert "Beta activation of the GRPC server." in content assert "### START GRPC SERVER ###" in content - assert " Server listening on" in content + assert "Server listening on" in content mapdl.exit(force=True) From 8ba6520ede3020b500da4c8656ac1271fab571ed Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Thu, 12 Dec 2024 19:16:27 +0100 Subject: [PATCH 4/6] fix: tests --- tests/test_launcher.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/tests/test_launcher.py b/tests/test_launcher.py index 8d5296a828..a98166d26a 100644 --- a/tests/test_launcher.py +++ b/tests/test_launcher.py @@ -1949,32 +1949,39 @@ def test_check_has_mapdl_failed(): assert check_has_mapdl() is False -@requires("local") -@requires("nostudent") -def test_mapdl_output(tmpdir): - def submitter(**kwargs): +@patch("ansys.mapdl.core.launcher._is_ubuntu", lambda *args, **kwargs: True) +@patch("ansys.mapdl.core.launcher.check_mapdl_launch", lambda *args, **kwargs: None) +def test_mapdl_output_pass_arg(tmpdir): + def submitter(*args, **kwargs): from _io import FileIO - from ansys.mapdl.core.launcher import submitter - # Checking we are passing the arguments assert isinstance(kwargs["stdout"], FileIO) assert kwargs["stderr"] is subprocess.STDOUT - return submitter(**kwargs) + return + + with patch("ansys.mapdl.core.launcher.submitter", submitter) as mck_sub: + mapdl_output = os.path.join(tmpdir, "apdl.txt") + args = launch_mapdl(just_launch=True, mapdl_output=mapdl_output) + + assert isinstance(args, list) - with patch("ansys.mapdl.core.launcher.submitter") as mck_sub: - mapdl_output = os.path.join(tmpdir, "apdl.out") - mapdl = launch_mapdl(mapdl_output=mapdl_output) +@requires("local") +@requires("nostudent") +def test_mapdl_output(tmpdir): + mapdl_output = os.path.join(tmpdir, "apdl.txt") + mapdl = launch_mapdl(mapdl_output=mapdl_output, port=50058) assert os.path.exists(mapdl_output) + mapdl.prep7() + mapdl.exit(force=True) + with open(mapdl_output, "r") as fid: content = fid.read() assert "Beta activation of the GRPC server." in content assert "### START GRPC SERVER ###" in content assert "Server listening on" in content - - mapdl.exit(force=True) From f7ce4d5931b17e3d3d7b0a4eb64d46771e92418d Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:46:20 +0100 Subject: [PATCH 5/6] fix: running test only on local --- tests/test_launcher.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_launcher.py b/tests/test_launcher.py index a98166d26a..57fbe2071f 100644 --- a/tests/test_launcher.py +++ b/tests/test_launcher.py @@ -1949,6 +1949,7 @@ def test_check_has_mapdl_failed(): assert check_has_mapdl() is False +@requires("local") @patch("ansys.mapdl.core.launcher._is_ubuntu", lambda *args, **kwargs: True) @patch("ansys.mapdl.core.launcher.check_mapdl_launch", lambda *args, **kwargs: None) def test_mapdl_output_pass_arg(tmpdir): From cf67a6a53d66654320eee1ae284f269c5ebcd9c3 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:32:13 +0100 Subject: [PATCH 6/6] test: adding more tests --- tests/test_launcher.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_launcher.py b/tests/test_launcher.py index 57fbe2071f..83790ba031 100644 --- a/tests/test_launcher.py +++ b/tests/test_launcher.py @@ -1986,3 +1986,21 @@ def test_mapdl_output(tmpdir): assert "Beta activation of the GRPC server." in content assert "### START GRPC SERVER ###" in content assert "Server listening on" in content + + +def test_check_server_is_alive_no_queue(): + from ansys.mapdl.core.launcher import _check_server_is_alive + + assert _check_server_is_alive(None, 30) is None + + +def test_get_std_output_no_queue(): + from ansys.mapdl.core.launcher import _get_std_output + + assert _get_std_output(None, 30) == [None] + + +def test_create_queue_for_std_no_queue(): + from ansys.mapdl.core.launcher import _create_queue_for_std + + assert _create_queue_for_std(None) == (None, None)