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

maint: set default value of `scope` in output function to `None`

wangweimin 3 жил өмнө
parent
commit
1f0fe2f59e
2 өөрчлөгдсөн 70 нэмэгдсэн , 77 устгасан
  1. 57 66
      pywebio/output.py
  2. 13 11
      pywebio/pin.py

+ 57 - 66
pywebio/output.py

@@ -102,10 +102,10 @@ Content Outputting
 .. autofunction:: put_text
 .. autofunction:: put_text
 .. autofunction:: put_markdown
 .. autofunction:: put_markdown
 
 
-.. py:function:: put_info(*contents, closable=False, scope=-1, position=-1) -> Output:
-                 put_success(*contents, closable=False, scope=-1, position=-1) -> Output:
-                 put_warning(*contents, closable=False, scope=-1, position=-1) -> Output:
-                 put_error(*contents, closable=False, scope=-1, position=-1) -> Output:
+.. py:function:: put_info(*contents, closable=False, scope=None, position=-1) -> Output:
+                 put_success(*contents, closable=False, scope=None, position=-1) -> Output:
+                 put_warning(*contents, closable=False, scope=None, position=-1) -> Output:
+                 put_error(*contents, closable=False, scope=None, position=-1) -> Output:
 
 
     Output Messages.
     Output Messages.
 
 
@@ -200,23 +200,17 @@ class OutputPosition:
     BOTTOM = -1
     BOTTOM = -1
 
 
 
 
-class Scope:
-    Current = -1
-    Root = 0
-    Parent = -2
-
-
 _scope_name_allowed_chars = set(string.ascii_letters + string.digits + '_-')
 _scope_name_allowed_chars = set(string.ascii_letters + string.digits + '_-')
 
 
 
 
-def set_scope(name, container_scope=Scope.Current, position=OutputPosition.BOTTOM, if_exist=None):
+def set_scope(name, container_scope=None, position=OutputPosition.BOTTOM, if_exist=None):
     """Create a new scope.
     """Create a new scope.
 
 
     :param str name: scope name
     :param str name: scope name
-    :param int/str container_scope: Specify the parent scope of this scope. You can use the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide <scope_param>`). When the scope does not exist, no operation is performed.
+    :param str container_scope: Specify the parent scope of this scope. 
+        When the scope doesn't exist, no operation is performed.
     :param int position: The location where this scope is created in the parent scope.
     :param int position: The location where this scope is created in the parent scope.
-       Available values: `OutputPosition.TOP`: created at the top of the parent scope, `OutputPosition.BOTTOM`: created at the bottom of the parent scope.
-       You can also use a integer to index the position (see :ref:`User Guide <scope_param>`)
+       (see :ref:`Scope related parameters <scope_param>`)
     :param str if_exist: What to do when the specified scope already exists:
     :param str if_exist: What to do when the specified scope already exists:
 
 
         - `None`: Do nothing
         - `None`: Do nothing
@@ -225,65 +219,65 @@ def set_scope(name, container_scope=Scope.Current, position=OutputPosition.BOTTO
 
 
        Default is `None`
        Default is `None`
     """
     """
-    if isinstance(container_scope, int):
-        container_scope = get_current_session().get_scope_name(container_scope)
-
+    if container_scope is None:
+        container_scope = get_scope()
     assert is_html_safe_value(name), "Scope name only allow letter/digit/'_'/'-' char."
     assert is_html_safe_value(name), "Scope name only allow letter/digit/'_'/'-' char."
     send_msg('output_ctl', dict(set_scope=scope2dom(name, no_css_selector=True),
     send_msg('output_ctl', dict(set_scope=scope2dom(name, no_css_selector=True),
                                 container=scope2dom(container_scope),
                                 container=scope2dom(container_scope),
                                 position=position, if_exist=if_exist))
                                 position=position, if_exist=if_exist))
 
 
 
 
-def get_scope(stack_idx=Scope.Current):
+def get_scope(stack_idx=-1):
     """Get the scope name of runtime scope stack
     """Get the scope name of runtime scope stack
 
 
     :param int stack_idx: The index of the runtime scope stack. Default is -1.
     :param int stack_idx: The index of the runtime scope stack. Default is -1.
 
 
-       0 means the top level scope(the ROOT Scope),
+       0 means the top level scope(the ``ROOT`` Scope),
        -1 means the current Scope,
        -1 means the current Scope,
-       -2 means the scope used before entering the current scope, 
+       -2 means the scope used before entering the current scope, ...
     :return: Returns the scope name with the index, and returns ``None`` when occurs index error
     :return: Returns the scope name with the index, and returns ``None`` when occurs index error
     """
     """
     try:
     try:
         return get_current_session().get_scope_name(stack_idx)
         return get_current_session().get_scope_name(stack_idx)
     except IndexError:
     except IndexError:
+        logger.exception("Scope stack index error")
         return None
         return None
 
 
 
 
-def clear(scope=Scope.Current):
+def clear(scope=None):
     """Clear the content of the specified scope
     """Clear the content of the specified scope
 
 
-    :param int/str scope: Can specify the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide <scope_param>`)
+    :param str scope: Target scope name. Default is the current scope.
     """
     """
