Skip to main content

embody

Structural Object Embodiment for Python - Transform skeletal templates into fully realized, type-safe objects through recursive hydration.

Documentation PyPI version Python

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

Apache License 2.0 - see LICENSE file for details.

Metadata

Release files for embody 0.1.10

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for embody 0.1.10
File Size Uploaded
embody-0.1.10.tar.gz 365.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for embody 0.1.10
File Interpreter ABI Platform
embody-0.1.10-py3-none-any.whl Python 3 none any Details

Total release size: 411.1 kB

Release files / embody-0.1.10.tar.gz

Download URL embody-0.1.10.tar.gz
Size 365.6 kB
Tags Source
SHA-256 checksum
How to use checksums
119d166edc6321972125678950cb56587bbe73d32e9357065ea78b9802a37cac
BLAKE2b-256 checksum
How to use checksums
5f3910aa4465872af7993444a17b865a66c3046edfc8daee6c127088e8f82e64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","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}

Release files / embody-0.1.10-py3-none-any.whl

Download URL embody-0.1.10-py3-none-any.whl
Size 45.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d7485a05d3f392920e69ee17442f8b90f80e2e1d9321756afa858a72674f07c
BLAKE2b-256 checksum
How to use checksums
adb1a5d8e06a112a4aee71d2dc82e6a7f44e963b285fcb2dc2d16589e166af01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","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}

Release history Release notifications | RSS feed

This release

0.1.10 This release

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

1 release file

0.1.4

1 release file

0.1.3

1 release file

0.1.2

1 release file

0.1.1

1 release file

0.1.0

1 release file

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page