fixed complex strings
This commit is contained in:
@@ -446,17 +446,11 @@ class AltiumParser:
|
|||||||
|
|
||||||
|
|
||||||
def make_complex_string(text: str, props: list[ComponentProperty]) -> str:
|
def make_complex_string(text: str, props: list[ComponentProperty]) -> str:
|
||||||
text = sanitize_text(text)
|
from app.services.designators import resolve_expression
|
||||||
if not text.startswith("="):
|
|
||||||
return text
|
|
||||||
expr = text[1:]
|
|
||||||
mapping = {p.name: p.text for p in props}
|
mapping = {p.name: p.text for p in props}
|
||||||
|
designator = mapping.get("Designator", "")
|
||||||
def repl(m: re.Match) -> str:
|
return sanitize_text(resolve_expression(text, mapping, designator))
|
||||||
key = m.group(1)
|
|
||||||
return mapping.get(key, "")
|
|
||||||
|
|
||||||
return sanitize_text(re.sub(r"['\"]([^'\"]+)['\"]", repl, expr))
|
|
||||||
|
|
||||||
|
|
||||||
def find_prjpcb(extract_dir: Path) -> Optional[Path]:
|
def find_prjpcb(extract_dir: Path) -> Optional[Path]:
|
||||||
|
|||||||
@@ -146,33 +146,67 @@ def split_long_text(text: str, max_length: int) -> list[str]:
|
|||||||
return parts or [""]
|
return parts or [""]
|
||||||
|
|
||||||
|
|
||||||
def resolve_expression(value: str, props: dict[str, str]) -> str:
|
def _split_expression_parts(expr: str) -> list[str]:
|
||||||
|
"""Split Altium expression by + outside quotes."""
|
||||||
|
parts: list[str] = []
|
||||||
|
current: list[str] = []
|
||||||
|
in_double = False
|
||||||
|
in_single = False
|
||||||
|
for ch in expr:
|
||||||
|
if ch == '"' and not in_single:
|
||||||
|
in_double = not in_double
|
||||||
|
current.append(ch)
|
||||||
|
elif ch == "'" and not in_double:
|
||||||
|
in_single = not in_single
|
||||||
|
current.append(ch)
|
||||||
|
elif ch == "+" and not in_double and not in_single:
|
||||||
|
if current:
|
||||||
|
parts.append("".join(current).strip())
|
||||||
|
current = []
|
||||||
|
else:
|
||||||
|
current.append(ch)
|
||||||
|
if current:
|
||||||
|
parts.append("".join(current).strip())
|
||||||
|
return parts
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_property(name: str, props: dict[str, str], designator: str = "") -> str:
|
||||||
|
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)
|
||||||
|
return raw
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_expression(value: str, props: dict[str, str], designator: str = "") -> str:
|
||||||
|
"""
|
||||||
|
Altium complex string: ='literal'+"Property"+Name
|
||||||
|
- single quotes = literal text
|
||||||
|
- double quotes = component property reference
|
||||||
|
- bare identifiers = property reference
|
||||||
|
"""
|
||||||
|
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)
|
||||||
if not value.startswith("="):
|
if not value.startswith("="):
|
||||||
return value
|
return value
|
||||||
expr = value[1:]
|
|
||||||
result = []
|
result: list[str] = []
|
||||||
i = 0
|
for part in _split_expression_parts(value[1:]):
|
||||||
while i < len(expr):
|
if not part:
|
||||||
ch = expr[i]
|
continue
|
||||||
if ch in "'\"":
|
if part.startswith("'") and part.endswith("'") and len(part) >= 2:
|
||||||
quote = ch
|
result.append(part[1:-1])
|
||||||
i += 1
|
elif part.startswith('"') and part.endswith('"') and len(part) >= 2:
|
||||||
start = i
|
result.append(_resolve_property(part[1:-1], props, designator))
|
||||||
while i < len(expr) and expr[i] != quote:
|
elif part == "Designator":
|
||||||
i += 1
|
result.append(designator or props.get("Designator", ""))
|
||||||
result.append(expr[start:i])
|
|
||||||
i += 1
|
|
||||||
elif ch == "+":
|
|
||||||
i += 1
|
|
||||||
elif ch.isspace():
|
|
||||||
i += 1
|
|
||||||
else:
|
else:
|
||||||
start = i
|
result.append(_resolve_property(part, props, designator))
|
||||||
while i < len(expr) and expr[i] not in "+'\"":
|
|
||||||
i += 1
|
|
||||||
key = expr[start:i].strip()
|
|
||||||
val = props.get(key, "")
|
|
||||||
if val.startswith("="):
|
|
||||||
val = resolve_expression(val, props)
|
|
||||||
result.append(val)
|
|
||||||
return "".join(result)
|
return "".join(result)
|
||||||
|
|||||||
@@ -24,8 +24,12 @@ class ComponentView:
|
|||||||
is_fitted: bool = True
|
is_fitted: bool = True
|
||||||
|
|
||||||
def get(self, key: str, default: str = "") -> str:
|
def get(self, key: str, default: str = "") -> str:
|
||||||
|
if key == "Designator":
|
||||||
|
return self.designator or self.properties.get("Designator", default)
|
||||||
raw = self.properties.get(key, default)
|
raw = self.properties.get(key, default)
|
||||||
return resolve_expression(raw, self.properties) if raw else default
|
if not raw:
|
||||||
|
return default
|
||||||
|
return resolve_expression(raw, self.properties, self.designator)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
Reference in New Issue
Block a user