Skip to main content

Python framework to build reactive web apps with seamless server-client interaction

Project description

Tests Documentation PyPI Binder

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,
    },
    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
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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pret-0.5.1-py3-none-any.whl (9.4 MB view details)

Uploaded Python 3

File details

Details for the file pret-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: pret-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 9.4 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.9

File hashes

Hashes for pret-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e8a1cfc6547dc19588082204d115cdee5205d6ead99ab7e5c927b95e55720475
MD5 809cf763ed8b43f158ec1352fabf6d28
BLAKE2b-256 4817ff81564d8614bb2bca2474aad06c684a452f1ad68668ab39cc7218e560ca

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page