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