fix(task-4): block_define dedupes requested layers case-insensitively so one layer in two spellings is created and reported once
DXF and ActiveX layer tables are case-insensitive, but block_define collected the primitives' layers with a case-sensitive set. A request naming 'Alpha' and 'ALPHA' with create_layers=True made ezdxf add the first, then raise DXFTableEntryError on the second after the write — layer left behind, no block, surfaced as an internal error instead of a named refusal. COM ran Layers.Add twice, got the existing layer back the second time, and reported two layers created for one that appeared; the two engines diverged and the refusal message without create_layers named the same layer twice. referenced_layers() in backends/block_specs.py keys the set on the folded name and keeps the first spelling; both engines consume it. _FakeLayers in the hardening tests now matches Item/Add case-insensitively and returns the existing record on a duplicate Add, as the ActiveX table does, so the COM path is pinned. 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
375c9f4c70
commit
b464bcdaf5
@@ -219,6 +219,24 @@ def validate_base_point(base_x, base_y) -> tuple[float, float]:
|
||||
)
|
||||
|
||||
|
||||
def referenced_layers(entities: list[dict]) -> list[str]:
|
||||
"""The distinct layers ``block_define``'s primitives reference, other than ``0``.
|
||||
|
||||
DXF and ActiveX layer tables are case-insensitive, so the set is keyed on
|
||||
the folded name and keeps the first spelling seen: a request naming
|
||||
``Alpha`` and ``ALPHA`` wants *one* layer. Deduping case-sensitively let
|
||||
ezdxf write ``ALPHA`` and then raise ``DXFTableEntryError`` on ``Alpha``
|
||||
mid-call, and let COM report two layers created for one ``Layers.Add``
|
||||
that took effect.
|
||||
"""
|
||||
seen: dict[str, str] = {}
|
||||
for spec in entities:
|
||||
layer = spec["layer"]
|
||||
if layer != "0" and layer.lower() not in seen:
|
||||
seen[layer.lower()] = layer
|
||||
return sorted(seen.values())
|
||||
|
||||
|
||||
def validate_attribute_values(attributes, where: str = "attributes") -> dict[str, str]:
|
||||
"""``{TAG: value}`` for ``block_insert`` / ``block_set_attributes`` as the
|
||||
strings that will be written, refused before any write.
|
||||
|
||||
Reference in New Issue
Block a user