Mercurial > libervia-web
annotate libervia/server/tasks/implicit/task_brython.py @ 1504:409d10211b20
server, browser: dynamic pages refactoring:
dynamic pages has been reworked, to change the initial basic implementation.
Pages are now dynamic by default, and a websocket is established by the first connected
page of a session. The socket is used to transmit bridge signals, and then the signal is
broadcasted to other tabs using broadcast channel.
If the connecting tab is closed, an other one is chosen.
Some tests are made to retry connecting in case of problem, and sometimes reload the pages
(e.g. if profile is connected).
Signals (or other data) are cached during reconnection phase, to avoid lost of data.
All previous partial rendering mechanism have been removed, chat page is temporarily not
working anymore, but will be eventually redone (one of the goal of this work is to have
proper chat).
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 01 Mar 2023 18:02:44 +0100 |
parents | 2796e73ed50c |
children | 106bae41f5c8 |
rev | line source |
---|---|
1247 | 1 #!/ur/bin/env python3 |
2 | |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
3 from ast import literal_eval |
1247 | 4 import json |
5 from pathlib import Path | |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
6 import shutil |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
7 from typing import Any, Dict |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
8 |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
9 from sat.core import exceptions |
1247 | 10 from sat.core.i18n import _ |
11 from sat.core.log import getLogger | |
1282
0e4e413eb8db
server: user new OrderedSet to handle scripts:
Goffi <goffi@goffi.org>
parents:
1279
diff
changeset
|
12 from sat.tools.common import utils |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
13 |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
14 from libervia.server.classes import Script |
1247 | 15 from libervia.server.constants import Const as C |
16 from libervia.server.tasks import task | |
17 | |
18 | |
19 log = getLogger(__name__) | |
20 | |
21 | |
22 class Task(task.Task): | |
23 | |
24 def prepare(self): | |
25 if "brython" not in self.resource.browser_modules: | |
1326
089742e065e3
pages (files/list, photos/album): updated thumbnails size limits
Goffi <goffi@goffi.org>
parents:
1282
diff
changeset
|
26 raise exceptions.CancelError("No brython module found") |
1247 | 27 |
28 brython_js = self.build_path / "brython.js" | |
29 if not brython_js.is_file(): | |
30 installed_ver = None | |
31 else: | |
32 with brython_js.open() as f: | |
33 for line in f: | |
34 if line.startswith('// implementation ['): | |
35 installed_ver = literal_eval(line[18:])[:3] | |
36 log.debug( | |
37 f"brython v{'.'.join(str(v) for v in installed_ver)} already " | |
38 f"installed") | |
39 break | |
40 else: | |
41 log.warning( | |
42 f"brython file at {brython_js} doesn't has implementation " | |
43 f"version" | |
44 ) | |
45 installed_ver = None | |
46 | |
1250
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
47 try: |
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
48 import brython |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
49 from brython import version as brython_version |
1250
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
50 except ModuleNotFoundError as e: |
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
51 log.error('"brython" module is missing, can\'t use browser code for Brython') |
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
52 raise e |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
53 ver = [int(v) for v in brython_version.implementation.split('.')[:3]] |
1247 | 54 if ver != installed_ver: |
55 log.info(_("Installing Brython v{version}").format( | |
56 version='.'.join(str(v) for v in ver))) | |
57 data_path = Path(brython.__file__).parent / 'data' | |
58 # shutil has blocking method, but the task is run before we start | |
59 # the web server, so it's not a big deal | |
60 shutil.copyfile(data_path / "brython.js", brython_js) | |
1279
2d1ceb026d0e
tasks (brython): copy and load `brython_stdlib.js`
Goffi <goffi@goffi.org>
parents:
1268
diff
changeset
|
61 shutil.copy(data_path / "brython_stdlib.js", self.build_path) |
1247 | 62 else: |
63 log.debug("Brython is already installed") | |
64 | |
65 self.WATCH_DIRS = [] | |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
66 self.set_common_scripts() |
1247 | 67 |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
68 def set_common_scripts(self): |
1247 | 69 for dyn_data in self.resource.browser_modules["brython"]: |
70 url_hash = dyn_data['url_hash'] | |
71 import_url = f"/{C.BUILD_DIR}/{C.BUILD_DIR_DYN}/{url_hash}" | |
1282
0e4e413eb8db
server: user new OrderedSet to handle scripts:
Goffi <goffi@goffi.org>
parents:
1279
diff
changeset
|
72 dyn_data.setdefault('scripts', utils.OrderedSet()).update([ |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
73 Script(src=f"/{C.BUILD_DIR}/brython.js"), |
1279
2d1ceb026d0e
tasks (brython): copy and load `brython_stdlib.js`
Goffi <goffi@goffi.org>
parents:
1268
diff
changeset
|
74 Script(src=f"/{C.BUILD_DIR}/brython_stdlib.js"), |
1282
0e4e413eb8db
server: user new OrderedSet to handle scripts:
Goffi <goffi@goffi.org>
parents:
1279
diff
changeset
|
75 ]) |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
76 dyn_data.setdefault('template', {})['body_onload'] = self.get_body_onload( |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
77 extra_path=[import_url]) |
1247 | 78 self.WATCH_DIRS.append(dyn_data['path'].resolve()) |
79 | |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
80 def get_body_onload(self, debug=True, cache=True, extra_path=None): |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
81 on_load_opts: Dict[str, Any] = {"pythonpath": [f"/{C.BUILD_DIR}"]} |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
82 if debug: |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
83 on_load_opts["debug"] = 1 |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
84 if cache: |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
85 on_load_opts["cache"] = True |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
86 if extra_path is not None: |
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
87 on_load_opts["pythonpath"].extend(extra_path) |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
88 |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
89 return f"brython({json.dumps(on_load_opts)})" |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
90 |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
91 def copy_files(self, files_paths, dest): |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
92 for p in files_paths: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
93 log.debug(f"copying {p}") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
94 if p.is_dir(): |
1335
f2ce8072d89d
tasks (brython): don't copy `__pycache__` to build_dir + fixed recursive copy
Goffi <goffi@goffi.org>
parents:
1326
diff
changeset
|
95 if p.name == '__pycache__': |
f2ce8072d89d
tasks (brython): don't copy `__pycache__` to build_dir + fixed recursive copy
Goffi <goffi@goffi.org>
parents:
1326
diff
changeset
|
96 continue |
f2ce8072d89d
tasks (brython): don't copy `__pycache__` to build_dir + fixed recursive copy
Goffi <goffi@goffi.org>
parents:
1326
diff
changeset
|
97 shutil.copytree(p, dest / p.name) |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
98 else: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
99 shutil.copy(p, dest) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
100 |
1384
b61509c47cac
tasks (brython): fixed Brython scripts during dev mode reload
Goffi <goffi@goffi.org>
parents:
1335
diff
changeset
|
101 async def onDirEvent(self, host, filepath, flags): |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
102 self.set_common_scripts() |
1384
b61509c47cac
tasks (brython): fixed Brython scripts during dev mode reload
Goffi <goffi@goffi.org>
parents:
1335
diff
changeset
|
103 await self.manager.runTaskInstance(self) |
b61509c47cac
tasks (brython): fixed Brython scripts during dev mode reload
Goffi <goffi@goffi.org>
parents:
1335
diff
changeset
|
104 |
1247 | 105 def start(self): |
106 dyn_path = self.build_path / C.BUILD_DIR_DYN | |
107 for dyn_data in self.resource.browser_modules["brython"]: | |
108 url_hash = dyn_data['url_hash'] | |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
109 if url_hash is None: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
110 # root modules |
1256
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
111 url_prefix = dyn_data.get('url_prefix') |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
112 if url_prefix is None: |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
113 dest = self.build_path |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
114 init_dest_url = f"/{C.BUILD_DIR}/__init__.py" |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
115 else: |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
116 dest = self.build_path / url_prefix |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
117 dest.mkdir(exist_ok = True) |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
118 init_dest_url = f"/{C.BUILD_DIR}/{url_prefix}/__init__.py" |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
119 |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
120 self.copy_files(dyn_data['path'].glob('*py'), dest) |
1256
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
121 |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
122 init_file = dyn_data['path'] / '__init__.py' |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
123 if init_file.is_file(): |
1282
0e4e413eb8db
server: user new OrderedSet to handle scripts:
Goffi <goffi@goffi.org>
parents:
1279
diff
changeset
|
124 self.resource.dyn_data_common['scripts'].update([ |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
125 Script(src=f"/{C.BUILD_DIR}/brython.js"), |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
126 Script(src=f"/{C.BUILD_DIR}/brython_stdlib.js"), |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
127 Script(type='text/python', src=init_dest_url) |
1282
0e4e413eb8db
server: user new OrderedSet to handle scripts:
Goffi <goffi@goffi.org>
parents:
1279
diff
changeset
|
128 ]) |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
129 self.resource.dyn_data_common.setdefault( |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
130 "template", {})['body_onload'] = self.get_body_onload() |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
131 else: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
132 page_dyn_path = dyn_path / url_hash |
1335
f2ce8072d89d
tasks (brython): don't copy `__pycache__` to build_dir + fixed recursive copy
Goffi <goffi@goffi.org>
parents:
1326
diff
changeset
|
133 log.debug(f"using dynamic path at {page_dyn_path}") |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
134 if page_dyn_path.exists(): |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
135 log.debug("cleaning existing path") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
136 shutil.rmtree(page_dyn_path) |
1247 | 137 |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
138 page_dyn_path.mkdir(parents=True, exist_ok=True) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
139 log.debug("copying browser python files") |
1503
2796e73ed50c
tasks (brython): fix brython scripts loading.
Goffi <goffi@goffi.org>
parents:
1384
diff
changeset
|
140 self.copy_files(dyn_data['path'].iterdir(), page_dyn_path) |
1247 | 141 |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
142 script = Script( |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
143 type='text/python', |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
144 src=f"/{C.BUILD_DIR}/{C.BUILD_DIR_DYN}/{url_hash}/__init__.py" |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
145 ) |
1384
b61509c47cac
tasks (brython): fixed Brython scripts during dev mode reload
Goffi <goffi@goffi.org>
parents:
1335
diff
changeset
|
146 dyn_data.setdefault('scripts', utils.OrderedSet()).add(script) |