Skip to main content

Drop-in replacement for openpyxl that connects to XLSX Studio for real-time collaboration

Project description

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

Branch + agent attribution:

from openpyxl import Workbook

with Workbook(
    "asset_abc",
    branch="suggest-run-7",
    custom_attributions=[
        {"k": "agent_id", "v": "spreadsheet-author"},
        {"k": "user_message_tracking_id", "v": "msg_xyz"},
    ],
) as wb:
    wb.active["A1"] = "agent edit"
    wb.save()

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 (Daytona-managed 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)
ATHENA_ORG_ID Workspace/org override; the API resolves the workspace from the API key when this is unset

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):

  • Charts and chartsheets (waiting on the cross-studio chart engine extraction from pptx-studio — see pptx-studio/docs/CHARTING_REFACTOR_PLAN_2026-04-21.md).
  • Pivot tables.
  • Sheet/workbook protection write side.
  • Page setup write side.
  • 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.pyrequests-backed HTTP client: auth, retries (urllib3 Retry), 401/409/4xx error mapping (AuthenticationError/ConflictError/RemoteError), and the workbook / commands / snapshot / export endpoints.
  • batching.pyCommandBuffer 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

bash ../scripts/publish-python-sdk.sh 0.2.0

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).

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

athena_openpyxl-0.15.0.tar.gz (347.0 kB view details)

Uploaded Source

Built Distribution

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

athena_openpyxl-0.15.0-py3-none-any.whl (337.2 kB view details)

Uploaded Python 3

File details

Details for the file athena_openpyxl-0.15.0.tar.gz.

File metadata

  • Download URL: athena_openpyxl-0.15.0.tar.gz
  • Upload date:
  • Size: 347.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for athena_openpyxl-0.15.0.tar.gz
Algorithm Hash digest
SHA256 9ebf268f4e66054fd902a9ca4823a42bf98f0a1fafbef65b701cce206c2408d0
MD5 de205e11e6c8fbd36c0d55b75a1a1279
BLAKE2b-256 1d97561645e8111939e761c4255080d95ffc0c630d43fac72f47f5268b5f2eb9

See more details on using hashes here.

File details

Details for the file athena_openpyxl-0.15.0-py3-none-any.whl.

File metadata

File hashes

Hashes for athena_openpyxl-0.15.0-py3-none-any.whl
Algorithm Hash digest
SHA256 161bcc7f7680daf20d44429e96c770b11bba03aa912a8652dafa7699db5173ce
MD5 f3fdc8c5823fa389dd536e24e506a710
BLAKE2b-256 9fcb2ae63199917d1e7546a45358b450a0bf75c3676d7bb6316f4d957ec42e61

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