reactpy 2.0.0b4__py3-none-any.whl → 2.0.0b6__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 +3 -2
- reactpy/_console/rewrite_props.py +2 -2
- reactpy/_html.py +11 -9
- reactpy/_option.py +2 -1
- reactpy/config.py +2 -2
- reactpy/core/_life_cycle_hook.py +12 -10
- reactpy/core/_thread_local.py +2 -1
- reactpy/core/component.py +4 -38
- reactpy/core/events.py +61 -36
- reactpy/core/hooks.py +25 -35
- reactpy/core/layout.py +193 -201
- reactpy/core/serve.py +17 -22
- reactpy/core/vdom.py +9 -12
- reactpy/executors/asgi/__init__.py +9 -4
- reactpy/executors/asgi/middleware.py +1 -2
- reactpy/executors/asgi/pyscript.py +3 -7
- reactpy/executors/asgi/standalone.py +4 -6
- reactpy/executors/asgi/types.py +2 -2
- reactpy/pyscript/components.py +3 -3
- reactpy/pyscript/utils.py +49 -46
- reactpy/reactjs/__init__.py +353 -0
- reactpy/reactjs/module.py +203 -0
- reactpy/reactjs/types.py +7 -0
- reactpy/reactjs/utils.py +183 -0
- reactpy/static/index-h31022cd.js +5 -0
- reactpy/static/index-h31022cd.js.map +11 -0
- reactpy/static/index-sbddj6ms.js +5 -0
- reactpy/static/index-sbddj6ms.js.map +10 -0
- reactpy/static/index-y71bxs88.js +5 -0
- reactpy/static/index-y71bxs88.js.map +10 -0
- reactpy/static/index.js +2 -2
- reactpy/static/index.js.map +6 -10
- reactpy/static/react-dom.js +4 -0
- reactpy/static/react-dom.js.map +11 -0
- reactpy/static/react-jsx-runtime.js +4 -0
- reactpy/static/react-jsx-runtime.js.map +9 -0
- reactpy/static/react.js +4 -0
- reactpy/static/react.js.map +10 -0
- reactpy/testing/backend.py +6 -5
- reactpy/testing/common.py +3 -5
- reactpy/testing/display.py +2 -1
- reactpy/testing/logs.py +1 -1
- reactpy/transforms.py +2 -2
- reactpy/types.py +117 -58
- reactpy/utils.py +8 -8
- reactpy/web/__init__.py +0 -6
- reactpy/web/module.py +37 -470
- reactpy/web/utils.py +2 -158
- reactpy/widgets.py +2 -2
- {reactpy-2.0.0b4.dist-info → reactpy-2.0.0b6.dist-info}/METADATA +4 -7
- {reactpy-2.0.0b4.dist-info → reactpy-2.0.0b6.dist-info}/RECORD +54 -39
- reactpy/web/templates/react.js +0 -61
- {reactpy-2.0.0b4.dist-info → reactpy-2.0.0b6.dist-info}/WHEEL +0 -0
- {reactpy-2.0.0b4.dist-info → reactpy-2.0.0b6.dist-info}/entry_points.txt +0 -0
- {reactpy-2.0.0b4.dist-info → reactpy-2.0.0b6.dist-info}/licenses/LICENSE +0 -0
reactpy/types.py
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import inspect
|
|
4
|
+
from collections.abc import Awaitable, Callable, Mapping, Sequence
|
|
4
5
|
from dataclasses import dataclass
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from types import TracebackType
|
|
7
8
|
from typing import (
|
|
8
9
|
Any,
|
|
9
|
-
Callable,
|
|
10
10
|
Generic,
|
|
11
11
|
Literal,
|
|
12
|
+
NamedTuple,
|
|
13
|
+
NewType,
|
|
14
|
+
NotRequired,
|
|
12
15
|
Protocol,
|
|
16
|
+
TypeAlias,
|
|
17
|
+
TypedDict,
|
|
13
18
|
TypeVar,
|
|
19
|
+
Unpack,
|
|
14
20
|
overload,
|
|
15
|
-
runtime_checkable,
|
|
16
21
|
)
|
|
17
22
|
|
|
18
|
-
from typing_extensions import NamedTuple, NotRequired, TypeAlias, TypedDict, Unpack
|
|
19
|
-
|
|
20
23
|
CarrierType = TypeVar("CarrierType")
|
|
21
24
|
_Type = TypeVar("_Type")
|
|
22
25
|
|
|
@@ -26,54 +29,84 @@ class State(NamedTuple, Generic[_Type]):
|
|
|
26
29
|
set_value: Callable[[_Type | Callable[[_Type], _Type]], None]
|
|
27
30
|
|
|
28
31
|
|
|
29
|
-
ComponentConstructor = Callable[..., "
|
|
32
|
+
ComponentConstructor = Callable[..., "Component"]
|
|
30
33
|
"""Simple function returning a new component"""
|
|
31
34
|
|
|
32
|
-
RootComponentConstructor = Callable[[], "
|
|
35
|
+
RootComponentConstructor = Callable[[], "Component"]
|
|
33
36
|
"""The root component should be constructed by a function accepting no arguments."""
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
Key: TypeAlias = str | int
|
|
37
40
|
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"""The expected interface for all component-like objects"""
|
|
42
|
-
|
|
43
|
-
key: Key | None
|
|
44
|
-
"""An identifier which is unique amongst a component's immediate siblings"""
|
|
42
|
+
class Component:
|
|
43
|
+
"""An object for rending component models."""
|
|
45
44
|
|
|
46
|
-
type
|
|
47
|
-
"""The function or class defining the behavior of this component
|
|
45
|
+
__slots__ = "__weakref__", "_args", "_func", "_kwargs", "_sig", "key", "type"
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
function: Callable[..., Component | VdomDict | str | None],
|
|
50
|
+
key: Any | None,
|
|
51
|
+
args: tuple[Any, ...],
|
|
52
|
+
kwargs: dict[str, Any],
|
|
53
|
+
sig: inspect.Signature,
|
|
54
|
+
) -> None:
|
|
55
|
+
self.key = key
|
|
56
|
+
self.type = function
|
|
57
|
+
self._args = args
|
|
58
|
+
self._kwargs = kwargs
|
|
59
|
+
self._sig = sig
|
|
60
|
+
|
|
61
|
+
def render(self) -> Component | VdomDict | str | None:
|
|
62
|
+
return self.type(*self._args, **self._kwargs)
|
|
51
63
|
|
|
52
|
-
def
|
|
53
|
-
|
|
64
|
+
def __repr__(self) -> str:
|
|
65
|
+
try:
|
|
66
|
+
args = self._sig.bind(*self._args, **self._kwargs).arguments
|
|
67
|
+
except TypeError:
|
|
68
|
+
return f"{self.type.__name__}(...)"
|
|
69
|
+
else:
|
|
70
|
+
items = ", ".join(f"{k}={v!r}" for k, v in args.items())
|
|
71
|
+
if items:
|
|
72
|
+
return f"{self.type.__name__}({id(self):02x}, {items})"
|
|
73
|
+
else:
|
|
74
|
+
return f"{self.type.__name__}({id(self):02x})"
|
|
54
75
|
|
|
55
76
|
|
|
56
77
|
_Render_co = TypeVar("_Render_co", covariant=True)
|
|
57
78
|
_Event_contra = TypeVar("_Event_contra", contravariant=True)
|
|
58
79
|
|
|
59
80
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
class BaseLayout(Protocol[_Render_co, _Event_contra]):
|
|
82
|
+
"""Renders and delivers views, and submits events to handlers."""
|
|
83
|
+
|
|
84
|
+
__slots__: tuple[str, ...] = (
|
|
85
|
+
"__weakref__",
|
|
86
|
+
"_event_handlers",
|
|
87
|
+
"_model_states_by_life_cycle_state_id",
|
|
88
|
+
"_render_tasks",
|
|
89
|
+
"_render_tasks_ready",
|
|
90
|
+
"_rendering_queue",
|
|
91
|
+
"_root_life_cycle_state_id",
|
|
92
|
+
"root",
|
|
93
|
+
)
|
|
63
94
|
|
|
64
95
|
async def render(
|
|
65
96
|
self,
|
|
66
|
-
) -> _Render_co:
|
|
97
|
+
) -> _Render_co:
|
|
98
|
+
"""Render an update to a view"""
|
|
99
|
+
...
|
|
67
100
|
|
|
68
|
-
async def deliver(
|
|
69
|
-
|
|
70
|
-
|
|
101
|
+
async def deliver(self, event: _Event_contra) -> None:
|
|
102
|
+
"""Relay an event to its respective handler"""
|
|
103
|
+
...
|
|
71
104
|
|
|
72
105
|
async def __aenter__(
|
|
73
106
|
self,
|
|
74
|
-
) ->
|
|
75
|
-
|
|
76
|
-
|
|
107
|
+
) -> BaseLayout[_Render_co, _Event_contra]:
|
|
108
|
+
"""Prepare the layout for its first render"""
|
|
109
|
+
...
|
|
77
110
|
|
|
78
111
|
async def __aexit__(
|
|
79
112
|
self,
|
|
@@ -82,6 +115,7 @@ class LayoutType(Protocol[_Render_co, _Event_contra]):
|
|
|
82
115
|
traceback: TracebackType,
|
|
83
116
|
) -> bool | None:
|
|
84
117
|
"""Clean up the view after its final render"""
|
|
118
|
+
...
|
|
85
119
|
|
|
86
120
|
|
|
87
121
|
class CssStyleTypeDict(TypedDict, total=False):
|
|
@@ -500,7 +534,7 @@ class CssStyleTypeDict(TypedDict, total=False):
|
|
|
500
534
|
zIndex: str | int
|
|
501
535
|
|
|
502
536
|
|
|
503
|
-
# TODO: Enable `extra_items` on `CssStyleDict` when PEP 728 is merged, likely in Python 3.
|
|
537
|
+
# TODO: Enable `extra_items` on `CssStyleDict` when PEP 728 is merged, likely in Python 3.15. Ref: https://peps.python.org/pep-0728/
|
|
504
538
|
CssStyleDict = CssStyleTypeDict | dict[str, Any]
|
|
505
539
|
|
|
506
540
|
EventFunc = Callable[[dict[str, Any]], Awaitable[None] | None]
|
|
@@ -510,8 +544,8 @@ class DangerouslySetInnerHTML(TypedDict):
|
|
|
510
544
|
__html: str
|
|
511
545
|
|
|
512
546
|
|
|
513
|
-
# TODO: It's probably better to break this
|
|
514
|
-
#
|
|
547
|
+
# TODO: It's probably better to break this down into what each HTML node's attributes can be,
|
|
548
|
+
# and make sure those types are resolved correctly within `HtmlConstructor`
|
|
515
549
|
# TODO: This could be generated by parsing from `@types/react` in the future
|
|
516
550
|
# https://www.npmjs.com/package/@types/react?activeTab=code
|
|
517
551
|
VdomAttributesTypeDict = TypedDict(
|
|
@@ -764,7 +798,6 @@ VdomAttributes = VdomAttributesTypeDict | dict[str, Any]
|
|
|
764
798
|
|
|
765
799
|
VdomDictKeys = Literal[
|
|
766
800
|
"tagName",
|
|
767
|
-
"key",
|
|
768
801
|
"children",
|
|
769
802
|
"attributes",
|
|
770
803
|
"eventHandlers",
|
|
@@ -773,7 +806,6 @@ VdomDictKeys = Literal[
|
|
|
773
806
|
]
|
|
774
807
|
ALLOWED_VDOM_KEYS = {
|
|
775
808
|
"tagName",
|
|
776
|
-
"key",
|
|
777
809
|
"children",
|
|
778
810
|
"attributes",
|
|
779
811
|
"eventHandlers",
|
|
@@ -786,8 +818,7 @@ class VdomTypeDict(TypedDict):
|
|
|
786
818
|
"""TypedDict representation of what the `VdomDict` should look like."""
|
|
787
819
|
|
|
788
820
|
tagName: str
|
|
789
|
-
|
|
790
|
-
children: NotRequired[Sequence[ComponentType | VdomChild]]
|
|
821
|
+
children: NotRequired[Sequence[Component | VdomChild]]
|
|
791
822
|
attributes: NotRequired[VdomAttributes]
|
|
792
823
|
eventHandlers: NotRequired[EventHandlerDict]
|
|
793
824
|
inlineJavaScript: NotRequired[InlineJavaScriptDict]
|
|
@@ -811,11 +842,9 @@ class VdomDict(dict):
|
|
|
811
842
|
@overload
|
|
812
843
|
def __getitem__(self, key: Literal["tagName"]) -> str: ...
|
|
813
844
|
@overload
|
|
814
|
-
def __getitem__(self, key: Literal["key"]) -> Key | None: ...
|
|
815
|
-
@overload
|
|
816
845
|
def __getitem__(
|
|
817
846
|
self, key: Literal["children"]
|
|
818
|
-
) -> Sequence[
|
|
847
|
+
) -> Sequence[Component | VdomChild]: ...
|
|
819
848
|
@overload
|
|
820
849
|
def __getitem__(self, key: Literal["attributes"]) -> VdomAttributes: ...
|
|
821
850
|
@overload
|
|
@@ -830,10 +859,8 @@ class VdomDict(dict):
|
|
|
830
859
|
@overload
|
|
831
860
|
def __setitem__(self, key: Literal["tagName"], value: str) -> None: ...
|
|
832
861
|
@overload
|
|
833
|
-
def __setitem__(self, key: Literal["key"], value: Key | None) -> None: ...
|
|
834
|
-
@overload
|
|
835
862
|
def __setitem__(
|
|
836
|
-
self, key: Literal["children"], value: Sequence[
|
|
863
|
+
self, key: Literal["children"], value: Sequence[Component | VdomChild]
|
|
837
864
|
) -> None: ...
|
|
838
865
|
@overload
|
|
839
866
|
def __setitem__(
|
|
@@ -857,7 +884,7 @@ class VdomDict(dict):
|
|
|
857
884
|
super().__setitem__(key, value)
|
|
858
885
|
|
|
859
886
|
|
|
860
|
-
VdomChild: TypeAlias =
|
|
887
|
+
VdomChild: TypeAlias = Component | VdomDict | str | None | Any
|
|
861
888
|
"""A single child element of a :class:`VdomDict`"""
|
|
862
889
|
|
|
863
890
|
VdomChildren: TypeAlias = Sequence[VdomChild] | VdomChild
|
|
@@ -907,19 +934,26 @@ class EventHandlerFunc(Protocol):
|
|
|
907
934
|
async def __call__(self, data: Sequence[Any]) -> None: ...
|
|
908
935
|
|
|
909
936
|
|
|
910
|
-
|
|
911
|
-
class EventHandlerType(Protocol):
|
|
937
|
+
class BaseEventHandler:
|
|
912
938
|
"""Defines a handler for some event"""
|
|
913
939
|
|
|
940
|
+
__slots__ = (
|
|
941
|
+
"__weakref__",
|
|
942
|
+
"function",
|
|
943
|
+
"prevent_default",
|
|
944
|
+
"stop_propagation",
|
|
945
|
+
"target",
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
function: EventHandlerFunc
|
|
949
|
+
"""A coroutine which can respond to an event and its data"""
|
|
950
|
+
|
|
914
951
|
prevent_default: bool
|
|
915
952
|
"""Whether to block the event from propagating further up the DOM"""
|
|
916
953
|
|
|
917
954
|
stop_propagation: bool
|
|
918
955
|
"""Stops the default action associate with the event from taking place."""
|
|
919
956
|
|
|
920
|
-
function: EventHandlerFunc
|
|
921
|
-
"""A coroutine which can respond to an event and its data"""
|
|
922
|
-
|
|
923
957
|
target: str | None
|
|
924
958
|
"""Typically left as ``None`` except when a static target is useful.
|
|
925
959
|
|
|
@@ -932,10 +966,10 @@ class EventHandlerType(Protocol):
|
|
|
932
966
|
"""
|
|
933
967
|
|
|
934
968
|
|
|
935
|
-
EventHandlerMapping = Mapping[str,
|
|
969
|
+
EventHandlerMapping = Mapping[str, BaseEventHandler]
|
|
936
970
|
"""A generic mapping between event names to their handlers"""
|
|
937
971
|
|
|
938
|
-
EventHandlerDict: TypeAlias = dict[str,
|
|
972
|
+
EventHandlerDict: TypeAlias = dict[str, BaseEventHandler]
|
|
939
973
|
"""A dict mapping between event names to their handlers"""
|
|
940
974
|
|
|
941
975
|
InlineJavaScriptMapping = Mapping[str, InlineJavaScript]
|
|
@@ -991,17 +1025,30 @@ class Context(Protocol[_Type]):
|
|
|
991
1025
|
*children: Any,
|
|
992
1026
|
value: _Type = ...,
|
|
993
1027
|
key: Key | None = ...,
|
|
994
|
-
) ->
|
|
1028
|
+
) -> ContextProvider[_Type]: ...
|
|
995
1029
|
|
|
996
1030
|
|
|
997
|
-
class
|
|
998
|
-
|
|
1031
|
+
class ContextProvider(Component, Generic[_Type]):
|
|
1032
|
+
def __init__(
|
|
1033
|
+
self,
|
|
1034
|
+
*children: Any,
|
|
1035
|
+
value: _Type,
|
|
1036
|
+
key: Key | None,
|
|
1037
|
+
type: Context[_Type],
|
|
1038
|
+
) -> None:
|
|
1039
|
+
self.children = children
|
|
1040
|
+
self.key = key
|
|
1041
|
+
self.type = type
|
|
1042
|
+
self.value = value
|
|
1043
|
+
|
|
1044
|
+
def render(self) -> VdomDict:
|
|
1045
|
+
from reactpy.core.hooks import HOOK_STACK
|
|
999
1046
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1047
|
+
HOOK_STACK.current_hook().set_context_provider(self)
|
|
1048
|
+
return VdomDict(tagName="", children=self.children)
|
|
1002
1049
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1050
|
+
def __repr__(self) -> str:
|
|
1051
|
+
return f"ContextProvider({self.type})"
|
|
1005
1052
|
|
|
1006
1053
|
|
|
1007
1054
|
@dataclass
|
|
@@ -1063,7 +1110,6 @@ class CustomVdomConstructor(Protocol):
|
|
|
1063
1110
|
self,
|
|
1064
1111
|
attributes: VdomAttributes,
|
|
1065
1112
|
children: Sequence[VdomChildren],
|
|
1066
|
-
key: Key | None,
|
|
1067
1113
|
event_handlers: EventHandlerDict,
|
|
1068
1114
|
) -> VdomDict: ...
|
|
1069
1115
|
|
|
@@ -1087,3 +1133,16 @@ class Event(dict):
|
|
|
1087
1133
|
|
|
1088
1134
|
def stopPropagation(self) -> None:
|
|
1089
1135
|
"""Stop the event from propagating."""
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
SourceType = NewType("SourceType", str)
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
@dataclass(frozen=True)
|
|
1142
|
+
class JavaScriptModule:
|
|
1143
|
+
source: str
|
|
1144
|
+
source_type: SourceType
|
|
1145
|
+
default_fallback: Any | None
|
|
1146
|
+
import_names: set[str] | None
|
|
1147
|
+
file: Path | None
|
|
1148
|
+
unmount_before_update: bool
|
reactpy/utils.py
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
-
from collections.abc import Iterable
|
|
4
|
+
from collections.abc import Callable, Iterable
|
|
5
5
|
from importlib import import_module
|
|
6
6
|
from itertools import chain
|
|
7
|
-
from typing import Any,
|
|
7
|
+
from typing import Any, Generic, TypeVar, cast
|
|
8
8
|
|
|
9
9
|
from lxml import etree
|
|
10
10
|
from lxml.html import fromstring
|
|
11
11
|
|
|
12
12
|
from reactpy import html
|
|
13
13
|
from reactpy.transforms import RequiredTransforms, attributes_to_reactjs
|
|
14
|
-
from reactpy.types import
|
|
14
|
+
from reactpy.types import Component, VdomDict
|
|
15
15
|
|
|
16
16
|
_RefValue = TypeVar("_RefValue")
|
|
17
17
|
_ModelTransform = Callable[[VdomDict], Any]
|
|
@@ -63,7 +63,7 @@ class Ref(Generic[_RefValue]):
|
|
|
63
63
|
return f"{type(self).__name__}({current})"
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
def reactpy_to_string(root: VdomDict |
|
|
66
|
+
def reactpy_to_string(root: VdomDict | Component) -> str:
|
|
67
67
|
"""Convert a ReactPy component or `reactpy.html` element into an HTML string.
|
|
68
68
|
|
|
69
69
|
Parameters:
|
|
@@ -186,7 +186,7 @@ def _add_vdom_to_etree(parent: etree._Element, vdom: VdomDict | dict[str, Any])
|
|
|
186
186
|
|
|
187
187
|
for c in vdom.get("children", []):
|
|
188
188
|
if hasattr(c, "render"):
|
|
189
|
-
c = component_to_vdom(cast(
|
|
189
|
+
c = component_to_vdom(cast(Component, c))
|
|
190
190
|
if isinstance(c, dict):
|
|
191
191
|
_add_vdom_to_etree(element, c)
|
|
192
192
|
|
|
@@ -232,17 +232,17 @@ def _generate_vdom_children(
|
|
|
232
232
|
)
|
|
233
233
|
|
|
234
234
|
|
|
235
|
-
def component_to_vdom(component:
|
|
235
|
+
def component_to_vdom(component: Component) -> VdomDict:
|
|
236
236
|
"""Convert the first render of a component into a VDOM dictionary"""
|
|
237
237
|
result = component.render()
|
|
238
238
|
|
|
239
239
|
if isinstance(result, dict):
|
|
240
240
|
return result
|
|
241
241
|
if hasattr(result, "render"):
|
|
242
|
-
return component_to_vdom(cast(
|
|
242
|
+
return component_to_vdom(cast(Component, result))
|
|
243
243
|
elif isinstance(result, str):
|
|
244
244
|
return html.div(result)
|
|
245
|
-
return html
|
|
245
|
+
return html()
|
|
246
246
|
|
|
247
247
|
|
|
248
248
|
def _react_attribute_to_html(key: str, value: Any) -> tuple[str, str]:
|
reactpy/web/__init__.py
CHANGED
|
@@ -3,9 +3,6 @@ from reactpy.web.module import (
|
|
|
3
3
|
module_from_file,
|
|
4
4
|
module_from_string,
|
|
5
5
|
module_from_url,
|
|
6
|
-
reactjs_component_from_file,
|
|
7
|
-
reactjs_component_from_string,
|
|
8
|
-
reactjs_component_from_url,
|
|
9
6
|
)
|
|
10
7
|
|
|
11
8
|
__all__ = [
|
|
@@ -13,7 +10,4 @@ __all__ = [
|
|
|
13
10
|
"module_from_file",
|
|
14
11
|
"module_from_string",
|
|
15
12
|
"module_from_url",
|
|
16
|
-
"reactjs_component_from_file",
|
|
17
|
-
"reactjs_component_from_string",
|
|
18
|
-
"reactjs_component_from_url",
|
|
19
13
|
]
|