Proto commits in psobot/keynote-parser

These 19 commits are when the Protocol Buffers files have changed:

Commit:85e8a57
Author:Peter Sobot
Committer:Peter Sobot

Bundle every previous Keynote version, and let one be selected. Apple renamed message types between Keynote releases, so a .yaml file written by an older keynote-parser names types the current schemas no longer contain - the caveat the README's Compatibility section has described for years without offering a way around it. With per-version descriptor pools in place, several versions can now coexist, so the way around it is to bundle them. The schemas for versions Apple has long since replaced can't be extracted from an installed Keynote, but they are already in this repository: every release tag from v1.10.2.1 carries the .proto files it shipped with and a mapping module holding that version's TSP registry. dumper/extract_historical_versions.py recovers them from those tags; it reads only from git and is safe to re-run. Bundles 10.2, 11.2, 12.0, 12.1, 12.2.1 and 13.1 alongside 14.4 and 14.5. All eight load together with distinct pools. 10.2 and 11.2 leave a few registry entries unresolved (3 and 1), which is faithful - those releases did not ship protos for them either. Renames turn out to occur at exactly two boundaries: 10.2 -> 11.2 renamed 24 types (Master -> Template) and 13.1 -> 14.4 renamed 36 (TSK -> TSCK). The versions in between are identical in naming. --keynote-version is now accepted by unpack, pack, cat and replace, and argparse restricts it to the bundled set. Threading it through required IWAFile and IWACompressedChunk to accept a version at all, and fixed a latent bug: IWAArchiveSegment.from_dict took a version argument but passed it to neither dict_to_header nor dict_to_message, so packing under a non-default version silently used the newest schemas anyway. Two existing tests hardcoded type 6383, which postdates 10.2 and 11.2; they now derive an id common to every bundled version so adding an older one can't break them again. Cost: the wheel grows from 0.40 MB to 1.45 MB, and protos/ from 1.2 MB to 4.4 MB. 188 tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0179M4xvAKPGrgKpy4AeCsM7

Commit:bf7332a
Author:Peter Sobot

Give each bundled Keynote version its own descriptor pool. The versions/ layout could only ever hold one version. protoc emits code that registers into descriptor_pool.Default(), which is global to the process and keyed by .proto filename, and every Keynote version compiles the same filenames. Importing a second version's mapping raised: TypeError: Couldn't build proto file into descriptor pool: duplicate file name TSDArchives.proto so the machinery was not merely unused, it could not work. dumper/run.py now writes a per-version pool module and rewrites that version's generated modules to register into it, which lets several versions coexist. Bundles Keynote 14.5 as a second version. Its schemas are in fact identical to 14.4's - all 33 shared .proto files match once trailing whitespace is ignored, the type registry is identical at 631 entries, and 14.5 merely drops TSKArchives_sos.proto - so this buys no new parsing ability. It is here to keep the multi-version path exercised by the test suite rather than decorative, which is what let it rot unnoticed. Also fixes a regression this would otherwise have introduced: the extension lookup added for charts in #77 consulted descriptor_pool.Default(), which no longer holds any of these descriptors. It now uses the pool the message class was actually built in, so it stays correct per version. Without this change the chart fix silently degrades back to opaque archives. Note that __supported_keynote_version__ becomes 14.5, so the derived package version moves from 1.14.4.x to 1.14.5.x. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0179M4xvAKPGrgKpy4AeCsM7

Commit:0f86ef0
Author:Peter Sobot

Add pre-commit hooks, excluding the binary test fixtures. The hooks are worth having, but they cannot be pointed at tests/data/. The .iwa and .key fixtures are binary, yet `identify` finds no NUL bytes near the start of some of them and classifies them as text, so trailing-whitespace strips any 0x09 that happens to precede a 0x0a - which inside a Snappy stream or an embedded JPEG quantization table is just data, not whitespace. The archive is silently corrupted and the only symptom is a zipfile.BadZipFile in an unrelated test run much later. Verified by running the hooks over tests/data/ without the exclude: three .key fixtures, one .yaml fixture and tests/data/table/Metadata/DocumentIdentifier were all modified. Excluding the directory rather than a *.key glob is deliberate - the .iwa files have the same problem, and the .yaml fixtures are compared byte-for-byte by tests/test_codec.py. ruff is pinned to the same 0.16.2 as .github/workflows/python-package.yml, and picks up the rule selection from pyproject.toml, so the hook and CI agree about what passes. Letting those drift is how the lint gate stopped meaning anything the last time round. pyright is deliberately absent: it reports 43 errors on master today, so including it would block every commit rather than catch anything new. Worth adding once those are dealt with. The first run also normalized missing trailing newlines in eight .proto files and docs/obriensp_docs.md. Confirmed inert: recompiling the protos before and after produces byte-identical generated code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0179M4xvAKPGrgKpy4AeCsM7

The documentation is generated from this commit.

Commit:dc5fedf
Author:Peter Sobot

WIP: uncommitted working-tree state as of 2026-08-07. Snapshot of the psobot/modernize-2025 overlay that had accumulated in the working tree, committed so nothing is lost while resetting to a clean master. Not intended to be merged as-is: it branched from before the 14.4 and multiversion merges, so it reverts codec.py's version plumbing, hardcodes version = "1.11.2.3" in pyproject.toml, and comments out the TSCK imports in generated code. Worth salvaging from here: - .pre-commit-config.yaml (needs `exclude: ^tests/data/` on the whitespace hooks; as written they corrupt the binary .key fixtures) - Makefile and the uv-based dev workflow - the modernized GitHub Actions (v4/v5, Python 3.14, uv) - codec.py opening .iwa files as "rb" rather than in text mode - the pytest.warns(None) fix in tests/test_bundle_utils.py (removed in pytest 8) Superseded by what shipped in v1.14.4.1: - the nested-message mapping fix (#71) - protoc pinning and the dumper docs (#73) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0179M4xvAKPGrgKpy4AeCsM7

Commit:f790baf
Author:Peter Sobot
Committer:Peter Sobot

Allow storing multiple versions of the generated protos for backwards compatibility.

Commit:7df5bea
Author:Peter Sobot
Committer:Peter Sobot

Update to Keynote v14.4.

Commit:d46e710
Author:Peter Sobot

Catch duplicate file name errors when importing protos.

Commit:8bfd4b8
Author:Peter Sobot

Fix extension range validation in new Protobuf dumper.

Commit:ed809d3
Author:Peter Sobot

Update protos to v13.1.

Commit:90909b8
Author:Peter Sobot
Committer:Peter Sobot

Add support for Keynote 12.2.1. Fixes #44.

Commit:7588e49
Author:Peter Sobot

Add compatibility for Keynote 12.1.

Commit:db89399
Author:Peter Sobot
Committer:Peter Sobot

Add support for Keynote 12. Closes #34.

Commit:bf84973
Author:Peter Sobot

Upgrade to Keynote 11.2. Closes #33.

Commit:700688f
Author:Peter Sobot
Committer:Peter Sobot

Added scripts to automatically dump Protobuf definitions from new versions of Keynote.

Commit:8c5eac3
Author:Peter Sobot
Committer:Peter Sobot

Switch to Python-based protobuf dumper.

Commit:cace7c6
Author:Peter Sobot

Added support for Keynote 10.2.

Commit:91c5f35
Author:Peter Sobot
Committer:Peter Sobot

Added support for Keynote 10.1.

Commit:3da3b5f
Author:Peter Sobot
Committer:Peter Sobot

Added support for Keynote 10.0 (6478).

Commit:1d25ea3
Author:Peter Sobot
Committer:Peter Sobot

Init commit.