From 4f84c414b4b025ba0008532b67ead4336cf3ed5a Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Tue, 7 Sep 2021 07:56:58 +0100 Subject: [PATCH] Add ability to execute commands in tee mode (#75) This is a required feature for use within molecule as the executed commands may run for a long period of time and users want to see live progress. Fixes: #40 --- .pre-commit-config.yaml | 1 + constraints.txt | 2 ++ docs/requirements.txt | 2 ++ setup.cfg | 1 + src/ansible_compat/runtime.py | 13 ++++++++++--- test/test_runtime.py | 9 +++++++++ tox.ini | 2 +- 7 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 50ab90f1..3fe3a88c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -84,6 +84,7 @@ repos: - packaging - pytest - pytest-mock + - subprocess-tee>=0.3.3 - types-PyYAML - repo: https://github.com/pre-commit/mirrors-pylint rev: v3.0.0a4 diff --git a/constraints.txt b/constraints.txt index 51ea56b7..bbaff1dc 100644 --- a/constraints.txt +++ b/constraints.txt @@ -44,6 +44,8 @@ pytest-plus==0.2 # via ansible-compat (setup.cfg) pyyaml==5.4.1 # via ansible-compat (setup.cfg) +subprocess-tee==0.3.3 + # via ansible-compat (setup.cfg) toml==0.10.2 # via # pep517 diff --git a/docs/requirements.txt b/docs/requirements.txt index 4ebe5f25..f97ac41f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -92,6 +92,8 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx +subprocess-tee==0.3.3 + # via ansible-compat (setup.cfg) tornado==6.1 # via # livereload diff --git a/setup.cfg b/setup.cfg index db382771..57b44bf1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -64,6 +64,7 @@ setup_requires = install_requires = cached_property ~= 1.5; python_version<="3.7" PyYAML + subprocess-tee >= 0.3.3 [options.extras_require] test = diff --git a/src/ansible_compat/runtime.py b/src/ansible_compat/runtime.py index 6b3478c4..374a675d 100644 --- a/src/ansible_compat/runtime.py +++ b/src/ansible_compat/runtime.py @@ -8,9 +8,10 @@ import shutil import subprocess import tempfile -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union import packaging +import subprocess_tee from ansible_compat.config import ( AnsibleConfig, @@ -116,14 +117,20 @@ def clean(self) -> None: shutil.rmtree(self.cache_dir, ignore_errors=True) def exec( - self, args: Union[str, List[str]], retry: bool = False + self, args: Union[str, List[str]], retry: bool = False, tee: bool = False ) -> CompletedProcess: """Execute a command inside an Ansible environment. :param retry: Retry network operations on failures. + :param tee: Also pass captured stdout/stderr to system while running. """ + if tee: + run_func: Callable[..., CompletedProcess] = subprocess_tee.run + else: + run_func = subprocess.run + for _ in range(self.max_retries + 1 if retry else 1): - result = subprocess.run( + result = run_func( args, universal_newlines=True, check=False, diff --git a/test/test_runtime.py b/test/test_runtime.py index 841ac229..1f3c443a 100644 --- a/test/test_runtime.py +++ b/test/test_runtime.py @@ -616,3 +616,12 @@ def test_install_collection_from_disk_fail() -> None: with pytest.raises(exception, match=msg): # this should call install_collection_from_disk(".") runtime.prepare_environment(install_local=True) + + +def test_runtime_run(runtime: Runtime) -> None: + """.""" + result1 = runtime.exec(["seq", "10"]) + result2 = runtime.exec(["seq", "10"], tee=True) + assert result1.returncode == result2.returncode + assert result1.stderr == result2.stderr + assert result1.stdout == result2.stdout diff --git a/tox.ini b/tox.ini index e16944e7..a18a06c0 100644 --- a/tox.ini +++ b/tox.ini @@ -47,7 +47,7 @@ setenv = PIP_DISABLE_PIP_VERSION_CHECK = 1 PIP_CONSTRAINT = {toxinidir}/constraints.txt PRE_COMMIT_COLOR = always - PYTEST_REQPASS = 70 + PYTEST_REQPASS = 71 FORCE_COLOR = 1 allowlist_externals = sh