Skip to main content

No project description provided

Project description

Schorle

logo

Schorle (pronounced as ˈʃɔʁlə) is a server-driven UI kit for Python with async support.


Latest Python Release We use black for formatting


Note: This project is in an early stage of development. It is not ready for production use.

Installation

pip install schorle

Usage

Take a look at the examples directory.

Concepts

Elements

Elements are the building blocks of a UI. The entrypoint to build a UI is the Page class.

from schorle.elements.page import Page


class MyPage(Page):
    pass

Elements can be nested.

from schorle.elements.button import Button
from schorle.elements.html import Div, Paragraph
from schorle.elements.page import Page
from schorle.reactives.text import Text


class Container(Div):
    p1: Paragraph = Paragraph(text=Text("Hello"))
    p2: Paragraph = Paragraph(text=Text("World"))


class MyPage(Page):
    button: Button = Button.factory(text=Text("Click me!"))
    container: Container = Container.factory()

There can also be dynamic elements:

from schorle.elements.base.element import Reactive
from schorle.elements.button import Button
from schorle.elements.html import Div, Paragraph
from schorle.elements.page import Page
from schorle.reactives.text import Text
import random


class MyPage(Page):
    button: Button = Button.factory(text=Text("Click me!"))
    reactive_element: Reactive = Reactive.inline()

    def __init__(self, **data):
        super().__init__(**data)
        self.button.add_callback("click", self.on_click)

    async def on_click(self):
        if random.random() > 0.5:
            self.dynamic.update(Paragraph(text=Text("Clicked!")))
        else:
            await self.dynamic.update(Div(text=Text("Not clicked!")))

As well as dynamic collections:

from schorle.elements.button import Button
from schorle.elements.html import Div
from schorle.elements.page import Page
from schorle.reactives.text import Text
from schorle.elements.base.element import Collection
import random


class MyPage(Page):
    button: Button = Button.factory(text=Text("Click me!"))
    paragraphs: Collection[Div] = Collection.factory()

    def __init__(self, **data):
        super().__init__(**data)
        self.button.add_callback("click", self.on_click)

    async def on_click(self):
        if random.random() > 0.5:
            new_paragraphs = [Div(text=Text("Clicked!"))]
        else:
            new_paragraphs = []
        await self.paragraphs.update(new_paragraphs)

Dynamic collections and elements can also be nested.

Reacting to client-side events

To call something in response to a client-side event, use either @reactive or add_callback.

  • React to a client-side event with @reactive:
from schorle.elements.button import Button
from schorle.utils import reactive


class MyButton(Button):
    @reactive("click")
    async def on_click(self):
        await self.text.update("Clicked!")
  • React to a client-side event with add_callback:
from schorle.elements.button import Button
from schorle.elements.html import Paragraph
from schorle.elements.page import Page
from schorle.reactives.text import Text


class MyPage(Page):
    button: Button = Button.factory(text=Text("Click me!"))
    p: Paragraph = Paragraph(text=Text("Not clicked!"))

    def __init__(self, **data):
        super().__init__(**data)
        self.button.add_callback("click", self.on_click)

    async def on_click(self):
        await self.p.text.update("Clicked!")

Server-side effects

To call some updates from the server-side, use @effector decorator in combination with subscribe method:

from __future__ import annotations

from schorle.app import Schorle
from schorle.effector import effector
from schorle.elements.button import Button
from schorle.elements.page import Page
from schorle.reactives.classes import Classes
from schorle.reactives.state import ReactiveModel
from schorle.reactives.text import Text
from schorle.utils import reactive

app = Schorle()


class Counter(ReactiveModel):
    value: int = 0

    @effector  # effector transforms a method into an effect generating function
    async def increment(self):
        self.value += 1


class ButtonWithCounter(Button):
    text: Text = Text("Click me!")
    counter: Counter = Counter.factory()

    @reactive("click")
    async def handle(self):
        await self.counter.increment()

    async def _on_increment(self, counter: Counter):
        await self.text.update(f"Clicked {counter.value} times")
        await self.classes.toggle("btn-success")

    async def before_render(self):
        await self.counter.increment.subscribe(self._on_increment)  # subscribe to the effect


class PageWithButton(Page):
    classes: Classes = Classes("flex flex-col justify-center items-center h-screen w-screen")
    first_button: ButtonWithCounter = ButtonWithCounter.factory()
    second_button: ButtonWithCounter = ButtonWithCounter.factory()


@app.get("/")
def get_page():
    return PageWithButton()

Running the application

Schorle application is a thin wrapper around FastAPI. To run the application, use uvicorn:

uvicorn examples.simple:app --reload

Tech stack

Project details


Download files

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

Source Distribution

schorle-0.0.2.tar.gz (138.7 kB view details)

Uploaded Source

Built Distribution

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

schorle-0.0.2-py3-none-any.whl (24.4 kB view details)

Uploaded Python 3

File details

Details for the file schorle-0.0.2.tar.gz.

File metadata

  • Download URL: schorle-0.0.2.tar.gz
  • Upload date:
  • Size: 138.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for schorle-0.0.2.tar.gz
Algorithm Hash digest
SHA256 51a0fd9f127260de12c39e850d8011663627fb10afb5732933d906e4c5fdbe70
MD5 e1a1861304e05dd1085ee5ae7c561be4
BLAKE2b-256 345c20ecf528104d1ca3086aac9b0997774993fe4010f9b012a91b576a02f54f

See more details on using hashes here.

File details

Details for the file schorle-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: schorle-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 24.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for schorle-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 041484429cbdd2e9beda08426628e8cd67bd399643c5d5368904e282bae4a040
MD5 3c8dc00f526591c7ebb009a23b3684be
BLAKE2b-256 f442b3bf309552fdb5ba59c654a21c26a7c0b1390166b1f17331a61d9b9e071b

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