Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add column defaults to ORM models and tests #1204

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions python/lib/db/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass


class Base(DeclarativeBase):
class Base(DeclarativeBase, MappedAsDataclass):
"""
Base SQLAlchemy class that must be inherited by all the ORM model classes.
"""
Expand Down
33 changes: 33 additions & 0 deletions python/lib/db/decorator/true_false_bool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from typing import Literal

from sqlalchemy import Enum
from sqlalchemy.engine import Dialect
from sqlalchemy.types import TypeDecorator


class TrueFalseBool(TypeDecorator[bool]):
"""
Decorator for a database yes/no type.
In SQL, the type will appear as 'true' | 'false'.
In Python, the type will appear as a boolean.
"""

impl = Enum('true', 'false')

def process_bind_param(self, value: bool | None, dialect: Dialect):
match value:
case True:
return 'true'
case False:
return 'false'
case None:
return None

def process_result_value(self, value: Literal['true', 'false'] | None, dialect: Dialect):
match value:
case 'true':
return True
case 'false':
return False
case None:
return None
60 changes: 33 additions & 27 deletions python/lib/db/model/candidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,52 @@

from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql.functions import current_timestamp

import lib.db.model.project as db_project
import lib.db.model.session as db_session
import lib.db.model.site as db_site
from lib.db.base import Base
from lib.db.decorator.true_false_bool import TrueFalseBool
from lib.db.decorator.y_n_bool import YNBool


class DbCandidate(Base):
__tablename__ = 'candidate'

id : Mapped[int] = mapped_column('ID', primary_key=True)
id : Mapped[int] = mapped_column('ID',
primary_key=True, autoincrement=True, init=False)
cand_id : Mapped[int] = mapped_column('CandID')
psc_id : Mapped[str] = mapped_column('PSCID')
external_id : Mapped[Optional[str]] = mapped_column('ExternalID')
date_of_birth : Mapped[Optional[date]] = mapped_column('DoB')
dete_of_death : Mapped[Optional[date]] = mapped_column('DoD')
edc : Mapped[Optional[date]] = mapped_column('EDC')
sex : Mapped[Optional[str]] = mapped_column('Sex')
registration_site_id : Mapped[int] = mapped_column('RegistrationCenterID', ForeignKey('psc.CenterID'))
registration_project_id : Mapped[int] \
= mapped_column('RegistrationProjectID', ForeignKey('Project.ProjectID'))
ethnicity : Mapped[Optional[str]] = mapped_column('Ethnicity')
active : Mapped[bool] = mapped_column('Active', YNBool)
date_active : Mapped[Optional[date]] = mapped_column('Date_active')
registered_by : Mapped[Optional[str]] = mapped_column('RegisteredBy')
user_id : Mapped[str] = mapped_column('UserID')
date_registered : Mapped[Optional[date]] = mapped_column('Date_registered')
flagged_caveatemptor : Mapped[Optional[str]] = mapped_column('flagged_caveatemptor')
flagged_reason : Mapped[Optional[int]] = mapped_column('flagged_reason')
flagged_other : Mapped[Optional[str]] = mapped_column('flagged_other')
flagged_other_status : Mapped[Optional[str]] = mapped_column('flagged_other_status')
test_date : Mapped[datetime] = mapped_column('Testdate')
entity_type : Mapped[str] = mapped_column('Entity_type')
proband_sex : Mapped[Optional[str]] = mapped_column('ProbandSex')
proband_sate_of_birth : Mapped[Optional[date]] = mapped_column('ProbandDoB')
registration_site_id : Mapped[int] = mapped_column('RegistrationCenterID',
ForeignKey('psc.CenterID'))
registration_project_id : Mapped[int] = mapped_column('RegistrationProjectID',
ForeignKey('Project.ProjectID'))
psc_id : Mapped[str] = mapped_column('PSCID', default='')
external_id : Mapped[Optional[str]] = mapped_column('ExternalID', default=None)
date_of_birth : Mapped[Optional[date]] = mapped_column('DoB', default=None)
dete_of_death : Mapped[Optional[date]] = mapped_column('DoD', default=None)
edc : Mapped[Optional[date]] = mapped_column('EDC', default=None)
sex : Mapped[Optional[str]] = mapped_column('Sex', default=None)
ethnicity : Mapped[Optional[str]] = mapped_column('Ethnicity', default=None)
active : Mapped[bool] = mapped_column('Active', YNBool, default=True)
date_active : Mapped[Optional[date]] = mapped_column('Date_active', default=None)
registered_by : Mapped[Optional[str]] = mapped_column('RegisteredBy', default=None)
user_id : Mapped[str] = mapped_column('UserID', default='')
date_registered : Mapped[Optional[date]] = mapped_column('Date_registered', default=None)
flagged_caveatemptor : Mapped[Optional[str]] = mapped_column('flagged_caveatemptor',
TrueFalseBool, default=False)
flagged_reason : Mapped[Optional[int]] = mapped_column('flagged_reason', default=None)
flagged_other : Mapped[Optional[str]] = mapped_column('flagged_other', default=None)
flagged_other_status : Mapped[Optional[str]] = mapped_column('flagged_other_status', default=None)
test_date : Mapped[datetime] = mapped_column('Testdate',
default=current_timestamp(), onupdate=current_timestamp())
entity_type : Mapped[str] = mapped_column('Entity_type', default='Human')
proband_sex : Mapped[Optional[str]] = mapped_column('ProbandSex', default=None)
proband_sate_of_birth : Mapped[Optional[date]] = mapped_column('ProbandDoB', default=None)

