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.builders 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.builders 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
  • Built-in builders — HTML5, Markdown, XSD (schema-driven XML)
  • 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.builders 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.10.2.tar.gz (186.1 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.10.2-py3-none-any.whl (81.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for genro_builders-0.10.2.tar.gz
Algorithm Hash digest
SHA256 7d37342e388b95dbe4e4ac34c1c232e7856e80b281365dfa5654e88060c30bfd
MD5 730325619e63834a8c3287dd3be2f28b
BLAKE2b-256 54b711a59dc4a64a352732845c51d216eda7ad5db3e4a32acc264aa277b8b096

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_builders-0.10.2.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.10.2-py3-none-any.whl.

File metadata

File hashes

Hashes for genro_builders-0.10.2-py3-none-any.whl
Algorithm Hash digest
SHA256 195ec1d9b04a22cc88f6f22b1ff52ed270a662b94a4631e8ab5debb9387fca44
MD5 0f1fac51a264adc41a3f9825890efd43
BLAKE2b-256 47b2322d07b8fbe3c16186b1389b8b72c64f75c10e021cda0a69e3226f6c1043

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_builders-0.10.2-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