engineering/arch/symbols.py is pure: grid_prims() draws each structural axis on the grid role - its CENTER linetype comes from the A-GRID-E-N row, no primitive sets one - with a 5 mm (paper) bubble and its label touching both ends, on the symbol role so the circle does not print dashed. Numbers run along x and letters along y (A..Z, AA, ... none skipped) unless labels names them; positions are sorted, duplicates and label-count mismatches refused by path. symbol_prims() draws the four plan symbols: the north arrow (a circle, an arrow turned CCW from +Y, the vocab(lang) north letter upright beyond the tip), the section mark (the cut line, a labelled bubble past each end and a viewing arrow at each end, p1/p2 relative to the origin), the level mark (the triangle, its line and the value formatted +3.00 / ±0.00, with a decimal comma in Turkish) and the elevation mark (a circle whose pointers are the tangents from r*sqrt(2) touching it at +/-45 degrees). An unknown kind is refused with the list, a parameter the kind does not take with the ones it does. Every size is a declared paper-mm drafting choice times the plot scale, not a standards value. arch_grid and arch_symbol draw through draw_prims with ARCH_ROLE_LAYER; alias records (COLUMNGRIDADD, English and Turkish synonyms), a regenerated inventory, the README snapshot at 233 tools and the branch-local group snapshot (entity_creation 21) complete the registration. Beyond the plan: grid_axes refuses a labels value that is not a dict and a labels.x / labels.y that is not a list (a string was split into one label per character, a number raised a bare TypeError). No new ActiveX member: a live run on AutoCAD 2026 (scratch document, closed after) drew the grid and all four symbols through draw_prims - A-GRID-E-N created with CENTER, bubbles, texts and symbols on A-SYMB-T-N, the Turkish north letter K and the level "+3,00". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
65 lines
2.3 KiB
Python
65 lines
2.3 KiB
Python
"""arch_grid / arch_symbol 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.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_grid_reports_its_axes_and_bubble_size(client):
|
|
result = (
|
|
await client.call_tool(
|
|
"arch_grid", {"x_axes": [0.0, 4000.0, 8000.0], "y_axes": [0.0, 5000.0], "scale": 100}
|
|
)
|
|
).structured_content
|
|
assert [axis["label"] for axis in result["axes"]["x"]] == ["1", "2", "3"]
|
|
assert [axis["label"] for axis in result["axes"]["y"]] == ["A", "B"]
|
|
assert result["bubble_radius"] == 500.0
|
|
assert len(result["handles"]) == 5 * 5
|
|
assert result["layers"] == sorted({ARCH_ROLE_LAYER["grid"], ARCH_ROLE_LAYER["symbol"]})
|
|
|
|
|
|
async def test_symbol_level_and_north_arrow_in_turkish(client):
|
|
result = (
|
|
await client.call_tool(
|
|
"arch_symbol",
|
|
{"kind": "level", "x": 0.0, "y": 0.0, "params": {"value": 3.0}, "lang": "tr"},
|
|
)
|
|
).structured_content
|
|
assert result["counts"] == {"poly": 1, "line": 1, "text": 1}
|
|
north = (
|
|
await client.call_tool(
|
|
"arch_symbol", {"kind": "north_arrow", "x": 0.0, "y": 0.0, "lang": "tr"}
|
|
)
|
|
).structured_content
|
|
assert north["layer"] == ARCH_ROLE_LAYER["symbol"]
|
|
assert north["counts"] == {"circle": 1, "poly": 1, "text": 1}
|
|
|
|
|
|
async def test_refusals_are_tool_errors(client):
|
|
with pytest.raises(
|
|
ToolError, match="kinds are north_arrow, section_mark, level, elevation_mark"
|
|
):
|
|
await client.call_tool("arch_symbol", {"kind": "compass", "x": 0.0, "y": 0.0})
|
|
with pytest.raises(ToolError, match="p1 and p2 are required"):
|
|
await client.call_tool(
|
|
"arch_symbol", {"kind": "section_mark", "x": 0.0, "y": 0.0, "params": {"label": "A"}}
|
|
)
|
|
with pytest.raises(ToolError, match="y_axes: a grid needs at least one axis"):
|
|
await client.call_tool("arch_grid", {"x_axes": [0.0], "y_axes": []})
|