from xml.etree import ElementTree from xml.dom import minidom import re import sys import pathlib import datetime import pickle import time import os def log(*args, **kwargs): # make it so this goes to a file print( " ".join(map(str,args)), **kwargs) class Bunch(object): def __init__(self, adict): self.__dict__.update(adict) def write_xml_file(filename, element): """write an element to an xml file""" try: xmlstr = ElementTree.tostring(element) dom = minidom.parseString(xmlstr) xmlstr = dom.toprettyxml() with open(filename, "w") as outbug: outbug.write(xmlstr) except Exception: log("invalid filename or xml.") def print_xml(element): """print an xml element to the terminal""" try: xmlstr = ElementTree.tostring(element) dom = minidom.parseString(xmlstr) log(dom.toprettyxml()) except Exception: log("invalid filename or xml.") def sanatise_path(path): return "".join([x for x in path if x not in "<>:\"|?*"]) def is_debugging(): """Return if the debugger is currently active""" gettrace = getattr(sys, 'gettrace', lambda : None) return gettrace() is not None def trywrap(): """wrap function in a debugger friendly try block""" def decorator(wrapped_function): def wrapper(*args, **kwargs): if not is_debugging(): try: return wrapped_function(*args, **kwargs) except Exception as e: log("exception: "+str(repr(e))) else: return wrapped_function(*args, **kwargs) return wrapper return decorator file_cache_hits = 0 file_cache_refresh = 0 file_cache_misses = 0 def file_cache(basedir, refresh=900): """wrap function in a file based cache""" _basedir = str(pathlib.Path.home()) basedir = os.path.join(_basedir, basedir) def decorator(wrapped_function): def wrapper(*args): global file_cache_hits global file_cache_misses global file_cache_refresh filename = map(sanatise_path, map(str, args)) filename = map(lambda x: x.replace("//", ""), filename) # to deal with network drive paths, not sure it's a good thing. filename = os.path.join(basedir, wrapped_function.__name__, *filename) try: filecache = pickle.load(open(filename, 'rb')) file_cache_hits += 1 except Exception: filecache = None if not filecache: file_cache_misses += 1 filecache = [wrapped_function(*args), time.time()] os.makedirs(os.path.dirname(filename), exist_ok=True) if filecache[0]: try: pickle.dump(filecache, open(filename, 'wb')) except Exception: pass elif time.time() - filecache[1] > refresh and refresh != False: file_cache_refresh += 1 filecache = [wrapped_function(*args), time.time()] if filecache[0]: try: pickle.dump(filecache, open(filename, 'wb')) except Exception: pass return filecache[0] return wrapper return decorator def re_unescape(pattern): unescape = re.compile(r'\\(.)') return unescape.sub(r'\1', pattern) def str_insert(line, ins, pos): return ''.join(line[:pos]+ins+line[pos:]) def file_mtime(path): t = datetime.datetime.fromtimestamp(os.stat(path).st_mtime, datetime.timezone.utc) return t.astimezone().isoformat() def confirm_prompt(question, default=None): answer = False while(True): try: answer = input(question+" (y/n): ") answer = answer.upper() if (answer in ["YES", "Y"]): answer = True break elif (answer in ["NO", "N"]): answer = False break elif not answer and default is not None: answer = default break except Exception: break return answer def ip_to_user(address): import socket import ipaddress user = ipaddress.ip_address(address) try: host = socket.gethostbyaddr(user.ipv4_mapped) user = host[0].split(".")[0] except Exception: user = str(int(user)) return user