diff --git a/backends/contracts/premium.py b/backends/contracts/premium.py index a33679b..f1f090b 100644 --- a/backends/contracts/premium.py +++ b/backends/contracts/premium.py @@ -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() diff --git a/backends/ezdxf_backend.py b/backends/ezdxf_backend.py index 92fa017..b119a58 100644 --- a/backends/ezdxf_backend.py +++ b/backends/ezdxf_backend.py @@ -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") diff --git a/tests/test_documents.py b/tests/test_documents.py index 7b3b600..4a159d3 100644 --- a/tests/test_documents.py +++ b/tests/test_documents.py @@ -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")