scripts: west_commands: runners: nrfutil: provide live feedback
nrfutil runner uses the batch-mode, so no live feedback is provided to
the user. However, batch-mode reports batch progress containing
human-readable strings of the operation being done. This patch changes
the _exec() implementation to parse the subprocess output in real-time,
logging to info the 'batch_update' reports. Note that only the first
batch update of a sequence (percentage = 0) is logged because first,
percentage resolution seems to be pretty bad, and, because logging
messages cannot be easily _appended_.
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
diff --git a/scripts/west_commands/runners/nrfutil.py b/scripts/west_commands/runners/nrfutil.py
index 50db41a..a7ff512 100644
--- a/scripts/west_commands/runners/nrfutil.py
+++ b/scripts/west_commands/runners/nrfutil.py
@@ -10,8 +10,10 @@
import sys
import subprocess
+from runners.core import _DRY_RUN
from runners.nrf_common import NrfBinaryRunner
+
class NrfUtilBinaryRunner(NrfBinaryRunner):
'''Runner front-end for nrfutil.'''
@@ -40,27 +42,34 @@
recover=args.recover)
def _exec(self, args):
- try:
- out = self.check_output(['nrfutil', '--json', 'device'] + args)
- except subprocess.CalledProcessError as e:
- # https://docs.python.org/3/reference/compound_stmts.html#except-clause
- cpe = e
- out = cpe.stdout
- else:
- cpe = None
- finally:
- # https://github.com/ndjson/ndjson-spec
- out = [json.loads(s) for s in
- out.decode(sys.getdefaultencoding()).split('\n') if len(s)]
- self.logger.debug(f'output: {out}')
- if cpe:
- if 'execute-batch' in args:
- for o in out:
- if o['type'] == 'batch_end' and o['data']['error']:
- cpe.returncode = o['data']['error']['code']
- raise cpe
+ jout_all = []
- return out
+ cmd = ['nrfutil', '--json', 'device'] + args
+ self._log_cmd(cmd)
+
+ if _DRY_RUN:
+ return {}
+
+ with subprocess.Popen(cmd, stdout=subprocess.PIPE) as p:
+ for line in iter(p.stdout.readline, b''):
+ # https://github.com/ndjson/ndjson-spec
+ jout = json.loads(line.decode(sys.getdefaultencoding()))
+ jout_all.append(jout)
+
+ if 'x-execute-batch' in args:
+ if jout['type'] == 'batch_update':
+ pld = jout['data']['data']
+ if (
+ pld['type'] == 'task_progress' and
+ pld['data']['progress']['progressPercentage'] == 0
+ ):
+ self.logger.info(pld['data']['progress']['description'])
+ elif jout['type'] == 'batch_end' and jout['data']['error']:
+ raise subprocess.CalledProcessError(
+ jout['data']['error']['code'], cmd
+ )
+
+ return jout_all
def do_get_boards(self):
out = self._exec(['list'])