From 5f45df0477597160446ca4dee8960a401b20927e Mon Sep 17 00:00:00 2001 From: Maxime Mulder Date: Sat, 5 Oct 2024 20:03:29 -0400 Subject: [PATCH 1/5] orm sync integration test --- .github/workflows/integration.yml | 2 +- python/lib/db/model/candidate.py | 4 +- python/lib/db/model/dicom_archive.py | 4 +- python/lib/db/model/session.py | 12 +-- python/lib/db/model/visit_window.py | 2 +- python/tests/integration/test_orm_sql_sync.py | 83 +++++++++++++++++++ python/tests/integration/test_poc.py | 9 -- python/tests/unit/db/query/test_candidate.py | 5 +- .../tests/unit/db/query/test_dicom_archive.py | 4 +- python/tests/util/database.py | 4 + test/docker-compose.yml | 6 ++ 11 files changed, 110 insertions(+), 25 deletions(-) create mode 100644 python/tests/integration/test_orm_sql_sync.py delete mode 100644 python/tests/integration/test_poc.py diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 6fbc6009d..52e7ffc15 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -18,7 +18,7 @@ jobs: - name: Clone the LORIS core repository run: git clone https://github.com/aces/Loris.git /tmp/Loris - - name: Import database files + - name: Import database files run: | mkdir -p ./test/database mkdir -p ./test/database/SQL diff --git a/python/lib/db/model/candidate.py b/python/lib/db/model/candidate.py index b88decd71..456be544b 100644 --- a/python/lib/db/model/candidate.py +++ b/python/lib/db/model/candidate.py @@ -1,4 +1,4 @@ -from datetime import date +from datetime import date, datetime from typing import Optional from sqlalchemy import ForeignKey @@ -35,7 +35,7 @@ class DbCandidate(Base): 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[int] = mapped_column('Testdate') + 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') diff --git a/python/lib/db/model/dicom_archive.py b/python/lib/db/model/dicom_archive.py index 8283859cf..97623cd39 100644 --- a/python/lib/db/model/dicom_archive.py +++ b/python/lib/db/model/dicom_archive.py @@ -22,7 +22,7 @@ class DbDicomArchive(Base): 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[date]] = mapped_column('LastUpdate') + 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') @@ -45,7 +45,7 @@ class DbDicomArchive(Base): 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[int] = mapped_column('PendingTransfer') + pending_transfer : Mapped[bool] = mapped_column('PendingTransfer') series : Mapped[list['db_dicom_archive_series.DbDicomArchiveSeries']] \ = relationship('DbDicomArchiveSeries', back_populates='archive') diff --git a/python/lib/db/model/session.py b/python/lib/db/model/session.py index eddb932fc..09606e309 100644 --- a/python/lib/db/model/session.py +++ b/python/lib/db/model/session.py @@ -20,12 +20,12 @@ class DbSession(Base): project_id : Mapped[int] = mapped_column('ProjectID', ForeignKey('Project.ProjectID')) visit_number : Mapped[Optional[int]] = mapped_column('VisitNo') visit_label : Mapped[str] = mapped_column('Visit_label') - cohort_id : Mapped[int] = mapped_column('CohortID') + cohort_id : Mapped[Optional[int]] = mapped_column('CohortID') submitted : Mapped[bool] = mapped_column('Submitted', YNBool) current_stage : Mapped[str] = mapped_column('Current_stage') date_stage_change : Mapped[Optional[date]] = mapped_column('Date_stage_change') screening : Mapped[Optional[str]] = mapped_column('Screening') - date_screening : Mapped[date] = mapped_column('Date_screening') + date_screening : Mapped[Optional[date]] = mapped_column('Date_screening') visit : Mapped[Optional[str]] = mapped_column('Visit') date_visit : Mapped[Optional[date]] = mapped_column('Date_visit') date_status_change : Mapped[Optional[date]] = mapped_column('Date_status_change') @@ -36,17 +36,17 @@ class DbSession(Base): registered_by : Mapped[Optional[str]] = mapped_column('RegisteredBy') user_id : Mapped[str] = mapped_column('UserID') date_registered : Mapped[Optional[date]] = mapped_column('Date_registered') - test_date : Mapped[int] = mapped_column('Testdate') + test_date : Mapped[datetime] = mapped_column('Testdate') hardcopy_request : Mapped[str] = mapped_column('Hardcopy_request') - bvl_qc_status : Mapped[Optional[str]] = mapped_column('BVLQCStaus') + bvl_qc_status : Mapped[Optional[str]] = mapped_column('BVLQCStatus') bvl_qc_type : Mapped[Optional[str]] = mapped_column('BVLQCType') bvl_qc_exclusion : Mapped[Optional[str]] = mapped_column('BVLQCExclusion') qcd : Mapped[Optional[str]] = mapped_column('QCd') scan_done : Mapped[Optional[bool]] = mapped_column('Scan_done', YNBool) mri_qc_status : Mapped[str] = mapped_column('MRIQCStatus') mri_qc_pending : Mapped[bool] = mapped_column('MRIQCPending', YNBool) - mri_qc_first_change_time : Mapped[Optional[datetime]] = mapped_column('MRIQCFirstChange') - mri_qc_last_change_time : Mapped[Optional[datetime]] = mapped_column('MRIQCLastChange') + mri_qc_first_change_time : Mapped[Optional[datetime]] = mapped_column('MRIQCFirstChangeTime') + mri_qc_last_change_time : Mapped[Optional[datetime]] = mapped_column('MRIQCLastChangeTime') mri_caveat : Mapped[str] = mapped_column('MRICaveat') language_id : Mapped[Optional[int]] = mapped_column('languageID') diff --git a/python/lib/db/model/visit_window.py b/python/lib/db/model/visit_window.py index 14016b666..e185a56a5 100644 --- a/python/lib/db/model/visit_window.py +++ b/python/lib/db/model/visit_window.py @@ -9,7 +9,7 @@ class DbVisitWindow(Base): __tablename__ = 'Visit_Windows' id : Mapped[int] = mapped_column('ID', primary_key=True) - visit_label : Mapped[str] = mapped_column('Visit_label') + visit_label : Mapped[Optional[str]] = mapped_column('Visit_label') window_min_days : Mapped[Optional[int]] = mapped_column('WindowMinDays') window_max_days : Mapped[Optional[int]] = mapped_column('WindowMaxDays') optimum_min_days : Mapped[Optional[int]] = mapped_column('OptimumMinDays') diff --git a/python/tests/integration/test_orm_sql_sync.py b/python/tests/integration/test_orm_sql_sync.py new file mode 100644 index 000000000..9a65b9b5c --- /dev/null +++ b/python/tests/integration/test_orm_sql_sync.py @@ -0,0 +1,83 @@ +import importlib +from pathlib import Path +from time import sleep +from typing import Any + +from sqlalchemy import Engine, MetaData +from sqlalchemy.dialects.mysql.types import DOUBLE, TINYINT +from sqlalchemy.exc import InterfaceError +from sqlalchemy.types import TypeDecorator, TypeEngine + +from lib.db.base import Base +from tests.util.database import get_integration_database_engine + + +# TODO: Implement a good health check for integration tests and remove this function. +def reflect(engine: Engine, sql_metadata: MetaData): + for counter in range(0, 20): + try: + sql_metadata.reflect(engine) + return + except InterfaceError: + print(f'Failed connection (tentative {counter})') + sleep(10) + + exit(-1) + + +def test_orm_sql_sync(): + """ + Test that the SQLAlchemy ORM definitions are in sync with the existing SQL database. + """ + + # Load all the ORM table definitions in the SQLAlchemy schema + for file in Path('python/lib/db/model').glob('*.py'): + importlib.import_module(f'lib.db.model.{file.name[:-3]}') + + orm_metadata = Base.metadata + + engine = get_integration_database_engine() + sql_metadata = MetaData() + reflect(engine, sql_metadata) + + for orm_table in orm_metadata.sorted_tables: + print(f'test table: {orm_table.name}') + + # Check that each ORM table has a corresponding SQL table + sql_table = sql_metadata.tables.get(orm_table.name) + assert sql_table is not None + + # Check that the ORM and SQL tables have the same columns + orm_column_names = orm_table.columns.keys().sort() + sql_column_names = sql_table.columns.keys().sort() + assert orm_column_names == sql_column_names + + for orm_column in orm_table.columns: + print(f' test column: {orm_column.name}') + + # Check that the types of the ORM and SQL column are equal + # The type comparison is not exact, minor differences are ignored + sql_column = sql_table.columns[orm_column.name] + orm_column_python_type = get_orm_python_type(orm_column.type) + sql_column_python_type = get_sql_python_type(sql_column.type) + assert orm_column_python_type == sql_column_python_type + assert orm_column.nullable == sql_column.nullable + + print() + + +def get_orm_python_type(orm_type: TypeEngine[Any]): + if isinstance(orm_type, TypeDecorator): + return orm_type.impl.python_type + + return orm_type.python_type + + +def get_sql_python_type(sql_type: TypeEngine[Any]): + if isinstance(sql_type, TINYINT) and sql_type.display_width == 1: # type: ignore + return bool + + if isinstance(sql_type, DOUBLE): + return float + + return sql_type.python_type diff --git a/python/tests/integration/test_poc.py b/python/tests/integration/test_poc.py deleted file mode 100644 index 2145cbfaf..000000000 --- a/python/tests/integration/test_poc.py +++ /dev/null @@ -1,9 +0,0 @@ -# Proof-of-concept integration tests. TODO: Replace with real tests - - -def test_addition(): - assert 1 + 1 == 2 - - -def test_subtraction(): - assert 2 - 1 == 1 diff --git a/python/tests/unit/db/query/test_candidate.py b/python/tests/unit/db/query/test_candidate.py index 94c5decc9..fdf4ebf25 100644 --- a/python/tests/unit/db/query/test_candidate.py +++ b/python/tests/unit/db/query/test_candidate.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from datetime import datetime import pytest from sqlalchemy.orm import Session as Database @@ -26,7 +27,7 @@ def setup(): registration_project_id = 1, active = True, user_id = 'admin', - test_date = 0, + test_date = datetime.now(), entity_type = 'human', ) @@ -37,7 +38,7 @@ def setup(): registration_project_id = 1, active = True, user_id = 'admin', - test_date = 0, + test_date = datetime.now(), entity_type = 'human', ) diff --git a/python/tests/unit/db/query/test_dicom_archive.py b/python/tests/unit/db/query/test_dicom_archive.py index d25555a38..cac37f7e6 100644 --- a/python/tests/unit/db/query/test_dicom_archive.py +++ b/python/tests/unit/db/query/test_dicom_archive.py @@ -44,7 +44,7 @@ def setup(): scanner_software_version = 'Test scanner software version', upload_attempt = 0, acquisition_metadata = '', - pending_transfer = 0, + pending_transfer = False, ) dicom_archive_2 = DbDicomArchive( @@ -65,7 +65,7 @@ def setup(): scanner_software_version = 'Test scanner software version', upload_attempt = 0, acquisition_metadata = '', - pending_transfer = 0, + pending_transfer = False, ) db.add(dicom_archive_1) diff --git a/python/tests/util/database.py b/python/tests/util/database.py index a2f393e31..a544613a5 100644 --- a/python/tests/util/database.py +++ b/python/tests/util/database.py @@ -12,3 +12,7 @@ def create_test_database(): engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) return Session(engine) + + +def get_integration_database_engine(): + return create_engine('mariadb+mysqlconnector://SQLTestUser:TestPassword@db:3306/LorisTest') diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 091f4e51d..3b18615ea 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -8,6 +8,12 @@ services: MYSQL_RANDOM_ROOT_PASSWORD: yes ports: - "3306:3306" + healthcheck: + test: ["CMD", "mysql", "-u", "SQLTestUser", "-pTestPassword", "LorisTest", "-e", "SELECT 1"] + interval: 10s + timeout: 10s + retries: 20 + start_period: 30s mri: image: loris-mri volumes: From 638406d2bd3b77d3d4558b524ddc2759325f01c5 Mon Sep 17 00:00:00 2001 From: Maxime Mulder Date: Mon, 7 Oct 2024 16:25:43 -0400 Subject: [PATCH 2/5] add docker health check --- .github/workflows/integration.yml | 2 -- python/tests/integration/test_orm_sql_sync.py | 19 ++------------ python/tests/util/database.py | 2 +- test/db.Dockerfile | 25 +++++++++++++------ test/docker-compose.yml | 17 +++++-------- test/test.Dockerfile | 13 ++++++++++ 6 files changed, 39 insertions(+), 39 deletions(-) create mode 100644 test/test.Dockerfile diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 52e7ffc15..be18d0770 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -39,8 +39,6 @@ jobs: with: context: . file: ./test/db.Dockerfile - build-args: | - BASE_DIR=/app/ tags: loris-db load: true cache-from: type=gha,scope=loris-db diff --git a/python/tests/integration/test_orm_sql_sync.py b/python/tests/integration/test_orm_sql_sync.py index 9a65b9b5c..dbcbac036 100644 --- a/python/tests/integration/test_orm_sql_sync.py +++ b/python/tests/integration/test_orm_sql_sync.py @@ -1,30 +1,15 @@ import importlib from pathlib import Path -from time import sleep from typing import Any -from sqlalchemy import Engine, MetaData +from sqlalchemy import MetaData from sqlalchemy.dialects.mysql.types import DOUBLE, TINYINT -from sqlalchemy.exc import InterfaceError from sqlalchemy.types import TypeDecorator, TypeEngine from lib.db.base import Base from tests.util.database import get_integration_database_engine -# TODO: Implement a good health check for integration tests and remove this function. -def reflect(engine: Engine, sql_metadata: MetaData): - for counter in range(0, 20): - try: - sql_metadata.reflect(engine) - return - except InterfaceError: - print(f'Failed connection (tentative {counter})') - sleep(10) - - exit(-1) - - def test_orm_sql_sync(): """ Test that the SQLAlchemy ORM definitions are in sync with the existing SQL database. @@ -38,7 +23,7 @@ def test_orm_sql_sync(): engine = get_integration_database_engine() sql_metadata = MetaData() - reflect(engine, sql_metadata) + sql_metadata.reflect(engine) for orm_table in orm_metadata.sorted_tables: print(f'test table: {orm_table.name}') diff --git a/python/tests/util/database.py b/python/tests/util/database.py index a544613a5..ce536546c 100644 --- a/python/tests/util/database.py +++ b/python/tests/util/database.py @@ -15,4 +15,4 @@ def create_test_database(): def get_integration_database_engine(): - return create_engine('mariadb+mysqlconnector://SQLTestUser:TestPassword@db:3306/LorisTest') + return create_engine('mysql+mysqldb://SQLTestUser:TestPassword@db:3306/LorisTest') diff --git a/test/db.Dockerfile b/test/db.Dockerfile index 1cfed4572..35e567df9 100644 --- a/test/db.Dockerfile +++ b/test/db.Dockerfile @@ -1,7 +1,5 @@ FROM mariadb:latest -ARG BASE_DIR - COPY test/database/SQL/0000-00-00-schema.sql /0000-00-00-schema.sql COPY test/database/SQL/0000-00-01-Modules.sql /0000-00-01-Modules.sql COPY test/database/SQL/0000-00-02-Permission.sql /0000-00-02-Permission.sql @@ -16,7 +14,7 @@ COPY test/database/raisinbread/instruments/instrument_sql/mri_parameter_form.sql COPY test/database/raisinbread/instruments/instrument_sql/radiology_review.sql /radiology_review.sql COPY test/database/test/test_instrument/testtest.sql /test_instrument.sql -RUN echo "Use LorisTest;" | cat - \ +RUN echo "CREATE DATABASE LorisTest; USE LorisTest;" | cat - \ 0000-00-00-schema.sql \ 0000-00-01-Modules.sql \ 0000-00-02-Permission.sql \ @@ -31,11 +29,22 @@ RUN echo "Use LorisTest;" | cat - \ test_instrument.sql \ RB_files/*.sql > /docker-entrypoint-initdb.d/0000-compiled.sql -RUN echo "Use LorisTest;" >> /docker-entrypoint-initdb.d/0001-paths.sql -RUN echo "UPDATE Config SET Value='${BASE_DIR}/' WHERE ConfigID=(SELECT ID FROM ConfigSettings WHERE Name='base');" >> /docker-entrypoint-initdb.d/0001-paths.sql -RUN echo "GRANT UPDATE,INSERT,SELECT,DELETE,DROP,CREATE TEMPORARY TABLES ON LorisTest.* TO 'SQLTestUser'@'%' IDENTIFIED BY 'TestPassword' WITH GRANT OPTION;" >> /docker-entrypoint-initdb.d/0004-sql-user.sql +RUN echo "CREATE USER 'SQLTestUser'@'%' IDENTIFIED BY 'TestPassword';" >> /docker-entrypoint-initdb.d/0000-compiled.sql +RUN echo "CREATE USER 'SQLTestUser'@'localhost' IDENTIFIED BY 'TestPassword';" >> /docker-entrypoint-initdb.d/0000-compiled.sql +RUN echo "GRANT SELECT,INSERT,UPDATE,DELETE,DROP,CREATE TEMPORARY TABLES ON LorisTest.* TO 'SQLTestUser'@'%';" >> /docker-entrypoint-initdb.d/0000-compiled.sql # Run the LORIS-MRI database installation script COPY install/install_database.sql /tmp/install_database.sql -RUN echo "SET @email := 'root@localhost'; SET @project := 'loris'; SET @minc_dir = '/opt/minc/1.9.18';" >> 0001-paths.sql -RUN cat /tmp/install_database.sql >> /docker-entrypoint-initdb.d/0001-paths.sql +RUN echo "SET @email := 'root@localhost'; SET @project := 'loris'; SET @minc_dir = '/opt/minc/1.9.18';" >> 0000-compiled.sql +RUN cat /tmp/install_database.sql >> /docker-entrypoint-initdb.d/0000-compiled.sql + +# By default, MariaDB runs the scripts in /docker-entrypoint-initdb.d/ at the time of the first +# startup to initialize the database. However, we want to populate the database at build time so +# that the database is part of the final image (and can be cached for CI). +RUN mariadb-install-db +RUN docker-entrypoint.sh mariadbd & \ + sleep 30 && \ + mariadb < /docker-entrypoint-initdb.d/0000-compiled.sql && \ + killall mariadbd + +CMD ["mariadbd", "--user=root"] diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 3b18615ea..a990412d4 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -3,21 +3,16 @@ services: image: loris-db volumes: - ./test/mysql-config:/etc/mysql/conf.d - environment: - MYSQL_DATABASE: LorisTest - MYSQL_RANDOM_ROOT_PASSWORD: yes - ports: - - "3306:3306" healthcheck: - test: ["CMD", "mysql", "-u", "SQLTestUser", "-pTestPassword", "LorisTest", "-e", "SELECT 1"] + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + start_period: 10s interval: 10s - timeout: 10s - retries: 20 - start_period: 30s + timeout: 5s + retries: 5 mri: image: loris-mri volumes: - ../:/opt/loris/bin/mri depends_on: - - db - command: pytest + db: + condition: service_healthy diff --git a/test/test.Dockerfile b/test/test.Dockerfile new file mode 100644 index 000000000..aef076e13 --- /dev/null +++ b/test/test.Dockerfile @@ -0,0 +1,13 @@ +FROM mariadb:latest + +RUN echo "CREATE DATABASE testtest;" >> /docker-entrypoint-initdb.d/test-init.sql + +# By default, MariaDB runs any scripts in /docker-entrypoint-initdb.d/ at the time of the first +# startup to initialize the database. +# We run those scripts at build time so that the database is populated and part of the final image. +RUN mariadb-install-db + +RUN docker-entrypoint.sh mariadbd & \ + sleep 30 && \ + mariadb < /docker-entrypoint-initdb.d/test-init.sql && \ + killall mariadbd From 340dc59c2faee8d6fb7d5e32f0d868af472b16f9 Mon Sep 17 00:00:00 2001 From: Maxime Mulder Date: Mon, 14 Oct 2024 19:40:17 -0400 Subject: [PATCH 3/5] use integration config file --- python/tests/util/database.py | 18 ++++++++++++++++-- test/docker-compose.yml | 2 -- test/test.Dockerfile | 13 ------------- 3 files changed, 16 insertions(+), 17 deletions(-) delete mode 100644 test/test.Dockerfile diff --git a/python/tests/util/database.py b/python/tests/util/database.py index ce536546c..67d74fc5e 100644 --- a/python/tests/util/database.py +++ b/python/tests/util/database.py @@ -1,7 +1,12 @@ -from sqlalchemy import create_engine +import os +import sys +from typing import cast + +from sqlalchemy import Engine, create_engine from sqlalchemy.orm import Session from lib.db.base import Base +from lib.db.connect import connect_to_database def create_test_database(): @@ -15,4 +20,13 @@ def create_test_database(): def get_integration_database_engine(): - return create_engine('mysql+mysqldb://SQLTestUser:TestPassword@db:3306/LorisTest') + """ + Get an SQLAlchemy engine for the integration testing database using the configuration from the + Python configuration file. + """ + + config_file = os.path.join(os.environ['LORIS_CONFIG'], '.loris_mri', 'database_config.py') + sys.path.append(os.path.dirname(config_file)) + config = __import__(os.path.basename(config_file[:-3])) + session = connect_to_database(config.mysql) + return cast(Engine, session.get_bind()) diff --git a/test/docker-compose.yml b/test/docker-compose.yml index a990412d4..1adb56d4c 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -11,8 +11,6 @@ services: retries: 5 mri: image: loris-mri - volumes: - - ../:/opt/loris/bin/mri depends_on: db: condition: service_healthy diff --git a/test/test.Dockerfile b/test/test.Dockerfile deleted file mode 100644 index aef076e13..000000000 --- a/test/test.Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM mariadb:latest - -RUN echo "CREATE DATABASE testtest;" >> /docker-entrypoint-initdb.d/test-init.sql - -# By default, MariaDB runs any scripts in /docker-entrypoint-initdb.d/ at the time of the first -# startup to initialize the database. -# We run those scripts at build time so that the database is populated and part of the final image. -RUN mariadb-install-db - -RUN docker-entrypoint.sh mariadbd & \ - sleep 30 && \ - mariadb < /docker-entrypoint-initdb.d/test-init.sql && \ - killall mariadbd From d1a70e676ac07c5e00f3244ace54ffe5cd46307e Mon Sep 17 00:00:00 2001 From: Maxime Mulder Date: Thu, 17 Oct 2024 11:36:51 -0400 Subject: [PATCH 4/5] test error --- python/lib/db/model/candidate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/lib/db/model/candidate.py b/python/lib/db/model/candidate.py index 456be544b..67ff2bce6 100644 --- a/python/lib/db/model/candidate.py +++ b/python/lib/db/model/candidate.py @@ -36,7 +36,7 @@ class DbCandidate(Base): 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') + entity_type : Mapped[int] = mapped_column('Entity_type') proband_sex : Mapped[Optional[str]] = mapped_column('ProbandSex') proband_sate_of_birth : Mapped[Optional[date]] = mapped_column('ProbandDoB') From 4cf3235c19f0e0c53cc7236c505fd71d187467b2 Mon Sep 17 00:00:00 2001 From: Maxime Mulder Date: Thu, 17 Oct 2024 11:37:45 -0400 Subject: [PATCH 5/5] Revert "test error" This reverts commit d1a70e676ac07c5e00f3244ace54ffe5cd46307e. --- python/lib/db/model/candidate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/lib/db/model/candidate.py b/python/lib/db/model/candidate.py index 67ff2bce6..456be544b 100644 --- a/python/lib/db/model/candidate.py +++ b/python/lib/db/model/candidate.py @@ -36,7 +36,7 @@ class DbCandidate(Base): 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[int] = mapped_column('Entity_type') + 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')