ExcelAlchemy 2.2.8__tar.gz → 2.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/PKG-INFO +15 -3
  2. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/README-pypi.md +14 -2
  3. excelalchemy-2.3.0/src/excelalchemy/README.md +463 -0
  4. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/__init__.py +13 -2
  5. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/boolean.py +1 -0
  6. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/date.py +1 -0
  7. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/date_range.py +1 -0
  8. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/multi_checkbox.py +1 -0
  9. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/number.py +1 -0
  10. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/organization.py +6 -1
  11. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/radio.py +1 -0
  12. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/staff.py +8 -1
  13. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/string.py +1 -0
  14. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/tree.py +6 -1
  15. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/abstract.py +13 -3
  16. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/alchemy.py +27 -4
  17. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/import_session.py +118 -48
  18. excelalchemy-2.3.0/src/excelalchemy/core/preflight.py +97 -0
  19. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/storage_minio.py +6 -2
  20. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/exceptions.py +7 -0
  21. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/i18n/messages.py +3 -0
  22. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/metadata.py +27 -0
  23. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/results.py +301 -0
  24. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/LICENSE +0 -0
  25. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/pyproject.toml +0 -0
  26. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/_primitives/__init__.py +0 -0
  27. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/_primitives/constants.py +0 -0
  28. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/_primitives/deprecation.py +0 -0
  29. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/_primitives/diagnostics.py +0 -0
  30. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/_primitives/header_models.py +0 -0
  31. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/_primitives/identity.py +0 -0
  32. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/_primitives/payloads.py +0 -0
  33. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/artifacts.py +0 -0
  34. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/__init__.py +0 -0
  35. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/base.py +0 -0
  36. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/email.py +0 -0
  37. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/money.py +0 -0
  38. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/number_range.py +0 -0
  39. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/phone_number.py +0 -0
  40. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/codecs/url.py +0 -0
  41. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/config.py +0 -0
  42. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/const.py +0 -0
  43. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/__init__.py +0 -0
  44. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/executor.py +0 -0
  45. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/headers.py +0 -0
  46. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/rendering.py +0 -0
  47. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/rows.py +0 -0
  48. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/schema.py +0 -0
  49. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/storage.py +0 -0
  50. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/storage_protocol.py +0 -0
  51. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/table.py +0 -0
  52. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/core/writer.py +0 -0
  53. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/exc.py +0 -0
  54. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/header_models.py +0 -0
  55. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/helper/__init__.py +0 -0
  56. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/helper/pydantic.py +0 -0
  57. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/i18n/__init__.py +0 -0
  58. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/identity.py +0 -0
  59. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/py.typed +0 -0
  60. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/__init__.py +0 -0
  61. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/abstract.py +0 -0
  62. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/alchemy.py +0 -0
  63. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/field.py +0 -0
  64. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/header.py +0 -0
  65. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/identity.py +0 -0
  66. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/result.py +0 -0
  67. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/__init__.py +0 -0
  68. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/boolean.py +0 -0
  69. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/date.py +0 -0
  70. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/date_range.py +0 -0
  71. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/email.py +0 -0
  72. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/money.py +0 -0
  73. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/multi_checkbox.py +0 -0
  74. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/number.py +0 -0
  75. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/number_range.py +0 -0
  76. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/organization.py +0 -0
  77. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/phone_number.py +0 -0
  78. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/radio.py +0 -0
  79. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/staff.py +0 -0
  80. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/string.py +0 -0
  81. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/tree.py +0 -0
  82. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/types/value/url.py +0 -0
  83. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/util/__init__.py +0 -0
  84. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/util/converter.py +0 -0
  85. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/util/convertor.py +0 -0
  86. {excelalchemy-2.2.8 → excelalchemy-2.3.0}/src/excelalchemy/util/file.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ExcelAlchemy
3
- Version: 2.2.8
3
+ Version: 2.3.0
4
4
  Summary: Schema-driven Python library for typed Excel import/export workflows with Pydantic and locale-aware workbooks.
5
5
  Keywords: excel,openpyxl,pydantic,minio,schema
6
6
  Author: Ray
