Explorar el Código

maint: use `session.info` instead of `session.get_info()`

wangweimin hace 4 años
padre
commit
419d10747a
Se han modificado 5 ficheros con 139 adiciones y 145 borrados
  1. 1 0
      demos/doc_demo.py
  2. 44 80
      docs/locales/zh_CN/LC_MESSAGES/session.po
  3. 80 51
      pywebio/session/__init__.py
  4. 4 4
      pywebio/session/base.py
  5. 10 10
      pywebio/utils.py

+ 1 - 0
demos/doc_demo.py

@@ -6,6 +6,7 @@ from pywebio import start_server
 from pywebio.input import *
 from pywebio.output import *
 from pywebio.session import *
+from pywebio.session import info as session_info  # for demo of `pywebio.session.info`
 from os import path, listdir
 from functools import partial
 from pywebio.platform import seo

+ 44 - 80
docs/locales/zh_CN/LC_MESSAGES/session.po

@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PyWebIO 1.1.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-02-18 11:52+0800\n"
-"PO-Revision-Date: 2021-02-18 11:55+0800\n"
+"POT-Creation-Date: 2021-02-24 09:32+0800\n"
+"PO-Revision-Date: 2021-02-24 09:37+0800\n"
 "Last-Translator: WangWeimin <wang0.618@qq.com>\n"
 "Language: zh_CN\n"
 "Language-Team: \n"
@@ -47,7 +47,7 @@ msgstr ""
 msgid "Coroutine object"
 msgstr "协程对象"
 
-#: of pywebio.session.eval_js pywebio.session.get_info pywebio.session.run_async
+#: of pywebio.session.eval_js pywebio.session.run_async
 msgid "Returns"
 msgstr ""
 
@@ -111,8 +111,7 @@ msgstr "下载保存为的文件名"
 msgid "File content. It is a bytes-like object"
 msgstr "文件内容. 类型为 bytes-like object"
 
-#: of pywebio.session.download:6 pywebio.session.eval_js:9
-#: pywebio.session.get_info:40
+#: of pywebio.session:126 pywebio.session.download:6 pywebio.session.eval_js:9
 msgid "Example:"
 msgstr ""
 
@@ -436,61 +435,17 @@ msgstr "是否在新窗口打开,默认为 `True`"
 msgid "See also: :ref:`Server mode <server_and_script_mode>`"
 msgstr "参见: :ref:`Server 模式 <server_and_script_mode>`"
 
-#: of pywebio.session.get_info:1
-msgid "Get information about the current session"
-msgstr "获取当前会话的相关信息"
-
-#: of pywebio.session.get_info:3
-msgid ""
-"Object of session information, whose attributes are:  * ``user_agent`` : The "
-"Object of the user browser information, whose attributes are       * "
-"``is_mobile`` (bool): whether user agent is identified as a mobile phone "
-"(iPhone, Android phones, Blackberry, Windows Phone devices etc)      * "
-"``is_tablet`` (bool): whether user agent is identified as a tablet device "
-"(iPad, Kindle Fire, Nexus 7 etc)      * ``is_pc`` (bool): whether user agent is "
-"identified to be running a traditional \"desktop\" OS (Windows, OS X, "
-"Linux)      * ``is_touch_capable`` (bool): whether user agent has touch "
-"capabilities       * ``browser.family`` (str): Browser family. such as 'Mobile "
-"Safari'      * ``browser.version`` (tuple): Browser version. such as (5, "
-"1)      * ``browser.version_string`` (str): Browser version string. such as "
-"'5.1'       * ``os.family`` (str): User OS family. such as 'iOS'      * ``os."
-"version`` (tuple): User OS version. such as (5, 1)      * ``os.version_string`` "
-"(str): User OS version string. such as '5.1'       * ``device.family`` (str): "
-"User agent's device family. such as 'iPhone'      * ``device.brand`` (str): "
-"Device brand. such as 'Apple'      * ``device.model`` (str): Device model. such "
-"as 'iPhone'  * ``user_language`` (str): Language used by the user's operating "
-"system. (e.g., ``'zh-CN'``) * ``server_host`` (str): PyWebIO server host, "
-"including domain and port, the port can be omitted when 80. * ``origin`` (str): "
-"Indicate where the user from. Including protocol, host, and port parts. Such as "
-"``'http://localhost:8080'`` .   It may be empty, but it is guaranteed to have a "
-"value when the user's page address is not under the server host. (that is, the "
-"host, port part are inconsistent with ``server_host``). * ``user_ip`` (str): "
-"User's ip address. * ``backend`` (str): The current PyWebIO backend server "
-"implementation. The possible values are ``'tornado'``, ``'flask'``, "
-"``'django'`` , ``'aiohttp'``. * ``request`` (object): The request object when "
-"creating the current session. Depending on the backend server, the type of "
-"``request`` can be:       * When using Tornado, ``request`` is instance "
-"of        `tornado.httputil.HTTPServerRequest <https://www.tornadoweb.org/en/"
-"stable/httputil.html#tornado.httputil.HTTPServerRequest>`_      * When using "
-"Flask, ``request`` is instance of `flask.Request <https://flask.palletsprojects."
-"com/en/1.1.x/api/#incoming-request-data>`_      * When using Django, "
-"``request`` is instance of `django.http.HttpRequest <https://docs.djangoproject."
-"com/en/3.0/ref/request-response/#django.http.HttpRequest>`_      * When using "
-"aiohttp, ``request`` is instance of `aiohttp.web.BaseRequest <https://docs."
-"aiohttp.org/en/stable/web_reference.html#aiohttp.web.BaseRequest>`_"
-msgstr ""
-
-#: of pywebio.session.get_info:3
-msgid "Object of session information, whose attributes are:"
+#: of pywebio.session:89
+msgid "The session information data object, whose attributes are:"
 msgstr "表示会话信息的对象,属性有:"
 
