Files
dxfmakros/lib/sivas_mapping.py
T
s.hensch 6044c35957 feat: Eckrad-Dialog, Kreiselname, Hoehen-Neuberechnung beim Export
- Eckrad: eigener DCL-Dialog (eckrad_edit.dcl) beim Einfuegen und per
  Doppelklick (EckradEdit); Sivas-Merkmale am Kreisel ausgerichtet
  (2950, 3381, 3992 Ja/Nein); bei Sep./Scanner-Zaehlung ausgenommen
- Kreisel: eigener Name bleibt in Bezeichnung + Beschriftung erhalten
- Sivas: Kreisel/Eckrad unterschiedlicher Hoehe nicht mehr zusammengefasst
- Export: Hoehen-Attribute in Z verschobener Kreisel/Eckrad/VF/GF neu
  berechnet
- GF-Edit: Einfuegehoehe aus aktueller Z-Koordinate
2026-10-13 14:24:01 +02:00

131 lines
4.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
sivas_mapping.py - Liest die Attribut->Sivas-Merkmal-Zuordnung aus
cfg/sivas.cfg und wendet sie auf ein Block-Attribut-Dict an.
Einzige Quelle fuer die "einfachen" build_*_details-Zuordnungen in
export_sivas.py (siehe cfg/sivas.cfg fuer das Zeilenformat und die
Begruendung, warum nur die einfachen Faelle hier landen).
"""
import configparser
import functools
import os
def cfg_path_from_env(default_dir=None):
"""Pfad zu sivas.cfg: DXFM_CFG env var, sonst <repo>/cfg."""
dxfm_cfg = os.environ.get("DXFM_CFG")
if dxfm_cfg:
return os.path.join(dxfm_cfg, "sivas.cfg")
base = default_dir or os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base, "cfg", "sivas.cfg")
def _parse_wert(roh):
"""Zerlegt eine Config-Wertzeile "attribut|alt_attribut:default|transform"
in (attribut, alt_attribut_oder_None, default, transform_oder_None).
Reihenfolge beim Parsen: erst am ":" in (attributteil, defaultteil)
trennen (nur der erste ":" zaehlt, ein Default-Text soll selbst keinen
":" enthalten muessen), danach im defaultteil am LETZTEN "|" den
Transform-Namen abtrennen (ein Default-Text wie "ohne HARTCOAT..."
enthaelt kein "|"). attributteil wird am ERSTEN "|" in Attribut/
Fallback-Attribut gesplittet.
"""
roh = roh.strip()
if ":" in roh:
attribut_teil, rest = roh.split(":", 1)
else:
attribut_teil, rest = roh, ""
transform = None
default = rest.strip()
if "|" in rest:
default_teil, transform_teil = rest.rsplit("|", 1)
default = default_teil.strip()
transform = transform_teil.strip() or None
attribut_teil = attribut_teil.strip()
alt_attribut = None
if "|" in attribut_teil:
attribut, alt_attribut = (p.strip() for p in attribut_teil.split("|", 1))
else:
attribut = attribut_teil
alt_attribut = alt_attribut or None
return (attribut or None, alt_attribut, default, transform)
@functools.lru_cache(maxsize=None)
def load_sivas_cfg(cfg_path):
"""Liest sivas.cfg einmal je Pfad (Prozess-Cache)."""
parser = configparser.ConfigParser(inline_comment_prefixes=None)
parser.optionxform = str # Keys (Merkmalnummern/Klartext-Keys) case-sensitive erhalten
parser.read(cfg_path, encoding="utf-8")
return parser
def load_section_mapping(section, cfg_path=None):
"""Liest einen Abschnitt aus sivas.cfg.
Rueckgabe: dict merkmal -> (attribut, alt_attribut, default, transform),
wie von _parse_wert geliefert. Bei fehlender Datei/Sektion: leeres dict -
Aufrufer bekommt dann einfach keine Merkmale aus der Config (bisheriges
Verhalten vor der Config-Einfuehrung, kein harter Fehler).
"""
if cfg_path is None:
cfg_path = cfg_path_from_env()
parser = load_sivas_cfg(cfg_path)
mapping = {}
if parser.has_section(section):
for merkmal, roh in parser.items(section):
mapping[merkmal] = _parse_wert(roh)
return mapping
def load_flat_mapping(section, cfg_path=None):
"""Liest einen Abschnitt als einfaches dict key -> value (z.B.
[geruest_typ_anzeige]: ASCII-Wert -> Sivas-Klartext), ohne das
attribut/default/transform-Format von load_section_mapping."""
if cfg_path is None:
cfg_path = cfg_path_from_env()
parser = load_sivas_cfg(cfg_path)
if parser.has_section(section):
return {k: v.strip() for k, v in parser.items(section)}
return {}
def anwenden(section_mapping, attribs, transforms):
"""Wendet eine per load_section_mapping() gelesene Zuordnung auf ein
Block-Attribut-Dict an.
transforms: dict transform_name -> Funktion(wert) -> wert. Ein in der
Config genannter, aber hier unbekannter Transform-Name wird ignoriert
(Rohwert bleibt unveraendert) statt abzubrechen - ein Tippfehler in
sivas.cfg darf den Export nicht zum Stillstand bringen.
Rueckgabe: dict merkmal -> wert. Ohne Transform wird der Rohwert zu str()
gewandelt (bisheriges Verhalten der build_*_details-Funktionen: alles
Merkmalnummer-Werte sind Strings). Ein Transform liefert seinen
Rueckgabewert UNVERAENDERT (er ist selbst fuer den Typ verantwortlich).
"""
ergebnis = {}
for merkmal, (attribut, alt_attribut, default, transform) in section_mapping.items():
if attribut is not None:
wert = attribs.get(attribut)
if wert is None and alt_attribut is not None:
wert = attribs.get(alt_attribut)
if wert is None:
wert = default
else:
wert = default
if transform:
fn = transforms.get(transform)
if fn is not None:
ergebnis[merkmal] = fn(wert)
continue
ergebnis[merkmal] = str(wert)
return ergebnis