fix(blocks): entity_create_block_ref refuses an undefined or layout block before writing, on both engines

Track A's task-1 gate covered block_insert only; the sibling tool still
returned a handle for a typo'd name that doc.audit() later deleted, and
both tools accepted *Model_Space (a reference cycle). One gate per engine
(_require_block / _require_block_defined) is now shared by both placing
tools: non-string name -> TypeError, unknown -> ValueError naming it,
layout block -> ValueError, all before add_blockref / InsertBlock.

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-16 21:13:44 +03:00
co-authored by Claude Opus 5
parent 49fc6ac6a5
commit b9510bf377
4 changed files with 278 additions and 8 deletions
+26
View File
@@ -193,6 +193,30 @@ def _msp():
return doc.ModelSpace
def _require_block_defined(doc, name):
"""``doc.Blocks.Item(name)``, or a ``ValueError`` before ``InsertBlock`` runs.
``InsertBlock`` with an unknown name raises a bare COM error after the call
has already been dispatched; refusing here names the block, costs one
``Blocks.Item`` probe and matches the headless engine's message. A layout
block (``IsLayout``) cannot be inserted into itself — same refusal by name.
Shared by ``block_insert`` and ``entity_create_block_ref``.
"""
if not isinstance(name, str) or not name.strip():
raise TypeError("block name must be a non-empty string")
try:
block = doc.Blocks.Item(name)
except Exception as exc:
raise ValueError(f"block {name!r} is not defined") from exc
try:
is_layout = bool(block.IsLayout)
except Exception:
is_layout = False
if is_layout:
raise ValueError(f"block {name!r} is a layout block and cannot be inserted")
return block
_BUILTIN_LINETYPES = {"continuous", "bylayer", "byblock"}
@@ -2479,6 +2503,7 @@ class ComBackend(AutoCADBackend):
layer=None,
) -> EntityInfo:
def _sync():
_require_block_defined(_acad_doc(), name)
mspace = _msp()
ref = mspace.InsertBlock(
_apoint(x, y),
@@ -3248,6 +3273,7 @@ class ComBackend(AutoCADBackend):
layer=None,
) -> EntityInfo:
def _sync():
_require_block_defined(_acad_doc(), name)
mspace = _msp()
ref = mspace.InsertBlock(
_apoint(x, y),