Skip to main content

A developer-friendly library for DynamoDB that simplifies single-table design without ORM lock-in

Project description

Dynamixe

A developer-friendly library for DynamoDB that simplifies single-table design without ORM lock-in.

Features

  • Expression-based API - SQLAlchemy-style attribute access for type-safe queries
  • Model configuration - Pydantic-compatible model_config pattern
  • No ORM lock-in - Works with Pydantic, dataclasses, or plain dicts
  • Transactional operations - Full support for transact_get and transact_write
  • Conditional operations - Expression-based conditions with custom exceptions
  • JMESPath transformations - Transform transactional results with powerful queries

Installation

pip install dynamixe

Quick Start

Define a Model

from dynamixe import Model, ConfigDict

class User(Model):
    model_config = ConfigDict(
        table='users',
        partition_key='id',
        sort_key='sk',
    )
    id: str
    sk: str
    name: str

Use Expressions

# SQLAlchemy-style expression access
User.id == 'USER#10'           # Equality
User.sk.not_exists()           # Condition
User.name.begins_with('A')     # Begins with
User.sk.between('0', '100')    # Range

# Combine expressions
(User.id == 'USER#10') & (User.sk == '0')

Conditional Put

from dynamixe import DynamoDBClient

client = DynamoDBClient(table_name='users')

# Put with condition using expressions
client.put_item(
    user,
    cond_expr=User.sk.not_exists(),
)

Query Items

# Query with key condition expression
result = client.query(
    User.id == 'USER#10',
    scan_index_forward=True,
    limit=10,
)

# Access results as dict
items = result['items']
count = result['count']
last_key = result['last_key']  # For pagination

# Transform with JMESPath
names = result.jmespath('[*].name')
# ['Alice', 'Bob', 'Charlie']

Transactional Writes

from dynamixe import TransactWriter, TransactionOperationFailed

class EmailConflictError(TransactionOperationFailed):
    pass

with TransactWriter('users', client=boto3_client) as tx:
    tx.put(
        item={'id': 'USER#1', 'sk': '0', 'name': 'Alice'},
        cond_expr=User.sk.not_exists(),
        exc_cls=EmailConflictError,
    )

# Or via client
with client.transact_writer() as tx:
    ...

Transactional Reads

from dynamixe import TransactGet, get

tx = TransactGet('users', client=boto3_client)
result = tx.get_items(
    get({'id': 'USER#1', 'sk': '0'}),
    get({'id': 'USER#2', 'sk': '0'}).project(User.name, User.email),
)

# Or via client
tx = client.transact_get()
result = tx.get_items(...)

JMESPath Transformations

Transform transactional results with JMESPath expressions:

from dynamixe import TransactGet, get

tx = client.transact_get()

names = tx.get_items(
    get({'id': 'USER#1', 'sk': '0'}),
    get({'id': 'USER#2', 'sk': '0'}),
).jmespath('[*].name')
# ['Alice', 'Bob']

The TransactGetResult wrapper supports list-like operations:

result = tx.get_items(get({'id': 'USER#1', 'sk': '0'}))
len(result)        # 1
result[0]          # {'id': 'USER#1', ...}
for item in results:
    print(item['name'])

Works with Any Model Pattern

Pydantic:

from pydantic import BaseModel

class User(BaseModel):
    model_config = ConfigDict(table='users', partition_key='id')
    id: str
    name: str

Dataclass (via __dynamodb_config__):

from dataclasses import dataclass

@dataclass
class User(Model):
    __dynamodb_config__ = ConfigDict(
        table='users',
        partition_key='id',
        sort_key='sk',
    )
    id: str
    sk: str
    name: str

Plain dict:

# No model needed
client.put_item({'id': 'USER#1', 'sk': '0', 'name': 'Alice'})

API Reference

DynamoDBClient

  • get_item(key, ...) - Get single item
  • put_item(item, cond_expr=..., exc_cls=...) - Put with condition
  • update_item(key, update_expr, ...) - Update item
  • delete_item(key, cond_expr=...) - Delete item
  • query(key_expr, ...) - Query items by key condition
  • scan(filter_expr=...) - Scan all items with optional filter
  • transact_get() - Start transactional read
  • transact_writer(flush_amount=50) - Start transactional write

Model

  • model_config - Class attribute for DynamoDB configuration
  • get_table() - Get table name
  • get_partition_key() - Get partition key attribute
  • get_sort_key() - Get sort key attribute

ConfigDict

ConfigDict(
    table='table-name',
    partition_key='pk',
    sort_key='sk',  # optional
)

Expressions

  • Comparison: ==, !=, <, <=, >, >=
  • Conditions: not_exists(), exists(), begins_with(), between()
  • Logical: & (AND), | (OR), ~ (NOT)

TransactGetResult

  • jmespath(expr) - Apply JMESPath expression to transform results
  • __len__() - Support for len()
  • __getitem__(index) - Support for indexing
  • __iter__() - Support for iteration

Why Dynamixe?

  • No ORM lock-in - Use Pydantic, dataclasses, or plain dicts
  • Type-safe - Full type hints for IDE autocomplete
  • Single-table design - Built for DynamoDB best practices
  • Expression API - Composable, testable, readable
  • Transactional - ACID operations with custom exceptions
  • JMESPath support - Powerful result transformations

License

MIT

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

dynamixe-0.1.0.tar.gz (69.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dynamixe-0.1.0-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file dynamixe-0.1.0.tar.gz.

File metadata

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

File hashes

Hashes for dynamixe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e6f4f96d55b4a111dd297aafe9361717aefff11e5732c7e77766e1c42f9fb225
MD5 53b5dccb22cb37e26ccdc918f1032f39
BLAKE2b-256 dd91c07b2b94db8e2197ff7a377b35467f9b8eb6d8782e51335b8001e25c6431

See more details on using hashes here.

Provenance

The following attestation bundles were made for dynamixe-0.1.0.tar.gz:

Publisher: python-publish.yaml on sergiors/dynamixe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dynamixe-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dynamixe-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dynamixe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4d86d3b272787799e54d43281ff1d5ba8d6a7d8f21ac2441d1508f8bc84483a9
MD5 d6e7eca1e27c20d8e34ac434d64b4180
BLAKE2b-256 69f1d4b4ccafbe5fa98bb2a485ca754eaa0ab8946bd051a6e8e48477b2506547

See more details on using hashes here.

Provenance

The following attestation bundles were made for dynamixe-0.1.0-py3-none-any.whl:

Publisher: python-publish.yaml on sergiors/dynamixe

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