base_x/base_y were only float()-cast, so a NaN base point was written into the BLOCK record; a primitive on a layer the drawing lacks was written as a dangling reference doc.audit() never flags (and on COM would fail mid-loop after Blocks.Add). validate_base_point names the key; the layer table is probed before the first write and the missing names are refused, or created and reported as layers_created when create_layers=true (new optional kwarg, contract + both engines + tool). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
"""Blocks and block references.
|
|
|
|
Split out of the single 1854-line ``AutoCADBackend`` ABC in v1.5.0 (M7).
|
|
``AutoCADBackend`` composes every contract in this package, so importing
|
|
``backends.base.AutoCADBackend`` is unchanged for callers.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from backends.base import BlockInfo, EntityInfo
|
|
|
|
|
|
class BlockContract(ABC):
|
|
@abstractmethod
|
|
async def block_list(self) -> list[BlockInfo]: ...
|
|
|
|
@abstractmethod
|
|
async def block_insert(
|
|
self,
|
|
name: str,
|
|
x: float,
|
|
y: float,
|
|
scale_x: float = 1.0,
|
|
scale_y: float = 1.0,
|
|
rotation: float = 0.0,
|
|
attributes: dict | None = None,
|
|
layer: str | None = None,
|
|
) -> EntityInfo: ...
|
|
|
|
@abstractmethod
|
|
async def block_explode(self, handle: str) -> dict: ...
|
|
|
|
@abstractmethod
|
|
async def block_get_attributes(self, handle: str) -> dict: ...
|
|
|
|
@abstractmethod
|
|
async def block_set_attributes(self, handle: str, attributes: dict) -> dict: ...
|
|
|
|
@abstractmethod
|
|
async def block_create_from_entities(
|
|
self,
|
|
name: str,
|
|
handles: list[str],
|
|
base_x: float = 0.0,
|
|
base_y: float = 0.0,
|
|
) -> dict: ...
|
|
|
|
@abstractmethod
|
|
async def block_define(
|
|
self,
|
|
name: str,
|
|
entities: list[dict],
|
|
attdefs: list[dict] | None = None,
|
|
base_x: float = 0.0,
|
|
base_y: float = 0.0,
|
|
overwrite: bool = False,
|
|
create_layers: bool = False,
|
|
) -> dict:
|
|
"""Create (or with ``overwrite`` replace the contents of) a block
|
|
definition from typed primitive specs and ATTDEF specs — see
|
|
``backends/block_specs.py`` for the spec vocabulary.
|
|
|
|
Refusals, all before any write: a malformed spec (``TypeError`` naming
|
|
``entities[i]``/``attdefs[i]`` and the key), a non-finite or non-numeric
|
|
``base_x``/``base_y`` (``TypeError`` naming it), a name clash without
|
|
``overwrite`` (``ValueError``), and a primitive ``layer`` that does not
|
|
exist in the drawing (``ValueError`` listing the missing names) unless
|
|
``create_layers`` is true, in which case the missing layers are created
|
|
with the engine's defaults and listed in ``layers_created``. Returns
|
|
``{ok, name, entity_count, attdef_count, replaced, layers_created,
|
|
backend}``."""
|
|
...
|