1
0

utils.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from collections import namedtuple
  2. from collections.abc import Mapping, Sequence
  3. from os import path
  4. from tornado import template
  5. from ..utils import isgeneratorfunction, iscoroutinefunction, get_function_name, get_function_doc
  6. AppMeta = namedtuple('App', 'title description')
  7. _here_dir = path.dirname(path.abspath(__file__))
  8. _index_page_tpl = template.Template(open(path.join(_here_dir, 'tpl', 'index.html')).read())
  9. def render_page(app, protocol):
  10. """渲染首页
  11. :param callable app: PyWebIO app
  12. :param str protocol: 'ws'/'http'
  13. :return: bytes
  14. """
  15. assert protocol in ('ws', 'http')
  16. meta = parse_app_metadata(app)
  17. return _index_page_tpl.generate(title=meta.title, description=meta.description, protocol=protocol)
  18. def parse_app_metadata(func):
  19. """解析函数注释文档"""
  20. doc = get_function_doc(func)
  21. doc = doc.strip().split('\n\n', 1)
  22. if len(doc) == 1:
  23. title, description = doc[0] or 'PyWebIO Application', ''
  24. else:
  25. title, description = doc
  26. return AppMeta(title, description)
  27. def _generate_index(applications):
  28. """生成默认的主页任务函数"""
  29. md_text = "## Application index\n"
  30. for name, task in applications.items():
  31. # todo 保留当前页面的设置项
  32. md_text += "- [{name}](?app={name}): {desc}\n".format(name=name, desc=get_function_doc(task))
  33. def index():
  34. from pywebio.output import put_markdown
  35. put_markdown(md_text)
  36. return index
  37. def make_applications(applications):
  38. """格式化 applications 为 任务名->任务函数 的映射, 并提供默认主页
  39. :param applications: 接受 单一任务函数、字典、列表 类型
  40. :return dict: 任务名->任务函数 的映射
  41. """
  42. if isinstance(applications, Sequence): # 列表 类型
  43. applications, app_list = {}, applications
  44. for func in app_list:
  45. name = get_function_name(func)
  46. if name in applications:
  47. raise ValueError("Duplicated application name:%r" % name)
  48. applications[name] = func
  49. elif not isinstance(applications, Mapping): # 单一任务函数 类型
  50. applications = {'index': applications}
  51. # covert dict key to str
  52. applications = {str(k): v for k, v in applications.items()}
  53. for app in applications.values():
  54. assert iscoroutinefunction(app) or isgeneratorfunction(app) or callable(app), \
  55. "Don't support application type:%s" % type(app)
  56. if 'index' not in applications:
  57. applications['index'] = _generate_index(applications)
  58. return applications