Interne Grenzen: Bestandsaufnahme der Abhängigkeiten ==================================================== Dies ist eine Architekturanalyse von mpylab bei Commit ``9d09c9a`` (2026-10-18), vor einer Überarbeitung der internen Grenzen. Sie schlägt Verantwortlichkeiten innerhalb des bestehenden Repositories vor. Sie führt keine Pakete ein, verschiebt keine Module, ändert keine Importpfade und definiert keine neuen unterstützten APIs. Umfang und Methode ------------------ Alle 229 Python-Quelldateien unter ``src/mpylab`` wurden mit einer AST-basierten Importinventur untersucht. Relative Imports und Imports innerhalb von Funktionen sind erfasst. Die 14 Dateien in ``device/legacy``, ``tools/legacy`` und dem Weiterleitungsmodul ``device/driver.py`` wurden von den übrigen 215 getrennt betrachtet. Generierte Dateien einschließlich ``_version.py`` und ``limits_ui.py`` sind mitgezählt. Modulzahlen beschreiben Ablageorte, weder Aufwand noch architektonische Qualität. Eine Kante bedeutet, dass ein Modul ein anderes explizit importiert, auch in einer Funktion. Wiederholte Imports zwischen demselben Modulpaar zählen in den folgenden Zahlen einmal. Attributimporte wurden soweit möglich dem Quellmodul zugeordnet. Ein Import beweist weder die Ausführung eines Zweigs noch eine unterstützte öffentliche API. Paketinitialisierung, Weiterexporte, konfigurationsabhängiges Laden und Pickle-Wiederherstellung benötigen zusätzliche Prüfung. Eine fehlende statische Kante bedeutet keine Laufzeitunabhängigkeit. Zusätzlich wurden versionierte Python-Quellen in TEMField, Conducted Emission, PExplorer, Shielding Effectiveness, beiden aktiven Konfigurations-Repositories und MpyConfig durchsucht. Anwendungs-/Konfigurationsquellen, Tests und archivierte/migrierte Konfigurationen wurden unterschieden. Kein Konfigurationsskript oder Treiber wurde ausgeführt. Messverfahren und Formeln wurden nicht fachlich bewertet. Heutige Ablageorte und Aufgaben ------------------------------- .. list-table:: Quellinventar :header-rows: 1 :widths: 25 10 65 * - Ablageort - Dateien - Heutige Aufgabe * - ``tools`` - 53 - Quantities, Konfiguration, Graph, Numerik, Kompatibilitätsexporte und CLI-Werkzeuge * - ``device`` ohne Legacy - 89 - Verträge, Kommunikation, Treiber, virtuelle Geräte, UI-Helfer und Fenster * - ``env`` ohne Fachunterpakete - 19 - Messlebenszyklus, EUT-Überwachung, UI-Verträge, Qt-Adapter und Runner * - ``env/tem`` - 18 - TEM-Abläufe, Auswertung, Historie, Reports und interaktive Prüfung * - ``env/msc`` - 5 - MSC-Abläufe, geschützte Erfassung und Schwellensuche * - ``env/univers`` - 3 - Verstärkertest und Namenszuordnungen * - ``limits`` - 22 - Grenzwertmodelle, Profile, Registry und Qt-Explorer * - ``gui`` - 4 - Qt-freie Identität/Verfügbarkeit, Branding, macOS-Helfer und Launcher * - Paketwurzel / Legacy - 2 / 14 - Version/Paketinitialisierung / historische Kompatibilität Wesentliche Befunde ------------------- 1. **TEM und MSC sind bereits sinnvoll getrennt.** Es wurden keine expliziten Imports zwischen diesen Fachbereichen oder von ihnen nach ``env/univers`` gefunden. Beide verwenden gemeinsame Messinfrastruktur und Werkzeuge. Von TEM zu gemeinsamen ``env``-Modulen bestehen fünf verschiedene Modulpaare, von MSC drei. Zu ``tools`` sind es von TEM 23, von MSC 13 und vom Verstärkertest sechs. Kein fachfremdes Quellmodul innerhalb von mpylab importiert diese Fachmodule explizit. Externe Anwendungen und das Laden von Konfigurationen verwenden sie dennoch. 2. **Verzeichnisnamen bilden die Qt-Zuständigkeit nicht ab.** 26 Quelldateien außerhalb von Legacy importieren direkt PySide6, Shiboken oder ein Matplotlib-Qt-Backend. Sie verteilen sich auf ``device``, ``env``, ``env/tem``, ``gui`` und ``limits``. Sechs sind konkrete Treiber mit funktionslokalen GUI-Startern, keine beim normalen Import Qt-pflichtigen Treiber. Umgekehrt enthält ``gui/__init__.py`` Qt-freie Metadaten und Verfügbarkeitsprüfungen. Auch ``device/ui_quantity_display.py``, ``ui_driver_lifecycle.py`` und ``receiver_scan_worker.py`` sind Qt-frei; das Präfix ``ui_`` begründet allein keine Verschiebung. 3. **TEM hängt bei der interaktiven Prüfung ausdrücklich von UI-Code ab.** ``TEMCell.py`` importiert lokal ``emission_sweep_ui._require_display`` und ``review_sweep``. Letzteres Modul importiert Qt nur innerhalb von Funktionen; ein normaler TEM-Import bleibt daher Qt-frei. Für eine strengere Fachgrenze sollten Prüfungs-/Anzeigedienste über einen Adapter übergeben werden. Erfassung, Prüfentscheidungen, Autosave und Fortsetzungszustand bleiben beim Messablauf. 4. **Grenzwertberechnung und Explorer sind weitgehend getrennt.** ``limit.py`` verwendet NumPy; die Registry lädt benannte Profile dynamisch. Drei FCC-Profilmodule verwenden kanonische Umrechnungen aus ``tools.uconv``; vier Profile enthalten lokale Beispielimporte aus ``tools.spacing``. Der Qt-Explorer importiert zusätzlich ``device.ui_frequency`` und das gemeinsame Branding. Die TEM-Vorbewertung importiert ``limits.registry.resolve_limit``. Das ist eine sinnvolle Abhängigkeit des Fachbereichs von der Berechnung, nicht vom Explorer. 5. **Der Explorer enthält einen kleinen expliziten Zyklus.** ``gui.launchers.limit_explorer_main`` importiert lokal ``limits.limits_ui_main.main``. Dieses ``main`` importiert wiederum den privaten ``gui.launchers._limit_parser``. Dies ist die einzige starke Zusammenhangskomponente mit mehreren Modulen im explizit aufgelösten Importgraphen ohne Legacy. Beide Kanten werden verzögert ausgeführt; daraus folgt kein Importabsturz. Ein neutrales Parsermodul oder eine klare Grenze der Argumentauswertung kann den Zyklus auflösen. 6. **Tools vermischen Grundlagen und Orchestrierung.** ``tools.config_inspect`` importiert ``env.config_view`` und ``env.script_cli``; ``tools.nport_check`` importiert ``device.nport``; ``tools.visa_probe`` importiert das private ``communication_gpib._resource_manager``. Das sind Anwendungs-/Prüfwerkzeuge, kein Beleg für eine Geräteabhängigkeit sämtlicher Numerikhelfer. Ein pauschales Verbot aller Kanten ``tools -> env/device`` wäre irreführend. Vor einer Importregel müssen Zuständigkeiten logisch unterschieden werden. 7. **Kompatibilitätsexporte werden intensiv genutzt.** 59 verschiedene Module ohne Legacy importieren ``tools.util``, 40 importieren ``tools.uconv`` und 31 ``tools.configuration``. ``util`` exportiert Implementierungen aus gezielten Modulen wie ``logging_utils``, ``text`` und ``sequences`` weiter. Neue interne Imports sollten diese Implementierungsmodule bevorzugen; die bestehende Fassade bleibt für Nutzer erhalten. ``uconv`` ist bereits die kanonische Umrechnungsimplementierung und sollte weder in Fachmodulen noch bei Grenzwerten dupliziert werden. Beobachtete Verträge mit Begleitprojekten ----------------------------------------- Dies sind genutzte Importpfade, kein Vorschlag, jeden importierten Namen zur öffentlichen API zu erklären. Alle Pfade beziehen sich auf das jeweilige Repo. .. list-table:: Beispiele aus produktiven Quellen :header-rows: 1 :widths: 23 42 35 * - Verbraucher - Nachweis - Konsequenz für die Grenze * - TEMField ``7f12792`` - ``src/temfield_mpylab/TestSusceptibility.py`` importiert ``dBm2W`` aus ``env.univers.AmplifierTest`` - Umrechnung aus dem kanonischen ``tools.uconv`` beziehen, ohne einen Verstärkermessablauf zu importieren. * - Shielding Effectiveness ``8b000c3`` - ``report.py`` und ``report_logo.py`` importieren Helfer/Fehler aus ``env.tem.report_profile`` - Gemeinsame Report-Metadaten liegen unter TEM; ein neutraler Ort benötigt kompatible Defaults und alte Importpfade. * - Conducted Emission ``7f739e5`` - ``ce.py`` und ``limit_dialog.py`` nutzen Grenzwertmodelle/Profile/Registry; die Messung verwendet ``MGraph`` und Quantity-Helfer - Berechnungs-APIs unabhängig vom Explorer erhalten. Weiterexporte wie Einheiten aus ``aunits`` getrennt bewerten. * - PExplorer ``3cb5af1`` - ``src/pexplorer/pickle_loading.py`` verwendet ``env.Measure.load_pickle_compat`` - Pickle-Anzeige hängt trotz fehlendem direktem TEM-/MSC-Import von der Wiederherstellung konkreter Klassen ab. * - GTEM-Konfiguration ``b473175`` - ``sw_gtem.py`` nutzt die Fassade ``device.driver.DRIVER``; Tests verwenden ``TEMCell`` und ``MGraph`` - Die historische Treiberfassade ist weiterhin ein aktiver externer Vertrag. * - RC-Konfiguration ``6e92692`` - ``virtual/build.py`` verwendet ``env.msc.acquisition.MSC_CONDITION_MAP`` und ``MGraph``; eigene Sensoren erben von virtuellen Treibern - Semantik der Condition-Map, Laden eigener Treiber und Verträge virtueller Treiber erhalten. MpyConfig ``0be1460`` und die ``migrated``-Verzeichnisse enthalten historische Aufrufer. Sie wurden separat geprüft und belegen Kompatibilitätsbedarf; sie sind keine zusätzlich zu modernisierenden aktiven Anwendungen dieses Schritts. TEMField implementiert außerdem eigene Messabläufe mit ``Measure`` und ist nicht lediglich eine TEMCell-Oberfläche. Abhängigkeiten jenseits normaler Imports ---------------------------------------- * ``tools.mgraph.MGraph.CreateDevices`` bildet aus der INI-Konfiguration Namen wie ``mpylab.device.`` und lädt auch eigene Treiberdateien. Das ist eine echte Graph-zu-Geräte-Abhängigkeit außerhalb der statischen Paarzahlen. * ``env.script_cli`` und ``env.qt_runner`` laden Konfigurationsmodule. Gerätefenster wählen Treiber dynamisch; Grenzwertsuche und Registry verwenden ebenfalls dynamische Imports. Diese Erweiterungsmechanismen brauchen eine ausdrückliche Zuständigkeit. * ``env.Measure.MpyLabCompatUnpickler`` ordnet historische ``mpy``-Pfade zu und löst anschließend gespeicherte Klassen auf. Verschobene Klassen oder entfernte Module können Messdateien und PExplorer beschädigen. Vor dem Verschieben persistierter Typen alte Importpfade erhalten und echte Wiederherstellung testen. Für diese Analyse wurden keine Messdateien geöffnet. * ``device.pm_rxatt`` enthält eine Demonstration, die ein externes Switch-Skript über einen absoluten Pfad lädt. Das ist Kopplung eines Beispiels an Konfiguration, keine automatische Abhängigkeit jedes Powermeter-Imports. Das Beispiel darf nicht als Laufzeitprobe des Importgraphen ausgeführt werden. Vorgeschlagene interne Zuständigkeiten -------------------------------------- Eine Distribution und die heutigen öffentlichen Importpfade beibehalten. Zunächst logische Zuständigkeiten festlegen; verzeichnisweite Regeln wären derzeit zu grob. .. graphviz:: digraph proposed_boundaries { rankdir=LR; node [shape=box]; "Qt-Adapter / Anwendungen" -> "TEM / MSC / Verstärkertest"; "Qt-Adapter / Anwendungen" -> "Grenzwertberechnung"; "TEM / MSC / Verstärkertest" -> "Messlebenszyklus / EUT / UI-Verträge"; "TEM / MSC / Verstärkertest" -> "Graph / Konfiguration"; "TEM / MSC / Verstärkertest" -> "Grenzwertberechnung" [label="bei Bedarf"]; "Graph / Konfiguration" -> "Geräteverträge / Treiber / Kommunikation"; "Messlebenszyklus / EUT / UI-Verträge" -> "Graph / Konfiguration"; "Geräteverträge / Treiber / Kommunikation" -> "Quantities / Umrechnung / Numerik"; "Grenzwertberechnung" -> "Quantities / Umrechnung / Numerik"; } Das Diagramm zeigt die angestrebte Richtung, keinen vollständigen heutigen Aufrufgraphen. Qt-freie Anwendungsidentität und gemeinsame Report-Metadaten sind unterstützende Dienste. Mess-UI-Verträge bleiben Qt-frei. Verstärkerschutz, RF-Off und Eingangsgrenzen bleiben gemeinsame Sicherheitsaufgaben; nicht jeder Verstärkerschutz gehört zum Verstärkertest. TEM-spezifische Berechnungen in ``tools`` können ihre Pfade bis zu einer getrennt geprüften Zuordnung behalten. Empfohlene nächste Schritte --------------------------- 1. Launcher-/Parserzyklus auflösen, ohne CLI-Hilfe, Versionsausgabe oder optionales Qt zu verändern. Das ist die kleinste einzeln prüfbare Änderung. 2. Neutrale Report-Metadaten und kanonische Imports gemeinsamer Helfer etablieren. Kompatibilitätsexporte erhalten, bestehende Report-Defaults und Begleitprojekte prüfen; beim Zuordnen keine Reportformate ändern. 3. Interaktive TEM-Prüfung hinter einen Qt-freien Adaptervertrag legen. Prüfentscheidungen, Unterbrechung und Persistenzsemantik bleiben erhalten. 4. Gemischte Treiberstarter, CLI-Werkzeuge und Fassaden ausdrücklich zuordnen; anschließend Importprüfungen für vereinbarte logische Bereiche ergänzen. Statische Prüfungen müssen lokale Imports erfassen und durch Qt-freie Laufzeittests sowie Konfigurations-/Pickle-Kompatibilität ergänzt werden. Diese Prüfungen gehören in einen späteren Schritt. Diese Bestandsaufnahme begründet weder eine Repo-Aufteilung noch neue Pakete. Der konkrete Anschluss ist die Launcher-/Parsergrenze; größere Verschiebungen sollten erst nach Prüfung der Befunde folgen. Erster Schritt: Argumentauswertung des Explorers ------------------------------------------------ Der oben im Ausgangsstand beschriebene Launcher-/Parserzyklus ist inzwischen aufgelöst. ``gui.limit_explorer_cli`` enthält Programmname und Argumentauswertung und importiert weder Launcher noch Explorer oder Qt. Der Konsolenstarter prüft Argumente einmal, kontrolliert die Qt-Verfügbarkeit und ruft dann den internen Fensterstarter auf. Das bestehende ``limits.limits_ui_main.main(argv=None)`` verwendet dieselbe CLI-Auswertung und denselben Fensterstarter. Ein Rückimport zum Launcher entfällt. Konsolenbefehl, direkter Modulstart, Hilfe-/Versionstext und Qt-Rückgabecode bleiben erhalten. Konsolenhilfe, Versionsausgabe und die Behandlung ungültiger Argumente funktionieren weiterhin ohne Qt; ein GUI-Start erklärt bei fehlendem Qt das Extra ``mpylab[gui]``. Der alte direkte GUI-Modulimport wird dadurch nicht zusätzlich Qt-frei. Fenstererzeugung, Branding und Zuständigkeit für die Ereignisschleife bleiben unverändert. Fachmodule, Treiber, Grenzwertberechnung und persistierte Typen wurden nicht verschoben. Zweiter Schritt: gemeinsame Report-Profile ------------------------------------------ ``reporting.profile`` enthält jetzt Profilvalidierung, Zusammenführung, Herkunftsverfolgung und Metadatentabellen. Es importiert keine Fach-, Geräte- oder Qt-Module. Der TEM-Historienreport und der Feature-Branch von Shielding Effectiveness verwenden diesen neutralen Dienst. Letzterer benötigt mpylab 1.0.33 und wartet vor Merge/Veröffentlichung auf diesen Release. ``env.tem.report_profile`` bleibt eine ausdrückliche Kompatibilitätsfassade mit denselben exportierten Objekten. Pickle-Globals von Profil und Fehler behalten ihren historischen Modulpfad; Attribute, Defaults, Fehlermeldungen, Logo-Regeln und TSV-Ausgaben bleiben unverändert. Die gemeinsame Implementierung behält den historischen Standardtitel; Shielding setzt weiterhin seinen eigenen Titel und die PDF-Logo-Freigabe. Dritter Schritt: austauschbare Sweep-Prüfung -------------------------------------------- TEMCell und Emissionsskript verwenden jetzt den Qt-freien Prüfadaptervertrag. Adapter liefern Entscheidungen und Auswertungsvorschläge aus getrennten Datenkopien; der Ablauf validiert und übernimmt Metadaten/Auswahlen. Bestehende Qt-Dialoge liegen hinter einem Adapter. Der Terminaladapter speichert dieselben Kurven als PNGs und fragt Wiederholen/Fortsetzen/Abschließen/Speichern-Beenden sowie Auswertungssätze ausdrücklich ab. Auto wechselt ohne Qt/Anzeige zum Terminal; fehlende Eingabemöglichkeit stoppt vor der Geräteerzeugung. EOF/Strg-C erhält ausstehende Daten zur Fortsetzung. Adapter bleiben auf den Aufruf begrenzt und werden nicht in Messpickles aufgenommen. Der Grafikhelfer ist Qt-frei; historische private Grafikimporte bleiben Aliase. Konfiguration und Bedienung beschreibt :doc:`../results/tem-emission-data`. Geprüfte direkte Importgrenzen ------------------------------ Der Qualitätsjob führt jetzt den ausschließlich auf der Standardbibliothek basierenden Prüfer aus:: python tools/check_import_boundaries.py Die Regeln stehen ausdrücklich in ``tools/check_import_boundaries.py``. Bei Einführung erfassen sie 49 Module; neue Module können die Zahl ändern. Der Prüfer importiert keinen Projektcode und greift nicht auf Hardware zu. .. list-table:: Geprüfter Umfang :header-rows: 1 :widths: 25 35 40 * - Regel - Ausgewählte Quellen - Verbotene direkte Abhängigkeiten * - ``report-profile`` - ``reporting.profile`` - ``env``, ``device``, ``gui``, Qt-Bindings/-Backends * - ``sweep-contract`` - ``env.ui.sweep_review`` - TEM-/MSC-/Verstärker-Fachbereiche, Geräte, GUI und konkrete Prüfadapter * - ``tem-workflow-ui`` - ``env.tem.TEMCell`` - Qt-Bindings/-Backends und konkrete Qt-Oberflächen einschließlich ``emission_sweep_ui`` * - ``limit-calculation`` - ``limits``-Initialisierung, ``limit``, ``registry``, ``fcc_ism`` und beide Profilpakete - Qt-Bindings/-Backends, ``gui``, ``device``, ``env`` und die drei Explorer-Module * - ``limit-cli`` - ``gui.limit_explorer_cli`` - Launcher, Limits/Explorer, Geräte, ``env`` und konkrete Qt-Oberflächen * - ``tem-domain`` / ``msc-domain`` / ``amplifier-domain`` - Paketbäume ``env.tem`` / ``env.msc`` / ``env.univers`` - Die beiden jeweils anderen Fachbereiche Qt-Ziele umfassen PySide2/6, PyQt5/6, Shiboken2/6 und die ausdrücklich genannten Matplotlib-Qt-Adapter. Exakte Quellmodulauswahl umfasst keine Untermodule; Paketregeln erfassen auch neue Kindmodule. Verbotene Präfixe werden an ganzen Namenskomponenten geprüft: ``temporal`` gilt nicht als ``tem``. Erfasst werden Imports in Funktionen, Klassen, Bedingungen, try-Blöcken und TYPE_CHECKING. Relative Imports und ``from parent import child`` werden syntaktisch aufgelöst, ohne Python auszuführen oder installierte Pakete zu suchen. Verstöße nennen Datei, Zeile, Ziel, Regel-ID und Begründung. Rückgabecode 0 bedeutet Erfolg, 1 einen Grenzverstoß, 2 unlesbare/ungültige ausgewählte Quellen oder einen fehlenden Quellordner. Auch eine Regel ohne zugehöriges Quellmodul scheitert mit 2; eine leere Prüfung wird nicht stillschweigend grün. ``--source-root`` akzeptiert für isolierte Prüfungen einen Paketordner namens ``mpylab``. Dies ist keine vollständige Abhängigkeits- oder Zyklusanalyse. Weiterexporte, Seiteneffekte der Paketinitialisierung, zur Laufzeit zugewiesene Aliase, dynamische Importaufrufe und die Matplotlib-Backendwahl werden nicht verfolgt. Sternimporte zeigen nur ihre benannte Basis, keine unbekannten weiterexportierten Kinder. MGraph-, eigene Treiber-, Konfigurations- und Grenzwertladewege sowie Pickle-Globals bleiben Laufzeitverträge. Kompatibilitätsfassaden und historische Modulpfad-Strings bleiben zulässig; es gibt kein pauschales Verbot für Imports aus ``tools`` zu Geräten/Messcode und keine Legacy-Ausnahmebaseline. Regeländerungen benötigen einen ausdrücklichen Umfang/Grund sowie passende Tests/Dokumentation; keine Unterdrückung zum Verbergen neuer Abhängigkeiten ergänzen. Der installierte Kernjob ohne Qt und bestehende Konfigurations- und Pickle-Tests bleiben erforderlich.