engineering/arch/catalogue.py is the standard-parts pattern of track B for an architectural plan: twenty authored plan symbols in two families - thirteen furniture items (single and double bed, wardrobe, three-seat sofa, armchair, chair, dining table with four chairs, desk, kitchen counter run, fridge, bookshelf, nightstand, coffee table) and seven sanitary items (WC, bidet, wall basin, shower tray, bathtub, kitchen sink, washing machine). Every size is a nominal catalogue dimension and says so in SIZE_BASIS, in each row and in both tool docstrings; no standard is cited because none fixes these sizes. Each item is typed block_define primitives on layer 0 inside [0, w] x [0, d], origin at the back-left corner with the wall side along +X - a test holds all twenty to their footprint. catalogue() searches name, family and the English and Turkish labels, ignoring case and Turkish diacritics (buzdolabi finds buzdolabı). insert_item() defines ARCH_<NAME> once, creates the furniture or sanitary layer from its ARCH_LAYERS row when missing (live ActiveX refuses a missing layer), inserts with an invisible ITEM attribute, and refuses an unknown name with the nearest catalogue names before any write. SECTION 25 opens on this branch with the two tools, alias records (INSERT, ADCENTER, TOOLPALETTES and English/Turkish synonyms), a regenerated inventory, the README snapshot at 231 tools, and the branch-local group snapshot (entity_query 10, entity_creation 19) that the track F merge recomputes. No new ActiveX call: insert_item composes the existing layer_list, layer_create, block_list, block_define and block_insert members. Run once live through ComBackend on AutoCAD 2026 (scratch document, closed after): all twenty items defined and inserted, a second double_bed insert reported defined=false, ITEM read back as double_bed, 20 ARCH_* blocks, 21 INSERTs on A-FURN-E-N / A-SANR-E-N, both layers created at ACI 5 / 0.18 mm. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
55 lines
2.0 KiB
Python
55 lines
2.0 KiB
Python
"""arch_catalogue_list / arch_catalogue_insert through a real MCP client."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
import pytest_asyncio
|
|
from fastmcp import Client
|
|
from fastmcp.exceptions import ToolError
|
|
|
|
import server
|
|
from engineering.arch.catalogue import SIZE_BASIS
|
|
from engineering.arch.layers import ARCH_ROLE_LAYER
|
|
|
|
pytestmark = pytest.mark.asyncio
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def client(monkeypatch):
|
|
monkeypatch.setenv("AUTOCAD_MCP_BACKEND", "ezdxf")
|
|
async with Client(server.mcp) as connected:
|
|
await connected.call_tool("drawing_new", {})
|
|
yield connected
|
|
|
|
|
|
async def test_list_searches_in_turkish_and_states_the_size_basis(client):
|
|
result = (
|
|
await client.call_tool("arch_catalogue_list", {"query": "yatak", "lang": "tr"})
|
|
).structured_content
|
|
assert result["count"] == 2
|
|
assert [row["name"] for row in result["items"]] == ["single_bed", "double_bed"]
|
|
assert result["items"][0]["label"] == "tek kişilik yatak"
|
|
assert result["size_basis"] == SIZE_BASIS
|
|
assert result["families"] == ["furniture", "sanitary"]
|
|
|
|
|
|
async def test_insert_twice_defines_once(client):
|
|
first = (
|
|
await client.call_tool("arch_catalogue_insert", {"name": "wc", "x": 0.0, "y": 0.0})
|
|
).structured_content
|
|
second = (
|
|
await client.call_tool(
|
|
"arch_catalogue_insert", {"name": "wc", "x": 1000.0, "y": 0.0, "rotation": 180.0}
|
|
)
|
|
).structured_content
|
|
assert first["defined"] is True and second["defined"] is False
|
|
assert first["block_name"] == second["block_name"] == "ARCH_WC"
|
|
assert first["layer"] == ARCH_ROLE_LAYER["sanitary"]
|
|
|
|
|
|
async def test_an_unknown_item_is_a_tool_error_naming_the_nearest(client):
|
|
with pytest.raises(ToolError, match="nearest: wardrobe"):
|
|
await client.call_tool("arch_catalogue_insert", {"name": "wardrob", "x": 0.0, "y": 0.0})
|
|
with pytest.raises(ToolError, match="furniture, sanitary"):
|
|
await client.call_tool("arch_catalogue_list", {"family": "garden"})
|