From 957b289c36c522e19916ef474f14a70caeab0c17 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Fri, 13 Oct 2023 05:00:20 +0200 Subject: [PATCH] Add ledger editing to ledger.py. --- ledger.py | 77 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/ledger.py b/ledger.py index c3f0ab9..9fa9f14 100755 --- a/ledger.py +++ b/ledger.py @@ -1,6 +1,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer import sys import os +from urllib.parse import parse_qs hostName = "localhost" serverPort = 8082 @@ -32,6 +33,7 @@ def parse_lines(lines): start_line = 0 bookings = [] comments = [] + lines += [''] # to ensure a booking-ending last line for i, line in enumerate(lines): prefix = f"line {i}" # we start with the case of an utterly empty line @@ -205,17 +207,32 @@ class Booking: class Database: - def __init__(self, load_from_file=True): + def __init__(self): db_name = "_ledger" self.db_file = db_name + ".json" self.lock_file = db_name+ ".lock" self.bookings = [] self.comments = [] - if load_from_file and os.path.exists(self.db_file): + self.real_lines = [] + if os.path.exists(self.db_file): with open(self.db_file, "r") as f: - ret = parse_lines(f.readlines()) - self.bookings += ret[0] - self.comments += ret[1] + self.real_lines += f.readlines() + ret = parse_lines(self.real_lines) + self.bookings += ret[0] + self.comments += ret[1] + + def replace(self, start, end, lines): + import shutil + if os.path.exists(self.lock_file): + raise HandledException('Sorry, lock file!') + if os.path.exists(self.db_file): + shutil.copy(self.db_file, self.db_file + ".bak") + f = open(self.lock_file, 'w+') + f.close() + text = ''.join(self.real_lines[:start]) + '\n'.join(lines) + ''.join(self.real_lines[end:]) + with open(self.db_file, 'w') as f: + f.write(text); + os.remove(self.lock_file) def append(self, lines): import shutil @@ -235,13 +252,18 @@ class MyServer(BaseHTTPRequestHandler): footer = '' def do_POST(self): - from urllib.parse import parse_qs length = int(self.headers['content-length']) postvars = parse_qs(self.rfile.read(length).decode(), keep_blank_values=1) lines = postvars['booking'][0].splitlines() + start = int(postvars['start'][0]) + end = int(postvars['end'][0]) try: - bookings, comments = parse_lines(lines) - db.append(lines) + _, _ = parse_lines(lines) + if start == end == 0: + db.append(lines) + else: + # raise HandledException(f'would write from {start} to {end}') + db.replace(start, end, lines) self.send_response(200) self.end_headers() page = f"{self.header}Success!{self.footer}" @@ -253,15 +275,20 @@ class MyServer(BaseHTTPRequestHandler): self.wfile.write(bytes(page, "utf-8")) def do_GET(self): + from urllib.parse import urlparse self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() db = Database() page = self.header + '' - if self.path == '/balance': + parsed_url = urlparse(self.path) + if parsed_url.path == '/balance': page += self.balance_as_html(db) - elif self.path == '/add': - page += self.add() + elif parsed_url.path == '/add': + params = parse_qs(parsed_url.query) + start = int(params.get('start', ['0'])[0]) + end = int(params.get('end', ['0'])[0]) + page += self.add(db, start, end) else: page += self.ledger_as_html(db) page += self.footer @@ -332,28 +359,34 @@ class MyServer(BaseHTTPRequestHandler): def ledger_as_html(self, db): lines = [] + line_sep = '
' for comment in db.comments: - lines += [f"; {comment}" if comment != '' else ''] + line = f'; {comment}' if comment != '' else '' + lines += [line + line_sep] for booking in db.bookings: i = booking.start_line - suffix = f" {lines[i]}" if len(lines[i]) > 0 else "" - lines[i] = f"{booking.date_string} {booking.description}{suffix}" + suffix = lines[i] # f" {lines[i]}" if len(lines[i]) > 0 else "" + lines[i] = f'

{booking.date_string} {booking.description}{suffix}' for booking_line in booking.lines: i += 1 if booking_line == '': continue - suffix = f" {lines[i]}" if len(lines[i]) > 0 else "" - value = f" {booking_line[1]} {booking_line[2]}" if booking_line[1] else "" - lines[i] = f"{booking_line[0]}{value}{suffix}" - content = "\n".join(lines) - return f"

{content}
" + suffix = f' {lines[i]}' if len(lines[i]) > 0 else '' + value = f' {booking_line[1]} {booking_line[2]}' if booking_line[1] else '' + lines[i] = f'{booking_line[0]}{value}{suffix}' + lines[i] = lines[i][:-len(line_sep)] + f'

edit
' + return '\n'.join(lines) - def add(self): - return '
' + def add(self, db, start=0, end=0): + if start == end == 0: + content = '' + else: + content = ''.join(db.real_lines[start:end]) + return f'
' db = Database() -if __name__ == "__main__": +if __name__ == "__main__": webServer = HTTPServer((hostName, serverPort), MyServer) print(f"Server started http://{hostName}:{serverPort}") try: -- 2.30.2