Builders Module
The builders package provides typed APIs for constructing TreeStore hierarchies.
Module Structure
graph TB
subgraph "genro_treestore.builders"
BASE[base.py<br/>BuilderBase]
DEC[decorators.py<br/>@element]
HTML[html.py<br/>HtmlBuilder]
subgraph "xsd/"
XSD[XsdBuilder]
end
BASE --> HTML
BASE --> XSD
DEC --> BASE
end
BuilderBase
- class genro_treestore.BuilderBase[source]
Bases:
ABCAbstract base class for TreeStore builders.
A builder provides domain-specific methods for creating nodes in a TreeStore. There are two ways to define elements:
- Using _schema dict for external/dynamic definitions:
- class HtmlBuilder(BuilderBase):
- _schema = {
‘div’: {‘children’: ‘=flow’}, ‘br’: {‘leaf’: True}, ‘td’: {
‘children’: ‘=flow’, ‘attrs’: {
‘colspan’: {‘type’: ‘int’, ‘min’: 1, ‘default’: 1}, ‘rowspan’: {‘type’: ‘int’, ‘min’: 0, ‘default’: 1}, ‘scope’: {‘type’: ‘enum’, ‘values’: [‘row’, ‘col’]},
}
},
}
- Schema keys:
children: str or set of allowed child tags (supports =ref)
leaf: True if element has no children (value=’’)
- attrs: dict of attribute specs for validation
type: ‘int’, ‘string’, ‘uri’, ‘bool’, ‘enum’, ‘idrefs’
required: True/False (default: False)
min/max: numeric constraints for int type
default: default value
values: list of valid values for enum type
The lookup order is: decorated methods first, then _schema. Attribute validation is performed with pure Python (no dependencies).
- Usage:
>>> store = TreeStore(builder=MyBuilder()) >>> store.fridge() # calls appliance() with tag='fridge'
- classmethod __init_subclass__(**kwargs)[source]
Build the _element_tags dict from @element decorated methods.
- child(target, tag, label=None, value=None, _position=None, _builder=None, **attr)[source]
Create a child node in the target TreeStore.
- Parameters:
target (
TreeStore) – The TreeStore to add the child to.tag (
str) – The node’s type (stored in node.tag).label (
str|None(default:None)) – Explicit label. If None, auto-generated as tag_N.value (
Any(default:None)) – If provided, creates a leaf node; otherwise creates a branch._position (
str|None(default:None)) – Position specifier (see TreeStore.set_item for syntax)._builder (
BuilderBase|None(default:None)) – Override builder for this branch and its descendants. If None, inherits from target.**attr (
Any) – Node attributes.
- Return type:
- Returns:
TreeStore if branch (for adding children), TreeStoreNode if leaf.
Example
>>> builder.child(store, 'div', id='main') >>> builder.child(store, 'meta', value='', charset='utf-8') # void >>> builder.child(store, 'svg', _builder=SvgBuilder())
Decorators
@element
- genro_treestore.element(tags='', children='', validate=True)[source]
Decorator to define element tags and validation rules for a builder method.
The decorator registers the method as handler for the specified tags. If no tags are specified, the method name is used as the tag.
Attribute validation is automatically extracted from function signature type hints when validate=True (default).
- Parameters:
tags (
str|tuple[str,...] (default:'')) – Tag names this method handles. Can be: - A comma-separated string: ‘fridge, oven, sink’ - A tuple of strings: (‘fridge’, ‘oven’, ‘sink’) If empty, the method name is used as the single tag.children (
str|tuple[str,...] (default:'')) –Valid child tag specs for structure validation. Can be: - A comma-separated string: ‘tag1, tag2[:1], tag3[1:]’ - A tuple of strings: (‘tag1’, ‘tag2[:1]’, ‘tag3[1:]’)
Each spec can be: - ‘tag’ - allowed, no cardinality constraint (0..∞) - ‘tag[n]’ - exactly n required - ‘tag[n:]’ - at least n required - ‘tag[:m]’ - at most m allowed - ‘tag[n:m]’ - between n and m (inclusive) Empty string or empty tuple means no children allowed (leaf node).
validate (
bool(default:True)) – If True (default), extract attribute validation rules from function signature type hints. Set to False to disable validation.
- Return type:
Example
>>> class MyBuilder(BuilderBase): ... # Multiple tags pointing to same method ... @element(tags='fridge, oven, sink') ... def appliance(self, target, tag, **attr): ... return self.child(target, tag, value='', **attr) ... ... # Structure validation with children ... @element(children='section, item[1:]') ... def menu(self, target, tag, **attr): ... return self.child(target, tag, **attr) ... ... @element() # No children allowed (leaf) ... def item(self, target, tag, **attr): ... return self.child(target, tag, value='', **attr) ... ... # Attribute validation from signature type hints ... @element() ... def td(self, target, tag, colspan: int = 1, ... scope: Literal['row', 'col'] | None = None, **attr): ... return self.child(target, tag, colspan=colspan, scope=scope, **attr)
Note
The element decorator handles both tag registration and children validation via the children parameter.
HtmlBuilder
- class genro_treestore.HtmlBuilder[source]
Bases:
BuilderBaseBuilder for HTML5 elements.
Provides dynamic methods for all 112 HTML5 tags via __getattr__. Void elements (meta, br, img, etc.) automatically use empty string value.
The schema is loaded from a pre-compiled MessagePack file generated from W3C Validator RELAX NG schema files.
- Usage:
>>> store = TreeStore(builder=HtmlBuilder()) >>> store.div(id='main').p(value='Hello') >>> store.ul().li(value='Item 1')
- VOID_ELEMENTS
Set of void (self-closing) element names.
- ALL_TAGS
Set of all valid HTML5 element names.
- __getattr__(name)[source]
Dynamic method for any HTML tag.
- Parameters:
name (
str) – Tag name (e.g., ‘div’, ‘span’, ‘meta’)- Return type:
- Returns:
Callable that creates a child with that tag.
- Raises:
AttributeError – If name is not a valid HTML tag.
HTML5 Content Model
graph TB
subgraph "Content Categories"
FLOW[Flow Content<br/>div, p, section...]
PHRASING[Phrasing Content<br/>span, a, em...]
EMBEDDED[Embedded Content<br/>img, video, iframe...]
INTERACTIVE[Interactive Content<br/>a, button, input...]
METADATA[Metadata Content<br/>head, title, meta...]
end
FLOW --> PHRASING
FLOW --> EMBEDDED
FLOW --> INTERACTIVE
XsdBuilder
Dynamic builder from XML Schema (XSD) files.
- class genro_treestore.XsdBuilder[source]
Bases:
BuilderBaseBuilder dynamically generated from XSD schema.
Creates methods for all elements defined in an XSD schema. Pass the schema TreeStore (from TreeStore.from_xml()) to __init__.
Example
>>> xsd = open('fatturapa.xsd').read() >>> schema = TreeStore.from_xml(xsd) >>> builder = XsdBuilder(schema) >>> >>> fattura = TreeStore(builder=builder) >>> fattura.FatturaElettronica(versione='FPR12')
- Parameters:
schema_store (
TreeStore)
- __init__(schema_store)[source]
Initialize builder from XSD schema TreeStore.
- Parameters:
schema_store (
TreeStore) – TreeStore from TreeStore.from_xml(xsd_string).
Example
from genro_treestore import TreeStore
from genro_treestore.builders import XsdBuilder
# Load XSD schema
xsd_content = open('invoice.xsd').read()
schema = TreeStore.from_xml(xsd_content)
builder = XsdBuilder(schema)
# Build validated structure
store = TreeStore(builder=builder)
invoice = store.Invoice()
invoice.Header().Date(value='2025-01-01')
Builder Architecture
classDiagram
class BuilderBase {
<<abstract>>
+_schema: dict
+child(tag, **attr)
+__getattr__(name)
}
class HtmlBuilder {
+div(**attr)
+span(**attr)
+p(**attr)
...
}
class XsdBuilder {
+__init__(schema)
}
BuilderBase <|-- HtmlBuilder
BuilderBase <|-- XsdBuilder
Validation Flow
flowchart TD
ADD[Add child node]
CHK{Valid child?}
CARD{Cardinality OK?}
OK[Node added]
ERR[InvalidChildError]
CERR[TooManyChildrenError]
ADD --> CHK
CHK -->|Yes| CARD
CHK -->|No| ERR
CARD -->|Yes| OK
CARD -->|No| CERR
Cardinality Syntax
Syntax |
Meaning |
Example |
|---|---|---|
|
Zero or more |
|
|
Zero or more |
|
|
Exactly one |
|
|
Zero or one |
|
|
One or more |
|
|
Range |
|
See Also
Builders Guide - Creating custom builders
Validation Guide - Validation rules