-
-
Notifications
You must be signed in to change notification settings - Fork 329
Expand file tree
/
Copy pathproto.py
More file actions
176 lines (118 loc) · 4.53 KB
/
Copy pathproto.py
File metadata and controls
176 lines (118 loc) · 4.53 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
from __future__ import annotations
from types import TracebackType
from typing import (
Any,
Callable,
Dict,
Iterable,
List,
Mapping,
Optional,
Sequence,
Type,
TypeVar,
Union,
)
from typing_extensions import Protocol, TypedDict, runtime_checkable
ComponentConstructor = Callable[..., "ComponentType"]
"""Simple function returning a new component"""
Key = Union[str, int]
@runtime_checkable
class ComponentType(Protocol):
"""The expected interface for all component-like objects"""
key: Key | None
"""An identifier which is unique amongst a component's immediate siblings"""
type: type[Any] | Callable[..., Any]
"""The function or class defining the behavior of this component
This is used to see if two component instances share the same definition.
"""
def render(self) -> VdomDict | ComponentType | None:
"""Render the component's view model."""
_Self = TypeVar("_Self")
_Render = TypeVar("_Render", covariant=True)
_Event = TypeVar("_Event", contravariant=True)
@runtime_checkable
class LayoutType(Protocol[_Render, _Event]):
"""Renders and delivers, updates to views and events to handlers, respectively"""
async def render(self) -> _Render:
"""Render an update to a view"""
async def deliver(self, event: _Event) -> None:
"""Relay an event to its respective handler"""
def __enter__(self: _Self) -> _Self:
"""Prepare the layout for its first render"""
def __exit__(
self, exc_type: Type[Exception], exc_value: Exception, traceback: TracebackType
) -> Optional[bool]:
"""Clean up the view after its final render"""
VdomAttributes = Mapping[str, Any]
"""Describes the attributes of a :class:`VdomDict`"""
VdomChild = Union[ComponentType, "VdomDict", str]
"""A single child element of a :class:`VdomDict`"""
VdomChildren = Sequence[VdomChild]
"""Describes a series of :class:`VdomChild` elements"""
VdomAttributesAndChildren = Union[
Mapping[str, Any], # this describes both VdomDict and VdomAttributes
Iterable[VdomChild],
]
"""Useful for the ``*attributes_and_children`` parameter in :func:`idom.core.vdom.vdom`"""
class _VdomDictOptional(TypedDict, total=False):
key: Key | None
children: Sequence[
# recursive types are not allowed yet:
# https://github.com/python/mypy/issues/731
Union[ComponentType, Dict[str, Any], str, Any]
]
attributes: VdomAttributes
eventHandlers: EventHandlerDict # noqa
importSource: ImportSourceDict # noqa
class _VdomDictRequired(TypedDict, total=True):
tagName: str # noqa
class VdomDict(_VdomDictRequired, _VdomDictOptional):
"""A :ref:`VDOM` dictionary"""
class ImportSourceDict(TypedDict):
source: str
fallback: Any
sourceType: str # noqa
unmountBeforeUpdate: bool # noqa
class _OptionalVdomJson(TypedDict, total=False):
key: Key
error: str
children: List[Any]
attributes: Dict[str, Any]
eventHandlers: Dict[str, _JsonEventTarget] # noqa
importSource: _JsonImportSource # noqa
class _RequiredVdomJson(TypedDict, total=True):
tagName: str # noqa
class VdomJson(_RequiredVdomJson, _OptionalVdomJson):
"""A JSON serializable form of :class:`VdomDict` matching the :data:`VDOM_JSON_SCHEMA`"""
class _JsonEventTarget(TypedDict):
target: str
preventDefault: bool # noqa
stopPropagation: bool # noqa
class _JsonImportSource(TypedDict):
source: str
fallback: Any
EventHandlerMapping = Mapping[str, "EventHandlerType"]
"""A generic mapping between event names to their handlers"""
EventHandlerDict = Dict[str, "EventHandlerType"]
"""A dict mapping between event names to their handlers"""
class EventHandlerFunc(Protocol):
"""A coroutine which can handle event data"""
async def __call__(self, data: Sequence[Any]) -> None:
...
@runtime_checkable
class EventHandlerType(Protocol):
"""Defines a handler for some event"""
prevent_default: bool
"""Whether to block the event from propagating further up the DOM"""
stop_propagation: bool
"""Stops the default action associate with the event from taking place."""
function: EventHandlerFunc
"""A coroutine which can respond to an event and its data"""
target: Optional[str]
"""Typically left as ``None`` except when a static target is useful.
When testing, it may be useful to specify a static target ID so events can be
triggered programatically.
.. note::
When ``None``, it is left to a :class:`LayoutType` to auto generate a unique ID.
"""