-#: of pywebio.session.get_info:5
+#: of pywebio.session:91
 msgid ""
 "``user_agent`` : The Object of the user browser information, whose attributes "
 "are"
 msgstr "``user_agent`` : 表示用户浏览器信息的对象,属性有"
 
-#: of pywebio.session.get_info:7
+#: of pywebio.session:93
 msgid ""
 "``is_mobile`` (bool): whether user agent is identified as a mobile phone "
 "(iPhone, Android phones, Blackberry, Windows Phone devices etc)"
@@ -498,7 +453,7 @@ msgstr ""
 "``is_mobile`` (bool): 用户使用的设备是否为手机 (比如 iPhone, Android phones, "
 "Blackberry, Windows Phone 等设备)"
 
-#: of pywebio.session.get_info:8
+#: of pywebio.session:94
 msgid ""
 "``is_tablet`` (bool): whether user agent is identified as a tablet device "
 "(iPad, Kindle Fire, Nexus 7 etc)"
@@ -506,7 +461,7 @@ msgstr ""
 "``is_tablet`` (bool): 用户使用的设备是否为平板 (比如 iPad, Kindle Fire, Nexus 7 "
 "等设备)"
 
-#: of pywebio.session.get_info:9
+#: of pywebio.session:95
 msgid ""
 "``is_pc`` (bool): whether user agent is identified to be running a traditional "
 "\"desktop\" OS (Windows, OS X, Linux)"
@@ -514,53 +469,53 @@ msgstr ""
 "``is_pc`` (bool): 用户使用的设备是否为桌面电脑 (比如运行 Windows, OS X, Linux 的"
 "设备)"
 
-#: of pywebio.session.get_info:10
+#: of pywebio.session:96
 msgid "``is_touch_capable`` (bool): whether user agent has touch capabilities"
 msgstr "``is_touch_capable`` (bool): 用户使用的设备是否支持触控"
 
-#: of pywebio.session.get_info:12
+#: of pywebio.session:98
 msgid "``browser.family`` (str): Browser family. such as 'Mobile Safari'"
 msgstr "``browser.family`` (str): 浏览器家族. 比如 'Mobile Safari'"
 
-#: of pywebio.session.get_info:13
+#: of pywebio.session:99
 msgid "``browser.version`` (tuple): Browser version. such as (5, 1)"
 msgstr "``browser.version`` (tuple): 浏览器版本元组. 比如 (5, 1)"
 
-#: of pywebio.session.get_info:14
+#: of pywebio.session:100
 msgid "``browser.version_string`` (str): Browser version string. such as '5.1'"
 msgstr "``browser.version_string`` (str): 浏览器版本字符串. 比如  '5.1'"
 
-#: of pywebio.session.get_info:16
+#: of pywebio.session:102
 msgid "``os.family`` (str): User OS family. such as 'iOS'"
 msgstr "``os.family`` (str): 操作系统家族. 比如 'iOS'"
 
