comparison libervia/server/tasks/implicit/task_brython.py @ 1247:a6c7f07f1e4d

tasks: implicit tasks + Brython task: - implicit tasks are tasks launched for every site. - a first one is made for Brython: it will install Brython and copy suitable files and set template data if Brython code is written in page `_browser` subdirectory.
author Goffi <goffi@goffi.org>
date Sun, 26 Apr 2020 22:07:18 +0200
parents
children 821b6ce57f99
comparison
equal deleted inserted replaced
1246:aaf28d45ae67 1247:a6c7f07f1e4d
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 sat.tools.common.template import safe
11 from libervia.server.constants import Const as C
12 from libervia.server.tasks import task
13
14
15 log = getLogger(__name__)
16
17
18 class Task(task.Task):
19 DOC_DIRS_DEFAULT = ('doc', 'docs')
20
21 def prepare(self):
22 if "brython" not in self.resource.browser_modules:
23 raise exceptions.CancelError(f"No brython module found")
24
25 brython_js = self.build_path / "brython.js"
26 if not brython_js.is_file():
27 installed_ver = None
28 else:
29 with brython_js.open() as f:
30 for line in f:
31 if line.startswith('// implementation ['):
32 installed_ver = literal_eval(line[18:])[:3]
33 log.debug(
34 f"brython v{'.'.join(str(v) for v in installed_ver)} already "
35 f"installed")
36 break
37 else:
38 log.warning(
39 f"brython file at {brython_js} doesn't has implementation "
40 f"version"
41 )
42 installed_ver = None
43
44 import brython
45 ver = [int(v) for v in brython.implementation.split('.')[:3]]
46 if ver != installed_ver:
47 log.info(_("Installing Brython v{version}").format(
48 version='.'.join(str(v) for v in ver)))
49 data_path = Path(brython.__file__).parent / 'data'
50 # shutil has blocking method, but the task is run before we start
51 # the web server, so it's not a big deal
52 shutil.copyfile(data_path / "brython.js", brython_js)
53 else:
54 log.debug("Brython is already installed")
55
56 self.WATCH_DIRS = []
57
58 for dyn_data in self.resource.browser_modules["brython"]:
59 url_hash = dyn_data['url_hash']
60 import_url = f"/{C.BUILD_DIR}/{C.BUILD_DIR_DYN}/{url_hash}"
61 on_load_opts = {
62 "debug": 1,
63 "pythonpath": [import_url],
64 }
65 dyn_data['template'] = {
66 "scripts": [{"src": f"/{C.BUILD_DIR}/brython.js"}],
67 "body_onload": f"brython({json.dumps(on_load_opts)})",
68 }
69 self.WATCH_DIRS.append(dyn_data['path'].resolve())
70
71 def start(self):
72 dyn_path = self.build_path / C.BUILD_DIR_DYN
73 for dyn_data in self.resource.browser_modules["brython"]:
74 url_hash = dyn_data['url_hash']
75 page_dyn_path = dyn_path / url_hash
76 if page_dyn_path.exists():
77 log.debug("cleaning existing path")
78 shutil.rmtree(page_dyn_path)
79
80 page_dyn_path.mkdir(parents=True, exist_ok=True)
81 log.debug("copying browser python files")
82 for p in dyn_data['path'].iterdir():
83 log.debug(f"copying {p}")
84 if p.is_dir():
85 shutil.copytree(p, page_dyn_path)
86 else:
87 shutil.copy(p, page_dyn_path)
88
89 script = {
90 'type': 'text/python',
91 'src': f"/{C.BUILD_DIR}/{C.BUILD_DIR_DYN}/{url_hash}/__init__.py"
92 }
93 scripts = dyn_data['template']['scripts']
94 if script not in scripts:
95 scripts.append(script)