Python SDK for the Cerebral data versioning API
Project description
Cerebral Python SDK
Python SDK for the Cerebral data versioning API.
Installation
pip install cerebral-sdk
Or with uv:
uv add cerebral-sdk
Quick Start
Using environment variables (simplest)
export CEREBRAL_API_KEY="your-api-key"
import cerebral
repo = cerebral.repository("my-org", "my-repo")
print(repo.description) # lazy-loaded on first access
branch = repo.branches.get("main")
branch.objects.put("data/example.csv", b"col1,col2\na,b\n")
branch.commit(message="added example csv")
Explicit configuration
import cerebral
cerebral.configure(api_key="your-api-key", endpoint_url="https://custom.endpoint")
repo = cerebral.repository("my-org", "my-repo")
Explicit client (most flexible)
from cerebral import Client
with Client(api_key="your-api-key") as client:
repo = client.repository("my-org", "my-repo")
branch = repo.branches.get("main")
Configuration
| Option | Environment Variable | Default |
|---|---|---|
api_key |
CEREBRAL_API_KEY |
required |
endpoint_url |
CEREBRAL_ENDPOINT_URL |
https://api.cerebral.storage |
Resolution order: explicit parameter > environment variable > default.
A missing API key is not an error at construction time; a ConfigurationError is raised
when the first request is made.
Usage
Repositories
repo = cerebral.repository("my-org", "my-repo")
# Lazy-loaded properties
print(repo.id, repo.description, repo.visibility)
# Update
repo.update(description="New description", visibility="public")
# Delete
repo.delete()
Branches
branches = repo.branches
# Create
branch = branches.create("feature-branch", source="main")
# Get
branch = branches.get("main")
print(branch.commit_id)
# List (auto-paginating)
for record in branches.list():
print(record.branch_id)
# Delete
branches.delete("feature-branch")
Objects
branch = repo.branches.get("main")
# Upload
branch.objects.put("data/file.csv", b"content")
# Download (streaming)
with branch.objects.get("data/file.csv") as f:
data = f.read()
# Stream large objects without caching
with branch.objects.get("data/large.bin", cache=False) as f:
for chunk in f.iter_bytes(chunk_size=8192):
process(chunk)
# List (auto-paginating, with directory grouping)
for entry in branch.objects.list(prefix="data/", delimiter="/"):
print(entry.path, entry.type) # type is "object" or "prefix"
# Check metadata
meta = branch.objects.head("data/file.csv")
print(meta.etag, meta.content_type, meta.content_length)
# Delete
branch.objects.delete("data/file.csv")
Commits
# Create a commit
commit_id = branch.commit(message="update data", metadata={"source": "etl"})
# Browse commit log
for entry in branch.log():
print(entry.id, entry.message)
# Access a specific commit
commit = repo.commits.get("abc123")
print(commit.committer, commit.message, commit.creation_date)
# Read objects at a specific commit
for entry in commit.objects.list():
print(entry.path)
Tags
# Create
repo.tags.create("v1.0", commit_id="abc123")
# Get (read-only object access)
tag = repo.tags.get("v1.0")
print(tag.commit_id)
with tag.objects.get("data.csv") as f:
data = f.read()
# List
for record in repo.tags.list():
print(record.tag_id)
# Delete
repo.tags.delete("v1.0")
Diff and Merge
# Diff two refs
for entry in repo.diff.diff("main", "feature", delimiter="/"):
print(entry.path, entry.status)
# Uncommitted changes
for entry in repo.diff.uncommitted("main"):
print(entry.path)
# Merge
commit_id = repo.merge.merge("feature", "main", message="merge feature")
# Or from a branch object
commit_id = branch.merge_into("main", message="merge feature")
Organizations
orgs = cerebral.Client(api_key="key").organizations
# Create
org = orgs.create("my-org", "My Organization")
# List
for org in orgs.list():
print(org.name)
# Members
for member in orgs.members("my-org").list():
print(member.username, member.role)
orgs.members("my-org").add(user_id="user-uuid", role="member")
Groups
groups = client.organizations.groups("my-org")
group = groups.create("engineers", description="Engineering team")
detail = groups.get(group.id) # includes members and attachments
groups.add_member(group.id, "user", "user-uuid")
groups.remove_member(group.id, "user", "user-uuid")
Policies
policies = client.organizations.policies("my-org")
# Create and validate
result = policies.validate("package cerebral.authz\ndefault allow = true")
policy = policies.create("allow-all", rego="...", description="Allow everything")
# Attach/detach
policies.attach(policy.id, "group", "group-uuid")
policies.detach(policy.id, "group", "group-uuid")
# Effective policies for a user
for ep in policies.effective_policies("user-uuid"):
print(ep.policy_name, ep.source)
Connectors and Imports
# Org-level connectors
connectors = client.organizations.connectors("my-org")
conn = connectors.create("my-s3", "s3", {"bucket": "my-bucket", "region": "us-east-1"})
# Attach to repo
repo.connectors.attach(conn.id)
# Import
job_id = repo.imports.start(
branch="main",
connector_id=conn.id,
source_path="s3://my-bucket/data/",
destination_path="imported/",
)
status = repo.imports.status(job_id)
print(status.status, status.objects_imported)
Error Handling
All SDK exceptions inherit from CerebralError:
CerebralError # base for all SDK errors
+-- ConfigurationError # missing API key, bad endpoint
+-- TransportError # network failures, DNS, timeouts
+-- SerializationError # invalid JSON in response
+-- APIError # base for HTTP API errors
+-- BadRequestError # 400
+-- AuthenticationError # 401
+-- ForbiddenError # 403
+-- NotFoundError # 404
+-- ConflictError # 409
+-- GoneError # 410
+-- PreconditionFailedError # 412
+-- LockedError # 423
+-- ServerError # 5xx
APIError includes status_code, message, code, request_id, method, url, and
response_text for debugging.
from cerebral import NotFoundError, CerebralError
try:
repo.branches.get("nonexistent").commit_id
except NotFoundError as e:
print(f"Not found: {e.message} (request_id={e.request_id})")
except CerebralError as e:
print(f"SDK error: {e}")
Large Object Handling
By default, objects.get() caches the full object in memory on .read(). For large
objects, disable caching and stream:
with branch.objects.get("large-file.bin", cache=False) as f:
for chunk in f.iter_bytes(chunk_size=1024 * 1024):
output.write(chunk)
Development
# Install dev dependencies
uv sync --all-extras
# Run tests
uv run pytest
# Lint and format
uv run ruff check src/ tests/
uv run ruff format src/ tests/
# Type check
uv run mypy src/cerebral/
# Build
uv build
License
Apache 2.0
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 cerebral_sdk-0.1.0.tar.gz.
File metadata
- Download URL: cerebral_sdk-0.1.0.tar.gz
- Upload date:
- Size: 100.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.3 {"installer":{"name":"uv","version":"0.10.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01dcd7b0ac691f418f178685e043980c54faca36b429cae54b9074c5fc7002fa
|
|
| MD5 |
d7ca20005242e17a352d4031d51bbc39
|
|
| BLAKE2b-256 |
02c998f2d58ac71b75cab6741faecd6d0e65416edc795aac10a96692ae2d8a2b
|
File details
Details for the file cerebral_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cerebral_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 33.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.3 {"installer":{"name":"uv","version":"0.10.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6df61ff8aabee4544e04e041ee4b0cce63b6adb179650f798ec5bc3c114c28dd
|
|
| MD5 |
a7ee83558cc9a6f2592dc059127eb815
|
|
| BLAKE2b-256 |
863631a74444d792844e8205102d76d42ba6277f7a799d7473ad04cd70eed7fa
|