@@ -49,7 +49,10 @@ ExcelAlchemy turns Pydantic models into typed workbook contracts:
49
49
  - render workbook-facing output in `zh-CN` or `en`
50
50
  - keep storage pluggable through `ExcelStorage`
51
51
 
52
- 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.
52
+ The current stable release is `2.3.0`, which continues the 2.x line with a
53
+ more complete import workflow: clearer template guidance before upload,
54
+ lightweight structural preflight before execution, synchronous lifecycle
55
+ visibility during import, and remediation-oriented payloads after failures.
53
56
 
54
57
  [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)
55
58
 
@@ -108,7 +111,12 @@ class Importer(BaseModel):
108
111
  email: Annotated[
109
112
  Email,
110
113
  Field(min_length=10),
111
- ExcelMeta(label='Email', order=1, hint='Use your work email'),
114
+ ExcelMeta(
115
+ label='Email',
116
+ order=1,
117
+ hint='Use your work email',
118
+ example_value='alice@company.com',
119
+ ),
112
120
  ]
113
121
 
114
122
 
@@ -116,6 +124,10 @@ alchemy = ExcelAlchemy(ImporterConfig(Importer, locale='en'))
116
124
  template = alchemy.download_template_artifact(filename='people-template.xlsx')
117
125
  ```
118
126
 
127
+ This template metadata is additive: it leaves the worksheet layout alone and
128
+ improves the generated header comment with both guidance text and a concrete
129
+ example value.
130
+
119
131
  ## Example Outputs
120
132
 
121
133
  These fixed outputs are generated from the repository examples by
@@ -10,7 +10,10 @@ ExcelAlchemy turns Pydantic models into typed workbook contracts:
10
10
  - render workbook-facing output in `zh-CN` or `en`
11
11
  - keep storage pluggable through `ExcelStorage`
12
12
 
13
- 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.
13
+ The current stable release is `2.3.0`, which continues the 2.x line with a
14
+ more complete import workflow: clearer template guidance before upload,
15
+ lightweight structural preflight before execution, synchronous lifecycle
16
+ visibility during import, and remediation-oriented payloads after failures.
14
17
 
15
18
  [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)
16
19
 
@@ -69,7 +72,12 @@ class Importer(BaseModel):
69
72
  email: Annotated[
70
73
  Email,
71
74
  Field(min_length=10),
72
- ExcelMeta(label='Email', order=1, hint='Use your work email'),
75
+ ExcelMeta(
76
+ label='Email',
77
+ order=1,
78
+ hint='Use your work email',
79
+ example_value='alice@company.com',
80
+ ),
73
81
  ]
74
82
 
75
83
 
@@ -77,6 +85,10 @@ alchemy = ExcelAlchemy(ImporterConfig(Importer, locale='en'))
77
85
  template = alchemy.download_template_artifact(filename='people-template.xlsx')
78
86
  ```
79
87
 
88
+ This template metadata is additive: it leaves the worksheet layout alone and
89
+ improves the generated header comment with both guidance text and a concrete
90
+ example value.
91
+
80
92
  ## Example Outputs
81
93
 
82
94
  These fixed outputs are generated from the repository examples by
