fix(task-9): finite text-style numbers, one symbol-name rule, canonical DIMBLK arrowheads
Three review findings on the standards data layer, each a value the layer
let through that a backend would then write as a silent wrong number or a
drawing that can no longer be saved:
* validate_textstyle never checked math.isfinite, unlike its siblings; nan
and inf passed every comparison and reached the STYLE record verbatim.
It now has the same _number helper dimstyles and mleaderstyles use.
* The three private _ILLEGAL_NAME_CHARS copies omitted \n \r \t that
security._FORBIDDEN_SYMBOL_CHARS holds, so 'a\nb' was accepted as a text
style, DIMTXSTY or leader text style and ezdxf refused the save. The rule
now lives once in engineering/standards/names.py (fastmcp-free), the
three modules import it, and a test pins its character set equal to
security's and its output equal to illegal_symbol_name_chars.
* DIMBLK/DIMBLK1/DIMBLK2 were ("str",): any string went through, and the
test pinned '_OBLIQUE', which ezdxf's writer refuses at doc.write while
the COM engine wants exactly that spelling. They are now ("arrow",):
canonical_arrowhead accepts a built-in with or without its underscore in
any case (and '', '.', CLOSEDFILLED for the closed filled default), emits
AutoCAD's documented block-name spelling (also what ezdxf reports after a
load), and holds user block names to the symbol-name rule; ARROWHEAD_BLOCKS
is pinned equal to ezdxf's ARROWS vocabulary, and ezdxf_arrowhead is the
one translation the headless writer needs, proved by exporting all twenty
headlessly and reading each back as its canonical name.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
co-authored by
Claude Opus 5
parent
54fac471a9
commit
827719fdd0
@@ -11,6 +11,8 @@ from __future__ import annotations
|
||||
import math
|
||||
from typing import Any
|
||||
|
||||
from engineering.standards.names import check_name
|
||||
|
||||
__all__ = ["MLEADER_KEYS", "MLEADER_PRESETS", "resolve_mleaderstyle"]
|
||||
|
||||
MLEADER_PRESETS: dict[str, dict[str, Any]] = {
|
||||
@@ -20,8 +22,6 @@ MLEADER_PRESETS: dict[str, dict[str, Any]] = {
|
||||
|
||||
MLEADER_KEYS: tuple[str, ...] = ("arrow_size", "landing_gap", "text_style", "text_height")
|
||||
|
||||
_ILLEGAL_NAME_CHARS = frozenset('<>/\\":;?*|,=`')
|
||||
|
||||
|
||||
def _positive(key: str, value: Any, *, allow_zero: bool = False) -> float:
|
||||
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
||||
@@ -51,14 +51,7 @@ def resolve_mleaderstyle(preset: str, overrides: dict | None = None) -> dict[str
|
||||
f"overrides: {raw_key!r} is not a leader style key; allowed: {list(MLEADER_KEYS)}"
|
||||
)
|
||||
if name == "text_style":
|
||||
if not isinstance(value, str) or not value.strip():
|
||||
raise ValueError("text_style: a text style name cannot be empty")
|
||||
bad = sorted(set(value.strip()) & _ILLEGAL_NAME_CHARS)
|
||||
if bad:
|
||||
raise ValueError(
|
||||
f"text_style: {value!r} contains characters DXF forbids in a name: {bad}"
|
||||
)
|
||||
values[name] = value.strip()
|
||||
values[name] = check_name(name, value, what="text style name")
|
||||
elif name == "landing_gap":
|
||||
values[name] = _positive(name, value, allow_zero=True)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user