output.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import json
  2. import logging
  3. from collections.abc import Mapping
  4. from base64 import b64encode
  5. from .framework import Global, Task
  6. from .input_ctrl import send_msg, single_input, input_control, next_event, run_async
  7. import asyncio
  8. import inspect
  9. def set_title(title):
  10. send_msg('output_ctl', dict(title=title))
  11. def text_print(text, *, ws=None):
  12. if text is None:
  13. text = ''
  14. msg = dict(command="output", spec=dict(content=text, type='text'))
  15. (ws or Global.active_ws).write_message(json.dumps(msg))
  16. def json_print(obj):
  17. text = "```\n%s\n```" % json.dumps(obj, indent=4, ensure_ascii=False)
  18. text_print(text)
  19. put_markdown = text_print
  20. def put_table(tdata):
  21. """
  22. | \| | | |
  23. | ---- | ---- | ---- | ---- |
  24. | | | | |
  25. | | | | |
  26. | | | | |
  27. :param tdata:
  28. :return:
  29. """
  30. def quote(data):
  31. return data.replace('|', r'\|')
  32. header = "|%s|" % "|".join(map(quote, tdata[0]))
  33. res = [header]
  34. res.append("|%s|" % "|".join(['----'] * len(tdata[0])))
  35. for tr in tdata[1:]:
  36. t = "|%s|" % "|".join(map(quote, tr))
  37. res.append(t)
  38. text_print('\n'.join(res))
  39. def buttons(buttons, onclick_coro, save=None, mutex_mode=False):
  40. """
  41. :param buttons: button列表, button可用形式:
  42. {value:, label:, }
  43. (value, label,)
  44. value 单值,label等于value
  45. :param onclick_coro: CallBack(data, save) todo 允许onclick_coro非coro
  46. :param save:
  47. :param mutex_mode: 互斥模式,回调在运行过程中,无法响应同一回调
  48. :return:
  49. """
  50. btns = []
  51. for btn in buttons:
  52. if isinstance(btn, Mapping):
  53. assert 'value' in btn and 'label' in btn, 'actions item must have value and label key'
  54. elif isinstance(btn, list):
  55. assert len(btn) == 2, 'actions item format error'
  56. btn = dict(zip(('value', 'label'), btn))
  57. else:
  58. btn = dict(value=btn, label=btn)
  59. btns.append(btn)
  60. async def callback_coro():
  61. while True:
  62. event = await next_event()
  63. assert event['event'] == 'callback'
  64. coro = None
  65. if asyncio.iscoroutinefunction(onclick_coro):
  66. coro = onclick_coro(event['data'], save)
  67. elif inspect.isgeneratorfunction(onclick_coro):
  68. coro = asyncio.coroutine(onclick_coro)(save, event['data'])
  69. else:
  70. onclick_coro(event['data'], save)
  71. if coro is not None:
  72. if mutex_mode:
  73. await coro
  74. else:
  75. run_async(coro)
  76. print('Global.active_ws', Global.active_ws)
  77. callback = Task(callback_coro(), Global.active_ws)
  78. callback.coro.send(None) # 激活,Non't callback.step() ,导致嵌套调用step todo 与inactive_coro_instances整合
  79. # callback_id = callback.coro_id
  80. Global.active_ws.coros[callback.coro_id] = callback
  81. send_msg('output', dict(type='buttons', callback_id=callback.coro_id, buttons=btns))
  82. def put_file(name, content):
  83. """
  84. :param name: file name
  85. :param content: bytes-like object
  86. :return:
  87. """
  88. content = b64encode(content).decode('ascii')
  89. send_msg('output', dict(type='file', name=name, content=content))