-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4823143
commit aa54f55
Showing
20 changed files
with
596 additions
and
437 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from dataclasses import dataclass | ||
from typing import Callable | ||
from sqlalchemy.orm import Session as Database | ||
|
||
from lib.db.query.notification import get_notification_type_with_name | ||
|
||
|
||
@dataclass | ||
class NotifInfo: | ||
""" | ||
This class wraps information used to send the script logs to the database. | ||
""" | ||
|
||
# Noification type ID | ||
type_id: int | ||
# Notification origin, which is usually the script name | ||
origin: str | ||
# Process ID, which is usually the MRI upload ID | ||
process_id: int | ||
|
||
|
||
@dataclass | ||
class Env: | ||
""" | ||
This class wraps information about the environmentin which a LORIS-MRI script is executed. It | ||
notably stores the database handle and various information used for logging. | ||
""" | ||
|
||
db: Database | ||
script_name: str | ||
log_file: str | ||
verbose: bool | ||
cleanups: list[Callable[[], None]] = [] | ||
notif_info: NotifInfo | None = None | ||
|
||
def add_cleanup(self, cleanup: Callable[[], None]): | ||
""" | ||
Add a cleanup function to the environment, which will be executed if the program exits | ||
early. | ||
""" | ||
|
||
self.cleanups.append(cleanup) | ||
|
||
def run_cleanups(self): | ||
""" | ||
Run all the cleanup functions of the environment in the reverse insertion order (most | ||
recent is ran first). This clears the cleanup functions list. | ||
""" | ||
|
||
while self.cleanups != []: | ||
cleanup = self.cleanups.pop() | ||
cleanup() | ||
|
||
def set_process_id(self, process_id: int): | ||
""" | ||
Associate the current script with a given process ID, which notably allows to start logging | ||
execution information in the database. | ||
""" | ||
|
||
notification_type_name = f'PYTHON {self.script_name.replace("_", " ").upper()}' | ||
notification_type = get_notification_type_with_name(self.db, notification_type_name) | ||
self.notif_info = NotifInfo( | ||
notification_type.id, | ||
f'{self.script_name}.py', | ||
process_id, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from sqlalchemy import String | ||
from sqlalchemy.engine import Dialect | ||
from sqlalchemy.types import TypeDecorator | ||
|
||
|
||
class YNBool(TypeDecorator[bool]): | ||
""" | ||
Decorator for a database yes/no type. | ||
In SQL, the type will appear as 'Y' | 'N'. | ||
In Python, the type will appear as a boolean. | ||
""" | ||
|
||
impl = String | ||
|
||
def process_bind_param(self, value: bool | None, dialect: Dialect): | ||
match value: | ||
case True: | ||
return 'Y' | ||
case False: | ||
return 'N' | ||
case None: | ||
return None | ||
|
||
def process_result_value(self, value: str | None, dialect: Dialect): | ||
match value: | ||
case 'Y': | ||
return True | ||
case 'N': | ||
return False | ||
case _: | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from typing import Optional | ||
from sqlalchemy import ForeignKey | ||
from sqlalchemy.orm import Mapped, mapped_column, relationship | ||
from lib.db.base import Base | ||
import lib.db.model.config_setting as db_config_setting | ||
|
||
|
||
class DbConfig(Base): | ||
__tablename__ = 'Config' | ||
|
||
id : Mapped[int] = mapped_column('ID', primary_key=True) | ||
setting_id : Mapped[int] = mapped_column('ConfigID', ForeignKey('ConfigSettings.ID')) | ||
value : Mapped[Optional[str]] = mapped_column('Value') | ||
|
||
setting : Mapped['db_config_setting.DbConfigSetting'] = relationship('DbConfigSetting') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from typing import Optional | ||
from sqlalchemy.orm import Mapped, mapped_column | ||
from lib.db.base import Base | ||
|
||
|
||
class DbConfigSetting(Base): | ||
__tablename__ = 'ConfigSettings' | ||
|
||
id : Mapped[int] = mapped_column('ID', primary_key=True) | ||
name : Mapped[str] = mapped_column('Name') | ||
description : Mapped[Optional[str]] = mapped_column('Description') | ||
visible : Mapped[Optional[bool]] = mapped_column('Visible') | ||
allow_multiple : Mapped[Optional[bool]] = mapped_column('AllowMultiple') | ||
data_type : Mapped[Optional[str]] = mapped_column('DataType') | ||
parent_id : Mapped[Optional[int]] = mapped_column('Parent') | ||
label : Mapped[Optional[str]] = mapped_column('Label') | ||
order_number : Mapped[Optional[int]] = mapped_column('OrderNumber') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from datetime import datetime | ||
from typing import Optional | ||
from sqlalchemy.orm import Mapped, mapped_column | ||
from lib.db.base import Base | ||
from lib.db.decorator.y_n_bool import YNBool | ||
|
||
|
||
class DbNotificationSpool(Base): | ||
__tablename__ = 'notification_spool' | ||
|
||
id : Mapped[int] = mapped_column('NotificationID') | ||
type_id : Mapped[int] = mapped_column('NotificationTypeID') | ||
process_id : Mapped[int] = mapped_column('ProcessID') | ||
time_spooled : Mapped[Optional[datetime]] = mapped_column('TimeSpooled') | ||
message : Mapped[Optional[str]] = mapped_column('Message') | ||
error : Mapped[Optional[YNBool]] = mapped_column('Error') | ||
verbose : Mapped[YNBool] = mapped_column('Verbose') | ||
sent : Mapped[YNBool] = mapped_column('Sent') | ||
site_id : Mapped[Optional[int]] = mapped_column('CenterID') | ||
origin : Mapped[Optional[str]] = mapped_column('Origin') | ||
active : Mapped[YNBool] = mapped_column('Active') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from typing import Optional | ||
from sqlalchemy.orm import Mapped, mapped_column | ||
from lib.db.base import Base | ||
|
||
|
||
class DbNotificationType(Base): | ||
__tablename__ = 'notification_types' | ||
|
||
id : Mapped[int] = mapped_column('NotificationTypeID') | ||
name : Mapped[str] = mapped_column('Type') | ||
private : Mapped[Optional[bool]] = mapped_column('private') | ||
description: Mapped[Optional[str]] = mapped_column('Description') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from sqlalchemy import select | ||
from sqlalchemy.orm import Session as Database | ||
from lib.db.model.config import DbConfig | ||
from lib.db.model.config_setting import DbConfigSetting | ||
|
||
|
||
def get_config_with_setting_name(db: Database, name: str): | ||
""" | ||
Get a single configuration entry from the database using its configuration setting name, or | ||
raise an exception if no entry or several entries are found. | ||
""" | ||
|
||
return db.execute(select(DbConfig) | ||
.join(DbConfig.setting) | ||
.where(DbConfigSetting.name == name) | ||
).scalar_one() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from sqlalchemy import select | ||
from sqlalchemy.orm import Session as Database | ||
from lib.db.model.notification_type import DbNotificationType | ||
|
||
|
||
def get_notification_type_with_name(db: Database, name: str): | ||
""" | ||
Get a notification type from the database using its configuration setting name, or raise an | ||
exception if no notification type is found. | ||
""" | ||
|
||
return db.execute(select(DbNotificationType) | ||
.where(DbNotificationType.name == name) | ||
).scalar_one() |
Oops, something went wrong.