-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript_runtime.py
More file actions
91 lines (70 loc) · 2.69 KB
/
Copy pathscript_runtime.py
File metadata and controls
91 lines (70 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""Load and run Python translated from page JavaScript via Js2Py."""
from __future__ import annotations
import copy
import os
import sys
from typing import Any, Callable
from dom_model import DomModel
HANDLER_MARKERS = ("PyJsHoisted_", ".func_name =")
def is_translated_script(python_src: str) -> bool:
stripped = python_src.strip()
if not stripped:
return False
lines = [
line
for line in stripped.splitlines()
if line.strip() and not line.strip().startswith("#")
]
return bool(lines)
def is_translated_handler_script(python_src: str) -> bool:
return is_translated_script(python_src) and any(
marker in python_src for marker in HANDLER_MARKERS
)
def _script_chunks(python_src: str) -> list[str]:
chunks = [chunk.strip() for chunk in python_src.split("\n\n") if chunk.strip()]
return chunks or ([python_src.strip()] if python_src.strip() else [])
def run_page_scripts(
python_src: str,
dom_model: DomModel,
namespace: dict[str, Any] | None = None,
) -> dict[str, Callable]:
"""Exec translated scripts against a live DOM and return callable handlers."""
if not is_translated_script(python_src):
dom_model.dispatch_event("DOMContentLoaded")
return {}
from js2py_runtime import build_runtime, extract_handlers
debug = bool(os.environ.get("BROWSER_DEBUG_JS"))
runtime = build_runtime(namespace, dom_model=dom_model)
for chunk in _script_chunks(python_src):
try:
exec(chunk, runtime)
except Exception as exc:
if debug:
print(f"Script error: {exc}", file=sys.stderr)
try:
dom_model.dispatch_event("DOMContentLoaded")
except Exception as exc:
if debug:
print(f"Script error (DOMContentLoaded): {exc}", file=sys.stderr)
return extract_handlers(runtime)
def load_scripts(
python_src: str,
namespace: dict[str, Any] | None = None,
dom_model: DomModel | None = None,
) -> dict[str, Callable]:
model = dom_model or DomModel({"type": "body", "attributes": {}, "children": []})
return run_page_scripts(python_src, model, namespace)
def apply_scripts_to_dom(
dom: dict[str, Any],
python_src: str,
namespace: dict[str, Any] | None = None,
) -> tuple[dict[str, Any], dict[str, Callable], str]:
"""Run translated scripts on a DOM snapshot and return the mutated tree."""
dom_model = DomModel(dom)
handlers = run_page_scripts(python_src, dom_model, namespace)
return dom_model.display_dom(), handlers, dom_model.title
def load_handlers(
python_src: str,
namespace: dict[str, Any] | None = None,
) -> dict[str, Callable]:
return load_scripts(python_src, namespace)