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
|
|
@ -197,6 +197,8 @@ def osbuild_cli() -> int:
|
||||||
for pid in exports:
|
for pid in exports:
|
||||||
export(pid, output_directory, object_store, manifest)
|
export(pid, output_directory, object_store, manifest)
|
||||||
|
|
||||||
|
# TODO: subpress when "--monitor=JSONSeqMontior" is used
|
||||||
|
# or (be explcit) have "--no-summary" or something
|
||||||
if args.json:
|
if args.json:
|
||||||
r = fmt.output(manifest, r, object_store)
|
r = fmt.output(manifest, r, object_store)
|
||||||
json.dump(r, sys.stdout)
|
json.dump(r, sys.stdout)
|
||||||
|
|
|
||||||
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