https://github.com/percevalw/pret
Pret is a library for building full-stack reactive user interfaces in Python, using React as a rendering engine.
https://github.com/percevalw/pret
application jupyter python react ui web widget
Last synced: about 2 months ago
JSON representation
Pret is a library for building full-stack reactive user interfaces in Python, using React as a rendering engine.
- Host: GitHub
- URL: https://github.com/percevalw/pret
- Owner: percevalw
- License: apache-2.0
- Created: 2023-05-15T20:47:49.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2025-06-23T00:31:01.000Z (about 1 year ago)
- Last Synced: 2025-06-23T00:33:48.618Z (about 1 year ago)
- Topics: application, jupyter, python, react, ui, web, widget
- Language: Python
- Homepage: https://percevalw.github.io/pret/
- Size: 6.53 MB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: changelog.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README

[](https://percevalw.github.io/pret/latest/)
[](https://pypi.org/project/pret/)
[](https://labextensions.dev/extensions/pret)
[](https://mybinder.org/v2/gh/percevalw/pret/main?urlpath=%2Fdoc%2Ftree%2Fexamples%2FTodos.ipynb)
# PRET
Pret is a library for building full-stack reactive user interfaces in Python, using React as a rendering engine.
## Installation
```bash
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):
```bash
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:
```python { .render-with-pret }
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,
},
sync=True,
)
@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
```python { .no-exec }
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
```python
if __name__ == "__main__":
run(TodoApp)
```
Then, run the following command, and voilà !
```bash
python app.py
```