Package
wybthon (package)¶
wybthon
¶
Wybthon: SolidJS for Python, running in the browser on Pyodide.
Wybthon brings SolidJS 2.0's signals-first reactive model to Python. Component bodies run once at mount; reactivity flows through reactive holes: accessors embedded in the VNode tree that update only the DOM nodes that depend on them. A virtual DOM batches every mutation into a single crossing of the Python-to-JavaScript bridge.
Highlights of the reactive model:
- Automatic batching. Signal writes are staged and applied on the
next flush (a microtask, and after each event handler). There is no
batch(); everything batches. Callflushto settle now. - Typed accessors.
create_signalreturns(Accessor[T], Setter[T]); call the accessor to read (tracked),.peek()to read without subscribing. - Typed props. Components declare inputs on a
Propsclass; pyright and mypy check every call without a plugin. - Async-first, with transitions. A memo whose body is
async def(or an async generator) is an async computation:Loadingboundaries show fallbacks until it first resolves. A later recompute opens a transition: the UI that depends on the changed input holds its previous, consistent state until the new value lands, so a new id never shows next to old data.is_pending/latestobserve the in-flight state;refreshandresolvedrive it imperatively. - Actions are transactions.
actionholds a transition open while a mutation runs, so its writes land together;create_optimisticandcreate_optimistic_storeshow temporary values immediately and revert when it settles;affectsanduntildescribe what the action changes and wait for it to land. - Draft-first stores.
create_storesetters take a function that mutates a draft with plain Python. - Server rendering.
wybthon.serverrenders the same components to HTML in CPython, including async data and out-of-order streaming;hydrateadopts that HTML in the browser instead of rebuilding it. - Dev diagnostics. Writes inside a tracking scope raise
WriteInScopeError; reading a signal at the top level of a component body warns.
Everything is importable outside a browser (CPython), so unit tests and tooling run anywhere; the DOM is only touched when rendering.
Example
A minimal counter component:
from wybthon import Prop, Props, button, component, create_signal, div, p, prop, render
class CounterProps(Props):
initial: Prop[int] = prop(default=0)
@component
def Counter(props: CounterProps):
count, set_count = create_signal(props.initial.peek())
return div(
p(t"Count: {count}"),
button("+1", on_click=lambda: set_count(lambda n: n + 1)),
)
render(Counter(initial=5), "#app")
See Also
Modules:
| Name | Description |
|---|---|
assets |
Explicit lazy application chunks produced by |
build |
Deterministic static app bundles, prerendered pages, and a production preview server. |
component |
The |
context |
Context: pass values down the tree without threading props. |
dev |
The |
diagnostics |
Opt-in runtime counters and JSON-ready ownership graph inspection. |
dom |
Lightweight DOM wrapper utilities for Pyodide/browser environments. |
error_boundary |
|
events |
Delegated event handling for the batched renderer. |
flow |
Control flow: |
forms |
Form state, validation helpers, and accessibility attribute utilities. |
html |
Pythonic HTML element helpers that wrap |
kernel |
Batched DOM command buffer and rendering backends. |
lazy |
Lazy-loaded components integrated with |
loading |
|
portal |
Portal component for rendering children into a different DOM container. |
reactivity |
Wybthon's reactive system. |
reconciler |
Reconciliation engine: mounting, patching, and unmounting VNode trees. |
request |
The request being server-rendered, and the response head the render declares. |
router |
Client-side router components and navigation helpers for Pyodide apps. |
scheduling |
Cooperative CPU work that gives the browser opportunities to paint. |
server |
Render components to HTML on the server, for hydration in the browser. |
store |
Transactional, entity-based reactive mappings and sequences. |
svg |
SVG element helpers. |
testing |
Render components in plain CPython and query them like a user would. |
virtual |
Fixed-height list virtualization built on owned virtual DOM list regions. |
vnode |
Virtual node data structure and tree-building helpers. |
Classes:
| Name | Description |
|---|---|
Component |
A run-once component produced by |
Context |
A context token that also acts as its provider component. |
ContextNotFoundError |
Raised by |
Element |
Thin wrapper around a DOM node with convenience methods. |
Ref |
Mutable container holding a reference to a mounted |
DomEvent |
The event object Wybthon passes to delegated handlers. |
EventHandler |
A handler with native listener options, constructed with |
Match |
A branch of a |
Accessor |
A zero-argument callable that returns a reactive value. |
Action |
A wrapped mutation returned by |
ChildrenAccessor |
The resolved children returned by |
Memo |
Read-only derived value; what |
NotReadyError |
Raised when reading an async computation that has no value yet. |
Owner |
A reactive ownership scope. |
ParentProps |
Props for a component that renders |
Prop |
A reactive component input, declared on a |
Props |
Base class for a component's declared inputs. |
ServerError |
An async memo failed on the server; raised again on the client while hydrating. |
Setter |
The write half of |
Signal |
Mutable reactive container; the accessor half of |
WriteInScopeError |
Raised (in dev mode) when a signal is written inside a tracking scope. |
Root |
A mounted application root returned by |
RequestEvent |
One request being rendered on the server. |
ResponseHead |
The status and headers a server render declares. |
VNode |
Virtual node representing an element, text, component, fragment, or hole. |
Draft |
A mapping draft that expires when its callback returns. |
DraftExpiredError |
A draft was used after its setter or deriving function finished. |
DraftList |
A sequence draft with standard Python mutation methods. |
Store |
Read-only reactive mapping with optional attribute access to data keys. |
StoreList |
Read-only reactive sequence. Entity proxies survive reorders. |
StoreSetter |
Apply an atomic draft edit. Exceptions discard all changes from the call. |
Functions:
| Name | Description |
|---|---|
is_dev_mode |
Return whether development mode is currently active. |
set_dev_mode |
Enable or disable development mode diagnostics globally. |
create_context |
Create a |
use_context |
Read the nearest provided value for |
Errored |
Catch errors raised while rendering |
event |
Configure a native listener. Ordinary handlers use batched delegation. |
For |
Render a list with a stable subtree per row. |
Hydration |
Mark a subtree for hydration; a passthrough in Wybthon. |
NoHydration |
Render |
Repeat |
Render |
Show |
Render |
Switch |
Render the first |
client_only |
Render |
dynamic |
Turn an accessor for a component (or tag) into a component you can call. |
is_hydrating |
Whether the browser is adopting server-rendered DOM right now. |
element |
Create a helper |
Loading |
Show a fallback while async reads under the boundary aren't ready. |
Reveal |
Coordinate the reveal order of multiple |
Portal |
Render children into a different DOM container. |
action |
Wrap a mutation in a transaction. |
affects |
Declare, inside an action, which values the action is going to change. |
children |
Resolve a component's children once, so it can inspect or reuse them. |
create_effect |
Create a side effect that re-runs when its tracked sources change. |
create_memo |
Create a derived value that recomputes when its sources change. |
create_optimistic |
Create a value whose writes are optimistic. |
create_owner |
Create an ownership scope owned by the current one. |
create_reaction |
Separate tracking from re-execution: run |
create_render_effect |
Create a split effect that runs in the render phase, before the DOM commit. |
create_root |
Run |
create_signal |
Create a reactive signal and return its |
create_tracked_effect |
Run a tracked callback after DOM commit, disposing its scope before each run. |
create_unique_id |
Return a unique id string (for |
flush |
Apply staged writes, run every dirty effect, and commit the DOM now. |
get_observer |
Return the computation currently tracking reads, or |
get_owner |
Return the active ownership scope, or |
is_accessor |
Return True when |
is_disposed |
Return whether |
is_pending |
Return True while a change is in flight for the value |
is_server |
Return True while a server render is in progress. |
latest |
Evaluate |
map_array |
Map a reactive list to mapped rows with per-row owner scopes. |
merge |
Merge prop sources into one reactive mapping; later sources win. |
omit |
Return a reactive view of |
on_cleanup |
Register |
on_settled |
Run |
prop |
Declare a |
refresh |
Recompute a derived read quietly and return an awaitable for its settled value. |
repeat |
Map an integer range to rows, each with its own owner scope. |
resolve |
Return an awaitable for the next settled value of |
run_with_owner |
Run |
until |
Return an awaitable for the settled, truthy value of |
untrack |
Run |
hydrate |
Adopt server-rendered HTML under |
render |
Render a tree into a container element. |
get_request_event |
Return the request being server-rendered, or |
http_header |
Declare a response header while the calling scope is alive (server only). |
http_status |
Declare the response status while the calling scope is alive (server only). |
Fragment |
Group children without adding a wrapper element. |
h |
Create a VNode from a tag, props, and children. |
hole |
Create a reactive hole explicitly, optionally with a |
create_optimistic_store |
Layer optimistic draft edits over a reactive authoritative source. |
create_projection |
Create a read-only derived store with memo readiness and refresh semantics. |
create_store |
Create a reactive mapping or sequence and its atomic draft setter. |
deep |
Return a detached snapshot, tracking changes only within this subtree. |
reconcile |
Prepare replacement data, preserving matched list entity identities. |
snapshot |
Return a detached, untracked copy of the currently visible state. |
Component
¶
Context
¶
A context token that also acts as its provider component.
Created by create_context. Calling the
context with a value and children returns a provider VNode:
Attributes:
| Name | Type | Description |
|---|---|---|
default |
Value returned by |
|
name |
Optional label for diagnostics. |
ContextNotFoundError
¶
Bases: LookupError
Raised by use_context when no provider is found and no default exists.
Element
¶
Element(tag: str | None = None, existing: bool = False, node: Any = None, node_id: int | None = None)
Thin wrapper around a DOM node with convenience methods.
Element can be constructed in four ways:
- With a tag name to create a brand-new node
(
Element("div")). - With a CSS selector and
existing=Trueto wrap an existing node (Element("#root", existing=True)). - With an opaque
nodevalue to wrap a node returned by another API. - With a kernel
node_id(used internally by the renderer for refs and event targets); the raw node is materialized lazily on first access.
The wrapper proxies common form-input properties (value,
checked, files) so handlers can read state from
e.target.value exactly as in React or SolidJS.
Create a new element, wrap an existing one, or wrap a node handle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tag
|
str | None
|
Tag name ( |
None
|
existing
|
bool
|
If |
False
|
node
|
Any
|
Raw underlying DOM node to wrap. When provided,
|
None
|
node_id
|
int | None
|
Kernel node id to wrap. The raw node is fetched
on first |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither |
Methods:
| Name | Description |
|---|---|
set_text |
Replace the text content of this element. |
append_to |
Append this element to |
append |
Append an |
remove |
Detach this element from its parent (no-op if already detached). |
load_html |
Fetch HTML from |
set_html |
Replace this element's content with the provided HTML string. |
set_attr |
Set an attribute on this element, with text-node fallbacks. |
get_attr |
Return the attribute value for |
remove_attr |
Remove an attribute from this element. |
set_style |
Set CSS properties using a dict and/or keyword arguments. |
add_class |
Add one or more CSS classes to this element. |
remove_class |
Remove one or more CSS classes from this element. |
toggle_class |
Toggle a CSS class, optionally forcing on/off. |
has_class |
Return |
query |
Query a single element by CSS selector. |
query_all |
Query all matching elements by CSS selector. |
find |
Return the first matching descendant |
find_all |
Return all matching descendant elements as a list. |
attach_ref |
Store this element on |
Attributes:
| Name | Type | Description |
|---|---|---|
element |
Any
|
The raw underlying DOM node, materialized on first access. |
node_id |
int
|
This element's kernel node id, registering the raw node if needed. |
value |
Any
|
Current value of an |
checked |
bool
|
Checked state of a checkbox or radio input. |
files |
Any
|
|
element
property
¶
element: Any
The raw underlying DOM node, materialized on first access.
For id-backed elements this commits pending batched DOM ops first, so the node exists and reflects every queued mutation.
load_html
async
¶
load_html(url: str) -> None
Fetch HTML from url and assign it to innerHTML.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
URL to fetch via the browser's |
required |
set_html
¶
set_html(html: str) -> None
Replace this element's content with the provided HTML string.
Caution
This bypasses the renderer's diffing and does not sanitize input. Avoid passing untrusted HTML.
set_attr
¶
get_attr
¶
Return the attribute value for name, or None when absent.
set_style
¶
remove_class
¶
remove_class(*class_names: str) -> None
Remove one or more CSS classes from this element.
toggle_class
¶
has_class
¶
Return True if the element currently has the given class.
query
classmethod
¶
Query a single element by CSS selector.
Commits pending batched DOM ops first so nodes created earlier in the same update are visible to the query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
selector
|
str
|
CSS selector string. |
required |
within
|
Element | None
|
Optional parent |
None
|
Returns:
| Type | Description |
|---|---|
Element | None
|
The first matching |
query_all
classmethod
¶
Query all matching elements by CSS selector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
selector
|
str
|
CSS selector string. |
required |
within
|
Element | None
|
Optional parent |
None
|
Returns:
| Type | Description |
|---|---|
list[Element]
|
A list of wrapped |
find_all
¶
Return all matching descendant elements as a list.
Ref
¶
Mutable container holding a reference to a mounted Element.
Pass a Ref to an element's ref= prop. After mount ref.current
is the wrapped element; after unmount it's reset to None. The ref
prop also accepts a callback ref(el) or a list mixing both, so a
component can forward a parent's ref and keep its own:
class FancyInputProps(Props):
ref: Ref | Callable[[Element], Any] | None = None
@component
def FancyInput(props: FancyInputProps):
local = Ref()
on_settled(lambda: local.current.element.focus())
return input_(type="text", ref=[local, props.ref])
Refs are assigned during mount, so read them in
on_settled or an effect, not at the top of
the component body.
DomEvent
¶
The event object Wybthon passes to delegated handlers.
Built from the kernel's dispatch payload rather than a JsProxy,
so reading it is free of bridge crossings. Use
raw to reach the native event object for
anything not covered by the payload.
Attributes:
| Name | Type | Description |
|---|---|---|
type |
Event type string (e.g., |
|
target |
Payload-backed view of the original event target,
exposing |
|
current_target |
The element whose handler is currently running
(an id-backed |
|
key |
|
|
code |
|
|
alt_key |
Whether Alt was held. |
|
ctrl_key |
Whether Ctrl was held. |
|
meta_key |
Whether Meta/Cmd was held. |
|
shift_key |
Whether Shift was held. |
|
button |
|
|
client_x |
Pointer x position, when applicable. |
|
client_y |
Pointer y position, when applicable. |
Build an event from a dispatch payload dict.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
dict[str, Any]
|
Parsed dispatch payload from the kernel. |
required |
current_target
|
Any | None
|
The |
None
|
Methods:
| Name | Description |
|---|---|
prevent_default |
Prevent the default browser action for this event. |
stop_propagation |
Stop the delegated dispatch from walking further up the tree. |
EventHandler
dataclass
¶
EventHandler(callback: Callable[..., Any], capture: bool = False, passive: bool = False, once: bool = False)
A handler with native listener options, constructed with event.
Match
¶
Accessor
¶
A zero-argument callable that returns a reactive value.
Calling an accessor inside a tracking scope (a memo, an effect's
compute stage, or a reactive hole) subscribes that scope to the
value. peek reads without subscribing.
Every reactive read in Wybthon goes through an Accessor:
create_signal getters are
Signals, create_memo
returns a Memo, and component parameters are
Props. Embedding an accessor in a VNode tree
creates a reactive hole. Type it as Accessor[T] in signatures
when you accept any of them.
Methods:
| Name | Description |
|---|---|
peek |
Return the current value without subscribing anything. |
Action
¶
A wrapped mutation returned by action.
Calling it invokes the wrapped function inside a transaction. The
pending accessor is True while any invocation is in flight; it
reveals immediately, so it's the right thing to bind a disabled
button or a spinner to.
Attributes:
| Name | Type | Description |
|---|---|---|
pending |
Accessor[bool]
|
Tracked accessor: |
pending
instance-attribute
¶
pending: Accessor[bool] = _core.run_with_owner(None, lambda: Memo(lambda: count() > 0))
Tracked accessor: True while an invocation is in flight.
ChildrenAccessor
¶
Memo
¶
Memo(fn: Callable[..., T], *, equals: Any = _DEFAULT_EQUALS, lazy: bool = False, unobserved: Callable[[], Any] | None = None, name: str | None = None, loading_value: Any = _MISSING, ssr_source: str = 'server')
Bases: Computation, Accessor[T]
Read-only derived value; what create_memo returns.
A Memo is both a Computation
(it tracks sources and recomputes lazily) and an
Accessor (call it to read). Recomputation
happens on read after a source changed, and observers are notified
only when the recomputed value differs under the memo's equals
policy.
Async bodies (async def, or an async generator) make the memo an
async computation; see create_memo.
Methods:
| Name | Description |
|---|---|
peek |
Return the (up-to-date) value without subscribing; |
NotReadyError
¶
Bases: Exception
Raised when reading an async computation that has no value yet.
Propagates "not ready" through the graph: a memo whose body reads a
pending async memo becomes pending itself, and a reactive hole that
hits NotReadyError keeps its previous content while the nearest
Loading boundary shows its fallback.
Application code rarely raises or catches this directly; use
is_pending and latest
to observe pending state without suspending.
Owner
¶
A reactive ownership scope.
Owners form a tree. Disposing an owner disposes its children first
(depth-first), then runs its own cleanup callbacks LIFO. Every
computation is an owner, as is each component instance, each
For row, and each create_root.
Owners also carry context values (see
create_context) and an optional error
handler installed by Errored.
Methods:
| Name | Description |
|---|---|
dispose |
Tear down this owner and every descendant. |
dispose
¶
Tear down this owner and every descendant.
Children are disposed depth-first, then this owner's cleanups run in LIFO order, then it detaches from its parent. Later calls are no-ops.
Prop
¶
A reactive component input, declared on a Props class.
The parent may pass a T, an accessor of T, or a zero-argument
function returning T. Reading the field on the component's props
returns an Accessor: place it in the tree to
create a reactive hole, call it inside a tracking scope, or use
.peek() for an intentional one-time read.
Props
¶
Props(**values: Any)
Bases: _PropsBase
Base class for a component's declared inputs.
Subclass it, annotate fields, and take one parameter of that type in
the component. Every component also accepts key, which gives the
instance a stable identity for keyed reconciliation.
At run time the reconciler builds one instance per mounted
component. Reading a Prop[T] field returns an accessor that tracks
the parent's current value, so a parent that later passes a new value
(or an accessor) updates the child without re-running it.
ServerError
¶
Bases: RuntimeError
An async memo failed on the server; raised again on the client while hydrating.
The original exception doesn't survive serialization, so the client
sees its type name and message. An Errored
boundary shows the same fallback on both sides; resetting the
boundary runs the computation again in the browser.
Setter
¶
Bases: Protocol
The write half of create_signal.
Call it with a new value, or with an updater (current) -> new for a
functional update. Returns the value that was staged.
Signal
¶
Signal(value: T, *, equals: Any = _DEFAULT_EQUALS, unobserved: Callable[[], Any] | None = None, name: str | None = None)
Bases: Accessor[T]
Mutable reactive container; the accessor half of create_signal.
Reading a Signal (calling it) returns the committed value and
subscribes the active tracking scope. set
stages a write that becomes visible at the next flush.
While a transition holds the signal (its last write is waiting for async work to land), reads from outside the graph, such as event handlers, keep returning the value the UI shows; reads inside memos, effects, and holes see the new value.
Most code destructures create_signal into (getter, setter);
Signal is public so it can appear in type hints and so
self-contained reactive fields (as in
Field) can carry their own setter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
T
|
The initial value. |
required |
equals
|
Any
|
Equality policy; see |
_DEFAULT_EQUALS
|
unobserved
|
Callable[[], Any] | None
|
Optional callback invoked when the signal loses its last subscriber (resource cleanup). |
None
|
name
|
str | None
|
Optional label used in dev-mode diagnostics. |
None
|
Methods:
| Name | Description |
|---|---|
peek |
Return the committed value without subscribing. |
set |
Stage a write; the new value is visible after the next flush. |
set
¶
set(value: T | Callable[[T], T]) -> T
Stage a write; the new value is visible after the next flush.
Supports functional updates: when value is callable it
receives the latest value (including any write staged earlier
in the same batch) and its result is stored, so two
set(lambda n: n + 1) calls in one handler add two. To store a
callable as the value, return it from an updater:
set(lambda _: my_fn).
In dev mode, writing from inside a tracking scope raises
WriteInScopeError.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
T | Callable[[T], T]
|
The new value, or an updater |
required |
Returns:
| Type | Description |
|---|---|
T
|
The value that was staged. |
WriteInScopeError
¶
Bases: RuntimeError
Raised (in dev mode) when a signal is written inside a tracking scope.
Writing a signal from a memo body, a single-function effect, or a
reactive hole is almost always a bug: derive the value with
create_memo instead, or move the write
into the untracked apply stage of a split
create_effect, an event handler, or an
action.
Root
¶
RequestEvent
dataclass
¶
RequestEvent(url: str = '/', request: Any = None, locals: dict[str, Any] = dict(), response: ResponseHead = ResponseHead())
One request being rendered on the server.
Attributes:
| Name | Type | Description |
|---|---|---|
url |
str
|
The request path and query, read by the router. |
request |
Any
|
The framework's request object, passed through as is. |
locals |
dict[str, Any]
|
Per-request values for the application (the signed-in user, a database session, and so on). |
response |
ResponseHead
|
The response head the render declares. |
ResponseHead
dataclass
¶
ResponseHead(status: int = 200, status_text: str | None = None, headers: dict[str, list[str]] = dict(), committed: bool = False, _statuses: list[tuple[object, int, str | None]] = list(), _headers: list[tuple[object, str, str, bool]] = list(), _base: tuple[int, str | None, dict[str, list[str]]] | None = None)
The status and headers a server render declares.
Attributes:
| Name | Type | Description |
|---|---|---|
status |
int
|
The HTTP status code. |
status_text |
str | None
|
An optional reason phrase. |
headers |
dict[str, list[str]]
|
Header values by lowercase name, in declaration order. |
committed |
bool
|
Set once the head can no longer change (the render finished, or a stream sent its shell). |
Methods:
| Name | Description |
|---|---|
header_items |
Return |
VNode
¶
VNode(tag: str | Callable[..., Any] | None, props: PropsDict | None = None, children: list[Any] | None = None, key: str | int | None = None)
Virtual node representing an element, text, component, fragment, or hole.
Uses __slots__ for a compact layout. The renderer populates the
internal attributes (el, subtree, render_effect,
component_ctx, ns, _frag_end) when the VNode mounts.
Attributes:
| Name | Type | Description |
|---|---|---|
tag |
Element tag name ( |
|
props |
PropsDict
|
Mapping of prop names to values: attributes, event handlers, refs, and reactive bindings. |
children |
list[Any]
|
Child VNodes (mixed values before normalization). |
key |
Optional stable identity for keyed reconciliation. |
|
el |
int | None
|
Kernel node id once mounted (for fragments the start marker; for holes the end marker). |
owner_scope |
Any
|
Optional reactive |
Draft
¶
DraftExpiredError
¶
Bases: RuntimeError
A draft was used after its setter or deriving function finished.
DraftList
¶
Bases: StoreList[T], MutableSequence[T]
A sequence draft with standard Python mutation methods.
Methods:
| Name | Description |
|---|---|
insert |
Insert a value at a draft index. |
extend |
Append values in one recorded splice. |
clear |
Remove all items in one transactional edit. |
sort |
Sort entities without changing their identities. |
reverse |
Reverse entity order in the draft. |
move |
Move a contiguous range to a final index, preserving its entities. |
sort
¶
Sort entities without changing their identities.
Store
¶
Bases: _Proxy, Mapping[str, Any]
Read-only reactive mapping with optional attribute access to data keys.
Missing subscriptions raise KeyError; missing attributes raise AttributeError.
Mapping methods take precedence over data keys: use store["items"].
Methods:
| Name | Description |
|---|---|
get |
Return the value for |
StoreList
¶
StoreSetter
¶
Apply an atomic draft edit. Exceptions discard all changes from the call.
set_dev_mode
¶
set_dev_mode(enabled: bool) -> None
Enable or disable development mode diagnostics globally.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enabled
|
bool
|
When |
required |
create_context
¶
Create a Context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
default
|
Any
|
Optional value returned by |
_MISSING
|
name
|
str | None
|
Optional label for diagnostics. |
None
|
Returns:
| Type | Description |
|---|---|
Context[Any]
|
A new |
use_context
¶
use_context(ctx: Context[T]) -> T
Read the nearest provided value for ctx.
Walks up the ownership tree from the active scope and returns the value exactly as the provider received it: a signal or accessor stays a signal or accessor (call it where you need the value), a static value is returned directly.
Raises:
| Type | Description |
|---|---|
ContextNotFoundError
|
No provider is above the caller and the context has no default. |
Errored
¶
Errored(children: Any = None, *, fallback: Any = None, on_error: Callable[[BaseException], Any] | None = None, reset_on: Any = None) -> VNode
Catch errors raised while rendering children and show a fallback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
children
|
Any
|
Content rendered while no error is active: a VNode, a zero-arg callable, or a list of either. |
None
|
fallback
|
Any
|
A VNode, a string, or a callable
|
None
|
on_error
|
Callable[[BaseException], Any] | None
|
Optional callback invoked with the caught exception. |
None
|
reset_on
|
Any
|
An accessor (or plain value) whose change clears the current error automatically, for example the current route. |
None
|
Returns:
| Type | Description |
|---|---|
VNode
|
A component |
VNode
|
whenever a descendant raises. |
event
¶
event(handler: Callable[..., Any], *, capture: bool = False, passive: bool = False, once: bool = False) -> EventHandler
Configure a native listener. Ordinary handlers use batched delegation.
For
¶
For(each: Any, children: Callable[..., Any], fallback: Any = None, *, keyed: bool | Callable[[Any], Any] = True) -> VNode
Render a list with a stable subtree per row.
The mapping callback runs once per row; when the list changes, existing rows keep their DOM and are only moved, never re-diffed. A row's reactive scope is disposed when it leaves the list.
keyed selects how rows are matched, and with it the callback
shape:
True(default): match by identity (scalars by value).children(item, index)receives the raw item and anAccessor[int]index.False: match by position.children(item, index)receives anAccessorfor the item at that position and anintindex.- a callable
key(item): match by key, updating the row in place when a new object has the same key.children(item, index)receives accessors for both.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
each
|
Any
|
List accessor (or a plain list, which renders once). |
required |
children
|
Callable[..., Any]
|
The row callback. |
required |
fallback
|
Any
|
Rendered when the list is empty. |
None
|
keyed
|
bool | Callable[[Any], Any]
|
Matching strategy. |
True
|
Hydration
¶
Mark a subtree for hydration; a passthrough in Wybthon.
Solid 2.0 uses <Hydration> to re-enable hydration for an island
inside <NoHydration>. Wybthon keeps a NoHydration region static
as a whole while hydrating, so this renders its children unchanged.
It's provided so code shared with Solid's model reads the same.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*children
|
Any
|
The content. |
()
|
id
|
str | None
|
Accepted for parity; unused. |
None
|
NoHydration
¶
Render children on the server as static HTML the browser won't hydrate.
While the browser hydrates, the region's server-rendered DOM is kept as is and nothing inside it is mounted, so it costs no Python work and never updates. In a page that wasn't server-rendered, the children render normally. Use it for content that never changes after the first paint: article bodies, footers, legal text.
Matches Solid 2.0's <NoHydration>.
Repeat
¶
Repeat(count: Any, children: Callable[[int], Any], fallback: Any = None, *, start: int | Any = 0) -> VNode
Render children(i) for i in range(start, start + count) with no diffing.
Rendering is driven purely by the count: growing mounts new tail slots, shrinking disposes them, and nothing else is touched. Use it for pagination dots, ratings, skeletons, and other count-driven UI.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
count
|
Any
|
Count accessor or plain integer. |
required |
children
|
Callable[[int], Any]
|
|
required |
fallback
|
Any
|
Rendered when the count is zero. |
None
|
start
|
int | Any
|
First index (accessor or int). |
0
|
Show
¶
Render children while when is truthy, else fallback.
Only the truthiness of when is tracked by default: the branch
re-renders when the condition flips, not on every value change. A
callable children may accept one argument, an
Accessor for the (truthy) value, so inner
holes can read it reactively.
With keyed=True, children re-renders whenever the value itself
changes and receives the raw value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
when
|
Any
|
Condition accessor or plain value. |
required |
children
|
Any
|
VNode, zero-arg callable, or |
None
|
fallback
|
Any
|
Rendered when |
None
|
keyed
|
bool
|
Re-create the branch on every value change. |
False
|
Switch
¶
Render the first Match whose condition is truthy.
Conditions are evaluated in order inside the switch's own scope;
only a change in which branch matches re-renders, so unrelated
value changes are ignored (unless a branch is keyed).
client_only
¶
Render children only in the browser, after hydration.
During a server render, and while the browser hydrates that render,
fallback shows instead; the children replace it as soon as
hydration has committed. In a page that wasn't server-rendered,
the children render immediately. Use it for widgets that need
browser APIs or whose output depends on the browser (a map, a chart
measured from the viewport, the user's local time).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
children
|
Any
|
A VNode or a zero-arg callable returning the content. |
required |
fallback
|
Any
|
What the server renders, and what shows until hydration finishes. |
None
|
dynamic
¶
Turn an accessor for a component (or tag) into a component you can call.
The returned callable behaves like any component: call it with
children and props to get a VNode. Each instance re-mounts when
source resolves to a different component; while source is an
async computation with no value yet, the instance keeps its current
content and the nearest Loading shows its
fallback. Passing None renders nothing.
This is the counterpart of SolidJS 2.0's dynamic(). For a one-off
use, call the result inline: dynamic(lambda: views[kind()])(title="Hi").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Any
|
An accessor returning a component, a tag name, or
|
required |
is_hydrating
¶
is_hydrating() -> bool
Whether the browser is adopting server-rendered DOM right now.
True only during the synchronous mount of hydrate:
render what the server rendered, then switch to client-only values
from on_settled. Always false on the server and in pages that
weren't server-rendered.
element
¶
Loading
¶
Show a fallback while async reads under the boundary aren't ready.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
children
|
Any
|
Content rendered when nothing is loading: a VNode, a
zero-arg callable, or a list of either. Async computations
read anywhere in this subtree self-register with the
boundary when a read raises
|
None
|
fallback
|
Any
|
VNode, string, or callable returning one of those, shown while any registered async computation has no value. |
None
|
on
|
Any
|
An accessor, or list of accessors, naming the boundary's
inputs. The boundary waits for them initially even if the
children never read them, and when one of them changes
while data under the boundary is pending, the fallback
shows again instead of the old content being held. Use it
for "new record, fresh boundary" (a route's |
None
|
Returns:
| Type | Description |
|---|---|
VNode
|
A component |
VNode
|
fallback and children. |
Reveal
¶
Reveal(children: Any = None, *, order: RevealOrder = 'sequential', collapsed: bool = False) -> VNode
Coordinate the reveal order of multiple Loading boundaries.
Each Loading boundary mounted underneath (that isn't nested
inside another boundary) registers with the Reveal in mount
order, and the Reveal decides when each may show its content and
whether it shows its fallback. A Reveal nested inside another is
one composite slot in the parent's order: its boundaries stay on
their fallbacks until the parent releases the slot, then follow the
inner order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
children
|
Any
|
Content containing one or more |
None
|
order
|
RevealOrder
|
|
'sequential'
|
collapsed
|
bool
|
Only consulted with |
False
|
Returns:
| Type | Description |
|---|---|
VNode
|
A component |
Example
Note
Every boundary's content mounts immediately (parked
off-document while pending), so all of them load in parallel;
order only controls when each is revealed.
Portal
¶
Render children into a different DOM container.
Matches SolidJS's <Portal mount={...}>. The children mount into
mount (by default document.body) while remaining linked to the
surrounding component's reactive scope, so signals, context, and
lifecycle hooks still apply, and they're removed when the portal
unmounts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
children
|
Any
|
A VNode, a list of VNodes, or a zero-arg callable (rendered as a reactive hole). |
None
|
mount
|
Any
|
The target container: an |
'body'
|
Returns:
| Type | Description |
|---|---|
VNode
|
A component |
Note
A portal renders nothing during a server render. Its children mount in the browser once the page has hydrated.
action
¶
Wrap a mutation in a transaction.
Calling the returned Action invokes fn and
holds a transition open until it settles. Inside:
- Plain writes stage into the transaction. Signals and stores
written by the action (before or after an
await) commit to the graph but reveal together when the action settles, as does the landing of any memo itrefreshes. Reads inside the action see the staged values. - Optimistic writes reveal now. Values written through
create_optimisticorcreate_optimistic_storeshow immediately and revert when the action settles. action.pending()isTruefrom the call until it settles;affectsmarks other values as pending, anduntilwaits for a condition on the authoritative view.
Independent actions settle separately. Nested actions and actions that write shared reactive state join and publish together.
Errors route to the nearest Errored boundary
captured at call time and re-raise to the awaiter, so
await my_action(...) behaves like a normal call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[..., Any]
|
The mutation; sync or |
required |
Returns:
| Type | Description |
|---|---|
Action
|
A callable |
Example
todos, set_todos = create_store({"items": []})
shown, set_shown = create_optimistic_store(lambda: deep(todos)["items"], [])
@action
async def add_todo(title):
set_shown(lambda s: s.append({"title": title, "saving": True}))
saved = await api_create(title)
set_todos(lambda s: s["items"].append(saved))
affects
¶
affects(*targets: Any) -> None
Declare, inside an action, which values the action is going to change.
Until the action settles, is_pending reports
True for expressions that read any of targets, even before the
action has written anything. Use it when the pending state should
show on the data being changed rather than on the action itself,
for example to dim a record while a save is in flight.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*targets
|
Any
|
Signals, memos, or stores (a store proxy marks the selected subtree). |
()
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If called outside an action's synchronous segment. |
TypeError
|
For a target that isn't a reactive node or store. |
children
¶
children(fn: Callable[[], Any]) -> ChildrenAccessor
Resolve a component's children once, so it can inspect or reuse them.
Wraps a getter that returns children (typically props.children)
and returns a memoized accessor. Nested lists are flattened,
reactive children (accessors and zero-argument functions) are called
and their results resolved, and None and booleans are dropped.
This matches Solid 2.0's children helper.
create_effect
¶
create_effect(compute: Callable[..., Any], apply: Callable[..., Any], *, defer: bool = False, error: Callable[[BaseException], Any] | None = None) -> Computation
Create a side effect that re-runs when its tracked sources change.
Effects run after the DOM has been committed, so they observe the updated document; the first run happens on the next flush (right after the component that created it has mounted), not at creation. Inside a component they're disposed on unmount.
Split effect: compute runs tracked and returns a
value; apply runs untracked with (value, prev) and performs
the side effect. Incidental reads inside apply never
over-subscribe the effect, and signal writes belong there. apply
may return a cleanup callable that runs before the next apply and
on disposal.
Use create_tracked_effect when one
callback should combine tracking and side effects. Split effects keep
committed resources alive while replacement data is held.
If compute accepts a positional parameter it receives its previous
return value (None on the first run). compute may be
async def; awaits suspend the effect without blocking and reads
after an await are still tracked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
Callable[..., Any]
|
The tracked stage. |
required |
apply
|
Callable[..., Any]
|
Untracked side-effect stage receiving
|
required |
defer
|
bool
|
When |
False
|
error
|
Callable[[BaseException], Any] | None
|
Optional handler receiving exceptions raised by
|
None
|
Returns:
| Type | Description |
|---|---|
Computation
|
The underlying computation; call |
Example
Note
Effects don't run during a server render; see
is_server.
create_memo
¶
create_memo(fn: Callable[..., AsyncIterator[T]], *, equals: Any = ..., lazy: bool = ..., unobserved: Callable[[], Any] | None = ..., name: str | None = ..., loading_value: T = ..., ssr_source: SsrSource = ...) -> Memo[T]
create_memo(fn: Callable[..., Any], *, equals: Any = _DEFAULT_EQUALS, lazy: bool = False, unobserved: Callable[[], Any] | None = None, name: str | None = None, loading_value: Any = _MISSING, ssr_source: SsrSource = 'server') -> Memo[Any]
Create a derived value that recomputes when its sources change.
Memos evaluate once at creation unless lazy=True. Updates are
pull-based: the body runs when the memo is read after
a tracked source changed, and observers are notified only when the
new value differs under equals. If fn accepts a positional
parameter it receives the previous value (None on the first run).
Async memos. When fn is an async def (or returns an
awaitable), the memo becomes an async computation: reading it
before the first value raises
NotReadyError, which the nearest
Loading boundary turns into fallback UI. Once
it has a value, a recompute caused by an input change opens a
transition: readers keep the previous value and the parts of
the UI that depend on the changed input stay as they are until the
new value lands, so the screen never shows a new input next to
old data. Use is_pending to show a refresh
hint and latest to read the new state early.
Reads after an await are tracked exactly like reads before it.
Async generators. An async def body containing yield
streams: each yielded value becomes the memo's new value. Use it
to adapt sockets, subscriptions, or any async iterable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[..., Any]
|
Zero- or one-arg callable producing the value (sync, async, or an async generator). |
required |
equals
|
Any
|
Equality policy; see |
_DEFAULT_EQUALS
|
lazy
|
bool
|
When |
False
|
unobserved
|
Callable[[], Any] | None
|
Optional callback fired when the memo loses its last
subscriber; pair it with |
None
|
name
|
str | None
|
Optional label used in dev-mode diagnostics. |
None
|
loading_value
|
Any
|
For async memos, a value to serve while the first
run is in flight instead of raising |
_MISSING
|
ssr_source
|
SsrSource
|
Where an async memo resolves when the page is
server-rendered. |
'server'
|
Returns:
| Type | Description |
|---|---|
Memo[Any]
|
A |
create_optimistic
¶
Create a value whose writes are optimistic.
Reads return the override while one is active, else the source
value. Writes reveal immediately, even inside an
action whose other writes are held, and the
override reverts when the transaction it was written in settles.
While an override is active, is_pending
reports True for expressions that read it, and
until sees through it to the source.
Use it both for optimistic data (the like count you expect the server to confirm) and for process state that must show during an action (a "saving" flag).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Any
|
A zero-arg accessor to shadow, or a plain initial value. |
required |
Returns:
| Type | Description |
|---|---|
tuple[Accessor[Any], Setter[Any]]
|
A |
create_owner
¶
create_owner() -> Owner
Create an ownership scope owned by the current one.
The scope is disposed with its parent. Run code under it with
run_with_owner, and dispose it early
with owner.dispose(). Pass it to run_with_owner(None, ...) first
for a scope with an independent lifetime.
create_reaction
¶
create_reaction(effect: Callable[[], Any], *, error: Callable[[BaseException], Any] | None = None) -> Callable[[Callable[[], Any]], None]
Separate tracking from re-execution: run effect once when tracked reads change.
Returns track(fn). Calling track runs fn and subscribes to what
it reads; the first time any of those sources changes, effect runs
(untracked, after the DOM commit) and the subscription ends. Call
track again to re-arm it. Matches Solid 2.0's createReaction.
create_render_effect
¶
create_render_effect(compute: Callable[..., Any], apply: Callable[..., Any], *, defer: bool = False, error: Callable[[BaseException], Any] | None = None) -> Computation
Create a split effect that runs in the render phase, before the DOM commit.
Wybthon's reactive holes and prop bindings are render effects, so a
render effect observes the DOM in the same state the framework's own
bindings do (updates emitted, not yet committed). Prefer
create_effect unless you're building a
rendering primitive.
Like Solid 2.0's createRenderEffect, it always takes a tracked
compute stage and an untracked apply stage, with the same
arguments as create_effect.
create_root
¶
Run fn inside a root owned by the current scope unless explicitly detached.
Use it for explicitly disposable reactive work. Pass detached=True
for global stores or subscriptions that outlive the surrounding component.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[[Callable[[], None]], T]
|
Receives a |
required |
detached
|
bool
|
Create an independent lifetime instead of joining the current owner. |
False
|
Returns:
| Type | Description |
|---|---|
T
|
Whatever |
create_signal
¶
create_signal(value: T | Callable[[], T], *, equals: Any = _DEFAULT_EQUALS, name: str | None = None, owned_write: bool = False) -> tuple[Accessor[T], Setter[T]]
Create a reactive signal and return its (getter, setter) pair.
Writes are staged: the setter records the new value and every
read keeps returning the committed value until the next flush (a
browser microtask, the end of an event handler, or an explicit
flush). There is no batch(); everything
batches.
The setter supports functional updates: pass lambda n: n + 1
and it receives the latest staged value, so repeated updates in one
handler compose. To store a callable as the value, return it from an
updater: set_fn(lambda _: my_callable).
Function form. When value is a zero-argument callable, the
result is a writable derived signal: the getter tracks whatever
the function reads and recomputes when those sources change, while
the setter overrides the value until the next source change.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
T | Callable[[], T]
|
The initial value, or a zero-arg function for the derived form. |
required |
equals
|
Any
|
Equality policy deciding when subscribers are notified:
|
_DEFAULT_EQUALS
|
name
|
str | None
|
Optional label used in dev-mode diagnostics. |
None
|
owned_write
|
bool
|
Allow writes from inside an owned scope (a memo,
an effect's compute stage, or a reactive hole) without
raising |
False
|
Returns:
| Type | Description |
|---|---|
Accessor[T]
|
A |
Setter[T]
|
|
tuple[Accessor[T], Setter[T]]
|
read untracked); the setter is a |
create_tracked_effect
¶
create_tracked_effect(fn: Callable[..., Any], *, error: Callable[[BaseException], Any] | None = None) -> Computation
Run a tracked callback after DOM commit, disposing its scope before each run.
Prefer split effects for external resources: a tracked callback can run while async work is pending. Reads subscribe; put writes in a split effect's apply stage. Doesn't run during a server render.
create_unique_id
¶
create_unique_id() -> str
Return a unique id string (for for/id attribute pairs).
Ids created while a server render or a hydration mounts are derived
from the component's position in the tree (wyb-h followed by a
short hash), so the server and the hydrating browser agree on them.
flush
¶
flush(fn: Callable[[], T] | None = None) -> T | None
Apply staged writes, run every dirty effect, and commit the DOM now.
Writes become visible to reads only when the graph flushes. In the
browser that happens automatically on a microtask and after every
event handler; call flush() when you need the settled state
now, for example right after a write in synchronous test code.
If the flush opens a transition (a write made an async computation that already had a value recompute), the affected parts of the UI stay on their previous state until that work lands; everything else reveals as usual.
Safe to call at any time; a no-op when nothing is pending, and a no-op inside an effect (the running flush finishes the work).
With fn, runs it first and then flushes, returning its result:
flush(lambda: set_count(1)) applies the write synchronously.
get_observer
¶
get_observer() -> Computation | None
Return the computation currently tracking reads, or None.
get_owner
¶
get_owner() -> Owner | None
Return the active ownership scope, or None outside any scope.
Capture it before an await and restore it with
run_with_owner when you need to create
primitives after the boundary.
is_accessor
¶
Return True when value is a reactive expression: an Accessor or a zero-arg function.
This is the single rule the framework uses to decide what becomes a
reactive hole (as a child), a reactive binding (as a prop), or an
auto-unwrapped component prop. Plain functions and lambdas qualify
when they take no required positional arguments; bound methods
likewise. Classes, Refs, components, and callbacks that take
arguments do not.
is_pending
¶
Return True while a change is in flight for the value fn reads.
Evaluates fn in probe mode and reports whether any value it read
is waiting on a transition:
- a signal or memo whose new value is held (the batch that
changed it is waiting for async work to land, or the write was
made inside an
actionthat hasn't settled); - an async computation whose recompute is in flight (a quiet
refreshis silent); - a value an in-flight action declared with
affects; - an optimistic value with an active override;
- a read that raises
NotReadyError.
The reads are tracked like any other, so a hole using is_pending
updates as the state changes, but they don't make the hole wait for
the transition: an indicator has to show during the hold.
latest
¶
latest(fn: Callable[[], T]) -> T | None
Evaluate fn against the newest state, without ever suspending.
Two things differ from a plain read:
- Not-ready async reads return their most recent value (or
Noneif they never resolved) instead of raisingNotReadyError. - Values a transition holds return the new value being computed rather than the one the UI still shows. Use it when a piece of UI should update ahead of the rest (a header that shows the newly selected id while the detail pane keeps the old record).
map_array
¶
map_array(source: Callable[[], Sequence[T] | None], fn: Callable[..., U], *, keyed: bool | Callable[[T], Any] = True, fallback: Callable[[], U] | None = None) -> Memo[list[U]]
Map a reactive list to mapped rows with per-row owner scopes.
Rows are matched between updates according to keyed:
True(default): match by identity (scalars by value). A matched row keeps its scope and mapped result and its index accessor updates.fn(item, index)receives the raw item and anAccessor[int].False: match by position. The row at each index is reused and its item accessor updates.fn(item, index)receives anAccessor[T]and anint.- a callable
key(item) -> hashable: match by key. Both item and index are accessors:fn(item, index)receivesAccessor[T]andAccessor[int].
Row bodies run untracked inside the row's owner; anything
reactive inside a row must read an accessor within a hole, memo, or
effect, and cleanups registered with on_cleanup run when the row is
removed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Callable[[], Sequence[T] | None]
|
Zero-arg accessor returning the list (or |
required |
fn
|
Callable[..., U]
|
Row mapping function; see the shapes above. |
required |
keyed
|
bool | Callable[[T], Any]
|
Matching strategy. |
True
|
fallback
|
Callable[[], U] | None
|
Optional zero-arg callable whose result is the single row when the list is empty. |
None
|
Returns:
| Type | Description |
|---|---|
Memo[list[U]]
|
A |
merge
¶
Merge prop sources into one reactive mapping; later sources win.
Each source may be a component's props, a plain dict (values may be
accessors or static), a zero-arg function returning a dict, or
another merged or omitted view. Reads resolve right to left at
access time, so tracking flows through to whichever source supplied
the key. A key present with the value None overrides earlier
sources, as an explicit undefined does in Solid 2.0.
The result is a mapping of accessors: spread it onto an element
(button(**merge(defaults, extra))).
omit
¶
Return a reactive view of source without some keys.
Pass key names, or a single predicate that returns True for each
key to drop. The replacement for Solid 1.x's splitProps: handle
some props locally and forward the rest.
on_cleanup
¶
Register fn to run when the active scope is disposed or re-runs.
- Inside an effect body: runs before each re-run and on disposal.
- Inside a component body: runs when the component unmounts.
- Inside a reactive hole or
Forrow: runs when that region is re-evaluated or torn down.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If called outside any reactive scope. |
on_settled
¶
Run fn once the current render has settled and committed to the DOM.
The replacement for on_mount: inside a component body, fn runs
after the flush that mounted the component has finished, so refs
are assigned and the DOM is live. fn may return a cleanup callable,
which runs when the owning scope is disposed (on unmount).
Doesn't run during a server render.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[[], Any]
|
Zero-arg callback. May return a cleanup callable. |
required |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If called outside any reactive scope. |
prop
¶
Declare a Prop[T] field's default.
Type checkers only recognize a field specifier's default when it's
passed by keyword, so write prop(default=0). Use
default_factory for mutable defaults.
refresh
¶
Recompute a derived read quietly and return an awaitable for its settled value.
"Quiet" means no pending state is reported while the run is in
flight: is_pending stays False and
readers keep the previous value. Use it after a server write to
re-ask for data derived from the source of truth.
Called inside an action, the refreshed value
lands into the action's transaction and reveals together with the
action's other writes when it settles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Any
|
A |
required |
Returns:
| Type | Description |
|---|---|
Awaitable[Any]
|
An awaitable resolving with the target's next settled value. |
Awaitable[Any]
|
Safe to ignore for fire-and-forget use. |
repeat
¶
repeat(count: Callable[[], int] | int, fn: Callable[[int], U], *, start: Callable[[], int] | int = 0, fallback: Callable[[], U] | None = None) -> Memo[list[U]]
Map an integer range to rows, each with its own owner scope.
The counterpart of Solid 2.0's repeat: fn(i) runs once per slot
for i in range(start, start + count). Growing the count maps only
the new slots; shrinking it disposes the removed ones. Changing
start maps every slot again, because each row received a plain int.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
count
|
Callable[[], int] | int
|
The number of slots, or an accessor for it. |
required |
fn
|
Callable[[int], U]
|
Maps one slot number to a row. |
required |
start
|
Callable[[], int] | int
|
The first slot number, or an accessor for it. |
0
|
fallback
|
Callable[[], U] | None
|
Optional zero-arg callable whose result is the single row when the count is zero. |
None
|
Returns:
| Type | Description |
|---|---|
Memo[list[U]]
|
A |
resolve
¶
Return an awaitable for the next settled value of fn().
Tracks every dependency of fn, including cached memos, and waits
for pending or quiet async recomputations. Streams become ready at
their first fresh yield. Rejects when the expression raises; cancellation
removes the temporary subscriptions.
run_with_owner
¶
Run fn under owner (pass None for no ownership) and return its result.
until
¶
Return an awaitable for the settled, truthy value of pred().
pred is evaluated reactively against the authoritative view:
optimistic overrides are invisible, so the condition observes real
data only. Inside an action, reads see the action's own staged
writes. A read that raises NotReadyError
simply waits for the value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred
|
Callable[[], T]
|
Zero-arg predicate. |
required |
timeout
|
float | None
|
Optional seconds after which the awaitable rejects with
|
None
|
untrack
¶
untrack(fn: Callable[[], T]) -> T
Run fn without tracking any reactive reads.
Use it to read a signal inside an effect without depending on it,
or to seed local state from a prop during component setup without
subscribing (the dev-mode top-level-read warning is silenced inside
untrack; Accessor.peek is the shorter
form for a single read).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[[], T]
|
Zero-arg callable to invoke with tracking suppressed. |
required |
Returns:
| Type | Description |
|---|---|
T
|
Whatever |
hydrate
¶
Adopt server-rendered HTML under container and make it interactive.
The counterpart of render for pages rendered by
wybthon.server. The tree mounts exactly as
render would mount it, except that each node claims the matching
node the server already put in the document instead of creating a
new one. Async values the server resolved come from the page's
data-wyb-state script, so they're neither fetched again nor shown
as loading. Input recorded by the production bootstrap before
hydration is replayed afterward.
Mismatches never break the page: a node that doesn't match is created in place, server nodes nobody claimed are removed, and dev mode logs a warning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vnode
|
Any
|
The same root view the server rendered. |
required |
container
|
Element | str | int
|
The element holding the server-rendered markup: an
|
required |
Returns:
| Type | Description |
|---|---|
Root
|
A |
render
¶
Render a tree into a container element.
Mounts vnode under container, commits every buffered DOM op in
one bridge crossing, and registers the container as an event
delegation root. Rendering into the same container again patches the
existing tree in place.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vnode
|
Any
|
The root VNode (or a component call, string, list, or reactive expression; anything a component may return). |
required |
container
|
Element | str | int
|
An |
required |
Returns:
| Type | Description |
|---|---|
Root
|
A |
get_request_event
¶
get_request_event() -> RequestEvent | None
Return the request being server-rendered, or None in the browser.
http_header
¶
Declare a response header while the calling scope is alive (server only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The header name (case-insensitive). |
required |
value
|
str
|
The header value. |
required |
append
|
bool
|
Add another value instead of replacing existing ones
(for |
False
|
http_status
¶
Declare the response status while the calling scope is alive (server only).
The most recent live declaration wins. When the declaring scope is disposed before the head is committed, its declaration is removed and the status falls back to the latest one still alive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
int
|
The HTTP status code. |
required |
text
|
str | None
|
An optional reason phrase. |
None
|
Fragment
¶
Group children without adding a wrapper element.
Fragments mount their children directly into the parent between two
empty comment markers, so they never pollute selectors like
:first-child or affect layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Children. Lists and tuples are flattened. |
()
|
Returns:
| Type | Description |
|---|---|
VNode
|
A |
h
¶
Create a VNode from a tag, props, and children.
The low-level constructor behind the helpers in
wybthon.html. Reactive expressions in child
positions are wrapped as holes when the parent mounts; components
receive their children verbatim through the children prop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tag
|
str | Callable[..., Any] | None
|
An HTML tag name, a special tag ( |
required |
props
|
PropsDict | None
|
Mapping of prop names to values. May be |
None
|
*children
|
Any
|
Children to attach. Lists and tuples are flattened. |
()
|
Returns:
| Type | Description |
|---|---|
VNode
|
A new |
hole
¶
Create a reactive hole explicitly, optionally with a key.
Reactive expressions in child positions become holes automatically;
reach for hole() when you need a stable key for keyed
reconciliation inside a fragment, or to make a hole visually
explicit.
The expression may return a VNode, a string, a list of either, or
None.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
getter
|
Callable[[], Any]
|
Zero-arg reactive expression evaluated inside its own render effect. |
required |
key
|
str | int | None
|
Optional stable identity for keyed reconciliation. |
None
|
Returns:
| Type | Description |
|---|---|
VNode
|
A |
create_optimistic_store
¶
Layer optimistic draft edits over a reactive authoritative source.
Active edits replay in submission order when the source changes. They are removed when their submitting action settles; other actions keep their edits. Draft callbacks must be deterministic: replay mustn't perform network or other side effects.
create_projection
¶
Create a read-only derived store with memo readiness and refresh semantics.
create_store
¶
create_store(initial: list[T], seed: None = None) -> tuple[StoreList[T], StoreSetter[DraftList[T]]]
create_store(initial: S, seed: None = None) -> tuple[Store[S], StoreSetter[Draft[S]]]
create_store(initial: Any, seed: Any = None) -> tuple[Any, StoreSetter]
Create a reactive mapping or sequence and its atomic draft setter.
A deriving function may return data or mutate its draft, synchronously or asynchronously. Its reads are tracked and its writes are staged together.
deep
¶
Return a detached snapshot, tracking changes only within this subtree.
reconcile
¶
Prepare replacement data, preserving matched list entity identities.
key names the field that identifies list entities ("id" by
default), or is a function computing the identity from an entity.
key=None replaces list entities positionally. Duplicate keys are
matched in occurrence order, without assigning the same entity to
multiple rows.
Public API by area¶
Everything below is importable with from wybthon import .... Module
pages linked in the left column carry the details.
| Area | Names |
|---|---|
| Components | component, Component, Props, ParentProps, Prop, prop, merge, omit, children, ChildrenAccessor |
| VDOM | VNode, h, hole, Fragment, element, is_accessor |
| Reactivity | Accessor, Setter, Signal, Memo, Owner, create_signal, create_memo, create_effect, create_tracked_effect, create_render_effect, create_reaction, create_root, create_owner, is_disposed, create_unique_id, flush, on_settled, on_cleanup, untrack, get_owner, get_observer, run_with_owner, map_array, repeat, WriteInScopeError |
| Async | NotReadyError, ServerError, is_pending, latest, refresh, resolve, action, Action, affects, until, create_optimistic |
| Stores | Store, StoreList, StoreSetter, Draft, DraftList, DraftExpiredError, create_store, create_projection, create_optimistic_store, reconcile, snapshot, deep |
| Flow control | Show, For, Repeat, Switch, Match, dynamic, client_only |
| Boundaries | Loading, Reveal, Errored, Portal, lazy |
| Context | Context, ContextNotFoundError, create_context, use_context |
| DOM and events | Element, Ref, DomEvent, EventHandler, event |
| Rendering | render, hydrate, Root, is_server, is_hydrating, NoHydration, Hydration |
| Server requests | RequestEvent, ResponseHead, get_request_event, http_status, http_header |
| Dev mode | is_dev_mode, set_dev_mode |
| HTML helpers | One helper per HTML element (div, p, button, input_, ...), plus element |
Other modules are imported by name and aren't re-exported:
| Module | Contents |
|---|---|
wybthon.router |
Router, Route, RouteProps, Outlet, Link, navigate, current_path, use_params, use_query, use_hash, use_base_path, preload, QueryParams, resolve, RouteSpec |
wybthon.forms |
form_state, FormState, Field, the bind_* helpers, validators, and ARIA helpers |
wybthon.server |
render_to_string, render_to_stream, RenderStream |
wybthon.testing |
render, Screen, fire, cleanup, and the in-memory DOM |
wybthon.svg |
SVG element helpers |
wybthon.virtual, wybthon.scheduling |
Virtual lists and cooperative scheduling |
wybthon.reactivity |
Everything above plus Computation and Transition |
from wybthon import Prop, Props, button, component, create_signal, div, p, prop, render
class CounterProps(Props):
initial: Prop[int] = prop(default=0)
@component
def Counter(props: CounterProps):
count, set_count = create_signal(props.initial.peek())
return div(
p(t"Count: {count}"),
button("+1", on_click=lambda: set_count(lambda n: n + 1)),
)
root = render(Counter(initial=5), "#app")
# later: root.dispose()
Browser versus CPython
Reactivity (including async memos, actions, and flush), stores,
forms, context, flow control, and VDOM construction (VNode, h,
Fragment, the HTML helpers) all run in plain CPython, which is how
the unit tests work. Touching a real DOM (render into a page,
Element queries, navigate with history) needs Pyodide, or the
in-memory DOM of wybthon.testing.