From 71257e4d67d21510cd16bc522113350146b5088d Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Sun, 16 Jun 2024 08:40:03 +0100 Subject: [PATCH] Ensure one db instance only Ensure testing db is correctly set to sqlite --- .envrc | 8 ++++---- app/dbmanager.py | 30 ++++++++++++++++++++++++++++++ app/models.py | 13 +++++++------ tests/__init__.py | 14 ++++++++++++++ tests/test_misc.py | 11 +---------- tests/test_models.py | 9 +-------- tests/test_playlistmodel.py | 12 ++---------- tests/test_ui.py | 13 +++++-------- 8 files changed, 64 insertions(+), 46 deletions(-) create mode 100644 app/dbmanager.py create mode 100644 tests/__init__.py diff --git a/.envrc b/.envrc index fcd4686..4462d1f 100644 --- a/.envrc +++ b/.envrc @@ -4,17 +4,17 @@ export MAIL_PORT=587 export MAIL_SERVER="smtp.fastmail.com" export MAIL_USERNAME="kae@midnighthax.com" export MAIL_USE_TLS=True -export PYGAME_HIDE_SUPPORT_PROMPT=1 branch=$(git branch --show-current) + # Always treat running from /home/kae/mm as production if [ $(pwd) == /home/kae/mm ]; then export MM_ENV="PRODUCTION" - export ALCHEMICAL_DATABASE_URI="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod" + export DATABASE_URL="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod" elif on_git_branch master; then export MM_ENV="PRODUCTION" - export ALCHEMICAL_DATABASE_URI="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod" + export DATABASE_URL="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod" else export MM_ENV="DEVELOPMENT" - export ALCHEMICAL_DATABASE_URI="mysql+mysqldb://dev_musicmuster:dev_musicmuster@localhost/dev_musicmuster" + export DATABASE_URL="mysql+mysqldb://dev_musicmuster:dev_musicmuster@localhost/dev_musicmuster" export PYTHONBREAKPOINT="pudb.set_trace" fi diff --git a/app/dbmanager.py b/app/dbmanager.py new file mode 100644 index 0000000..43048cb --- /dev/null +++ b/app/dbmanager.py @@ -0,0 +1,30 @@ +# Standard library imports + +# PyQt imports + +# Third party imports +from alchemical import Alchemical # type:ignore + +# App imports + + +class DatabaseManager: + """ + Singleton class to ensure we only ever have one db object + """ + + __instance = None + + def __init__(self, database_url, **kwargs): + if DatabaseManager.__instance is None: + self.db = Alchemical(database_url, **kwargs) + self.db.create_all() + DatabaseManager.__instance = self + else: + raise Exception("Attempted to create a second DatabaseManager instance") + + @staticmethod + def get_instance(database_url, **kwargs): + if DatabaseManager.__instance is None: + DatabaseManager(database_url, **kwargs) + return DatabaseManager.__instance diff --git a/app/models.py b/app/models.py index 02f5239..d6da42a 100644 --- a/app/models.py +++ b/app/models.py @@ -8,7 +8,6 @@ import sys # PyQt imports # Third party imports -from alchemical import Alchemical # type:ignore from sqlalchemy import ( bindparam, delete, @@ -22,18 +21,20 @@ from sqlalchemy.orm import joinedload from sqlalchemy.orm.session import Session # App imports +from dbmanager import DatabaseManager import dbtables from config import Config from log import log # Establish database connection -ALCHEMICAL_DATABASE_URI = os.environ.get("ALCHEMICAL_DATABASE_URI") -if ALCHEMICAL_DATABASE_URI is None: - raise ValueError("ALCHEMICAL_DATABASE_URI is undefined") -if "unittest" in sys.modules and "sqlite" not in ALCHEMICAL_DATABASE_URI: +DATABASE_URL = os.environ.get("DATABASE_URL") +if DATABASE_URL is None: + raise ValueError("DATABASE_URL is undefined") +if "unittest" in sys.modules and "sqlite" not in DATABASE_URL: raise ValueError("Unit tests running on non-Sqlite database") -db = Alchemical(ALCHEMICAL_DATABASE_URI, engine_options=Config.ENGINE_OPTIONS) +db = DatabaseManager.get_instance(DATABASE_URL, engine_options=Config.ENGINE_OPTIONS).db +db.create_all() # Database classes diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..58ccb70 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,14 @@ +# Standard library imports +import os + +# PyQt imports + +# Third party imports + +# App imports +# Set up test database before importing db +# https://blog.miguelgrinberg.com/post/how-to-write-unit-tests-in-python-part-3-web-applications +DB_FILE = "/tmp/mm.db" +if os.path.exists(DB_FILE): + os.unlink(DB_FILE) +os.environ["DATABASE_URL"] = "sqlite:///" + DB_FILE diff --git a/tests/test_misc.py b/tests/test_misc.py index c0d89f4..b85c685 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,5 +1,4 @@ # Standard library imports -import os import unittest # PyQt imports @@ -8,15 +7,7 @@ import unittest import pytest # App imports -# Set up test database before importing db -# Mark subsequent lines to ignore E402, imports not at top of file -# Set up test database before importing db -# Mark subsequent lines to ignore E402, imports not at top of file -DB_FILE = "/tmp/mm.db" -if os.path.exists(DB_FILE): - os.unlink(DB_FILE) -os.environ["ALCHEMICAL_DATABASE_URI"] = "sqlite:///" + DB_FILE -from models import db, Settings # noqa: E402 +from app.models import db, Settings class TestMMMisc(unittest.TestCase): diff --git a/tests/test_models.py b/tests/test_models.py index 5e0856a..b03eef1 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,6 +1,5 @@ # Standard library imports import datetime as dt -import os import unittest # PyQt imports @@ -10,13 +9,7 @@ import unittest # App imports from app import helpers -# Set up test database before importing db -# Mark subsequent lines to ignore E402, imports not at top of file -DB_FILE = "/tmp/mm.db" -if os.path.exists(DB_FILE): - os.unlink(DB_FILE) -os.environ["ALCHEMICAL_DATABASE_URI"] = "sqlite:///" + DB_FILE -from app.models import ( # noqa: E402 +from app.models import ( db, NoteColours, Playdates, diff --git a/tests/test_playlistmodel.py b/tests/test_playlistmodel.py index 2a5f227..c697f64 100644 --- a/tests/test_playlistmodel.py +++ b/tests/test_playlistmodel.py @@ -1,5 +1,4 @@ # Standard library imports -import os import unittest # PyQt imports @@ -9,15 +8,8 @@ from PyQt6.QtCore import Qt, QModelIndex # App imports from app.helpers import get_all_track_metadata - -# Set up test database before importing db -# Mark subsequent lines to ignore E402, imports not at top of file -DB_FILE = "/tmp/mm.db" -if os.path.exists(DB_FILE): - os.unlink(DB_FILE) -os.environ["ALCHEMICAL_DATABASE_URI"] = "sqlite:///" + DB_FILE -from app import playlistmodel # noqa: E402 -from app.models import ( # noqa: E402 +from app import playlistmodel +from app.models import ( db, Playlists, Tracks, diff --git a/tests/test_ui.py b/tests/test_ui.py index 8a84e4e..b4370e0 100644 --- a/tests/test_ui.py +++ b/tests/test_ui.py @@ -3,22 +3,19 @@ import os import unittest # PyQt imports +from PyQt6.QtCore import Qt +from PyQt6.QtGui import QColor # Third party imports import pytest from pytestqt.plugin import QtBot # type: ignore # App imports - -# Set up test database before importing db -# Mark subsequent lines to ignore E402, imports not at top of file -DB_FILE = "/tmp/mm.db" -if os.path.exists(DB_FILE): - os.unlink(DB_FILE) -os.environ["ALCHEMICAL_DATABASE_URI"] = "sqlite:///" + DB_FILE +from config import Config from app import playlistmodel, utilities -from app.models import ( # noqa: E402 +from app.models import ( db, + NoteColours, Playlists, Tracks, )