fix(task-15): angle sysvars are radians on both engines; OSMODE is registry-saved and refused headlessly

Three authored claims in SYSVAR_CATALOG were false against the engines:

- HPANG said "degrees" but ActiveX GetVariable/SetVariable (and AutoLISP
  getvar) hold radians - measured on AutoCAD 2026 in a scratch document:
  SetVariable(pi/4) reads back 0.7853981633974483 on both paths. The row
  now says radians, like POLARANG.
- ANGBASE said "radians" with both engines True, but the DXF header stores
  $ANGBASE in degrees (AutoCAD saved the 1.5708-radian seat value as 90.0)
  and ezdxf read/wrote it raw, so the two engines disagreed by a factor of
  57.3. EzdxfBackend now translates that header variable at its boundary
  (_HEADER_DEGREE_SYSVARS): the tool speaks radians on both engines, the
  file keeps degrees.
- OSMODE claimed engines.ezdxf True, but $OSMODE is an R12-only header
  variable ezdxf never exports for R2000+: a headless write reported
  ok: True and read back None after save + reopen. It is registry-saved
  in AutoCAD, so it joins _UNSAVED_SYSVARS (refused with
  capability: registry_sysvar; the facade's `osmode` key refuses and
  snapshots None headlessly, like polar / polar_angle). Headless reads of
  every registry-saved variable now report None instead of whatever the
  ezdxf template holds in memory.

The gate that should have caught all three, tests/test_sysvar_catalog.py's
default round-trip, wrote 56 no-ops out of 66 and never saved: it now
writes a value that differs from the fresh document's for every writable
ezdxf-True entry, saves, reopens and reads back from the file. Two new
tests pin OSMODE's refusal and ANGBASE's radians-at-the-tool /
degrees-in-the-file split.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
Umut CAN
2026-09-17 15:20:02 +03:00
co-authored by Claude Opus 5
parent 125a8ed3b8
commit 75c13196b9
5 changed files with 175 additions and 37 deletions
+6 -5
View File
@@ -5093,11 +5093,12 @@ async def drawing_settings(
Refusals, per key, nothing else rolled back: an unknown key; a value outside
its range (grid/snap spacing > 0, polar_angle 0–360, precision 0–8, …); a
malformed `limits` or `annotation_scale`; `polar` / `polar_angle` on the
headless engine (`capability: registry_sysvar` — AutoCAD keeps them in the
registry, a file cannot); `dimstyle` / `textstyle` when the backend has no
styles contract. On the live engine `annotation_scale` must name a scale in
the drawing's scale list (SCALELISTEDIT) and AutoCAD refuses the write on a
malformed `limits` or `annotation_scale`; `osmode` / `polar` / `polar_angle`
on the headless engine (`capability: registry_sysvar` — AutoCAD keeps them in
the registry, a file cannot, and a headless snapshot reports them as `None`);
`dimstyle` / `textstyle` when the backend has no styles contract. On the
live engine `annotation_scale` must name a scale in the drawing's scale list
(SCALELISTEDIT) and AutoCAD refuses the write on a
paper-space layout with no active viewport; the headless engine adds the
scale, seeding AutoCAD's default list first when the drawing has none,
and refuses it on an R12 file (no OBJECTS section, so the value would