Py_sax2sab/claudeCodeChatLog.md
arda.aydin@ontrol.com.tr 7a99fa1b87 Track testprogram/ again, add claudeCodeChatLog.md
The test pair verify.py runs against is back in the repo, so a fresh clone
can run the built-in checks. Conversion output (*-sab2sax-*) stays ignored,
so converting inside testprogram/ still leaves the tree clean.

claudeCodeChatLog.md records how this got built: what was asked for, the
decisions worth remembering (plain paths in system.properties, the port
source, Java float formatting, the f4-rounded manifest default, why a sab
cannot return runtime props) and what is still untested.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 10:59:14 +03:00

4.8 KiB

Claude Code session log

What was asked for, what was built, and the decisions behind it. Written 2026-08-13, covering the work that produced ec4019e .. 2dcc170 (tags v0.0.0.001, v0.0.0.002).

Starting point: sab.py, a pure-Python .sax -> .sab encoder taking <app.sax> <sedona_home> <out.sab> on the command line, plus verify.py.

What was asked, in order

  1. Sedona home into system.properties, with a folder chooser on first run, and a file chooser for the input.
  2. Plain paths, not java-escaped, in that properties file.
  3. Timestamped output names[name]-sab2sax-20260728-140609.
  4. The reverse direction, .sab -> .sax, direction chosen by the input's extension.
  5. A version, shown in dialog titles.
  6. testprogram/ out of the repo — later reversed: the test pair is checked in again, while conversion output (*-sab2sax-*) stays gitignored.
  7. A file chooser in verify.py and a round-trip check on whatever is chosen.
  8. A window with a button per direction, showing the chosen file before converting and the output afterwards.
  9. run.py as the entry point; log labels in capitals, values on their own lines.

What exists now

run.py               entry point: window with no arguments, CLI with them
gui.py               the window: a button per direction
sab2sax.py           the CLI: dispatches on the input extension
sab.py               sax -> sab encoder
sax.py               sab -> sax decoder
config.py            system.properties, dialogs, NAME/VERSION
verify.py            round trips + comparison against sedonac output
system.properties    sedona.home
testprogram/         test apps verify.py runs against

sedona.home lives in system.properties. Missing or pointing somewhere without manifests/ and a folder chooser opens, then the answer is written back. Output files are always written next to the input as <stem>-sab2sax-<YYYYMMDD-HHMMSS>.<ext>, so a run never overwrites the previous one.

Decisions worth remembering

Plain paths in system.properties. Java's Properties (what sedonac reads it with) treats \ as an escape and doubles them up; we only read the file ourselves, so we write plain Windows paths. The parser collapses \\ to \ and keeps every other backslash literal — both forms load, and C:\niagara never becomes a newline.

The decoder is a port, not a guess. sax.py follows OfflineApp.decodeAppBinary + encodeAppXml and OfflineComponent/OfflineLink from sedonaSrcOrginal/sedona/src/sedona/offline/. The tree is rebuilt from the firstChild/nextSibling id chain; the XML is written the way XWriter does it — two-space indent, a <!-- /path --> comment above every <comp>, &#x..; escaping.

Java float formatting. Value.encodeString for a float is java.lang.Float.toString: shortest digits that round-trip, always a decimal point, E form outside [1e-3, 1e7). sax.java_float reproduces it. It matches modern Java rather than the old JDK's extra-digit quirk on subnormals (1.4E-45 vs our 1.0E-45) — only reachable with denormal floats.

The manifest default is a 32-bit float too. A prop equal to its default is not written to the .sax. Comparing a decoded float against a default parsed as a Python double makes 0.1 look different from 0.1, and every minDelta="0.1" gets written where sedonac omits it. Rounding the default to f4 first was the last diff between "close" and "identical".

A .sab cannot give back runtime props. Only config props are in the binary. sedonac has the same hole. That is why a .sax round trip compares the two binaries, not the two texts.

Verification

  • test_normal.sax -> sab, byte-identical to test_normal_sedonac.sab (7852 bytes)
  • test_normal_sedonac.sab -> sax, byte-identical to test_normal.sax (61294 bytes)
  • both round trips clean: sab -> sax -> sab, and sax -> sab -> sax -> sab

A live sedonac.exe comparison was attempted and could not run here — it fails with Cannot load library: C:\Program Files\Zulu\zulu-21-jre\bin\server\jvm.dll. verify.check_encode(sax) / check_decode(sab) with no reference argument still do that comparison on a machine with a JRE sedonac will start under.

Malformed input fails with one line and exit 1, not a traceback: comp 0 app: missing child 254.

Where to pick up

  • Untested paths are unchanged from before: action overrides, Buf-typed props, non-ASCII strings, and apps whose ids exceed the 256-entry lookup table.
  • verify.py prints SKIP and exits 0 when testprogram/ is empty rather than failing; the test pair is checked in, so it normally runs.
  • Version lives in config.py (NAME, VERSION). The window title, every dialog title and the CLI banner all read from it.