refactor: database initialize checker

This commit is contained in:
2025-08-13 15:17:46 +08:00
parent 806acd5793
commit 06a1ca00bd
6 changed files with 80 additions and 37 deletions

10
core/database/__init__.py Normal file
View File

@ -0,0 +1,10 @@
from .init_checker import DatabaseInitCheckResult, check_db_init
from .utils import create_engine, db_path_to_sqlite_url, sqlite_url_to_db_path
__all__ = [
"check_db_init",
"create_engine",
"db_path_to_sqlite_url",
"DatabaseInitCheckResult",
"sqlite_url_to_db_path",
]

View File

@ -0,0 +1,30 @@
from enum import Flag, auto
from pathlib import Path
from arcaea_offline.database import Database
from .utils import create_engine, db_path_to_sqlite_url
class DatabaseInitCheckResult(Flag):
NONE = 0
FILE_EXISTS = auto()
INITIALIZED = auto()
OK = FILE_EXISTS | INITIALIZED
def check_db_init(file: Path) -> DatabaseInitCheckResult:
flags = DatabaseInitCheckResult.NONE
if not file.exists():
return flags
flags |= DatabaseInitCheckResult.FILE_EXISTS
db_url = db_path_to_sqlite_url(file)
db = Database(create_engine(db_url))
if db.check_init():
flags |= DatabaseInitCheckResult.INITIALIZED
return flags

28
core/database/utils.py Normal file
View File

@ -0,0 +1,28 @@
from pathlib import Path
from PySide6.QtCore import QSysInfo, QUrl
from sqlalchemy import Engine
from sqlalchemy import create_engine as sa_create_engine
from sqlalchemy.pool import NullPool, Pool
def db_path_to_sqlite_url(file: Path) -> QUrl:
kernelType = QSysInfo.kernelType()
# the slash count varies depending on the kernel
# https://docs.sqlalchemy.org/en/20/core/engines.html#sqlite
uri = file.resolve().as_uri()
if kernelType == "winnt":
return QUrl(uri.replace("file://", "sqlite://"))
else:
return QUrl(uri.replace("file://", "sqlite:///"))
def sqlite_url_to_db_path(url: str) -> Path:
db_file_url = url.replace("sqlite://", "file://")
return Path(QUrl(db_file_url).toLocalFile()).resolve()
def create_engine(_url: str | QUrl, pool: type[Pool] = NullPool) -> Engine:
url = _url.toString() if isinstance(_url, QUrl) else _url
return sa_create_engine(url, poolclass=pool)

View File

@ -13,7 +13,7 @@ import ui.resources.resources_rc # noqa: F401
from core.settings import SettingsKeys, settings from core.settings import SettingsKeys, settings
from ui.extends.shared.language import changeAppLanguage from ui.extends.shared.language import changeAppLanguage
from ui.implements.mainwindow import MainWindow from ui.implements.mainwindow import MainWindow
from ui.startup.databaseChecker import DatabaseChecker, DatabaseCheckerResult from ui.startup.databaseChecker import DatabaseChecker, DatabaseInitCheckResult
rootLogger = logging.getLogger("root") rootLogger = logging.getLogger("root")
rootLogger.setLevel(logging.DEBUG) rootLogger.setLevel(logging.DEBUG)
@ -71,10 +71,10 @@ if __name__ == "__main__":
databaseCheckResult = ( databaseCheckResult = (
databaseChecker.confirmDb() databaseChecker.confirmDb()
if settings.stringValue(SettingsKeys.General.DatabaseUrl) if settings.stringValue(SettingsKeys.General.DatabaseUrl)
else 0 else DatabaseInitCheckResult.NONE
) )
if not databaseCheckResult & DatabaseCheckerResult.Initted: if not databaseCheckResult & DatabaseInitCheckResult.INITIALIZED:
result = databaseChecker.exec() result = databaseChecker.exec()
if result == QDialog.DialogCode.Accepted: if result == QDialog.DialogCode.Accepted:

View File

