Source code for pywebio_battery.interaction

import json

from pywebio.output import *
from pywebio.input import *
from pywebio.session import *
from pywebio.pin import *
from pywebio.utils import random_str
from pywebio.output import Output
import io
from functools import partial
import subprocess
from pywebio.output import OutputPosition

__all__ = ['confirm', 'popup_input', 'redirect_stdout', 'run_shell', 'put_logbox', 'logbox_append']


[docs]def confirm(title, content=None, *, timeout=None): """Show a confirmation modal. :param str title: Model title. :param list/put_xxx() content: Model content. :param None/float timeout: Seconds for operation time out. :return: Return `True` when the "CONFIRM" button is clicked, return `False` when the "CANCEL" button is clicked, return `None` when a timeout is given and the operation times out. """ if content is None: content = [] if not isinstance(content, list): content = [content] action_name = random_str(10) content.append(put_actions(action_name, buttons=[ {'label': 'CONFIRM', 'value': True}, {'label': 'CANCEL', 'value': False, 'color': 'danger'}, ])) popup(title=title, content=content, closable=False) result = pin_wait_change(action_name, timeout=timeout) if result: result = result['value'] close_popup() return result
[docs]def redirect_stdout(output_func=partial(put_text, inline=True)): """Context manager for temporarily redirecting stdout to pywebio. :: with redirect_stdout(): print("Hello world.") """ from contextlib import redirect_stdout class WebIO(io.IOBase): def write(self, content): output_func(content) return redirect_stdout(WebIO())
[docs]def run_shell(cmd, output_func=partial(put_text, inline=True)): """Run command in shell and output the result to pywebio""" process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while True: out = process.stdout.readline() if out: output_func(out.decode('utf8')) if not out and process.poll() is not None: break
[docs]def put_logbox(name, height=None, scope=None, position=OutputPosition.BOTTOM) -> Output: """Output a logbox widget :param str name: :param int height: the height of the widget in pixel """ html = '<pre><code id="webio-logbox-%s"></code></pre>' % name return put_html(html, scope=scope, position=position).style('height:%spx' % height if height else '')
[docs]def logbox_append(name, text): """Append text to a logbox widget""" run_js('$("#webio-logbox-%s").append(text)' % name, text=str(text))
def put_datatable(tdata, header=None, scope=None, position=OutputPosition.BOTTOM, **extra_props) -> Output: """Output datatable The ``tdata`` and ``header`` arguments have the same meaning as for `pywebio.output.put_table()` except that the table cell can't be ``put_xxx()`` call :param extra_props: extra properties passed to the underlying `react data table component <https://github.com/jbetancur/react-data-table-component>`_ . See: https://react-data-table-component.netlify.app/?path=/docs/api-props--page """ if not tdata: return put_text('Empty datatable') # Change ``dict`` row table to list row table if isinstance(tdata[0], dict): if isinstance(header[0], (list, tuple)): header_ = [h[0] for h in header] order = [h[-1] for h in header] else: header_ = order = header tdata = [ [row.get(k, '') for k in order] for row in tdata ] header = header_ else: tdata = [list(i) for i in tdata] # copy data if not header: header, tdata = tdata[0], tdata[1:] dom_id = random_str(10) html = """ <div id="react-app-%s">⌛Loading datatable️</div> <script type="module"> let header=%s, data=%s, extra_props=%s; import React from "https://esm.sh/react"; import ReactDOM from "https://esm.sh/react-dom"; import DataTable from "https://esm.sh/react-data-table-component" data = data.map((value) => { let row = {}; for (let idx in header) row[header[idx]] = value[idx]; return row; }) let columns = header.map((value) => ({ "name": value, "selector": (row) => row[value], "sortable": true, "reorder": true })) ReactDOM.render(React.createElement(DataTable, { "columns": columns, "data": data, "pagination": true, ...extra_props }), document.getElementById("react-app-%s")); </script> """ % (dom_id, json.dumps(header), json.dumps(tdata), json.dumps(extra_props), dom_id) return put_html(html, scope=scope, position=position)