Code Monkey home page Code Monkey logo

puepy's Introduction

PuePy — PyScript Frontend Framework

➡️ https://puepy.dev

PuePy is an attempt to create a frontend framework using PyScript. PuePy is partially inspired by Vue. It runs entirely in your browser, though server-side rendering is likely feasible. PuePy aims to support two runtime environments: PyScript Pyodide or PyScript Micropython. The Micropython option foregoes some features found in the CPython, but offers a far, far smaller runtime, making it a better option for websites. Line-of-business or scientific webapp developers may prefer the CPython version, which is heavier but more functional.

😎 To see an example of a demo built with PuePy, see ExpenseLemur.com and the Expense Lemur Github Rep.

Here's an example:

from puepy import Page, Application, t

app = Application()


@app.page()
class Hello(Page):
    def initial(self):
        return dict(name="")

    def populate(self):
        with t.div(classes=["container", "mx-auto", "p-4"]):
            t.h1("Welcome to PyScript", classes=["text-xl", "pb-4"])
            if self.state["name"]:
                t.p(f"Why hello there, {self.state['name']}")
            else:
                t.p("Why don't you tell me your name?")
            t.input(placeholder="Enter your name", bind="name")
            t.button("Continue", classes="btn btn-lg", on_click=self.on_button_click)

    def on_button_click(self, event):
        print("Button clicked")  # This logs to console


app.mount("#app")

A few things to note:

  • The .state dictionary, which is populated by initial(), is reactive. As it changes, populate is called as necessary and the page is redrawn.
  • Events are simply and Python, but use JavaScript events under the hood (including custom events)
  • You layout your page with context managers.

Components, Props, Slots

You can define reusable components with PuePy, which also use slots (similar to Vue, Web Components, etc). Here's a simple Card component:

from puepy import Component, Prop, t

# This registers the component
@t.component()
class Card(Component):
    default_role = "card"
    props = ["help_text", Prop("show_buttons", "whether to show buttons", bool, False)]

    def populate(self):
        with t.div(classes="card-header"):
            self.insert_slot("card-header")
        with t.div(classes="card-body"):
            self.insert_slot()
            if self.show_buttons:
                with t.div(classes="card-footer"):
                    t.button("Button 1")
                    t.button("Button 2")

Using the component is simple:

@app.page("/my-page")
class MyPage(Page):
    def populate(self):
        with t.card(show_buttons=True) as card:
            with card.slot("card-header"):
                t("Show header here")
            with card.slot():
                t("This is the card body")

Where to go from here...

A few things to note:

  • PuePy is not fully documented yet
  • I haven't figured out exactly what is permanent and what isn't
  • You can examine, in git, the /examples directory and view them with python3 ./serve_examples.py

puepy's People

Contributors

kkinder avatar

Stargazers

Barend Burger avatar  avatar Brian Hammond avatar Jaroslav Němec avatar  avatar Brandon Townes avatar Michaël de Vries avatar  avatar  avatar Lars Briem avatar Jagannath A avatar Nils Billerbeck avatar Dave Proffer avatar akae avatar jgp avatar Felix Guerrero avatar hubo avatar George Psarakis avatar Dennis avatar  avatar vvanglro avatar so1n avatar Jon Grace-Cox avatar Ben Falk avatar  avatar Troy McConaghy avatar 正心 avatar  avatar allen.hu avatar  avatar William avatar Tom Daley avatar Vinod Ronold avatar Leo Neto avatar Joe Stanley avatar  avatar Martin Bärwolff avatar  avatar Ferenc Fejes avatar Anton Wemmenborn avatar Ahmed Lemine avatar João Palmeiro avatar Joseph Muller avatar  avatar Kishan K avatar pypeaday avatar Oussama EL GHANNAMI avatar Emanuel Angelo avatar Lasse Guzek avatar  avatar Carlos Guzman avatar  avatar Kamil Mielczarek avatar Adam Twardoch avatar Andy Shapiro avatar Sam Edwardes avatar Fabien Bourgeois avatar Michael H avatar James Harrison avatar Luke Trevorrow avatar Ralph Willgoss avatar  avatar  avatar  avatar Stefan Lehmann avatar wygud avatar Joe Stone avatar John Qing avatar Simon Wu avatar Jessica Smith avatar provefar avatar Maciej Budzyński avatar Sergio Sánchez Ramírez avatar Adrian Salceanu avatar blurhead avatar Colin Bieberstein avatar Javier Llopis avatar Maxwell Morais avatar Bjarte Johansen avatar Macaulay  avatar Lang avatar Maic Siemering avatar Latin avatar Resheku avatar  avatar Marc Guirand avatar  avatar Filipp Frizzy avatar Praveen Kulkarni avatar OtwakO avatar Onur ULUSOY avatar Rinaldo Moreira Magalhães avatar Vincent avatar A.s. avatar Jugurtha-Green avatar Ryuta Suzuki avatar GitMarco27 avatar Farhood avatar Antonio Porcelli avatar Pavel Klammert avatar

