Explorar o código

unify dom name check (fix #380)

wangweimin %!s(int64=3) %!d(string=hai) anos
pai
achega
b49510ef66
Modificáronse 4 ficheiros con 32 adicións e 27 borrados
  1. 7 6
      pywebio/input.py
  2. 7 5
      pywebio/output.py
  3. 9 11
      pywebio/pin.py
  4. 9 5
      pywebio/utils.py

+ 7 - 6
pywebio/input.py

@@ -72,15 +72,15 @@ Functions list
 Functions doc
 --------------
 """
-import os.path
+import copy
 import logging
+import os.path
 from collections.abc import Mapping
-import copy
 
 from .io_ctrl import single_input, input_control, output_register_callback, send_msg, single_input_kwargs
-from .session import get_current_session, get_current_task_id
-from .utils import Setter, is_html_safe_value, parse_file_size
 from .platform import page as platform_setting
+from .session import get_current_session, get_current_task_id
+from .utils import Setter, parse_file_size, check_dom_name_value
 
 logger = logging.getLogger(__name__)
 
@@ -99,7 +99,8 @@ RADIO = 'radio'
 SELECT = 'select'
 TEXTAREA = 'textarea'
 
-__all__ = ['TEXT', 'NUMBER', 'FLOAT', 'PASSWORD', 'URL', 'DATE', 'TIME', 'COLOR', 'DATETIME_LOCAL', 'input', 'textarea', 'select',
+__all__ = ['TEXT', 'NUMBER', 'FLOAT', 'PASSWORD', 'URL', 'DATE', 'TIME', 'COLOR', 'DATETIME_LOCAL', 'input', 'textarea',
+           'select',
            'checkbox', 'radio', 'actions', 'file_upload', 'slider', 'input_group', 'input_update']
 
 
@@ -112,7 +113,7 @@ def _parse_args(kwargs, excludes=()):
     :return:(spec,valid_func)
     """
     kwargs = {k: v for k, v in kwargs.items() if v is not None and k not in excludes}
-    assert is_html_safe_value(kwargs.get('name', '')), '`name` can only contains a-z、A-Z、0-9、_、-'
+    check_dom_name_value(kwargs.get('name', ''), '`name`')
 
     kwargs.update(kwargs.get('other_html_attrs', {}))
     kwargs.pop('other_html_attrs', None)

+ 7 - 5
pywebio/output.py

@@ -217,7 +217,7 @@ from typing import Union
 
 from .io_ctrl import output_register_callback, send_msg, Output, safely_destruct_output_when_exp, OutputList, scope2dom
 from .session import get_current_session, download
-from .utils import random_str, iscoroutinefunction, is_html_safe_value
+from .utils import random_str, iscoroutinefunction, check_dom_name_value
 
 try:
     from PIL.Image import Image as PILImage
@@ -274,7 +274,7 @@ def set_scope(name, container_scope=None, position=OutputPosition.BOTTOM, if_exi
     """
     if container_scope is None:
         container_scope = get_scope()
-    assert is_html_safe_value(name), "Scope name only allow letter/digit/'_'/'-' char."
+    check_dom_name_value(name, 'scope name')
     send_msg('output_ctl', dict(set_scope=scope2dom(name, no_css_selector=True),
                                 container=scope2dom(container_scope),
                                 position=position, if_exist=if_exist))
@@ -961,6 +961,7 @@ def put_processbar(name, init=0, label=None, auto_close=False, scope=None,
 
     .. seealso:: use `set_processbar()` to set the progress of progress bar
     """
+    check_dom_name_value(name)
     processbar_id = 'webio-processbar-%s' % name
     percentage = init * 100
     label = '%.1f%%' % percentage if label is None else label
@@ -985,6 +986,8 @@ def set_processbar(name, value, label=None):
     """
     from pywebio.session import run_js
 
+    check_dom_name_value(name)
+
     processbar_id = 'webio-processbar-%s' % name
     percentage = value * 100
     label = '%.1f%%' % percentage if label is None else label
@@ -1410,7 +1413,7 @@ def put_scope(name, content=[], scope=None, position=OutputPosition.BOTTOM) -> O
     if not isinstance(content, list):
         content = [content]
 
-    assert is_html_safe_value(name), "Scope name only allow letter/digit/'_'/'-' char."
+    check_dom_name_value(name, 'scope name')
     dom_id = scope2dom(name, no_css_selector=True)
 
     spec = _get_output_spec('scope', dom_id=dom_id, contents=content, scope=scope, position=position)
@@ -1754,8 +1757,7 @@ def use_scope(name=None, clear=False, **kwargs):
 
     if name is None:
         name = random_str(10)
-    else:
-        assert is_html_safe_value(name), "Scope name only allow letter/digit/'_'/'-' char."
+    check_dom_name_value(name, 'scope name')
 
     def before_enter():
         if create_scope:

+ 9 - 11
pywebio/pin.py

@@ -131,6 +131,7 @@ from pywebio.output import OutputPosition, Output
 from pywebio.output import _get_output_spec
 from .io_ctrl import send_msg, single_input_kwargs, output_register_callback
 from .session import next_client_event, chose_impl
+from .utils import check_dom_name_value
 
 _pin_name_chars = set(string.ascii_letters + string.digits + '_-')
 
@@ -138,9 +139,6 @@ __all__ = ['put_input', 'put_textarea', 'put_select', 'put_checkbox', 'put_radio
            'pin', 'pin_update', 'pin_wait_change', 'pin_on_change']
 
 
-def check_name(name):
-    assert all(i in _pin_name_chars for i in name), "pin `name` can only contain letters, digits, " \
-                                                    "minus sign and underscore"
 
 
 def _pin_output(single_input_return, scope, position):
@@ -153,7 +151,7 @@ def put_input(name, type='text', *, label='', value=None, placeholder=None, read
               help_text=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output an input widget. Refer to: `pywebio.input.input()`"""
     from pywebio.input import input
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     single_input_return = input(name=name, label=label, value=value, type=type, placeholder=placeholder,
                                 readonly=readonly, datalist=datalist, help_text=help_text)
     return _pin_output(single_input_return, scope, position)
@@ -163,7 +161,7 @@ def put_textarea(name, *, label='', rows=6, code=None, maxlength=None, minlength
                  readonly=None, help_text=None, scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a textarea widget. Refer to: `pywebio.input.textarea()`"""
     from pywebio.input import textarea
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     single_input_return = textarea(
         name=name, label=label, rows=rows, code=code, maxlength=maxlength,
         minlength=minlength, value=value, placeholder=placeholder, readonly=readonly, help_text=help_text)
@@ -174,7 +172,7 @@ def put_select(name, options=None, *, label='', multiple=None, value=None, help_
                scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a select widget. Refer to: `pywebio.input.select()`"""
     from pywebio.input import select
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     single_input_return = select(name=name, options=options, label=label, multiple=multiple,
                                  value=value, help_text=help_text)
     return _pin_output(single_input_return, scope, position)
@@ -184,7 +182,7 @@ def put_checkbox(name, options=None, *, label='', inline=None, value=None, help_
                  scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a checkbox widget. Refer to: `pywebio.input.checkbox()`"""
     from pywebio.input import checkbox
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     single_input_return = checkbox(name=name, options=options, label=label, inline=inline, value=value,
                                    help_text=help_text)
     return _pin_output(single_input_return, scope, position)
@@ -194,7 +192,7 @@ def put_radio(name, options=None, *, label='', inline=None, value=None, help_tex
               scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a radio widget. Refer to: `pywebio.input.radio()`"""
     from pywebio.input import radio
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     single_input_return = radio(name=name, options=options, label=label, inline=inline, value=value,
                                 help_text=help_text)
     return _pin_output(single_input_return, scope, position)
@@ -204,7 +202,7 @@ def put_slider(name, *, label='', value=0, min_value=0, max_value=100, step=1, r
                scope=None, position=OutputPosition.BOTTOM) -> Output:
     """Output a slide widget. Refer to: `pywebio.input.slider()`"""
     from pywebio.input import slider
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     single_input_return = slider(name=name, label=label, value=value, min_value=min_value, max_value=max_value,
                                  step=step, required=required, help_text=help_text)
     return _pin_output(single_input_return, scope, position)
@@ -220,7 +218,7 @@ def put_actions(name, *, label='', buttons=None, help_text=None,
     .. versionadded:: 1.4
     """
     from pywebio.input import actions
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     single_input_return = actions(name=name, label=label, buttons=buttons, help_text=help_text)
     input_kwargs = single_input_kwargs(single_input_return)
     for btn in input_kwargs['item_spec']['buttons']:
@@ -329,7 +327,7 @@ def pin_update(name, **spec):
     :param spec: The pin widget parameters need to be updated.
        Note that those parameters can not be updated: ``type``, ``name``, ``code``, ``multiple``
     """
-    check_name(name)
+    check_dom_name_value(name, 'pin `name`')
     attributes = parse_input_update_spec(spec)
     send_msg('pin_update', spec=dict(name=name, attributes=attributes))
 

+ 9 - 5
pywebio/utils.py

@@ -328,11 +328,6 @@ class LRUDict(OrderedDict):
 _html_value_chars = set(string.ascii_letters + string.digits + '_-')
 
 
-def is_html_safe_value(val):
-    """检查是字符串是否可以作为html属性值"""
-    return all(i in _html_value_chars for i in val)
-
-
 def check_webio_js():
     js_files = [os.path.join(STATIC_PATH, 'js', i) for i in ('pywebio.js', 'pywebio.min.js')]
     if any(os.path.isfile(f) for f in js_files):
@@ -378,3 +373,12 @@ def strip_space(text, n):
         for i in text.splitlines()
     )
     return '\n'.join(lines)
+
+
+def check_dom_name_value(value, name='`name`'):
+    """check the class name / id name of DOM element"""
+    allowed_chars = set(string.ascii_letters + string.digits + '_-')
+
+    if not all(i in allowed_chars for i in value):
+        raise ValueError(name + " can only contain letters, digits, "
+                                "hyphens ('-') and underscore ('_')")