Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
Repository-local references:

- [AGENTS.md](../AGENTS.md)
- [docs/documentation-maintenance-checklist.md](../docs/documentation-maintenance-checklist.md)
- [docs/repo-map.md](../docs/repo-map.md)
- [docs/domain-model.md](../docs/domain-model.md)
- [docs/invariants.md](../docs/invariants.md)
- [src/excelalchemy/README.md](../src/excelalchemy/README.md)
- [tests/README.md](../tests/README.md)
- [examples/README.md](../examples/README.md)

## Summary

- Describe the user-facing or engineering goal of this change.
Expand All @@ -15,6 +26,7 @@

## Checklist

- [ ] I updated documentation when behavior or workflows changed.
- [ ] I updated documentation when behavior, workflows, or design changed.
- [ ] I updated the relevant repository-local knowledge docs listed above, following `docs/documentation-maintenance-checklist.md`.
- [ ] I did not include generated files or local-only artifacts.
- [ ] I confirmed this change does not require additional release steps.
358 changes: 240 additions & 118 deletions AGENTS.md

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,64 @@ All notable changes to this project will be documented in this file.

The format is inspired by Keep a Changelog and versioned according to PEP 440.

## [2.3.0] - 2026-04-23

This release continues the stable 2.x line with a more complete import
workflow: clearer template guidance before upload, lightweight structural
preflight before execution, synchronous lifecycle visibility during import, and
compact remediation-oriented payloads after failures.

### Added

- Added additive template UX metadata support through `hint=` and
`example_value=` so generated header comments can provide clearer workbook
input guidance
- Added `ExcelAlchemy.preflight_import(...)` for lightweight structural import
validation before full import execution
- Added `ImportPreflightResult` and `ImportPreflightStatus` as stable public
preflight result types
- Added additive `on_event=` support on `ExcelAlchemy.import_data(...)` for
synchronous import lifecycle callbacks
- Added `build_frontend_remediation_payload(...)` for compact retry-oriented
remediation payloads alongside the existing import result surfaces
- Added a dedicated `WorksheetNotFoundError` exception so sheet-missing
preflight classification does not rely on backend-specific message parsing

### Changed

- Extended the import workflow so applications can combine template guidance,
preflight validation, lifecycle event observation, and remediation payloads
without replacing the existing full import API
- Kept `ExcelAlchemy.import_data(...)` as the full validation and execution
path while clarifying that `preflight_import(...)` is structural only
- Updated storage-backed workbook reading so preflight maps only explicit
worksheet-missing failures to `SHEET_MISSING` and re-raises unrelated
storage/runtime failures
- Refined template comment rendering for single-staff guidance formatting
- Expanded contract coverage for:
- preflight header validation
- missing and extra field handling
- row-count estimation
- import lifecycle event payloads
- remediation payload behavior

### Documentation

- Updated `README.md`, `README-pypi.md`, and onboarding docs to describe the
additive template guidance metadata
- Updated `docs/getting-started.md` with practical preflight usage guidance and
a `preflight -> import` workflow example
- Updated `docs/public-api.md` and `docs/result-objects.md` to document
`preflight_import(...)`, `ImportPreflightResult`, lifecycle callbacks, and
remediation payload helpers
- Updated `docs/architecture.md`, `docs/domain-model.md`, examples, and
reference-app guidance to reflect the broader import workflow story
- Added design plans under `plans/` for:
- template UX metadata v1
- job-friendly import lifecycle events v1
- import preflight v1
- front-end remediation payload v1

## [2.2.8] - 2026-04-05

This release continues the stable 2.x line with a clearer integration reading
Expand Down
29 changes: 26 additions & 3 deletions README-pypi.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ ExcelAlchemy turns Pydantic models into typed workbook contracts:
- render workbook-facing output in `zh-CN` or `en`
- keep storage pluggable through `ExcelStorage`