sessions : Mapped[list['db_session.DbSession']] \
= relationship('DbSession', back_populates='candidate')
= relationship('DbSession', back_populates='candidate', init=False)
registration_site : Mapped['db_site.DbSite'] \
= relationship('DbSite')
= relationship('DbSite', init=False)
registration_project : Mapped['db_project.DbProject'] \
= relationship('DbProject')
= relationship('DbProject', init=False)
4 changes: 2 additions & 2 deletions python/lib/db/model/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
class DbConfig(Base):
__tablename__ = 'Config'

id : Mapped[int] = mapped_column('ID', primary_key=True)
id : Mapped[int] = mapped_column('ID', primary_key=True, autoincrement=True, init=False)
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')
setting : Mapped['db_config_setting.DbConfigSetting'] = relationship('DbConfigSetting', init=False)
16 changes: 8 additions & 8 deletions python/lib/db/model/config_setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
class DbConfigSetting(Base):
__tablename__ = 'ConfigSettings'

id : Mapped[int] = mapped_column('ID', primary_key=True)
id : Mapped[int] = mapped_column('ID', primary_key=True, autoincrement=True, init=False)
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')
description : Mapped[Optional[str]] = mapped_column('Description', default=None)
visible : Mapped[Optional[bool]] = mapped_column('Visible', default=False)
allow_multiple : Mapped[Optional[bool]] = mapped_column('AllowMultiple', default=False)
data_type : Mapped[Optional[str]] = mapped_column('DataType', default=None)
parent_id : Mapped[Optional[int]] = mapped_column('Parent', default=None)
label : Mapped[Optional[str]] = mapped_column('Label', default=None)
order_number : Mapped[Optional[int]] = mapped_column('OrderNumber', default=None)
70 changes: 36 additions & 34 deletions python/lib/db/model/dicom_archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,46 @@
class DbDicomArchive(Base):
__tablename__ = 'tarchive'

