ads1_2021/code/python/src/algorithms/methods.py

100 lines
3.5 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import functools
from src.core.log import *;
from src.setup import appconfig;
from src.core.metrics import *;
from src.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,
outputnames: List[str] = ['result'],
preChecks: Any = None,
postChecks: Any = None
):
'''
Decorator für Algorithmen, 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, **inputs);
# Prechecks
if appconfig.AppConfigPerformChecks() and callable(preChecks):
preChecks(**inputs);
# Metriken initialisieren + starten
ResetMetrics();
StartMetrics();
# Ausführung des Algorithmus:
nonnestedRecursion.trigger();
nonnestedAlgorithms.trigger();
outputs = func(*[], **inputs);
nonnestedAlgorithms.state = state1;
nonnestedRecursion.state = state2;
if state:
# Metriken anhalten
StopMetrics();
# benenne Outputs:
outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]);
outputsNamed = { outputnames[k]: value for k, value in enumerate(outputs_) };
# Letzte Messages
if appconfig.AppConfigShowMetrics():
DisplayMetrics();
DisplayEndOfAlgorithm(**outputsNamed);
# Postchecks
if appconfig.AppConfigPerformChecks() and callable(postChecks):
postChecks(**inputs, **outputsNamed);
except Exception as e:
nonnestedAlgorithms.state = state1;
nonnestedRecursion.state = state2;
raise e;
return outputs;
return func_wrapper;
return func_decorator;