diff options
| author | Jan Tuomi <jan@jantuomi.fi> | 2025-02-11 17:59:28 +0200 |
|---|---|---|
| committer | Jan Tuomi <jan@jantuomi.fi> | 2025-02-11 18:04:22 +0200 |
| commit | 001b52fc1b6d2b30b371611f5a8b961e5c6945d3 (patch) | |
| tree | 937b73ccad1aeb927d8974fe703382dafd360768 /browser/app.py | |
| parent | e8f3a470ce693bef9303d3dd4c46523cdc691826 (diff) | |
Implement find
Diffstat (limited to 'browser/app.py')
| -rw-r--r-- | browser/app.py | 120 |
1 files changed, 98 insertions, 22 deletions
diff --git a/browser/app.py b/browser/app.py index ebe590d..be00fa4 100644 --- a/browser/app.py +++ b/browser/app.py @@ -8,7 +8,8 @@ import tempfile from flask import Flask, render_template, request from flask_compress import Compress # type: ignore -from log_db import DB, Bound +import log_db +from log_db import DB, Bound, Value app = Flask(__name__) Compress(app) @@ -20,28 +21,35 @@ print("""\n""" f"""BASE_URL: {BASE_URL}\n""" f"""DB_DIR: {DB_DIR}\n""") +db_fields = ["id", "name"] +db_types = ["int", "string"] + db = DB \ .configure() \ .data_dir(DB_DIR) \ - .fields(["id", "name"]) \ + .fields(db_fields) \ .primary_key("id") \ .secondary_keys(["name"]) \ .initialize() -@app.errorhandler(Exception) -def error_handler(e: Exception): - if e.code >= 500: # type: ignore - traceback.print_exception(e, file=sys.stderr) - error_text = "Internal Server Error" - else: - error_text = str(e) +def error(e: str, code: int): + error_text = f"HTTP {code}: {e}" + #return render_template("page_error.html.j2", error = error_text) - htmz_target = request.form.get("htmz") - if htmz_target: - return render_template("frag_error.html.j2", error = error_text, container = htmz_target) + htmp_target = request.form.get("htmp") or request.args.get("htmp") + if htmp_target: + return render_template("frag_error.html.j2", error = error_text, container = htmp_target) else: return render_template("page_error.html.j2", error = error_text) +@app.errorhandler(Exception) +def error_handler(e: Exception): + if hasattr(e, "code") and 400 >= getattr(e, "code") < 500: + return error(str(e), getattr(e, "code")) + else: + traceback.print_exception(e, file=sys.stderr) + return error("Internal Server Error", 500) + @app.get("/") def index(): return page_find() @@ -49,19 +57,87 @@ def index(): @app.get("/find") def page_find(): rows = db.range_by("id", Bound.unbounded(), Bound.unbounded(), limit=100) + rows = [[value_to_str(v) for v in row] for row in rows] + + htmp_target = request.form.get("htmp") or request.args.get("htmp") + if htmp_target: + return render_template("frag_form_find.html.j2") + else: + return render_template('page_main.html.j2', + selected_form = "frag_form_find.html.j2", + field_names = ["id", "name"], + rows = rows, + ) - return render_template('page_main.html.j2', - selected_form = "frag_form_find.html.j2", - field_names = ["id", "name"], - rows = rows, - ) +@app.post("/find") +def query_find(): + field = request.form.get("field") + if not field: raise ValueError("Field is required") + + values = request.form.get("values") + if not values: raise ValueError("Values are required") + + field_index = db_fields.index(field) + if field_index == -1: raise ValueError(f"Field '{field}' not found") + + try: + values = [cast_to_value(field, v) for v in values.split("\n")] + values = [v for v in values if v is not None] + except ValueError as e: + return error(str(e), 400) + + tagged_rows = db.batch_find_by(field, values, limit=100) + rows = [[value_to_str(v) for v in row] for (_, row) in tagged_rows] + + htmp_target = request.form.get("htmp") or request.args.get("htmp") + if htmp_target: + return render_template("frag_results.html.j2", + field_names = ["id", "name"], + rows = rows, + ) + else: + return render_template('page_main.html.j2', + selected_form = "frag_form_find.html.j2", + field_names = ["id", "name"], + rows = rows, + ) @app.get("/range") def page_range(): rows = db.range_by("id", Bound.unbounded(), Bound.unbounded(), limit=100) - return render_template('page_main.html.j2', - selected_form = "frag_form_range.html.j2", - field_names = ["id", "name"], - rows = rows, - ) + htmp_target = request.form.get("htmp") or request.args.get("htmp") + if htmp_target: + return render_template("frag_form_range.html.j2") + else: + return render_template('page_main.html.j2', + selected_form = "frag_form_range.html.j2", + field_names = ["id", "name"], + rows = rows, + ) + +def cast_to_value(field: str, str_value: str) -> Value | None: + str_value = str_value.strip() + if str_value == "": return None + if str_value[0] == "\"": + if str_value[-1] != "\"": raise ValueError(f"Invalid string: {str_value}") + str_value = str_value[1:-1] + + field_index = db_fields.index(field) + if field_index == -1: raise ValueError(f"Field '{field}' not found") + + type = db_types[field_index] + + match type: + case "int": return Value.int(int(str_value)) + case "string": return Value.string(str_value) + case _: raise ValueError(f"Unsupported type: {type}") + +def value_to_str(value: Value) -> str: + match value.kind(): + case log_db.VALUE_INT: return f"{str(value.as_int())} (int)" + case log_db.VALUE_STRING: return f"\"{value.as_string()}\" (string)" + case log_db.VALUE_DECIMAL: return f"{value.as_decimal()} (decimal)" + case log_db.VALUE_BYTES: return f"{value.as_bytes()} (bytes)" + case log_db.VALUE_NULL: return "null" + case _: raise ValueError(f"Unsupported value kind: {value.kind()}") |
