reactpy 2.0.0b5__py3-none-any.whl → 2.0.0b7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reactpy/__init__.py +4 -3
- reactpy/_html.py +11 -9
- reactpy/config.py +1 -1
- reactpy/core/_life_cycle_hook.py +4 -1
- reactpy/core/_thread_local.py +1 -1
- reactpy/core/hooks.py +11 -19
- reactpy/core/layout.py +43 -38
- reactpy/core/serve.py +11 -16
- reactpy/core/vdom.py +3 -5
- reactpy/executors/asgi/pyscript.py +4 -1
- reactpy/executors/asgi/standalone.py +1 -1
- reactpy/{pyscript → executors/pyscript}/component_template.py +1 -1
- reactpy/{pyscript → executors/pyscript}/components.py +1 -1
- reactpy/{pyscript → executors/pyscript}/utils.py +1 -1
- reactpy/executors/utils.py +32 -7
- reactpy/reactjs/__init__.py +351 -0
- reactpy/reactjs/module.py +267 -0
- reactpy/reactjs/types.py +7 -0
- reactpy/reactjs/utils.py +212 -0
- reactpy/static/index-64wy0fss.js +5 -0
- reactpy/static/index-64wy0fss.js.map +10 -0
- reactpy/static/index-beq660xy.js +5 -0
- reactpy/static/index-beq660xy.js.map +12 -0
- reactpy/static/index.js +2 -2
- reactpy/static/index.js.map +7 -10
- reactpy/static/preact-dom.js +4 -0
- reactpy/static/preact-dom.js.map +11 -0
- reactpy/static/preact-jsx-runtime.js +4 -0
- reactpy/static/preact-jsx-runtime.js.map +9 -0
- reactpy/static/preact.js +4 -0
- reactpy/static/preact.js.map +10 -0
- reactpy/templatetags/jinja.py +4 -1
- reactpy/testing/__init__.py +2 -7
- reactpy/testing/backend.py +24 -12
- reactpy/testing/common.py +1 -9
- reactpy/testing/display.py +65 -28
- reactpy/testing/logs.py +1 -1
- reactpy/transforms.py +2 -2
- reactpy/types.py +17 -11
- reactpy/utils.py +1 -1
- reactpy/web/__init__.py +0 -6
- reactpy/web/module.py +37 -473
- reactpy/web/utils.py +2 -158
- {reactpy-2.0.0b5.dist-info → reactpy-2.0.0b7.dist-info}/METADATA +1 -1
- {reactpy-2.0.0b5.dist-info → reactpy-2.0.0b7.dist-info}/RECORD +50 -38
- reactpy/testing/utils.py +0 -27
- reactpy/web/templates/react.js +0 -61
- /reactpy/{pyscript → executors/pyscript}/__init__.py +0 -0
- /reactpy/{pyscript → executors/pyscript}/layout_handler.py +0 -0
- {reactpy-2.0.0b5.dist-info → reactpy-2.0.0b7.dist-info}/WHEEL +0 -0
- {reactpy-2.0.0b5.dist-info → reactpy-2.0.0b7.dist-info}/entry_points.txt +0 -0
- {reactpy-2.0.0b5.dist-info → reactpy-2.0.0b7.dist-info}/licenses/LICENSE +0 -0
reactpy/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from reactpy import config, logging, types, web, widgets
|
|
1
|
+
from reactpy import config, logging, reactjs, types, web, widgets
|
|
2
2
|
from reactpy._html import html
|
|
3
3
|
from reactpy.core import hooks
|
|
4
4
|
from reactpy.core.component import component
|
|
@@ -19,11 +19,11 @@ from reactpy.core.hooks import (
|
|
|
19
19
|
use_state,
|
|
20
20
|
)
|
|
21
21
|
from reactpy.core.vdom import Vdom
|
|
22
|
-
from reactpy.pyscript.components import pyscript_component
|
|
22
|
+
from reactpy.executors.pyscript.components import pyscript_component
|
|
23
23
|
from reactpy.utils import Ref, reactpy_to_string, string_to_reactpy
|
|
24
24
|
|
|
25
25
|
__author__ = "The Reactive Python Team"
|
|
26
|
-
__version__ = "2.0.
|
|
26
|
+
__version__ = "2.0.0b7"
|
|
27
27
|
|
|
28
28
|
__all__ = [
|
|
29
29
|
"Ref",
|
|
@@ -36,6 +36,7 @@ __all__ = [
|
|
|
36
36
|
"html",
|
|
37
37
|
"logging",
|
|
38
38
|
"pyscript_component",
|
|
39
|
+
"reactjs",
|
|
39
40
|
"reactpy_to_string",
|
|
40
41
|
"string_to_reactpy",
|
|
41
42
|
"types",
|
reactpy/_html.py
CHANGED
|
@@ -6,7 +6,6 @@ from typing import ClassVar, overload
|
|
|
6
6
|
from reactpy.core.vdom import Vdom
|
|
7
7
|
from reactpy.types import (
|
|
8
8
|
EventHandlerDict,
|
|
9
|
-
Key,
|
|
10
9
|
VdomAttributes,
|
|
11
10
|
VdomChild,
|
|
12
11
|
VdomChildren,
|
|
@@ -14,7 +13,7 @@ from reactpy.types import (
|
|
|
14
13
|
VdomDict,
|
|
15
14
|
)
|
|
16
15
|
|
|
17
|
-
__all__ = ["html"]
|
|
16
|
+
__all__ = ["h", "html"]
|
|
18
17
|
|
|
19
18
|
NO_CHILDREN_ALLOWED_HTML_BODY = {
|
|
20
19
|
"area",
|
|
@@ -100,12 +99,10 @@ NO_CHILDREN_ALLOWED_SVG = {
|
|
|
100
99
|
def _fragment(
|
|
101
100
|
attributes: VdomAttributes,
|
|
102
101
|
children: Sequence[VdomChild],
|
|
103
|
-
key: Key | None,
|
|
104
102
|
event_handlers: EventHandlerDict,
|
|
105
103
|
) -> VdomDict:
|
|
106
104
|
"""An HTML fragment - this element will not appear in the DOM"""
|
|
107
|
-
|
|
108
|
-
if attributes or event_handlers:
|
|
105
|
+
if any(k != "key" for k in attributes) or event_handlers:
|
|
109
106
|
msg = "Fragments cannot have attributes besides 'key'"
|
|
110
107
|
raise TypeError(msg)
|
|
111
108
|
model = VdomDict(tagName="")
|
|
@@ -113,8 +110,8 @@ def _fragment(
|
|
|
113
110
|
if children:
|
|
114
111
|
model["children"] = children
|
|
115
112
|
|
|
116
|
-
if
|
|
117
|
-
model["
|
|
113
|
+
if attributes:
|
|
114
|
+
model["attributes"] = attributes
|
|
118
115
|
|
|
119
116
|
return model
|
|
120
117
|
|
|
@@ -122,7 +119,6 @@ def _fragment(
|
|
|
122
119
|
def _script(
|
|
123
120
|
attributes: VdomAttributes,
|
|
124
121
|
children: Sequence[VdomChild],
|
|
125
|
-
key: Key | None,
|
|
126
122
|
event_handlers: EventHandlerDict,
|
|
127
123
|
) -> VdomDict:
|
|
128
124
|
"""Create a new `<script> <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script>`__ element.
|
|
@@ -148,6 +144,8 @@ def _script(
|
|
|
148
144
|
msg = "'script' elements do not support event handlers"
|
|
149
145
|
raise ValueError(msg)
|
|
150
146
|
|
|
147
|
+
key = attributes.get("key")
|
|
148
|
+
|
|
151
149
|
if children:
|
|
152
150
|
if len(children) > 1:
|
|
153
151
|
msg = "'script' nodes may have, at most, one child."
|
|
@@ -165,7 +163,9 @@ def _script(
|
|
|
165
163
|
key = attributes["src"]
|
|
166
164
|
|
|
167
165
|
if key is not None:
|
|
168
|
-
|
|
166
|
+
if "attributes" not in model:
|
|
167
|
+
model["attributes"] = {}
|
|
168
|
+
model["attributes"]["key"] = key
|
|
169
169
|
|
|
170
170
|
return model
|
|
171
171
|
|
|
@@ -287,6 +287,7 @@ class HtmlConstructor:
|
|
|
287
287
|
"fragment": Vdom("", custom_constructor=_fragment),
|
|
288
288
|
"svg": SvgConstructor(),
|
|
289
289
|
}
|
|
290
|
+
__call__ = __cache__["fragment"].__call__
|
|
290
291
|
|
|
291
292
|
def __getattr__(self, value: str) -> VdomConstructor:
|
|
292
293
|
value = value.rstrip("_").replace("_", "-")
|
|
@@ -423,3 +424,4 @@ class HtmlConstructor:
|
|
|
423
424
|
|
|
424
425
|
|
|
425
426
|
html = HtmlConstructor()
|
|
427
|
+
h = html # shorthand alias for html
|
reactpy/config.py
CHANGED
reactpy/core/_life_cycle_hook.py
CHANGED
|
@@ -33,7 +33,10 @@ class _HookStack(Singleton): # nocov
|
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
def get(self) -> list[LifeCycleHook]:
|
|
36
|
-
|
|
36
|
+
try:
|
|
37
|
+
return self._state.get()
|
|
38
|
+
except LookupError:
|
|
39
|
+
return []
|
|
37
40
|
|
|
38
41
|
def initialize(self) -> Token[list[LifeCycleHook]] | None:
|
|
39
42
|
return None if isinstance(self._state, ThreadLocal) else self._state.set([])
|
reactpy/core/_thread_local.py
CHANGED
|
@@ -8,7 +8,7 @@ _StateType = TypeVar("_StateType")
|
|
|
8
8
|
|
|
9
9
|
class ThreadLocal(Generic[_StateType]): # nocov
|
|
10
10
|
"""Utility for managing per-thread state information. This is only used in
|
|
11
|
-
environments where ContextVars are not available, such as the `
|
|
11
|
+
environments where ContextVars are not available, such as the `pyscript`
|
|
12
12
|
executor."""
|
|
13
13
|
|
|
14
14
|
def __init__(self, default: Callable[[], _StateType]):
|
reactpy/core/hooks.py
CHANGED
|
@@ -84,11 +84,7 @@ class _CurrentState(Generic[_Type]):
|
|
|
84
84
|
self,
|
|
85
85
|
initial_value: _Type | Callable[[], _Type],
|
|
86
86
|
) -> None:
|
|
87
|
-
if callable(initial_value)
|
|
88
|
-
self.value = initial_value()
|
|
89
|
-
else:
|
|
90
|
-
self.value = initial_value
|
|
91
|
-
|
|
87
|
+
self.value = initial_value() if callable(initial_value) else initial_value
|
|
92
88
|
hook = HOOK_STACK.current_hook()
|
|
93
89
|
|
|
94
90
|
def dispatch(new: _Type | Callable[[_Type], _Type]) -> None:
|
|
@@ -434,10 +430,7 @@ def use_callback(
|
|
|
434
430
|
def setup(function: _CallbackFunc) -> _CallbackFunc:
|
|
435
431
|
return memoize(lambda: function)
|
|
436
432
|
|
|
437
|
-
if function is not None
|
|
438
|
-
return setup(function)
|
|
439
|
-
else:
|
|
440
|
-
return setup
|
|
433
|
+
return setup(function) if function is not None else setup
|
|
441
434
|
|
|
442
435
|
|
|
443
436
|
class _LambdaCaller(Protocol):
|
|
@@ -553,17 +546,16 @@ def _try_to_infer_closure_values(
|
|
|
553
546
|
func: Callable[..., Any] | None,
|
|
554
547
|
values: Sequence[Any] | ellipsis | None,
|
|
555
548
|
) -> Sequence[Any] | None:
|
|
556
|
-
if values is ...:
|
|
557
|
-
if isinstance(func, FunctionType):
|
|
558
|
-
return (
|
|
559
|
-
[cell.cell_contents for cell in func.__closure__]
|
|
560
|
-
if func.__closure__
|
|
561
|
-
else []
|
|
562
|
-
)
|
|
563
|
-
else:
|
|
564
|
-
return None
|
|
565
|
-
else:
|
|
549
|
+
if values is not ...:
|
|
566
550
|
return values
|
|
551
|
+
if isinstance(func, FunctionType):
|
|
552
|
+
return (
|
|
553
|
+
[cell.cell_contents for cell in func.__closure__]
|
|
554
|
+
if func.__closure__
|
|
555
|
+
else []
|
|
556
|
+
)
|
|
557
|
+
else:
|
|
558
|
+
return None
|
|
567
559
|
|
|
568
560
|
|
|
569
561
|
def strictly_equal(x: Any, y: Any) -> bool:
|
reactpy/core/layout.py
CHANGED
|
@@ -34,7 +34,7 @@ from reactpy.config import (
|
|
|
34
34
|
REACTPY_CHECK_VDOM_SPEC,
|
|
35
35
|
REACTPY_DEBUG,
|
|
36
36
|
)
|
|
37
|
-
from reactpy.core._life_cycle_hook import LifeCycleHook
|
|
37
|
+
from reactpy.core._life_cycle_hook import HOOK_STACK, LifeCycleHook
|
|
38
38
|
from reactpy.core.vdom import validate_vdom_json
|
|
39
39
|
from reactpy.types import (
|
|
40
40
|
BaseLayout,
|
|
@@ -162,43 +162,47 @@ class Layout(BaseLayout):
|
|
|
162
162
|
async def _create_layout_update(
|
|
163
163
|
self, old_state: _ModelState
|
|
164
164
|
) -> LayoutUpdateMessage:
|
|
165
|
-
|
|
165
|
+
token = HOOK_STACK.initialize()
|
|
166
166
|
try:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
167
|
+
component = old_state.life_cycle_state.component
|
|
168
|
+
try:
|
|
169
|
+
parent: _ModelState | None = old_state.parent
|
|
170
|
+
except AttributeError:
|
|
171
|
+
parent = None
|
|
172
|
+
|
|
173
|
+
async with AsyncExitStack() as exit_stack:
|
|
174
|
+
new_state = await self._render_component(
|
|
175
|
+
exit_stack,
|
|
176
|
+
old_state,
|
|
177
|
+
parent,
|
|
178
|
+
old_state.index,
|
|
179
|
+
old_state.key,
|
|
180
|
+
component,
|
|
181
|
+
)
|
|
180
182
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
183
|
+
if parent is not None:
|
|
184
|
+
parent.children_by_key[new_state.key] = new_state
|
|
185
|
+
old_parent_model = parent.model.current
|
|
186
|
+
old_parent_children = old_parent_model.setdefault("children", [])
|
|
187
|
+
parent.model.current = {
|
|
188
|
+
**old_parent_model,
|
|
189
|
+
"children": [
|
|
190
|
+
*old_parent_children[: new_state.index],
|
|
191
|
+
new_state.model.current,
|
|
192
|
+
*old_parent_children[new_state.index + 1 :],
|
|
193
|
+
],
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if REACTPY_CHECK_VDOM_SPEC.current:
|
|
197
|
+
validate_vdom_json(new_state.model.current)
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
"type": "layout-update",
|
|
201
|
+
"path": new_state.patch_path,
|
|
202
|
+
"model": new_state.model.current,
|
|
192
203
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
validate_vdom_json(new_state.model.current)
|
|
196
|
-
|
|
197
|
-
return {
|
|
198
|
-
"type": "layout-update",
|
|
199
|
-
"path": new_state.patch_path,
|
|
200
|
-
"model": new_state.model.current,
|
|
201
|
-
}
|
|
204
|
+
finally:
|
|
205
|
+
HOOK_STACK.reset(token)
|
|
202
206
|
|
|
203
207
|
async def _render_component(
|
|
204
208
|
self,
|
|
@@ -299,8 +303,9 @@ class Layout(BaseLayout):
|
|
|
299
303
|
except Exception as e: # nocov
|
|
300
304
|
msg = f"Expected a VDOM element dict, not {raw_model}"
|
|
301
305
|
raise ValueError(msg) from e
|
|
302
|
-
|
|
303
|
-
|
|
306
|
+
key = raw_model.get("attributes", {}).get("key")
|
|
307
|
+
if key is not None:
|
|
308
|
+
new_state.key = key
|
|
304
309
|
if "importSource" in raw_model:
|
|
305
310
|
new_state.model.current["importSource"] = raw_model["importSource"]
|
|
306
311
|
self._render_model_attributes(old_state, new_state, raw_model)
|
|
@@ -722,7 +727,7 @@ def _get_children_info(
|
|
|
722
727
|
continue
|
|
723
728
|
elif isinstance(child, dict):
|
|
724
729
|
child_type = _DICT_TYPE
|
|
725
|
-
key = child.get("key")
|
|
730
|
+
key = child.get("attributes", {}).get("key")
|
|
726
731
|
elif isinstance(child, Component):
|
|
727
732
|
child_type = _COMPONENT_TYPE
|
|
728
733
|
key = child.key
|
reactpy/core/serve.py
CHANGED
|
@@ -8,7 +8,6 @@ from anyio import create_task_group
|
|
|
8
8
|
from anyio.abc import TaskGroup
|
|
9
9
|
|
|
10
10
|
from reactpy.config import REACTPY_DEBUG
|
|
11
|
-
from reactpy.core._life_cycle_hook import HOOK_STACK
|
|
12
11
|
from reactpy.types import BaseLayout, LayoutEventMessage, LayoutUpdateMessage
|
|
13
12
|
|
|
14
13
|
logger = getLogger(__name__)
|
|
@@ -45,22 +44,18 @@ async def _single_outgoing_loop(
|
|
|
45
44
|
send: SendCoroutine,
|
|
46
45
|
) -> None:
|
|
47
46
|
while True:
|
|
48
|
-
|
|
47
|
+
update = await layout.render()
|
|
49
48
|
try:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
logger.error(msg)
|
|
61
|
-
raise
|
|
62
|
-
finally:
|
|
63
|
-
HOOK_STACK.reset(token)
|
|
49
|
+
await send(update)
|
|
50
|
+
except Exception: # nocov
|
|
51
|
+
if not REACTPY_DEBUG.current:
|
|
52
|
+
msg = (
|
|
53
|
+
"Failed to send update. More info may be available "
|
|
54
|
+
"if you enabling debug mode by setting "
|
|
55
|
+
"`reactpy.config.REACTPY_DEBUG.current = True`."
|
|
56
|
+
)
|
|
57
|
+
logger.error(msg)
|
|
58
|
+
raise
|
|
64
59
|
|
|
65
60
|
|
|
66
61
|
async def _single_incoming_loop(
|
reactpy/core/vdom.py
CHANGED
|
@@ -41,7 +41,6 @@ VDOM_JSON_SCHEMA = {
|
|
|
41
41
|
"type": "object",
|
|
42
42
|
"properties": {
|
|
43
43
|
"tagName": {"type": "string"},
|
|
44
|
-
"key": {"type": ["string", "number", "null"]},
|
|
45
44
|
"error": {"type": "string"},
|
|
46
45
|
"children": {"$ref": "#/definitions/elementChildren"},
|
|
47
46
|
"attributes": {"type": "object"},
|
|
@@ -170,7 +169,6 @@ class Vdom:
|
|
|
170
169
|
) -> VdomDict:
|
|
171
170
|
"""The entry point for the VDOM API, for example reactpy.html(<WE_ARE_HERE>)."""
|
|
172
171
|
attributes, children = separate_attributes_and_children(attributes_and_children)
|
|
173
|
-
key = attributes.get("key", None)
|
|
174
172
|
attributes, event_handlers, inline_javascript = (
|
|
175
173
|
separate_attributes_handlers_and_inline_javascript(attributes)
|
|
176
174
|
)
|
|
@@ -180,7 +178,6 @@ class Vdom:
|
|
|
180
178
|
# Run custom constructor, if defined
|
|
181
179
|
if self.custom_constructor:
|
|
182
180
|
result = self.custom_constructor(
|
|
183
|
-
key=key,
|
|
184
181
|
children=children,
|
|
185
182
|
attributes=attributes,
|
|
186
183
|
event_handlers=event_handlers,
|
|
@@ -189,7 +186,6 @@ class Vdom:
|
|
|
189
186
|
# Otherwise, use the default constructor
|
|
190
187
|
else:
|
|
191
188
|
result = {
|
|
192
|
-
**({"key": key} if key is not None else {}),
|
|
193
189
|
**({"children": children} if children else {}),
|
|
194
190
|
**({"attributes": attributes} if attributes else {}),
|
|
195
191
|
**({"eventHandlers": event_handlers} if event_handlers else {}),
|
|
@@ -277,7 +273,9 @@ def _validate_child_key_integrity(value: Any) -> None:
|
|
|
277
273
|
for child in value:
|
|
278
274
|
if isinstance(child, Component) and child.key is None:
|
|
279
275
|
warn(f"Key not specified for child in list {child}", UserWarning)
|
|
280
|
-
elif isinstance(child, Mapping) and "key" not in child
|
|
276
|
+
elif isinstance(child, Mapping) and "key" not in child.get(
|
|
277
|
+
"attributes", {}
|
|
278
|
+
):
|
|
281
279
|
# remove 'children' to reduce log spam
|
|
282
280
|
child_copy = {**child, "children": EllipsisRepr()}
|
|
283
281
|
warn(f"Key not specified for child in list {child_copy}", UserWarning)
|
|
@@ -13,8 +13,11 @@ from reactpy import html
|
|
|
13
13
|
from reactpy.executors.asgi.middleware import ReactPyMiddleware
|
|
14
14
|
from reactpy.executors.asgi.standalone import ReactPy, ReactPyApp
|
|
15
15
|
from reactpy.executors.asgi.types import AsgiWebsocketScope
|
|
16
|
+
from reactpy.executors.pyscript.utils import (
|
|
17
|
+
pyscript_component_html,
|
|
18
|
+
pyscript_setup_html,
|
|
19
|
+
)
|
|
16
20
|
from reactpy.executors.utils import vdom_head_to_html
|
|
17
|
-
from reactpy.pyscript.utils import pyscript_component_html, pyscript_setup_html
|
|
18
21
|
from reactpy.types import ReactPyConfig, VdomDict
|
|
19
22
|
|
|
20
23
|
|
|
@@ -23,8 +23,8 @@ from reactpy.executors.asgi.types import (
|
|
|
23
23
|
AsgiV3WebsocketApp,
|
|
24
24
|
AsgiWebsocketScope,
|
|
25
25
|
)
|
|
26
|
+
from reactpy.executors.pyscript.utils import pyscript_setup_html
|
|
26
27
|
from reactpy.executors.utils import server_side_component_html, vdom_head_to_html
|
|
27
|
-
from reactpy.pyscript.utils import pyscript_setup_html
|
|
28
28
|
from reactpy.types import (
|
|
29
29
|
PyScriptOptions,
|
|
30
30
|
ReactPyConfig,
|
|
@@ -4,7 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from reactpy import component, hooks
|
|
7
|
-
from reactpy.pyscript.utils import pyscript_component_html
|
|
7
|
+
from reactpy.executors.pyscript.utils import pyscript_component_html
|
|
8
8
|
from reactpy.types import Component, Key
|
|
9
9
|
from reactpy.utils import string_to_reactpy
|
|
10
10
|
|
|
@@ -123,7 +123,7 @@ def extend_pyscript_config(
|
|
|
123
123
|
pyscript_config["packages"].extend(extra_py)
|
|
124
124
|
|
|
125
125
|
# FIXME: https://github.com/pyscript/pyscript/issues/2282
|
|
126
|
-
if any(pkg.endswith(".whl") for pkg in pyscript_config["packages"]):
|
|
126
|
+
if any(pkg.endswith(".whl") for pkg in pyscript_config["packages"]): # nocov
|
|
127
127
|
pyscript_config["packages_cache"] = "never"
|
|
128
128
|
|
|
129
129
|
# Extend the JavaScript dependency list
|
reactpy/executors/utils.py
CHANGED
|
@@ -64,16 +64,41 @@ def server_side_component_html(
|
|
|
64
64
|
) -> str:
|
|
65
65
|
return (
|
|
66
66
|
f'<div id="{element_id}" class="{class_}"></div>'
|
|
67
|
+
"<script>"
|
|
68
|
+
'if (!document.querySelector("#reactpy-importmap")) {'
|
|
69
|
+
" console.debug("
|
|
70
|
+
' "ReactPy did not detect a suitable JavaScript import map. Falling back to ReactPy\'s internal framework (Preact)."'
|
|
71
|
+
" );"
|
|
72
|
+
' const im = document.createElement("script");'
|
|
73
|
+
' im.type = "importmap";'
|
|
74
|
+
f" im.textContent = '{default_import_map()}';"
|
|
75
|
+
' im.id = "reactpy-importmap";'
|
|
76
|
+
" document.head.appendChild(im);"
|
|
77
|
+
" delete im;"
|
|
78
|
+
"}"
|
|
79
|
+
"</script>"
|
|
67
80
|
'<script type="module" crossorigin="anonymous">'
|
|
68
81
|
f'import {{ mountReactPy }} from "{REACTPY_PATH_PREFIX.current}static/index.js";'
|
|
69
82
|
"mountReactPy({"
|
|
70
|
-
f'
|
|
71
|
-
f'
|
|
72
|
-
f'
|
|
73
|
-
f"
|
|
74
|
-
f"
|
|
75
|
-
f"
|
|
76
|
-
f"
|
|
83
|
+
f' mountElement: document.getElementById("{element_id}"),'
|
|
84
|
+
f' pathPrefix: "{REACTPY_PATH_PREFIX.current}",'
|
|
85
|
+
f' componentPath: "{component_path}",'
|
|
86
|
+
f" reconnectInterval: {REACTPY_RECONNECT_INTERVAL.current},"
|
|
87
|
+
f" reconnectMaxInterval: {REACTPY_RECONNECT_MAX_INTERVAL.current},"
|
|
88
|
+
f" reconnectMaxRetries: {REACTPY_RECONNECT_MAX_RETRIES.current},"
|
|
89
|
+
f" reconnectBackoffMultiplier: {REACTPY_RECONNECT_BACKOFF_MULTIPLIER.current},"
|
|
77
90
|
"});"
|
|
78
91
|
"</script>"
|
|
79
92
|
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def default_import_map() -> str:
|
|
96
|
+
path_prefix = REACTPY_PATH_PREFIX.current.strip("/")
|
|
97
|
+
return f"""{{
|
|
98
|
+
"imports": {{
|
|
99
|
+
"react": "/{path_prefix}/static/preact.js",
|
|
100
|
+
"react-dom": "/{path_prefix}/static/preact-dom.js",
|
|
101
|
+
"react-dom/client": "/{path_prefix}/static/preact-dom.js",
|
|
102
|
+
"react/jsx-runtime": "/{path_prefix}/static/preact-jsx-runtime.js"
|
|
103
|
+
}}
|
|
104
|
+
}}""".replace("\n", "").replace(" ", "")
|