Mercurial > libervia-web
annotate libervia/server/tasks/implicit/task_brython.py @ 1253:6d49fae517ba
pages: browser metadata + root `_browser`:
- the `_browser` directory can now be put in root of a site `pages` directory, it will then
include modules for the whole website
- in `_browser` directories (notably the root one), a `browser_meta.json` file can be put to
specify settings for a browser engine
- pathlib.Path is now used LiberviaRootResource.site_path
- introduced some type hints
- task_brython copy modules in root `_browser` to build_path root.
- minimal python version is now 3.7 due to type hints
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 29 Apr 2020 17:34:53 +0200 |
parents | 821b6ce57f99 |
children | 08cd652dea14 |
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 | |
11 from libervia.server.tasks import task | |
12 | |
13 | |
14 log = getLogger(__name__) | |
15 | |
16 | |
17 class Task(task.Task): | |
18 | |
19 def prepare(self): | |
20 if "brython" not in self.resource.browser_modules: | |
21 raise exceptions.CancelError(f"No brython module found") | |
22 | |
23 brython_js = self.build_path / "brython.js" | |
24 if not brython_js.is_file(): | |
25 installed_ver = None | |
26 else: | |
27 with brython_js.open() as f: | |
28 for line in f: | |
29 if line.startswith('// implementation ['): | |
30 installed_ver = literal_eval(line[18:])[:3] | |
31 log.debug( | |
32 f"brython v{'.'.join(str(v) for v in installed_ver)} already " | |
33 f"installed") | |
34 break | |
35 else: | |
36 log.warning( | |
37 f"brython file at {brython_js} doesn't has implementation " | |
38 f"version" | |
39 ) | |
40 installed_ver = None | |
41 | |
1250
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
42 try: |
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
43 import brython |
821b6ce57f99
server (tasks/brython): log an error if brython is missing and needed
Goffi <goffi@goffi.org>
parents:
1247
diff
changeset
|
44 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
|
45 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
|
46 raise e |
1247 | 47 ver = [int(v) for v in brython.implementation.split('.')[:3]] |
48 if ver != installed_ver: | |
49 log.info(_("Installing Brython v{version}").format( | |
50 version='.'.join(str(v) for v in ver))) | |
51 data_path = Path(brython.__file__).parent / 'data' | |
52 # shutil has blocking method, but the task is run before we start | |
53 # the web server, so it's not a big deal | |
54 shutil.copyfile(data_path / "brython.js", brython_js) | |
55 else: | |
56 log.debug("Brython is already installed") | |
57 | |
58 self.WATCH_DIRS = [] | |
59 | |
60 for dyn_data in self.resource.browser_modules["brython"]: | |
61 url_hash = dyn_data['url_hash'] | |
62 import_url = f"/{C.BUILD_DIR}/{C.BUILD_DIR_DYN}/{url_hash}" | |
63 on_load_opts = { | |
64 "debug": 1, | |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
65 "cache": True, |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
66 "pythonpath": [f"/{C.BUILD_DIR}", import_url], |
1247 | 67 } |
68 dyn_data['template'] = { | |
69 "scripts": [{"src": f"/{C.BUILD_DIR}/brython.js"}], | |
70 "body_onload": f"brython({json.dumps(on_load_opts)})", | |
71 } | |
72 self.WATCH_DIRS.append(dyn_data['path'].resolve()) | |
73 | |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
74 def copyFiles(self, files_paths, dest): |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
75 for p in files_paths: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
76 log.debug(f"copying {p}") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
77 if p.is_dir(): |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
78 shutil.copytree(p, dest) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
79 else: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
80 shutil.copy(p, dest) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
81 |
1247 | 82 def start(self): |
83 dyn_path = self.build_path / C.BUILD_DIR_DYN | |
84 for dyn_data in self.resource.browser_modules["brython"]: | |
85 url_hash = dyn_data['url_hash'] | |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
86 if url_hash is None: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
87 # root modules |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
88 self.copyFiles(dyn_data['path'].glob('*py'), self.build_path) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
89 else: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
90 page_dyn_path = dyn_path / url_hash |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
91 if page_dyn_path.exists(): |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
92 log.debug("cleaning existing path") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
93 shutil.rmtree(page_dyn_path) |
1247 | 94 |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
95 page_dyn_path.mkdir(parents=True, exist_ok=True) |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
96 log.debug("copying browser python files") |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
97 self.copyFiles(dyn_data['path'].iterdir(), page_dyn_path) |
1247 | 98 |
1253
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
99 script = { |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
100 'type': 'text/python', |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
101 'src': f"/{C.BUILD_DIR}/{C.BUILD_DIR_DYN}/{url_hash}/__init__.py" |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
102 } |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
103 scripts = dyn_data['template']['scripts'] |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
104 if script not in scripts: |
6d49fae517ba
pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents:
1250
diff
changeset
|
105 scripts.append(script) |