@@ -0,0 +1,463 @@
1
+ # `src/excelalchemy/` Package Guide
2
+
3
+ This file explains the internal structure of the main package directory.
4
+ It is meant for developers and AI agents who need to change implementation details without confusing public API, compatibility layers, and internal collaborators.
5
+
6
+ ## Related docs
7
+
8
+ - [../../README.md](../../README.md) for the public-facing overview.
9
+ - [../../AGENTS.md](../../AGENTS.md) for repository-local editing guidance.
10
+ - [../../docs/repo-map.md](../../docs/repo-map.md) for top-level repository navigation.
11
+ - [../../docs/domain-model.md](../../docs/domain-model.md) for the main concepts implemented here.
12
+ - [../../docs/invariants.md](../../docs/invariants.md) for important behavioral constraints.
13
+ - [../../tests/README.md](../../tests/README.md) for where this package's behavior is protected.
14
+
15
+ ## Role of This Package
16
+
17
+ - `src/excelalchemy/` is the main library package.
18
+ - It contains:
19
+ - the stable public surface used by application code
20
+ - the internal orchestration that implements import, export, template generation, rendering, and storage integration
21
+ - compatibility modules retained for the 2.x line
22
+ - The package is organized around a small public facade and a set of focused internal collaborators.
23
+
24
+ ## High-Level Package Structure
25
+
26
+ - `__init__.py`
27
+ - Main public re-export surface.
28
+ - If application-facing imports change, start here.
29
+ - `config.py`
30
+ - Public workflow configuration types.
31
+ - `metadata.py`
32
+ - Public metadata declarations plus the internal layered field-metadata model.
33
+ - `results.py`
34
+ - Public result models and API-friendly error maps.
35
+ - `exceptions.py`
36
+ - Public exception types.
37
+ - `artifacts.py`
38
+ - Public workbook artifact wrapper.
39
+ - `codecs/`
40
+ - Public field codecs and codec base classes.
41
+ - `core/`
42
+ - Internal workflow orchestration and execution.
43
+ - `helper/`
44
+ - Internal adapter layer, currently centered on Pydantic integration.
45
+ - `i18n/`
46
+ - Internal message and locale handling.
47
+ - `_primitives/`
48
+ - Internal low-level types, constants, payload aliases, diagnostics, and deprecation helpers.
49
+ - `types/`, `exc.py`, `identity.py`, `header_models.py`, `const.py`, `util/convertor.py`
50
+ - Compatibility-oriented modules retained in the 2.x line.
51
+
52
+ ## Public Surface vs Internal Implementation
53
+
54
+ ### Public surface
55
+
56
+ These modules are the stable public entry points documented in `docs/public-api.md`:
57
+
58
+ - `src/excelalchemy/__init__.py`
59
+ - `src/excelalchemy/config.py`
60
+ - `src/excelalchemy/metadata.py`
61
+ - `src/excelalchemy/results.py`
62
+ - `src/excelalchemy/exceptions.py`
63
+ - `src/excelalchemy/codecs/`
64
+ - `src/excelalchemy/artifacts.py`
65
+
66
+ ### Internal implementation
67
+
68
+ These modules implement behavior but are not the recommended import paths for application code:
69
+
70
+ - `src/excelalchemy/core/`
71
+ - `src/excelalchemy/helper/`
72
+ - `src/excelalchemy/i18n/`
73
+ - `src/excelalchemy/_primitives/`
74
+
75
+ ### Compatibility-only surface
76
+
77
+ These exist to support the 2.x line and should not be treated as preferred implementation entry points for new work:
78
+
79
+ - `src/excelalchemy/types/`
80
+ - `src/excelalchemy/exc.py`
81
+ - `src/excelalchemy/identity.py`
82
+ - `src/excelalchemy/header_models.py`
83
+ - `src/excelalchemy/const.py`
84
+ - `src/excelalchemy/util/convertor.py`
85
+
86
+ ## Major Modules and Responsibilities
87
+
88
+ ### Public-facing root modules
89
+
90
+ - `src/excelalchemy/__init__.py`
91
+ - Re-exports `ExcelAlchemy`, configs, codecs, result types, exception types, and common identity/value types.
92
+ - Changes here affect top-level user imports directly.
93
+
94
+ - `src/excelalchemy/config.py`
95
+ - Defines:
96
+ - `ExcelMode`
97
+ - `ImportMode`
98
+ - `ImporterConfig`
99
+ - `ExporterConfig`
100
+ - normalized schema/behavior/storage option groupings
101
+ - Also contains legacy Minio compatibility handling and deprecation warnings.
102
+
103
+ - `src/excelalchemy/metadata.py`
104
+ - Defines public declaration helpers:
105
+ - `FieldMeta(...)`
106
+ - `ExcelMeta(...)`
107
+ - Also defines the internal metadata layers behind `FieldMetaInfo`:
108
+ - `DeclaredFieldMeta`
109
+ - `RuntimeFieldBinding`
110
+ - `WorkbookPresentationMeta`
111
+ - `ImportConstraints`
112
+ - This file is central when changing field declaration behavior, workbook comments, formatting hints, or constraint overlay rules.
113
+
114
+ - `src/excelalchemy/results.py`
115
+ - Defines public result objects:
116
+ - `ImportResult`
117
+ - `ValidateHeaderResult`
118
+ - `ValidateResult`
119
+ - `ValidateRowResult`
120
+ - `CellErrorMap`
121
+ - `RowIssueMap`
122
+ - This is the main file for API payload shape and structured error access.
123
+
124
+ - `src/excelalchemy/exceptions.py`
125
+ - Defines the public exception model:
126
+ - `ExcelAlchemyError`
127
+ - `ExcelCellError`
128
+ - `ExcelRowError`
129
+ - `ProgrammaticError`
130
+ - `ConfigError`
131
+
132
+ - `src/excelalchemy/artifacts.py`
133
+ - Defines `ExcelArtifact`, which wraps rendered workbook content as bytes, base64, or a data URL.
134
+
135
+ ### `core/` internal orchestration
136
+
137
+ - `src/excelalchemy/core/alchemy.py`
138
+ - Main facade implementation.
139
+ - Builds layout and storage, exposes the top-level workflow methods, and surfaces inspection properties like `worksheet_table` and `cell_error_map`.
140
+ - This is the first internal file to inspect when changing how the facade behaves.
141
+
142
+ - `src/excelalchemy/core/import_session.py`
143
+ - Owns one import run’s runtime state.
144
+ - Tracks:
145
+ - workbook load state
146
+ - header table
147
+ - worksheet table
148
+ - issue maps
149
+ - execution counts
150
+ - result rendering state
151
+ - `ImportSessionSnapshot`
152
+ - This is the main import lifecycle owner.
153
+
154
+ - `src/excelalchemy/core/schema.py`
155
+ - Converts extracted field metadata into `ExcelSchemaLayout`.
156
+ - Responsible for:
157
+ - layout ordering
158
+ - unique label/key indexing
159
+ - composite field expansion
160
+ - merged-header detection for selected output keys
161
+
162
+ - `src/excelalchemy/core/headers.py`
163
+ - Header parsing and header validation.
164
+ - Responsible for:
165
+ - detecting simple vs merged headers
166
+ - normalizing parsed headers into `ExcelHeader` objects
167
+ - comparing workbook headers against schema layout
168
+
169
+ - `src/excelalchemy/core/rows.py`
170
+ - Row reconstruction and issue tracking.
171
+ - `RowAggregator` groups flattened worksheet data back into model-shaped payloads.
172
+ - `ImportIssueTracker` maps row/cell failures back to workbook coordinates and prepends result columns.
173
+
174
+ - `src/excelalchemy/core/executor.py`
175
+ - Dispatches the actual import execution path.
176
+ - Responsible for:
177
+ - choosing create/update/create-or-update behavior
178
+ - validating reconstructed payloads
179
+ - invoking configured callbacks
180
+ - mapping failures into row/cell issues
181
+
182
+ - `src/excelalchemy/core/rendering.py`
183
+ - High-level rendering entry points for templates, exports, and import result workbooks.
184
+
185
+ - `src/excelalchemy/core/writer.py`
186
+ - Lower-level workbook writing details:
187
+ - comments
188
+ - fills/colors
189
+ - workbook rows/cells
190
+ - result/reason columns
191
+
192
+ - `src/excelalchemy/core/storage_protocol.py`
193
+ - Defines the `ExcelStorage` protocol.
194
+ - This is the main storage extension boundary.
195
+
196
+ - `src/excelalchemy/core/storage.py`
197
+ - Resolves configured storage into a concrete gateway.
198
+ - Also defines the missing-storage fallback path.
199
+
200
+ - `src/excelalchemy/core/storage_minio.py`
201
+ - Built-in Minio-backed storage implementation.
202
+
203
+ - `src/excelalchemy/core/table.py`
204
+ - Defines `WorksheetTable`, `WorksheetRow`, and related helpers.
205
+ - This is the internal table abstraction used instead of pandas.
206
+
207
+ ### `codecs/` field behavior
208
+
209
+ - `src/excelalchemy/codecs/base.py`
210
+ - Defines:
211
+ - `ExcelFieldCodec`
212
+ - `CompositeExcelFieldCodec`
213
+ - fallback logging helpers
214
+ - Start here when changing the codec contract itself.
215
+
216
+ - `src/excelalchemy/codecs/*.py`
217
+ - Built-in concrete field codecs such as:
218
+ - `string.py`
219
+ - `number.py`
220
+ - `date.py`
221
+ - `date_range.py`
222
+ - `email.py`
223
+ - `phone_number.py`
224
+ - `money.py`
225
+ - `radio.py`
226
+ - `multi_checkbox.py`
227
+ - `organization.py`
228
+ - `staff.py`
229
+ - `tree.py`
230
+ - `url.py`
231
+
232
+ ### Adapter, i18n, and primitive helpers
233
+
234
+ - `src/excelalchemy/helper/pydantic.py`
235
+ - Isolates the Pydantic boundary.
236
+ - Responsible for:
237
+ - extracting model metadata
238
+ - resolving codec types
239
+ - normalizing validation messages
240
+ - mapping Pydantic validation output to `ExcelCellError` and `ExcelRowError`
241
+
242
+ - `src/excelalchemy/i18n/messages.py`
243
+ - Central message lookup and locale handling.
244
+ - Important when changing workbook-facing text, runtime error text, or locale policy.
245
+
246
+ - `src/excelalchemy/_primitives/constants.py`
247
+ - Internal constants and enum-like definitions used across the package.
248
+
249
+ - `src/excelalchemy/_primitives/identity.py`
250
+ - Internal typed wrappers for labels, keys, row indexes, column indexes, URLs, and related string-like identifiers.
251
+
252
+ - `src/excelalchemy/_primitives/payloads.py`
253
+ - Shared payload type aliases for import/export/data-converter/callback paths.
254
+
255
+ - `src/excelalchemy/_primitives/diagnostics.py`
256
+ - Developer-facing diagnostic logging helpers.
257
+
258
+ - `src/excelalchemy/_primitives/deprecation.py`
259
+ - Deprecation warning helpers used by compatibility modules.
260
+
261
+ - `src/excelalchemy/_primitives/header_models.py`
262
+ - Internal parsed-header model objects.
263
+
264
+ ## Major Internal Flows
265
+
266
+ ### Import validation flow
267
+
268
+ The import path is implemented roughly in this order:
269
+
270
+ 1. `src/excelalchemy/core/alchemy.py`
271
+ - `ExcelAlchemy.import_data(...)` creates a new import session.
272
+ 2. `src/excelalchemy/core/import_session.py`
273
+ - loads workbook data through storage
274
+ - builds header and worksheet state
275
+ 3. `src/excelalchemy/core/headers.py`
276
+ - parses headers
277
+ - validates headers against the schema layout
278
+ 4. `src/excelalchemy/core/rows.py`
279
+ - reconstructs model-shaped row payloads
280
+ 5. `src/excelalchemy/core/executor.py`
281
+ - validates and dispatches create/update/upsert logic
282
+ 6. `src/excelalchemy/helper/pydantic.py`
283
+ - adapts Pydantic validation into ExcelAlchemy issues
284
+ 7. `src/excelalchemy/core/rows.py`
285
+ - records row/cell failures in workbook coordinates
286
+ 8. `src/excelalchemy/core/rendering.py` and `src/excelalchemy/core/writer.py`
287
+ - render the import result workbook when rows fail
288
+ 9. `src/excelalchemy/results.py`
289
+ - exposes the final result through `ImportResult`, `CellErrorMap`, and `RowIssueMap`
290
+
291
+ ### Template generation flow
292
+
293
+ The template path is implemented roughly in this order:
294
+
295
+ 1. `src/excelalchemy/core/alchemy.py`
296
+ - selects output keys and header shape
297
+ 2. `src/excelalchemy/core/schema.py`
298
+ - provides ordered layout and merged-header decisions
299
+ 3. `src/excelalchemy/codecs/`
300
+ - provide comments, display formatting, and field-specific workbook semantics
301
+ 4. `src/excelalchemy/core/rendering.py`
302
+ 5. `src/excelalchemy/core/writer.py`
303
+ - produce the workbook output
304
+ 6. `src/excelalchemy/artifacts.py`
305
+ - wraps the output when the artifact API is used
306
+
307
+ ### Export flow
308
+
309
+ The export path is implemented roughly in this order:
310
+
311
+ 1. `src/excelalchemy/core/alchemy.py`
312
+ - accepts export rows and selected keys
313
+ 2. `src/excelalchemy/core/schema.py`
314
+ - resolves output layout and merged-header needs
315
+ 3. `src/excelalchemy/codecs/`
316
+ - format workbook-facing values
317
+ 4. `src/excelalchemy/core/rendering.py`
318
+ 5. `src/excelalchemy/core/writer.py`
319
+ 6. `src/excelalchemy/core/storage_protocol.py` and `src/excelalchemy/core/storage.py`
320
+ - are used only when the upload path is chosen
321
+
322
+ ### Storage integration flow
323
+
324
+ Storage-related behavior is split into three concerns:
325
+
326
+ - contract:
327
+ - `src/excelalchemy/core/storage_protocol.py`
328
+ - resolution:
329
+ - `src/excelalchemy/core/storage.py`
330
+ - built-in Minio backend:
331
+ - `src/excelalchemy/core/storage_minio.py`
332
+
333
+ The recommended 2.x design is:
334
+
335
+ - config holds `storage=...`
336
+ - `build_storage_gateway(...)` resolves it
337
+ - import reads workbook data as `WorksheetTable`
338
+ - export/import-result uploads return a URL through the storage implementation
339
+ - custom storage readers currently use `src/excelalchemy/core/table.py` for that `WorksheetTable` contract
340
+
341
+ ## Where To Look When Changing Specific Behavior
342
+
343
+ ### Changing public API behavior
344
+
345
+ Start here:
346
+
347
+ - `src/excelalchemy/__init__.py`
348
+ - `src/excelalchemy/config.py`
349
+ - `src/excelalchemy/metadata.py`
350
+ - `src/excelalchemy/results.py`
351
+ - `src/excelalchemy/exceptions.py`
352
+ - `docs/public-api.md`
353
+ - `MIGRATIONS.md`
354
+ - `tests/contracts/`
355
+
356
+ Use extra caution when changing:
357
+
358
+ - exported names
359
+ - config constructor behavior
360
+ - result payload shape
361
+ - exception wording or exception type mapping
362
+ - compatibility aliases
363
+
364
+ ### Changing import validation behavior
365
+
366
+ Start here:
367
+
368
+ - `src/excelalchemy/core/import_session.py`
369
+ - `src/excelalchemy/core/headers.py`
370
+ - `src/excelalchemy/core/rows.py`
371
+ - `src/excelalchemy/core/executor.py`
372
+ - `src/excelalchemy/helper/pydantic.py`
373
+ - `src/excelalchemy/results.py`
374
+ - `tests/contracts/test_import_contract.py`
375
+ - `tests/contracts/test_core_components_contract.py`
376
+ - `tests/contracts/test_pydantic_contract.py`
377
+
378
+ Typical examples:
379
+
380
+ - header validation rules
381
+ - row reconstruction
382
+ - Pydantic error mapping
383
+ - create/update/upsert behavior
384
+ - result-workbook error placement
385
+
386
+ ### Changing export or template generation behavior
387
+
388
+ Start here:
389
+
390
+ - `src/excelalchemy/core/alchemy.py`
391
+ - `src/excelalchemy/core/schema.py`
392
+ - `src/excelalchemy/core/rendering.py`
393
+ - `src/excelalchemy/core/writer.py`
394
+ - `src/excelalchemy/codecs/`
395
+ - `tests/contracts/test_template_contract.py`
396
+ - `tests/contracts/test_export_contract.py`
397
+
398
+ Typical examples:
399
+
400
+ - workbook comments
401
+ - merged headers
402
+ - selected output keys
403
+ - workbook-facing display formatting
404
+ - artifact generation
405
+
406
+ ### Changing storage integration behavior
407
+
408
+ Start here:
409
+
410
+ - `src/excelalchemy/core/storage_protocol.py`
411
+ - `src/excelalchemy/core/storage.py`
412
+ - `src/excelalchemy/core/storage_minio.py`
413
+ - `src/excelalchemy/config.py`
414
+ - `examples/custom_storage.py`
415
+ - `tests/contracts/test_storage_contract.py`
416
+ - `tests/unit/test_config_options.py`
417
+
418
+ Typical examples:
419
+
420
+ - storage contract shape
421
+ - default gateway selection
422
+ - missing-storage behavior
423
+ - Minio compatibility behavior
424
+ - upload payload expectations
425
+
426
+ ### Changing locale-aware output behavior
427
+
428
+ Start here:
429
+
430
+ - `src/excelalchemy/i18n/messages.py`
431
+ - `src/excelalchemy/metadata.py`
432
+ - `src/excelalchemy/core/alchemy.py`
433
+ - `src/excelalchemy/core/writer.py`
434
+ - `docs/locale.md`
435
+ - `tests/contracts/test_template_contract.py`
436
+ - `tests/contracts/test_import_contract.py`
437
+
438
+ Typical examples:
439
+
440
+ - workbook instruction text
441
+ - header comments
442
+ - result/reason column labels
443
+ - row status text
444
+ - fallback locale behavior
445
+
446
+ ## Implementation Cautions
447
+
448
+ - Do not treat compatibility modules under `src/excelalchemy/types/` and the root compatibility shims as preferred edit points for new behavior.
449
+ - Do not reintroduce pandas-style assumptions into the runtime path; this package now uses `WorksheetTable`.
450
+ - Do not hard-wire Minio into core workflow logic; storage is intentionally abstracted behind `ExcelStorage`.
451
+ - Treat `src/excelalchemy/core/table.py` as a narrow extension seam for current 2.x storage integrations, not as a general application import surface.
452
+ - If you change result payload shape, inspect:
453
+ - `src/excelalchemy/results.py`
454
+ - `docs/result-objects.md`
455
+ - `docs/api-response-cookbook.md`
456
+ - `scripts/smoke_api_payload_snapshot.py`
457
+ - `files/example-outputs/import-failure-api-payload.json`
458
+ - If you change docs-visible example behavior, inspect:
459
+ - `examples/`
460
+ - `files/example-outputs/`
461
+ - `scripts/generate_example_output_assets.py`
462
+ - `scripts/smoke_examples.py`
463
+ - `scripts/smoke_docs_assets.py`
@@ -1,6 +1,6 @@
1
1
  """A Python Library for Reading and Writing Excel Files"""
