Generate templated objects
Project description
embody
Structural Object Embodiment for Python - Transform skeletal templates into fully realized, type-safe objects through recursive hydration.
What is Embody?
Embody is a powerful library for templated object generation that goes beyond simple string formatting. It provides structural embodiment - the recursive hydration of nested data structures with type preservation, cycle detection, and intelligent traversal strategies.
Key Features
- 🎯 Type Preservation: Variables like
${count}preserve their types (int, bool, list, dict) instead of converting everything to strings - 🔄 Multiple Strategies: Choose between recursive visitor, compiled path, or iterative stack traversal
- 🎨 Multiple Syntaxes: Support for
${var},{var}, and[[var]]template syntaxes - 🛡️ Cycle Detection: Automatically detect and prevent circular references
- 📍 Path Addressing: Access nested data via JSON Pointer, dot notation, or tuple paths
- 🗺️ Mapping Interfaces: Uniform interfaces for attribute access, flattening, and path-based operations
- ⚡ Performance: Auto-selects optimal strategy based on template complexity
- 🔒 Type Safety: Full integration with Pydantic and other validation libraries
Installation
pip install embody
Quick Start
Basic Usage
from embody import embody
# Simple template embodiment
template = {
'name': '${name}',
'age': '${age}',
'greeting': 'Hello ${name}!'
}
result = embody(template, {'name': 'Alice', 'age': 30})
# {'name': 'Alice', 'age': 30, 'greeting': 'Hello Alice!'}
Type Preservation
Unlike traditional templating, embody preserves types:
template = {
'count': '${num}', # Will be int, not string!
'active': '${flag}', # Will be bool
'items': '${list}', # Will be list
'message': 'Count: ${num}' # Will be string (interpolation)
}
result = embody(template, {
'num': 42,
'flag': True,
'list': [1, 2, 3]
})
assert isinstance(result['count'], int) # True - type preserved!
assert isinstance(result['active'], bool) # True
assert isinstance(result['items'], list) # True
Nested Structures
Embody handles deep nesting naturally:
template = {
'user': {
'profile': {
'name': '${name}',
'settings': {
'theme': '${theme}',
'notifications': '${notify}'
}
}
}
}
result = embody(template, {
'name': 'Bob',
'theme': 'dark',
'notify': True
})
Advanced Features
Context with Resolvers
from embody import Context
import datetime
ctx = Context({
'now': lambda: datetime.datetime.now(),
'user': 'Alice'
})
# Callables are invoked on access
print(ctx['now']) # Current time
print(ctx['user']) # 'Alice'
Mapping Interfaces
from embody.mappings import AttributeMapping, PathMapping
# Attribute access (Box pattern)
attr_map = AttributeMapping({'user': {'name': 'Alice'}})
print(attr_map.user.name) # 'Alice'
# Path-based access
path_map = PathMapping({'a': {'b': {'c': 42}}})
print(path_map['a.b.c']) # Dot notation
print(path_map['/a/b/c']) # JSON Pointer
print(path_map[('a', 'b', 'c')]) # Tuple path
Path Addressing
from embody.paths import JSONPointer, resolve_path
data = {'users': [{'name': 'Alice'}, {'name': 'Bob'}]}
# JSON Pointer (RFC 6901)
ptr = JSONPointer('/users/0/name')
print(ptr.resolve(data)) # 'Alice'
# Convenience function
print(resolve_path(data, 'users.0.name')) # 'Alice'
Traversal Strategies
from embody import Embodier
template = {'data': '${value}'}
# Recursive visitor (default, best for one-off templates)
embodier1 = Embodier(template, strategy='recursive')
# Compiled path (best for repeated embodiment)
embodier2 = Embodier(template, strategy='compiled')
# Auto-select based on template complexity
embodier3 = Embodier(template, strategy='auto')
result = embodier1({'value': 42})
Examples
Configuration Management
from embody import embody
import os
config_template = {
'database': {
'host': '${db_host}',
'port': '${db_port}',
'name': '${db_name}'
},
'api': {
'base_url': '${api_url}',
'timeout': '${timeout}'
}
}
config = embody(config_template, {
'db_host': os.getenv('DB_HOST', 'localhost'),
'db_port': int(os.getenv('DB_PORT', '5432')),
'db_name': 'myapp',
'api_url': 'https://api.example.com',
'timeout': 30
})
API Response Templates
from embody import Embodier
response_template = {
'status': 'success',
'data': {
'user_id': '${id}',
'name': '${name}',
'timestamp': '${ts}'
}
}
embodier = Embodier(response_template, strategy='compiled')
# Efficiently generate many responses
for user in users:
response = embodier({
'id': user.id,
'name': user.name,
'ts': datetime.now()
})
Backwards Compatibility
The original Templater API is fully preserved:
from embody.templater import Templater
template = {
'hello': '{name}',
'how are you': ['{verb}', 2, '{name} and {verb} again']
}
g = Templater.template_func(template=template)
result = g(name='NAME', verb="VERB")
# {'hello': 'NAME', 'how are you': ['VERB', 2, 'NAME and VERB again']}
Documentation
Contributing
Contributions are welcome! Please see our contributing guidelines.
License
MIT License - see LICENSE file for details.
Project details
Release history Release notifications | RSS feed
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 embody-0.1.8.tar.gz.
File metadata
- Download URL: embody-0.1.8.tar.gz
- Upload date:
- Size: 365.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02cad239735fc8b51d5f8227a5d308138d50ddb150ccd27f0a660a1f3a18ae4e
|
|
| MD5 |
4ceb1dcb32d08b39912e13fb030f7d72
|
|
| BLAKE2b-256 |
db3469e40660498be1f88a8b66af0b193fdaa7cb8fe94f0f05f29e28a72eff86
|
File details
Details for the file embody-0.1.8-py3-none-any.whl.
File metadata
- Download URL: embody-0.1.8-py3-none-any.whl
- Upload date:
- Size: 45.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd3db2223474f138c0e7999980ce135a30b0b2345ea272dfe0c04a36168f5ecd
|
|
| MD5 |
d20053655e435b3773fc43438e2c1197
|
|
| BLAKE2b-256 |
784fbdf9def88c3ec9052165bebdfe6683d09e65469edd1d31e1e61f53a7f57d
|