PRET
Pret is a library for building full-stack reactive user interfaces in Python, using React as a rendering engine.
Installation
pip install pret pret-joy
To use it with Jupyter, if you install the library in a custom environment (conda, venv, or other), you will likely need to tell Jupyter where to find the front-end files. You can do this by running the following command (only once):
pret update-jupyter-config --apply
Features
- Python, only Python: pret is written in Python: you can write your both your UI and server actions Python. No need to learn a new language.
- Client-side rendering: unlike other Python UI frameworks, pret runs primarily in the browser. This enables a fast response time to user actions (like hover events), and a better user experience under degraded network conditions.
- Built on React: pret uses React as a rendering engine, and benefits from its ecosystem.
- Reactive: unlike other solutions like ipywidgets, pret is reactive. Only the parts of the UI that need to be updated are re-rendered.
- State management: in addition to React's local state management (i.e.
use_state), pret provides a global and modular state management solution that is synchronized between components, between the browser and the server, and can even be persisted to a file for collaborative editing. - Modular: pret is designed to be modular. You can easily create your own components, and reuse them in other pret-based projects.
- Integrated with Jupyter: pret components can be used in Jupyter notebooks, as well as in standalone web applications.
- Remote execution: pret can call and use the result of Python functions on the server from the browser
Use it in a notebook
Let's write a simple todo app that should:
- display a list of todos, that can be checked as done
- display the number remaining todos
- change the font to bold as a todo is hovered
- allow editing the todo list directly in Python
Copy and paste the following code in a notebook:
from pret import component, create_store, run, use_state, use_store_snapshot
from pret_joy import Checkbox, Input, Stack, Typography
store = create_store(
{
"faire à manger": True,
"faire la vaisselle": False,
},
)
@component
def TodoApp():
todos = use_store_snapshot(store)
typed, set_typed = use_state("")
num_remaining = sum(not ok for ok in todos.values())
plural = "s" if num_remaining > 1 else ""
def on_key_down(event):
if event.key == "Enter":
store[typed] = False
set_typed("")
return Stack(
*(
Checkbox(
label=todo,
checked=ok,
on_change=lambda e, t=todo: store.update({t: e.target.checked}),
)
for todo, ok in todos.items()
),
Input(
value=typed,
on_change=lambda event: set_typed(event.target.value),
on_key_down=on_key_down,
placeholder="Add a todo",
),
Typography(
f"Number of unfinished todo{plural}: {num_remaining}",
sx={"minWidth": "230px"}, # just to avoid jittering when it's centered
),
spacing=2,
sx={"m": 1},
)
TodoApp()
In comparison, the closest alternative using ipywidgets looks like the following snippet:
IPyWidget's implementation
import ipywidgets as widgets
state = {
"faire à manger": True,
"faire la vaisselle": False,
}
class IPWTodoApp:
def __init__(self):
self.box = widgets.VBox()
self.render()
def _repr_mimebundle_(self, *args, **kwargs):
return self.box._repr_mimebundle_(*args, **kwargs)
def render(self, *args, **kwargs):
num_remaining = sum([not checked for _, checked in state.items()])
plural = "s" if num_remaining > 1 else ""
def on_input_submit(sender):
state[input_widget.value] = False
self.render()
def create_todo_item(todo, checked):
def update_todo_status(*args, **kwargs):
state[todo] = checkbox.value
self.render()
checkbox = widgets.Checkbox(
value=checked,
description=todo,
disabled=False,
indent=False,
)
checkbox.observe(update_todo_status, names="value")
return checkbox
input_widget = widgets.Text(
placeholder="Add a todo",
description="",
disabled=False,
)
input_widget.on_submit(on_input_submit)
self.box.children = [
*(create_todo_item(todo, checked) for todo, checked in state.items()),
input_widget,
widgets.Label(value=f"Number of unfinished todo{plural}: {num_remaining}"),
]
IPWTodoApp()
You also lose some features:
- the app stops working if the server shuts down
- hover events cannot be listened to
- no React dom diffing: the app must either be re-rendered entirely (as in the example), or you must determine specifically which field of which widget to update
Use it in a standalone app
You can also use pret to build standalone web applications. Copy the above code in a file
named app.py, and change the last line to
if __name__ == "__main__":
run(TodoApp)
Then, run the following command, and voilà !
python app.py
Metadata
Release files for pret 0.6.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pret-0.6.4-py3-none-any.whl | Python 3 | none | any | Details |
Release files / pret-0.6.4-py3-none-any.whl
| Download URL | pret-0.6.4-py3-none-any.whl |
|---|---|
| Size | 9.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
67305d8c581657b147c7202c691d1a68baf802a3e7af4327e42ecb18a0fe0535
|
|
BLAKE2b-256 checksum How to use checksums |
1c9fc56c726b25346ddefcdb07c8d619259f80c97422e385bb56189c33dbbb42
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 10, 2026.
Transparency log