-#: of pywebio.session.get_info:17
+#: of pywebio.session:103
 msgid "``os.version`` (tuple): User OS version. such as (5, 1)"
 msgstr "``os.version`` (tuple): 操作系统版本元组. 比如 (5, 1)"
 
-#: of pywebio.session.get_info:18
+#: of pywebio.session:104
 msgid "``os.version_string`` (str): User OS version string. such as '5.1'"
 msgstr "``os.version_string`` (str): 操作系统版本字符串. 比如 '5.1'"
 
-#: of pywebio.session.get_info:20
+#: of pywebio.session:106
 msgid "``device.family`` (str): User agent's device family. such as 'iPhone'"
 msgstr "``device.family`` (str): 设备家族. 比如 'iPhone'"
 
-#: of pywebio.session.get_info:21
+#: of pywebio.session:107
 msgid "``device.brand`` (str): Device brand. such as 'Apple'"
 msgstr "``device.brand`` (str): 设备品牌. 比如 'Apple'"
 
-#: of pywebio.session.get_info:22
+#: of pywebio.session:108
 msgid "``device.model`` (str): Device model. such as 'iPhone'"
 msgstr "``device.model`` (str): 设备型号. 比如 'iPhone'"
 
-#: of pywebio.session.get_info:24
+#: of pywebio.session:110
 msgid ""
 "``user_language`` (str): Language used by the user's operating system. (e.g., "
 "``'zh-CN'``)"
 msgstr "``user_language`` (str): 用户操作系统使用的语言. 比如 ``'zh-CN'``"
 
-#: of pywebio.session.get_info:25
+#: of pywebio.session:111
 msgid ""
 "``server_host`` (str): PyWebIO server host, including domain and port, the port "
 "can be omitted when 80."
@@ -568,7 +523,7 @@ msgstr ""
 "``server_host`` (str): 当前会话的服务器host,包含域名和端口,端口为80时可以被省"
 "略"
 
-#: of pywebio.session.get_info:26
+#: of pywebio.session:112
 msgid ""
 "``origin`` (str): Indicate where the user from. Including protocol, host, and "
 "port parts. Such as ``'http://localhost:8080'`` . It may be empty, but it is "
@@ -580,11 +535,11 @@ msgstr ""
 "可能为空,但保证当用户的页面地址不在当前服务器下(即 主机、端口部分和 "
 "``server_host`` 不一致)时有值."
 
-#: of pywebio.session.get_info:28
+#: of pywebio.session:114
 msgid "``user_ip`` (str): User's ip address."
 msgstr "用户的ip地址."
 
-#: of pywebio.session.get_info:29
+#: of pywebio.session:115
 msgid ""
 "``backend`` (str): The current PyWebIO backend server implementation. The "
 "possible values are ``'tornado'``, ``'flask'``, ``'django'`` , ``'aiohttp'``."
@@ -592,7 +547,7 @@ msgstr ""
 "当前PyWebIO使用的后端Server实现. 可能出现的值有 ``'tornado'`` , ``'flask'`` , "
 "``'django'`` , ``'aiohttp'``."
 
-#: of pywebio.session.get_info:30
+#: of pywebio.session:116
 msgid ""
 "``request`` (object): The request object when creating the current session. "
 "Depending on the backend server, the type of ``request`` can be:"
@@ -600,7 +555,7 @@ msgstr ""
 "创建当前会话时的Web请求对象. 根据PyWebIO使用的后端Server不同,``request`` 的类型"
 "也不同:"
 
-#: of pywebio.session.get_info:32
+#: of pywebio.session:118
 msgid ""
 "When using Tornado, ``request`` is instance of `tornado.httputil."
 "HTTPServerRequest <https://www.tornadoweb.org/en/stable/httputil.html#tornado."
@@ -610,7 +565,7 @@ msgstr ""
 "www.tornadoweb.org/en/stable/httputil.html#tornado.httputil."
 "HTTPServerRequest>`_ 实例"
 
-#: of pywebio.session.get_info:34
+#: of pywebio.session:120
 msgid ""
 "When using Flask, ``request`` is instance of `flask.Request <https://flask."
 "palletsprojects.com/en/1.1.x/api/#incoming-request-data>`_"
@@ -618,7 +573,7 @@ msgstr ""
 "使用Flask后端时, ``request`` 为 `flask.Request <https://flask.palletsprojects."
 "com/en/1.1.x/api/#incoming-request-data>`_ 实例"
 
