merge: track-e group S
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
@@ -3351,7 +3351,7 @@ Part of `docs/superpowers/plans/2026-09-16-v1.6-settings-implementation.md`. Its
|
||||
- Test: `tests/test_standards_presets.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `PRESETS = {"iso-25": {...17 vars...}, "ansi": {...}}`, `PRESET_VARIABLES` (the 17, spec order), `DIM_VARIABLE_WHITELIST: frozenset` (17 + 16 = 33), `DIM_VARIABLE_RANGES: dict[str, tuple | set]`, `resolve_dimstyle(preset, overrides) -> dict`, `validate_overrides(overrides) -> dict`, `check_dim_value(name, value)`, `describe_preset(name) -> dict`; `TEXT_PRESETS`, `resolve_font(font) -> (font_file, known)`, `validate_textstyle(name, font, height, width_factor, oblique_deg) -> dict`; `MLEADER_PRESETS`, `MLEADER_KEYS`, `resolve_mleaderstyle(preset, overrides) -> dict`.
|
||||
- Produces: `PRESETS = {"iso-25": {...17 vars...}, "ansi": {...}}`, `PRESET_VARIABLES` (the 17, spec order), `DIM_VARIABLE_WHITELIST: frozenset` (17 + 16 = 33), `DIM_VARIABLE_RANGES: dict[str, tuple | set]`, `resolve_dimstyle(preset, overrides) -> dict`, `validate_overrides(overrides) -> dict`, `check_dim_value(name, value)`, `describe_preset(name) -> dict`; the arrowhead vocabulary (added by the Task 9 review fixes and consumed by Task 10's helpers below): `ARROWHEAD_BLOCKS: frozenset` (AutoCAD's nineteen named built-ins, `_OBLIQUE` spelling, pinned equal to ezdxf's `ARROWS.__acad__`), `canonical_arrowhead(key, value) -> str` (what `check_dim_value` returns for `DIMBLK`/`DIMBLK1`/`DIMBLK2`: `""` for closed filled and its aliases `.`/`CLOSEDFILLED`/`_CLOSEDFILLED`, a built-in in any case with or without its underscore → its block name, anything else a user block name under the symbol-name rule — whether that block *exists* is the backend's check against `doc.blocks`, before any write), `ezdxf_arrowhead(canonical) -> str` (the one translation the headless **writer** needs: `_OBLIQUE` → `OBLIQUE`, user blocks and `""` unchanged — ezdxf raises `DXFValueError: Block "_OBLIQUE" does not exist` at `doc.write` and `DXFUndefinedBlockError` at render if the canonical spelling is stored verbatim), `reported_arrowhead(raw) -> str` (the **read** side, never raises: ezdxf reports `OBLIQUE` in-session and `_OBLIQUE` after a reload, COM reports `_OBLIQUE`; both come back as the canonical name, a foreign name passes through); `TEXT_PRESETS`, `resolve_font(font) -> (font_file, known)`, `validate_textstyle(name, font, height, width_factor, oblique_deg) -> dict`; `MLEADER_PRESETS`, `MLEADER_KEYS`, `resolve_mleaderstyle(preset, overrides) -> dict`.
|
||||
- Every refusal is `ValueError` (wrong type: `TypeError`) naming the key, and nothing in this package writes anything — the backends call these before they touch a table.
|
||||
- Groups C and P add `sysvars.py`, `papers.py`, `pdfinfo.py`, `templates.py`, `plot.py` to the same package and import them by path; this `__init__.py` re-exports only group S's names, so those groups never need to edit it.
|
||||
|
||||
@@ -3821,7 +3821,9 @@ LINEWEIGHT_CODES: frozenset[int] = frozenset(int(code) for code in _LINEWEIGHT_T
|
||||
#: * ``("int", low, high)`` — an integer (a float with no fraction is accepted).
|
||||
#: * ``("nonzero_float", low, high)`` — as ``float`` but ``0`` is refused.
|
||||
#: * ``("char",)`` — exactly one character.
|
||||
#: * ``("str",)`` — any string (arrowhead block names; ``""`` is the closed filled arrow).
|
||||
#: * ``("arrow",)`` — an arrowhead: ``""`` (closed filled), one of ``ARROWHEAD_BLOCKS``
|
||||
#: given with or without its underscore in any case, or a user block name under the
|
||||
#: symbol-name rule; ``check_dim_value`` returns ``canonical_arrowhead(key, value)``.
|
||||
#: * ``("name",)`` — a non-empty DXF symbol-table name.
|
||||
#: * a ``set`` — one of its members.
|
||||
DIM_VARIABLE_RANGES: dict[str, tuple | set] = {
|
||||
@@ -3838,15 +3840,20 @@ DIM_VARIABLE_RANGES: dict[str, tuple | set] = {
|
||||
"DIMDSEP": ("char",),
|
||||
"DIMLUNIT": ("int", 1, 6),
|
||||
"DIMZIN": ("int", 0, 15), # a bitmask
|
||||
"DIMBLK": ("str",),
|
||||
"DIMBLK": ("arrow",),
|
||||
"DIMTXSTY": ("name",),
|
||||
"DIMLWD": LINEWEIGHT_CODES,
|
||||
"DIMLWE": LINEWEIGHT_CODES,
|
||||
"DIMSCALE": ("float", 0.0, 1e6), # 0 means "scale to the viewport"
|
||||
# tolerances, rounding, fit, colours, arrowheads — the rest of the whitelist
|
||||
"DIMTOL": {0, 1},
|
||||
"DIMTP": ("float", 0.0, 1e6),
|
||||
"DIMTM": ("float", 0.0, 1e6),
|
||||
# Both signed, as AutoCAD documents them: the displayed lower deviation is
|
||||
# -DIMTM, so a double-positive fit (ISO 286 p6, +0.035/+0.022) stores
|
||||
# DIMTM -0.022 and a double-negative one (f7, -0.020/-0.041) stores DIMTP
|
||||
# -0.020 — exactly what engineering/tolerances.py::build_dim_override emits
|
||||
# per dimension; a style must be able to hold the same numbers.
|
||||
"DIMTP": ("float", -1e6, 1e6),
|
||||
"DIMTM": ("float", -1e6, 1e6),
|
||||
"DIMTOLJ": ("int", 0, 2),
|
||||
"DIMTFAC": ("float", 1e-9, 1e6),
|
||||
"DIMLFAC": ("nonzero_float", -1e6, 1e6),
|
||||
@@ -3857,8 +3864,8 @@ DIM_VARIABLE_RANGES: dict[str, tuple | set] = {
|
||||
"DIMCLRE": ("int", 0, 256),
|
||||
"DIMCLRT": ("int", 0, 256),
|
||||
"DIMSAH": {0, 1},
|
||||
"DIMBLK1": ("str",),
|
||||
"DIMBLK2": ("str",),
|
||||
"DIMBLK1": ("arrow",),
|
||||
"DIMBLK2": ("arrow",),
|
||||
"DIMCEN": ("float", -1e6, 1e6), # negative draws centre lines, 0 none
|
||||
}
|
||||
|
||||
@@ -4224,7 +4231,7 @@ git commit -m "feat(standards): ISO-25 and ANSI dimension, text and leader style
|
||||
- Test: `tests/test_styles.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `resolve_dimstyle`, `validate_overrides`, `PRESET_VARIABLES`, `DIM_VARIABLE_WHITELIST`, `TEXT_PRESETS`, `validate_textstyle`, `MLEADER_KEYS` (Task 9); `sanitize_symbol_name` (`security.py`) — note it raises `ToolError`, not `ValueError`, on an empty or illegal style name, the same refusal the existing block and layer tools give (the skeleton's Global Constraints record this as the one standing exception to the `ValueError`/`TypeError` rule); `_async`/`_require_doc`/`_mark_dirty` (ezdxf), `_run`/`_acad_doc`/`_acad_app`/`_regen`/`deg2rad`/`rad2deg` (COM).
|
||||
- Consumes: `resolve_dimstyle`, `validate_overrides`, `PRESET_VARIABLES`, `DIM_VARIABLE_WHITELIST`, `ARROWHEAD_BLOCKS`, `ezdxf_arrowhead`, `reported_arrowhead`, `TEXT_PRESETS`, `validate_textstyle`, `MLEADER_KEYS` (Task 9) — `validate_overrides` already returns `DIMBLK`/`DIMBLK1`/`DIMBLK2` in the canonical `_OBLIQUE` spelling, which ActiveX takes verbatim but ezdxf's writer refuses, so the headless helpers translate on write (`ezdxf_arrowhead`), canonicalise on read (`reported_arrowhead`, both engines) and refuse a user block absent from `doc.blocks` before any write; `sanitize_symbol_name` (`security.py`) — note it raises `ToolError`, not `ValueError`, on an empty or illegal style name, the same refusal the existing block and layer tools give (the skeleton's Global Constraints record this as the one standing exception to the `ValueError`/`TypeError` rule); `_async`/`_require_doc`/`_mark_dirty` (ezdxf), `_run`/`_acad_doc`/`_acad_app`/`_regen`/`deg2rad`/`rad2deg` (COM).
|
||||
- Produces: the nine `StylesContract` methods on both backends, exactly the plan's signatures. Extra keys beyond the plan's row shapes, on both engines: `dimstyle_list` rows carry `values_available: bool`; `dimstyle_create` carries `written: [vars]`; `dimstyle_set_current` / `textstyle_set_current` carry `changed: bool`; `mleaderstyle_create` carries `textstyle_created`. Names are matched case-insensitively (AutoCAD's rule) and reported in the table's own spelling.
|
||||
- The COM rule, stated once in the code and enforced by the fake: `AcadDimStyle` has `Name` and `CopyFrom` only. Values are written by setting the `DIM*` document variables and `CopyFrom(document)`; making a style current (`ActiveDimStyle`) restores its saved settings and drops unsaved overrides; reading a non-current style's values is impossible, so `dimstyle_list` reports `values` for the current style only. `mleaderstyle_create` stays the `@capability("mleaderstyle")` default on COM (never defined there); `mleaderstyle_list` reads names from the `ACAD_MLEADERSTYLE` dictionary with `values_available: false`.
|
||||
|
||||
@@ -4368,6 +4375,46 @@ async def test_refusals_happen_before_anything_is_written(backend):
|
||||
assert backend._doc.dimstyles.get("ISO-25").dxf.dimdec == 2
|
||||
|
||||
|
||||
async def test_builtin_arrowheads_render_save_and_report_one_spelling(backend, tmp_path):
|
||||
"""`validate_overrides` hands the canonical `_OBLIQUE`; stored verbatim ezdxf
|
||||
raises at render and at `doc.write`. The witness is the rendered INSERT and
|
||||
a save/reopen that reports the same name before and after."""
|
||||
values = resolve_dimstyle("iso-25", {"DIMBLK": "oblique", "DIMSAH": 1, "DIMBLK1": "_DOT",
|
||||
"DIMBLK2": "."})
|
||||
result = await backend.dimstyle_create("ISO-25", values, set_current=True)
|
||||
assert result["values"]["DIMBLK"] == "_OBLIQUE"
|
||||
style = backend._doc.dimstyles.get("ISO-25")
|
||||
assert style.dxf.dimblk == "OBLIQUE" and style.dxf.dimblk1 == "DOT" and style.dxf.dimblk2 == ""
|
||||
dim = await backend.dimension_linear(0, 0, 20, 0, 10, -10)
|
||||
block = backend._doc.blocks.get(backend._doc.entitydb.get(dim.handle).dxf.geometry)
|
||||
assert {e.dxf.name for e in block if e.dxftype() == "INSERT"} == {"_DOT", "_CLOSEDFILLED"}, (
|
||||
"DIMSAH on: the two separate arrowheads win over DIMBLK"
|
||||
)
|
||||
again = await backend.dimstyle_modify("ISO-25", {"DIMBLK": "OBLIQUE", "DIMBLK1": "_dot"})
|
||||
assert again["changed"] == {}, "re-setting a value to itself is not a change (spec §8.3)"
|
||||
path = str(tmp_path / "arrows.dxf")
|
||||
await backend.drawing_save_as(path)
|
||||
await backend.drawing_open(path)
|
||||
rows = {r["name"]: r for r in await backend.dimstyle_list()}
|
||||
assert rows["ISO-25"]["values"]["DIMBLK"] == "_OBLIQUE", "reloaded, the same spelling"
|
||||
reopened = await backend.dimstyle_modify("ISO-25", {"DIMBLK": "oblique"})
|
||||
assert reopened["changed"] == {}
|
||||
|
||||
|
||||
async def test_user_arrowhead_block_must_exist_before_anything_is_written(backend):
|
||||
with pytest.raises(ValueError, match="DIMBLK: block 'MYARROW' does not exist"):
|
||||
await backend.dimstyle_create("X", resolve_dimstyle("iso-25", {"DIMBLK": "MYARROW"}))
|
||||
assert not backend._doc.dimstyles.has_entry("X")
|
||||
await backend.dimstyle_create("ISO-25", resolve_dimstyle("iso-25", None))
|
||||
with pytest.raises(ValueError, match="DIMBLK1: block 'MYARROW' does not exist"):
|
||||
await backend.dimstyle_modify("ISO-25", {"DIMSAH": 1, "DIMBLK1": "MYARROW"})
|
||||
assert not backend._doc.dimstyles.get("ISO-25").dxf.hasattr("dimsah"), "nothing written"
|
||||
backend._doc.blocks.new("MYARROW").add_line((0, 0), (1, 1))
|
||||
result = await backend.dimstyle_modify("ISO-25", {"DIMBLK": "myarrow"})
|
||||
assert result["changed"] == {"DIMBLK": ["", "MYARROW"]}, "the block table's own spelling"
|
||||
assert backend._doc.dimstyles.get("ISO-25").dxf.dimblk == "MYARROW"
|
||||
|
||||
|
||||
async def test_dimstyle_set_current_reports_previous_and_survives_save_reopen(backend, tmp_path):
|
||||
await backend.dimstyle_create("ISO-25", resolve_dimstyle("iso-25", None))
|
||||
result = await backend.dimstyle_set_current("iso-25")
|
||||
@@ -5019,8 +5066,14 @@ def _dimstyle_schema_default(var: str):
|
||||
return None if attrib is None else attrib.default
|
||||
|
||||
|
||||
_ARROWHEAD_VARS = ("DIMBLK", "DIMBLK1", "DIMBLK2")
|
||||
|
||||
|
||||
def _dimstyle_value(style, var: str):
|
||||
"""A style's value for ``var`` in the tool vocabulary (DIMDSEP as the character)."""
|
||||
"""A style's value for ``var`` in the tool vocabulary (DIMDSEP as the
|
||||
character, arrowheads in the canonical ``_OBLIQUE`` spelling)."""
|
||||
from engineering.standards.dimstyles import reported_arrowhead
|
||||
|
||||
attr = var.lower()
|
||||
raw = style.dxf.get(attr) if style.dxf.hasattr(attr) else None
|
||||
if raw is None:
|
||||
@@ -5030,6 +5083,12 @@ def _dimstyle_value(style, var: str):
|
||||
return "," if code == 0 else chr(code)
|
||||
if var == "DIMTXSTY":
|
||||
return str(raw) if raw else "Standard"
|
||||
if var in _ARROWHEAD_VARS:
|
||||
# Measured: ezdxf holds the writer's ``OBLIQUE`` in-session and the
|
||||
# block name ``_OBLIQUE`` after a reload. Raw, one style would be
|
||||
# spelled two ways and re-setting a value to itself would report a
|
||||
# change (spec §8.3); canonicalised, both reads agree.
|
||||
return reported_arrowhead(raw)
|
||||
return raw
|
||||
|
||||
|
||||
@@ -5039,19 +5098,58 @@ def _read_dimstyle_values(style, variables=None) -> dict[str, Any]:
|
||||
return {var: _dimstyle_value(style, var) for var in (variables or PRESET_VARIABLES)}
|
||||
|
||||
|
||||
def _require_arrowhead_blocks(doc, values: dict[str, Any]) -> None:
|
||||
"""Refuse a user arrowhead block the drawing does not define — before any write.
|
||||
|
||||
A built-in (``ARROWHEAD_BLOCKS``) and closed filled (``""``) need no block:
|
||||
ezdxf creates the built-in's block on first use. A user block name passes
|
||||
the data layer (it cannot see the drawing) and, stored, ezdxf raises
|
||||
``DXFUndefinedBlockError`` at the next dimension render and ``DXFValueError:
|
||||
Block "MYARROW" does not exist`` at ``doc.write`` — after the create tool
|
||||
already said ``ok``. ``doc.blocks`` membership is case-insensitive, and a
|
||||
reload reports the block table's own spelling (measured: ``myarrow`` stored,
|
||||
``MYARROW`` after reopen), so the name is rewritten in ``values`` to that
|
||||
spelling here — the same "reported in the table's own spelling" rule the
|
||||
style names follow, and what keeps a re-set after reopen a non-change.
|
||||
"""
|
||||
from engineering.standards.dimstyles import ARROWHEAD_BLOCKS
|
||||
|
||||
for var in _ARROWHEAD_VARS:
|
||||
name = values.get(var)
|
||||
if not name or name in ARROWHEAD_BLOCKS:
|
||||
continue
|
||||
if name not in doc.blocks:
|
||||
raise ValueError(
|
||||
f"{var}: block {name!r} does not exist in this drawing; define it first "
|
||||
"with block_define, or name one of AutoCAD's built-in arrowheads"
|
||||
)
|
||||
values[var] = doc.blocks.get(name).name
|
||||
|
||||
|
||||
def _write_dimstyle_values(style, values: dict[str, Any]) -> None:
|
||||
"""Store typed values (from ``validate_overrides``) on a DIMSTYLE entry.
|
||||
|
||||
DIMRND 0 is AutoCAD's "no rounding"; ezdxf applies ``xround(x, 0.0)`` to a
|
||||
*stored* 0.0 and rounds every dimension to a whole unit, so it is
|
||||
discarded rather than stored (the `_normalise_dimstyle_rounding` lesson).
|
||||
|
||||
Arrowheads arrive in the canonical ``_OBLIQUE`` spelling (what ActiveX
|
||||
takes verbatim); ezdxf's writer wants ``OBLIQUE`` and raises at
|
||||
``doc.write`` on the underscore form, so they go through
|
||||
``ezdxf_arrowhead``. The caller has run ``_require_arrowhead_blocks``.
|
||||
"""
|
||||
from engineering.standards.dimstyles import ezdxf_arrowhead
|
||||
|
||||
for var, value in values.items():
|
||||
attr = var.lower()
|
||||
if var == "DIMRND" and float(value) == 0.0:
|
||||
style.dxf.discard("dimrnd")
|
||||
continue
|
||||
style.dxf.set(attr, ord(value) if var == "DIMDSEP" else value)
|
||||
if var == "DIMDSEP":
|
||||
value = ord(value)
|
||||
elif var in _ARROWHEAD_VARS:
|
||||
value = ezdxf_arrowhead(value)
|
||||
style.dxf.set(attr, value)
|
||||
|
||||
|
||||
def _sync_header_to_dimstyle(doc, style) -> None:
|
||||
@@ -5179,6 +5277,7 @@ Insert immediately before ` # ── corner ops` in `EzdxfBackend` (directly
|
||||
"use dimstyle_modify to change it"
|
||||
)
|
||||
previous = _current_dimstyle_name(doc)
|
||||
_require_arrowhead_blocks(doc, typed)
|
||||
txsty, textstyle_created = _ensure_textstyle(
|
||||
doc, str(typed.get("DIMTXSTY", "Standard")), refusal_key="DIMTXSTY"
|
||||
)
|
||||
@@ -5225,6 +5324,7 @@ Insert immediately before ` # ── corner ops` in `EzdxfBackend` (directly
|
||||
f"DIMTXSTY: text style {typed['DIMTXSTY']!r} does not exist in this drawing; "
|
||||
"create it first with textstyle_create"
|
||||
)
|
||||
_require_arrowhead_blocks(doc, typed)
|
||||
before = _read_dimstyle_values(style, tuple(typed))
|
||||
_write_dimstyle_values(style, typed)
|
||||
after = _read_dimstyle_values(style, tuple(typed))
|
||||
@@ -5458,7 +5558,14 @@ def _com_dimvar_for_report(var: str, raw: Any) -> Any:
|
||||
return "," if raw == 0 else chr(raw)
|
||||
text = str(raw)
|
||||
return text[:1] if text else ","
|
||||
if var in ("DIMBLK", "DIMBLK1", "DIMBLK2", "DIMTXSTY"):
|
||||
if var in ("DIMBLK", "DIMBLK1", "DIMBLK2"):
|
||||
# AutoCAD reports the block name (``_OBLIQUE``, ``""`` for closed
|
||||
# filled) — already canonical; the same read-side rule as ezdxf keeps
|
||||
# the two engines' rows spelled identically.
|
||||
from engineering.standards.dimstyles import reported_arrowhead
|
||||
|
||||
return reported_arrowhead(raw)
|
||||
if var == "DIMTXSTY":
|
||||
return str(raw)
|
||||
return raw
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ name.
|
||||
- `dimstyle_modify(name, overrides)` — `changed` reports only variables that actually moved (the `hatch_edit` rule). Dimensions already using the style are listed in `dimensions_using_style` with `rerender_required: true` on the headless engine: AutoCAD re-renders them on the next regen, but a headless DIMENSION carries its rendered block, so the drawing shows the old style until the dimension is redrawn — stated rather than silent.
|
||||
- `dimstyle_set_current(name)` — `$DIMSTYLE`; the dimension tools then use it (the existing per-dimension override path stays as is).
|
||||
- `textstyle_list()`, `textstyle_create(name, font: "isocp.shx"|"isocpeur.ttf"|"arial.ttf"|"romans.shx"|<file>, height=0.0, width_factor=1.0, oblique_deg=0.0, set_current=False)`, `textstyle_set_current(name)` — `$TEXTSTYLE`; a font file that is neither a bundled preset nor present in the engine's font path is written but reported `font_resolved: false` (AutoCAD substitutes at open; the headless renderer falls back), never refused, because DXF only stores the name.
|
||||
- `mleaderstyle_list()`, `mleaderstyle_create(name, preset: "iso"|"ansi", overrides)` — arrow size, landing gap, text style, text height on ezdxf's `doc.mleader_styles`. ActiveX exposes no MLeaderStyle collection, so the COM engine refuses both with `capability: "mleaderstyle"` (the reason names `leader_create_mleader`'s existing per-leader parameters as the route); `mleaderstyle_list` on COM still reads the names from the `ACAD_MLEADERSTYLE` dictionary.
|
||||
- `mleaderstyle_list()`, `mleaderstyle_create(name, preset: "iso"|"ansi", overrides)` — arrow size, landing gap, text style, text height, both engines: ezdxf on `doc.mleader_styles`; COM through the `ACAD_MLEADERSTYLE` dictionary, whose items are `IAcadMLeaderStyle` objects (`ArrowSize` / `LandingGap` / `TextHeight` in drawing units, `TextStyle` a name — verified against the AutoCAD 2026 type library), created with `Dictionaries.Item("ACAD_MLEADERSTYLE").AddObject(name, "AcDbMLeaderStyle")` followed by the property writes. ActiveX has no `MLeaderStyles` *collection* property, which is not an engine boundary — no `mleaderstyle` capability key exists.
|
||||
- `drawing_apply_standard(standard: "iso"|"ansi", layers: bool = True, units: bool = True)` — one call: the dimstyle preset (created and set current), its text style, `drawing_settings` (units mm, decimal linear and angular units, LTSCALE 1, DIMSCALE 1; the decimal separator comes from the preset) and, with `layers`, the `mech` layer set for both standards (ANSI layer naming is company-specific; the set reuses the mech names with ISO 128 lineweights — only styles and the separator differ between the two). Returns, per item, whether it was created or was already present.
|
||||
|
||||
## 5. Settings (SECTION 20 shares these; 3 tools + facade growth)
|
||||
@@ -187,9 +187,10 @@ A state is the layer table snapshot `{layer: {on, frozen, locked, color, linetyp
|
||||
|
||||
### 8.1 Capability keys (added to **both** maps)
|
||||
|
||||
`mleaderstyle` (COM false), `dwgprops` (ezdxf false: summary fields), `dwt_write`
|
||||
(ezdxf false), `live_application`, `preferences`, `interactive_prompt` (ezdxf
|
||||
false). `tests/test_capability_contract.py` enforces both maps.
|
||||
`dwgprops` (ezdxf false: summary fields), `dwt_write` (ezdxf false),
|
||||
`live_application`, `preferences`, `interactive_prompt` (ezdxf false).
|
||||
`tests/test_capability_contract.py` enforces both maps. (`mleaderstyle` was
|
||||
listed here as COM false; the ActiveX route exists — §4.2 — so there is no key.)
|
||||
|
||||
### 8.2 Packs, profiles, discovery
|
||||
|
||||
@@ -219,7 +220,9 @@ shop-floor synonyms; the discovery golden set gains ≥ 10 queries for them
|
||||
(A0 841×1189 … A4 210×297; ANSI A 216×279 … E 864×1118), every catalog
|
||||
sysvar has type+meaning+engines.
|
||||
- Dual-engine tests for every tool (ezdxf real; COM fake-ActiveX asserting call
|
||||
shapes: `DimStyles.Add`, `TextStyles.Add`, `Layout.ConfigName/…`,
|
||||
shapes: `DimStyles.Add`, `TextStyles.Add`,
|
||||
`Dictionaries.Item("ACAD_MLEADERSTYLE").AddObject(name, "AcDbMLeaderStyle")`,
|
||||
`Layout.ConfigName/…`,
|
||||
`Documents.Item().Activate`, `Dictionaries.Add`+`AddXRecord`, `Views.Add`,
|
||||
`UserCoordinateSystems.Add`, `Preferences.OpenSave.*`, `SummaryInfo.*`,
|
||||
`Utility.GetPoint`).
|
||||
|
||||
+143
-2
@@ -3,10 +3,10 @@
|
||||
"schema_version": 1,
|
||||
"package_version": "1.5.1",
|
||||
"totals": {
|
||||
"tools": 166,
|
||||
"tools": 176,
|
||||
"resources": 8,
|
||||
"prompts": 5,
|
||||
"groups": 20
|
||||
"groups": 21
|
||||
},
|
||||
"groups": {
|
||||
"analysis": 12,
|
||||
@@ -24,6 +24,7 @@
|
||||
"pid": 9,
|
||||
"premium": 12,
|
||||
"solids": 5,
|
||||
"styles": 10,
|
||||
"system": 7,
|
||||
"templates": 2,
|
||||
"transactions": 3,
|
||||
@@ -450,6 +451,62 @@
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dimstyle_create",
|
||||
"group": "styles",
|
||||
"cost": "mutate",
|
||||
"summary": "Create a dimension style from the ISO-25 or ANSI preset, with per-variable overrides.",
|
||||
"tags": [
|
||||
"create",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: Create Dimension Style",
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dimstyle_list",
|
||||
"group": "styles",
|
||||
"cost": "read",
|
||||
"summary": "List dimension styles with their ISO-25/ANSI variables and the current one.",
|
||||
"tags": [
|
||||
"query",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: List Dimension Styles",
|
||||
"readOnlyHint": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dimstyle_modify",
|
||||
"group": "styles",
|
||||
"cost": "mutate",
|
||||
"summary": "Change DIM* variables on an existing dimension style; reports only what moved.",
|
||||
"tags": [
|
||||
"modify",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: Modify Dimension Style",
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dimstyle_set_current",
|
||||
"group": "styles",
|
||||
"cost": "safe",
|
||||
"summary": "Make a dimension style current so new dimensions use it.",
|
||||
"tags": [
|
||||
"modify",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: Set Current Dimension Style",
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drawing_apply_iso_layers",
|
||||
"group": "premium",
|
||||
@@ -464,6 +521,20 @@
|
||||
"destructiveHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drawing_apply_standard",
|
||||
"group": "styles",
|
||||
"cost": "mutate",
|
||||
"summary": "Put the drawing on ISO or ANSI in one call: dimstyle, text style, units, mech layers.",
|
||||
"tags": [
|
||||
"drawing",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Drawing: Apply Drafting Standard",
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drawing_audit",
|
||||
"group": "drawing",
|
||||
@@ -1717,6 +1788,34 @@
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mleaderstyle_create",
|
||||
"group": "styles",
|
||||
"cost": "mutate",
|
||||
"summary": "Create a multileader style from the ISO or ANSI preset, on both engines.",
|
||||
"tags": [
|
||||
"create",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: Create Multileader Style",
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mleaderstyle_list",
|
||||
"group": "styles",
|
||||
"cost": "read",
|
||||
"summary": "List multileader styles: arrow size, landing gap, text style and height.",
|
||||
"tags": [
|
||||
"query",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: List Multileader Styles",
|
||||
"readOnlyHint": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pid_equipment_list",
|
||||
"group": "pid",
|
||||
@@ -2155,6 +2254,48 @@
|
||||
"destructiveHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "textstyle_create",
|
||||
"group": "styles",
|
||||
"cost": "mutate",
|
||||
"summary": "Create a text style from a bundled font (isocp, isocpeur, arial, romans) or any file.",
|
||||
"tags": [
|
||||
"create",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: Create Text Style",
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "textstyle_list",
|
||||
"group": "styles",
|
||||
"cost": "read",
|
||||
"summary": "List text styles: font file, height, width factor, oblique angle.",
|
||||
"tags": [
|
||||
"query",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: List Text Styles",
|
||||
"readOnlyHint": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "textstyle_set_current",
|
||||
"group": "styles",
|
||||
"cost": "safe",
|
||||
"summary": "Make a text style current so new text uses it.",
|
||||
"tags": [
|
||||
"modify",
|
||||
"style"
|
||||
],
|
||||
"annotations": {
|
||||
"title": "Styles: Set Current Text Style",
|
||||
"readOnlyHint": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "titleblock_apply_iso_a3",
|
||||
"group": "engineering",
|
||||
|
||||
Reference in New Issue
Block a user