Skip to content

Commit 8cfa74f

Browse files
committed
Allow direct call of helpers: shortcut to execute
(cherry picked from commit 3ab7700)
1 parent 4c984db commit 8cfa74f

File tree

7 files changed

+102
-2
lines changed

7 files changed

+102
-2
lines changed

README.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,15 @@ This methods are almost the same for `SSHCleint` and `Subprocess`, except specif
153153
raise_on_err=True, # type: bool
154154
)
155155
156+
.. code-block:: python
157+
158+
result = helper( # Lazy way: instances are callable and uses `execute`.
159+
command, # type: str
160+
verbose=False, # type: bool
161+
timeout=1 * 60 * 60, # type: typing.Union[int, float, None]
162+
**kwargs
163+
)
164+
156165
If no STDOUT or STDERR required, it is possible to disable this FIFO pipes via `**kwargs` with flags `open_stdout=False` and `open_stderr=False`.
157166

158167
The next command level uses lower level and kwargs are forwarded, so expected exit codes are forwarded from `check_stderr`.

doc/source/SSHClient.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,21 @@ API: SSHClient and SSHAuth.
160160

161161
.. versionchanged:: 1.2.0 default timeout 1 hour
162162

163+
.. py:method:: __call__(command, verbose=False, timeout=1*60*60, **kwargs)
164+
165+
Execute command and wait for return code.
166+
167+
:param command: Command for execution
168+
:type command: ``str``
169+
:param verbose: Produce log.info records for command call and output
170+
:type verbose: ``bool``
171+
:param timeout: Timeout for command execution.
172+
:type timeout: ``typing.Union[int, float, None]``
173+
:rtype: ExecResult
174+
:raises ExecHelperTimeoutError: Timeout exceeded
175+
176+
.. versionadded:: 1.9.7
177+
163178
.. py:method:: check_call(command, verbose=False, timeout=1*60*60, error_info=None, expected=None, raise_on_err=True, **kwargs)
164179
165180
Execute command and check for return code.

doc/source/Subprocess.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,22 @@ API: Subprocess
8282
.. versionchanged:: 1.2.0 default timeout 1 hour
8383
.. versionchanged:: 1.2.0 stdin data
8484

85+
.. py:method:: __call__(command, verbose=False, timeout=1*60*60, **kwargs)
86+
87+
Execute command and wait for return code.
88+
89+
:param command: Command for execution
90+
:type command: ``str``
91+
:param verbose: Produce log.info records for command call and output
92+
:type verbose: ``bool``
93+
:param timeout: Timeout for command execution.
94+
:type timeout: ``typing.Union[int, float, None]``
95+
:rtype: ExecResult
96+
:raises ExecHelperTimeoutError: Timeout exceeded
97+
98+
.. note:: stdin channel is closed after the input processing
99+
.. versionadded:: 1.9.7
100+
85101
.. py:method:: check_call(command, verbose=False, timeout=1*60*60, error_info=None, expected=None, raise_on_err=True, **kwargs)
86102
87103
Execute command and check for return code.

exec_helpers/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@
5353
"ExecResult",
5454
)
5555

56-
try:
56+
try: # pragma: no cover
5757
__version__ = pkg_resources.get_distribution(__name__).version
58-
except pkg_resources.DistributionNotFound:
58+
except pkg_resources.DistributionNotFound: # pragma: no cover
5959
# package is not installed, try to get from SCM
6060
try:
6161
# noinspection PyPackageRequirements,PyUnresolvedReferences

exec_helpers/api.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,31 @@ def execute(
249249
self.logger.log(level=logging.INFO if verbose else logging.DEBUG, msg=message) # type: ignore
250250
return result
251251

252+
def __call__(
253+
self,
254+
command, # type: str
255+
verbose=False, # type: bool
256+
timeout=constants.DEFAULT_TIMEOUT, # type: typing.Union[int, float, None]
257+
**kwargs
258+
): # type: (...) -> exec_result.ExecResult
259+
"""Execute command and wait for return code.
260+
261+
:param command: Command for execution
262+
:type command: str
263+
:param verbose: Produce log.info records for command call and output
264+
:type verbose: bool
265+
:param timeout: Timeout for command execution.
266+
:type timeout: typing.Union[int, float, None]
267+
:param kwargs: additional parameters for call.
268+
:type kwargs: typing.Any
269+
:return: Execution result
270+
:rtype: ExecResult
271+
:raises ExecHelperTimeoutError: Timeout exceeded
272+
273+
.. versionadded:: 1.9.7
274+
"""
275+
return self.execute(command=command, verbose=verbose, timeout=timeout, **kwargs)
276+
252277
def check_call(
253278
self,
254279
command, # type: str

test/test_ssh_client_execute.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,24 @@ def test_010_execute_together_expected(ssh, ssh2, execute_async, exec_result, ru
508508
)
509509
)
510510
assert results == {(host, port): exec_result, (host2, port): exec_result}
511+
512+
513+
def test_011_call(ssh, ssh_transport_channel, exec_result, run_parameters):
514+
kwargs = {}
515+
if "get_pty" in run_parameters:
516+
kwargs["get_pty"] = run_parameters["get_pty"]
517+
if "width" in run_parameters:
518+
kwargs["width"] = run_parameters["width"]
519+
if "height" in run_parameters:
520+
kwargs["height"] = run_parameters["height"]
521+
522+
res = ssh(
523+
command,
524+
stdin=run_parameters["stdin"],
525+
open_stdout=run_parameters["open_stdout"],
526+
open_stderr=run_parameters["open_stderr"],
527+
**kwargs
528+
)
529+
assert isinstance(res, exec_helpers.ExecResult)
530+
assert res == exec_result
531+
ssh_transport_channel.assert_has_calls((mock.call.status_event.is_set(),))

test/test_subprocess.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,17 @@ def test_008_check_stderr_no_raise(execute, exec_result, logger):
325325
runner.check_stderr(command, stdin=exec_result.stdin, expected=[exec_result.exit_code], raise_on_err=False)
326326
== exec_result
327327
)
328+
329+
330+
def test_009_call(popen, logger, exec_result, run_parameters):
331+
runner = exec_helpers.Subprocess()
332+
res = runner(
333+
command,
334+
stdin=run_parameters["stdin"],
335+
open_stdout=run_parameters["open_stdout"],
336+
open_stderr=run_parameters["open_stderr"],
337+
)
338+
assert isinstance(res, exec_helpers.ExecResult)
339+
assert res == exec_result
340+
popen().wait.assert_called_once_with()
341+
popen().poll.assert_called_once_with()

0 commit comments

Comments
 (0)