Mercurial > libervia-web
annotate libervia/server/tasks/implicit/task_brython.py @ 1276:cad8f24e23d4
pages: use a coroutine for renderPage:
renderPage is now a coroutine, and pages methods are launched using asDeferred, so they
can be coroutines too.
Full traceback is now logged for uncatched errors.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 19 Jun 2020 16:47:50 +0200 |
parents | e628724530ec |
children | 2d1ceb026d0e |
rev | line source |
---|---|
1247 | 1 #!/ur/bin/env python3 |
2 | |
3 import shutil | |
4 import json | |
5 from pathlib import Path | |
6 from ast import literal_eval | |
7 from sat.core.i18n import _ | |
8 from sat.core.log import getLogger | |
9 from sat.core import exceptions | |
10 from libervia.server.constants import Const as C | |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
11 from libervia.server.classes import Script |
1247 | 12 from libervia.server.tasks import task |
13 | |
14 | |
15 log = getLogger(__name__) | |
16 | |
17 | |
18 class Task(task.Task): | |
19 | |
20 def prepare(self): | |
21 if "brython" not in self.resource.browser_modules: | |
22 raise exceptions.CancelError(f"No brython module found") | |
23 | |
24 brython_js = self.build_path / "brython.js" | |
25 if not brython_js.is_file(): | |
26 installed_ver = None | |
27 else: | |
28 with brython_js.open() as f: | |
29 for line in f: | |
30 if line.startswith('// implementation ['): | |
31 installed_ver = literal_eval(line[18:])[:3] | |
32 log.debug( | |
33 f"brython v{'.'.join(str(v) for v in installed_ver)} already " | |
34 f"installed") | |
35 break | |
36 else: | |
37 log.warning( | |
38 f"brython file at {brython_js} doesn't has implementation " | |
39 f"version" | |
40 ) | |
41 installed_ver = None | |
42 | |
1250
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
43 try: |
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
44 import brython |
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
45 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
|
46 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
|
47 raise e |
1247 | 48 ver = [int(v) for v in brython.implementation.split('.')[:3]] |
49 if ver != installed_ver: | |
50 log.info(_("Installing Brython v{version}").format( | |
51 version='.'.join(str(v) for v in ver))) | |
52 data_path = Path(brython.__file__).parent / 'data' | |
53 # shutil has blocking method, but the task is run before we start | |
54 # the web server, so it's not a big deal | |
55 shutil.copyfile(data_path / "brython.js", brython_js) | |
56 else: | |
57 log.debug("Brython is already installed") | |
58 | |
59 self.WATCH_DIRS = [] | |
60 | |
61 for dyn_data in self.resource.browser_modules["brython"]: | |
62 url_hash = dyn_data['url_hash'] | |
63 import_url = f"/{C.BUILD_DIR}/{C.BUILD_DIR_DYN}/{url_hash}" | |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
64 dyn_data.setdefault('scripts', set()).update({ |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
65 Script(src=f"/{C.BUILD_DIR}/brython.js"), |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
66 }) |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
67 dyn_data.setdefault('template', {})['body_onload'] = self.getBodyOnload( |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
68 extra_path=[import_url]) |
1247 | 69 self.WATCH_DIRS.append(dyn_data['path'].resolve()) |
70 | |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
71 def getBodyOnload(self, debug=True, cache=True, extra_path=None): |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
72 on_load_opts = {"pythonpath": [f"/{C.BUILD_DIR}"]} |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
73 if debug: |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
74 on_load_opts[debug] = 1 |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
75 if cache: |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
76 on_load_opts["cache"] = True |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
77 if extra_path is not None: |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
78 on_load_opts["pythonpath"].extend(extra_path) |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
79 |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
80 return f"brython({json.dumps(on_load_opts)})" |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
81 |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
82 def copyFiles(self, files_paths, dest): |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
83 for p in files_paths: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
84 log.debug(f"copying {p}") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
85 if p.is_dir(): |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
86 shutil.copytree(p, dest) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
87 else: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
88 shutil.copy(p, dest) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
89 |
1247 | 90 def start(self): |
91 dyn_path = self.build_path / C.BUILD_DIR_DYN | |
92 for dyn_data in self.resource.browser_modules["brython"]: | |
93 url_hash = dyn_data['url_hash'] | |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
94 if url_hash is None: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
95 # root modules |
1256
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
96 url_prefix = dyn_data.get('url_prefix') |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
97 if url_prefix is None: |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
98 dest = self.build_path |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
99 init_dest_url = f"/{C.BUILD_DIR}/__init__.py" |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
100 else: |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
101 dest = self.build_path / url_prefix |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
102 dest.mkdir(exist_ok = True) |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
103 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
|
104 |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
105 self.copyFiles(dyn_data['path'].glob('*py'), dest) |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
106 |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
107 init_file = dyn_data['path'] / '__init__.py' |
08cd652dea14
server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents:
1253
diff
changeset
|
108 if init_file.is_file(): |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
109 self.resource.dyn_data_common['scripts'].update({ |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
110 Script(src=f"/{C.BUILD_DIR}/brython.js"), |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
111 Script(type='text/python', src=init_dest_url) |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
112 }) |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
113 self.resource.dyn_data_common.setdefault( |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
114 "template", {})['body_onload'] = self.getBodyOnload() |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
115 else: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
116 page_dyn_path = dyn_path / url_hash |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
117 if page_dyn_path.exists(): |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
118 log.debug("cleaning existing path") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
119 shutil.rmtree(page_dyn_path) |
1247 | 120 |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
121 page_dyn_path.mkdir(parents=True, exist_ok=True) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
122 log.debug("copying browser python files") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
123 self.copyFiles(dyn_data['path'].iterdir(), page_dyn_path) |
1247 | 124 |
1268
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
125 script = Script( |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
126 type='text/python', |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
127 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
|
128 ) |
e628724530ec
pages, tasks (brython): use set for scripts + common template data:
Goffi <goffi@goffi.org>
parents:
1262
diff
changeset
|
129 dyn_data['scripts'].add(script) |