Skip to main content

athena-openpyxl

openpyxl-shaped Python SDK that talks to xlsx-studio's HTTP API. Writes go through POST /workbooks/:id/commands; the Fastify service applies them to a server-side pycrdt Doc and pushes Y.Doc updates to Keryx so Olympus's @rowsncolumns/y-spreadsheet renderer sees the change live. The SDK process never opens its own y-websocket — there is no pycrdt dependency on the SDK side.

Status: v0.2.0 — Tier-A surface complete (full openpyxl public API up to formatting + dates), Tier-B surfaces (tables / data validation / conditional formatting / defined names / comments / images / hyperlinks) wired through the Keryx Y.Doc.

Quick start

from openpyxl import Workbook

with Workbook("asset_abc123") as wb:   # opens Keryx session, runs initial sync
    ws = wb.active
    ws["A1"] = "Hello"
    ws["A2"] = 42
    ws["A3"] = "=SUM(A2)"
    wb.save()                          # flushes pending updates to Keryx

Bulk writes via batch context (one logical activity-log entry):

from openpyxl import Workbook

with Workbook("asset_abc") as wb:
    ws = wb.active
    with wb.batch():
        for row_idx in range(1, 1001):
            ws.cell(row_idx, 1, f"row {row_idx}")
        wb.save()

Environment

The SDK reads these env vars (agora injects them into the spreadsheet executor sandbox in production):

Variable Required Notes
ATHENA_XLSX_BASE_URL ✓ xlsx-studio API URL, e.g. https://xlsx-api.stg.athenaintel.com
ATHENA_XLSX_API_KEY Bearer token for the apps/api ownership middleware (omit for local dev with no auth). The workspace is resolved server-side from this key.
ATHENA_API_KEY Used when ATHENA_XLSX_API_KEY is unset. With ATHENA_API_URL beside it, an opened workbook's calls carry a 15-minute token Athena mints for that workbook alone (POST /api/v0/assets/{asset_id}/studio-token, read-only for reads), and Workbook.create() creates through Athena's public API (openpyxl/_asset_token.py).
ATHENA_API_URL Athena's URL, bare or ending in /api/v0: token minting, load_workbook(<file>) uploads and uploaded-file reads.

Install (development)

cd xlsx-studio/python-sdk
uv venv && uv pip install -e ".[dev]"
uv run pytest tests/

Public surface (v0.2.0)

Tier A — Core (fully implemented):

Surface Status
Workbook lifecycle (Workbook(asset_id), load_workbook, save, close, ctx mgr) ✅
Sheet listing (sheetnames, worksheets, active, wb[title]) ✅
Single-cell I/O (ws['A1'], ws.cell(r, c), cell.value) ✅
Range access (ws['A1:C3'], ws['A:C'], ws[1]) ✅
Bulk writes (ws.append, iter_rows, iter_cols) ✅
Dimensions (column_dimensions, row_dimensions, width, height, hidden, outline_level, group) ✅
Structural mutations (create_sheet, remove, move_sheet, copy_worksheet, ws.title = x) ✅
Merged cells (merge_cells, unmerge_cells, merged_cells) ✅
Freeze panes (ws.freeze_panes) ✅
Auto filter (ws.auto_filter.ref) ✅
Cell formatting (font, fill, alignment, border, protection, number_format, style) ✅
Date / datetime / time values ✅

Tier B — Common (wired through Keryx Y.Doc):

Surface Status
wb.defined_names / DefinedName ✅
ws.tables / Table / TableStyleInfo ✅
ws.data_validations / DataValidation ✅
ws.conditional_formatting / Rule classes ✅
cell.comment / Comment ✅
cell.hyperlink / Hyperlink ✅
ws.add_image / Image ✅
wb.named_styles / NamedStyle (object model only) partial

Tier C — Advanced (raises UnsupportedFeatureError):

  • Chartsheets (wb.create_chartsheet); charts embedded on a worksheet work.
  • Macros / VBA passthrough.

See docs/API_PARITY_EXCEPTIONS.md for the canonical list of intentional deviations.

Common gotchas

  • Vertical alignment defaults to bottom, not center. Both Excel and openpyxl default Alignment.vertical to "bottom", so a brand-new KPI tile, banner row, or centered headline cell will draw text glued to the bottom edge until you set vertical="center" explicitly. Set it on the cell that anchors the visual:

    from openpyxl.styles import Alignment
    
    cell.alignment = Alignment(horizontal="center", vertical="center")
    

    The same applies to merged ranges — set the alignment on the anchor cell (top-left of the merge) before or after ws.merge_cells(...); the renderer reads the anchor cell's style. The ws.merge_and_style(...) helper does this correctly out of the box.

