ソースを参照

maint: use 'pywebio.session.set_env()' to set session environment settings

wangweimin 4 年 前
コミット
c0b42940c8

+ 3 - 2
demos/__main__.py

@@ -8,7 +8,8 @@ from demos.output_usage import main as output_usage
 from demos.config import charts_demo_host
 
 from pywebio import STATIC_PATH
-from pywebio.output import put_markdown, set_auto_scroll_bottom
+from pywebio.output import put_markdown
+from pywebio.session import set_env
 from pywebio.platform.tornado import webio_handler
 from tornado.options import define, options
 
@@ -43,7 +44,7 @@ PyWebIO还支持使用第三方库进行数据可视化
 
 
 def index():
-    set_auto_scroll_bottom(False)
+    set_env(auto_scroll_bottom=False)
     put_markdown(index_md)
 
 

+ 2 - 2
demos/bmi.py

@@ -9,11 +9,11 @@ BMI指数计算
 from pywebio import start_server
 from pywebio.input import *
 from pywebio.output import *
+from pywebio.session import set_env
 
 
 def main():
-    set_output_fixed_height(True)
-    set_title("BMI Calculation")
+    set_env(title="BMI Calculation", output_fixed_height=True)
 
     put_markdown("""计算 [`BMI指数`](https://baike.baidu.com/item/%E4%BD%93%E8%B4%A8%E6%8C%87%E6%95%B0/1455733) 的简单应用,源代码[链接](https://github.com/wang0618/PyWebIO/blob/master/demos/bmi.py)""", lstrip=True)
 

+ 3 - 3
demos/chat_room.py

@@ -13,7 +13,7 @@ import asyncio
 from pywebio import start_server, run_async
 from pywebio.input import *
 from pywebio.output import *
-from pywebio.session import defer_call
+from pywebio.session import defer_call, set_env
 
 # 最大消息记录保存
 MAX_MESSAGES_CNT = 10 ** 4
@@ -42,8 +42,8 @@ async def refresh_msg(my_name):
 async def main():
     global chat_msgs
 
-    set_output_fixed_height(True)
-    set_title("PyWebIO Chat Room")
+    set_env(title="PyWebIO Chat Room", output_fixed_height=True)
+
     put_markdown("""欢迎来到聊天室,你可以和当前所有在线的人聊天\n
     本应用使用不到80行代码实现,源代码[链接](https://github.com/wang0618/PyWebIO/blob/master/demos/chat_room.py)""", lstrip=True)
 

+ 2 - 2
demos/input_usage.py

@@ -8,11 +8,11 @@
 from pywebio import start_server
 from pywebio.input import *
 from pywebio.output import *
+from pywebio.session import set_env
 
 
 def main():
