Skip to content

Commit d73e95f

Browse files
target: Add Target.read_tree_values_flat(decode=None) parameter
Allow not decoding the values and keep them as bytestring, for when e.g. sysfs files have binary content (e.g. exposed from device tree) True decodes the bytestring, None attempts to decode and False does not decode.
1 parent 003fc03 commit d73e95f

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

devlib/target.py

+25-14
Original file line numberDiff line numberDiff line change
@@ -1348,7 +1348,7 @@ async def read_tree_tar_flat(self, path, depth=1, check_exit_code=True,
13481348
# if it is a file and not a folder
13491349
if content_f:
13501350
content = content_f.read()
1351-
if decode_unicode:
1351+
if decode_unicode in (True, None):
13521352
try:
13531353
content = content.decode('utf-8').strip()
13541354
if strip_null_chars:
@@ -1362,27 +1362,37 @@ async def read_tree_tar_flat(self, path, depth=1, check_exit_code=True,
13621362
return result
13631363

13641364
@asyn.asyncf
1365-
async def read_tree_values_flat(self, path, depth=1, check_exit_code=True):
1365+
async def read_tree_values_flat(self, path, depth=1, check_exit_code=True, decode=None):
13661366
self.async_manager.track_access(
13671367
asyn.PathAccess(namespace='target', path=path, mode='r')
13681368
)
13691369
command = 'read_tree_values {} {}'.format(quote(path), depth)
13701370
output = await self._execute_util.asyn(command, as_root=self.is_rooted,
1371-
check_exit_code=check_exit_code)
1372-
1371+
check_exit_code=check_exit_code, decode=False)
13731372
accumulator = defaultdict(list)
1374-
for entry in output.strip().split('\n'):
1375-
if ':' not in entry:
1373+
for entry in output.strip().splitlines():
1374+
if b':' not in entry:
13761375
continue
1377-
path, value = entry.strip().split(':', 1)
1376+
path, value = entry.strip().split(b':', 1)
13781377
accumulator[path].append(value)
13791378

1380-
result = {k: '\n'.join(v).strip() for k, v in accumulator.items()}
1379+
if decode is None:
1380+
def do_decode(b):
1381+
try:
1382+
return b.decode()
1383+
except UnicodeDecodeError:
1384+
return b
1385+
elif decode:
1386+
do_decode = lambda b: b.decode()
1387+
else:
1388+
do_decode = lambda b: b
1389+
1390+
result = {k.decode(): do_decode(b'\n'.join(v).strip()) for k, v in accumulator.items()}
13811391
return result
13821392

13831393
@asyn.asyncf
13841394
async def read_tree_values(self, path, depth=1, dictcls=dict,
1385-
check_exit_code=True, tar=False, decode_unicode=True,
1395+
check_exit_code=True, tar=False, decode_unicode=None,
13861396
strip_null_chars=True):
13871397
"""
13881398
Reads the content of all files under a given tree
@@ -1400,7 +1410,7 @@ async def read_tree_values(self, path, depth=1, dictcls=dict,
14001410
:returns: a tree-like dict with the content of files as leafs
14011411
"""
14021412
if not tar:
1403-
value_map = await self.read_tree_values_flat.asyn(path, depth, check_exit_code)
1413+
value_map = await self.read_tree_values_flat.asyn(path, depth, check_exit_code, decode=decode_unicode)
14041414
else:
14051415
value_map = await self.read_tree_tar_flat.asyn(path, depth, check_exit_code,
14061416
decode_unicode,
@@ -1436,14 +1446,15 @@ async def _setup_shutils(self):
14361446

14371447
@asyn.asyncf
14381448
@call_conn
1439-
async def _execute_util(self, command, timeout=None, check_exit_code=True, as_root=False):
1449+
async def _execute_util(self, command, timeout=None, check_exit_code=True, as_root=False, decode=True):
14401450
command = '{} sh {} {}'.format(quote(self.busybox), quote(self.shutils), command)
1441-
return await self.execute.asyn(
1442-
command,
1451+
stdout, stderr = await self.execute_raw.asyn(
1452+
command=command,
14431453
timeout=timeout,
14441454
check_exit_code=check_exit_code,
1445-
as_root=as_root
1455+
as_root=as_root,
14461456
)
1457+
return stdout.decode() if decode else stdout
14471458

14481459
async def _extract_archive(self, path, cmd, dest=None):
14491460
cmd = '{} ' + cmd # busybox

0 commit comments

Comments
 (0)