-#: of pywebio.session.get_info:35
+#: of pywebio.session:121
 msgid ""
 "When using Django, ``request`` is instance of `django.http.HttpRequest <https://"
 "docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest>`_"
@@ -626,7 +581,7 @@ msgstr ""
 "使用Django后端时, ``request`` 为 `django.http.HttpRequest <https://docs."
 "djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest>`_ 实例"
 
-#: of pywebio.session.get_info:36
+#: of pywebio.session:122
 msgid ""
 "When using aiohttp, ``request`` is instance of `aiohttp.web.BaseRequest "
 "<https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web."
@@ -635,7 +590,7 @@ msgstr ""
 "使用aiohttp后端时, ``request`` 为 `aiohttp.web.BaseRequest <https://docs."
 "aiohttp.org/en/stable/web_reference.html#aiohttp.web.BaseRequest>`_ 实例"
 
-#: of pywebio.session.get_info:38
+#: of pywebio.session:124
 msgid ""
 "The ``user_agent`` attribute of the session information object is parsed by the "
 "user-agents library. See https://github.com/selwin/python-user-agents#usage"
@@ -643,17 +598,26 @@ msgstr ""
 "会话信息对象的 ``user_agent`` 属性是通过 user-agents 库进行解析生成的。参见 "
 "https://github.com/selwin/python-user-agents#usage"
 
-#: of pywebio.session.get_info:42
+#: of pywebio.session:128
 msgid ""
 "import json\n"
+"from pywebio import session\n"
 "\n"
-"info = get_info()\n"
 "put_code(json.dumps({\n"
-"    k: str(v)\n"
-"    for k,v in info.items()\n"
+"    k: str(getattr(session.info, k))\n"
+"    for k in ['user_agent', 'user_language', 'server_host',\n"
+"              'origin', 'user_ip', 'backend', 'request']\n"
 "}, indent=4), 'json')"
 msgstr ""
 
+#: of pywebio.session.get_info:1
+msgid "Get information about the current session"
+msgstr "获取当前会话的相关信息"
+
+#: of pywebio.session.get_info:3
+msgid "Use `info <pywebio.session.info>` instead."
+msgstr ""
+
 #: of pywebio.session.coroutinebased.TaskHandler:1
 msgid "The handler of coroutine task"
 msgstr "协程任务句柄"

+ 80 - 51
pywebio/session/__init__.py

