tools: add example json-seq render based on tqdm
Add an example render to test/demo how the json-seq based progress
works. It needs the python `tqdm` package for the actual rendering.
See the output with:
```
$ sudo OSBUILD_TEST_STORE=/var/tmp/osbuild-test-store \
python3 -m osbuild --libdir=. --monitor=JSONSeqMonitor --export image \
--output-dir=/tmp/output-dir ./test/data/manifests/fedora-boot.json | ./tools/osbuild-json-seq-progress-example-renderer
```
This commit is contained in:
parent
83e66839bc
commit
f034bef127
2 changed files with 93 additions and 0 deletions
91
tools/osbuild-json-seq-progress-example-renderer
Executable file
91
tools/osbuild-json-seq-progress-example-renderer
Executable file
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/python3
|
||||
#
|
||||
# example how to use the json-seq rendering
|
||||
#
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
import tqdm
|
||||
|
||||
|
||||
class TqdmProgressRenderer:
|
||||
BAR_FMT = "{desc} ({n_fmt}/{total_fmt}): {percentage:3.0f}%|{bar}|{elapsed}"
|
||||
|
||||
def __init__(self, inf, outf):
|
||||
self._pbar = None
|
||||
self._sub_pbar = None
|
||||
self._inf = inf
|
||||
self._outf = outf
|
||||
self._last_done = 0
|
||||
self._last_sub_done = 0
|
||||
|
||||
def _read_json_seq_rec(self):
|
||||
# *sigh* we really should be using a proper json-seq reader here
|
||||
while True:
|
||||
line = self._inf.readline()
|
||||
if not line:
|
||||
return None
|
||||
try:
|
||||
payload = json.loads(line.strip("\x1e"))
|
||||
except json.JSONDecodeError:
|
||||
self.warn(f"WARN: invalid json: {line}")
|
||||
continue
|
||||
return payload
|
||||
|
||||
def warn(self, warn):
|
||||
if self._pbar:
|
||||
self._pbar.write(warn)
|
||||
else:
|
||||
print(warn, file=self._outf)
|
||||
|
||||
def _init_pbar(self, pbar_name, total, pos):
|
||||
pbar = getattr(self, pbar_name, None)
|
||||
if pbar is not None:
|
||||
return
|
||||
pbar = tqdm.tqdm(total=total, position=pos, bar_format=self.BAR_FMT)
|
||||
setattr(self, pbar_name, pbar)
|
||||
|
||||
def render(self):
|
||||
while True:
|
||||
js = self._read_json_seq_rec()
|
||||
if js is None:
|
||||
return
|
||||
|
||||
# main progress
|
||||
main_progress = js.get("progress", {})
|
||||
total = main_progress.get("total", 0)
|
||||
self._init_pbar("_pbar", total, pos=0)
|
||||
|
||||
ctx = js["context"]
|
||||
pipeline_name = ctx.get("pipeline", {}).get("name")
|
||||
if pipeline_name:
|
||||
self._pbar.set_description(f"Pipeline {pipeline_name}")
|
||||
done = main_progress.get("done", 0)
|
||||
if self._last_done < done:
|
||||
self._pbar.update()
|
||||
self._last_done = done
|
||||
# reset sub-progress
|
||||
self._last_sub_done = 0
|
||||
self._sub_pbar = None
|
||||
|
||||
# sub progress
|
||||
sub_progress = main_progress.get("progress")
|
||||
if sub_progress:
|
||||
total = sub_progress.get("total")
|
||||
self._init_pbar("_sub_pbar", total, pos=1)
|
||||
stage_name = ctx.get("pipeline", {}).get("stage", {}).get("name")
|
||||
if stage_name:
|
||||
self._sub_pbar.set_description(f"Stage {stage_name}")
|
||||
sub_done = sub_progress.get("done", 0)
|
||||
if self._last_sub_done < sub_done:
|
||||
self._sub_pbar.update()
|
||||
self._last_sub_done = sub_done
|
||||
|
||||
# (naively) handle messages (could decorate with origin)
|
||||
self._pbar.write(js.get("message", "").strip())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
prg = TqdmProgressRenderer(sys.stdin, sys.stdout)
|
||||
prg.render()
|
||||
Loading…
Add table
Add a link
Reference in a new issue