X-Git-Url: https://plomlompom.com/repos/berlin_corona.txt?a=blobdiff_plain;f=plomlib.py;fp=plomlib.py;h=9dac71284a5c990514c0e2c89bbd6f8a16e8a55d;hb=5f3b9e7eb997cacea086decc3dcd04d6619b9121;hp=0000000000000000000000000000000000000000;hpb=2c81e34cd696fd5da8b4a5d0338b2fe388fa8178;p=misc diff --git a/plomlib.py b/plomlib.py new file mode 100644 index 0000000..9dac712 --- /dev/null +++ b/plomlib.py @@ -0,0 +1,119 @@ +import os +from http.server import BaseHTTPRequestHandler + + +class PlomException(Exception): + pass + + +class PlomDB: + + def __init__(self, db_name): + self.db_file = db_name + ".json" + self.lock_file = db_name+ ".lock" + if os.path.exists(self.db_file): + with open(self.db_file, "r") as f: + self.read_db_file(f) + + def lock(self): + if os.path.exists(self.lock_file): + raise PlomException('Sorry, lock file!') + f = open(self.lock_file, 'w+') + f.close() + + def unlock(self): + os.remove(self.lock_file) + + def backup(self): + import shutil + from datetime import datetime, timedelta + # collect modification times of numbered .bak files + bak_prefix = f'{self.db_file}.bak.' + backup_dates = [] + i = 0 + bak_as = f'{bak_prefix}{i}' + while os.path.exists(bak_as): + mod_time = os.path.getmtime(bak_as) + backup_dates += [str(datetime.fromtimestamp(mod_time))] + i += 1 + bak_as = f'{bak_prefix}{i}' + + # collect what numbered .bak files to save: the older, the fewer; for each + # timedelta, keep the newest file that's older + ages_to_keep = [timedelta(minutes=4**i) for i in range(0, 8)] + now = datetime.now() + to_save = [] + for age in ages_to_keep: + limit = now - age + for i, date in enumerate(reversed(backup_dates)): + if datetime.strptime(date, '%Y-%m-%d %H:%M:%S.%f') < limit: + unreversed_i = len(backup_dates) - i - 1 + if unreversed_i not in to_save: + to_save += [unreversed_i] + break + + # remove redundant backup files + j = 0 + for i in to_save: + if i != j: + source = f'{bak_prefix}{i}' + target = f'{bak_prefix}{j}' + shutil.move(source, target) + j += 1 + for i in range(j, len(backup_dates)): + try: + os.remove(f'{bak_prefix}{i}') + except FileNotFoundError: + pass + + # put copy of current state at end of bak list + shutil.copy(self.db_file, f'{bak_prefix}{j}') + + def write_text_to_db(self, text, mode='w'): + self.lock() + self.backup() + with open(self.db_file, mode) as f: + f.write(text); + self.unlock() + + +class PlomServer(BaseHTTPRequestHandler): + header = '' + footer = '' + + def run(self, port): + from http.server import HTTPServer + webServer = HTTPServer(('localhost', port), type(self)) + print(f"Server started http://localhost:{port}") + try: + webServer.serve_forever() + except KeyboardInterrupt: + pass + webServer.server_close() + print("Server stopped.") + + def fail_400(self, e): + page = f'{self.header}ERROR: {e}{self.footer}' + self.send_HTML(page, 400) + + def send_HTML(self, html, code=200): + self.send_code_and_headers(code, [('Content-type', 'text/html')]) + self.wfile.write(bytes(html, "utf-8")) + + def send_code_and_headers(self, code, headers=[]): + self.send_response(code) + for fieldname, content in headers: + self.send_header(fieldname, content) + self.end_headers() + + +def run_server(port, server_class): + from http.server import HTTPServer + webServer = HTTPServer(('localhost', port), server_class) + print(f"Server started http://localhost:{port}") + try: + webServer.serve_forever() + except KeyboardInterrupt: + pass + webServer.server_close() + print("Server stopped.")