Welcome to Coraline
Coraline is a Python library that provides a seamless integration between Pydantic models and AWS DynamoDB tables. It allows you to define your data models using Pydantic's powerful validation system and easily map them to DynamoDB tables.
Features
- Define DynamoDB tables using Pydantic models
- Automatic table creation and management
- Type validation and conversion
- Support for complex data types
- Easy configuration of AWS credentials
- Simplified CRUD operations
Installation
# Basic installation
pip install coraline
# With boto3 dependency
pip install coraline[boto]
Documentation
Architecture
graph TD
A[Pydantic Model] -->|Extends| B[CoralModel]
B -->|Creates/Manages| C[DynamoDB Table]
B -->|Validates| D[Data]
D -->|Stored in| C
E[AWS Credentials] -->|Configure| B
F[CoralConfig] -->|Configure| B
Quick Start
Define Your Model
import uuid
from enum import Enum
from coraline import CoralModel, KeyField, HashType
from pydantic import SecretStr, Field
class UserType(Enum):
USER = "USER"
ADMIN = "ADMIN"
class Users(CoralModel):
user_id: uuid.UUID = KeyField(
default=lambda: uuid.uuid4(),
hash_key=HashType.HASH,
alias="userId"
)
user_type: UserType = KeyField(
...,
hash_type=HashType.RANGE,
alias="userType"
)
name: str
age: int = Field(..., gt=0)
password: SecretStr
# Create the table if it doesn't exist
Users.get_or_create_table()
# Create and save a new user
new_user = Users(
name="John Doe",
user_type=UserType.USER,
age=30,
password="123456"
)
new_user.save()
This example:
- Defines a
Usersmodel that extendsCoralModel - Creates a DynamoDB table named
Userswith:PAY_PER_REQUESTbilling mode (default)userId(String) as the Hash KeyuserType(String) as the Range Key- Additional fields:
name(String),age(Number), andpassword(String)
- Creates and saves a new user record to the table
Table Configuration
Use the CoralConfig class to customize your DynamoDB table settings.
import uuid
from enum import Enum
from coraline import (
CoralModel,
KeyField,
HashType,
CoralConfig,
BillingMode,
TableClass
)
from pydantic import SecretStr, Field
class UserType(Enum):
USER = "USER"
ADMIN = "ADMIN"
def to_camel(string: str) -> str:
"""Convert snake_case to camelCase"""
return ''.join(word.capitalize() for word in string.split('_'))
# CoralModel is a subclass of Pydantic's BaseModel
class Users(CoralModel):
# CoralConfig is a subclass of Pydantic's ConfigDict
model_config = CoralConfig(
# Custom table name (default is the class name)
table_name="MyUsers",
# Set billing mode to PROVISIONED (default is PAY_PER_REQUEST)
billing_mode=BillingMode.PROVISIONED,
read_capacity_units=5,
write_capacity_units=5,
# Convert field names to camelCase in DynamoDB
alias_generator=to_camel,
# Prevent fields from being excluded when None
protect_from_exclusion=True,
# Set table storage class
table_class=TableClass.STANDARD_INFREQUENT_ACCESS,
# Add any additional parameters accepted by boto3's create_table
extra_table_params={
"Tags": [
{
"Key": "Project",
"Value": "MyProject"
}
]
}
)
# KeyField is a subclass of Pydantic's Field
user_id: uuid.UUID = KeyField(
default=lambda: uuid.uuid4(),
hash_key=HashType.HASH
)
user_type: UserType = KeyField(
...,
hash_type=HashType.RANGE
)
name: str
age: int = Field(..., gt=0)
password: SecretStr
Available Configuration Options
| Option | Description | Default |
|---|---|---|
table_name |
Custom name for the DynamoDB table | Class name |
billing_mode |
BillingMode.PROVISIONED or BillingMode.PAY_PER_REQUEST |
BillingMode.PAY_PER_REQUEST |
read_capacity_units |
Read capacity units (when using PROVISIONED) | 5 |
write_capacity_units |
Write capacity units (when using PROVISIONED) | 5 |
alias_generator |
Function to transform field names | None |
protect_from_exclusion |
Prevent fields from being excluded when None | False |
table_class |
Storage class for the table | TableClass.STANDARD |
extra_table_params |
Additional parameters for boto3's create_table | {} |
AWS Credentials Configuration
Coraline provides multiple ways to configure AWS credentials for connecting to DynamoDB. The library follows a priority order when determining which credentials to use:
- Class-specific configuration in
model_config - Coraline environment variables
- Standard AWS environment variables
Environment Variables
You can set AWS credentials using environment variables:
# Standard AWS environment variables
AWS_REGION="us-east-1"
AWS_ACCESS_KEY_ID="your-access-key"
AWS_SECRET_ACCESS_KEY="your-secret-key"
# Coraline-specific environment variables (take precedence)
CORALINE_AWS_REGION="us-west-2"
CORALINE_AWS_ACCESS_KEY_ID="your-coraline-access-key"
CORALINE_AWS_SECRET_ACCESS_KEY="your-coraline-secret-key"
CORALINE_AWS_ENDPOINT_URL="http://localhost:8000" # For local development
Model Configuration
You can specify AWS credentials directly in your model configuration:
from coraline import CoralModel, CoralConfig
class Users(CoralModel):
model_config = CoralConfig(
# AWS credentials
aws_region="us-east-1",
aws_access_key_id="your-access-key",
aws_secret_access_key="your-secret-key",
aws_endpoint_url="http://localhost:8000" # For local development
)
Using Boto3 Config
For more advanced configuration, you can use a boto3 Config instance:
from botocore.config import Config
from coraline import CoralModel, CoralConfig
# Create a boto3 Config instance
config = Config(
region_name="us-east-1",
endpoint_url="http://localhost:8000",
retries={
'max_attempts': 10,
'mode': 'standard'
}
)
class Users(CoralModel):
model_config = CoralConfig(
aws_config=config
)
Local Development
For local development with DynamoDB Local:
from coraline import CoralModel, CoralConfig
class Users(CoralModel):
model_config = CoralConfig(
aws_region="local",
aws_endpoint_url="http://localhost:8000"
)
Basic Operations
Coraline provides a set of methods to interact with DynamoDB tables. Here are the most common operations:
Table Operations
Create or Get Table
Creates a new table if it doesn't exist, or returns information about the existing table:
# Create the table if it doesn't exist
table_description: dict = Users.get_or_create_table()
# Get the table name (returns "Users" by default, or the custom name if specified)
table_name: str = Users.get_table_name()
Get Table Information
Retrieve detailed information about the table:
# Get basic table information
table_info: dict = Users.get_table_info()
# Include additional describe operations
table_info: dict = Users.get_table_info(
include=[
"describe_continuous_backups",
"describe_time_to_live"
]
)
Note: Only describe operations that take just the TableName parameter are supported, such as:
describe_continuous_backupsdescribe_time_to_livedescribe_limitsOperations that require additional parameters (like
describe_backup,describe_global_table) are not supported through this method.
Record Operations
Check if a Record Exists
Check if a record exists by providing all hash and range keys:
# Check if a user exists
user_exists: bool = Users.exists(
user_id="12345678-1234-1234-1234-123456789012",
user_type=UserType.USER
)
Get a Record
Retrieve a record by providing all hash and range keys:
# Get a user
user: Users = Users.get(
user_id="12345678-1234-1234-1234-123456789012",
user_type=UserType.USER
)
# Access user properties
print(f"User name: {user.name}")
print(f"User age: {user.age}")
Create and Save a Record
Create a new record and save it to the table:
# Create a new user
new_user = Users(
name="John Doe",
user_type=UserType.USER,
age=30,
password="123456"
)
# Save the user to the table
new_user.save()
Update a Record
Update an existing record:
# Get an existing user
user = Users.get(
user_id="12345678-1234-1234-1234-123456789012",
user_type=UserType.USER
)
# Update properties
user.name = "Jane Doe"
user.age = 31
# Save the changes
user.save()
Delete a Record
Delete an existing record:
# Get an existing user
user = Users.get(
user_id="12345678-1234-1234-1234-123456789012",
user_type=UserType.USER
)
# Delete the user
user.delete()
# You can also use the async version
await user.adelete()
# Verify the user no longer exists
user_exists = Users.exists(
user_id="12345678-1234-1234-1234-123456789012",
user_type=UserType.USER
)
assert user_exists is False
Advanced Operations
Using boto3's Client Directly
For operations not covered by Coraline's methods, you can access the boto3 client directly:
# Get the boto3 client
client = Users.get_client()
# Use any boto3 DynamoDB client method
client.create_backup(
TableName=Users.get_table_name(),
BackupName="MyBackup"
)
# Or from an instance
user = Users.get(
user_id="12345678-1234-1234-1234-123456789012",
user_type=UserType.USER
)
user.get_client().update_time_to_live(
TableName=user.table_name(),
TimeToLiveSpecification={
'Enabled': True,
'AttributeName': 'ExpirationTime'
}
)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please make sure to update tests as appropriate.
Issues and Support
If something isn't working as expected, don't panic. Get a towel and please open an issue.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for coraline 1.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| coraline-1.4.1.tar.gz | 13.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| coraline-1.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.6 kB
Release files / coraline-1.4.1.tar.gz
| Download URL | coraline-1.4.1.tar.gz |
|---|---|
| Size | 13.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a4a987fc83bd397540c56fb6a003e748c677d0cbde8d9a3a1c10b6d4b537c738
|
|
BLAKE2b-256 checksum How to use checksums |
ad3baba9f37be5cf19e8c0f58b9b925d59d13e31be64de97831ff590a1a23007
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.3.1 CPython/3.12.1 Linux/6.11.0-1018-azure
|
Release files / coraline-1.4.1-py3-none-any.whl
| Download URL | coraline-1.4.1-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f17aff581a9ad7931d2f4bc85cdfafedd6b2af7fa8f75b4db3a0048c51cdf6e5
|
|
BLAKE2b-256 checksum How to use checksums |
b610e99c0d36be2b27a77dbb805a3a56b40a426f56c6a1b7c79cc56023bed946
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.3.1 CPython/3.12.1 Linux/6.11.0-1018-azure
|
Security for coraline 1.4.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.