Modulunterklassen (Module Subclasses)
Was macht die Modulunterklasse?
- Die Modulunterklasse dient dazu, ein Modul um neue Funktionen und Attribute zu erweitern.
- Wird versucht eine Funktion aufzurufen, die es in der Modulunterklasse nicht gibt, wird stattdessen in der "echten" Modul-Instanz danach gesucht.
- Durch diese Fassade können Module leicht um neue Funktionen erweitert werden.
Theorie
- Um Modulunterklassen zu verstehen, sollte man einen Überblick darüber besitzen, wie die Python-Anbindung in PLANTA funktioniert:
- Die nativen Funktionen werden in einem speziellen Modul (
ppms.i) angebunden. - Mit dem Tool SWIG werden diese Funktionen kompiliert.
- Es ensteht eine
.dll/.soähnliche Datei namens_ppms.pyd, die als Bibliothek die entsprechenden Funktionen bereitstellt. - Es entsteht eine Python-Datei namens
ppms_.py, die sämtliche Funktionen aus der_ppms.pydBibliothek bereitstellt.
- Es ensteht eine
- Im Python-Verzeichnis befindet sich die Python-Datei
ppms.py, die ausppms_.pyimportiert und den Code um weitere, in Python geschriebene, Funktionen erweitert. - Benutzt man nun eine API-Funktion, die einem eine
ModuleInstanz zurückliefert, wird diese Modul-Instanz nicht direkt zurück gegeben, stattdessen erhält man eine Modulunterklasse: Entweder die im 405er Datensatz angegebene Klasse, oder die StandardBaseKlasse.

Praxis
Information
- Jedes neue Modul hat standardmäßig die Modulunterklasse
ppms.module_subclasses.base_class.Base. - Alle Modulunterklassen sollten von dieser Klasse erben.
Hinweis
- So wie bei allen anderen ausgelagerten Python-Dateien muss der Client neugestartet werden, nachdem Änderungen vorgenommen wurden.
Modulunterklassen und Makros
- Editierbarkeit mit einer IDE (Pycharm, PyDev, Visual Studio, ...)
- Bessere Durchsuchbarkeit
- Einfache Austauschbarkeit (ermöglicht zentrale Anpassungen)
- Wiederverwendbarkeit von Funktionen
- Einfachere Anpassung von Funktionen in bestimmten Modulen
- Versionierung in einem Quellcodeverwaltungssystem möglich (Nachvollziehbarkeit von Anpassungen)
Informationen
- Hat ein Modul ein Makro sowie eine Modulunterklasse, verhält es sich wie folgt:
- Das Modulmakro wird nach dem Öffnen des Moduls ausgeführt. Code auf der obersten Ebene wird ausgeführt.
- Gibt es die gleiche Funktion (z.B.
on_load()) in beiden, so wird nur die Funktion der Modulunterklasse aufgerufen. - Gibt es eine Funktion nur auf einer Seite, so wird sie aufgerufen.
Methoden aufrufen
Vorgehensweise
- Um eine Methode der Modulunterklasse aufrufbar zu machen, beispielsweise über einen Button, geht man wie folgt vor:
- Man implementiert die Methode in der Modulunterklasse
- Die Methodensignatur muss wie folgt aussehen:
(self, applied_dfc, clicked_df)
- Die Methodensignatur muss wie folgt aussehen:
- Man fügt ein neues Button-DI (004336) in einen Datenbereich ein mit:
- DF-Verhalten: *5 (c5, e5, f5, g5, m5)
- Aktions-ID: Der Name der Methode
- Man implementiert die Methode in der Modulunterklasse
Menüpunkte überschreiben
Vorgehensweise
- Um einen Menüpunkt zu überschreiben, geht man wie folgt vor:
- Man überschreibt die Methode
menu_override(self, menu_id)in seiner Modulunterklasse. - Man prüft mit einem
if, ob der Menüpunkt, der überschrieben werden soll, ausgeführt wird. - Man behandelt den Menüpunkt und benutzt einen der folgenden zwei Rückgabewerte:
self.MENU_OVERRIDE_SUCCESS: Der Menüpunkt wurde erfolgreich behandelt.self.MENU_OVERRIDE_FAILURE: Der Menüpunkt wurde nicht erfolgreich behandelt.
- Zum Schluss sollte man noch die
super()Funktion aufrufen, um den normalen Programmfluss für andere Menüpunkte zu gewährleisten.
- Man überschreibt die Methode
Beispiel
from ppms import ppms
from ppms.module_subclasses.base_class import Base
from ppms.constants import MENU_FILTER, MENU_RESET, MENU_SAVE
class ModuleThatOverwritesSave(Base):
def menu_override(self, menu_id):
if menu_id == MENU_SAVE:
ppms.ui_message_box('No saving allowed!')
return self.MENU_OVERRIDE_SUCCESS
# Don't allow resetting as that brings up a save prompt
elif menu_id == MENU_RESET:
return self.MENU_OVERRIDE_SUCCESS
return super(ModuleThatOverwritesSave, self).menu_override(menu_id)