Use exceptions instead of prints
Change-Id: Ib60369ebd8f7346b7edffcd21fd9c097da84b1ef
diff --git a/deploy.py b/deploy.py
index 9e7976a..437548d 100755
--- a/deploy.py
+++ b/deploy.py
@@ -21,7 +21,27 @@
]
-def adb(*args, serial = None):
+class HostCommandError(BaseException):
+ """An error happened while issuing a command on the host."""
+ def __init__(self, command, error_message):
+ self.command = command
+ self.error_message = error_message
+ message = 'Command `{}` failed: {}'.format(command, error_message)
+ super(HostCommandError, self).__init__(message)
+
+
+class DeviceCommandError(BaseException):
+ """An error happened while sending a command to a device."""
+ def __init__(self, serial, command, error_message):
+ self.serial = serial
+ self.command = command
+ self.error_message = error_message
+ message = 'Command `{}` failed on {}: {}'.format(
+ command, serial, error_message)
+ super(DeviceCommandError, self).__init__(message)
+
+
+def adb(*args, serial = None, raise_on_error = True):
"""Run ADB command attached to serial.
Example:
@@ -35,50 +55,85 @@
List of options to ADB (including command).
:param str serial:
Identifier for ADB connection to device.
+ :param raise_on_error bool:
+ Whether to raise a DeviceCommandError exception if the return code is
+ less than 0.
:returns subprocess.CompletedProcess:
Completed process.
+ :raises DeviceCommandError:
+ If the command failed.
"""
# Make sure the adb server is started to avoid the infamous "out of date"
# message that pollutes stdout.
- subprocess.run(
+ ret = subprocess.run(
['adb', 'start-server'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True)
+ if ret.returncode < 0:
+ if raise_on_error:
+ raise DeviceCommandError(
+ serial if serial else '??', str(args), ret.stderr)
+ else:
+ return None
command = ['adb']
if serial:
command += ['-s', serial]
if args:
command += list(args)
- return subprocess.run(
+ ret = subprocess.run(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True)
+ if raise_on_error and ret.returncode < 0:
+ raise DeviceCommandError(
+ serial if serial else '??', str(args), ret.stderr)
-def aapt(*args):
+ return ret
+
+
+def aapt(*args, raise_on_error = True):
"""Run an AAPT command.
:param *args:
The AAPT command with its options.
+ :param raise_on_error bool:
+ Whether to raise a DeviceCommandError exception if the return code is
+ less than 0.
:returns subprocess.CompletedProcess:
Completed process.
+ :raises HostCommandError:
+ If the command failed.
"""
command = ['aapt']
if args:
command += list(args)
- return subprocess.run(
+ ret = subprocess.run(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True)
+ if raise_on_error and ret.returncode < 0:
+ raise HostCommandError(str(args), ret.stderr)
+
+ return ret
+
def force_awake(serial, always=True):
- """Force the device to stay awake."""
- return adb('shell', 'svc power stayon {}'.format(
+ """Force the device to stay awake.
+
+ Raises:
+ DeviceCommandError: If the underlying adb command failed.
+ """
+ adb('shell', 'svc power stayon {}'.format(
'true' if always else 'false'), serial=serial)
def unlock(serial):
- """Wake-up the device and unlock it."""
+ """Wake-up the device and unlock it.
+
+ Raises:
+ DeviceCommandError: If the underlying adb commands failed.
+ """
adb('shell', 'input keyevent KEYCODE_POWER', serial=serial)
time.sleep(1)
adb('shell', 'input keyevent KEYCODE_MENU', serial=serial)
@@ -99,6 +154,7 @@
Key of property to get.
:returns str:
Value of system property.
+ :raise DeviceCommandError: If the underlying adb command failed.
"""
process = adb('shell', 'getprop', key, serial=serial)
return process.stdout.strip()
@@ -115,49 +171,43 @@
Identifier for ADB connection to device.
:returns bool:
True if device runs GMS, false otherwise.
+ :raise DeviceCommandError: If the underlying adb command failed.
"""
return getprop(serial, 'ro.build.id').startswith('FP2-gms-')
def uninstall_apk(serial, filename, prebuilts_dir):
- """Uninstall apk from prebuilts_dir on device."""
+ """Uninstall apk from prebuilts_dir on device.
+
+ Raises:
+ ValueError: If the package name could not be read from the apk.
+ DeviceCommandError: If the uninstall command failed.
+ """
ret = aapt('dump', 'badging', '{}/{}'.format(prebuilts_dir, filename))
- if 0 < ret.returncode:
- print('Could retrieve app `{}` info, error was: {}'.format(
- filename, ret.stderr), file=sys.stderr)
- else:
- package = None
- for line in ret.stdout.splitlines():
- if line.startswith('package'):
- for token in line.split(' '):
- if token.startswith('name='):
- # Extract the package name out of the token
- # (name='some.package.name')
- package = token[6:-1]
- break
- if not package:
- print('Could not find package of app `{}`'.format(filename),
- file=sys.stderr)
- else:
- print('Uninstalling `{}`'.format(package))
- ret = adb('uninstall', package, serial=serial)
- if 0 < ret.returncode:
- print('Could not uninstall app `{}`, error was: {}'.format(
- filename, ret.stderr), file=sys.stderr)
- else:
- print('App `{}` uninstalled.'.format(filename))
+ package = None
+ for line in ret.stdout.splitlines():
+ if line.startswith('package'):
+ for token in line.split(' '):
+ if token.startswith('name='):
+ # Extract the package name out of the token
+ # (name='some.package.name')
+ package = token[6:-1]
+ break
+ if not package:
+ raise ValueError('Could not find package of app `{}`'.format(
+ filename))
+
+ adb('uninstall', package, serial=serial)
def install_apk(serial, filename, prebuilts_dir):
- """Install apk from prebuilts_dir on device."""
- print('Installing {}.'.format(filename))
+ """Install apk from prebuilts_dir on device.
+
+ Raises:
+ DeviceCommandError: If the install command failed.
+ """
path = os.path.join(prebuilts_dir, filename)
- ret = adb('install', '-r', path, serial=serial)
- if 0 < ret.returncode:
- print('Could not install app `{}`, error was: {}'.format(
- filename, ret.stderr), file=sys.stderr)
- else:
- print('App `{}` installed.'.format(filename))
+ adb('install', '-r', path, serial=serial)
# Prepare the DUT
@@ -166,26 +216,20 @@
# Uninstall the smartviser apps
for app in PREBUILT_APKS + [PREBUILT_PROXY_APKS[flavour]]:
+ print('Uninstalling `{}`…'.format(app))
uninstall_apk(serial, app, prebuilts_dir)
# Copy the scenarios
- ret = adb('push', scenarios_dir, '/sdcard/viser', serial=serial)
- if 0 < ret.returncode:
- print('Could not push the scenarios, error was: {}'.format(ret.stderr),
- file=sys.stderr)
- else:
- print('Scenarios pushed.')
+ print('Pushing scenarios from `{}`…'.format(scenarios_dir))
+ adb('push', scenarios_dir, '/sdcard/viser', serial=serial)
# Copy the scenarios data
- ret = adb('push', data_dir, '/sdcard/viser/data', serial=serial)
- if 0 < ret.returncode:
- print('Could not push the scenarios data, error was: {}'.format(ret.stderr),
- file=sys.stderr)
- else:
- print('Scenarios data pushed.')
+ print('Pushing scenarios data from `{}`…'.format(data_dir))
+ adb('push', data_dir, '/sdcard/viser/data', serial=serial)
# Install the smartviser apps (starting with the proxy app)
for app in [PREBUILT_PROXY_APKS[flavour]] + PREBUILT_APKS:
+ print('Installing `{}`…'.format(app))
install_apk(serial, app, prebuilts_dir)
@@ -288,36 +332,39 @@
serials.append(serial)
for serial in serials:
- print('Configuring device {}'.format(serial))
+ print('Configuring device {}…'.format(serial))
dut = Device(serial)
- # Make sure the screen stays on - we're going to use UI automation
- force_awake(serial)
- unlock(serial)
+ try:
+ # Make sure the screen stays on - we're going to use UI automation
+ force_awake(serial)
+ unlock(serial)
- # Push the scenarios, their data, and install the apps
- prepare_dut(serial, '../scenarios', '../scenarios-data', PREBUILTS_PATH)
+ # Push the scenarios, their data, and install the apps
+ prepare_dut(
+ serial, '../scenarios', '../scenarios-data', PREBUILTS_PATH)
- # Start the viser app
- ret = adb(
+ # Start the viser app
+ adb(
'shell', 'monkey', '-p', 'com.lunarlabs.panda', '-c',
'android.intent.category.LAUNCHER', '1', serial=serial)
- if 0 < ret.returncode:
- print('Could not start the viser app, error was: {}'.format(app,
- ret.stderr), file=sys.stderr)
- exit(-1)
- configure_perms(dut)
+ configure_perms(dut)
- # TODO DO NOT DO THE FOLLOWING IF NO SIM CARD IS IN THE DUT
- # time.sleep(10)
- # configure_sms(dut)
+ # TODO DO NOT DO THE FOLLOWING IF NO SIM CARD IS IN THE DUT
+ # time.sleep(10)
+ # configure_sms(dut)
- configure_settings(dut)
-
- # Leave the device alone now
- force_awake(serial, always=False)
+ configure_settings(dut)
+ except (HostCommandError, DeviceCommandError) as e:
+ print('ERROR {}'.format(e), file=sys.stderr)
+ finally:
+ try:
+ # Leave the device alone now
+ force_awake(serial, always=False)
+ except DeviceCommandError as e:
+ print('WARNING {}'.format(e), file=sys.stderr)
if __name__ == '__main__':