1
0
Эх сурвалжийг харах

maint: move `hold()` to session module

wangweimin 5 жил өмнө
parent
commit
a96caa931c

+ 6 - 1
docs/guide.rst

@@ -131,7 +131,7 @@ PyWebIO提供了一些便捷函数来输出表格、链接等格式::
 
 PyWebIO提供的全部输出函数请见 :doc:`pywebio.output </output>` 模块
 
-输出事件回调
+事件回调
 ^^^^^^^^^^^^^^
 
 PyWebIO把程序与用户的交互分成了输入和输出两部分:输入函数为阻塞式调用,在用户提交表单之前将不会返回;对输出函数的调用将会立刻将内容输出至浏览器。
@@ -161,6 +161,9 @@ PyWebIO把程序与用户的交互分成了输入和输出两部分:输入函
         put_text("You click %s button" % btn_val)
     put_buttons(['A', 'B', 'C'], onclick=btn_click)
 
+.. note::
+   在PyWebIO会话(关于会话的概念见下文 :ref:`Server and script mode <server_and_script_mode>` )结束后,事件回调也将不起作用,你可以在任务函数末尾处使用 :func:`pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器前,事件回调将一直可用。
+
 锚点
 ^^^^^^^^^^^^^^
 就像在控制台输出文本一样,PyWebIO默认在页面的末尾输出各种内容,你可以使用锚点来改变这一行为。
@@ -211,6 +214,8 @@ PyWebIO支持两种外观:输出区固定高度/可变高度。
 在不指定锚点进行输出时,PyWebIO默认在输出完毕后自动将页面滚动到页面最下方;在调用输入函数时,也会将页面滚动到表单处。
 通过调用 `set_auto_scroll_bottom(False) <pywebio.output.set_auto_scroll_bottom>` 来关闭自动滚动。
 
+.. _server_and_script_mode:
+
 Server mode & Script mode
 ------------------------------------
 

+ 1 - 3
pywebio/__init__.py

@@ -1,9 +1,7 @@
 from .platform import start_server
 from . import input
 from . import output
-from .session import (
-    run_async, run_asyncio_coroutine, register_thread, defer_call
-)
+from .session import *
 from .exceptions import SessionException, SessionClosedException, SessionNotFoundException
 from .utils import STATIC_PATH
 

+ 3 - 9
pywebio/input.py

@@ -28,7 +28,7 @@ import logging
 from base64 import b64decode
 from collections.abc import Mapping
 
-from .io_ctrl import single_input, input_control, _hold
+from .io_ctrl import single_input, input_control
 
 logger = logging.getLogger(__name__)
 
@@ -42,7 +42,8 @@ SELECT = 'select'
 TEXTAREA = 'textarea'
 
 __all__ = ['TEXT', 'NUMBER', 'FLOAT', 'PASSWORD', 'input', 'textarea', 'select',
-           'checkbox', 'radio', 'actions', 'file_upload', 'input_group', 'hold']
+           'checkbox', 'radio', 'actions', 'file_upload', 'input_group']
+
 
 
 def _parse_args(kwargs):
@@ -356,13 +357,6 @@ def file_upload(label='', accept=None, name=None, placeholder='Choose file', req
     return single_input(item_spec, valid_func, read_file)
 
 
-def hold():
-    """保持会话,直到用户手动关闭浏览器,
-    此时函数抛出 `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常
-    """
-    return _hold()
-
-
 def input_group(label='', inputs=None, valid_func=None, cancelable=False):
     r"""输入组。向页面上展示一组输入
 

+ 2 - 28
pywebio/io_ctrl.py