@@ -85,6 +85,61 @@ r"""
 .. autofunction:: data
 .. autofunction:: set_env
 .. autofunction:: go_app
+
+.. data:: info
+
+    The session information data object, whose attributes are:
+
+       * ``user_agent`` : The Object of the user browser information, whose attributes are
+
+            * ``is_mobile`` (bool): whether user agent is identified as a mobile phone (iPhone, Android phones, Blackberry, Windows Phone devices etc)
+            * ``is_tablet`` (bool): whether user agent is identified as a tablet device (iPad, Kindle Fire, Nexus 7 etc)
+            * ``is_pc`` (bool): whether user agent is identified to be running a traditional "desktop" OS (Windows, OS X, Linux)
+            * ``is_touch_capable`` (bool): whether user agent has touch capabilities
+
+            * ``browser.family`` (str): Browser family. such as 'Mobile Safari'
+            * ``browser.version`` (tuple): Browser version. such as (5, 1)
+            * ``browser.version_string`` (str): Browser version string. such as '5.1'
+
+            * ``os.family`` (str): User OS family. such as 'iOS'
+            * ``os.version`` (tuple): User OS version. such as (5, 1)
+            * ``os.version_string`` (str): User OS version string. such as '5.1'
+
+            * ``device.family`` (str): User agent's device family. such as 'iPhone'
+            * ``device.brand`` (str): Device brand. such as 'Apple'
+            * ``device.model`` (str): Device model. such as 'iPhone'
+
+       * ``user_language`` (str): Language used by the user's operating system. (e.g., ``'zh-CN'``)
+       * ``server_host`` (str): PyWebIO server host, including domain and port, the port can be omitted when 80.
+       * ``origin`` (str): Indicate where the user from. Including protocol, host, and port parts. Such as ``'http://localhost:8080'`` .
+         It may be empty, but it is guaranteed to have a value when the user's page address is not under the server host. (that is, the host, port part are inconsistent with ``server_host``).
+       * ``user_ip`` (str): User's ip address.
+       * ``backend`` (str): The current PyWebIO backend server implementation. The possible values are ``'tornado'``, ``'flask'``, ``'django'`` , ``'aiohttp'``.
+       * ``request`` (object): The request object when creating the current session. Depending on the backend server, the type of ``request`` can be:
+
+            * When using Tornado, ``request`` is instance of
+              `tornado.httputil.HTTPServerRequest <https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest>`_
+            * When using Flask, ``request`` is instance of `flask.Request <https://flask.palletsprojects.com/en/1.1.x/api/#incoming-request-data>`_
+            * When using Django, ``request`` is instance of `django.http.HttpRequest <https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest>`_
+            * When using aiohttp, ``request`` is instance of `aiohttp.web.BaseRequest <https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.BaseRequest>`_
+
+    The ``user_agent`` attribute of the session information object is parsed by the user-agents library. See https://github.com/selwin/python-user-agents#usage
+
+    Example:
+
+    .. exportable-codeblock::
+        :name: get_info
+        :summary: `session.info` usage
+
+        import json
+        from pywebio.session import info as session_info
+
+        put_code(json.dumps({
+            k: str(getattr(session_info, k))
+            for k in ['user_agent', 'user_language', 'server_host',
+                      'origin', 'user_ip', 'backend', 'request']
+        }, indent=4), 'json')
+
 .. autofunction:: get_info
 
 .. autoclass:: pywebio.session.coroutinebased.TaskHandler
@@ -95,18 +150,21 @@ import threading
 from base64 import b64encode
 from functools import wraps
 
+import user_agents
+
 from .base import Session
 from .coroutinebased import CoroutineBasedSession
 from .threadbased import ThreadBasedSession, ScriptModeSession
 from ..exceptions import SessionNotFoundException, SessionException
-from ..utils import iscoroutinefunction, isgeneratorfunction, run_as_function, to_coroutine, ObjectDictProxy
+from ..utils import iscoroutinefunction, isgeneratorfunction, run_as_function, to_coroutine, ObjectDictProxy, \
+    ReadOnlyObjectDict
 
 # 当前进程中正在使用的会话实现的列表
 # List of session implementations currently in use
 _active_session_cls = []
 
 __all__ = ['run_async', 'run_asyncio_coroutine', 'register_thread', 'hold', 'defer_call', 'data', 'get_info',
-           'run_js', 'eval_js', 'download', 'set_env', 'go_app', 'local']
+           'run_js', 'eval_js', 'download', 'set_env', 'go_app', 'local', 'info']
 
 
 def register_session_implement_for_target(target_func):
@@ -435,58 +493,29 @@ def go_app(name, new_window=True):
     run_js('javascript:WebIO.openApp(app, new_window)', app=name, new_window=new_window)
 
 
-def get_info():
-    """Get information about the current session
-
-    :return: Object of session information, whose attributes are:
-
-       * ``user_agent`` : The Object of the user browser information, whose attributes are
-
-            * ``is_mobile`` (bool): whether user agent is identified as a mobile phone (iPhone, Android phones, Blackberry, Windows Phone devices etc)
-            * ``is_tablet`` (bool): whether user agent is identified as a tablet device (iPad, Kindle Fire, Nexus 7 etc)
-            * ``is_pc`` (bool): whether user agent is identified to be running a traditional "desktop" OS (Windows, OS X, Linux)
-            * ``is_touch_capable`` (bool): whether user agent has touch capabilities
-
-            * ``browser.family`` (str): Browser family. such as 'Mobile Safari'
-            * ``browser.version`` (tuple): Browser version. such as (5, 1)
-            * ``browser.version_string`` (str): Browser version string. such as '5.1'
-
-            * ``os.family`` (str): User OS family. such as 'iOS'
-            * ``os.version`` (tuple): User OS version. such as (5, 1)
-            * ``os.version_string`` (str): User OS version string. such as '5.1'
-
-            * ``device.family`` (str): User agent's device family. such as 'iPhone'
-            * ``device.brand`` (str): Device brand. such as 'Apple'
-            * ``device.model`` (str): Device model. such as 'iPhone'
-
-       * ``user_language`` (str): Language used by the user's operating system. (e.g., ``'zh-CN'``)
-       * ``server_host`` (str): PyWebIO server host, including domain and port, the port can be omitted when 80.
-       * ``origin`` (str): Indicate where the user from. Including protocol, host, and port parts. Such as ``'http://localhost:8080'`` .
-         It may be empty, but it is guaranteed to have a value when the user's page address is not under the server host. (that is, the host, port part are inconsistent with ``server_host``).
-       * ``user_ip`` (str): User's ip address.
-       * ``backend`` (str): The current PyWebIO backend server implementation. The possible values are ``'tornado'``, ``'flask'``, ``'django'`` , ``'aiohttp'``.
-       * ``request`` (object): The request object when creating the current session. Depending on the backend server, the type of ``request`` can be:
-
-            * When using Tornado, ``request`` is instance of
-              `tornado.httputil.HTTPServerRequest <https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest>`_
-            * When using Flask, ``request`` is instance of `flask.Request <https://flask.palletsprojects.com/en/1.1.x/api/#incoming-request-data>`_
-            * When using Django, ``request`` is instance of `django.http.HttpRequest <https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest>`_
-            * When using aiohttp, ``request`` is instance of `aiohttp.web.BaseRequest <https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.BaseRequest>`_
+# session info data object
+info = ReadOnlyObjectDict(lambda: get_current_session().info)  # type: _SessionInfoType
 
