A lightweight, async-friendly library for building dynamic, context-aware UI blocks with Pydantic validation and variable substitution.
Project description
EBlock (Easy Block Builder)
A flexible, schema-driven library for building dynamic, context-aware content blocks with variable substitution, nested composition, validation, and asynchronous rendering.
Designed for use in page builders, CMS backends, or dynamic UI generation systems where content is defined as structured JSON, rendered with context variables, and validated via Pydantic models.
Installation
pip install eblock
or with uv:
uv add eblock
Core Concepts
Context
A container for variables and metadata used during block rendering.
- Variables are case-normalized to uppercase.
- Supports deep copying for safety.
- Allows dynamic assignment via
ctx["key"] = value. - Stores:
vars: dictionary of scalar or structured values (strings, numbers, lists, dicts, etc.)extra: arbitrary metadata (not used in substitution)
BaseBlock
Abstract base class for all content blocks.
Each block:
- Accepts
properties(dict) on initialization. - Optionally validates input/output using Pydantic models.
- Recursively resolves
{{ variable }}placeholders fromContext. - Supports nesting (blocks inside dicts, lists, etc.).
- Exposes a standardized async
build()method. - Allows custom output transformation via
prepare_output().
Features
✅ Variable substitution
Placeholders like {{ user_name }} are replaced with values from context.
✅ Recursive structure support
Handles dicts, lists, tuples, sets, and nested BaseBlock instances.
✅ Input/Output validation
Define _input_schema and _output_schema using Pydantic models.
✅ Computed fields
Override prepare_output() to add or transform fields after substitution but before output validation.
✅ Static dependency analysis
Use .get_vars() to extract all required variables from a block (including nested ones).
✅ Async-first design
Full async/await support for future extensibility (e.g., async data fetching in prepare_output).
✅ Structured logging
Each block and context instance logs actions with a unique hierarchical logger name.
Usage Examples
Basic Block
from easy_block_builder import BaseBlock, Context
class TextBlock(BaseBlock):
_type = "text"
ctx = Context(vars={"name": "Alice"})
block = TextBlock({"content": "Hello, {{ name }}!"})
result, _ = await block.build(ctx)
# result = {"content": "Hello, Alice!"}
Validated Block with Computed Output
from pydantic import BaseModel
from easy_block_builder import BaseBlock
class Input(BaseModel):
title: str
score: int
class Output(BaseModel):
title: str
score: int
badge: str
class ScoreCard(BaseBlock):
_type = "score_card"
_input_schema = Input
_output_schema = Output
async def prepare_output(self, result, ctx):
result["badge"] = "🏆" if result["score"] >= 90 else "📝"
return result
Nested Blocks
header = TextBlock({"text": "Welcome, {{ user }}!"})
page = PageBlock({"header": header, "theme": "{{ theme }}"})
# Both `user` and `theme` will be resolved from context
Variable Inspection
block = TextBlock({"msg": "Hi {{ first }}, {{ last }}!"})
print(block.get_vars()) # {"first", "last"}
API Reference
class Context
__init__(self, vars: dict | None = None, **extra)__getitem__(key),__setitem__(key, value)- Properties:
vars(deep copy),extra(shallow copy)
class BaseBlock
__init__(self, properties: dict)async build(self, ctx: Context) -> tuple[dict, Type[BaseModel] | None]async prepare_output(self, result: dict, ctx: Context) -> dict(override to customize)get_vars(self) -> set[str]- Properties:
type(read-only)
Class-level attributes (define in subclass)
_type: str— block identifier (e.g.,"image","form")_input_schema: Type[BaseModel] | None_output_schema: Type[BaseModel] | None
Requirements
- Python ≥ 3.10
- Pydantic ≥ 2.0
Notes
- All string placeholders must use double curly braces:
{{ var_name }}. - Whitespace inside placeholders is stripped:
{{ user_id }}→user_id. - If a variable is missing in context, it resolves to
Noneand logs a warning. - Blocks are not reusable across different
build()calls if they hold mutable state — design them as stateless.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file eblock-0.2.2.tar.gz.
File metadata
- Download URL: eblock-0.2.2.tar.gz
- Upload date:
- Size: 15.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4821a1eff0c57249d38a28e373c4328123b4c1c088ac7e6a0e857df557d5361e
|
|
| MD5 |
97b70ded9b77a3dafe92556f5bbc2f40
|
|
| BLAKE2b-256 |
5c6b8a138e7c24ba3f142e0d799f999db4206056bfe789f6549d4960022f99c6
|
Provenance
The following attestation bundles were made for eblock-0.2.2.tar.gz:
Publisher:
python-publish.yml on GAKiknadze/easy_block_builder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
eblock-0.2.2.tar.gz -
Subject digest:
4821a1eff0c57249d38a28e373c4328123b4c1c088ac7e6a0e857df557d5361e - Sigstore transparency entry: 748029534
- Sigstore integration time:
-
Permalink:
GAKiknadze/easy_block_builder@7f70fa2e1a73749a0b3371956ef2eec6c9fe24d2 -
Branch / Tag:
refs/tags/0.2.2 - Owner: https://github.com/GAKiknadze
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@7f70fa2e1a73749a0b3371956ef2eec6c9fe24d2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file eblock-0.2.2-py3-none-any.whl.
File metadata
- Download URL: eblock-0.2.2-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
288d18d71d6276cc3d214183f60b84879e5bfd5f38a6d2704b4f5ada47292756
|
|
| MD5 |
3299d037f229f93cab5860c3f29390d3
|
|
| BLAKE2b-256 |
d7efb111f0d6a0481cefe4f27faebebfb63fd314b8954398ecc9a6e60b159211
|
Provenance
The following attestation bundles were made for eblock-0.2.2-py3-none-any.whl:
Publisher:
python-publish.yml on GAKiknadze/easy_block_builder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
eblock-0.2.2-py3-none-any.whl -
Subject digest:
288d18d71d6276cc3d214183f60b84879e5bfd5f38a6d2704b4f5ada47292756 - Sigstore transparency entry: 748029536
- Sigstore integration time:
-
Permalink:
GAKiknadze/easy_block_builder@7f70fa2e1a73749a0b3371956ef2eec6c9fe24d2 -
Branch / Tag:
refs/tags/0.2.2 - Owner: https://github.com/GAKiknadze
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@7f70fa2e1a73749a0b3371956ef2eec6c9fe24d2 -
Trigger Event:
release
-
Statement type: