Pamhyr2/src/tools.py

256 lines
5.4 KiB
Python

# -*- coding: utf-8 -*-
import time
import sqlite3
import traceback
from pathlib import Path
from colorama import Fore
from colorama import Back
from colorama import Style
from functools import (
reduce, partial, wraps
)
##########
# TIMERS #
##########
_timers = {}
_calls = {}
def reset_timers():
global _timers
global _calls
_timers = {}
_calls = {}
def display_timers():
global _timers
global _calls
fmax = max(
map(
lambda f: len(f.__qualname__) + len(f.__module__),
_timers
)
)
head = " +--"
head += f"{Style.BRIGHT}{Fore.BLUE}Timers{Style.RESET_ALL}"
for t in range(fmax + 26):
head += "-"
head += "+"
print(head)
lst = sorted(
map(
lambda f: (f, _timers[f], _calls[f]),
_timers
),
key = lambda f: f[1],
reverse = True
)
for func, time, calls in lst:
name = (f"{Fore.BLUE}{func.__module__}{Style.RESET_ALL}" +
f".{Style.BRIGHT}{Fore.GREEN}{func.__qualname__:<{fmax - len(func.__module__)}}{Style.RESET_ALL}")
print(f" | {name} | {time:>10.6f} sec | {calls:>5} calls |")
tail = " +--"
for t in range(fmax + 32):
tail += "-"
tail += "+"
print(tail)
def timer(func):
"""Function wrapper to register function runtime"""
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.perf_counter()
value = None
try:
value = func(*args, **kwargs)
except Exception as e:
print(f"[{Fore.RED}ERROR{Style.RESET_ALL}]" +
f"[{func.__module__}.{Fore.GREEN}{func.__qualname__}{Style.RESET_ALL}]: " +
f"{Fore.RED}{e}{Style.RESET_ALL}")
traceback.print_exc()
end_time = time.perf_counter()
run_time = end_time - start_time
_timers[func] += run_time
_calls[func] += 1
return value
_timers[func] = 0
_calls[func] = 0
return wrapper
#########
# DEBUG #
#########
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
t = time.ctime()
head = f"[{Fore.BLUE}TRACE{Style.RESET_ALL}]"
c = f"{head}[{t}] Call {func.__module__}.{Fore.GREEN}{func.__qualname__}{Style.RESET_ALL}({args}, {kwargs})"
print(c)
value = func(*args, **kwargs)
t = time.ctime()
r = f"{head}[{t}] Return {func.__module__}.{Fore.GREEN}{func.__qualname__}{Style.RESET_ALL}: {value}"
print(r)
return value
return wrapper
################
# OTHERS TOOLS #
################
@timer
def flatten(lst):
"""Flatten list of list
Args:
lst: A list of list
Returns:
returns a list of element
"""
if not lst:
return []
return reduce(list.__add__, lst)
def old_pamhyr_date_to_timestamp(date:str):
v = date.split(":")
if len(v) != 4:
return 0
m = [
(24 * 60 * 60), # Day to sec
(60 * 60), # Hour to sec
60, # Minute to sec
1 # Sec
]
ts = reduce(
lambda acc, x: acc + x,
map(
lambda v, m: int(v) * int(m),
v, m
)
)
return ts
#######
# SQL #
#######
# This class is an abstract class to make class with save and load
# from sqlite3.
class SQL(object):
def _init_db_file(self, db):
exists = Path(db).exists()
self._db = sqlite3.connect(db)
self._cur = self._db.cursor()
if not exists:
self._create() # Create db
self._save() # Save
else:
self._update() # Update db scheme if necessary
self._load() # Load data
def __init__(self, filename = None):
self._db = None
if filename is not None:
self._init_db_file(filename)
def commit(self):
self._db.commit()
def _fetch_string(self, s):
return s.replace("&#39;", "'")
def _fetch_tuple(self, tup):
res = []
for v in tup:
if type(v) == str:
v = self._fetch_string(v)
res.append(v)
return res
def _fetch_list(self, lst):
res = []
for v in lst:
if type(v) == str:
v = self._fetch_string(v)
elif type(v) == tuple:
v = self._fetch_tuple(v)
res.append(v)
return res
def _fetch(self, res, one):
if one:
value = res.fetchone()
else:
value = res.fetchall()
res = value
if type(value) == list:
res = self._fetch_list(value)
elif type(value) == tuple:
res = self._fetch_tuple(value)
return res
def _sql_format(self, value):
# Replace ''' by '&#39;' to preserve SQL injection
if type(value) == str:
value = value.replace("'", "&#39;")
return value
@timer
def execute(self, cmd, fetch_one = True, commit = False):
#print(f"[SQL] {cmd}")
res = self._cur.execute(cmd)
if commit:
self._db.commit()
value = self._fetch(res, fetch_one)
return value
def _create(self):
print("TODO: Create")
def _update(self):
print("TODO: Update")
def _save(self):
print("TODO: Save")
def _load(self):
print("TODO: Load")