The current stable release is `2.2.8`, which continues the 2.x line with a clearer integration roadmap, stronger import-failure payload smoke verification, and more direct install-time validation of the FastAPI reference app.
The current stable release is `2.3.0`, which continues the 2.x line with a
more complete import workflow: clearer template guidance before upload,
lightweight structural preflight before execution, synchronous lifecycle
visibility during import, and remediation-oriented payloads after failures.

[GitHub Repository](https://github.com/RayCarterLab/ExcelAlchemy) · [Full README](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/README.md) · [Getting Started](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/getting-started.md) · [Integration Roadmap](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/integration-roadmap.md) · [Result Objects](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/result-objects.md) · [API Response Cookbook](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/api-response-cookbook.md) · [Examples Showcase](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/examples-showcase.md) · [Architecture](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/architecture.md) · [Migration Notes](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/MIGRATIONS.md)
At the top level, that import workflow is:

- template authoring
- preflight gate
- import runtime
- result intelligence
- artifact and delivery

[GitHub Repository](https://github.com/RayCarterLab/ExcelAlchemy) · [Full README](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/README.md) · [Getting Started](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/getting-started.md) · [Integration Roadmap](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/integration-roadmap.md) · [Platform Architecture](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/platform-architecture.md) · [Runtime Model](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/runtime-model.md) · [Integration Blueprints](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/integration-blueprints.md) · [Result Objects](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/result-objects.md) · [API Response Cookbook](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/api-response-cookbook.md) · [Examples Showcase](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/examples-showcase.md) · [Architecture](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/architecture.md) · [Migration Notes](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/MIGRATIONS.md)

## Screenshots

Expand Down Expand Up @@ -69,14 +80,23 @@ class Importer(BaseModel):
email: Annotated[
Email,
Field(min_length=10),
ExcelMeta(label='Email', order=1, hint='Use your work email'),
ExcelMeta(
label='Email',
order=1,
hint='Use your work email',
example_value='alice@company.com',
),
]


alchemy = ExcelAlchemy(ImporterConfig(Importer, locale='en'))
template = alchemy.download_template_artifact(filename='people-template.xlsx')
```

This template metadata is additive: it leaves the worksheet layout alone and
improves the generated header comment with both guidance text and a concrete
example value.

## Example Outputs

These fixed outputs are generated from the repository examples by
Expand Down Expand Up @@ -154,6 +174,9 @@ for configured selection fields.
## Learn More

- [Full project README](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/README.md)
- [Platform architecture](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/platform-architecture.md)
- [Runtime model](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/runtime-model.md)
- [Integration blueprints](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/integration-blueprints.md)
- [Architecture notes](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/architecture.md)
- [Locale policy](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/docs/locale.md)
- [Migration notes](https://github.com/RayCarterLab/ExcelAlchemy/blob/main/MIGRATIONS.md)
141 changes: 138 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
![Lint](https://img.shields.io/badge/lint-ruff-D7FF64)
![Typing](https://img.shields.io/badge/typing-pyright-2C6BED)

[中文 README](README_cn.md) · [About](ABOUT.md) · [Getting Started](docs/getting-started.md) · [Integration Roadmap](docs/integration-roadmap.md) · [Result Objects](docs/result-objects.md) · [API Response Cookbook](docs/api-response-cookbook.md) · [Architecture](docs/architecture.md) · [Examples Showcase](docs/examples-showcase.md) · [Public API](docs/public-api.md) · [Locale Policy](docs/locale.md) · [Limitations](docs/limitations.md) · [Performance](docs/performance.md) · [Changelog](CHANGELOG.md) · [Migration Notes](MIGRATIONS.md)
[中文 README](README_cn.md) · [About](ABOUT.md) · [Getting Started](docs/getting-started.md) · [Integration Roadmap](docs/integration-roadmap.md) · [Platform Architecture](docs/platform-architecture.md) · [Runtime Model](docs/runtime-model.md) · [Integration Blueprints](docs/integration-blueprints.md) · [Result Objects](docs/result-objects.md) · [API Response Cookbook](docs/api-response-cookbook.md) · [Architecture](docs/architecture.md) · [Examples Showcase](docs/examples-showcase.md) · [Public API](docs/public-api.md) · [Locale Policy](docs/locale.md) · [Limitations](docs/limitations.md) · [Performance](docs/performance.md) · [Changelog](CHANGELOG.md) · [Migration Notes](MIGRATIONS.md)

Repository guides: [AGENTS.md](AGENTS.md) · [Repository Map](docs/repo-map.md) · [Domain Model](docs/domain-model.md) · [Invariants](docs/invariants.md) · [Package Guide](src/excelalchemy/README.md) · [Test Guide](tests/README.md) · [Examples Guide](examples/README.md)

Engineering records: [Plans](plans/README.md) · [Technical Debt](tech_debt/README.md) · [ADRs](adr/README.md)

ExcelAlchemy is a schema-driven Python library for Excel import and export workflows.
It turns Pydantic models into typed workbook contracts: generate templates, validate uploads, map failures back to rows
Expand All @@ -16,12 +20,26 @@ This repository is also a design artifact.
It documents a series of deliberate engineering choices: `src/` layout, Pydantic v2 migration, pandas removal,
pluggable storage, `uv`-based workflows, and locale-aware workbook output.

The current stable release is `2.2.8`, which continues the ExcelAlchemy 2.x line with a clearer integration roadmap, stronger import-failure payload smoke verification, and more direct install-time validation of the FastAPI reference app.
The current stable release is `2.3.0`, which continues the ExcelAlchemy 2.x
line with a more complete import workflow: clearer template guidance before
upload, lightweight structural preflight before execution, synchronous
lifecycle visibility during import, and remediation-oriented payloads after
failures.

For the platform-layer architecture of that workflow, see:

- [`docs/platform-architecture.md`](docs/platform-architecture.md)
- [`docs/runtime-model.md`](docs/runtime-model.md)
- [`docs/integration-blueprints.md`](docs/integration-blueprints.md)

## At a Glance

- Build Excel templates directly from typed Pydantic schemas
- Guide users with workbook-facing input hints and examples
- Run lightweight structural preflight checks before full import
- Validate uploaded workbooks and write failures back to rows and cells
- Observe import lifecycle progress through additive callbacks
- Build remediation-oriented payloads for retry workflows
- Keep storage pluggable through `ExcelStorage`
- Render workbook-facing text in `zh-CN` or `en`
- Stay lightweight at runtime with `openpyxl` instead of pandas
Expand Down Expand Up @@ -67,17 +85,126 @@ class Importer(BaseModel):
email: Annotated[
Email,
Field(min_length=10),
ExcelMeta(label='Email', order=1, hint='Use your work email'),
ExcelMeta(
label='Email',
order=1,
hint='Use your work email',
example_value='alice@company.com',
),
]


alchemy = ExcelAlchemy(ImporterConfig(Importer, locale='en'))
template = alchemy.download_template_artifact(filename='people-template.xlsx')
```

This template metadata is additive: it keeps the worksheet layout unchanged and
adds clearer header comments for spreadsheet users, such as a free-form hint
and a concrete example value.

For browser downloads, prefer `template.as_bytes()` with a `Blob`, or return the bytes from your backend with
`Content-Disposition: attachment`. A top-level navigation to a long `data:` URL is less reliable in modern browsers.

## Import Workflow

ExcelAlchemy is designed to work as a product-ready import layer rather than
only a row-validation helper.

The top-level import workflow in the 2.x line is:

- template authoring
- preflight gate
- import runtime
- result intelligence
- artifact and delivery

In practical terms, that usually means:

- generate a template with workbook-facing guidance
- run `preflight_import(...)` as a lightweight structural gate
- run `import_data(..., on_event=...)` for full validation and execution
- inspect `ImportResult`, `CellErrorMap`, and `RowIssueMap`
- build remediation-oriented payloads if the import fails
- deliver template or result workbook artifacts through the configured storage seam

For the platform view and runtime sequence behind this workflow, see:

- [`docs/platform-architecture.md`](docs/platform-architecture.md)
- [`docs/runtime-model.md`](docs/runtime-model.md)
- [`docs/integration-blueprints.md`](docs/integration-blueprints.md)

Use `preflight_import(...)` when you want a fast answer to:

- does the configured sheet exist
- do the workbook headers match the schema
- is the workbook structurally importable

Use `import_data(...)` when you want the full workflow:

- row validation
- create / update callback execution
- result workbook rendering
- structured row and cell failure output

Short example:

```python
from pydantic import BaseModel

from excelalchemy import ExcelAlchemy, Email, FieldMeta, ImporterConfig, Number, String
from excelalchemy.results import build_frontend_remediation_payload


class EmployeeImporter(BaseModel):
full_name: String = FieldMeta(label='Full name', order=1, hint='Use the legal name')
age: Number = FieldMeta(label='Age', order=2)
work_email: Email = FieldMeta(label='Work email', order=3, example_value='alice@company.com')


async def create_employee(row: dict[str, object], context: dict[str, object] | None) -> dict[str, object]:
return row


alchemy = ExcelAlchemy(
ImporterConfig.for_create(
EmployeeImporter,
creator=create_employee,
storage=storage,
locale='en',
)
)

template = alchemy.download_template_artifact(filename='employee-template.xlsx')

preflight = alchemy.preflight_import('employees.xlsx')
if not preflight.is_valid:
response = {'preflight': preflight.to_api_payload()}
else:
events: list[dict[str, object]] = []
result = await alchemy.import_data(
'employees.xlsx',
'employees-result.xlsx',
on_event=events.append,
)

response = {
'result': result.to_api_payload(),
'events': events,
'remediation': build_frontend_remediation_payload(
result=result,
cell_error_map=alchemy.cell_error_map,
row_error_map=alchemy.row_error_map,
),
}
```

This keeps one clear separation:

- template authoring and preflight help before execution
- import runtime handles real validation and persistence
- result intelligence helps API and frontend retry flows after failure
- artifact and delivery expose files and URLs after the run

## When To Use / When Not To Use / Limitations & Gotchas

### When To Use
Expand Down Expand Up @@ -180,6 +307,10 @@ flowchart TD
```

See the full breakdown in [docs/architecture.md](docs/architecture.md).
For the integration-oriented platform view layered above those components, see
[docs/platform-architecture.md](docs/platform-architecture.md),
[docs/runtime-model.md](docs/runtime-model.md), and
[docs/integration-blueprints.md](docs/integration-blueprints.md).

## Workflow

Expand Down Expand Up @@ -258,6 +389,7 @@ Import workflow output:

```text
Employee import workflow completed
Preflight: VALID
Result: SUCCESS
Success rows: 1
Failed rows: 0
Expand Down Expand Up @@ -485,6 +617,9 @@ More detail is documented in [ABOUT.md](ABOUT.md).
- [README.md](README.md): product + design overview
- [README_cn.md](README_cn.md): Chinese usage-oriented guide
- [ABOUT.md](ABOUT.md): engineering rationale and evolution notes
- [docs/platform-architecture.md](docs/platform-architecture.md): import platform capability model
- [docs/runtime-model.md](docs/runtime-model.md): runtime sequence across the import workflow
- [docs/integration-blueprints.md](docs/integration-blueprints.md): backend/frontend integration patterns
- [docs/architecture.md](docs/architecture.md): component map and boundaries
- [docs/limitations.md](docs/limitations.md): practical fit, limitations, and gotchas
- [docs/performance.md](docs/performance.md): operational guidance for large files, memory, and backend guardrails
Expand Down
Loading
Loading