Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PUI: Declarative UI framework for Python

Buganini
December 09, 2023

PUI: Declarative UI framework for Python

SwiftUI/Jetpack Compose/Flutter have their languages and environments; how about Python? This framework can turn any imperative UI framework into declarative flavor in vanilla Python workflow, using standard Python syntax without resorting to the parentheses trick or yet another DSL with limited expression. With preliminary support to multiple long-existing frameworks, including "Tkinter", "PySide6", "Textual" in text mode, and the newly emerged Flutter-based "Flet," the PUI project also comes with generic UI expressions so that you can change the underlying framework without changing UI code. Based on the functional nature of declarative UI, hot-reload also becomes feasible.

Buganini

December 09, 2023
Tweet

Other Decks in Programming

Transcript

  1. About Me • Freel a ncer • Odds & Ends

    Developer • Web, Mobile App, FW, a bit HW • ❤ 🐍 🐍 🐍 (Python *3*) • Su ff er from UI progr a mming 🤡 https://github.com/buganini/PUI
  2. Declarative UI • Apple: SwiftUI • Android: Jetp a ck

    Compose • Web: Angul a r, Re a ct, Vue … https://github.com/buganini/PUI • Python: PUI 🎉 🎉 🎉
  3. Wishlist • Code structure == UI structure SwiftUI VBox {

    Text(“Item 1”) Text(“Item 2”) } Hierarchy by statements Hierarchy by code structure Traditional Python layout = VBoxLayout() layout.addChild(Text(“Item 1”)) layout.addChild(Text(“Item 2”)) root.addChild(layout) Hierarchy by statements
  4. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters
  5. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools
  6. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar
  7. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generator
  8. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators
  9. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger
  10. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDE Integration
  11. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration
  12. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness
  13. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability
  14. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve
  15. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve Language Maintenance
  16. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve Language Maintenance Traceability
  17. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve Language Maintenance Traceability Job Security
  18. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve Language Maintenance Traceability Job Security Fun
  19. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve Language Maintenance Traceability Job Security Fun for younger me 🤡
  20. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Parenthesis VBox( Text(“Item 1”), Text(“Item 1”) ) Control Flow Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve Language Maintenance Traceability Job Security Fun for younger me 🤡
  21. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters DSL <VBox> <Text if=“xxx”>Item 1</Text> <Text>Item 2</Text> </VBox> Parenthesis VBox( Text(“Item 1”), Text(“Item 1”) ) Control Flow Disturbing 😨 Another language Another ton of tools * Syntax & Grammar * Code Generators * Debugger * IDEs Integration Turing Completeness Interoperability Learning Curve Language Maintenance Traceability Job Security Fun for younger me 🤡
  22. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge Source: pix a b a y ×N ×N
  23. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge Source: pix a b a y
  24. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge • Not too much migr a tion p a in • Di ff erent b a ckends support & Interoper a bility Source: Wikipedi a - Hyperloop
  25. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge • Not too much migr a tion p a in • Di ff erent b a ckends support & Interoper a bility Source: 2023 Apr 23
  26. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge • Not too much migr a tion p a in • Di ff erent b a ckends support & Interoper a bility Source:
  27. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge • Not too much migr a tion p a in • Di ff erent b a ckends support & Interoper a bility • Even Better Developer Experience • Hot Relo a ding Source: Wikipedi a - Gl a dys Ingle REAL FUN
  28. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge • Not too much migr a tion p a in • Di ff erent b a ckends support & Interoper a bility • Even Better Developer Experience • Hot Relo a ding with just Python 🤔
  29. Syntax Challenge Traditional Python layout = VBoxLayout() layout.addChild(Label(“Item 1”)) layout.addChild(Label(“Item

    2”)) root.addChild(layout) Swift / Kotlin Style VBox { Label(“Item 1”) Label(“Item 2”) } VBox ({ Label(“Item 1”) Label(“Item 2”) }) Hierarchy by statements Hierarchy by code structure Not available in Python Tr a iling Closure
  30. Python Syntax Challenge Swift / Kotlin VBox { Label(“Item 1”)

    Label(“Item 2”) } • Construct hier a rchy with Python synt a x • 🚫 No multi-line l a mbd a in Python • How do children f ind their p a rent? 🤔
  31. Python Syntax Challenge with VBox(): Label(“Item 1”) Label(“Item 2”) parent

    = VBox() enter parent ➡ push stack Label(“Item 1”) # attach to parent Label(“Item 2”) # attach to parent exit parent ➡ pop stack Where to store the st a ck ? 🤔 Glob a l V a ri a ble? Thre a d-S a fety? ➡ Per-Thre a d Glob a l V a ri a ble Thre a d-Loc a l Stor a ge ✅ Context M a n a ger
  32. Hello World from PUI.PySide6 import * class Example(Application): def content(self):

    with Window(title="test", size=(320,240)): Label("Hello world") root = Example() root.run() 👆 👆
  33. One way to do declarative UI Virtual Document Object Model

    Virtu a l DOM B a ckend- a gnostic blueprint Actu a l UI (DOM in web world) with Tree(): Star() Ball(color=green) Ball(color=red)
  34. Virtual DOM Proper synt a x + D a t

    a Binding + Virtu a l DOM = Decl a r a tive wr a pper for imper a tive b a ckends Indirection
  35. Di ffi ng Virtual DOM diff( , ) with Tree():

    Star() Ball(color=green) Ball(color=red) with Tree(): Ball(color=green) Ball(color=blue)
  36. Different Backends Virtu a l DOM B a ckend- a

    gnostic blueprint B a ckend 1 B a ckend 2
  37. Data Binding state = StateDict() state[“var”] = “python” ## UI

    with VBox(): Label(state[“var”]) state[“var”] = “boa” ➡ Register listener for the view root in st a te getter Trigger view upd a te in st a te setter ⬅ class StateDict(BaseState): def __getitem__(self, key): try: view = find_puiview() self.__listeners.add(view) except PuiViewNotFoundError: pass return self.__values[key] def __setitem__(self, key, value): if not key in self.__values or self.__values[key] != value: self.__values[key] = value _notify(self.__listeners) PUI/st a te.py
  38. data = State() data.var = 0 def content(self): with Window(title="blah"):

    with VBox(): with HBox(): Button("-").click(self.on_minus) Label(f"{data.var}") Button("+").click(self.on_plus) with HBox(): for i in range(0, data.var): Label(f"{i}") def on_minus(self): data.var -= 1 def on_plus(self): data.var += 1 ex a mples/generic_minim a l.py Data Binding
  39. data = State() data.var = 0 def content(self): with Window(title="blah"):

    with VBox(): with HBox(): Button("-").click(self.on_minus) Label(f"{data.var}") Button("+").click(self.on_plus) with HBox(): for i in range(0, data.var): Label(f"{i}") def on_minus(self): data.var -= 1 def on_plus(self): data.var += 1 ex a mples/generic_minim a l.py Data Binding
  40. Another Python Syntax Challenge SwiftUI struct ContentView: View { @State

    private var name = "" var body: some View { VBox { Text(name) TextField("Name", text: $name) } } } $n a me ➡ Binding<String> PUI state = State() state.text = "" @PUI def TextFieldExample(): with VBox(): # getter Label(state.text) # binding TextField(state("text")) __c a ll__ cookbook/text f ield.py
  41. Hot Reload Virtu a l DOM B a ckend- a

    gnostic blueprint Actu a l UI (DOM in web world) with Tree(): Star() Ball(color=green) Ball(color=red)
  42. Update Triggers Virtu a l DOM B a ckend- a

    gnostic blueprint Actu a l UI (DOM in web world) • St a te Ch a nge • Source Code Ch a nge • Timer
  43. Update Triggers • St a te Ch a nge •

    Source Code Ch a nge • Timer @PUI def TimelineViewExample(): from datetime import datetime with TimelineView(ttl_sec=1): Label(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) cookbook/timeline.py
  44. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge • Not too much migr a tion p a in • Di ff erent b a ckends support & Interoper a bility • Even Better Developer Experience • Hot Relo a ding with just Python 🤔
  45. Wishlist • Code structure == UI structure • No more

    dom a in speci f ic l a ngu a ge / m a rkup l a ngu a ge / p a renthesis trick • Control Flow: If-Else, Loop, etc. • Turing completeness m a tters • Better Developer Experience • Popul a te content on d a t a ch a nge • Not too much migr a tion p a in • Di ff erent b a ckends support & Interoper a bility • Even Better Developer Experience • Hot Relo a ding with Python(): return True #😎
  46. Buganini Chiu (aka. Bug) email: [email protected] https://github.com/buganini/PUI PUI: Declarative UI

    Framework for Python 🤔 QA / Demo 🫣 https://0rz.tw/JJvsC Slides sciwork 2023