Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cerebral_sdk-0.1.0.tar.gz (100.0 kB view details)

Uploaded Source

Built Distribution

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

cerebral_sdk-0.1.0-py3-none-any.whl (33.1 kB view details)

Uploaded Python 3

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

Hashes for cerebral_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 01dcd7b0ac691f418f178685e043980c54faca36b429cae54b9074c5fc7002fa
MD5 d7ca20005242e17a352d4031d51bbc39
BLAKE2b-256 02c998f2d58ac71b75cab6741faecd6d0e65416edc795aac10a96692ae2d8a2b

See more details on using hashes here.

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

Hashes for cerebral_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6df61ff8aabee4544e04e041ee4b0cce63b6adb179650f798ec5bc3c114c28dd
MD5 a7ee83558cc9a6f2592dc059127eb815
BLAKE2b-256 863631a74444d792844e8205102d76d42ba6277f7a799d7473ad04cd70eed7fa

See more details on using hashes here.

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