@@ -4,10 +4,8 @@
 
 """
 import logging
-from functools import wraps
 
-from .session import get_session_implement, CoroutineBasedSession, get_current_task_id, get_current_session
-from .utils import run_as_function, to_coroutine
+from .session import chose_impl, next_client_event, get_current_task_id, get_current_session
 
 logger = logging.getLogger(__name__)
 
@@ -17,30 +15,6 @@ def send_msg(cmd, spec=None):
     get_current_session().send_task_command(msg)
 
 
-def chose_impl(gen_func):
-    @wraps(gen_func)
-    def inner(*args, **kwargs):
-        gen = gen_func(*args, **kwargs)
-        if get_session_implement() == CoroutineBasedSession:
-            return to_coroutine(gen)
-        else:
-            return run_as_function(gen)
-
-    return inner
-
-
-@chose_impl
-def next_event():
-    res = yield get_current_session().next_client_event()
-    return res
-
-
-@chose_impl
-def _hold():
-    while True:
-        yield next_event()
-
-
 @chose_impl
 def single_input(item_spec, valid_func, preprocess_func):
     """
@@ -112,7 +86,7 @@ def input_event_handle(item_valid_funcs, form_valid_funcs, preprocess_funcs):
     :return:
     """
     while True:
-        event = yield next_event()
+        event = yield next_client_event()
         event_name, event_data = event['event'], event['data']
         if event_name == 'input_event':
             input_event = event_data['event_name']

+ 34 - 2
pywebio/session/__init__.py

@@ -3,6 +3,7 @@ r"""
 .. autofunction:: run_asyncio_coroutine
 .. autofunction:: register_thread
 .. autofunction:: defer_call
+.. autofunction:: hold
 
 .. autoclass:: pywebio.session.coroutinebased.TaskHandle
    :members:
@@ -15,12 +16,12 @@ from .base import AbstractSession
 from .coroutinebased import CoroutineBasedSession
 from .threadbased import ThreadBasedSession, ScriptModeSession
 from ..exceptions import SessionNotFoundException
-from ..utils import iscoroutinefunction, isgeneratorfunction
+from ..utils import iscoroutinefunction, isgeneratorfunction, run_as_function, to_coroutine
 
 # 当前进程中正在使用的会话实现的列表
 _active_session_cls = []
 
-__all__ = ['run_async', 'run_asyncio_coroutine', 'register_thread']
+__all__ = ['run_async', 'run_asyncio_coroutine', 'register_thread', 'hold', 'defer_call']
 
 
 def register_session_implement_for_target(target_func):
@@ -72,6 +73,8 @@ def get_current_task_id():
 
 def check_session_impl(session_type):
     def decorator(func):
+        """装饰器:在函数调用前检查当前会话实现是否满足要求"""
+
         @wraps(func)
         def inner(*args, **kwargs):
             curr_impl = get_session_implement()
@@ -92,6 +95,35 @@ def check_session_impl(session_type):
     return decorator
 
 
+def chose_impl(gen_func):
+    """根据当前会话实现来将 gen_func 转化为协程对象或直接以函数运行"""
+
+    @wraps(gen_func)
+    def inner(*args, **kwargs):
+        gen = gen_func(*args, **kwargs)
+        if get_session_implement() == CoroutineBasedSession:
+            return to_coroutine(gen)
+        else:
+            return run_as_function(gen)
+
+    return inner
+
+
+@chose_impl
+def next_client_event():
+    res = yield get_current_session().next_client_event()
+    return res
+
+
+@chose_impl
+def hold():
+    """保持会话,直到用户关闭浏览器,
+    此时函数抛出 `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常
+    """
+    while True:
+        yield next_client_event()
+
+
 @check_session_impl(CoroutineBasedSession)
 def run_async(coro_obj):
     """异步运行协程对象。协程中依然可以调用 PyWebIO 交互函数。 仅能在基于协程的会话上下文中调用

+ 1 - 1
test/1.basic_output.py

@@ -9,8 +9,8 @@ from selenium.webdriver import Chrome
 
 import pywebio
 from pywebio import start_server
-from pywebio.input import *
 from pywebio.output import *
+from pywebio.session import *
 
 proj_dir = path.dirname(path.dirname(path.abspath(__file__)))