-    set_auto_scroll_bottom(False)
-    set_title("PyWebIO输入演示")
+    set_env(title="PyWebIO输入演示", auto_scroll_bottom=False)
 
     put_markdown("""# PyWebIO 输入演示
     

+ 2 - 3
demos/output_usage.py

@@ -7,12 +7,11 @@
 """
 from pywebio import start_server
 from pywebio.output import *
-from pywebio.session import hold
+from pywebio.session import hold, set_env
 
 
 def main():
-    set_auto_scroll_bottom(False)
-    set_title("PyWebIO输出演示")
+    set_env(title="PyWebIO输出演示", auto_scroll_bottom=False)
 
     put_markdown("""# PyWebIO 输入演示
     

+ 3 - 3
docs/guide.rst

@@ -310,16 +310,16 @@ PyWebIO使用Scope栈来保存运行时的Scope的嵌套层级。
 **输出区外观**
 
 PyWebIO支持两种外观:输出区固定高度/可变高度。
-可以通过调用 `set_output_fixed_height(True) <pywebio.output.set_output_fixed_height>` 来开启输出区固定高度。
+可以通过调用 `set_env(output_fixed_heigh=True) <pywebio.session.set_env>` 来开启输出区固定高度。
 
 **设置页面标题**
 
-调用 `set_title(title) <pywebio.output.set_title>` 可以设置页面标题。
+调用 `set_env(title=...) <pywebio.session.set_env>` 可以设置页面标题。
 
 **自动滚动**
 
 在 ``ROOT`` 域进行输出时,PyWebIO默认在输出完毕后自动将页面滚动到页面最下方;在调用输入函数时,也会将页面滚动到表单处。
-通过调用 `set_auto_scroll_bottom(False) <pywebio.output.set_auto_scroll_bottom>` 来关闭自动滚动。
+通过调用 `set_env(auto_scroll_bottom=False) <pywebio.session.set_env>` 来关闭自动滚动。
 
 布局
 ^^^^^^^^^^^^^^

+ 12 - 3
docs/spec.rst

@@ -249,15 +249,24 @@ close_popup
 
 该命令字段 ``spec`` 为 ``null``
 
+set_env
+^^^^^^^^^^^^^^^
+环境配置
+
+命令 spec 字段:
+
+* title (str): 设定标题
+* output_animation (bool): 是否在输出内容时,使用过渡动画
+* output_fixed_height (bool): 设置是否输出区固定高度
+* auto_scroll_bottom (bool): 是否在内容输出时将页面自动滚动到底部
+* http_pull_interval (int): HTTP轮训后端消息的周期(单位为毫秒,默认1000ms),仅在使用HTTP的连接中可用
+
 output_ctl
 ^^^^^^^^^^^^^^^
 输入控制
 
 命令 spec 字段:
 
-* title: 设定标题
-* output_fixed_height: 设置是否输出区固定高度
-* auto_scroll_bottom: 设置有新内容时是否自动滚动到底部
 * set_scope: 要创建的scope的名字
 
     * container: 新创建的scope的父scope的css选择器

+ 1 - 23
pywebio/output.py

@@ -10,13 +10,6 @@ r"""输出内容到用户浏览器
 .. autofunction:: scroll_to
 .. autofunction:: use_scope
 
-
-环境设置
---------------
-.. autofunction:: set_title
-.. autofunction:: set_output_fixed_height
-.. autofunction:: set_auto_scroll_bottom
-
 内容输出
 --------------
 .. autofunction:: put_text
@@ -76,7 +69,7 @@ except ImportError:
 
 logger = logging.getLogger(__name__)
 
-__all__ = ['Position', 'set_title', 'set_output_fixed_height', 'set_auto_scroll_bottom', 'remove', 'scroll_to',
+__all__ = ['Position', 'remove', 'scroll_to',
            'put_text', 'put_html', 'put_code', 'put_markdown', 'use_scope', 'set_scope', 'clear', 'remove',
            'put_table', 'table_cell_buttons', 'put_buttons', 'put_image', 'put_file', 'PopupSize', 'popup',
            'close_popup', 'put_widget', 'put_collapse', 'put_link', 'put_scrollable', 'style', 'put_column',
@@ -109,21 +102,6 @@ class Scope:
     Parent = -2
 
 
-def set_title(title):
-    r"""设置页面标题"""
-    send_msg('output_ctl', dict(title=title))
-
-
-def set_output_fixed_height(enabled=True):
-    r"""开启/关闭页面固高度模式"""
-    send_msg('output_ctl', dict(output_fixed_height=enabled))
-
-
-def set_auto_scroll_bottom(enabled=True):
-    r"""开启/关闭页面自动滚动到底部"""
-    send_msg('output_ctl', dict(auto_scroll_bottom=enabled))
-
-
 _scope_name_allowed_chars = set(string.ascii_letters + string.digits + '_-')
 
 

+ 21 - 1
pywebio/session/__init__.py

@@ -10,6 +10,7 @@ r"""
 .. autofunction:: hold
 .. autofunction:: data
 .. autofunction:: get_info
+.. autofunction:: set_env
 
 .. autoclass:: pywebio.session.coroutinebased.TaskHandle
    :members:
@@ -29,7 +30,7 @@ from ..utils import iscoroutinefunction, isgeneratorfunction, run_as_function, t
 _active_session_cls = []
 
 __all__ = ['run_async', 'run_asyncio_coroutine', 'register_thread', 'hold', 'defer_call', 'data', 'get_info',
-           'run_js', 'eval_js', 'download']
+           'run_js', 'eval_js', 'download', 'set_env']
 
 
 def register_session_implement_for_target(target_func):
@@ -276,6 +277,25 @@ def data():
     return get_current_session().save
 
 
+def set_env(**env_info):
+    """当前会话的环境设置
+
+    可配置项有:
+
+    * ``title`` (str): 当前页面的标题
+    * ``output_animation`` (bool): 是否启用输出动画(在输出内容时,使用过渡动画),默认启用
+    * ``auto_scroll_bottom`` (bool): 是否在内容输出时将页面自动滚动到底部,默认启用
+    * ``http_pull_interval`` (int): HTTP轮训后端消息的周期(单位为毫秒,默认1000ms),仅在使用HTTP的连接中可用
+    * ``fix_output_height`` (bool): 是否使用固定高度的输出区域(默认不启用)
+
+    调用示例::
+
+        set_env(title='Awesome PyWebIO!!', output_animation=False)
+    """
+    from ..io_ctrl import send_msg
+    send_msg('set_env', spec=env_info)
+
+
 def get_info():
     """ 获取当前会话的相关信息
 

+ 2 - 1
test/1.basic.py

@@ -9,11 +9,12 @@ import util
 from pywebio import start_server
 from pywebio.input import *
 from pywebio.output import *
+from pywebio.session import set_env
 from pywebio.utils import run_as_function
 
 
 def target():
-    set_auto_scroll_bottom(True)
+    set_env(auto_scroll_bottom=False)
 
     template.set_defer_call()
 

+ 2 - 2
test/13.misc.py

@@ -15,7 +15,7 @@ from pywebio.utils import *
 
 
 def target():
-    set_auto_scroll_bottom(False)
+    set_env(auto_scroll_bottom=False)
 
     # test session data
     g = data()
@@ -41,7 +41,7 @@ def target():
     get_free_port()
 
     # test pywebio.output
-    set_output_fixed_height(False)
+    set_env(fix_output_height=False)
 
     try:
         yield put_buttons([{'label': 'must not be shown'}], onclick=[lambda: None])

+ 1 - 1
test/template.py

@@ -26,7 +26,7 @@ def get_visible_form(browser):
 
 
 def basic_output():
-    set_title("PyWebIO Test")
+    set_env(title="PyWebIO Test")
     set_scope('top')
 
     put_markdown('### Basic')

+ 38 - 0
webiojs/src/handlers/env.ts

@@ -0,0 +1,38 @@
+import {Command, HttpSession} from "../session";
+import {CommandHandler} from "./base";
+import {config, state} from "../state";
+
+export class EnvSettingHandler implements CommandHandler {
+    accept_command: string[] = ['set_env'];
+
+    constructor() {
+    }
+
+    handle_message(msg: Command) {
+        let spec = msg.spec;
+        if (spec.title !== undefined) {
+            $('#title').text(spec.title);  // 直接使用#title不规范 todo
+            document.title = spec.title;
+        }
+
+        if (spec.output_fixed_height !== undefined) {
+            state.OutputFixedHeight = spec.output_fixed_height;
+            if (spec.output_fixed_height)
+                $('.container').removeClass('no-fix-height');  // todo 不规范
+            else
+                $('.container').addClass('no-fix-height');  // todo 不规范
+        }
+
+        if (spec.auto_scroll_bottom !== undefined)
+            state.AutoScrollBottom = spec.auto_scroll_bottom;
+
+        if (spec.output_animation !== undefined) {
+            config.outputAnimation = spec.output_animation;
+        }
+
+        if (spec.http_pull_interval !== undefined) {
+            if (state.CurrentSession instanceof HttpSession)
+                state.CurrentSession.change_pull_interval(spec.http_pull_interval);
+        }
+    }
+}

+ 0 - 13
webiojs/src/handlers/output.ts

@@ -71,19 +71,6 @@ export class OutputHandler implements CommandHandler {
     };
 
     handle_output_ctl(msg: Command) {
-        if (msg.spec.title) {
-            $('#title').text(msg.spec.title);  // 直接使用#title不规范 todo
-            document.title = msg.spec.title;
-        }
-        if (msg.spec.output_fixed_height !== undefined) {
-            state.OutputFixedHeight = msg.spec.output_fixed_height;
-            if (msg.spec.output_fixed_height)
-                $('.container').removeClass('no-fix-height');  // todo 不规范
-            else
-                $('.container').addClass('no-fix-height');  // todo 不规范
-        }
-        if (msg.spec.auto_scroll_bottom !== undefined)
-            state.AutoScrollBottom = msg.spec.auto_scroll_bottom;
         if (msg.spec.set_scope !== undefined) {
             let spec = msg.spec as {
                 set_scope: string, // scope名

+ 3 - 1
webiojs/src/main.ts

@@ -9,6 +9,7 @@ import {openApp} from "./utils";
 import {ScriptHandler} from "./handlers/script";
 import {DownloadHandler} from "./handlers/download";
 import {ToastHandler} from "./handlers/toast";
+import {EnvSettingHandler} from "./handlers/env";
 
 // 获取后端API地址
 function get_backend_addr() {
@@ -32,8 +33,9 @@ function set_up_session(webio_session: Session, output_container_elem: JQuery, i
     let script_ctrl = new ScriptHandler(webio_session);
     let download_ctrl = new DownloadHandler();
     let toast_ctrl = new ToastHandler();
+    let env_ctrl = new EnvSettingHandler();
 
-    let dispatcher = new CommandDispatcher(output_ctrl, input_ctrl, popup_ctrl, close_ctrl, script_ctrl, download_ctrl, toast_ctrl);
+    let dispatcher = new CommandDispatcher(output_ctrl, input_ctrl, popup_ctrl, close_ctrl, script_ctrl, download_ctrl, toast_ctrl, env_ctrl);
 
     webio_session.on_server_message((msg: Command) => {
         try {

+ 25 - 20
webiojs/src/session.ts

@@ -158,27 +158,26 @@ export class HttpSession implements Session {
 
     start_session(debug: boolean = false): void {
         this.debug = debug;
-        let that = this;
-
-        function pull() {
-            $.ajax({
-                type: "GET",
-                url: that.api_url,
-                contentType: "application/json; charset=utf-8",
-                dataType: "json",
-                headers: {"webio-session-id": that.webio_session_id},
-                success: function (data: Command[], textStatus: string, jqXHR: JQuery.jqXHR) {
-                    that._on_request_success(data, textStatus, jqXHR);
-                    that._on_session_create();
-                },
-                error: function () {
-                    console.error('Http pulling failed');
-                }
-            })
-        }
+        this.pull();
+        this.interval_pull_id = setInterval(()=>{this.pull()},this.pull_interval_ms);
+    }
 
-        pull();
-        this.interval_pull_id = setInterval(pull, this.pull_interval_ms);
+    pull() {
+        let that = this;
+        $.ajax({
+            type: "GET",
+            url: this.api_url,
+            contentType: "application/json; charset=utf-8",
+            dataType: "json",
+            headers: {"webio-session-id": this.webio_session_id},
+            success: function (data: Command[], textStatus: string, jqXHR: JQuery.jqXHR) {
+                that._on_request_success(data, textStatus, jqXHR);
+                that._on_session_create();
+            },
+            error: function () {
+                console.error('Http pulling failed');
+            }
+        })
     }
 
     private _on_request_success(data: Command[], textStatus: string, jqXHR: JQuery.jqXHR) {
@@ -230,6 +229,12 @@ export class HttpSession implements Session {
     closed(): boolean {
         return this._closed;
     }
+
+    change_pull_interval(new_interval: number): void {
+        clearInterval(this.interval_pull_id);
+        this.pull_interval_ms = new_interval;
+        this.interval_pull_id = setInterval(()=>{this.pull()}, this.pull_interval_ms);
+    }
 }
 
 /*