annotate libervia/server/tasks/implicit/task_brython.py @ 1256:08cd652dea14

server, pages, tasks (brython): common_scripts: - scripts common to all pages can now be put in root `_browser` dir - `scripts` list is not set in `dyn_data`'s `template` anymore, but directly in a root `scripts` key (because it's not data which are sent verbatim to the template renderer) - if an `__init__.py` script is found in root `_browser` dir, brython task will add it to template scripts.
author Goffi <goffi@goffi.org>
date Sun, 03 May 2020 18:15:22 +0200
parents 6d49fae517ba
children 3fc3f2cde6a1
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 libervia.server.constants import Const as C
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 from libervia.server.tasks import task
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
12
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 log = getLogger(__name__)
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
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 class Task(task.Task):
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
18
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
19 def prepare(self):
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 if "brython" not in self.resource.browser_modules:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 raise exceptions.CancelError(f"No brython module found")
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
22
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 brython_js = self.build_path / "brython.js"
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 if not brython_js.is_file():
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 installed_ver = None
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 else:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 with brython_js.open() as f:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 for line in f:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 if line.startswith('// implementation ['):
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 installed_ver = literal_eval(line[18:])[:3]
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 log.debug(
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 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
33 f"installed")
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 break
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 else:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 log.warning(
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 f"brython file at {brython_js} doesn't has implementation "
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 f"version"
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 )
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 installed_ver = None
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
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
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 ver = [int(v) for v in brython.implementation.split('.')[:3]]
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 if ver != installed_ver:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 log.info(_("Installing Brython v{version}").format(
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 version='.'.join(str(v) for v in ver)))
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 data_path = Path(brython.__file__).parent / 'data'
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 # 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
53 # the web server, so it's not a big deal
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 shutil.copyfile(data_path / "brython.js", brython_js)
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 else:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 log.debug("Brython is already installed")
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 self.WATCH_DIRS = []
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
59
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 for dyn_data in self.resource.browser_modules["brython"]:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 url_hash = dyn_data['url_hash']
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 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
63 on_load_opts = {
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
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
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 }
1256
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
68 dyn_data.setdefault('scripts', set()).extend([
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
69 {"src": f"/{C.BUILD_DIR}/brython.js"},
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
70 ])
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
71 dyn_data.setdefault('template', {})['body_onload'] = (
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
72 f"brython({json.dumps(on_load_opts)})")
1247
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
73 self.WATCH_DIRS.append(dyn_data['path'].resolve())
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
74
1253
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
75 def copyFiles(self, files_paths, dest):
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
76 for p in files_paths:
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
77 log.debug(f"copying {p}")
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
78 if p.is_dir():
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
79 shutil.copytree(p, dest)
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
80 else:
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
81 shutil.copy(p, dest)
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
82
1247
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 def start(self):
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 dyn_path = self.build_path / C.BUILD_DIR_DYN
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 for dyn_data in self.resource.browser_modules["brython"]:
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 url_hash = dyn_data['url_hash']
1253
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
87 if url_hash is None:
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
88 # root modules
1256
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
89 url_prefix = dyn_data.get('url_prefix')
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
90 if url_prefix is None:
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
91 dest = self.build_path
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
92 init_dest_url = f"/{C.BUILD_DIR}/__init__.py"
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
93 else:
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
94 dest = self.build_path / url_prefix
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
95 dest.mkdir(exist_ok = True)
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
96 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
97
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
98 self.copyFiles(dyn_data['path'].glob('*py'), dest)
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
99
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
100 init_file = dyn_data['path'] / '__init__.py'
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
101 if init_file.is_file():
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
102 common_scripts = self.resource.dyn_data_common['scripts']
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
103 script = {
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
104 'type': 'text/python',
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
105 'src': init_dest_url
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 if script not in common_scripts:
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
108 common_scripts.append(script)
1253
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
109 else:
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
110 page_dyn_path = dyn_path / url_hash
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
111 if page_dyn_path.exists():
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
112 log.debug("cleaning existing path")
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
113 shutil.rmtree(page_dyn_path)
1247
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
114
1253
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
115 page_dyn_path.mkdir(parents=True, exist_ok=True)
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
116 log.debug("copying browser python files")
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
117 self.copyFiles(dyn_data['path'].iterdir(), page_dyn_path)
1247
a6c7f07f1e4d tasks: implicit tasks + Brython task:
Goffi <goffi@goffi.org>
parents:
diff changeset
118
1253
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
119 script = {
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
120 'type': 'text/python',
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
121 '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
122 }
1256
08cd652dea14 server, pages, tasks (brython): common_scripts:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
123 scripts = dyn_data['scripts']
1253
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
124 if script not in scripts:
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1250
diff changeset
125 scripts.append(script)