diff --git a/web/backend/app/services/designators.py b/web/backend/app/services/designators.py index 47b8d4c..0e8cceb 100644 --- a/web/backend/app/services/designators.py +++ b/web/backend/app/services/designators.py @@ -170,30 +170,48 @@ def _split_expression_parts(expr: str) -> list[str]: return parts -def _resolve_property(name: str, props: dict[str, str], designator: str = "") -> str: +def _resolve_property( + name: str, + props: dict[str, str], + designator: str = "", + resolving: frozenset[str] | None = None, +) -> str: + if resolving is None: + resolving = frozenset() + if name in resolving: + return "" if name == "Designator": raw = designator or props.get("Designator", "") else: raw = props.get(name, "") if not raw: return "" - if raw.startswith("=") or (raw.startswith('"') and raw.endswith('"') and len(raw) > 1): - return resolve_expression(raw, props, designator) + if raw.startswith("="): + return resolve_expression(raw, props, designator, resolving | {name}) return raw -def resolve_expression(value: str, props: dict[str, str], designator: str = "") -> str: +def resolve_expression( + value: str, + props: dict[str, str], + designator: str = "", + resolving: frozenset[str] | None = None, +) -> str: """ Altium complex string: ='literal'+"Property"+Name - single quotes = literal text - double quotes = component property reference - bare identifiers = property reference """ + if resolving is None: + resolving = frozenset() + if len(resolving) > 64: + return "" if not value: return "" value = value.strip() if value.startswith('"') and value.endswith('"') and not value.startswith('="'): - return _resolve_property(value[1:-1], props, designator) + return _resolve_property(value[1:-1], props, designator, resolving) if not value.startswith("="): return value @@ -204,9 +222,9 @@ def resolve_expression(value: str, props: dict[str, str], designator: str = "") if part.startswith("'") and part.endswith("'") and len(part) >= 2: result.append(part[1:-1]) elif part.startswith('"') and part.endswith('"') and len(part) >= 2: - result.append(_resolve_property(part[1:-1], props, designator)) + result.append(_resolve_property(part[1:-1], props, designator, resolving)) elif part == "Designator": result.append(designator or props.get("Designator", "")) else: - result.append(_resolve_property(part, props, designator)) + result.append(_resolve_property(part, props, designator, resolving)) return "".join(result)