Skip to main content

Builder system for genro-bag - grammar, validation, compilation

Project description

genro-builders

Builder system for genro-bag — grammar, validation, reactive data binding, and computed data infrastructure.

Installation

pip install genro-builders

Quick start

from genro_builders.contrib.html import HtmlBuilder

builder = HtmlBuilder()
body = builder.source.body()
body.div(id='main').p('Hello, world!')

builder.build()
print(builder.render())

The manager pattern — store() and main()

A builder is a machine. To define what to build, use a BuilderManager:

from genro_builders.contrib.html import HtmlBuilder
from genro_builders.manager import BuilderManager

class HtmlManager(BuilderManager):
    def __init__(self):
        self.page = self.set_builder('page', HtmlBuilder)

    def render(self):
        return self.page.render()

class MyPage(HtmlManager):
    def __init__(self):
        super().__init__()
        self.setup()       # store -> main
        self.build()       # source -> built

    def store(self, data):
        data['title'] = 'Hello, world!'

    def main(self, source):
        body = source.body()
        body.h1(value='^title')
        self.footer(source)

    def footer(self, source):
        source.footer().p('(c) 2026')

page = MyPage()
print(page.render())

Features

  • Domain-specific grammars — Define elements, validation rules, and components via decorators (@element, @abstract, @component)
  • Data infrastructure@data_element decorator for data_setter, data_formula, and data_controller — write, compute, and act on the reactive data store directly from the source Bag
  • Reactive formulasdata_formula with ^pointer dependencies re-executes automatically when sources change, in topological order (dependencies first, cycles detected)
  • Computed attributes — Callable attributes with ^pointer defaults are resolved just-in-time during render/compile
  • Debounce and periodic_delay for debounced formula re-execution, _interval for periodic polling
  • Output suspensionsuspend_output() / resume_output() to batch data changes and trigger a single render
  • Pointer formali — The built Bag retains ^pointer strings; resolution happens just-in-time during render/compile, not during build
  • Named slots — Components can declare insertion points (slots=['left', 'right']) for user content injection
  • Contributed builders — HTML5, Markdown, SVG, XSD in genro_builders.contrib (optional, not loaded unless imported)
  • Multi-builder coordinationBuilderManager coordinates multiple builders with a shared data store
  • Renderers and compilers@renderer for serialized output (HTML, Markdown), @compiler for live objects (widgets, workbooks)
  • Node identificationnode_id attribute for O(1) lookup via node_by_id()
  • Validationsub_tags cardinality, parent_tags constraints, typed attribute validation via Annotated

Architecture

A builder is a machine that materializes a source Bag into a built Bag. A BuilderManager mixin orchestrates population and lifecycle:

setup()           ->  build()              ->  subscribe()     ->  render() / compile()
store + main          two-pass walk:           activate            output
(populate)            1. data elements         reactivity
                      2. normal elements
  • setup() — on manager: calls store(data) then main(source)
  • build() — two-pass materialize:
    • Pass 1: process data elements (data_setter writes values, data_formula computes, data_controller executes side effects)
    • Pass 2: materialize normal elements and components into the built Bag, register ^pointer bindings
    • After both passes: topological sort of formulas, fire _onBuilt hooks
  • subscribe() — optional: activate reactive bindings. Data changes trigger formula re-execution and automatic re-render. Starts _interval timers.
  • render() — produce serialized output via BagRendererBase (just-in-time ^pointer resolution)
  • compile() — produce live objects via BagCompilerBase (just-in-time ^pointer resolution)

Data infrastructure

Data elements let you define computed and reactive data directly in the source Bag:

from genro_builders.contrib.html import HtmlBuilder

builder = HtmlBuilder()
s = builder.source

# Static data
s.data_setter('greeting', value='Hello')

# Computed data (re-executes when ^greeting changes)
s.data_formula('message', func=lambda greeting: f'{greeting}, World!',
               greeting='^greeting')

# Controller (side effect, no output path)
s.data_controller(func=lambda message: print(f'Message: {message}'),
                   message='^message')

# UI bound to computed data
s.body().h1(value='^message')

builder.build()
builder.subscribe()
print(builder.output)
# <body><h1>Hello, World!</h1></body>

# Change source data -> formula re-executes -> re-render
builder.data['greeting'] = 'Ciao'
print(builder.output)
# <body><h1>Ciao, World!</h1></body>

Debounce and periodic execution

# Re-execute at most once every 500ms (debounce)
s.data_formula('search_results', func=do_search,
               query='^search.query', _delay=0.5)

# Re-execute every 10 seconds (polling)
s.data_formula('clock', func=lambda: time.strftime('%H:%M:%S'),
               _interval=10.0)

Output suspension

builder.suspend_output()     # pause rendering
builder.data['a'] = 1
builder.data['b'] = 2
builder.data['c'] = 3        # no render triggered yet
builder.resume_output()       # single render with all 3 changes

Documentation

See the docs/ directory for full documentation:

License

Apache License 2.0 — Copyright 2025 Softwell S.r.l.

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

genro_builders-0.14.0.tar.gz (197.2 kB view details)

Uploaded Source

Built Distribution

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

genro_builders-0.14.0-py3-none-any.whl (109.5 kB view details)

Uploaded Python 3

File details

Details for the file genro_builders-0.14.0.tar.gz.

File metadata

  • Download URL: genro_builders-0.14.0.tar.gz
  • Upload date:
  • Size: 197.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for genro_builders-0.14.0.tar.gz
Algorithm Hash digest
SHA256 4032045a6eb7317c976c0cb84b86899f17af995daa828fb7f87eef9637330450
MD5 3d264e1bafe31e994590844fcaa636d1
BLAKE2b-256 d63a4645a9364f68cd35fb61200c5cb83c7aa06542b3c48b03ab225a200247ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_builders-0.14.0.tar.gz:

Publisher: publish.yml on genropy/genro-builders

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file genro_builders-0.14.0-py3-none-any.whl.

File metadata

  • Download URL: genro_builders-0.14.0-py3-none-any.whl
  • Upload date:
  • Size: 109.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for genro_builders-0.14.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c0e5228ab2a76079a567f573a9408cd15763e4b93da83a2f9baf807a038e2ff5
MD5 01324963b59d349df7f32ffc992e778c
BLAKE2b-256 227862aea5ea565ac68b5cef982037fa1981058062d889874325144a56a5eb0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_builders-0.14.0-py3-none-any.whl:

Publisher: publish.yml on genropy/genro-builders

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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