1
0

doc_demo.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. """
  2. Run the example code in the documentation online
  3. """
  4. import base64
  5. from functools import partial
  6. from os import path, listdir
  7. from pywebio import start_server
  8. from pywebio.platform import config
  9. from pywebio.session import local as session_local, info as session_info
  10. import pywebio_battery
  11. ##########################################
  12. # Pre-import modules for demo
  13. import time # lgtm [py/unused-import]
  14. from pywebio.input import *
  15. from pywebio.output import *
  16. from pywebio.session import *
  17. from pywebio.pin import *
  18. from pywebio_battery import *
  19. ##########################################
  20. here_dir = path.dirname(path.abspath(__file__))
  21. playground_host = "https://play.pywebio.online"
  22. def t(eng, chinese):
  23. """return English or Chinese text according to the user's browser language"""
  24. return chinese if 'zh' in session_info.user_language else eng
  25. def playground(code):
  26. pre_import = PRE_IMPORT
  27. battery_apis = pywebio_battery.__all__
  28. if 'pywebio_battery import' not in code and any(api in code for api in battery_apis):
  29. pre_import += 'from pywebio_battery import *\n'
  30. code = f"{pre_import}\n{code}"
  31. encode = base64.b64encode(code.encode('utf8')).decode('utf8')
  32. url = f"{playground_host}/#{encode}"
  33. run_js('window.open(url)', url=url)
  34. def gen_snippets(code):
  35. code = code.replace('# ..demo-only', '')
  36. code = '\n'.join(i for i in code.splitlines() if '# ..doc-only' not in i)
  37. parts = code.split('\n## ----\n')
  38. for p in parts:
  39. yield p.strip('\n')
  40. def run_code(code, scope):
  41. with use_scope(scope):
  42. try:
  43. """
  44. Remember that at module level, globals and locals are the same dictionary.
  45. If exec gets two separate objects as globals and locals,
  46. the code will be executed as if it were embedded in a class definition.
  47. https://docs.python.org/3/library/functions.html#exec
  48. """
  49. exec(code, session_local.globals)
  50. except Exception as e:
  51. toast('Exception occurred: "%s:%s"' % (type(e).__name__, e), color='error')
  52. PRE_IMPORT = """from pywebio.input import *
  53. from pywebio.output import *
  54. from pywebio.session import *
  55. from pywebio.pin import *
  56. from pywebio import start_server
  57. """
  58. APP_TPL = f"""{PRE_IMPORT}
  59. def main():
  60. %s
  61. start_server(main, port=8080, debug=True)
  62. """
  63. CLIPBOARD_SETUP = """
  64. window.writeText = function(text) {
  65. const input = document.createElement('textarea');
  66. input.style.opacity = 0;
  67. input.style.position = 'absolute';
  68. input.style.left = '-100000px';
  69. document.body.appendChild(input);
  70. input.value = text;
  71. input.select();
  72. input.setSelectionRange(0, text.length);
  73. document.execCommand('copy');
  74. document.body.removeChild(input);
  75. return true;
  76. }
  77. """
  78. def copytoclipboard(code):
  79. code = APP_TPL % code.replace('\n', '\n ')
  80. run_js("writeText(text)", text=code)
  81. toast('The code has been copied to the clipboard')
  82. def handle_code(code, title):
  83. run_js(CLIPBOARD_SETUP)
  84. session_local.globals = dict(globals())
  85. if title:
  86. put_markdown('## %s' % title)
  87. for p in gen_snippets(code):
  88. with use_scope() as scope:
  89. put_code(p, 'python')
  90. put_buttons(
  91. [t('Run', '运行'),
  92. t("Edit", '编辑'),
  93. t("Copy to clipboard", '复制代码')],
  94. onclick=[
  95. partial(run_code, code=p, scope=scope),
  96. partial(playground, code=p),
  97. partial(copytoclipboard, code=p)
  98. ]
  99. )
  100. put_markdown('----')
  101. def get_app():
  102. """PyWebIO demos from document
  103. Run the demos from the document online.
  104. """
  105. app = {}
  106. try:
  107. demos = listdir(path.join(here_dir, 'doc_demos'))
  108. except Exception:
  109. demos = []
  110. for name in demos:
  111. code = open(path.join(here_dir, 'doc_demos', name)).read()
  112. title, code = code.split('\n\n', 1)
  113. app[name] = partial(handle_code, code=code, title=title)
  114. app[name] = config(title=name, description=title)(app[name])
  115. return app
  116. main = get_app()
  117. if __name__ == '__main__':
  118. start_server(main, debug=True, port=8080)