Architecture

Agent code (openpyxl idiom)
    ↓
Workbook / Worksheet / Cell           (sync facade)
    ↓  CommandBuffer.append(<cmd>)
batching.CommandBuffer                (groups + flushes)
    ↓  Client.post_commands(...)
HTTP POST /workbooks/:id/commands     (Bearer auth + ownership middleware)
    ↓
xlsx-studio apps/api (Fastify)        (validates schema, runs applier.ts)
    ↓  pycrdt Doc transactions
Keryx  ←→  Olympus (@rowsncolumns/y-spreadsheet renderer)
  (Y.Doc lives server-side; room = "{workspace}/{asset_id}")
  • client.py — requests-backed HTTP client: auth, retries (urllib3 Retry), 401/409/4xx error mapping (AuthenticationError/ConflictError/RemoteError), and the workbook / commands / snapshot / export endpoints.
  • batching.py — CommandBuffer queues SDK calls into a single POST /commands payload (so one cell or one bulk write becomes one HTTP round-trip, not N) and flush_all() for end-of-script drain.
  • commands.py — typed dataclasses (SetCellValue, SetCellStyle, SetIterativeCalculation, …) with .validate() and .to_dict(). Each one round-trips against apps/api/src/commands/types.ts Zod schemas.
  • cell/, worksheet/, workbook/, styles/, comments/, formatting/, drawing/, pivot/, tables.py — openpyxl-shaped surface; reads materialize from snapshot (Client.get_snapshot), writes append commands to the buffer.

Publishing

Releases go through a release PR, never a hand upload. bun run scripts/release-studio-sdk.ts athena-openpyxl X.Y.Z --pr (from the repo root) moves the version and every image that bakes the SDK; merging it runs .github/workflows/release-studio-sdk.yml, which publishes to PyPI and then builds the images. See the bump-athena-openpyxl skill.

Development workflow

# Install editable + dev tools.
uv venv && uv pip install -e ".[dev]"

# Run the unit suite (no Keryx required).
uv run pytest tests/ -x

# Lint.
uv run ruff check openpyxl tests

Tests

The SDK ships ~190 unit tests covering: utility helpers, all five style descriptors (Font / Fill / Alignment / Border / Protection / NamedStyle), Workbook lifecycle / registry / flush_all, single-cell I/O, range access, iter_rows / iter_cols, append, max_row / max_column, dimensions, structural mutations, merges, freeze panes, auto filter, cell formatting, dates, comments, hyperlinks, and the UnsupportedFeatureError boundary.

Tests stub the HTTP transport (Client._request) and assert on the captured command payloads — no network access required.

The integration / parity / fidelity lanes live separately (see the roadmap doc at xlsx-studio/docs/ATHENA_OPENPYXL_ROADMAP_2026-04-29.md).

Metadata

Release files for athena-openpyxl 0.29.0

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

Source distribution (sdist)

Source distribution for athena-openpyxl 0.29.0
File Size Uploaded Provenance Actions
athena_openpyxl-0.29.0.tar.gz 582.1 kB Without provenance Details for athena_openpyxl-0.29.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for athena-openpyxl 0.29.0
File Interpreter ABI Platform Actions
athena_openpyxl-0.29.0-py3-none-any.whl Python 3 none any Details for athena_openpyxl-0.29.0-py3-none-any.whl

Total release size: 1.1 MB

Release files / athena_openpyxl-0.29.0.tar.gz

Download URL athena_openpyxl-0.29.0.tar.gz
Size 582.1 kB
Tags Source
SHA-256 checksum
How to use checksums
8b31acc3809e56b8714be8648154e78b82fd3cbcf4da2e5095146b70e04eb64e
BLAKE2b-256 checksum
How to use checksums
7d0f2b3bd9b02b31027e81f55e5b38c473fa7efc00b806d80bdbbb754179f6b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / athena_openpyxl-0.29.0-py3-none-any.whl

Download URL athena_openpyxl-0.29.0-py3-none-any.whl
Size 515.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a18acc4cad2ea605549e039c9bfe15edcac96ec123d226817606e11a65c65109
BLAKE2b-256 checksum
How to use checksums
5ddbae1ccdb1082f3680cf32a45aed4cfce2fce9fd189d1a970ee248a36bc2c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Security for athena-openpyxl 0.29.0

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.29.0 This release

2 release files No provenance

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