From be3c91b1317fee58607b47d08df040fe650b307f Mon Sep 17 00:00:00 2001 From: Sergei Trofimov Date: Wed, 2 Aug 2017 12:37:42 +0100 Subject: [PATCH] Device: raise RuntimeError in _check_ready Previously, a AttributeError has been raised. This causes issues when attempting to access some properties that rely on invoking commands on the device. The error would get swallowed up in Python attribute resolution machinery, resulting in an error claiming a missing attribute. For example, for AndroidDevice, "abi" is a property that internally calls getprop(), which executes on the device, and thus requires a connection. If attempting to access device.abi before device.connect() has been invoked, the following sequence takes place 1. Caller tries to access attribute "abi" of device, which resolves to the device.abi property defined in the class. 2. device.abi calls device.getprop() 3. ...which calls device.execute() 4. ...which calls device._check_ready() 5. device._check_ready() raises AttributeError('device not ready.') 6. That gets propagated all the way up to 1., which gets interpreted as attribute not being found. 7. Since AndroidDevice defines a __getattr__(), that gets called next 8. __getattr__() looks for a loaded Device module that has an "abi" attribute. Since there isn't one, it raises AttributeError('abi'). The result is that the error reports a missing "abi" attribute, rather than "device not ready", leading to some fun debugging. Raising RuntimeError (which more appropriate for the circumstances anyway) does not trigger __getattr__, so the correct error message is reported to the user. The text of the message has also been adjusted to make it clearer what has likely gone wrong. --- wlauto/common/linux/device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wlauto/common/linux/device.py b/wlauto/common/linux/device.py index 0044a78e..34968fb2 100644 --- a/wlauto/common/linux/device.py +++ b/wlauto/common/linux/device.py @@ -599,7 +599,7 @@ class BaseLinuxDevice(Device): # pylint: disable=abstract-method def _check_ready(self): if not self._is_ready: - raise AttributeError('Device not ready.') + raise RuntimeError('Device not ready (has connect() been called?)') def _get_core_cluster(self, core): """Returns the first cluster that has cores of the specified type. Raises