jxcel 0.1.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.
- jxcel-0.1.0/LICENSE +21 -0
- jxcel-0.1.0/MANIFEST.in +5 -0
- jxcel-0.1.0/PKG-INFO +263 -0
- jxcel-0.1.0/README.md +239 -0
- jxcel-0.1.0/RELEASE_NOTES.md +61 -0
- jxcel-0.1.0/pyproject.toml +43 -0
- jxcel-0.1.0/setup.cfg +4 -0
- jxcel-0.1.0/src/jxcel/__init__.py +3 -0
- jxcel-0.1.0/src/jxcel/cli.py +420 -0
- jxcel-0.1.0/src/jxcel/discovery.py +130 -0
- jxcel-0.1.0/src/jxcel/jsonio.py +168 -0
- jxcel-0.1.0/src/jxcel/planning.py +848 -0
- jxcel-0.1.0/src/jxcel/reporting.py +357 -0
- jxcel-0.1.0/src/jxcel/workbook.py +928 -0
- jxcel-0.1.0/src/jxcel.egg-info/PKG-INFO +263 -0
- jxcel-0.1.0/src/jxcel.egg-info/SOURCES.txt +18 -0
- jxcel-0.1.0/src/jxcel.egg-info/dependency_links.txt +1 -0
- jxcel-0.1.0/src/jxcel.egg-info/entry_points.txt +2 -0
- jxcel-0.1.0/src/jxcel.egg-info/requires.txt +1 -0
- jxcel-0.1.0/src/jxcel.egg-info/top_level.txt +1 -0
jxcel-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mahmoud Ehab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
jxcel-0.1.0/MANIFEST.in
ADDED
jxcel-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jxcel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A cross-platform CLI for converting JSON datasets into Excel workbooks
|
|
5
|
+
Author: Mahmoud Ehab
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Source, https://github.com/abutaha7000d/jxcel
|
|
8
|
+
Keywords: json,excel,xlsx,cli,converter
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: openpyxl<4,>=3.1.5
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# jxcel
|
|
26
|
+
|
|
27
|
+
`jxcel` is a cross-platform command-line application for converting JSON files into formatted Excel `.xlsx` workbooks. It discovers tabular object arrays in general JSON documents; it has no fixed columns or domain-specific assumptions.
|
|
28
|
+
|
|
29
|
+
## Development status
|
|
30
|
+
|
|
31
|
+
The converter is functional. JSON loading and validation, dataset discovery, schema planning and value preparation, workbook generation with validated publication, and command-line integration are implemented in `src/jxcel/`. The package has not been published.
|
|
32
|
+
|
|
33
|
+
Current cross-platform release verification passed in GitHub Actions run [41933979297](https://github.com/AbuTaha7000D/jxcel/actions/runs/41933979297) on commit `6d2e5e3f3f0b9cb4a0b7985847a496be744cc1e7`. All 12 Linux, Windows, and macOS × Python 3.11–3.14 jobs passed. Each ran the full 309-test suite and 25 CLI acceptance checks; Windows skipped three POSIX-only permission tests. The workflow also built and inspected wheel and source distributions, installed them in separate environments, and verified pipx installation.
|
|
34
|
+
|
|
35
|
+
The earlier Phase 8 run [41666703215](https://github.com/AbuTaha7000D/jxcel/actions/runs/41666703215) validated commit `f351669e6ed5ef072eb888e9a2f2f85401832210` on Windows and macOS with the original 299-test suite.
|
|
36
|
+
|
|
37
|
+
Release notes for version `0.1.0` are in [RELEASE_NOTES.md](https://github.com/AbuTaha7000D/jxcel/blob/main/RELEASE_NOTES.md).
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- Python 3.11 or newer is declared. Python 3.11, 3.12, 3.13, and 3.14 have all been exercised on Ubuntu 24.04, Windows 2025, and macOS 15 in run 41933979297.
|
|
42
|
+
- Runtime dependencies: the Python standard library and `openpyxl`.
|
|
43
|
+
- Linux, Windows, and macOS are intended targets. All three have been exercised: Linux locally, and Windows and macOS on GitHub-hosted runners in Phase 8.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
A package distribution is not published yet. From a local checkout:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m pip install .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This command was verified on Linux in an isolated virtual environment and on the Windows and macOS CI runners in Phase 8. The build uses isolation, so it needs access to a package index or a populated build-dependency cache; an offline install fails if the required `setuptools` build dependency is unavailable.
|
|
54
|
+
|
|
55
|
+
An isolated installation from the checkout was also verified with `pipx`: 1.18.11 on Linux and 1.18.12 on the Windows and macOS CI runners.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pipx install .
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Both commands install a `jxcel` command that points at `jxcel.cli:main`. Command availability, the isolated `pipx` command path, and execution from outside the checkout were verified on Linux, Windows, and macOS.
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
Exactly one input source is required: positional `INPUT` or `-i/--input PATH`.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
jxcel data.json
|
|
69
|
+
jxcel -i data.json
|
|
70
|
+
jxcel /path/to/data.json
|
|
71
|
+
jxcel -i /path/to/data.json -o result.xlsx
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
By default, the output is written beside the input with an `.xlsx` suffix, so `data.json` produces `data.xlsx`. The output parent directory must already exist; jxcel never creates directories.
|
|
75
|
+
|
|
76
|
+
Existing output files are preserved unless `--overwrite` is supplied:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
jxcel data.json --overwrite
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Without `--overwrite`, an existing destination is an error. With it, jxcel builds and validates a temporary workbook first, then replaces the destination through the approved publication path. jxcel does not claim crash durability or stronger atomicity than the operating system and filesystem provide.
|
|
83
|
+
|
|
84
|
+
No-overwrite publication creates the destination with a same-directory hard link, so the temporary and destination files stay on one filesystem. Some filesystems do not support hard links, including FAT32/exFAT and some network or container mounts. On such filesystems, no-overwrite publication fails with exit status 1 and an explicit error. jxcel does not fall back to rename or replace, because that fallback could destroy a destination created concurrently. Overwrite publication uses the operating system's replace operation and depends on that filesystem's support. Hard-link behavior was exercised on Linux `tmpfs` and on the Windows and macOS runner temporary filesystems; other filesystem types, including FAT32/exFAT and network mounts, were not tested.
|
|
85
|
+
|
|
86
|
+
## Input validation
|
|
87
|
+
|
|
88
|
+
jxcel reads the input as UTF-8 and accepts an optional UTF-8 BOM. Empty or whitespace-only files, malformed JSON, invalid UTF-8, and trailing content after the JSON value are rejected with exit status 1 and a path-aware error. Malformed JSON reports the line and column; invalid UTF-8 reports the byte offset.
|
|
89
|
+
|
|
90
|
+
Object keys must be unique at every level. Duplicate keys are rejected even when one is written with an escape such as `\u0061`, because it decodes to the same key; the same key in separate objects is allowed. `NaN`, `Infinity`, and `-Infinity` are rejected as non-standard JSON constants. JSON real numbers must be finite: tokens that overflow a Python float or underflow a nonzero value to zero are rejected. Integers decode as Python integers, subject to Python's configured integer-string conversion limit.
|
|
91
|
+
|
|
92
|
+
The loader does not restrict the JSON root category: objects, arrays, strings, numbers, booleans, and `null` are all accepted, subject to the validation above. Dataset discovery then treats a root that is not an object or array as `unsupported_root`. Discovery reports an empty array outside dataset records as `empty_array`, and an empty object outside arrays as `empty_object`; neither is an exportable dataset. `--list` and `--preview` report these findings and exit 0; `--dry-run` and conversion exit 1 when no workbook can be produced.
|
|
93
|
+
|
|
94
|
+
## Inspection modes
|
|
95
|
+
|
|
96
|
+
The following modes never create a workbook, temporary workbook, or output directory. They are safe to run against an existing destination.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
jxcel data.json --list
|
|
100
|
+
jxcel data.json --preview
|
|
101
|
+
jxcel data.json --preview --preview-rows 10
|
|
102
|
+
jxcel data.json --dry-run
|
|
103
|
+
jxcel data.json --preview --dry-run
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- `--list` builds schemas, reports dataset pointers, record counts, available columns, effective columns after mappings, non-exportable reasons, and unsupported structures. It performs schema-only validation and does not scan cell values for exportability.
|
|
107
|
+
- `--preview` displays bounded records, respecting dataset and column selection. It prepares only the displayed rows and does not export-validate values outside the preview window. `--preview-rows` defaults to 5 and must be a positive integer.
|
|
108
|
+
- `--dry-run` performs full export validation and shows the selected datasets, effective columns, destination, warnings, and unsupported structures. It validates the destination read-only, so an existing file without `--overwrite` or a missing parent directory fails with exit status 1.
|
|
109
|
+
- `--preview --dry-run` combines both: the full export plan is built once and preview rows come from its validated snapshot.
|
|
110
|
+
|
|
111
|
+
`--list` cannot be combined with `--preview` or `--dry-run`. `--preview-rows` requires `--preview`. `--output` and `--overwrite` are rejected with `--list` or preview-only mode because they have no effect there; they are valid with `--dry-run` and normal conversion.
|
|
112
|
+
|
|
113
|
+
## Dataset and column selection
|
|
114
|
+
|
|
115
|
+
`--dataset` is repeatable and takes a canonical JSON Pointer:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
jxcel data.json --dataset /students
|
|
119
|
+
jxcel data.json --dataset /students --dataset /orders
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Pointer tokens use JSON Pointer escaping: `~` is written as `~0` and `/` as `~1`. For example, a dataset under the key `a/b~c` has the pointer `/a~1b~0c`.
|
|
123
|
+
|
|
124
|
+
Unsupported structures remain visible even when only some datasets are selected. Scalar values and empty objects outside dataset boundaries are listed with their JSON Pointers, so input content that is not exported is visible.
|
|
125
|
+
|
|
126
|
+
`--column-map` and `--exclude-map` are repeatable and take a JSON array of exactly two strings: the dataset pointer and the exact planned column name. Use shell quoting appropriate to your platform.
|
|
127
|
+
|
|
128
|
+
Bash:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
jxcel data.json \
|
|
132
|
+
--column-map '["/students","user.name"]' \
|
|
133
|
+
--column-map '["/orders","order,id"]' \
|
|
134
|
+
--exclude-map '["/orders","internal=status"]'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
PowerShell (verified on Windows in Phase 8):
|
|
138
|
+
|
|
139
|
+
```powershell
|
|
140
|
+
jxcel data.json `
|
|
141
|
+
--column-map '["/students","user.name"]' `
|
|
142
|
+
--exclude-map '["/orders","internal=status"]'
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Mappings are validated against every discovered dataset, but applied only to selected datasets. Include mappings select columns; exclude mappings remove columns afterward and take precedence. In `--dry-run`, a mapping for a valid but unselected dataset is reported as validated but unapplied. Unknown pointers and columns fail clearly.
|
|
146
|
+
|
|
147
|
+
## Nested values and flattening
|
|
148
|
+
|
|
149
|
+
Nested objects flatten by default. For example, `user.name` becomes a column named `user.name`. An empty nested object outside an array contributes no column in this mode and produces an `empty_object_omitted` warning with its column path and sample record indexes. Use `--no-flatten` for one column per top-level property:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
jxcel data.json --no-flatten
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
With `--no-flatten`, nested objects, arrays, and empty objects are written as compact JSON text (`{}` for an empty object, `[]` for an empty array); an empty object no longer produces an `empty_object_omitted` warning. Arrays never expand into rows or worksheets in either mode, and empty objects inside arrays are preserved as JSON text. Flattened column names use a reversible encoding of the original key path; conflicting flattened names fail rather than overwriting data. With `--no-flatten`, top-level keys are used as column names unchanged.
|
|
156
|
+
|
|
157
|
+
## Output and exit status
|
|
158
|
+
|
|
159
|
+
- `stdout`: listings, previews, dry-run plans, warnings, unsupported findings, and the successful conversion summary.
|
|
160
|
+
- `stderr`: errors and argument-parser diagnostics.
|
|
161
|
+
- If the console cannot encode a character, jxcel escapes it; a closed output pipe exits with status 1 without a traceback.
|
|
162
|
+
- Exit `0`: successful help, version, listing, preview, dry-run, or conversion.
|
|
163
|
+
- Exit `1`: input, JSON, planning, mapping, destination, workbook, or publication failure.
|
|
164
|
+
- Exit `2`: command-line argument or usage error.
|
|
165
|
+
|
|
166
|
+
`--quiet` suppresses only the routine successful conversion summary. Errors, warnings, unsupported findings, and non-exportable dataset notices remain visible. `--quiet` and `--verbose` are mutually exclusive. `--verbose` adds context such as the input path and worksheet assignments.
|
|
167
|
+
|
|
168
|
+
`--list` and `--preview` treat the absence of an exportable dataset as informational and exit 0 after reporting it. `--dry-run` and normal conversion exit 1 because no workbook can be produced.
|
|
169
|
+
|
|
170
|
+
## Data preservation
|
|
171
|
+
|
|
172
|
+
- Strings remain strings; numeric-looking and date-like text is not reinterpreted.
|
|
173
|
+
- Direct integer values with absolute value at least `10**15` are written as text with an `integer_precision_as_text` warning; smaller direct integers remain numeric.
|
|
174
|
+
- Direct float values remain numeric and are never rounded; values with more than 15 significant decimal digits produce a `float_precision_limited` warning, and direct finite floats outside Excel's numeric range fail export validation.
|
|
175
|
+
- Values written as JSON text (arrays in either mode, and nested objects under `--no-flatten`) produce a `nested_value_as_json_text` warning; numbers inside that text are not converted or range-checked individually.
|
|
176
|
+
- Export validation enforces Excel's limits: at most 1,048,575 data rows per dataset (the header uses row 1 of Excel's 1,048,576 rows), at most 16,384 columns, and at most 32,767 UTF-16 code units per cell or column header. Cell text and column headers reject control characters below `U+0020` other than tab, line feed, and carriage return, lone surrogates, and `U+FFFE`/`U+FFFF`; control characters inside JSON-serialized nested values are escaped. These failures are reported rather than truncated.
|
|
177
|
+
- Formula-like strings are written as text, never as formulas.
|
|
178
|
+
- Null and missing values become blank cells.
|
|
179
|
+
|
|
180
|
+
Warnings are aggregated by code, dataset, and effective column, with an occurrence count and at most five sample record indexes.
|
|
181
|
+
|
|
182
|
+
## Workbook output
|
|
183
|
+
|
|
184
|
+
Each selected exportable dataset becomes one worksheet, in plan order. Worksheet names are derived from dataset pointers: the root dataset is `root`, and pointer tokens are joined with dots. Names are sanitized for Excel, truncated to 31 UTF-16 code units, and made unique case-insensitively with `_2`, `_3`, and so on. The name `History` is reserved case-insensitively.
|
|
185
|
+
|
|
186
|
+
The header row is bold, filled, and vertically centered, with the header row frozen and an auto-filter over the data range. Column widths are based on the header and the first 100 data rows, with padding, and are clamped to 10–60 characters.
|
|
187
|
+
|
|
188
|
+
The workbook is written and validated through one open temporary-file stream before publication. On POSIX, the temporary file is mode `0600` while it is written and validated; its intended final mode is applied only after validation. With `--overwrite`, an existing regular file's POSIX permission bits are preserved; new files use the platform's normal file-creation mode. A permission failure before publication leaves the existing destination unchanged. Windows temporary files inherit the output directory's ACL; Windows `chmod` does not preserve general ACLs.
|
|
189
|
+
|
|
190
|
+
Choose an output directory whose access controls are appropriate for the workbook data. jxcel protects against accidental concurrent publishers: no-overwrite publication uses a same-directory hard link, and overwrite uses the operating system's replace operation. It does not defend against a malicious process running as the same user or another user/process with permission to change entries in the output directory. The temporary pathname is still used for publication and cleanup, so a hostile writable output directory is outside the security guarantee.
|
|
191
|
+
|
|
192
|
+
## Platform validation
|
|
193
|
+
|
|
194
|
+
The current 12-combination matrix passed in [GitHub Actions run 41933979297](https://github.com/AbuTaha7000D/jxcel/actions/runs/41933979297), validating commit `6d2e5e3f3f0b9cb4a0b7985847a496be744cc1e7`.
|
|
195
|
+
|
|
196
|
+
| Platform | Status | Evidence |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| Linux (`ubuntu-24.04`, plus local Fedora 44) | **PASS on Python 3.11–3.14** | All four jobs passed all 309 unit tests and 25 acceptance checks. Each built and inspected wheel/sdist, installed each in isolated environments, ran CLI/pipx smoke checks, and verified publication behavior. |
|
|
199
|
+
| Windows (`windows-2025`, X64) | **PASS on Python 3.11–3.14** | All four jobs passed the 309-test suite (306 passed, three POSIX-only permission-bit tests skipped) and 25 acceptance checks. Windows shell quoting and native console checks passed. |
|
|
200
|
+
| macOS (`macos-15`, ARM64) | **PASS on Python 3.11–3.14** | All four jobs passed all 309 unit tests and 25 acceptance checks. POSIX permission preservation and hard-link publication checks passed. |
|
|
201
|
+
|
|
202
|
+
Reproducible Linux install and smoke commands, with temporary directories:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
python -m venv /tmp/jxcel-venv
|
|
206
|
+
/tmp/jxcel-venv/bin/python -m pip install .
|
|
207
|
+
cd /tmp
|
|
208
|
+
/tmp/jxcel-venv/bin/jxcel --version
|
|
209
|
+
/tmp/jxcel-venv/bin/jxcel --help
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The Linux, Windows, and macOS Python matrix is automated by `.github/workflows/phase8-cross-platform.yml`, which is dispatched manually. The current verification run is linked above.
|
|
213
|
+
|
|
214
|
+
The full test suite uses the standard library. Bash:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python -m unittest discover -s tests
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
PowerShell:
|
|
221
|
+
|
|
222
|
+
```powershell
|
|
223
|
+
$env:PYTHONDONTWRITEBYTECODE = "1"
|
|
224
|
+
$env:PYTHONPATH = "src"
|
|
225
|
+
python -m unittest discover -s tests
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Windows CMD:
|
|
229
|
+
|
|
230
|
+
```bat
|
|
231
|
+
set PYTHONDONTWRITEBYTECODE=1
|
|
232
|
+
set PYTHONPATH=src
|
|
233
|
+
python -m unittest discover -s tests
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## GitHub and PyPI release process
|
|
237
|
+
|
|
238
|
+
Create each GitHub Release from a version tag (for example, `v0.1.0`) pointing to the reviewed release commit on `main`. GitHub provides source archives for the tag. Creating a GitHub Release does not publish a Python package to PyPI.
|
|
239
|
+
|
|
240
|
+
The manually dispatched [PyPI workflow](.github/workflows/publish.yml) builds a wheel and source distribution. Its `publish` input defaults to `false`; the publishing job is eligible only when the workflow is dispatched with `publish=true` from a tag whose name begins with `v`. The tag must identify the reviewed release commit. Do not enable that input without separate authorization to publish this release.
|
|
241
|
+
|
|
242
|
+
The workflow uses [PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/) and does not store a PyPI token. Before first publication, configure the PyPI trusted publisher for owner `AbuTaha7000D`, repository `jxcel`, workflow `.github/workflows/publish.yml`, and GitHub environment `pypi`. Configure that GitHub environment with the required release reviewers. The project currently has no PyPI registration; PyPI's [trusted publisher project creation](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/) flow can register it during an explicitly authorized first publish.
|
|
243
|
+
|
|
244
|
+
## Limitations
|
|
245
|
+
|
|
246
|
+
- The complete JSON document and the export snapshot are held in memory; jxcel is not a streaming converter.
|
|
247
|
+
- JSON documents nested more than 500 object/array levels are rejected with a path-aware error. This fixed limit avoids interpreter-dependent parser behavior and excessive discovery paths; brackets inside strings do not count.
|
|
248
|
+
- Concurrent mutation of source records while a plan is being built is unsupported. Constructing or forging internal plan objects directly can bypass validation and is outside the supported contract.
|
|
249
|
+
- The matrix covers GitHub-hosted Ubuntu 24.04, Windows 2025, and macOS 15; other OS releases, hardware architectures, and filesystems were not tested.
|
|
250
|
+
- Hard-link publication depends on filesystem support and was exercised on Linux `tmpfs` and the Windows and macOS runner temporary filesystems; other filesystem types were not tested.
|
|
251
|
+
- The current matrix ran Python 3.11–3.14 on all three named operating systems; future interpreter patch releases and OS runner images may differ.
|
|
252
|
+
- The detailed roadmap is maintained locally and is not included in Git or package distributions.
|
|
253
|
+
|
|
254
|
+
## License
|
|
255
|
+
|
|
256
|
+
jxcel is licensed under the MIT License. See [LICENSE](LICENSE) for the full text.
|
|
257
|
+
|
|
258
|
+
## Project guidance
|
|
259
|
+
|
|
260
|
+
- [AGENTS.md](AGENTS.md) contains repository-wide instructions for coding agents.
|
|
261
|
+
- The detailed product roadmap is maintained locally and may not be present in a checkout.
|
|
262
|
+
|
|
263
|
+
The former `export_students.py` legacy exporter was removed during project cleanup. It is not part of jxcel or its distributions.
|
jxcel-0.1.0/README.md
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# jxcel
|
|
2
|
+
|
|
3
|
+
`jxcel` is a cross-platform command-line application for converting JSON files into formatted Excel `.xlsx` workbooks. It discovers tabular object arrays in general JSON documents; it has no fixed columns or domain-specific assumptions.
|
|
4
|
+
|
|
5
|
+
## Development status
|
|
6
|
+
|
|
7
|
+
The converter is functional. JSON loading and validation, dataset discovery, schema planning and value preparation, workbook generation with validated publication, and command-line integration are implemented in `src/jxcel/`. The package has not been published.
|
|
8
|
+
|
|
9
|
+
Current cross-platform release verification passed in GitHub Actions run [41933979297](https://github.com/AbuTaha7000D/jxcel/actions/runs/41933979297) on commit `6d2e5e3f3f0b9cb4a0b7985847a496be744cc1e7`. All 12 Linux, Windows, and macOS × Python 3.11–3.14 jobs passed. Each ran the full 309-test suite and 25 CLI acceptance checks; Windows skipped three POSIX-only permission tests. The workflow also built and inspected wheel and source distributions, installed them in separate environments, and verified pipx installation.
|
|
10
|
+
|
|
11
|
+
The earlier Phase 8 run [41666703215](https://github.com/AbuTaha7000D/jxcel/actions/runs/41666703215) validated commit `f351669e6ed5ef072eb888e9a2f2f85401832210` on Windows and macOS with the original 299-test suite.
|
|
12
|
+
|
|
13
|
+
Release notes for version `0.1.0` are in [RELEASE_NOTES.md](https://github.com/AbuTaha7000D/jxcel/blob/main/RELEASE_NOTES.md).
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Python 3.11 or newer is declared. Python 3.11, 3.12, 3.13, and 3.14 have all been exercised on Ubuntu 24.04, Windows 2025, and macOS 15 in run 41933979297.
|
|
18
|
+
- Runtime dependencies: the Python standard library and `openpyxl`.
|
|
19
|
+
- Linux, Windows, and macOS are intended targets. All three have been exercised: Linux locally, and Windows and macOS on GitHub-hosted runners in Phase 8.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
A package distribution is not published yet. From a local checkout:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m pip install .
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This command was verified on Linux in an isolated virtual environment and on the Windows and macOS CI runners in Phase 8. The build uses isolation, so it needs access to a package index or a populated build-dependency cache; an offline install fails if the required `setuptools` build dependency is unavailable.
|
|
30
|
+
|
|
31
|
+
An isolated installation from the checkout was also verified with `pipx`: 1.18.11 on Linux and 1.18.12 on the Windows and macOS CI runners.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pipx install .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Both commands install a `jxcel` command that points at `jxcel.cli:main`. Command availability, the isolated `pipx` command path, and execution from outside the checkout were verified on Linux, Windows, and macOS.
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
Exactly one input source is required: positional `INPUT` or `-i/--input PATH`.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
jxcel data.json
|
|
45
|
+
jxcel -i data.json
|
|
46
|
+
jxcel /path/to/data.json
|
|
47
|
+
jxcel -i /path/to/data.json -o result.xlsx
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
By default, the output is written beside the input with an `.xlsx` suffix, so `data.json` produces `data.xlsx`. The output parent directory must already exist; jxcel never creates directories.
|
|
51
|
+
|
|
52
|
+
Existing output files are preserved unless `--overwrite` is supplied:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
jxcel data.json --overwrite
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Without `--overwrite`, an existing destination is an error. With it, jxcel builds and validates a temporary workbook first, then replaces the destination through the approved publication path. jxcel does not claim crash durability or stronger atomicity than the operating system and filesystem provide.
|
|
59
|
+
|
|
60
|
+
No-overwrite publication creates the destination with a same-directory hard link, so the temporary and destination files stay on one filesystem. Some filesystems do not support hard links, including FAT32/exFAT and some network or container mounts. On such filesystems, no-overwrite publication fails with exit status 1 and an explicit error. jxcel does not fall back to rename or replace, because that fallback could destroy a destination created concurrently. Overwrite publication uses the operating system's replace operation and depends on that filesystem's support. Hard-link behavior was exercised on Linux `tmpfs` and on the Windows and macOS runner temporary filesystems; other filesystem types, including FAT32/exFAT and network mounts, were not tested.
|
|
61
|
+
|
|
62
|
+
## Input validation
|
|
63
|
+
|
|
64
|
+
jxcel reads the input as UTF-8 and accepts an optional UTF-8 BOM. Empty or whitespace-only files, malformed JSON, invalid UTF-8, and trailing content after the JSON value are rejected with exit status 1 and a path-aware error. Malformed JSON reports the line and column; invalid UTF-8 reports the byte offset.
|
|
65
|
+
|
|
66
|
+
Object keys must be unique at every level. Duplicate keys are rejected even when one is written with an escape such as `\u0061`, because it decodes to the same key; the same key in separate objects is allowed. `NaN`, `Infinity`, and `-Infinity` are rejected as non-standard JSON constants. JSON real numbers must be finite: tokens that overflow a Python float or underflow a nonzero value to zero are rejected. Integers decode as Python integers, subject to Python's configured integer-string conversion limit.
|
|
67
|
+
|
|
68
|
+
The loader does not restrict the JSON root category: objects, arrays, strings, numbers, booleans, and `null` are all accepted, subject to the validation above. Dataset discovery then treats a root that is not an object or array as `unsupported_root`. Discovery reports an empty array outside dataset records as `empty_array`, and an empty object outside arrays as `empty_object`; neither is an exportable dataset. `--list` and `--preview` report these findings and exit 0; `--dry-run` and conversion exit 1 when no workbook can be produced.
|
|
69
|
+
|
|
70
|
+
## Inspection modes
|
|
71
|
+
|
|
72
|
+
The following modes never create a workbook, temporary workbook, or output directory. They are safe to run against an existing destination.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
jxcel data.json --list
|
|
76
|
+
jxcel data.json --preview
|
|
77
|
+
jxcel data.json --preview --preview-rows 10
|
|
78
|
+
jxcel data.json --dry-run
|
|
79
|
+
jxcel data.json --preview --dry-run
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- `--list` builds schemas, reports dataset pointers, record counts, available columns, effective columns after mappings, non-exportable reasons, and unsupported structures. It performs schema-only validation and does not scan cell values for exportability.
|
|
83
|
+
- `--preview` displays bounded records, respecting dataset and column selection. It prepares only the displayed rows and does not export-validate values outside the preview window. `--preview-rows` defaults to 5 and must be a positive integer.
|
|
84
|
+
- `--dry-run` performs full export validation and shows the selected datasets, effective columns, destination, warnings, and unsupported structures. It validates the destination read-only, so an existing file without `--overwrite` or a missing parent directory fails with exit status 1.
|
|
85
|
+
- `--preview --dry-run` combines both: the full export plan is built once and preview rows come from its validated snapshot.
|
|
86
|
+
|
|
87
|
+
`--list` cannot be combined with `--preview` or `--dry-run`. `--preview-rows` requires `--preview`. `--output` and `--overwrite` are rejected with `--list` or preview-only mode because they have no effect there; they are valid with `--dry-run` and normal conversion.
|
|
88
|
+
|
|
89
|
+
## Dataset and column selection
|
|
90
|
+
|
|
91
|
+
`--dataset` is repeatable and takes a canonical JSON Pointer:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
jxcel data.json --dataset /students
|
|
95
|
+
jxcel data.json --dataset /students --dataset /orders
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Pointer tokens use JSON Pointer escaping: `~` is written as `~0` and `/` as `~1`. For example, a dataset under the key `a/b~c` has the pointer `/a~1b~0c`.
|
|
99
|
+
|
|
100
|
+
Unsupported structures remain visible even when only some datasets are selected. Scalar values and empty objects outside dataset boundaries are listed with their JSON Pointers, so input content that is not exported is visible.
|
|
101
|
+
|
|
102
|
+
`--column-map` and `--exclude-map` are repeatable and take a JSON array of exactly two strings: the dataset pointer and the exact planned column name. Use shell quoting appropriate to your platform.
|
|
103
|
+
|
|
104
|
+
Bash:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
jxcel data.json \
|
|
108
|
+
--column-map '["/students","user.name"]' \
|
|
109
|
+
--column-map '["/orders","order,id"]' \
|
|
110
|
+
--exclude-map '["/orders","internal=status"]'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
PowerShell (verified on Windows in Phase 8):
|
|
114
|
+
|
|
115
|
+
```powershell
|
|
116
|
+
jxcel data.json `
|
|
117
|
+
--column-map '["/students","user.name"]' `
|
|
118
|
+
--exclude-map '["/orders","internal=status"]'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Mappings are validated against every discovered dataset, but applied only to selected datasets. Include mappings select columns; exclude mappings remove columns afterward and take precedence. In `--dry-run`, a mapping for a valid but unselected dataset is reported as validated but unapplied. Unknown pointers and columns fail clearly.
|
|
122
|
+
|
|
123
|
+
## Nested values and flattening
|
|
124
|
+
|
|
125
|
+
Nested objects flatten by default. For example, `user.name` becomes a column named `user.name`. An empty nested object outside an array contributes no column in this mode and produces an `empty_object_omitted` warning with its column path and sample record indexes. Use `--no-flatten` for one column per top-level property:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
jxcel data.json --no-flatten
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
With `--no-flatten`, nested objects, arrays, and empty objects are written as compact JSON text (`{}` for an empty object, `[]` for an empty array); an empty object no longer produces an `empty_object_omitted` warning. Arrays never expand into rows or worksheets in either mode, and empty objects inside arrays are preserved as JSON text. Flattened column names use a reversible encoding of the original key path; conflicting flattened names fail rather than overwriting data. With `--no-flatten`, top-level keys are used as column names unchanged.
|
|
132
|
+
|
|
133
|
+
## Output and exit status
|
|
134
|
+
|
|
135
|
+
- `stdout`: listings, previews, dry-run plans, warnings, unsupported findings, and the successful conversion summary.
|
|
136
|
+
- `stderr`: errors and argument-parser diagnostics.
|
|
137
|
+
- If the console cannot encode a character, jxcel escapes it; a closed output pipe exits with status 1 without a traceback.
|
|
138
|
+
- Exit `0`: successful help, version, listing, preview, dry-run, or conversion.
|
|
139
|
+
- Exit `1`: input, JSON, planning, mapping, destination, workbook, or publication failure.
|
|
140
|
+
- Exit `2`: command-line argument or usage error.
|
|
141
|
+
|
|
142
|
+
`--quiet` suppresses only the routine successful conversion summary. Errors, warnings, unsupported findings, and non-exportable dataset notices remain visible. `--quiet` and `--verbose` are mutually exclusive. `--verbose` adds context such as the input path and worksheet assignments.
|
|
143
|
+
|
|
144
|
+
`--list` and `--preview` treat the absence of an exportable dataset as informational and exit 0 after reporting it. `--dry-run` and normal conversion exit 1 because no workbook can be produced.
|
|
145
|
+
|
|
146
|
+
## Data preservation
|
|
147
|
+
|
|
148
|
+
- Strings remain strings; numeric-looking and date-like text is not reinterpreted.
|
|
149
|
+
- Direct integer values with absolute value at least `10**15` are written as text with an `integer_precision_as_text` warning; smaller direct integers remain numeric.
|
|
150
|
+
- Direct float values remain numeric and are never rounded; values with more than 15 significant decimal digits produce a `float_precision_limited` warning, and direct finite floats outside Excel's numeric range fail export validation.
|
|
151
|
+
- Values written as JSON text (arrays in either mode, and nested objects under `--no-flatten`) produce a `nested_value_as_json_text` warning; numbers inside that text are not converted or range-checked individually.
|
|
152
|
+
- Export validation enforces Excel's limits: at most 1,048,575 data rows per dataset (the header uses row 1 of Excel's 1,048,576 rows), at most 16,384 columns, and at most 32,767 UTF-16 code units per cell or column header. Cell text and column headers reject control characters below `U+0020` other than tab, line feed, and carriage return, lone surrogates, and `U+FFFE`/`U+FFFF`; control characters inside JSON-serialized nested values are escaped. These failures are reported rather than truncated.
|
|
153
|
+
- Formula-like strings are written as text, never as formulas.
|
|
154
|
+
- Null and missing values become blank cells.
|
|
155
|
+
|
|
156
|
+
Warnings are aggregated by code, dataset, and effective column, with an occurrence count and at most five sample record indexes.
|
|
157
|
+
|
|
158
|
+
## Workbook output
|
|
159
|
+
|
|
160
|
+
Each selected exportable dataset becomes one worksheet, in plan order. Worksheet names are derived from dataset pointers: the root dataset is `root`, and pointer tokens are joined with dots. Names are sanitized for Excel, truncated to 31 UTF-16 code units, and made unique case-insensitively with `_2`, `_3`, and so on. The name `History` is reserved case-insensitively.
|
|
161
|
+
|
|
162
|
+
The header row is bold, filled, and vertically centered, with the header row frozen and an auto-filter over the data range. Column widths are based on the header and the first 100 data rows, with padding, and are clamped to 10–60 characters.
|
|
163
|
+
|
|
164
|
+
The workbook is written and validated through one open temporary-file stream before publication. On POSIX, the temporary file is mode `0600` while it is written and validated; its intended final mode is applied only after validation. With `--overwrite`, an existing regular file's POSIX permission bits are preserved; new files use the platform's normal file-creation mode. A permission failure before publication leaves the existing destination unchanged. Windows temporary files inherit the output directory's ACL; Windows `chmod` does not preserve general ACLs.
|
|
165
|
+
|
|
166
|
+
Choose an output directory whose access controls are appropriate for the workbook data. jxcel protects against accidental concurrent publishers: no-overwrite publication uses a same-directory hard link, and overwrite uses the operating system's replace operation. It does not defend against a malicious process running as the same user or another user/process with permission to change entries in the output directory. The temporary pathname is still used for publication and cleanup, so a hostile writable output directory is outside the security guarantee.
|
|
167
|
+
|
|
168
|
+
## Platform validation
|
|
169
|
+
|
|
170
|
+
The current 12-combination matrix passed in [GitHub Actions run 41933979297](https://github.com/AbuTaha7000D/jxcel/actions/runs/41933979297), validating commit `6d2e5e3f3f0b9cb4a0b7985847a496be744cc1e7`.
|
|
171
|
+
|
|
172
|
+
| Platform | Status | Evidence |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| Linux (`ubuntu-24.04`, plus local Fedora 44) | **PASS on Python 3.11–3.14** | All four jobs passed all 309 unit tests and 25 acceptance checks. Each built and inspected wheel/sdist, installed each in isolated environments, ran CLI/pipx smoke checks, and verified publication behavior. |
|
|
175
|
+
| Windows (`windows-2025`, X64) | **PASS on Python 3.11–3.14** | All four jobs passed the 309-test suite (306 passed, three POSIX-only permission-bit tests skipped) and 25 acceptance checks. Windows shell quoting and native console checks passed. |
|
|
176
|
+
| macOS (`macos-15`, ARM64) | **PASS on Python 3.11–3.14** | All four jobs passed all 309 unit tests and 25 acceptance checks. POSIX permission preservation and hard-link publication checks passed. |
|
|
177
|
+
|
|
178
|
+
Reproducible Linux install and smoke commands, with temporary directories:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
python -m venv /tmp/jxcel-venv
|
|
182
|
+
/tmp/jxcel-venv/bin/python -m pip install .
|
|
183
|
+
cd /tmp
|
|
184
|
+
/tmp/jxcel-venv/bin/jxcel --version
|
|
185
|
+
/tmp/jxcel-venv/bin/jxcel --help
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The Linux, Windows, and macOS Python matrix is automated by `.github/workflows/phase8-cross-platform.yml`, which is dispatched manually. The current verification run is linked above.
|
|
189
|
+
|
|
190
|
+
The full test suite uses the standard library. Bash:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python -m unittest discover -s tests
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
PowerShell:
|
|
197
|
+
|
|
198
|
+
```powershell
|
|
199
|
+
$env:PYTHONDONTWRITEBYTECODE = "1"
|
|
200
|
+
$env:PYTHONPATH = "src"
|
|
201
|
+
python -m unittest discover -s tests
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Windows CMD:
|
|
205
|
+
|
|
206
|
+
```bat
|
|
207
|
+
set PYTHONDONTWRITEBYTECODE=1
|
|
208
|
+
set PYTHONPATH=src
|
|
209
|
+
python -m unittest discover -s tests
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## GitHub and PyPI release process
|
|
213
|
+
|
|
214
|
+
Create each GitHub Release from a version tag (for example, `v0.1.0`) pointing to the reviewed release commit on `main`. GitHub provides source archives for the tag. Creating a GitHub Release does not publish a Python package to PyPI.
|
|
215
|
+
|
|
216
|
+
The manually dispatched [PyPI workflow](.github/workflows/publish.yml) builds a wheel and source distribution. Its `publish` input defaults to `false`; the publishing job is eligible only when the workflow is dispatched with `publish=true` from a tag whose name begins with `v`. The tag must identify the reviewed release commit. Do not enable that input without separate authorization to publish this release.
|
|
217
|
+
|
|
218
|
+
The workflow uses [PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/) and does not store a PyPI token. Before first publication, configure the PyPI trusted publisher for owner `AbuTaha7000D`, repository `jxcel`, workflow `.github/workflows/publish.yml`, and GitHub environment `pypi`. Configure that GitHub environment with the required release reviewers. The project currently has no PyPI registration; PyPI's [trusted publisher project creation](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/) flow can register it during an explicitly authorized first publish.
|
|
219
|
+
|
|
220
|
+
## Limitations
|
|
221
|
+
|
|
222
|
+
- The complete JSON document and the export snapshot are held in memory; jxcel is not a streaming converter.
|
|
223
|
+
- JSON documents nested more than 500 object/array levels are rejected with a path-aware error. This fixed limit avoids interpreter-dependent parser behavior and excessive discovery paths; brackets inside strings do not count.
|
|
224
|
+
- Concurrent mutation of source records while a plan is being built is unsupported. Constructing or forging internal plan objects directly can bypass validation and is outside the supported contract.
|
|
225
|
+
- The matrix covers GitHub-hosted Ubuntu 24.04, Windows 2025, and macOS 15; other OS releases, hardware architectures, and filesystems were not tested.
|
|
226
|
+
- Hard-link publication depends on filesystem support and was exercised on Linux `tmpfs` and the Windows and macOS runner temporary filesystems; other filesystem types were not tested.
|
|
227
|
+
- The current matrix ran Python 3.11–3.14 on all three named operating systems; future interpreter patch releases and OS runner images may differ.
|
|
228
|
+
- The detailed roadmap is maintained locally and is not included in Git or package distributions.
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
jxcel is licensed under the MIT License. See [LICENSE](LICENSE) for the full text.
|
|
233
|
+
|
|
234
|
+
## Project guidance
|
|
235
|
+
|
|
236
|
+
- [AGENTS.md](AGENTS.md) contains repository-wide instructions for coding agents.
|
|
237
|
+
- The detailed product roadmap is maintained locally and may not be present in a checkout.
|
|
238
|
+
|
|
239
|
+
The former `export_students.py` legacy exporter was removed during project cleanup. It is not part of jxcel or its distributions.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# jxcel 0.1.0 Release Notes
|
|
2
|
+
|
|
3
|
+
Version: `0.1.0`
|
|
4
|
+
|
|
5
|
+
Status: **initial release**. This version has not been published as a package distribution to PyPI or any other package index.
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
|
|
9
|
+
`jxcel` is a cross-platform command-line application for converting JSON files into formatted Excel `.xlsx` workbooks. It discovers tabular object arrays in general JSON documents and has no fixed columns or domain-specific assumptions.
|
|
10
|
+
|
|
11
|
+
This release includes:
|
|
12
|
+
|
|
13
|
+
- Strict JSON loading with path-aware errors for malformed JSON, invalid UTF-8, duplicate object keys, non-standard numeric constants, unsupported float ranges, and integer conversion limits. Documents deeper than 500 object/array levels are rejected consistently across supported interpreters.
|
|
14
|
+
- Deterministic dataset discovery, including reporting of unsupported structures and non-exportable datasets.
|
|
15
|
+
- Schema planning with nested-object flattening (or `--no-flatten`), column selection, and reversible column-name encoding.
|
|
16
|
+
- Dataset and column selection with repeatable `--dataset`, `--column-map`, and `--exclude-map` options.
|
|
17
|
+
- Inspection modes: `--list`, `--preview` with `--preview-rows`, and `--dry-run`, including `--preview --dry-run`.
|
|
18
|
+
- Data-preserving value handling with aggregated warnings and enforcement of Excel row, column, and cell-text limits.
|
|
19
|
+
- Workbook generation with worksheet naming, header formatting, frozen headers, auto-filters, and column widths.
|
|
20
|
+
- Validated publication through one retained temporary-file stream: POSIX temporary workbooks remain mode `0600` during serialization and validation; no-overwrite publication uses a same-directory hard link; `--overwrite` uses the operating system's replace operation.
|
|
21
|
+
- User-facing output through `stdout` and errors through `stderr`, with exit statuses `0` (success), `1` (processing or publication failure), and `2` (usage error).
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
No distribution is published. Install from a local checkout:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m pip install .
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or install in an isolated environment with `pipx`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pipx install .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Both commands install a `jxcel` command that points at `jxcel.cli:main`. The build uses isolation, so it needs access to a package index or a populated build-dependency cache.
|
|
38
|
+
|
|
39
|
+
## Validation evidence
|
|
40
|
+
|
|
41
|
+
- The 309-test `unittest` suite passed on all 12 supported OS/Python combinations in [GitHub Actions run 41933979297](https://github.com/AbuTaha7000D/jxcel/actions/runs/41933979297), commit `6d2e5e3f3f0b9cb4a0b7985847a496be744cc1e7`. Windows skipped three POSIX-only permission tests per job.
|
|
42
|
+
- Linux, Windows, and macOS each passed 25 CLI acceptance checks on Python 3.11, 3.12, 3.13, and 3.14.
|
|
43
|
+
- The matrix built and inspected the wheel and source distribution, installed each into isolated environments, and verified pipx installation and CLI conversion.
|
|
44
|
+
|
|
45
|
+
## Known limitations
|
|
46
|
+
|
|
47
|
+
- The complete JSON document and the export snapshot are held in memory; jxcel is not a streaming converter.
|
|
48
|
+
- No-overwrite publication relies on hard links, so it depends on filesystem support. Filesystems without hard-link support fail with an explicit error rather than falling back.
|
|
49
|
+
- Windows/macOS and Python 3.11–3.14 compatibility was verified on the named GitHub-hosted runner images in run 41933979297; other operating-system releases, architectures, and filesystems were not tested.
|
|
50
|
+
- There is no graphical user interface; jxcel is a command-line tool only.
|
|
51
|
+
- The package is not published, so there is no supported installation from a package index.
|
|
52
|
+
- Workbook contents were validated by reopening the generated file with openpyxl; opening the workbook in Excel or LibreOffice was not verified.
|
|
53
|
+
- No crash-durability guarantee stronger than the operating system and filesystem provide is claimed.
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
jxcel is licensed under the MIT License. See [LICENSE](LICENSE).
|
|
58
|
+
|
|
59
|
+
## Legacy script
|
|
60
|
+
|
|
61
|
+
The former `export_students.py` legacy exporter was removed during project cleanup. It is not part of jxcel or its distributions.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.3"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "jxcel"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A cross-platform CLI for converting JSON datasets into Excel workbooks"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{name = "Mahmoud Ehab"},
|
|
15
|
+
]
|
|
16
|
+
keywords = ["json", "excel", "xlsx", "cli", "converter"]
|
|
17
|
+
dependencies = ["openpyxl>=3.1.5,<4"]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Environment :: Console",
|
|
21
|
+
"Intended Audience :: End Users/Desktop",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Topic :: Utilities",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
"Source" = "https://github.com/abutaha7000d/jxcel"
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
jxcel = "jxcel.cli:main"
|
|
36
|
+
|
|
37
|
+
[tool.setuptools]
|
|
38
|
+
package-dir = {"" = "src"}
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
where = ["src"]
|
|
42
|
+
include = ["jxcel", "jxcel.*"]
|
|
43
|
+
namespaces = false
|