refactor: create_numbers ohne Kopie von error_collector
Fehler/Warnungen als zwei einfache Listen (neue_meldungen, meldungen_als_dict) statt der aus kabellaengen kopierten ErrorCollector-Klasse; lib/error_collector.py entfernt. Format der Fehlerdatei unveraendert, an sechs Testzeichnungen gegen das Original verglichen (identische Nummern und Fehlerdateien). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8abb6b3c65
commit
4100cbfb97
4 files changed
+97
-184
No files matched your search
+88
-59
@@ -1,4 +1,5 @@
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -6,7 +7,35 @@ from pathlib import Path
|
||||
import ezdxf
|
||||
from ezdxf.lldxf.const import DXFStructureError
|
||||
|
||||
from error_collector import ErrorCollector, write_json_file
|
||||
|
||||
# ============================================================================
|
||||
# Meldungen: zwei einfache Listen von (art, text) - Fehler und Warnungen.
|
||||
# Ersetzt die Fehlersammler-Klasse ErrorCollector aus kabellaengen (lib/error_collector.py),
|
||||
# damit keine Kopie davon in diesem Repo liegt.
|
||||
# ============================================================================
|
||||
|
||||
def neue_meldungen():
|
||||
"""Leere Meldungssammlung: {"errors": [(art, text), ...], "warnings": [...]}."""
|
||||
return {"errors": [], "warnings": []}
|
||||
|
||||
|
||||
def meldungen_als_dict(meldungen):
|
||||
"""Fuer die Fehlerdatei nach Art gruppiert, Format wie bisher:
|
||||
{"errors": {art: [text, ...]}, "warnings": {...}} - leere Teile entfallen."""
|
||||
erg = {}
|
||||
for teil in ("errors", "warnings"):
|
||||
gruppen = {}
|
||||
for art, text in meldungen[teil]:
|
||||
gruppen.setdefault(art, []).append(text)
|
||||
if gruppen:
|
||||
erg[teil] = gruppen
|
||||
return erg
|
||||
|
||||
|
||||
def write_json_file(data, out_dir, filename):
|
||||
"""data als JSON (UTF-8, eingerueckt) nach out_dir/filename schreiben."""
|
||||
with open(Path(out_dir) / filename, 'w', encoding='utf-8') as fh:
|
||||
json.dump(data, fh, indent=2, ensure_ascii=False, default=str)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -37,7 +66,7 @@ def get_dxf_file(filepath: Path):
|
||||
return doc
|
||||
|
||||
|
||||
def extract_block_attributes(doc, insert, error_collector=None) -> dict:
|
||||
def extract_block_attributes(doc, insert, meldungen=None) -> dict:
|
||||
"""
|
||||
Alle Attribute eines INSERT als {tag: text}. Unterstuetzt die zweistufige
|
||||
Blockstruktur der Renamer-Bloecke (aeusserer Block mit LWPOLYLINE und einem
|
||||
@@ -64,9 +93,9 @@ def extract_block_attributes(doc, insert, error_collector=None) -> dict:
|
||||
attributes[attrib.dxf.tag] = attrib.dxf.text
|
||||
break
|
||||
except Exception as e:
|
||||
if error_collector:
|
||||
if meldungen:
|
||||
error_msg = f"Fehler beim Extrahieren der Attribute aus Block '{insert.dxf.name}': {e}"
|
||||
error_collector.add_warnings({"attribute_extraction_error": error_msg})
|
||||
meldungen["warnings"].append(("attribute_extraction_error", error_msg))
|
||||
|
||||
return attributes
|
||||
|
||||
@@ -377,7 +406,7 @@ def point_near_polyline(point, polyline_points, max_distance=500.0):
|
||||
return min_dist_sq <= (max_distance * max_distance)
|
||||
|
||||
|
||||
def find_symbols_in_boundary(doc, msp, boundary, target_layers, attributes, error_collector=None, polyline_max_distance=500.0):
|
||||
def find_symbols_in_boundary(doc, msp, boundary, target_layers, attributes, meldungen=None, polyline_max_distance=500.0):
|
||||
"""
|
||||
Findet alle Symbole (INSERT-Blöcke) innerhalb des angegebenen Bereichs auf den Ziel-Layern.
|
||||
|
||||
@@ -411,7 +440,7 @@ def find_symbols_in_boundary(doc, msp, boundary, target_layers, attributes, erro
|
||||
|
||||
# Prüfe ob der Block Attribute hat (direkt oder in zweistufiger Struktur)
|
||||
# Verwende extract_block_attributes um beides zu unterstützen
|
||||
symbol_attribs = extract_block_attributes(doc, entity, error_collector)
|
||||
symbol_attribs = extract_block_attributes(doc, entity, meldungen)
|
||||
|
||||
if not symbol_attribs:
|
||||
continue
|
||||
@@ -758,7 +787,7 @@ def validate_direction_with_geometry(direction, is_rectangle):
|
||||
return True, f"Unbekannte DIRECTION '{direction}' - Verarbeitung wird fortgesetzt"
|
||||
|
||||
|
||||
def collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector):
|
||||
def collect_and_group_renamer_blocks(doc, msp, renamer_layers, meldungen):
|
||||
"""
|
||||
Erster Pass: Sammelt und gruppiert alle Renamer-Blöcke nach Konfiguration.
|
||||
|
||||
@@ -773,7 +802,7 @@ def collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector):
|
||||
# Finde alle INSERT-Blöcke auf diesem Layer
|
||||
for insert in msp.query(f'INSERT[layer=="{layer}"]'):
|
||||
# Extrahiere Attribute (unterstützt zweistufige Blockstruktur)
|
||||
attributes = extract_block_attributes(doc, insert, error_collector)
|
||||
attributes = extract_block_attributes(doc, insert, meldungen)
|
||||
|
||||
if not attributes:
|
||||
print(f" Block ohne Attribute gefunden an Position {insert.dxf.insert}")
|
||||
@@ -796,7 +825,7 @@ def collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector):
|
||||
if boundary is None:
|
||||
error_msg = f"Keine Polylinie/Rechteck im Renamer-Block '{block_name}' an Position {insert.dxf.insert} gefunden"
|
||||
print(f" FEHLER: {error_msg}")
|
||||
error_collector.add_errors({"missing_boundary": error_msg})
|
||||
meldungen["errors"].append(("missing_boundary", error_msg))
|
||||
continue
|
||||
|
||||
print(f" Boundary gefunden mit {len(boundary)} Punkten (Rechteck: {is_rectangle})")
|
||||
@@ -809,12 +838,12 @@ def collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector):
|
||||
if not is_valid:
|
||||
error_msg = f"Renamer-Block '{block_name}' an Position {insert.dxf.insert}: {validation_error}"
|
||||
print(f" FEHLER: {error_msg}")
|
||||
error_collector.add_errors({"direction_geometry_mismatch": error_msg})
|
||||
meldungen["errors"].append(("direction_geometry_mismatch", error_msg))
|
||||
continue
|
||||
elif validation_error:
|
||||
# Warnung bei unbekannter DIRECTION, aber fortfahren
|
||||
print(f" WARNUNG: {validation_error}")
|
||||
error_collector.add_warnings({"unknown_direction": validation_error})
|
||||
meldungen["warnings"].append(("unknown_direction", validation_error))
|
||||
|
||||
# Erstelle Konfigurationsschlüssel und gruppiere
|
||||
config_key = get_renamer_config_key(attributes)
|
||||
@@ -825,7 +854,7 @@ def collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector):
|
||||
return renamer_groups
|
||||
|
||||
|
||||
def find_template_symbols_in_geometry(doc, msp, group_blocks, error_collector):
|
||||
def find_template_symbols_in_geometry(doc, msp, group_blocks, meldungen):
|
||||
"""
|
||||
Findet alle Symbole mit '@' die geometrisch in den Renamer-Bereichen liegen,
|
||||
unabhängig vom Layer.
|
||||
@@ -834,7 +863,7 @@ def find_template_symbols_in_geometry(doc, msp, group_blocks, error_collector):
|
||||
doc: DXF-Dokument
|
||||
msp: Modelspace
|
||||
group_blocks: Liste von (insert, boundary, attributes, is_rectangle) Tupeln
|
||||
error_collector: ErrorCollector für Fehlerbehandlung
|
||||
meldungen: Meldungen (neue_meldungen) fuer Fehler/Warnungen
|
||||
|
||||
Returns:
|
||||
Liste von Dictionaries mit 'layer', 'position', 'io' für jedes gefundene Symbol
|
||||
@@ -842,7 +871,7 @@ def find_template_symbols_in_geometry(doc, msp, group_blocks, error_collector):
|
||||
symbols_in_geometry = []
|
||||
for insert, boundary, attributes, is_rectangle in group_blocks:
|
||||
for entity in msp.query('INSERT'):
|
||||
symbol_attribs = extract_block_attributes(doc, entity, error_collector)
|
||||
symbol_attribs = extract_block_attributes(doc, entity, meldungen)
|
||||
if not symbol_attribs:
|
||||
continue
|
||||
|
||||
@@ -862,7 +891,7 @@ def find_template_symbols_in_geometry(doc, msp, group_blocks, error_collector):
|
||||
|
||||
|
||||
def create_no_symbols_found_error_message(block_name, direction, layer_names, group_blocks,
|
||||
doc, msp, error_collector):
|
||||
doc, msp, meldungen):
|
||||
"""
|
||||
Erstellt eine detaillierte Fehlermeldung wenn keine Symbole in einem Renamer-Bereich gefunden wurden.
|
||||
|
||||
@@ -873,7 +902,7 @@ def create_no_symbols_found_error_message(block_name, direction, layer_names, gr
|
||||
group_blocks: Liste von (insert, boundary, attributes, is_rectangle) Tupeln
|
||||
doc: DXF-Dokument
|
||||
msp: Modelspace
|
||||
error_collector: ErrorCollector für Fehlerbehandlung
|
||||
meldungen: Meldungen (neue_meldungen) fuer Fehler/Warnungen
|
||||
|
||||
Returns:
|
||||
Fehlermeldungs-String
|
||||
@@ -882,7 +911,7 @@ def create_no_symbols_found_error_message(block_name, direction, layer_names, gr
|
||||
for insert, _, _, _ in group_blocks]
|
||||
|
||||
# Prüfe ob es Symbole mit @ gibt, die geometrisch im Bereich liegen (egal auf welchem Layer)
|
||||
symbols_in_geometry = find_template_symbols_in_geometry(doc, msp, group_blocks, error_collector)
|
||||
symbols_in_geometry = find_template_symbols_in_geometry(doc, msp, group_blocks, meldungen)
|
||||
|
||||
# Erstelle Fehlermeldung basierend auf gefundenen Symbolen
|
||||
if symbols_in_geometry and not layer_names:
|
||||
@@ -917,7 +946,7 @@ def create_no_symbols_found_error_message(block_name, direction, layer_names, gr
|
||||
)
|
||||
|
||||
|
||||
def collect_symbols_from_group(doc, msp, renamer_layers, group_blocks, block_name, error_collector, polyline_max_distance=500.0):
|
||||
def collect_symbols_from_group(doc, msp, renamer_layers, group_blocks, block_name, meldungen, polyline_max_distance=500.0):
|
||||
"""
|
||||
Sammelt alle Symbole aus allen Boundaries einer Renamer-Gruppe.
|
||||
Prüft auf Duplikate (Symbole in mehreren Bereichen).
|
||||
@@ -928,7 +957,7 @@ def collect_symbols_from_group(doc, msp, renamer_layers, group_blocks, block_nam
|
||||
renamer_layers: Layer auf denen nach Renamer-Blöcken gesucht wird
|
||||
group_blocks: Liste von (insert, boundary, attributes, is_rectangle) Tupeln
|
||||
block_name: Name des Renamer-Blocks (für Fehlermeldungen)
|
||||
error_collector: ErrorCollector für Fehlerbehandlung
|
||||
meldungen: Meldungen (neue_meldungen) fuer Fehler/Warnungen
|
||||
polyline_max_distance: Maximale Distanz zur Polylinie (aus Config)
|
||||
|
||||
Returns:
|
||||
@@ -939,7 +968,7 @@ def collect_symbols_from_group(doc, msp, renamer_layers, group_blocks, block_nam
|
||||
|
||||
for insert, boundary, attributes, is_rectangle in group_blocks:
|
||||
# Finde Symbole innerhalb dieses Bereichs
|
||||
symbols = find_symbols_in_boundary(doc, msp, boundary, renamer_layers, attributes, error_collector, polyline_max_distance)
|
||||
symbols = find_symbols_in_boundary(doc, msp, boundary, renamer_layers, attributes, meldungen, polyline_max_distance)
|
||||
|
||||
# Füge Symbole hinzu, aber nur wenn das Entity noch nicht gesehen wurde
|
||||
for symbol in symbols:
|
||||
@@ -962,12 +991,12 @@ def collect_symbols_from_group(doc, msp, renamer_layers, group_blocks, block_nam
|
||||
f"{', '.join([f'({p[0]:.1f}, {p[1]:.1f})' for p in existing_positions])}"
|
||||
)
|
||||
print(f" FEHLER: {error_msg}")
|
||||
error_collector.add_errors({"symbol_in_multiple_boundaries": error_msg})
|
||||
meldungen["errors"].append(("symbol_in_multiple_boundaries", error_msg))
|
||||
|
||||
return all_symbols
|
||||
|
||||
|
||||
def process_renamer_groups(doc, msp, renamer_layers, renamer_groups, error_collector, polyline_max_distance=500.0):
|
||||
def process_renamer_groups(doc, msp, renamer_layers, renamer_groups, meldungen, polyline_max_distance=500.0):
|
||||
"""
|
||||
Zweiter Pass: Verarbeitet jede Renamer-Block-Gruppe.
|
||||
Sammelt Symbole, sortiert sie und nummeriert sie.
|
||||
@@ -992,7 +1021,7 @@ def process_renamer_groups(doc, msp, renamer_layers, renamer_groups, error_colle
|
||||
print(f"\n Verarbeite Gruppe: {block_name} ({len(group_blocks)} Renamer-Blöcke)")
|
||||
|
||||
# Sammle Symbole aus ALLEN Boundaries dieser Gruppe
|
||||
all_symbols = collect_symbols_from_group(doc, msp, renamer_layers, group_blocks, block_name, error_collector, polyline_max_distance)
|
||||
all_symbols = collect_symbols_from_group(doc, msp, renamer_layers, group_blocks, block_name, meldungen, polyline_max_distance)
|
||||
|
||||
print(f" Gesamt {len(all_symbols)} eindeutige Template-Symbole aus {len(group_blocks)} Blöcken")
|
||||
|
||||
@@ -1000,10 +1029,10 @@ def process_renamer_groups(doc, msp, renamer_layers, renamer_groups, error_colle
|
||||
# Fehlermeldung: Keine Symbole gefunden
|
||||
layer_names = get_layer_names_from_attributes(reference_attributes)
|
||||
error_msg = create_no_symbols_found_error_message(
|
||||
block_name, direction, layer_names, group_blocks, doc, msp, error_collector
|
||||
block_name, direction, layer_names, group_blocks, doc, msp, meldungen
|
||||
)
|
||||
print(f" FEHLER: {error_msg}")
|
||||
error_collector.add_errors({"no_symbols_found": error_msg})
|
||||
meldungen["errors"].append(("no_symbols_found", error_msg))
|
||||
continue
|
||||
|
||||
# Für POLYLINE_PATH: Hole die Polylinie vom ersten Block
|
||||
@@ -1029,21 +1058,21 @@ def process_renamer_groups(doc, msp, renamer_layers, renamer_groups, error_colle
|
||||
return all_renamed
|
||||
|
||||
|
||||
def find_symbols_with_at_in_io(doc, msp, error_collector):
|
||||
def find_symbols_with_at_in_io(doc, msp, meldungen):
|
||||
"""
|
||||
Findet alle Symbole mit "@" im IO-Attribut.
|
||||
|
||||
Args:
|
||||
doc: DXF-Dokument
|
||||
msp: Modelspace
|
||||
error_collector: ErrorCollector für Fehlerbehandlung
|
||||
meldungen: Meldungen (neue_meldungen) fuer Fehler/Warnungen
|
||||
|
||||
Returns:
|
||||
Liste von Dictionaries mit Symbol-Informationen
|
||||
"""
|
||||
symbols_with_at = []
|
||||
for entity in msp.query('INSERT'):
|
||||
symbol_attribs = extract_block_attributes(doc, entity, error_collector)
|
||||
symbol_attribs = extract_block_attributes(doc, entity, meldungen)
|
||||
if not symbol_attribs:
|
||||
continue
|
||||
|
||||
@@ -1138,7 +1167,7 @@ def create_wrong_layer_warning(symbol, wrong_layer_info):
|
||||
)
|
||||
|
||||
|
||||
def check_symbols_in_boundaries(doc, msp, renamer_groups, error_collector, polyline_max_distance=500.0):
|
||||
def check_symbols_in_boundaries(doc, msp, renamer_groups, meldungen, polyline_max_distance=500.0):
|
||||
"""
|
||||
Dritter Pass: Prüft ob alle Symbole mit "@" im IO in einem Renamer-Bereich liegen.
|
||||
|
||||
@@ -1156,7 +1185,7 @@ def check_symbols_in_boundaries(doc, msp, renamer_groups, error_collector, polyl
|
||||
all_boundaries.append((boundary, attributes, insert.dxf.insert))
|
||||
|
||||
# Finde alle Symbole mit "@" im IO-Attribut
|
||||
symbols_with_at = find_symbols_with_at_in_io(doc, msp, error_collector)
|
||||
symbols_with_at = find_symbols_with_at_in_io(doc, msp, meldungen)
|
||||
|
||||
# Prüfe für jedes Symbol, ob es in mindestens einem Renamer-Bereich liegt
|
||||
symbols_not_in_any_boundary = []
|
||||
@@ -1180,7 +1209,7 @@ def check_symbols_in_boundaries(doc, msp, renamer_groups, error_collector, polyl
|
||||
# Warnung: Symbol liegt geometrisch im Bereich, aber Layer stimmt nicht
|
||||
warning_msg = create_wrong_layer_warning(symbol, wrong_layer_info)
|
||||
print(f" WARNUNG: {warning_msg}")
|
||||
error_collector.add_warnings({"symbol_wrong_layer": warning_msg})
|
||||
meldungen["warnings"].append(("symbol_wrong_layer", warning_msg))
|
||||
# NICHT als Fehler hinzufügen - Warnung reicht aus
|
||||
else:
|
||||
# Fehler: Symbol liegt weder geometrisch noch vom Layer her in einem Renamer-Bereich
|
||||
@@ -1195,7 +1224,7 @@ def check_symbols_in_boundaries(doc, msp, renamer_groups, error_collector, polyl
|
||||
f"enthält '@' im IO-Attribut, liegt aber in keinem Renamer-Bereich."
|
||||
)
|
||||
print(f" FEHLER: {error_msg}")
|
||||
error_collector.add_errors({"symbol_with_at_not_in_boundary": error_msg})
|
||||
meldungen["errors"].append(("symbol_with_at_not_in_boundary", error_msg))
|
||||
else:
|
||||
print(f" Alle {len(symbols_with_at)} Symbole mit '@' im IO liegen in einem Renamer-Bereich.")
|
||||
|
||||
@@ -1231,14 +1260,14 @@ def rectangles_overlap(boundary1, boundary2):
|
||||
return not no_overlap
|
||||
|
||||
|
||||
def check_overlapping_renamer_blocks(renamer_groups, error_collector):
|
||||
def check_overlapping_renamer_blocks(renamer_groups, meldungen):
|
||||
"""
|
||||
Prüft ob sich Renamer-Rechtecke überlappen.
|
||||
Polyline-Pfade (DIRECTION=POLYLINE_PATH) werden nicht geprüft.
|
||||
|
||||
Args:
|
||||
renamer_groups: Dictionary mit gruppierten Renamer-Blöcken
|
||||
error_collector: ErrorCollector für Fehlerbehandlung
|
||||
meldungen: Meldungen (neue_meldungen) fuer Fehler/Warnungen
|
||||
"""
|
||||
print("\n" + "="*60)
|
||||
print("Prüfe auf überlappende Renamer-Bereiche")
|
||||
@@ -1287,12 +1316,12 @@ def check_overlapping_renamer_blocks(renamer_groups, error_collector):
|
||||
f"Symbole könnten mehrfach nummeriert werden."
|
||||
)
|
||||
print(f" {error_msg}")
|
||||
error_collector.add_errors({"overlapping_renamer_blocks": error_msg})
|
||||
meldungen["errors"].append(("overlapping_renamer_blocks", error_msg))
|
||||
else:
|
||||
print(f"\nOK: Keine Überlappungen zwischen {len(rectangle_renamers)} Renamer-Rechtecken gefunden")
|
||||
|
||||
|
||||
def process_renamer_blocks(doc, msp, renamer_layers, error_collector, polyline_max_distance=500.0):
|
||||
def process_renamer_blocks(doc, msp, renamer_layers, meldungen, polyline_max_distance=500.0):
|
||||
"""
|
||||
Verarbeitet alle Renamer-Blöcke auf den angegebenen Layern.
|
||||
Gruppiert Blöcke mit identischer Konfiguration und nummeriert alle Symbole
|
||||
@@ -1307,21 +1336,21 @@ def process_renamer_blocks(doc, msp, renamer_layers, error_collector, polyline_m
|
||||
- renamer_groups: Dictionary der gruppierten Renamer-Blöcke
|
||||
"""
|
||||
# Erster Pass: Sammle und gruppiere alle Renamer-Blöcke
|
||||
renamer_groups = collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector)
|
||||
renamer_groups = collect_and_group_renamer_blocks(doc, msp, renamer_layers, meldungen)
|
||||
|
||||
# Prüfe auf überlappende Renamer-Bereiche
|
||||
check_overlapping_renamer_blocks(renamer_groups, error_collector)
|
||||
check_overlapping_renamer_blocks(renamer_groups, meldungen)
|
||||
|
||||
# Zweiter Pass: Verarbeite jede Gruppe
|
||||
all_renamed = process_renamer_groups(doc, msp, renamer_layers, renamer_groups, error_collector, polyline_max_distance)
|
||||
all_renamed = process_renamer_groups(doc, msp, renamer_layers, renamer_groups, meldungen, polyline_max_distance)
|
||||
|
||||
# Dritter Pass: Prüfe ob alle Symbole mit "@" im IO in einem Renamer-Bereich liegen
|
||||
check_symbols_in_boundaries(doc, msp, renamer_groups, error_collector, polyline_max_distance)
|
||||
check_symbols_in_boundaries(doc, msp, renamer_groups, meldungen, polyline_max_distance)
|
||||
|
||||
return all_renamed, renamer_groups
|
||||
|
||||
|
||||
def collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, error_collector, polyline_max_distance=500.0):
|
||||
def collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, meldungen, polyline_max_distance=500.0):
|
||||
"""
|
||||
Sammelt alle Symbole aus allen Renamer-Gruppen für Visualisierungszwecke.
|
||||
|
||||
@@ -1330,7 +1359,7 @@ def collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, er
|
||||
msp: Modelspace
|
||||
renamer_groups: Dictionary mit gruppierten Renamer-Blöcken
|
||||
renamer_layers: Liste der Layer mit Renamer-Blöcken
|
||||
error_collector: ErrorCollector für Fehlerbehandlung
|
||||
meldungen: Meldungen (neue_meldungen) fuer Fehler/Warnungen
|
||||
polyline_max_distance: Maximale Distanz zur Polylinie (aus Config)
|
||||
|
||||
Returns:
|
||||
@@ -1347,7 +1376,7 @@ def collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, er
|
||||
|
||||
for insert, boundary, attributes, is_rectangle in group_blocks:
|
||||
# Finde Symbole innerhalb dieses Bereichs
|
||||
symbols = find_symbols_in_boundary(doc, msp, boundary, renamer_layers, attributes, error_collector, polyline_max_distance)
|
||||
symbols = find_symbols_in_boundary(doc, msp, boundary, renamer_layers, attributes, meldungen, polyline_max_distance)
|
||||
|
||||
# Füge Symbole hinzu, aber nur wenn das Entity noch nicht gesehen wurde
|
||||
for symbol in symbols:
|
||||
@@ -1371,12 +1400,12 @@ def process_single_file(dxf_path, work_dir, renamer_layers, polyline_max_distanc
|
||||
args: Argparse-Argumente
|
||||
|
||||
Returns:
|
||||
Tuple (success, error_collector):
|
||||
Tuple (success, meldungen):
|
||||
- success: True wenn erfolgreich verarbeitet
|
||||
- error_collector: ErrorCollector mit gesammelten Fehlern/Warnungen
|
||||
- meldungen: Meldungen (neue_meldungen) mit gesammelten Fehlern/Warnungen
|
||||
"""
|
||||
# Initialisiere ErrorCollector für diese Datei
|
||||
error_collector = ErrorCollector()
|
||||
# Meldungen fuer diese Datei
|
||||
meldungen = neue_meldungen()
|
||||
|
||||
print(f"\n{'='*80}")
|
||||
print(f"Verarbeite Datei: {dxf_path.name}")
|
||||
@@ -1397,7 +1426,7 @@ def process_single_file(dxf_path, work_dir, renamer_layers, polyline_max_distanc
|
||||
print("Starte Verarbeitung der Renamer-Blöcke")
|
||||
print("="*60 + "\n")
|
||||
|
||||
renamed_symbols, renamer_groups = process_renamer_blocks(doc, msp, renamer_layers, error_collector, polyline_max_distance)
|
||||
renamed_symbols, renamer_groups = process_renamer_blocks(doc, msp, renamer_layers, meldungen, polyline_max_distance)
|
||||
|
||||
print("\n" + "="*60)
|
||||
print(f"Verarbeitung abgeschlossen: {len(renamed_symbols)} Symbole nummeriert")
|
||||
@@ -1411,7 +1440,7 @@ def process_single_file(dxf_path, work_dir, renamer_layers, polyline_max_distanc
|
||||
|
||||
# Zeichne Symbol-Rahmen wenn gewünscht
|
||||
if args.show_symbol_frames:
|
||||
all_symbols = collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, error_collector, polyline_max_distance)
|
||||
all_symbols = collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, meldungen, polyline_max_distance)
|
||||
if all_symbols:
|
||||
draw_symbol_frames(doc, msp, all_symbols)
|
||||
else:
|
||||
@@ -1467,9 +1496,9 @@ def process_single_file(dxf_path, work_dir, renamer_layers, polyline_max_distanc
|
||||
print(f"Ergebnisse in JSON gespeichert: {output_dir / output_filename}")
|
||||
|
||||
# Schreibe Fehler-Datei nur wenn Fehler oder Warnungen vorhanden sind
|
||||
if error_collector.has_errors_or_warnings():
|
||||
if (meldungen["errors"] or meldungen["warnings"]):
|
||||
if args.errorfile:
|
||||
error_data = error_collector.get_all_issues()
|
||||
error_data = meldungen_als_dict(meldungen)
|
||||
error_path = Path(args.errorfile)
|
||||
|
||||
# Wenn nur ein Dateiname ohne Pfad angegeben wurde, speichere im work-Ordner
|
||||
@@ -1486,19 +1515,19 @@ def process_single_file(dxf_path, work_dir, renamer_layers, polyline_max_distanc
|
||||
else:
|
||||
# Keine explizite Fehlerdatei angegeben, generiere eine basierend auf Input-Datei
|
||||
error_filename = f"{dxf_path.stem}_errors.json"
|
||||
error_data = error_collector.get_all_issues()
|
||||
error_data = meldungen_als_dict(meldungen)
|
||||
write_json_file(error_data, dxf_path.parent, error_filename)
|
||||
print(f"Fehler/Warnungen gespeichert: {dxf_path.parent / error_filename}")
|
||||
|
||||
# Status-Meldung
|
||||
if error_collector.has_errors():
|
||||
if meldungen["errors"]:
|
||||
print("\n!!! Es sind Fehler aufgetreten !!!")
|
||||
return False, error_collector
|
||||
elif error_collector.has_errors_or_warnings():
|
||||
return False, meldungen
|
||||
elif (meldungen["errors"] or meldungen["warnings"]):
|
||||
print("\n(Warnungen vorhanden, aber keine kritischen Fehler)")
|
||||
return True, error_collector
|
||||
return True, meldungen
|
||||
else:
|
||||
return True, error_collector
|
||||
return True, meldungen
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
@@ -1552,9 +1581,9 @@ def main(argv=None):
|
||||
print(f"Datei nicht gefunden: {dxf_path}")
|
||||
return 1
|
||||
|
||||
_success, error_collector = process_single_file(dxf_path, dxf_path.parent, renamer_layers,
|
||||
_success, meldungen = process_single_file(dxf_path, dxf_path.parent, renamer_layers,
|
||||
polyline_max_distance, args)
|
||||
return 1 if error_collector.has_errors() else 0
|
||||
return 1 if meldungen["errors"] else 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
"""
|
||||
ErrorCollector - Gemeinsame Klasse zum Sammeln von Fehlern und Warnungen
|
||||
|
||||
Diese Klasse wird von getpositions.py und drawdxf.py verwendet, um Fehler
|
||||
und Warnungen während der Verarbeitung zu sammeln und zu verwalten.
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class ErrorCollector:
|
||||
"""Sammelt alle Fehler und Warnungen während der Verarbeitung."""
|
||||
|
||||
def __init__(self):
|
||||
self.errors = {}
|
||||
self.warnings = {}
|
||||
|
||||
def add_errors(self, error_dict):
|
||||
"""Fügt Fehler aus einem Dictionary hinzu."""
|
||||
for key, value in error_dict.items():
|
||||
if key in self.errors:
|
||||
# Key existiert bereits - Verhalten hängt vom Typ ab
|
||||
existing = self.errors[key]
|
||||
|
||||
if isinstance(existing, dict) and isinstance(value, dict):
|
||||
# Beide sind Dictionaries → Merge/Update
|
||||
existing.update(value)
|
||||
elif isinstance(existing, list):
|
||||
# Existierender Wert ist Liste
|
||||
if isinstance(value, list):
|
||||
existing.extend(value)
|
||||
else:
|
||||
existing.append(value)
|
||||
else:
|
||||
# Existierender Wert ist weder dict noch list → Mache Liste daraus
|
||||
if isinstance(value, list):
|
||||
self.errors[key] = [existing] + value
|
||||
else:
|
||||
self.errors[key] = [existing, value]
|
||||
else:
|
||||
# Neuer Key - behalte Typ des Wertes
|
||||
if isinstance(value, (dict, list)):
|
||||
# Dictionary oder Liste → direkt speichern
|
||||
self.errors[key] = value
|
||||
else:
|
||||
# Primitiver Wert (String, etc.) → als Liste speichern
|
||||
self.errors[key] = [value]
|
||||
|
||||
def add_warnings(self, warning_dict):
|
||||
"""Fügt Warnungen aus einem Dictionary hinzu."""
|
||||
for key, value in warning_dict.items():
|
||||
if key in self.warnings:
|
||||
# Key existiert bereits - Verhalten hängt vom Typ ab
|
||||
existing = self.warnings[key]
|
||||
|
||||
if isinstance(existing, dict) and isinstance(value, dict):
|
||||
# Beide sind Dictionaries → Merge/Update
|
||||
existing.update(value)
|
||||
elif isinstance(existing, list):
|
||||
# Existierender Wert ist Liste
|
||||
if isinstance(value, list):
|
||||
existing.extend(value)
|
||||
else:
|
||||
existing.append(value)
|
||||
else:
|
||||
# Existierender Wert ist weder dict noch list → Mache Liste daraus
|
||||
if isinstance(value, list):
|
||||
self.warnings[key] = [existing] + value
|
||||
else:
|
||||
self.warnings[key] = [existing, value]
|
||||
else:
|
||||
# Neuer Key - behalte Typ des Wertes
|
||||
if isinstance(value, (dict, list)):
|
||||
# Dictionary oder Liste → direkt speichern
|
||||
self.warnings[key] = value
|
||||
else:
|
||||
# Primitiver Wert (String, etc.) → als Liste speichern
|
||||
self.warnings[key] = [value]
|
||||
|
||||
def has_errors_or_warnings(self):
|
||||
"""Prüft ob Fehler oder Warnungen vorhanden sind."""
|
||||
return bool(self.errors) or bool(self.warnings)
|
||||
|
||||
def has_errors(self):
|
||||
"""Prüft ob Fehler vorhanden sind."""
|
||||
return bool(self.errors)
|
||||
|
||||
def get_all_issues(self):
|
||||
"""Gibt alle Fehler und Warnungen als Dictionary zurück."""
|
||||
result = {}
|
||||
if self.errors:
|
||||
result["errors"] = self.errors
|
||||
if self.warnings:
|
||||
result["warnings"] = self.warnings
|
||||
return result
|
||||
|
||||
def write_errorfile(self, work_dir: Path, filename: str):
|
||||
"""Schreibt Fehlerdatei nur wenn Fehler oder Warnungen vorhanden sind."""
|
||||
if self.has_errors():
|
||||
print("Fehler gefunden. Schreibe Error-Datei.")
|
||||
all_issues = self.get_all_issues()
|
||||
write_json_file(all_issues, work_dir, filename)
|
||||
else:
|
||||
print("Keine Fehler gefunden. Keine Error-Datei geschrieben.")
|
||||
|
||||
|
||||
def write_json_file(data: dict, out_dir: Path, filename: str) -> None:
|
||||
"""
|
||||
Schreibt Daten in eine JSON-Datei.
|
||||
|
||||
Args:
|
||||
data: Dictionary mit zu schreibenden Daten
|
||||
out_dir: Ausgabeverzeichnis
|
||||
filename: Dateiname für die JSON-Datei
|
||||
"""
|
||||
print("writing data to a json file ...")
|
||||
outfile = out_dir / filename if isinstance(out_dir, Path) else Path(out_dir) / filename
|
||||
with open(outfile, 'w', encoding='utf-8') as fh:
|
||||
json.dump(data, fh, indent=2, ensure_ascii=False, default=str)
|
||||
print("done")
|
||||
Reference in new issue
Block a user