#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import functools; from code.core.log import *; from code.setup.display import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # CLASSES # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class OneShot(object): state: bool; def __init__(self): self.state = True; def setState(self, state: bool): self.state = state; def reload(self): self.state = True; def trigger(self): self.state = False; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # DECORATORS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Trigger, der das fancy Zeug bei verschachtelten Algorithmen verhindert nonnestedAlgorithms = OneShot(); def algorithmInfos( name: str, checks: bool = True, metrics: bool = None, outputnames: Union[str, Tuple[str]] = 'result', preChecks: Any = None, postChecks: Any = None ): ''' Decorator für Algorthmen, der Folgendes macht: - Zeigt vorm Start Console-Messages mit Namen des Algorithmus + Inputs. - Zeit am Ende optional Metriken (bspw. Zeitkosten). - Zeigt am Ende Console-Messages von Output/s. - Prüft optional vor und nach Ausführung des Algorithmus, dass die Inputs/Outputs stimmen. Bei rekursiven Definitionen werden die o. s. Punkte nur bei dem äußersten Aufruf gemacht. ''' def func_decorator(func): ## Trigger, der das fancy Zeug bei verschachtelten Aufrufen verhindert nonnestedRecursion = OneShot(); @functools.wraps(func) def func_wrapper(**inputs): try: state1 = nonnestedAlgorithms.state; state2 = nonnestedRecursion.state; state = state1 and state2; if state: # Initialisierung DisplayStartOfAlgorithm(name.title(), **inputs); RestartCounter(); # Prechecks if checks and callable(preChecks): preChecks(**inputs); # Ausführung des Algorithmus: nonnestedRecursion.trigger(); nonnestedAlgorithms.trigger(); outputs = func(*[], **inputs); nonnestedAlgorithms.state = state1; nonnestedRecursion.state = state2; if state: # benenne Outputs: outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]); outputnames_ = outputnames if isinstance(outputnames, tuple) else tuple([outputnames]); outputsNamed = { outputnames_[k]: value for k, value in enumerate(outputs_) }; # Postchecks if checks and callable(postChecks): postChecks(**inputs, **outputsNamed); # Letzte Messages if metrics: DisplayMetrics(); DisplayEndOfAlgorithm(**outputsNamed); except Exception as e: nonnestedAlgorithms.state = state1; nonnestedRecursion.state = state2; raise e; return outputs; return func_wrapper; return func_decorator;