id : Mapped[int] = mapped_column('TarchiveID', primary_key=True)
study_uid : Mapped[str] = mapped_column('DicomArchiveID')
patient_id : Mapped[str] = mapped_column('PatientID')
patient_name : Mapped[str] = mapped_column('PatientName')
patient_birthdate : Mapped[Optional[date]] = mapped_column('PatientDoB')
patient_sex : Mapped[Optional[str]] = mapped_column('PatientSex')
neuro_db_center_name : Mapped[Optional[str]] = mapped_column('neurodbCenterName')
center_name : Mapped[str] = mapped_column('CenterName')
last_update : Mapped[Optional[datetime]] = mapped_column('LastUpdate')
date_acquired : Mapped[Optional[date]] = mapped_column('DateAcquired')
date_first_archived : Mapped[Optional[datetime]] = mapped_column('DateFirstArchived')
date_last_archived : Mapped[Optional[datetime]] = mapped_column('DateLastArchived')
acquisition_count : Mapped[int] = mapped_column('AcquisitionCount')
dicom_file_count : Mapped[int] = mapped_column('DicomFileCount')
non_dicom_file_count : Mapped[int] = mapped_column('NonDicomFileCount')
md5_sum_dicom_only : Mapped[Optional[str]] = mapped_column('md5sumDicomOnly')
md5_sum_archive : Mapped[Optional[str]] = mapped_column('md5sumArchive')
creating_user : Mapped[str] = mapped_column('CreatingUser')
sum_type_version : Mapped[int] = mapped_column('sumTypeVersion')
tar_type_version : Mapped[Optional[int]] = mapped_column('tarTypeVersion')
source_location : Mapped[str] = mapped_column('SourceLocation')
archive_location : Mapped[Optional[str]] = mapped_column('ArchiveLocation')
scanner_manufacturer : Mapped[str] = mapped_column('ScannerManufacturer')
scanner_model : Mapped[str] = mapped_column('ScannerModel')
scanner_serial_number : Mapped[str] = mapped_column('ScannerSerialNumber')
scanner_software_version : Mapped[str] = mapped_column('ScannerSoftwareVersion')
session_id : Mapped[Optional[int]] = mapped_column('SessionID', ForeignKey('session.ID'))
upload_attempt : Mapped[int] = mapped_column('uploadAttempt')
create_info : Mapped[Optional[str]] = mapped_column('CreateInfo')
acquisition_metadata : Mapped[str] = mapped_column('AcquisitionMetadata')
date_sent : Mapped[Optional[datetime]] = mapped_column('DateSent')
pending_transfer : Mapped[bool] = mapped_column('PendingTransfer')
id : Mapped[int] = mapped_column('TarchiveID',
primary_key=True, autoincrement=True, init=False)
study_uid : Mapped[str] = mapped_column('DicomArchiveID', default='')
patient_id : Mapped[str] = mapped_column('PatientID', default='')
patient_name : Mapped[str] = mapped_column('PatientName', default='')
patient_birthdate : Mapped[Optional[date]] = mapped_column('PatientDoB', default=None)
patient_sex : Mapped[Optional[str]] = mapped_column('PatientSex', default=None)
neuro_db_center_name : Mapped[Optional[str]] = mapped_column('neurodbCenterName', default=None)
center_name : Mapped[str] = mapped_column('CenterName', default='')
last_update : Mapped[Optional[datetime]] = mapped_column('LastUpdate', default=None)
date_acquired : Mapped[Optional[date]] = mapped_column('DateAcquired', default=None)
date_first_archived : Mapped[Optional[datetime]] = mapped_column('DateFirstArchived', default=None)
date_last_archived : Mapped[Optional[datetime]] = mapped_column('DateLastArchived', default=None)
acquisition_count : Mapped[int] = mapped_column('AcquisitionCount', default=0)
dicom_file_count : Mapped[int] = mapped_column('DicomFileCount', default=0)
non_dicom_file_count : Mapped[int] = mapped_column('NonDicomFileCount', default=0)
md5_sum_dicom_only : Mapped[Optional[str]] = mapped_column('md5sumDicomOnly', default=None)
md5_sum_archive : Mapped[Optional[str]] = mapped_column('md5sumArchive', default=None)
creating_user : Mapped[str] = mapped_column('CreatingUser', default='')
sum_type_version : Mapped[int] = mapped_column('sumTypeVersion', default=0)
tar_type_version : Mapped[Optional[int]] = mapped_column('tarTypeVersion', default=None)
source_location : Mapped[str] = mapped_column('SourceLocation', default='')
archive_location : Mapped[Optional[str]] = mapped_column('ArchiveLocation', default=None)
scanner_manufacturer : Mapped[str] = mapped_column('ScannerManufacturer', default='')
scanner_model : Mapped[str] = mapped_column('ScannerModel', default='')
scanner_serial_number : Mapped[str] = mapped_column('ScannerSerialNumber', default='')
scanner_software_version : Mapped[str] = mapped_column('ScannerSoftwareVersion', default='')
session_id : Mapped[Optional[int]] = mapped_column('SessionID',
ForeignKey('session.ID'), default=None)
upload_attempt : Mapped[int] = mapped_column('uploadAttempt', default=0)
date_sent : Mapped[Optional[datetime]] = mapped_column('DateSent', default=None)
pending_transfer : Mapped[bool] = mapped_column('PendingTransfer', default=False)

