From 4961ddc3497b4ca16dfa2f87d8bddd55134dbc29 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Mon, 2 Mar 2026 19:05:56 +0000 Subject: [PATCH 1/7] refactor: move db dir into server --- server/app.py | 6 +++--- server/auth.py | 2 +- {db => server/db}/database.py | 19 ++++--------------- {db => server/db}/schema.sql | 5 +---- .../{dataset_processor.py => enrichment.py} | 2 +- server/stat_gen.py | 2 -- server/utils.py | 2 +- 7 files changed, 11 insertions(+), 27 deletions(-) rename {db => server/db}/database.py (90%) rename {db => server/db}/schema.sql (94%) rename server/{dataset_processor.py => enrichment.py} (98%) diff --git a/server/app.py b/server/app.py index 5e63acd..7df12cb 100644 --- a/server/app.py +++ b/server/app.py @@ -12,9 +12,9 @@ from flask_jwt_extended import ( ) from server.stat_gen import StatGen -from server.dataset_processor import DatasetProcessor +from server.enrichment import DatasetEnrichment from server.exceptions import NotAuthorisedException, NotExistentDatasetException -from db.database import PostgresConnector +from server.db.database import PostgresConnector from server.auth import AuthManager from server.utils import get_request_filters, get_dataset_and_validate @@ -130,7 +130,7 @@ def upload_data(): posts_df = pd.read_json(post_file, lines=True, convert_dates=False) topics = json.load(topic_file) - processor = DatasetProcessor(posts_df, topics) + processor = DatasetEnrichment(posts_df, topics) enriched_df = processor.enrich() dataset_id = db.save_dataset_info( current_user, f"dataset_{current_user}", topics diff --git a/server/auth.py b/server/auth.py index 9d62512..2371da9 100644 --- a/server/auth.py +++ b/server/auth.py @@ -1,4 +1,4 @@ -from db.database import PostgresConnector +from server.db.database import PostgresConnector from flask_bcrypt import Bcrypt class AuthManager: diff --git a/db/database.py b/server/db/database.py similarity index 90% rename from db/database.py rename to server/db/database.py index a9c6d41..80cf5b3 100644 --- a/db/database.py +++ b/server/db/database.py @@ -3,7 +3,6 @@ import psycopg2 import pandas as pd from psycopg2.extras import RealDictCursor from psycopg2.extras import execute_batch, Json -from server.exceptions import NotExistentDatasetException class PostgresConnector: @@ -68,7 +67,6 @@ class PostgresConnector: type, parent_id, author, - title, content, timestamp, date, @@ -90,8 +88,7 @@ class PostgresConnector: %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s + %s, %s, %s, %s, %s ) """ @@ -103,7 +100,6 @@ class PostgresConnector: row["type"], row["parent_id"], row["author"], - row.get("title"), row["content"], row["timestamp"], row["date"], @@ -114,7 +110,7 @@ class PostgresConnector: row["source"], row.get("topic"), row.get("topic_confidence"), - Json(row["entities"]) if row.get("entities") else None, + Json(row["ner_entities"]) if row.get("ner_entities") else None, row.get("emotion_anger"), row.get("emotion_disgust"), row.get("emotion_fear"), @@ -130,19 +126,12 @@ class PostgresConnector: def get_dataset_content(self, dataset_id: int) -> pd.DataFrame: query = "SELECT * FROM events WHERE dataset_id = %s" result = self.execute(query, (dataset_id,), fetch=True) - - if result: - return pd.DataFrame(result) - - raise NotExistentDatasetException("Dataset does not exist") + return pd.DataFrame(result) def get_dataset_info(self, dataset_id: int) -> dict: query = "SELECT * FROM datasets WHERE id = %s" result = self.execute(query, (dataset_id,), fetch=True) - if result: - return result[0] - - raise NotExistentDatasetException("Dataset does not exist") + return result[0] if result else None def close(self): if self.connection: diff --git a/db/schema.sql b/server/db/schema.sql similarity index 94% rename from db/schema.sql rename to server/db/schema.sql index 5a9eaee..693f821 100644 --- a/db/schema.sql +++ b/server/db/schema.sql @@ -30,10 +30,7 @@ CREATE TABLE events ( hour INTEGER NOT NULL, weekday VARCHAR(255) NOT NULL, - /* Posts Only */ - title VARCHAR(255), - - /* Comments Only*/ + /* Comments and Replies */ parent_id VARCHAR(255), reply_to VARCHAR(255), source VARCHAR(255) NOT NULL, diff --git a/server/dataset_processor.py b/server/enrichment.py similarity index 98% rename from server/dataset_processor.py rename to server/enrichment.py index 37e94da..065caea 100644 --- a/server/dataset_processor.py +++ b/server/enrichment.py @@ -2,7 +2,7 @@ import pandas as pd from server.analysis.nlp import NLP -class DatasetProcessor: +class DatasetEnrichment: def __init__(self, df, topics): self.df = self._explode_comments(df) self.topics = topics diff --git a/server/stat_gen.py b/server/stat_gen.py index 2ea5ac1..f9d8344 100644 --- a/server/stat_gen.py +++ b/server/stat_gen.py @@ -1,5 +1,3 @@ -import datetime - import nltk import pandas as pd from nltk.corpus import stopwords diff --git a/server/utils.py b/server/utils.py index 71e593b..5e20706 100644 --- a/server/utils.py +++ b/server/utils.py @@ -3,7 +3,7 @@ import pandas as pd from flask import request from flask_jwt_extended import get_jwt_identity -from db.database import PostgresConnector +from server.db.database import PostgresConnector from server.exceptions import NotAuthorisedException def parse_datetime_filter(value): -- 2.49.1 From 4bec0dd32cfb0ffcc2d4260608a48ac3081d68d3 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Mon, 2 Mar 2026 19:18:05 +0000 Subject: [PATCH 2/7] refactor: extract dataset functionality out of db class --- server/app.py | 36 +++++++++------ server/auth.py | 29 ++++++++++-- server/datasets.py | 104 ++++++++++++++++++++++++++++++++++++++++++ server/db/database.py | 103 +---------------------------------------- server/utils.py | 14 ------ 5 files changed, 151 insertions(+), 135 deletions(-) create mode 100644 server/datasets.py diff --git a/server/app.py b/server/app.py index 7df12cb..f7ad584 100644 --- a/server/app.py +++ b/server/app.py @@ -16,14 +16,14 @@ from server.enrichment import DatasetEnrichment from server.exceptions import NotAuthorisedException, NotExistentDatasetException from server.db.database import PostgresConnector from server.auth import AuthManager -from server.utils import get_request_filters, get_dataset_and_validate +from server.datasets import DatasetManager +from server.utils import get_request_filters import pandas as pd import traceback import json app = Flask(__name__) -db = PostgresConnector() # Env Variables load_dotenv() @@ -40,11 +40,12 @@ app.config["JWT_ACCESS_TOKEN_EXPIRES"] = jwt_access_token_expires bcrypt = Bcrypt(app) jwt = JWTManager(app) + +db = PostgresConnector() auth_manager = AuthManager(db, bcrypt) - +dataset_manager = DatasetManager(db) stat_gen = StatGen() - @app.route("/register", methods=["POST"]) def register_user(): data = request.get_json() @@ -132,10 +133,8 @@ def upload_data(): processor = DatasetEnrichment(posts_df, topics) enriched_df = processor.enrich() - dataset_id = db.save_dataset_info( - current_user, f"dataset_{current_user}", topics - ) - db.save_dataset_content(dataset_id, enriched_df) + dataset_id = dataset_manager.save_dataset_info(current_user, f"dataset_{current_user}", topics) + dataset_manager.save_dataset_content(dataset_id, enriched_df) return jsonify( { @@ -154,7 +153,8 @@ def upload_data(): @jwt_required() def get_dataset(dataset_id): try: - dataset_content = get_dataset_and_validate(dataset_id, db) + user_id = get_jwt_identity() + dataset_content = dataset_manager.get_dataset_and_validate(dataset_id, int(user_id)) filters = get_request_filters() filtered_dataset = stat_gen.filter_dataset(dataset_content, filters) return jsonify(filtered_dataset), 200 @@ -171,7 +171,8 @@ def get_dataset(dataset_id): @jwt_required() def content_endpoint(dataset_id): try: - dataset_content = get_dataset_and_validate(dataset_id, db) + user_id = get_jwt_identity() + dataset_content = dataset_manager.get_dataset_and_validate(dataset_id, int(user_id)) filters = get_request_filters() return jsonify(stat_gen.get_content_analysis(dataset_content, filters)), 200 except NotAuthorisedException: @@ -187,7 +188,8 @@ def content_endpoint(dataset_id): @jwt_required() def get_summary(dataset_id): try: - dataset_content = get_dataset_and_validate(dataset_id, db) + user_id = get_jwt_identity() + dataset_content = dataset_manager.get_dataset_and_validate(dataset_id, int(user_id)) filters = get_request_filters() return jsonify(stat_gen.summary(dataset_content, filters)), 200 except NotAuthorisedException: @@ -203,7 +205,8 @@ def get_summary(dataset_id): @jwt_required() def get_time_analysis(dataset_id): try: - dataset_content = get_dataset_and_validate(dataset_id, db) + user_id = get_jwt_identity() + dataset_content = dataset_manager.get_dataset_and_validate(dataset_id, int(user_id)) filters = get_request_filters() return jsonify(stat_gen.get_time_analysis(dataset_content, filters)), 200 except NotAuthorisedException: @@ -219,7 +222,8 @@ def get_time_analysis(dataset_id): @jwt_required() def get_user_analysis(dataset_id): try: - dataset_content = get_dataset_and_validate(dataset_id, db) + user_id = get_jwt_identity() + dataset_content = dataset_manager.get_dataset_and_validate(dataset_id, int(user_id)) filters = get_request_filters() return jsonify(stat_gen.get_user_analysis(dataset_content, filters)), 200 except NotAuthorisedException: @@ -235,7 +239,8 @@ def get_user_analysis(dataset_id): @jwt_required() def get_cultural_analysis(dataset_id): try: - dataset_content = get_dataset_and_validate(dataset_id, db) + user_id = get_jwt_identity() + dataset_content = dataset_manager.get_dataset_and_validate(dataset_id, int(user_id)) filters = get_request_filters() return jsonify(stat_gen.get_cultural_analysis(dataset_content, filters)), 200 except NotAuthorisedException: @@ -251,7 +256,8 @@ def get_cultural_analysis(dataset_id): @jwt_required() def get_interaction_analysis(dataset_id): try: - dataset_content = get_dataset_and_validate(dataset_id, db) + user_id = get_jwt_identity() + dataset_content = dataset_manager.get_dataset_and_validate(dataset_id, int(user_id)) filters = get_request_filters() return jsonify(stat_gen.get_interactional_analysis(dataset_content, filters)), 200 except NotAuthorisedException: diff --git a/server/auth.py b/server/auth.py index 2371da9..625c3c2 100644 --- a/server/auth.py +++ b/server/auth.py @@ -6,19 +6,28 @@ class AuthManager: self.db = db self.bcrypt = bcrypt + # private + def _save_user(self, username, email, password_hash): + query = """ + INSERT INTO users (username, email, password_hash) + VALUES (%s, %s, %s) + """ + self.db.execute(query, (username, email, password_hash)) + + # public def register_user(self, username, email, password): hashed_password = self.bcrypt.generate_password_hash(password).decode("utf-8") - if self.db.get_user_by_email(email): + if self.get_user_by_email(email): raise ValueError("Email already registered") - if self.db.get_user_by_username(username): + if self.get_user_by_username(username): raise ValueError("Username already taken") - self.db.save_user(username, email, hashed_password) + self._save_user(username, email, hashed_password) def authenticate_user(self, username, password): - user = self.db.get_user_by_username(username) + user = self.get_user_by_username(username) if user and self.bcrypt.check_password_hash(user['password_hash'], password): return user return None @@ -26,4 +35,14 @@ class AuthManager: def get_user_by_id(self, user_id): query = "SELECT id, username, email FROM users WHERE id = %s" result = self.db.execute(query, (user_id,), fetch=True) - return result[0] if result else None \ No newline at end of file + return result[0] if result else None + + def get_user_by_username(self, username) -> dict: + query = "SELECT id, username, email, password_hash FROM users WHERE username = %s" + result = self.db.execute(query, (username,), fetch=True) + return result[0] if result else None + + def get_user_by_email(self, email) -> dict: + query = "SELECT id, username, email, password_hash FROM users WHERE email = %s" + result = self.db.execute(query, (email,), fetch=True) + return result[0] if result else None diff --git a/server/datasets.py b/server/datasets.py new file mode 100644 index 0000000..f741d7d --- /dev/null +++ b/server/datasets.py @@ -0,0 +1,104 @@ +import pandas as pd +from server.db.database import PostgresConnector +from psycopg2.extras import Json +from server.exceptions import NotAuthorisedException +from flask_jwt_extended import get_jwt_identity + +class DatasetManager: + def __init__(self, db: PostgresConnector): + self.db = db + + def get_dataset_and_validate(self, dataset_id: int, user_id: int) -> pd.DataFrame: + dataset_info = self.get_dataset_info(dataset_id) + + if dataset_info.get("user_id") != user_id: + raise NotAuthorisedException("This user is not authorised to access this dataset") + + return self.get_dataset_content(dataset_id) + + def get_dataset_content(self, dataset_id: int) -> pd.DataFrame: + query = "SELECT * FROM events WHERE dataset_id = %s" + result = self.db.execute(query, (dataset_id,), fetch=True) + return pd.DataFrame(result) + + def get_dataset_info(self, dataset_id: int) -> dict: + query = "SELECT * FROM datasets WHERE id = %s" + result = self.db.execute(query, (dataset_id,), fetch=True) + return result[0] if result else None + + def save_dataset_info(self, user_id: int, dataset_name: str, topics: dict) -> int: + query = """ + INSERT INTO datasets (user_id, name, topics) + VALUES (%s, %s, %s) + RETURNING id + """ + result = self.db.execute(query, (user_id, dataset_name, Json(topics)), fetch=True) + return result[0]["id"] if result else None + + def get_dataset_content(self, dataset_id: int) -> pd.DataFrame: + query = "SELECT * FROM events WHERE dataset_id = %s" + result = self.db.execute(query, (dataset_id,), fetch=True) + return pd.DataFrame(result) + + def save_dataset_content(self, dataset_id: int, event_data: pd.DataFrame): + if event_data.empty: + return + + query = """ + INSERT INTO events ( + dataset_id, + type, + parent_id, + author, + content, + timestamp, + date, + dt, + hour, + weekday, + reply_to, + source, + topic, + topic_confidence, + ner_entities, + emotion_anger, + emotion_disgust, + emotion_fear, + emotion_joy, + emotion_sadness + ) + VALUES ( + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s + ) + """ + + values = [ + ( + dataset_id, + row["type"], + row["parent_id"], + row["author"], + row["content"], + row["timestamp"], + row["date"], + row["dt"], + row["hour"], + row["weekday"], + row.get("reply_to"), + row["source"], + row.get("topic"), + row.get("topic_confidence"), + Json(row["ner_entities"]) if row.get("ner_entities") else None, + row.get("emotion_anger"), + row.get("emotion_disgust"), + row.get("emotion_fear"), + row.get("emotion_joy"), + row.get("emotion_sadness"), + ) + for _, row in event_data.iterrows() + ] + + self.db.execute_batch(query, values) \ No newline at end of file diff --git a/server/db/database.py b/server/db/database.py index 80cf5b3..34a63f2 100644 --- a/server/db/database.py +++ b/server/db/database.py @@ -27,112 +27,13 @@ class PostgresConnector: return cursor.fetchall() self.connection.commit() - def executemany(self, query, param_list) -> list: - with self.connection.cursor(cursor_factory=RealDictCursor) as cursor: - cursor.executemany(query, param_list) - self.connection.commit() - - ## User Management Methods - def save_user(self, username, email, password_hash): - query = """ - INSERT INTO users (username, email, password_hash) - VALUES (%s, %s, %s) - """ - self.execute(query, (username, email, password_hash)) - - def get_user_by_username(self, username) -> dict: - query = "SELECT id, username, email, password_hash FROM users WHERE username = %s" - result = self.execute(query, (username,), fetch=True) - return result[0] if result else None - - def get_user_by_email(self, email) -> dict: - query = "SELECT id, username, email, password_hash FROM users WHERE email = %s" - result = self.execute(query, (email,), fetch=True) - return result[0] if result else None - - # Dataset Management Methods - def save_dataset_info(self, user_id: int, dataset_name: str, topics: dict) -> int: - query = """ - INSERT INTO datasets (user_id, name, topics) - VALUES (%s, %s, %s) - RETURNING id - """ - result = self.execute(query, (user_id, dataset_name, Json(topics)), fetch=True) - return result[0]["id"] if result else None - - def save_dataset_content(self, dataset_id: int, event_data: pd.DataFrame): - query = """ - INSERT INTO events ( - dataset_id, - type, - parent_id, - author, - content, - timestamp, - date, - dt, - hour, - weekday, - reply_to, - source, - topic, - topic_confidence, - ner_entities, - emotion_anger, - emotion_disgust, - emotion_fear, - emotion_joy, - emotion_sadness - ) - VALUES ( - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s - ) - """ - - values = [] - - for _, row in event_data.iterrows(): - values.append(( - dataset_id, - row["type"], - row["parent_id"], - row["author"], - row["content"], - row["timestamp"], - row["date"], - row["dt"], - row["hour"], - row["weekday"], - row.get("reply_to"), - row["source"], - row.get("topic"), - row.get("topic_confidence"), - Json(row["ner_entities"]) if row.get("ner_entities") else None, - row.get("emotion_anger"), - row.get("emotion_disgust"), - row.get("emotion_fear"), - row.get("emotion_joy"), - row.get("emotion_sadness"), - )) - - + def execute_batch(self, query, values): with self.connection.cursor(cursor_factory=RealDictCursor) as cursor: execute_batch(cursor, query, values) self.connection.commit() - def get_dataset_content(self, dataset_id: int) -> pd.DataFrame: - query = "SELECT * FROM events WHERE dataset_id = %s" - result = self.execute(query, (dataset_id,), fetch=True) - return pd.DataFrame(result) - - def get_dataset_info(self, dataset_id: int) -> dict: - query = "SELECT * FROM datasets WHERE id = %s" - result = self.execute(query, (dataset_id,), fetch=True) - return result[0] if result else None + ## User Management Methods def close(self): if self.connection: self.connection.close() \ No newline at end of file diff --git a/server/utils.py b/server/utils.py index 5e20706..815739f 100644 --- a/server/utils.py +++ b/server/utils.py @@ -1,10 +1,5 @@ import datetime -import pandas as pd - from flask import request -from flask_jwt_extended import get_jwt_identity -from server.db.database import PostgresConnector -from server.exceptions import NotAuthorisedException def parse_datetime_filter(value): if not value: @@ -53,12 +48,3 @@ def get_request_filters() -> dict: filters["data_sources"] = data_sources return filters - -def get_dataset_and_validate(dataset_id: int, db: PostgresConnector) -> pd.DataFrame: - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - raise NotAuthorisedException("This user is not authorised to access this dataset") - - return db.get_dataset_content(dataset_id) -- 2.49.1 From 36bede42d9f8687e4e8c9616cf7028c6a6ed4129 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Tue, 3 Mar 2026 11:08:56 +0000 Subject: [PATCH 3/7] style: clean up imports --- server/app.py | 7 +++---- server/datasets.py | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/server/app.py b/server/app.py index f7ad584..a5aab98 100644 --- a/server/app.py +++ b/server/app.py @@ -1,4 +1,7 @@ import os +import pandas as pd +import traceback +import json from dotenv import load_dotenv from flask import Flask, jsonify, request @@ -19,10 +22,6 @@ from server.auth import AuthManager from server.datasets import DatasetManager from server.utils import get_request_filters -import pandas as pd -import traceback -import json - app = Flask(__name__) # Env Variables diff --git a/server/datasets.py b/server/datasets.py index f741d7d..0d5dba5 100644 --- a/server/datasets.py +++ b/server/datasets.py @@ -2,7 +2,6 @@ import pandas as pd from server.db.database import PostgresConnector from psycopg2.extras import Json from server.exceptions import NotAuthorisedException -from flask_jwt_extended import get_jwt_identity class DatasetManager: def __init__(self, db: PostgresConnector): -- 2.49.1 From 8b8462fd58c95d56878b4f303ed3c6a1a833ed5d Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Tue, 3 Mar 2026 11:11:10 +0000 Subject: [PATCH 4/7] chore: add non-existent database error check --- server/db/database.py | 24 +++++++++++++++--------- server/exceptions.py | 3 +++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/server/db/database.py b/server/db/database.py index 34a63f2..efbbfcd 100644 --- a/server/db/database.py +++ b/server/db/database.py @@ -1,8 +1,9 @@ import os import psycopg2 -import pandas as pd from psycopg2.extras import RealDictCursor -from psycopg2.extras import execute_batch, Json +from psycopg2.extras import execute_batch + +from server.exceptions import DatabaseNotConfiguredException class PostgresConnector: @@ -11,13 +12,18 @@ class PostgresConnector: """ def __init__(self): - self.connection = psycopg2.connect( - host=os.getenv("POSTGRES_HOST", "localhost"), - port=os.getenv("POSTGRES_PORT", 5432), - user=os.getenv("POSTGRES_USER", "postgres"), - password=os.getenv("POSTGRES_PASSWORD", "postgres"), - database=os.getenv("POSTGRES_DB", "postgres"), - ) + + try: + self.connection = psycopg2.connect( + host=os.getenv("POSTGRES_HOST", "localhost"), + port=os.getenv("POSTGRES_PORT", 5432), + user=os.getenv("POSTGRES_USER", "postgres"), + password=os.getenv("POSTGRES_PASSWORD", "postgres"), + database=os.getenv("POSTGRES_DB", "postgres"), + ) + except psycopg2.OperationalError as e: + raise DatabaseNotConfiguredException(f"Ensure database is up and running: {e}") + self.connection.autocommit = False def execute(self, query, params=None, fetch=False) -> list: diff --git a/server/exceptions.py b/server/exceptions.py index f3ebaa9..e63be49 100644 --- a/server/exceptions.py +++ b/server/exceptions.py @@ -2,4 +2,7 @@ class NotAuthorisedException(Exception): pass class NotExistentDatasetException(Exception): + pass + +class DatabaseNotConfiguredException(Exception): pass \ No newline at end of file -- 2.49.1 From 87bdc0245a3e06708d78b2ffc4c30294b1f9b2b4 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Tue, 3 Mar 2026 11:13:33 +0000 Subject: [PATCH 5/7] refactor: move core files into separate dirs --- server/{ => analysis}/enrichment.py | 0 server/{ => analysis}/stat_gen.py | 0 server/{ => core}/app.py | 8 ++++---- server/{ => core}/auth.py | 0 server/{ => core}/datasets.py | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename server/{ => analysis}/enrichment.py (100%) rename server/{ => analysis}/stat_gen.py (100%) rename server/{ => core}/app.py (98%) rename server/{ => core}/auth.py (100%) rename server/{ => core}/datasets.py (100%) diff --git a/server/enrichment.py b/server/analysis/enrichment.py similarity index 100% rename from server/enrichment.py rename to server/analysis/enrichment.py diff --git a/server/stat_gen.py b/server/analysis/stat_gen.py similarity index 100% rename from server/stat_gen.py rename to server/analysis/stat_gen.py diff --git a/server/app.py b/server/core/app.py similarity index 98% rename from server/app.py rename to server/core/app.py index a5aab98..be48607 100644 --- a/server/app.py +++ b/server/core/app.py @@ -14,12 +14,12 @@ from flask_jwt_extended import ( get_jwt_identity, ) -from server.stat_gen import StatGen -from server.enrichment import DatasetEnrichment +from server.analysis.stat_gen import StatGen +from server.analysis.enrichment import DatasetEnrichment from server.exceptions import NotAuthorisedException, NotExistentDatasetException from server.db.database import PostgresConnector -from server.auth import AuthManager -from server.datasets import DatasetManager +from server.core.auth import AuthManager +from server.core.datasets import DatasetManager from server.utils import get_request_filters app = Flask(__name__) diff --git a/server/auth.py b/server/core/auth.py similarity index 100% rename from server/auth.py rename to server/core/auth.py diff --git a/server/datasets.py b/server/core/datasets.py similarity index 100% rename from server/datasets.py rename to server/core/datasets.py -- 2.49.1 From 07a3b204bfdda94cbebf5e3c0319c3eeb34cf78b Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Tue, 3 Mar 2026 11:14:41 +0000 Subject: [PATCH 6/7] fix: incorrect docker compose db dirs --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index dec2007..3522b91 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,8 +8,8 @@ services: ports: - "5432:5432" volumes: - - ./db/postgres_vol:/var/lib/postgresql/data - - ./db/schema.sql:/docker-entrypoint-initdb.d/schema.sql + - ./server/db/postgres_vol:/var/lib/postgresql/data + - ./server/db/schema.sql:/docker-entrypoint-initdb.d/schema.sql volumes: postgres_data: \ No newline at end of file -- 2.49.1 From 6248b32ce2cd79e458ba98e2225263dc5186d191 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Tue, 3 Mar 2026 11:14:51 +0000 Subject: [PATCH 7/7] refactor: move app.py into main server dir --- server/{core => }/app.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename server/{core => }/app.py (100%) diff --git a/server/core/app.py b/server/app.py similarity index 100% rename from server/core/app.py rename to server/app.py -- 2.49.1