2
2
 
3
- __version__ = '2.2.8'
3
+ __version__ = '2.3.0'
4
4
  from excelalchemy._primitives.constants import CharacterSet, DataRangeOption, DateFormat, Option
5
5
  from excelalchemy._primitives.deprecation import ExcelAlchemyDeprecationWarning
6
6
  from excelalchemy._primitives.identity import (
@@ -45,7 +45,13 @@ from excelalchemy.codecs.url import Url, UrlCodec
45
45
  from excelalchemy.config import ExporterConfig, ImporterConfig, ImportMode
46
46
  from excelalchemy.core.alchemy import ExcelAlchemy
47
47
  from excelalchemy.core.storage_protocol import ExcelStorage
48
- from excelalchemy.exceptions import ConfigError, ExcelCellError, ExcelRowError, ProgrammaticError
48
+ from excelalchemy.exceptions import (
49
+ ConfigError,
50
+ ExcelCellError,
51
+ ExcelRowError,
52
+ ProgrammaticError,
53
+ WorksheetNotFoundError,
54
+ )
49
55
  from excelalchemy.helper.pydantic import extract_pydantic_model
50
56
  from excelalchemy.metadata import ExcelMeta, FieldMeta, PatchFieldMeta
51
57
  from excelalchemy.results import (
@@ -53,6 +59,8 @@ from excelalchemy.results import (
53
59
  CellIssueRecord,
54
60
  CodeIssueSummary,
55
61
  FieldIssueSummary,
62
+ ImportPreflightResult,
63
+ ImportPreflightStatus,
56
64
  ImportResult,
57
65
  RowIssueMap,
58
66
  RowIssueRecord,
@@ -94,6 +102,8 @@ __all__ = [
94
102
  'FieldIssueSummary',
95
103
  'FieldMeta',
96
104
  'ImportMode',
105
+ 'ImportPreflightResult',
106
+ 'ImportPreflightStatus',
97
107
  'ImportResult',
98
108
  'ImporterConfig',
99
109
  'Key',
@@ -140,6 +150,7 @@ __all__ = [
140
150
  'ValidateHeaderResult',
141
151
  'ValidateResult',
142
152
  'ValidateRowResult',
153
+ 'WorksheetNotFoundError',
143
154
  'extract_pydantic_model',
144
155
  'flatten',
145
156
  ]
@@ -39,6 +39,7 @@ class Boolean(ExcelFieldCodec):
39
39
  [
40
40
  declared.comment_required,
41
41
  presentation.comment_hint,
42
+ *([presentation.comment_example] if presentation.comment_example else []),
42
43
  ]
43
44
  )
44
45
 
@@ -41,6 +41,7 @@ class Date(ExcelFieldCodec, datetime):
41
41
  presentation.comment_date_format,
42
42
  presentation.comment_date_range_option,
43
43
  presentation.comment_hint,
44
+ *([presentation.comment_example] if presentation.comment_example else []),
44
45
  ]
45
46
  )
46
47
 
@@ -62,6 +62,7 @@ class DateRange(CompositeExcelFieldCodec):
62
62
  declared.comment_required,
63
63
  presentation.comment_date_format,
64
64
  dmsg(MessageKey.COMMENT_DATE_RANGE_START_NOT_AFTER_END, extra_hint=presentation.hint or ''),
65
+ *([presentation.comment_example] if presentation.comment_example else []),
65
66
  ]
