Weichenknoten zwischen Kreiseln, Track-Mouseover, Parameter in cfg/parameter.ini
TRO-Typen an Kreisel-Beruehrpunkten (lib/kreisel_junctions.py, derive_tros Schritt 3c): jeder Kreisel als Stadion-Form mit Laufrichtung; jeder gleichlaufende Beruehrpunkt ist eine Weiche (exportierte ILS Weiche oder abgeleitet W<a>_<b>), Beruehrpunkte derselben Umlenkung bilden einen Knoten. Ein Separator steuert ihn, wenn er in Laufrichtung unmittelbar davor liegt (keine andere Weiche dazwischen). Typ = Separatoren x Weichen. export.csv: 1Sep1Swi (9/1, 9/8, 8/7), 2Sep1Swi (7/2), 2Sep2Swi (2/3/4), 3Sep2Swi (4/5/6). Neuer Katalogtyp 3Sep2Swi (nicht aus SCL belegt). Gegenlaeufige Beruehrpunkte (Mubea, Dematic) bleiben bei der alten Regel; Mubea/HundM05/Dematic unveraendert, Showroom 0018+0019 jetzt 2Sep1Swi. material_flow --track: Mouseover je Knoten mit Zugehoerigkeit zu Kreisel/VF/GF (Zuordnung, TrackIds-Kette, Lage laut Geometrie), Weiche mit beiden Kreiseln, Be-/Entladung mit ihrem Kreisel; Widersprueche mit "!". Zahlenwerte (Toleranzen, Schwellen, Massstaebe, Groessen) aus allen lib-Modulen nach cfg/parameter.ini (lib/parameter.py, Abschnitt je Modul, Ueberschreiben je Anlage ueber %SKEL_CFG%/parameter.ini). Ausgaben aller Anlagen bytegleich. tro_flow.py: Docstrings mit Parametern/Rueckgabe, fehlende Typangaben. Geprueft: 90 Tests gruen; tro_flow/material_flow/scl_skeleton auf 5 CSVs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0c69faf3db
commit
550bdeb464
@@ -0,0 +1,69 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests fuer lib/parameter.py und cfg/parameter.ini."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import configparser
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
import parameter
|
||||
from parameter import ParameterError, get_float, get_int
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
BASE = ROOT / "cfg" / parameter.PARAMETER_FILE
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def frisch(monkeypatch: pytest.MonkeyPatch):
|
||||
"""Parameter-Cache leeren, damit SKEL_CFG im Test wirkt - und danach wieder."""
|
||||
parameter._parser.cache_clear()
|
||||
yield monkeypatch
|
||||
parameter._parser.cache_clear()
|
||||
|
||||
|
||||
def _base() -> configparser.ConfigParser:
|
||||
parser = configparser.ConfigParser(inline_comment_prefixes=(";", "#"))
|
||||
parser.read(BASE, encoding="utf-8")
|
||||
return parser
|
||||
|
||||
|
||||
def test_base_values_are_read(frisch: pytest.MonkeyPatch) -> None:
|
||||
frisch.delenv("SKEL_CFG", raising=False)
|
||||
assert get_float("kreisel_junctions", "contact_tolerance") == 50.0
|
||||
assert get_int("tro_flow", "min_store_lanes") == 2
|
||||
|
||||
|
||||
def test_skel_cfg_overrides_single_value(frisch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
||||
(tmp_path / parameter.PARAMETER_FILE).write_text(
|
||||
"[kreisel_junctions]\ncontact_tolerance = 75 ; Anlage X\n", encoding="utf-8")
|
||||
frisch.setenv("SKEL_CFG", str(tmp_path))
|
||||
assert get_float("kreisel_junctions", "contact_tolerance") == 75.0
|
||||
# nicht ueberschriebene Werte kommen weiter aus der Grunddatei
|
||||
assert get_float("kreisel_junctions", "separator_tolerance") == 100.0
|
||||
|
||||
|
||||
def test_missing_key_is_an_error(frisch: pytest.MonkeyPatch) -> None:
|
||||
frisch.delenv("SKEL_CFG", raising=False)
|
||||
with pytest.raises(ParameterError, match=r"\[tro_flow\] gibt_es_nicht fehlt"):
|
||||
get_float("tro_flow", "gibt_es_nicht")
|
||||
|
||||
|
||||
def test_non_number_is_an_error(frisch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
||||
(tmp_path / parameter.PARAMETER_FILE).write_text(
|
||||
"[tro_flow]\nmin_store_lanes = zwei\n", encoding="utf-8")
|
||||
frisch.setenv("SKEL_CFG", str(tmp_path))
|
||||
with pytest.raises(ParameterError, match="keine ganze Zahl"):
|
||||
get_int("tro_flow", "min_store_lanes")
|
||||
|
||||
|
||||
def test_every_key_is_used_by_its_module() -> None:
|
||||
"""Jeder Schluessel der Grunddatei wird in lib/<Abschnitt>.py gelesen -
|
||||
keine verwaisten Werte, die nichts mehr steuern."""
|
||||
parser = _base()
|
||||
for section in parser.sections():
|
||||
source = (ROOT / "lib" / f"{section}.py").read_text(encoding="utf-8")
|
||||
for key in parser.options(section):
|
||||
assert re.search(rf'"{key}"', source), f"[{section}] {key} wird nicht gelesen"
|
||||
Reference in New Issue
Block a user