Watchers

Kishan K avatar Lars Briem avatar  avatar Björn Schrammel avatar  avatar Jaroslav Němec avatar

puepy's Issues

Firefox - DOMException: The operation is insecure.

when testing https://pyscript.com/@kkinder/puepy-tutorial/latest with Firefox / Ubuntu 24.04 i got:

DOMException: The operation is insecure.
    lookup_attr micropython.mjs:1
    invoke_iii micropython.mjs:1
    invoke_iiiii micropython.mjs:1
    invoke_ii micropython.mjs:1
    createExportWrapper micropython.mjs:1
    ccall micropython.mjs:1
    runPython micropython.mjs:1
    Lt _python.js:29
    ht/e[t]< utils.js:66
    xn/e[i]< hooks.js:65
    run utils.js:53
    onReady core.js:220
_io.js:40:21

Bug: Button event ordering re-arranges

Consider this example:

from puepy import Application, Page, t

app = Application()


@app.page()
class HelloWorldPage(Page):
    def initial(self):
        return {"messages": []}

    def populate(self):
        t.h1("Test...")
        for msg in self.state["messages"]:
            t.p(msg)

        t.sl_button("Click 1!", on_click=self.on_click_1)
        t.sl_button("Click 2!", on_click=self.on_click_2)
        t.sl_button("Click 3!", on_click=self.on_click_3)

    def on_click_1(self, event):
        with self.state.mutate("messages"):
            self.state["messages"].append("You clicked button 1!")

    def on_click_2(self, event):
        with self.state.mutate("messages"):
            self.state["messages"].append("You clicked button 2!")

    def on_click_3(self, event):
        with self.state.mutate("messages"):
            self.state["messages"].append("You clicked button 3!")


app.mount("#app")

The first time you click on button 1, it shows the correct message. The next time, it thinks it's button 2. The next, button 3. Then it's always button3:

CleanShot.2024-06-22.at.17.55.08.mp4

This only happens with Shoelace elements.

Trying to add beautiful soup as per tutorial fails in error

The tutorial https://docs.puepy.dev/pypi-libraries.html#pypi-libraries-when-using-cpython-pyodide gives this error:

Traceback (most recent call last):
  File "/lib/python312.zip/_pyodide/_base.py", line 502, in eval_code
    .run(globals, locals)
     ^^^^^^^^^^^^^^^^^^^^
  File "/lib/python312.zip/_pyodide/_base.py", line 340, in run
    coroutine = eval(self.code, globals, locals)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<exec>", line 2, in <module>
ModuleNotFoundError: No module named 'bs4'
The module 'beautifulsoup4' is included in the Pyodide distribution, but it is not installed.
You can install it by calling:
  await micropip.install("beautifulsoup4") in Python, or
  await pyodide.loadPackage("beautifulsoup4") in JavaScript
See https://pyodide.org/en/stable/usage/loading-packages.html for more details.

pyscript.json:

{
  "name": "PuePy Tutorial",
  "debug": true,
  "packages": [
    "./puepy-0.3.3-py3-none-any.whl",
    "beautifulsoup4"
  ],
  "js_modules": {
    "main": {
      "https://cdn.jsdelivr.net/npm/[email protected]/+esm": "morphdom"
    }
  }
}

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>PuePy Hello, World</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- Load PyScript from CDN -->
    <link rel="stylesheet" href="https://pyscript.net/releases/2024.6.2/core.css">
    <script type="module" src="https://pyscript.net/releases/2024.6.2/core.js"></script>
</head>
<body>
    <!-- Where application is mounted -->
    <div id="app"></div>

    <!-- PyScript Config -->
    <script type="py" src="./hello.py" config="./pyscript.json"></script>
</body>
</html>

Improce docs on app state

This project looks awesome, I'm excited to try it out on a few projects we're working on.

One question I had though after reading through the docs. A common pattern we use in our web apps is a single state store, and then multiple components can read/write to the state store, with components being updated reactively. In JS, we use mobx, though there other other libraries that accomplish something similar.

Is this pattern possible with puepy? It's seems better than passing state up/down the component tree. I didn't see any examples that explored this concept, though maybe I was missing it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.