series : Mapped[list['db_dicom_archive_series.DbDicomArchiveSeries']] \
= relationship('DbDicomArchiveSeries', back_populates='archive')
= relationship('DbDicomArchiveSeries', back_populates='archive', init=False)
files : Mapped[list['db_dicom_archive_file.DbDicomArchiveFile']] \
= relationship('DbDicomArchiveFile', back_populates='archive')
= relationship('DbDicomArchiveFile', back_populates='archive', init=False)
upload : Mapped[Optional['db_mri_upload.DbMriUpload']] \
= relationship('DbMriUpload', back_populates='dicom_archive')
= relationship('DbMriUpload', back_populates='dicom_archive', init=False)
session : Mapped[Optional['db_session.DbSession']] \
= relationship('DbSession')
= relationship('DbSession', init=False)
19 changes: 10 additions & 9 deletions python/lib/db/model/dicom_archive_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@
class DbDicomArchiveFile(Base):
__tablename__ = 'tarchive_files'

id : Mapped[int] = mapped_column('TarchiveFileID', primary_key=True)
id : Mapped[int] = mapped_column('TarchiveFileID',
primary_key=True, autoincrement=True, init=False)
archive_id : Mapped[int] = mapped_column('TarchiveID', ForeignKey('tarchive.TarchiveID'))
series_id : Mapped[Optional[int]] \
= mapped_column('TarchiveSeriesID', ForeignKey('tarchive_series.TarchiveSeriesID'))
series_number : Mapped[Optional[int]] = mapped_column('SeriesNumber')
series_description : Mapped[Optional[str]] = mapped_column('SeriesDescription')
file_number : Mapped[Optional[int]] = mapped_column('FileNumber')
echo_number : Mapped[Optional[int]] = mapped_column('EchoNumber')
md5_sum : Mapped[str] = mapped_column('Md5Sum')
file_name : Mapped[str] = mapped_column('FileName')
series_id : Mapped[Optional[int]] \
= mapped_column('TarchiveSeriesID', ForeignKey('tarchive_series.TarchiveSeriesID'), default=None)
series_number : Mapped[Optional[int]] = mapped_column('SeriesNumber', default=None)
series_description : Mapped[Optional[str]] = mapped_column('SeriesDescription', default=None)
file_number : Mapped[Optional[int]] = mapped_column('FileNumber', default=None)
echo_number : Mapped[Optional[int]] = mapped_column('EchoNumber', default=None)

archive : Mapped['db_dicom_archive.DbDicomArchive'] \
= relationship('DbDicomArchive', back_populates='files')
= relationship('DbDicomArchive', back_populates='files', init=False)
series : Mapped[Optional['db_dicom_archive_series.DbDicomArchiveSeries']] \
= relationship('DbDicomArchiveSeries', back_populates='files')
= relationship('DbDicomArchiveSeries', back_populates='files', init=False)
Loading
Loading