@ -1,14 +1,4 @@
from typing import Type from PySide6.QtCore import QObject, Signal
from PySide6.QtCore import QObject, QUrl, Signal
from sqlalchemy import Engine
from sqlalchemy import create_engine as sa_create_engine
from sqlalchemy.pool import NullPool, Pool
def create_engine(_url: str | QUrl, pool: Type[Pool] = NullPool) -> Engine:
url = _url.toString() if isinstance(_url, QUrl) else _url
return sa_create_engine(url, poolclass=pool)
class DatabaseUpdateSignals(QObject): class DatabaseUpdateSignals(QObject):

View File

@ -1,24 +1,19 @@
import logging import logging
import traceback import traceback
from enum import IntEnum from pathlib import Path
from arcaea_offline.database import Database from arcaea_offline.database import Database
from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, QSysInfo, Qt, QUrl, Slot from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, QSysInfo, Qt, QUrl, Slot
from PySide6.QtWidgets import QDialog, QMessageBox from PySide6.QtWidgets import QDialog, QMessageBox
from core.database import DatabaseInitCheckResult, check_db_init, create_engine
from core.settings import SettingsKeys, settings from core.settings import SettingsKeys, settings
from ui.extends.shared.database import create_engine
from .databaseChecker_ui import Ui_DatabaseChecker from .databaseChecker_ui import Ui_DatabaseChecker
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class DatabaseCheckerResult(IntEnum):
FileExist = 0x001
Initted = 0x002
class DatabaseChecker(Ui_DatabaseChecker, QDialog): class DatabaseChecker(Ui_DatabaseChecker, QDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
@ -69,21 +64,11 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
else: else:
return QUrl(self.dbFileUrl().toString().replace("file://", "sqlite:///")) return QUrl(self.dbFileUrl().toString().replace("file://", "sqlite:///"))
def confirmDb(self) -> DatabaseCheckerResult: def confirmDb(self) -> DatabaseInitCheckResult:
flags = 0x000
dbFileInfo = self.dbFileInfo() dbFileInfo = self.dbFileInfo()
dbSqliteUrl = self.dbSqliteUrl() dbPath = Path(dbFileInfo.absoluteFilePath())
if not dbFileInfo.exists():
return flags
flags |= DatabaseCheckerResult.FileExist return check_db_init(dbPath)
db = Database(create_engine(dbSqliteUrl))
if db.check_init():
flags |= DatabaseCheckerResult.Initted
self.writeDatabaseUrlToSettings(self.dbSqliteUrl().toString())
return flags
def updateLabels(self): def updateLabels(self):
result = self.confirmDb() result = self.confirmDb()
@ -102,7 +87,7 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
self.dbVersionLabel.setText("-") self.dbVersionLabel.setText("-")
self.dbCheckConnLabel.setText( self.dbCheckConnLabel.setText(
f'<font color="red">Error: {e}</font>' f'<font color="red">Error: {e}</font>'
if result & DatabaseCheckerResult.FileExist if result & DatabaseInitCheckResult.FILE_EXISTS
else "-" else "-"
) )
self.continueButton.setEnabled(False) self.continueButton.setEnabled(False)
@ -113,10 +98,10 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
self.writeDatabaseUrlToSettings(dbSqliteUrl.toString()) self.writeDatabaseUrlToSettings(dbSqliteUrl.toString())
result = self.confirmDb() result = self.confirmDb()
if result & DatabaseCheckerResult.Initted: if result & DatabaseInitCheckResult.INITIALIZED:
if not self.confirmDbByExistingSettings: if not self.confirmDbByExistingSettings:
self.writeDatabaseUrlToSettings(dbSqliteUrl.toString()) self.writeDatabaseUrlToSettings(dbSqliteUrl.toString())
elif result & DatabaseCheckerResult.FileExist: elif result & DatabaseInitCheckResult.FILE_EXISTS:
confirm_try_init = QMessageBox.question( confirm_try_init = QMessageBox.question(
self, self,
None, None,