-    The ``user_agent`` attribute of the session information object is parsed by the user-agents library. See https://github.com/selwin/python-user-agents#usage
 
-    Example:
+class _SessionInfoType:
+    user_agent = None  # type: user_agents.parsers.UserAgent
+    user_language = ''  # e.g.: zh-CN
+    server_host = ''  # e.g.: localhost:8080
+    origin = ''  # e.g.: http://localhost:8080
+    user_ip = ''
+    backend = ''  # one of ['tornado', 'flask', 'django', 'aiohttp']
+    request = None
 
-    .. exportable-codeblock::
-        :name: get_info
-        :summary: `get_info()` usage
 
-        import json
+def get_info():
+    """Get information about the current session
 
-        info = get_info()
-        put_code(json.dumps({
-            k: str(v)
-            for k,v in info.items()
-        }, indent=4), 'json')
+    .. deprecated:: 1.2
+        Use `info <pywebio.session.info>` instead.
     """
-    return get_current_session().info
+    global info
+
+    import warnings
+    warnings.warn("`pywebio.session.get_info()` is deprecated in v1.2 and will remove in the future version, "
+                  "please use `pywebio.session.info` instead", DeprecationWarning, stacklevel=2)
+    return info

+ 4 - 4
pywebio/session/base.py

@@ -5,7 +5,7 @@ from collections import defaultdict
 
 import user_agents
 
-from ..utils import ObjectDict, catch_exp_call
+from ..utils import catch_exp_call
 
 logger = logging.getLogger(__name__)
 
@@ -125,7 +125,7 @@ class Session:
         type, value, tb = sys.exc_info()
         lines = traceback.format_exception(type, value, tb)
         traceback_msg = ''.join(lines)
-        traceback_msg = 'Internal Server Error\n'+traceback_msg
+        traceback_msg = 'Internal Server Error\n' + traceback_msg
         try:
             toast('应用发生内部错误', duration=1, color='error')
             run_js("console.error(traceback_msg)", traceback_msg=traceback_msg)
@@ -167,6 +167,6 @@ def get_session_info_from_headers(headers):
     user_language = headers.get('Accept-Language', '').split(',', 1)[0].split(' ', 1)[0].split(';', 1)[0]
     server_host = headers.get('Host', '')
     origin = headers.get('Origin', '')
-    session_info = ObjectDict(user_agent=ua, user_language=user_language,
-                              server_host=server_host, origin=origin)
+    session_info = dict(user_agent=ua, user_language=user_language,
+                        server_host=server_host, origin=origin)
     return session_info

+ 10 - 10
pywebio/utils.py

@@ -109,18 +109,18 @@ class ObjectDictProxy:
             pass
 
 
-class ObjectDict(dict):
-    """
-    Object like dict, every dict[key] can visite by dict.key
+class ReadOnlyObjectDict(ObjectDictProxy):
+    def __delitem__(self, key):
+        raise NotImplementedError
 
-    If dict[key] is `Get`, calculate it's value.
-    """
+    def __delattr__(self, item):
+        raise NotImplementedError
 
-    def __getattr__(self, name):
-        ret = self.__getitem__(name)
-        if hasattr(ret, '__get__'):
-            return ret.__get__(self, ObjectDict)
-        return ret
+    def __setitem__(self, key, item):
+        raise NotImplementedError
+
+    def __setattr__(self, key, value):
+        raise NotImplementedError
 
 
 def catch_exp_call(func, logger):