# HG changeset patch # User Goffi # Date 1684749464 -7200 # Node ID 5ea06e8b06ed403fed0d055471fc9bd3f1b3850a # Parent 106bae41f5c86de4be0f74213fa074837cabb107 browser: make bridge API closer to the one use with other frontends: `bridge.AsyncBridge` is not used instead of `aio_bridge.Bridge` diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/_browser/__init__.py --- a/libervia/pages/_browser/__init__.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/_browser/__init__.py Mon May 22 11:57:44 2023 +0200 @@ -2,4 +2,4 @@ # we create a bridge instance to receive signals -bridge.bridge() +bridge.Bridge() diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/_browser/aio_bridge.py --- a/libervia/pages/_browser/aio_bridge.py Sat Apr 08 13:44:11 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -from browser import window, aio -import javascript - - -class BridgeException(Exception): - """An exception which has been raised from the backend and arrived to the frontend.""" - - def __init__(self, name, message="", condition=""): - """ - - @param name (str): full exception class name (with module) - @param message (str): error message - @param condition (str) : error condition - """ - Exception.__init__(self) - self.fullname = str(name) - self.message = str(message) - self.condition = str(condition) if condition else "" - self.module, __, self.classname = str(self.fullname).rpartition(".") - - def __str__(self): - return f"{self.classname}: {self.message or ''}" - - def __eq__(self, other): - return self.classname == other - - -class bridge: - - def __getattr__(self, attr): - return lambda *args, **kwargs: self.call(attr, *args, **kwargs) - - async def call(self, method_name, *args, **kwargs): - data = javascript.JSON.stringify({ - "args": args, - "kwargs": kwargs, - }) - url = f"/_bridge/{method_name}" - r = await aio.post( - url, - headers={ - 'X-Csrf-Token': window.csrf_token, - }, - data=data, - ) - - if r.status == 200: - return javascript.JSON.parse(r.data) - elif r.status == 502: - ret = javascript.JSON.parse(r.data) - raise BridgeException(ret['fullname'], ret['message'], ret['condition']) - else: - print(f"bridge called failed: code: {r.status}, text: {r.statusText}") - raise BridgeException("InternalError", r.statusText) diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/_browser/bridge.py --- a/libervia/pages/_browser/bridge.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/_browser/bridge.py Mon May 22 11:57:44 2023 +0200 @@ -1,4 +1,4 @@ -from browser import window, timer, console as log +from browser import window, aio, timer, console as log import time import random import json @@ -11,6 +11,29 @@ log.info(f"TAB ID is {tab_id}") +class BridgeException(Exception): + """An exception which has been raised from the backend and arrived to the frontend.""" + + def __init__(self, name, message="", condition=""): + """ + + @param name (str): full exception class name (with module) + @param message (str): error message + @param condition (str) : error condition + """ + Exception.__init__(self) + self.fullname = str(name) + self.message = str(message) + self.condition = str(condition) if condition else "" + self.module, __, self.classname = str(self.fullname).rpartition(".") + + def __str__(self): + return f"{self.classname}: {self.message or ''}" + + def __eq__(self, other): + return self.classname == other + + class WebSocket: def __init__(self, broadcast_channel): @@ -243,12 +266,12 @@ }) -class bridge: +class Bridge: bc: BroadcastChannel | None = None def __init__(self) -> None: - if bridge.bc is None: - bridge.bc = BroadcastChannel() + if Bridge.bc is None: + Bridge.bc = BroadcastChannel() def __getattr__(self, attr): return lambda *args, **kwargs: self.call(attr, *args, **kwargs) @@ -268,7 +291,7 @@ errback(ret) else: log.error( - f"bridge called failed: code: {xhr.response}, text: {xhr.statusText}" + f"bridge call failed: code: {xhr.response}, text: {xhr.statusText}" ) if errback is not None: errback({"fullname": "BridgeInternalError", "message": xhr.statusText}) @@ -289,3 +312,37 @@ def register_signal(self, signal: str, handler, iface=None) -> None: BroadcastChannel.handlers.setdefault(signal, []).append(handler) log.debug(f"signal {signal} has been registered") + + +class AsyncBridge: + + def __getattr__(self, attr): + return lambda *args, **kwargs: self.call(attr, *args, **kwargs) + + async def call(self, method_name, *args, **kwargs): + print(f"calling {method_name}") + data = javascript.JSON.stringify({ + "args": args, + "kwargs": kwargs, + }) + url = f"/_bridge/{method_name}" + r = await aio.post( + url, + headers={ + 'X-Csrf-Token': window.csrf_token, + }, + data=data, + ) + + if r.status == 200: + return javascript.JSON.parse(r.data) + elif r.status == 502: + ret = javascript.JSON.parse(r.data) + raise BridgeException(ret['fullname'], ret['message'], ret['condition']) + else: + print(f"bridge called failed: code: {r.status}, text: {r.statusText}") + raise BridgeException("InternalError", r.statusText) + + def register_signal(self, signal: str, handler, iface=None) -> None: + BroadcastChannel.handlers.setdefault(signal, []).append(handler) + log.debug(f"signal {signal} has been registered") diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/_browser/cache.py --- a/libervia/pages/_browser/cache.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/_browser/cache.py Mon May 22 11:57:44 2023 +0200 @@ -2,10 +2,10 @@ from browser.local_storage import storage from javascript import JSON from dialog import notification -from bridge import bridge +from bridge import Bridge session_uuid = window.session_uuid -bridge = bridge() +bridge = Bridge() # XXX: we don't use browser.object_storage because it is affected by # https://github.com/brython-dev/brython/issues/1467 and mixing local_storage.storage diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/_browser/editor.py --- a/libervia/pages/_browser/editor.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/_browser/editor.py Mon May 22 11:57:44 2023 +0200 @@ -4,11 +4,11 @@ from browser.local_storage import storage from browser.object_storage import ObjectStorage from javascript import JSON -from aio_bridge import bridge, BridgeException +from bridge import AsyncBridge as Bridge, BridgeException from template import Template import dialog -bridge = bridge() +bridge = Bridge() object_storage = ObjectStorage(storage) profile = window.profile diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/_browser/invitation.py --- a/libervia/pages/_browser/invitation.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/_browser/invitation.py Mon May 22 11:57:44 2023 +0200 @@ -1,11 +1,11 @@ from browser import document, window, timer -from bridge import bridge +from bridge import Bridge from template import Template import dialog from cache import cache import javascript -bridge = bridge() +bridge = Bridge() # we use JS RegExp because Python's re is really long to import in Brython # FIXME: this is a naive JID regex, a more accurate should be used instead jid_re = javascript.RegExp.new(r"^\w+@\w+\.\w+") diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/events/_browser/__init__.py --- a/libervia/pages/events/_browser/__init__.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/events/_browser/__init__.py Mon May 22 11:57:44 2023 +0200 @@ -1,9 +1,9 @@ from browser import DOMNode, document, aio from javascript import JSON -from aio_bridge import bridge, BridgeException +from bridge import AsyncBridge as Bridge, BridgeException import dialog -bridge = bridge() +bridge = Bridge() async def on_delete(evt): diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/lists/_browser/__init__.py --- a/libervia/pages/lists/_browser/__init__.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/lists/_browser/__init__.py Mon May 22 11:57:44 2023 +0200 @@ -1,9 +1,9 @@ from browser import DOMNode, document, aio from javascript import JSON -from aio_bridge import bridge, BridgeException +from bridge import AsyncBridge as Bridge, BridgeException import dialog -bridge = bridge() +bridge = Bridge() async def on_delete(evt): diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/lists/view/_browser/__init__.py --- a/libervia/pages/lists/view/_browser/__init__.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/lists/view/_browser/__init__.py Mon May 22 11:57:44 2023 +0200 @@ -1,11 +1,11 @@ from browser import window, document, aio, bind from invitation import InvitationManager from javascript import JSON -from aio_bridge import bridge, BridgeException +from bridge import Async as Bridge, BridgeException import dialog -bridge = bridge() +bridge = Bridge() lists_ns = window.lists_ns pubsub_service = window.pubsub_service pubsub_node = window.pubsub_node diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/lists/view_item/_browser/__init__.py --- a/libervia/pages/lists/view_item/_browser/__init__.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/lists/view_item/_browser/__init__.py Mon May 22 11:57:44 2023 +0200 @@ -1,5 +1,5 @@ from browser import document, window, aio -from aio_bridge import bridge +from bridge import AsyncBridge as Bridge import dialog try: @@ -9,7 +9,7 @@ except AttributeError: can_delete = False else: - bridge = bridge() + bridge = Bridge() can_delete = True diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/photos/_browser/__init__.py --- a/libervia/pages/photos/_browser/__init__.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/photos/_browser/__init__.py Mon May 22 11:57:44 2023 +0200 @@ -1,9 +1,9 @@ from browser import window, bind, DOMNode from javascript import JSON -from bridge import bridge +from bridge import Bridge import dialog -bridge = bridge() +bridge = Bridge() def album_delete_cb(item_elt, item): diff -r 106bae41f5c8 -r 5ea06e8b06ed libervia/pages/photos/album/_browser/__init__.py --- a/libervia/pages/photos/album/_browser/__init__.py Sat Apr 08 13:44:11 2023 +0200 +++ b/libervia/pages/photos/album/_browser/__init__.py Mon May 22 11:57:44 2023 +0200 @@ -1,7 +1,6 @@ from browser import document, window, bind, html, DOMNode, aio from javascript import JSON -from bridge import bridge -from aio_bridge import bridge as AIOBridge +from bridge import Bridge, AsyncBridge from template import Template import dialog from slideshow import SlideShow @@ -19,8 +18,8 @@ affiliations = window.affiliations.to_dict() except AttributeError: pass -bridge = bridge() -aio_bridge = AIOBridge() +bridge = Bridge() +async_bridge = AsyncBridge() alt_media_player.install_if_needed() @@ -192,7 +191,7 @@ img_name = img_elt.src.rsplit('/', 1)[-1] img_size = img_blob.size - slot = await aio_bridge.file_http_upload_get_slot( + slot = await async_bridge.file_http_upload_get_slot( img_name, img_size, '', @@ -209,7 +208,7 @@ return extra = {"thumb_url": get_url} album_name = files_path.rsplit('/', 1)[-1] - await aio_bridge.interests_file_sharing_register( + await async_bridge.interests_file_sharing_register( files_service, "photos", "",