Metadata-Version: 2.4
Name: athena-openpyxl
Version: 0.6.2
Summary: Drop-in replacement for openpyxl that connects to XLSX Studio for real-time collaboration
Project-URL: Homepage, https://github.com/Athena-Intel/demo-app-monorepo/tree/staging/xlsx-studio
Project-URL: Documentation, https://github.com/Athena-Intel/demo-app-monorepo/tree/staging/xlsx-studio/python-sdk
Project-URL: Issues, https://github.com/Athena-Intel/demo-app-monorepo/issues
Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
License-Expression: MIT
Keywords: api,excel,openpyxl,sdk,spreadsheet,xlsx
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: requests>=2.28.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: responses>=0.23; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Provides-Extra: e2e
Requires-Dist: openpyxl>=3.1.0; extra == 'e2e'
Requires-Dist: pytest>=7.0; extra == 'e2e'
Description-Content-Type: text/markdown

# athena-openpyxl

`openpyxl`-shaped Python SDK that writes directly to Athena's Keryx-backed spreadsheet Y.Docs. No HTTP middleware on the data path — mirrors [`athena-python-docx`](../../docx-studio/python-sdk/).

**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

```python
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:

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

```python
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 |
|---|---|---|
| `KERYX_WS_URL` | ✓ | e.g. `wss://keryx-staging.athenaintel.com` |
| `ATHENA_WORKSPACE_ID` | ✓ | workspace routing segment |
| `KERYX_COLLAB_TOKEN` | one of | pre-minted JWT (preferred — Daytona injects this) |
| `KERYX_AUTH_PRIVATE_KEY` | one of | ECDSA P-384 JWK/PEM; used to sign locally for dev |
| `ATHENA_SERVICE_USER_ID` |   | `yuserid` JWT claim, defaults to `athena@athenaintel.com` |

## Install (development)

```bash
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`](docs/API_PARITY_EXCEPTIONS.md) for the canonical list of intentional deviations.

## Architecture

```
Agent code (openpyxl idiom)
    ↓
Workbook / Worksheet / Cell  (sync facade)
    ↓  _batching.run_sync → persistent background event loop thread
Session  (pycrdt Doc + Keryx connection, branch + custom_attributions)
    ↓  _keryx_client: ECDSA P-384 JWT + y-websocket sync protocol
Keryx  ←→  Olympus (@rowsncolumns/y-spreadsheet renderer)
  (same Y.Doc; room = "{workspace}/{asset_id}")
```

- `_keryx_client.py` — ECDSA P-384 JWT signing, y-websocket sync step1/step2/update frames, awareness state with `customAttributions`. Ported from `agora/agora/services/keryx/client.py` minus retry/metrics.
- `_batching.py` — sync→async bridge, one persistent event loop. Ported from `docx-studio/python-sdk/docx/_batching.py`.
- `_session.py` — `Session` class owning the pycrdt `Doc` + WebSocket; exposes per-cell I/O, dimension setters, structural mutations, merges, freeze panes, filter, xf registry, batch mode.
- `cell/`, `worksheet/`, `workbook/`, `dimensions.py`, `styles/`, `comments/`, `formatting/`, `drawing/` — openpyxl-shaped surface that routes through `Session`.

## Publishing

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

## Development workflow

```bash
# 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 Keryx WebSocket connection and operate against an in-memory pycrdt Doc — 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`).
