Skip to content

Commit 003fc03

Browse files
devlib: Add Target.execute_raw() method
Add a Target.execute_raw() method that provides raw stderr and stdout output as bytestring. This allows dealing with binary data in the output of commands and also splitting stdout stderr.
1 parent b7ef2dc commit 003fc03

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

devlib/target.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@
5454
from devlib.exception import (DevlibTransientError, TargetStableError,
5555
TargetNotRespondingError, TimeoutError,
5656
TargetTransientError, KernelConfigKeyError,
57-
TargetError, HostError, TargetCalledProcessError) # pylint: disable=redefined-builtin
57+
TargetError, HostError, TargetCalledProcessError,
58+
TargetStableCalledProcessError, TargetTransientCalledProcessError,
59+
) # pylint: disable=redefined-builtin
5860
from devlib.utils.ssh import SshConnection
5961
from devlib.utils.android import AdbConnection, AndroidProperties, LogcatMonitor, adb_command, adb_disconnect, INTENT_FLAGS
6062
from devlib.utils.misc import memoized, isiterable, convert_new_lines, groupby_value
@@ -888,6 +890,32 @@ def _execute(self, command, timeout=None, check_exit_code=True,
888890
check_exit_code=check_exit_code, as_root=as_root,
889891
strip_colors=strip_colors, will_succeed=will_succeed)
890892

893+
@asyn.asyncf
894+
@call_conn
895+
async def execute_raw(self, command, *, timeout=None, check_exit_code=True,
896+
as_root=False, will_succeed=False, force_locale='C'):
897+
bg = self.background(
898+
command=command,
899+
as_root=as_root,
900+
force_locale=force_locale,
901+
)
902+
903+
# TODO: make BackgroundCommand API async-friendly and use that
904+
with bg as bg:
905+
try:
906+
# Timeout on communicate() usually saves a thread
907+
stdout, stderr = bg.communicate(timeout=timeout)
908+
except subprocess.CalledProcessError as e:
909+
if check_exit_code:
910+
if will_succeed:
911+
raise TargetTransientCalledProcessError(*e.args)
912+
else:
913+
raise
914+
else:
915+
return (e.stdout, e.stderr)
916+
else:
917+
return (stdout, stderr)
918+
891919
execute = asyn._AsyncPolymorphicFunction(
892920
asyn=_execute_async.asyn,
893921
blocking=_execute,

doc/target.rst

+6-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ Target
275275
notably paramiko + OpenSSH combination having performance issues when
276276
pulling big files from sysfs.
277277

278-
.. method:: Target.execute(command [, timeout [, check_exit_code [, as_root [, strip_colors [, will_succeed [, force_locale]]]]]])
278+
.. method:: Target.execute(command [, timeout [, check_exit_code [, as_root [, strip_colors [, will_succeed [, force_locale, ]]]]]])
279279

280280
Execute the specified command on the target device and return its output.
281281

@@ -299,6 +299,11 @@ Target
299299
command to get predictable output that can be more safely parsed.
300300
If ``None``, no locale is prepended.
301301

302+
.. method:: Target.execute_raw(command [, timeout [, check_exit_code [, as_root [, will_succeed [, force_locale, ]]]]])
303+
304+
Same as :meth:`Target.execute` except that it will return a ``tuple(stdout, stderr)`` of
305+
bytestrings.
306+
302307
.. method:: Target.background(command [, stdout [, stderr [, as_root, [, force_locale [, timeout]]])
303308

304309
Execute the command on the target, invoking it via subprocess on the host.

0 commit comments

Comments
 (0)