From 8e7512965c2bbc711c246c075937ac96efdc2b77 Mon Sep 17 00:00:00 2001 From: Brian Rogers Date: Sat, 10 Jan 2026 18:34:10 -0700 Subject: [PATCH] database migration stuff --- weather/__init__.py | 3 +++ weather/db.py | 46 +++++++++++++++++++++++++++++++++++++++++++++ weather/schema.sql | 43 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 weather/db.py create mode 100644 weather/schema.sql diff --git a/weather/__init__.py b/weather/__init__.py index 67bdfc5..c8bc86d 100644 --- a/weather/__init__.py +++ b/weather/__init__.py @@ -23,4 +23,7 @@ def create_app(test_config=None): def hello(): return "'Ello, Wurld!" + from . import db + db.init_app(app) + return app diff --git a/weather/db.py b/weather/db.py new file mode 100644 index 0000000..a6c4602 --- /dev/null +++ b/weather/db.py @@ -0,0 +1,46 @@ +import sqlite3 +from datetime import datetime + +import click +from flask import current_app, g + + +def get_db(): + if 'db' not in g: + g.db = sqlite3.connect( + current_app.config['DATABASE'], + detect_types=sqlite3.PARSE_DECLTYPES + ) + g.db.row_factory = sqlite3.Row + + return g.db + +def close_db(e=None): + db = g.pop('db', None) + + if db is not None: + db.close() + +def init_db(): + db = get_db() + + with current_app.open_resource('schema.sql') as f: + db.executescript(f.read().decode('utf8')) + + +@click.command('init-db') +def init_db_command(): + """Refresh database""" + init_db() + click.echo('Initialized the database.') + + +sqlite3.register_converter( + "timestamp", lambda v: datetime.fromisoformat(v.decode()) +) + + +def init_app(app): + app.teardown_appcontext(close_db) + app.cli.add_command(init_db_command) + diff --git a/weather/schema.sql b/weather/schema.sql new file mode 100644 index 0000000..36526aa --- /dev/null +++ b/weather/schema.sql @@ -0,0 +1,43 @@ +DROP TABLE IF EXISTS periods; +DROP TABLE IF EXISTS reports; + +CREATE TABLE "periods" ( + "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT, + "report_id" Integer NOT NULL, + "period_number" Integer NOT NULL, + "name" Text, + "start_time" DateTime NOT NULL, + "end_time" DateTime NOT NULL, + "is_daytime" Integer NOT NULL, + "temperature" Integer NOT NULL, + "temperature_unit" Text NOT NULL DEFAULT 'F', + "precipitation_probability" Integer, + "dewpoint_celsius" Numeric, + "relative_humidity" Integer, + "wind_speed" Text, + "wind_direction" Text, + "icon_url" Text, + "short_forecast" Text, + "detailed_forecast" Text, + "created_at" DateTime, + "updated_at" DateTime, + CONSTRAINT "periods_reports_CASCADE_NO ACTION_report_id_id_0" FOREIGN KEY ( "report_id" ) REFERENCES "reports"( "id" ) + ON DELETE Cascade + ); + +CREATE INDEX "periods_report_id_start_time_index" ON "periods"( "report_id", "start_time" ); + +CREATE TABLE "reports" ( + "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT, + "type" Text NOT NULL, + "reported_at" DateTime NOT NULL, + "generated_at" DateTime NOT NULL, + "latitude" Numeric NOT NULL, + "longitude" Numeric NOT NULL, + "elevation_meters" Numeric, + "created_at" DateTime, + "updated_at" DateTime, +CONSTRAINT "check ""type"" in ('hourly', 'weekly')" CHECK ("type" in ('hourly', 'weekly')) ); + +CREATE INDEX "reports_type_reported_at_index" ON "reports"( "type", "reported_at" ); +CREATE UNIQUE INDEX "reports_type_reported_at_unique" ON "reports"( "type", "reported_at" );