fix(task-21): the applied ISO layer set is per document — it follows document_activate on ezdxf and is cleared on every document switch on both engines
`drawing_apply_iso_layers` recorded its standard in `_active_layer_set` on
the backend, and `_role_layer` reads it ahead of the PlanSpec to decide where
`dimension_auto` / `construction_xline` file their output. It was neither a
`_DocState` field nor cleared by `_reset_document_state`, so an iso13567
sheet next to a mech one pushed the mech drawing's dimensions onto
`M-DIMEN-T-N` (created on demand), silently — and `drawing_critique` could
not see it because the same stale set drove the critique. The attribute
predates the registry (v1.5 `drawing_new` did not reset it either), but the
per-document claim of Task 21 covered it and the measured attribute list
missed it.
- `_DocState.active_layer_set` + `_ActiveField("active_layer_set")` on
`EzdxfBackend`: the set follows the active entry, bidirectionally.
- `PremiumContract._reset_document_state` clears it (declared on the mixin
like `_plan_spec`), which fixes COM's `_ensure_document_state` switch and
`drawing_new` / `drawing_open` / `disconnect` on both engines.
- tests: `test_active_layer_set_is_per_document` (headless registry, the
reviewer's repro plus the reverse direction) and the COM activate test now
also asserts the set is cleared and `_role_layer('dim')` is back on DIM.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
co-authored by
Claude Opus 5
parent
64cec37cc7
commit
b1c93cdd2a
@@ -36,11 +36,18 @@ class PremiumContract(ABC):
|
||||
|
||||
_plan_spec: PlanSpec | None = None
|
||||
_preflight_result: Any = None
|
||||
# The standard `drawing_apply_iso_layers` last bootstrapped on *this*
|
||||
# drawing (None until it runs) — `_active_layer_set_id` reads it ahead of
|
||||
# the PlanSpec. Drawing-scoped like the plan: a live backend clears it
|
||||
# when AutoCAD's active document changes, the headless registry keeps one
|
||||
# per open document.
|
||||
_active_layer_set: LayerSetId | None = None
|
||||
|
||||
def _reset_document_state(self) -> None:
|
||||
"""Clear metadata that is valid only for the current drawing."""
|
||||
self._plan_spec = None
|
||||
self._preflight_result = None
|
||||
self._active_layer_set = None
|
||||
self._gdt_datums_defined = set()
|
||||
self._gdt_datums_referenced = set()
|
||||
|
||||
|
||||
@@ -977,6 +977,11 @@ class _DocState:
|
||||
transaction_stack: list[Path] = field(default_factory=list)
|
||||
plan_spec: Any = None
|
||||
preflight_result: Any = None
|
||||
# `drawing_apply_iso_layers` records the standard here so `_role_layer`
|
||||
# files dims / scaffolding on that standard's layer; it is per drawing,
|
||||
# not per backend (an iso13567 sheet next to a mech one must not push
|
||||
# the mech drawing's dimensions onto M-DIMEN-T-N).
|
||||
active_layer_set: str | None = None
|
||||
gdt_datums_defined: set = field(default_factory=set)
|
||||
gdt_datums_referenced: set = field(default_factory=set)
|
||||
activated_seq: int = 0
|
||||
@@ -1033,6 +1038,7 @@ class EzdxfBackend(AutoCADBackend):
|
||||
_transaction_stack = _ActiveField("transaction_stack")
|
||||
_plan_spec = _ActiveField("plan_spec")
|
||||
_preflight_result = _ActiveField("preflight_result")
|
||||
_active_layer_set = _ActiveField("active_layer_set")
|
||||
_gdt_datums_defined = _ActiveField("gdt_datums_defined")
|
||||
_gdt_datums_referenced = _ActiveField("gdt_datums_referenced")
|
||||
|
||||
|
||||
@@ -88,6 +88,39 @@ async def test_per_document_state_follows_the_active_entry(backend):
|
||||
assert backend._dirty is False
|
||||
|
||||
|
||||
async def test_active_layer_set_is_per_document(backend):
|
||||
"""The standard ``drawing_apply_iso_layers`` bootstrapped is per drawing.
|
||||
|
||||
It drives ``_role_layer`` — where ``dimension_auto`` and
|
||||
``construction_xline`` file their output — and the critique that checks
|
||||
them. Held on the backend it bled across documents: an iso13567 sheet
|
||||
next to a mech one pushed the mech drawing's dimensions onto
|
||||
``M-DIMEN-T-N`` (created on demand), silently, and ``drawing_critique``
|
||||
could not see it because the same stale set drove the critique.
|
||||
"""
|
||||
await backend.drawing_apply_iso_layers("iso13567")
|
||||
assert backend._role_layer("dim") == "M-DIMEN-T-N"
|
||||
|
||||
second = (await backend.drawing_new())["document"]
|
||||
assert backend._active_layer_set is None, "a fresh drawing has no explicit set"
|
||||
assert backend._role_layer("dim") == "DIM"
|
||||
line = await backend.entity_create_line(0, 0, 50, 0)
|
||||
dims = await backend.dimension_auto([line.handle], style="chain")
|
||||
assert dims[0].layer == "DIM"
|
||||
assert "M-DIMEN-T-N" not in [lyr.name for lyr in await backend.layer_list()]
|
||||
|
||||
# Bidirectional: switching back restores the first document's set …
|
||||
await backend.document_activate("untitled-1")
|
||||
assert backend._active_layer_set == "iso13567"
|
||||
assert backend._role_layer("construction") == "M-CONST-E-N"
|
||||
# … and a set applied on B while A is open does not reach A.
|
||||
await backend.document_activate(second)
|
||||
await backend.drawing_apply_iso_layers("pid")
|
||||
assert backend._role_layer("dim") == "DIM"
|
||||
await backend.document_activate("untitled-1")
|
||||
assert backend._active_layer_set == "iso13567"
|
||||
|
||||
|
||||
async def test_opening_a_file_twice_reloads_it_instead_of_registering_twice(backend, tmp_path):
|
||||
path = tmp_path / "part.dxf"
|
||||
await backend.drawing_save(str(path))
|
||||
@@ -495,6 +528,7 @@ async def test_com_activate_calls_activate_and_resets_document_scope(com_backend
|
||||
backend, app = com_backend
|
||||
await backend._ensure_document_state()
|
||||
backend._plan_spec = object()
|
||||
backend._active_layer_set = "iso13567"
|
||||
result = await backend.document_activate("Second.dwg")
|
||||
assert result == {
|
||||
"ok": True,
|
||||
@@ -505,6 +539,8 @@ async def test_com_activate_calls_activate_and_resets_document_scope(com_backend
|
||||
}
|
||||
assert app.Documents._docs[1].calls == [("Activate", ())]
|
||||
assert backend._plan_spec is None, "a document switch clears drawing-scoped state"
|
||||
assert backend._active_layer_set is None, "the layer set is drawing-scoped too"
|
||||
assert backend._role_layer("dim") == "DIM"
|
||||
with pytest.raises(ValueError, match="no open document named 'Third.dwg'"):
|
||||
await backend.document_activate("Third.dwg")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user