-    if isinstance(scope, int):
-        scope = get_current_session().get_scope_name(scope)
+    if scope is None:
+        scope = get_scope()
     send_msg('output_ctl', dict(clear=scope2dom(scope)))
     send_msg('output_ctl', dict(clear=scope2dom(scope)))
 
 
 
 
-def remove(scope=Scope.Current):
+def remove(scope=None):
     """Remove the specified scope
     """Remove the specified scope
 
 
-    :param int/str scope: Can specify the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide <scope_param>`)
+    :param str scope: Target scope name. Default is the current scope.
     """
     """
-    if isinstance(scope, int):
-        scope = get_current_session().get_scope_name(scope)
+    if scope is None:
+        scope = get_scope()
     assert scope != 'ROOT', "Can not remove `ROOT` scope."
     assert scope != 'ROOT', "Can not remove `ROOT` scope."
     send_msg('output_ctl', dict(remove=scope2dom(scope)))
     send_msg('output_ctl', dict(remove=scope2dom(scope)))
 
 
 
 
-def scroll_to(scope=Scope.Current, position=Position.TOP):
+def scroll_to(scope=None, position=Position.TOP):
     """
     """
     Scroll the page to the specified scope
     Scroll the page to the specified scope
 
 
-    :param str/int scope: Target scope. Can specify the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide <scope_param>`)
+    :param str scope: Target scope. Default is the current scope.
     :param str position: Where to place the scope in the visible area of the page. Available value:
     :param str position: Where to place the scope in the visible area of the page. Available value:
 
 
        * ``'top'`` : Keep the scope at the top of the visible area of the page
        * ``'top'`` : Keep the scope at the top of the visible area of the page
        * ``'middle'`` : Keep the scope at the middle of the visible area of the page
        * ``'middle'`` : Keep the scope at the middle of the visible area of the page
        * ``'bottom'`` : Keep the scope at the bottom of the visible area of the page
        * ``'bottom'`` : Keep the scope at the bottom of the visible area of the page
     """
     """
-    if isinstance(scope, int):
-        scope = get_current_session().get_scope_name(scope)
+    if scope is None:
+        scope = get_scope()
     send_msg('output_ctl', dict(scroll_to=scope2dom(scope), position=position))
     send_msg('output_ctl', dict(scroll_to=scope2dom(scope), position=position))
 
 
 
 
@@ -292,7 +286,7 @@ def _get_output_spec(type, scope, position, **other_spec):
     get the spec dict of output functions
     get the spec dict of output functions
 
 
     :param str type: output type
     :param str type: output type
-    :param int/str scope: target scope
+    :param str scope: target scope
     :param int position:
     :param int position:
     :param other_spec: Additional output parameters, the None value will not be included in the return value
     :param other_spec: Additional output parameters, the None value will not be included in the return value
 
 
@@ -303,8 +297,8 @@ def _get_output_spec(type, scope, position, **other_spec):
     # add non-None arguments to spec
     # add non-None arguments to spec
     spec.update({k: v for k, v in other_spec.items() if v is not None})
     spec.update({k: v for k, v in other_spec.items() if v is not None})
 
 
-    if isinstance(scope, int):
-        scope_name = get_current_session().get_scope_name(scope)
+    if not scope:
+        scope_name = get_scope()
     else:
     else:
         scope_name = scope
         scope_name = scope
 
 
@@ -314,14 +308,14 @@ def _get_output_spec(type, scope, position, **other_spec):
     return spec
     return spec
 
 
 
 