66
67
  )
67
68
 
@@ -60,6 +60,7 @@ class MultiCheckbox(ExcelFieldCodec, list[str]):
60
60
  presentation.comment_options,
61
61
  dmsg(MessageKey.COMMENT_SELECTION_MODE, value=dmsg(MessageKey.COMMENT_SELECTION_VALUE_MULTI)),
62
62
  presentation.comment_hint,
63
+ *([presentation.comment_example] if presentation.comment_example else []),
63
64
  ]
64
65
  )
65
66
 
@@ -56,6 +56,7 @@ class Number(Decimal, ExcelFieldCodec):
56
56
  presentation.comment_fraction_digits,
57
57
  dmsg(MessageKey.COMMENT_NUMBER_INPUT_RANGE, value=cls.__get_range_description__(field_meta)),
58
58
  presentation.comment_unit,
59
+ *([presentation.comment_example] if presentation.comment_example else []),
59
60
  ]
60
61
  )
61
62
 
@@ -28,7 +28,11 @@ class SingleOrganization(Radio):
28
28
  else MessageKey.COMMENT_REQUIRED_VALUE_OPTIONAL
29
29
  )
30
30
  return '\n'.join(
31
- [dmsg(MessageKey.COMMENT_REQUIRED, value=dmsg(value_key)), dmsg(MessageKey.COMMENT_HINT, value=extra_hint)]
31
+ [
32
+ dmsg(MessageKey.COMMENT_REQUIRED, value=dmsg(value_key)),
33
+ dmsg(MessageKey.COMMENT_HINT, value=extra_hint),
34
+ *([presentation.comment_example] if presentation.comment_example else []),
35
+ ]
32
36
  )
33
37
 
34
38
  @classmethod
@@ -64,6 +68,7 @@ class MultiOrganization(MultiCheckbox):
64
68
  [
65
69
  declared.comment_required,
66
70
  dmsg(MessageKey.COMMENT_HINT, value=presentation.hint or dmsg(MessageKey.MULTI_ORGANIZATION_HINT)),
71
+ *([presentation.comment_example] if presentation.comment_example else []),
67
72
  ]
68
73
  )
69
74
 
@@ -61,6 +61,7 @@ class Radio(ExcelFieldCodec, str):
61
61
  presentation.comment_options,
62
62
  dmsg(MessageKey.COMMENT_SELECTION_MODE, value=dmsg(MessageKey.COMMENT_SELECTION_VALUE_SINGLE)),
63
63
  presentation.comment_hint,
64
+ *([presentation.comment_example] if presentation.comment_example else []),
64
65
  ]
65
66
  )
66
67