Skip to content

Python SDK v3: gzip-compressed pickles - #18

Merged
cleemansen merged 3 commits into
mainfrom
gzip
Sep 24, 2026
Merged

cleemansen merged 3 commits into
mainfrom
gzip

Conversation

@cleemansen

Copy link
Copy Markdown
Contributor

Draft on purpose — see "Why this is a draft" below.

What changes

App output is now always written as a gzip-compressed pickle, and App input is read whether it is
compressed or not. On the samples shipped here that is a factor of 8 to 19 — input2_LatLon goes from
72.5 MB to 3.8 MB.

The compression is determined from the file content, not from the file name. That is the one
non-obvious part, so it is worth spelling out: during an App run MoveApps dictates the paths and they
carry no extension —

SOURCE_FILE=/tmp/source_file
OUTPUT_FILE=/tmp/output_file

— so pandas' compression='infer', which only looks at the suffix, has nothing to work with. Writing
therefore states the compression explicitly, and reading reads the gzip magic number (1f 8b,
RFC 1952) from the first two bytes.

This is what the R SDK has always done: saveRDS gzips by default into that very same extension-less
/tmp/output_file, and readRDS recognises the compression from the header.

  • sdk/moveapps_pickle.py (new) — read(), write(), detect_compression()
  • sdk/moveapps_execution.py delegates to it; its direct pandas import is gone
  • tests/sdk/test_moveapps_pickle.py (new) — 7 tests; the full suite is 21 green
  • CHANGELOG_SDK.md — released as v3.0.0, breaking change stated explicitly

Breaking, deliberately

Reading stays backward compatible: an App on this SDK happily consumes uncompressed output from an App
built against an earlier one. That matters more than it may look, because MoveApps replays the stored
output of a pinned workflow item, and those blobs are never rewritten.

Writing cannot be made compatible. An App on SDK ≤ v2.3.0 sitting behind a new App reads a gzip
stream with infer and dies on UnpicklingError: invalid load key, '\x1f'. Hence the major version,
and hence every Python App on MoveApps needs rebuilding against the new co-pilot image.

Why this is a draft

Two reasons, both about blast radius rather than about the code:

  1. The SDK has not run on MoveApps yet. It is verified locally end to end — with the extension-less
    wiring the platform actually uses — but the platform rollout is still ahead of us. Tag
    v3.0.0-RC1 exists on this branch so the co-pilot image can be built and rehearsed on an isolated
    environment first. The real v3.0.0 follows on main, after that rehearsal.
  2. This repository is a GitHub template, and .github/workflows/template-sync.yml runs weekly in
    every repository derived from it. sdk/ is not listed in .github/.templatesyncignore, so merging
    here propagates the change into all of those App repositories. That is the intended end state — but
    it should happen once, deliberately, and not before the rehearsal has passed.

Companion work already released: cargo-agent-python v2.2.0 reads the compressed output, and
link-r-python v2.1.0 / v1.1.0 cover the four R↔Python translator Apps, which handle pickles
outside this SDK.

robe2037 and others added 3 commits July 28, 2026 10:59
MoveApps hands the App extension-less input and output paths, so pandas cannot
infer the compression from the file name. Write gzip explicitly, and determine
on read whether the input is compressed - that keeps uncompressed output from
Apps built against an earlier SDK readable.

Breaking change, hence the SDK version is v3.0.0: Apps built against an earlier
SDK cannot read the compressed output and have to be rebuilt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Measured against the new co-pilot base image on linux/amd64: 3.14 solves
with pandas, geopandas, movingpandas and the SDK's own dependencies.

`environment.yml` is in `.templatesyncignore`, so this reaches new Apps
created from the template and never an existing fork. The changelog
entry says so, because it is the only channel a fork owner reads.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cleemansen cleemansen self-assigned this Sep 24, 2026
@cleemansen
cleemansen marked this pull request as ready for review September 24, 2026 09:18
@cleemansen
cleemansen merged commit 1df87d1 into main Sep 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants