Skip to content

Explorer YAML skeleton export (+ fix variable-attribute to_dict_skeleton)#94

Merged
jeandet merged 4 commits into
mainfrom
feature/wacdfpp-yaml-skeleton-export
Jun 25, 2026
Merged

Explorer YAML skeleton export (+ fix variable-attribute to_dict_skeleton)#94
jeandet merged 4 commits into
mainfrom
feature/wacdfpp-yaml-skeleton-export

Conversation

@jeandet

@jeandet jeandet commented Jun 24, 2026

Copy link
Copy Markdown
Member

What

Two related changes around CDF skeleton serialization:

1. Fix: pycdfpp.to_dict_skeleton drops variable attributes

VariableAttribute is not a subclass of Attribute, so the singledispatch-based to_dict_skeleton found no matching handler and fell through to the no-op base — serializing every variable attribute to null.

to_dict_skeleton(cdf)["variables"]["v"]["attributes"]["UNITS"]  # was: None

Registers a dedicated VariableAttribute handler emitting the same {values, types} shape as the global Attribute handler (single-entry lists, since variable attributes hold exactly one entry) and stringifies time-typed values.

2. Feature: YAML skeleton export in the CDFpp Explorer

New pure, Node-testable wacdfpp/cdf-yaml.js:

  • toYaml(value) — minimal YAML emitter for the restricted skeleton value space (nested maps, scalar/nested arrays incl. typed arrays, strings quoted only when risky, .nan/.inf for fill values).
  • buildSkeleton(rawVars, rawGlobals, fileMeta) — produces the same structure as to_dict_skeleton; resolves CDF type codes to names via a static CDF_TYPE_NAMES map (no WASM needed → fully unit-testable).
  • skeletonFromCdfFile / cdfFileToYaml — browser-only adapters over the live CdfFile getters.

An "Export YAML" button in the Explorer downloads <name>.skeleton.yaml for the loaded CDF. It is metadata-only (types/shapes/attributes, never array data), so it is inherently safe for high-rank / huge variables — consistent with the existing plot/table gating.

Test plan

  • tests/python_skeletons/test.py — new test_variable_attributes_are_serialized (fails before the fix, passes after).
  • tests/wacdfpp_yaml/test.mjs — 41 checks pinning the emitter format and buildSkeleton shape (registered in tests/meson.build).
  • meson test → all green, no regressions.
  • Emitted YAML round-trips through PyYAML (special chars quoted, .nan preserved, nested arrays intact).
  • End-to-end verified against the real WASM module + a real ACE MFI CDF (17 vars / 28 globals, type names resolved, no malformed output).

Notes

  • The WASM bundle build (wacdfpp/meson.build) gains cdf-yaml.js in extra_files + a copyfile, mirroring the existing JS modules. Rebuild with emsdk to pick it up into the served app; the emitter logic itself is verified against the already-built module.

🤖 Generated with Claude Code

jeandet and others added 2 commits June 24, 2026 19:01
VariableAttribute is not a subclass of Attribute, so to_dict_skeleton's
singledispatch found no handler and fell through to the no-op base,
serializing every variable attribute to null. Register a dedicated
VariableAttribute handler that emits the same {values, types} shape as
the global Attribute handler (single-entry lists, since variable
attributes hold one entry) and stringifies time-typed values.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add cdf-yaml.js: a pure, Node-testable YAML emitter plus a buildSkeleton
that mirrors pycdfpp.to_dict_skeleton (metadata only — types, shapes,
attributes; never array data, so it is safe for high-rank/huge
variables). Type codes resolve to names via a static CDF_TYPE_NAMES map,
so the serializer needs no WASM. Browser-only skeletonFromCdfFile/
cdfFileToYaml adapt the live CdfFile getters.

Wire an "Export YAML" button into the Explorer that downloads
<name>.skeleton.yaml for the loaded CDF.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.11%. Comparing base (f5ca1ec) to head (cc83899).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #94      +/-   ##
==========================================
- Coverage   91.85%   91.11%   -0.74%     
==========================================
  Files          58       58              
  Lines        3524     3524              
==========================================
- Hits         3237     3211      -26     
- Misses        287      313      +26     
Flag Coverage Δ
unittests 91.11% <ø> (-0.74%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

jeandet and others added 2 commits June 25, 2026 08:52
…n export

Two correctness fixes from the PR #94 review:

- Emitter escaping: mapping keys were interpolated verbatim and needsQuote
  missed leading YAML indicators (`- `, `? `, `~`) and YAML-1.1 number forms
  (`1_000`, `0x1a`). Such keys/values re-parsed to a different value or failed
  to parse, so the skeleton did not round-trip. Quote keys via needsQuote and
  broaden it (verified by re-parsing the emitted YAML with PyYAML).

- Export no longer force-loads variable data. skeletonFromCdfFile re-walked the
  CDF via get_variable(), which unconditionally calls var.load_values() +
  copy_values (wacdfpp.cpp), materializing every variable's array — exactly the
  OOM the high-rank gating guards against, and contradicting the file's own
  "metadata only" claim. Build the skeleton from the currentModel app.js already
  holds instead (rawFromCdfFile now also carries per-variable compression +
  attribute type codes), so export does zero WASM calls and reads no array data.
  Removes the duplicate CdfFile adapter the review also flagged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- cdf-yaml.js: use `\d` instead of `[0-9]` (S6353).
- wacdfpp_yaml test: `Number.NaN` instead of bare `NaN` (S7773).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jeandet jeandet merged commit b73613a into main Jun 25, 2026
22 of 23 checks passed
jeandet added a commit that referenced this pull request Jun 25, 2026
…n export

Two correctness fixes from the PR #94 review:

- Emitter escaping: mapping keys were interpolated verbatim and needsQuote
  missed leading YAML indicators (`- `, `? `, `~`) and YAML-1.1 number forms
  (`1_000`, `0x1a`). Such keys/values re-parsed to a different value or failed
  to parse, so the skeleton did not round-trip. Quote keys via needsQuote and
  broaden it (verified by re-parsing the emitted YAML with PyYAML).

- Export no longer force-loads variable data. skeletonFromCdfFile re-walked the
  CDF via get_variable(), which unconditionally calls var.load_values() +
  copy_values (wacdfpp.cpp), materializing every variable's array — exactly the
  OOM the high-rank gating guards against, and contradicting the file's own
  "metadata only" claim. Build the skeleton from the currentModel app.js already
  holds instead (rawFromCdfFile now also carries per-variable compression +
  attribute type codes), so export does zero WASM calls and reads no array data.
  Removes the duplicate CdfFile adapter the review also flagged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@jeandet jeandet deleted the feature/wacdfpp-yaml-skeleton-export branch June 25, 2026 11:54
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.

1 participant