2 from http.server import BaseHTTPRequestHandler
5 class PlomException(Exception):
11 def __init__(self, db_name):
12 self.db_file = db_name
13 self.lock_file = db_name+ '.lock'
14 if os.path.exists(self.db_file):
15 with open(self.db_file, 'r') as f:
19 if os.path.exists(self.lock_file):
20 raise PlomException('Sorry, lock file!')
21 f = open(self.lock_file, 'w+')
25 os.remove(self.lock_file)
29 from datetime import datetime, timedelta
30 if not os.path.exists(self.db_file):
33 # collect modification times of numbered .bak files
34 bak_prefix = f'{self.db_file}.bak.'
37 bak_as = f'{bak_prefix}{i}'
38 while os.path.exists(bak_as):
39 mod_time = os.path.getmtime(bak_as)
40 backup_dates += [str(datetime.fromtimestamp(mod_time))]
42 bak_as = f'{bak_prefix}{i}'
44 # collect what numbered .bak files to save: the older, the fewer; for each
45 # timedelta, keep the newest file that's older
46 ages_to_keep = [timedelta(minutes=4**i) for i in range(0, 8)]
49 for age in ages_to_keep:
51 for i, date in enumerate(reversed(backup_dates)):
52 if datetime.strptime(date, '%Y-%m-%d %H:%M:%S.%f') < limit:
53 unreversed_i = len(backup_dates) - i - 1
54 if unreversed_i not in to_save:
55 to_save += [unreversed_i]
58 # remove redundant backup files
62 source = f'{bak_prefix}{i}'
63 target = f'{bak_prefix}{j}'
64 shutil.move(source, target)
66 for i in range(j, len(backup_dates)):
68 os.remove(f'{bak_prefix}{i}')
69 except FileNotFoundError:
72 # put copy of current state at end of bak list
73 shutil.copy(self.db_file, f'{bak_prefix}{j}')
75 def write_text_to_db(self, text, mode='w'):
78 with open(self.db_file, mode) as f:
83 class PlomHandler(BaseHTTPRequestHandler):
85 html_head = '<!DOCTYPE html>\n<html>\n<meta charset="UTF-8">'
86 html_foot = '</body>\n</html>'
88 def fail_400(self, e):
89 self.send_HTML(f'ERROR: {e}', 400)
91 def send_HTML(self, html, code=200):
92 self.send_code_and_headers(code, [('Content-type', 'text/html')])
93 self.wfile.write(bytes(f'{self.html_head}\n{html}\n{self.html_foot}', 'utf-8'))
95 def send_code_and_headers(self, code, headers=[]):
96 self.send_response(code)
97 for fieldname, content in headers:
98 self.send_header(fieldname, content)
101 def redirect(self, url='/'):
102 self.send_code_and_headers(302, [('Location', url)])
106 def run_server(port, handler_class):
107 from http.server import HTTPServer
108 webServer = HTTPServer(('localhost', port), handler_class)
109 print(f"Server started http://localhost:{port}")
111 webServer.serve_forever()
112 except KeyboardInterrupt:
114 webServer.server_close()
115 print("Server stopped.")