-def put_text(*texts, sep=' ', inline=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_text(*texts, sep=' ', inline=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """
     """
     Output plain text
     Output plain text
 
 
     :param texts: Texts need to output. The type can be any object, and the `str()` function will be used for non-string objects.
     :param texts: Texts need to output. The type can be any object, and the `str()` function will be used for non-string objects.
     :param str sep: The separator between the texts
     :param str sep: The separator between the texts
     :param bool inline: Use text as an inline element (no line break at the end of the text). Default is ``False``
     :param bool inline: Use text as an inline element (no line break at the end of the text). Default is ``False``
-    :param int/str scope: The target scope to output. If the scope does not exist, no operation will be performed.
+    :param str scope: The target scope to output. If the scope does not exist, no operation will be performed.
 
 
        Can specify the scope name or use a integer to index the runtime scope stack.
        Can specify the scope name or use a integer to index the runtime scope stack.
     :param int position: The position where the content is output in target scope
     :param int position: The position where the content is output in target scope
@@ -333,7 +327,7 @@ def put_text(*texts, sep=' ', inline=False, scope=Scope.Current, position=Output
     return Output(spec)
     return Output(spec)
 
 
 
 
-def _put_message(color, contents, closable=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def _put_message(color, contents, closable=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     tpl = r"""
     tpl = r"""
 <div class="alert alert-{{color}} {{#dismissible}}alert-dismissible fade show{{/dismissible}}" role="alert">
 <div class="alert alert-{{color}} {{#dismissible}}alert-dismissible fade show{{/dismissible}}" role="alert">
 {{#contents}}
 {{#contents}}
@@ -350,7 +344,7 @@ def _put_message(color, contents, closable=False, scope=Scope.Current, position=
                       scope=scope, position=position).enable_context_manager()
                       scope=scope, position=position).enable_context_manager()
 
 
 
 
-def put_info(*contents, closable=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_info(*contents, closable=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output information message.
     """Output information message.
 
 
     :param contents: Message contents.
     :param contents: Message contents.
@@ -363,7 +357,7 @@ def put_info(*contents, closable=False, scope=Scope.Current, position=OutputPosi
     return _put_message(color='info', contents=contents, closable=closable, scope=scope, position=position)
     return _put_message(color='info', contents=contents, closable=closable, scope=scope, position=position)
 
 
 
 
-def put_success(*contents, closable=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_success(*contents, closable=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output success message.
     """Output success message.
     .. seealso:: `put_info()`
     .. seealso:: `put_info()`
     .. versionadded:: 1.2
     .. versionadded:: 1.2
@@ -371,21 +365,21 @@ def put_success(*contents, closable=False, scope=Scope.Current, position=OutputP
     return _put_message(color='success', contents=contents, closable=closable, scope=scope, position=position)
     return _put_message(color='success', contents=contents, closable=closable, scope=scope, position=position)
 
 
 
 
-def put_warning(*contents, closable=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_warning(*contents, closable=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output warning message.
     """Output warning message.
     .. seealso:: `put_info()`
     .. seealso:: `put_info()`
     """
     """
     return _put_message(color='warning', contents=contents, closable=closable, scope=scope, position=position)
     return _put_message(color='warning', contents=contents, closable=closable, scope=scope, position=position)
 
 
 
 
-def put_error(*contents, closable=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_error(*contents, closable=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output error message.
     """Output error message.
     .. seealso:: `put_info()`
     .. seealso:: `put_info()`
     """
     """
     return _put_message(color='danger', contents=contents, closable=closable, scope=scope, position=position)
     return _put_message(color='danger', contents=contents, closable=closable, scope=scope, position=position)
 
 
 
 
-def put_html(html, sanitize=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_html(html, sanitize=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """
     """
     Output HTML content
     Output HTML content
 
 
@@ -405,7 +399,7 @@ def put_html(html, sanitize=False, scope=Scope.Current, position=OutputPosition.
     return Output(spec)
     return Output(spec)
 
 
 
 
-def put_code(content, language='', rows=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_code(content, language='', rows=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """
     """
     Output code block
     Output code block
 
 
@@ -431,7 +425,7 @@ def put_code(content, language='', rows=None, scope=Scope.Current, position=Outp
 
 
 
 
 def put_markdown(mdcontent, strip_indent=0, lstrip=False, options=None, sanitize=True,
 def put_markdown(mdcontent, strip_indent=0, lstrip=False, options=None, sanitize=True,
-                 scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+                 scope=None, position=OutputPosition.BOTTOM) -> Output:
     """
     """
     Output Markdown
     Output Markdown
 
 
@@ -512,7 +506,7 @@ def span(content, row=1, col=1):
 
 
 
 
 @safely_destruct_output_when_exp('tdata')
 @safely_destruct_output_when_exp('tdata')
-def put_table(tdata, header=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_table(tdata, header=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """
     """
     Output table
     Output table
 
 
@@ -628,7 +622,7 @@ def _format_button(buttons):
     return btns
     return btns
 
 
 
 
-def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, group=False, scope=Scope.Current,
+def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, group=False, scope=None,
                 position=OutputPosition.BOTTOM, **callback_options) -> Output:
                 position=OutputPosition.BOTTOM, **callback_options) -> Output:
     """
     """
     Output a group of buttons and bind click event
     Output a group of buttons and bind click event
@@ -699,11 +693,6 @@ def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, g
             put_text("You click delete button")
             put_text("You click delete button")
 
 
         put_buttons(['edit', 'delete'], onclick=[edit, delete])
         put_buttons(['edit', 'delete'], onclick=[edit, delete])
-
-    .. attention::
-
-        After the PyWebIO session (see :ref:`Server and script mode <server_and_script_mode>` for more information about session) closed, the event callback will not work. You can call the :func:`pywebio.session.hold()` function at the end of the task function to hold the session, so that the event callback will always be available before the browser page is closed by user.
-
     """
     """
     btns = _format_button(buttons)
     btns = _format_button(buttons)
 
 
@@ -724,7 +713,7 @@ def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, g
     return Output(spec)
     return Output(spec)
 
 
 
 
-def put_button(label, onclick, color=None, small=None, link_style=False, outline=False, scope=Scope.Current,
+def put_button(label, onclick, color=None, small=None, link_style=False, outline=False, scope=None,
                position=OutputPosition.BOTTOM) -> Output:
                position=OutputPosition.BOTTOM) -> Output:
     """Output a single button and bind click event to it.
     """Output a single button and bind click event to it.
 
 
@@ -741,13 +730,15 @@ def put_button(label, onclick, color=None, small=None, link_style=False, outline
         :summary: `put_button()` usage
         :summary: `put_button()` usage
 
 
         put_button("click me", onclick=lambda: toast("Clicked"), color='success', outline=True)
         put_button("click me", onclick=lambda: toast("Clicked"), color='success', outline=True)
+
+    .. versionadded:: 1.4
     """
     """
     return put_buttons([{'label': label, 'value': '', 'color': color or 'primary'}], onclick=[onclick],
     return put_buttons([{'label': label, 'value': '', 'color': color or 'primary'}], onclick=[onclick],
                        small=small, link_style=link_style, outline=outline, scope=scope, position=position)
                        small=small, link_style=link_style, outline=outline, scope=scope, position=position)
 
 
 
 
 def put_image(src, format=None, title='', width=None, height=None,
 def put_image(src, format=None, title='', width=None, height=None,
-              scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+              scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output image
     """Output image
 
 
     :param src: Source of image. It can be a string specifying image URL, a bytes-like object specifying the binary content of an image or an instance of ``PIL.Image.Image``
     :param src: Source of image. It can be a string specifying image URL, a bytes-like object specifying the binary content of an image or an instance of ``PIL.Image.Image``
@@ -792,7 +783,7 @@ def put_image(src, format=None, title='', width=None, height=None,
     return put_html(tag, scope=scope, position=position)
     return put_html(tag, scope=scope, position=position)
 
 
 
 
-def put_file(name, content, label=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_file(name, content, label=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a link to download a file
     """Output a link to download a file
 
 
     To show a link with the file name on the browser. When click the link, the browser automatically downloads the file.
     To show a link with the file name on the browser. When click the link, the browser automatically downloads the file.
@@ -822,7 +813,7 @@ def put_file(name, content, label=None, scope=Scope.Current, position=OutputPosi
     return output
     return output
 
 
 
 
-def put_link(name, url=None, app=None, new_window=False, scope=Scope.Current,
+def put_link(name, url=None, app=None, new_window=False, scope=None,
              position=OutputPosition.BOTTOM) -> Output:
              position=OutputPosition.BOTTOM) -> Output:
     """Output hyperlinks to other web page or PyWebIO Application page.
     """Output hyperlinks to other web page or PyWebIO Application page.
 
 
@@ -843,7 +834,7 @@ def put_link(name, url=None, app=None, new_window=False, scope=Scope.Current,
     return put_html(tag, scope=scope, position=position)
     return put_html(tag, scope=scope, position=position)
 
 
 
 
-def put_processbar(name, init=0, label=None, auto_close=False, scope=Scope.Current,
+def put_processbar(name, init=0, label=None, auto_close=False, scope=None,
                    position=OutputPosition.BOTTOM) -> Output:
                    position=OutputPosition.BOTTOM) -> Output:
     """Output a process bar
     """Output a process bar
 
 
@@ -906,7 +897,7 @@ def set_processbar(name, value, label=None):
     run_js(js_code)
     run_js(js_code)
 
 
 
 
-def put_loading(shape='border', color='dark', scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_loading(shape='border', color='dark', scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output loading prompt
     """Output loading prompt
 
 
     :param str shape: The shape of loading prompt. The available values are: `'border'` (default)、 `'grow'`
     :param str shape: The shape of loading prompt. The available values are: `'border'` (default)、 `'grow'`
@@ -959,7 +950,7 @@ def put_loading(shape='border', color='dark', scope=Scope.Current, position=Outp
 
 
 
 
 @safely_destruct_output_when_exp('content')
 @safely_destruct_output_when_exp('content')
-def put_collapse(title, content=[], open=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_collapse(title, content=[], open=False, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output collapsible content
     """Output collapsible content
 
 
     :param str title: Title of content
     :param str title: Title of content
@@ -1004,7 +995,7 @@ def put_collapse(title, content=[], open=False, scope=Scope.Current, position=Ou
 
 
 @safely_destruct_output_when_exp('content')
 @safely_destruct_output_when_exp('content')
 def put_scrollable(content=[], height=400, keep_bottom=False, horizon_scroll=False, border=True,
 def put_scrollable(content=[], height=400, keep_bottom=False, horizon_scroll=False, border=True,
-                   scope=Scope.Current, position=OutputPosition.BOTTOM, **kwargs) -> Output:
+                   scope=None, position=OutputPosition.BOTTOM, **kwargs) -> Output:
     """Output a fixed height content area. scroll bar is displayed when the content exceeds the limit
     """Output a fixed height content area. scroll bar is displayed when the content exceeds the limit
 
 
     :type content: list/str/put_xxx()
     :type content: list/str/put_xxx()
@@ -1088,7 +1079,7 @@ def put_scrollable(content=[], height=400, keep_bottom=False, horizon_scroll=Fal
 
 
 
 
 @safely_destruct_output_when_exp('tabs')
 @safely_destruct_output_when_exp('tabs')
-def put_tabs(tabs, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_tabs(tabs, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output tabs.
     """Output tabs.
 
 
     :param list tabs: Tab list, each item is a dict: ``{"title": "Title", "content": ...}`` .
     :param list tabs: Tab list, each item is a dict: ``{"title": "Title", "content": ...}`` .
@@ -1123,7 +1114,7 @@ def put_tabs(tabs, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Outpu
 
 
 
 
 @safely_destruct_output_when_exp('data')
 @safely_destruct_output_when_exp('data')
-def put_widget(template, data, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_widget(template, data, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output your own widget
     """Output your own widget
 
 
     :param template: html template, using `mustache.js <https://github.com/janl/mustache.js>`_ syntax
     :param template: html template, using `mustache.js <https://github.com/janl/mustache.js>`_ syntax
@@ -1168,7 +1159,7 @@ def put_widget(template, data, scope=Scope.Current, position=OutputPosition.BOTT
 
 
 
 
 @safely_destruct_output_when_exp('content')
 @safely_destruct_output_when_exp('content')
-def put_row(content=[], size=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_row(content=[], size=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Use row layout to output content. The content is arranged horizontally
     """Use row layout to output content. The content is arranged horizontally
 
 
     :param list content: Content list, the item is ``put_xxx()`` call or ``None``. ``None`` represents the space between the output
     :param list content: Content list, the item is ``put_xxx()`` call or ``None``. ``None`` represents the space between the output
@@ -1207,7 +1198,7 @@ def put_row(content=[], size=None, scope=Scope.Current, position=OutputPosition.
 
 
 
 
 @safely_destruct_output_when_exp('content')
 @safely_destruct_output_when_exp('content')
-def put_column(content=[], size=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def put_column(content=[], size=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Use column layout to output content. The content is arranged vertically
     """Use column layout to output content. The content is arranged vertically
 
 
     :param list content: Content list, the item is ``put_xxx()`` call or ``None``. ``None`` represents the space between the output
     :param list content: Content list, the item is ``put_xxx()`` call or ``None``. ``None`` represents the space between the output
@@ -1219,7 +1210,7 @@ def put_column(content=[], size=None, scope=Scope.Current, position=OutputPositi
     return _row_column_layout(content, flow='row', size=size, scope=scope, position=position).enable_context_manager()
     return _row_column_layout(content, flow='row', size=size, scope=scope, position=position).enable_context_manager()
 
 
 
 
-def _row_column_layout(content, flow, size, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+def _row_column_layout(content, flow, size, scope=None, position=OutputPosition.BOTTOM) -> Output:
     if not isinstance(content, (list, tuple, OutputList)):
     if not isinstance(content, (list, tuple, OutputList)):
         content = [content]
         content = [content]
 
 
@@ -1243,7 +1234,7 @@ def _row_column_layout(content, flow, size, scope=Scope.Current, position=Output
 
 
 @safely_destruct_output_when_exp('content')
 @safely_destruct_output_when_exp('content')
 def put_grid(content, cell_width='auto', cell_height='auto', cell_widths=None, cell_heights=None, direction='row',
 def put_grid(content, cell_width='auto', cell_height='auto', cell_widths=None, cell_heights=None, direction='row',
-             scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+             scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output content using grid layout
     """Output content using grid layout
 
 
     :param content: Content of grid, which is a two-dimensional list. The item of list is ``put_xxx()`` call or ``None``.
     :param content: Content of grid, which is a two-dimensional list. The item of list is ``put_xxx()`` call or ``None``.

+ 13 - 11
pywebio/pin.py

@@ -13,7 +13,7 @@ In most cases, it enough to use this way to get input.
 However in some cases, you may want to make the input form **not** disappear after submission,
 However in some cases, you may want to make the input form **not** disappear after submission,
 and can continue to receive input.
 and can continue to receive input.
 
 
-So PyWebIO provide the ``pin`` module to achieve persistent input by pinning input widgets to the page.
+So PyWebIO provides the ``pin`` module to achieve persistent input by pinning input widgets to the page.
 
 
 The ``pin`` module achieves persistent input in 3 parts:
 The ``pin`` module achieves persistent input in 3 parts:
 
 
@@ -70,10 +70,10 @@ Since the pin widget functions is not blocking,
 Pin widgets
 Pin widgets
 ------------------
 ------------------
 Each pin widget function corresponds to an input function of :doc:`input <./input>` module.
 Each pin widget function corresponds to an input function of :doc:`input <./input>` module.
+(For performance reasons, no pin widget for `file_upload() <pywebio.input.file_upload>` input function)
 
 
 The function of pin widget supports most of the parameters of the corresponding input function.
 The function of pin widget supports most of the parameters of the corresponding input function.
-
-The following is the difference between the two in parameters:
+Here lists the difference between the two in parameters:
 
 
  * The first parameter of pin widget function is always the name of the widget,
  * The first parameter of pin widget function is always the name of the widget,
    and if you output two pin widgets with the same name, the previous one will expire.
    and if you output two pin widgets with the same name, the previous one will expire.
@@ -122,7 +122,7 @@ Pin utils
 import string
 import string
 
 
 from pywebio.input import parse_input_update_spec
 from pywebio.input import parse_input_update_spec
-from pywebio.output import Scope, OutputPosition, Output
+from pywebio.output import OutputPosition, Output
 from pywebio.output import _get_output_spec
 from pywebio.output import _get_output_spec
 from .io_ctrl import send_msg, single_input_kwargs
 from .io_ctrl import send_msg, single_input_kwargs
 from .session import next_client_event, chose_impl
 from .session import next_client_event, chose_impl
@@ -145,7 +145,7 @@ def _pin_output(single_input_return, scope, position):
 
 
 
 
 def put_input(name, type='text', *, label='', value=None, placeholder=None, readonly=None, datalist=None,
 def put_input(name, type='text', *, label='', value=None, placeholder=None, readonly=None, datalist=None,
-              help_text=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+              help_text=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output an input widget. Refer to: `pywebio.input.input()`"""
     """Output an input widget. Refer to: `pywebio.input.input()`"""
     from pywebio.input import input
     from pywebio.input import input
     check_name(name)
     check_name(name)
@@ -155,7 +155,7 @@ def put_input(name, type='text', *, label='', value=None, placeholder=None, read
 
 
 
 
 def put_textarea(name, *, label='', rows=6, code=None, maxlength=None, minlength=None, value=None, placeholder=None,
 def put_textarea(name, *, label='', rows=6, code=None, maxlength=None, minlength=None, value=None, placeholder=None,
-                 readonly=None, help_text=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+                 readonly=None, help_text=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a textarea widget. Refer to: `pywebio.input.textarea()`"""
     """Output a textarea widget. Refer to: `pywebio.input.textarea()`"""
     from pywebio.input import textarea
     from pywebio.input import textarea
     check_name(name)
     check_name(name)
@@ -166,7 +166,7 @@ def put_textarea(name, *, label='', rows=6, code=None, maxlength=None, minlength
 
 
 
 
 def put_select(name, options=None, *, label='', multiple=None, value=None, help_text=None,
 def put_select(name, options=None, *, label='', multiple=None, value=None, help_text=None,
-               scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+               scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a select widget. Refer to: `pywebio.input.select()`"""
     """Output a select widget. Refer to: `pywebio.input.select()`"""
     from pywebio.input import select
     from pywebio.input import select
     check_name(name)
     check_name(name)
@@ -176,7 +176,7 @@ def put_select(name, options=None, *, label='', multiple=None, value=None, help_
 
 
 
 
 def put_checkbox(name, options=None, *, label='', inline=None, value=None, help_text=None,
 def put_checkbox(name, options=None, *, label='', inline=None, value=None, help_text=None,
-                 scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+                 scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a checkbox widget. Refer to: `pywebio.input.checkbox()`"""
     """Output a checkbox widget. Refer to: `pywebio.input.checkbox()`"""
     from pywebio.input import checkbox
     from pywebio.input import checkbox
     check_name(name)
     check_name(name)
@@ -186,7 +186,7 @@ def put_checkbox(name, options=None, *, label='', inline=None, value=None, help_
 
 
 
 
 def put_radio(name, options=None, *, label='', inline=None, value=None, help_text=None,
 def put_radio(name, options=None, *, label='', inline=None, value=None, help_text=None,
-              scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+              scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a radio widget. Refer to: `pywebio.input.radio()`"""
     """Output a radio widget. Refer to: `pywebio.input.radio()`"""
     from pywebio.input import radio
     from pywebio.input import radio
     check_name(name)
     check_name(name)
@@ -196,7 +196,7 @@ def put_radio(name, options=None, *, label='', inline=None, value=None, help_tex
 
 
 
 
 def put_slider(name, *, label='', value=0, min_value=0, max_value=100, step=1, required=None, help_text=None,
 def put_slider(name, *, label='', value=0, min_value=0, max_value=100, step=1, required=None, help_text=None,
-               scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+               scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a slide widget. Refer to: `pywebio.input.slider()`"""
     """Output a slide widget. Refer to: `pywebio.input.slider()`"""
     from pywebio.input import slider
     from pywebio.input import slider
     check_name(name)
     check_name(name)
@@ -206,11 +206,13 @@ def put_slider(name, *, label='', value=0, min_value=0, max_value=100, step=1, r
 
 
 
 
 def put_actions(name, *, label='', buttons=None, help_text=None,
 def put_actions(name, *, label='', buttons=None, help_text=None,
-                scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
+                scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a group of action button. Refer to: `pywebio.input.actions()`
     """Output a group of action button. Refer to: `pywebio.input.actions()`
 
 
     Unlike the ``actions()``, ``put_actions()`` won't submit any form, it will only set the value of the pin widget.
     Unlike the ``actions()``, ``put_actions()`` won't submit any form, it will only set the value of the pin widget.
     Only 'submit' type button is available in pin widget version.
     Only 'submit' type button is available in pin widget version.
+
+    .. versionadded:: 1.4
     """
     """
     from pywebio.input import actions
     from pywebio.input import actions
     check_name(name)
     check_name(name)