From d017c2608fddfe81801f3a0662b25e655140c97b Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Tue, 20 Aug 2024 15:08:48 -0400 Subject: [PATCH] Add BaseTableBuilder and CountsBuilder to the public API --- cumulus_library/__init__.py | 4 +++- .../studies/core/builder_condition.py | 6 +++--- .../studies/core/builder_documentreference.py | 6 +++--- .../studies/core/builder_encounter.py | 6 +++--- .../studies/core/builder_medicationrequest.py | 6 +++--- .../studies/core/builder_observation.py | 6 +++--- cumulus_library/studies/core/builder_patient.py | 8 ++++---- .../studies/core/builder_prereq_tables.py | 4 ++-- cumulus_library/studies/core/count_core.py | 6 +++--- .../studies/discovery/code_detection.py | 7 ++++--- .../studies/vocab/vocab_icd_builder.py | 6 +++--- .../test_data/study_dedicated_schema/module1.py | 4 ++-- .../test_data/study_dedicated_schema/module2.py | 4 ++-- .../study_python_counts_valid/module1.py | 4 ++-- .../study_python_counts_valid/module2.py | 4 ++-- .../study_python_local_template/module1.py | 4 ++-- .../study_python_no_subclass/module1.py | 4 ++-- tests/test_data/study_python_s3/module1.py | 4 ++-- tests/test_data/study_python_s3/module2.py | 4 ++-- tests/test_data/study_python_valid/module1.py | 4 ++-- tests/test_data/study_python_valid/module2.py | 4 ++-- tests/test_discovery.py | 17 +++++++++++++++++ 22 files changed, 71 insertions(+), 51 deletions(-) diff --git a/cumulus_library/__init__.py b/cumulus_library/__init__.py index 3873fff8..6fdf222f 100644 --- a/cumulus_library/__init__.py +++ b/cumulus_library/__init__.py @@ -1,7 +1,9 @@ """Package metadata""" +from .base_table_builder import BaseTableBuilder from .base_utils import StudyConfig +from .statistics.counts import CountsBuilder from .study_manifest import StudyManifest -__all__ = ["StudyConfig", "StudyManifest"] +__all__ = ["BaseTableBuilder", "CountsBuilder", "StudyConfig", "StudyManifest"] __version__ = "3.0.0" diff --git a/cumulus_library/studies/core/builder_condition.py b/cumulus_library/studies/core/builder_condition.py index b9954a72..d0e3d144 100644 --- a/cumulus_library/studies/core/builder_condition.py +++ b/cumulus_library/studies/core/builder_condition.py @@ -1,4 +1,4 @@ -from cumulus_library import base_table_builder, base_utils +import cumulus_library from cumulus_library.studies.core.core_templates import core_templates from cumulus_library.template_sql import base_templates, sql_utils @@ -12,7 +12,7 @@ } -class CoreConditionBuilder(base_table_builder.BaseTableBuilder): +class CoreConditionBuilder(cumulus_library.BaseTableBuilder): display_text = "Creating Condition tables..." def denormalize_codes(self): @@ -75,7 +75,7 @@ def denormalize_codes(self): def prepare_queries( self, *args, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, **kwargs, ): self.denormalize_codes() diff --git a/cumulus_library/studies/core/builder_documentreference.py b/cumulus_library/studies/core/builder_documentreference.py index c58221c0..225c01e2 100644 --- a/cumulus_library/studies/core/builder_documentreference.py +++ b/cumulus_library/studies/core/builder_documentreference.py @@ -1,4 +1,4 @@ -from cumulus_library import base_table_builder, base_utils +import cumulus_library from cumulus_library.studies.core.core_templates import core_templates from cumulus_library.template_sql import sql_utils @@ -14,13 +14,13 @@ } -class CoreDocumentreferenceBuilder(base_table_builder.BaseTableBuilder): +class CoreDocumentreferenceBuilder(cumulus_library.BaseTableBuilder): display_text = "Creating DocumentReference tables..." def prepare_queries( self, *args, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, **kwargs, ): self.queries = sql_utils.denormalize_complex_objects( diff --git a/cumulus_library/studies/core/builder_encounter.py b/cumulus_library/studies/core/builder_encounter.py index 1e7ab7dd..20a5b46a 100644 --- a/cumulus_library/studies/core/builder_encounter.py +++ b/cumulus_library/studies/core/builder_encounter.py @@ -1,6 +1,6 @@ from dataclasses import dataclass -from cumulus_library import base_table_builder, base_utils +import cumulus_library from cumulus_library.studies.core.core_templates import core_templates from cumulus_library.template_sql import sql_utils @@ -34,7 +34,7 @@ def __post_init__(self): self.target_table = f"core__encounter_dn_{self.column_hierarchy[-1][0]}" -class CoreEncounterBuilder(base_table_builder.BaseTableBuilder): +class CoreEncounterBuilder(cumulus_library.BaseTableBuilder): display_text = "Creating Encounter tables..." def denormalize_codes(self, database): @@ -108,7 +108,7 @@ def denormalize_codes(self, database): def prepare_queries( self, *args, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, **kwargs, ): self.denormalize_codes(config.db) diff --git a/cumulus_library/studies/core/builder_medicationrequest.py b/cumulus_library/studies/core/builder_medicationrequest.py index e68ee8c5..ee374301 100644 --- a/cumulus_library/studies/core/builder_medicationrequest.py +++ b/cumulus_library/studies/core/builder_medicationrequest.py @@ -1,6 +1,6 @@ """Module for generating core medicationrequest table""" -from cumulus_library import base_table_builder, base_utils +import cumulus_library from cumulus_library.studies.core.core_templates import core_templates from cumulus_library.template_sql import sql_utils @@ -19,13 +19,13 @@ } -class MedicationRequestBuilder(base_table_builder.BaseTableBuilder): +class MedicationRequestBuilder(cumulus_library.BaseTableBuilder): display_text = "Creating MedicationRequest table..." def prepare_queries( self, *args, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, **kwargs, ) -> None: """Constructs queries related to medication requests diff --git a/cumulus_library/studies/core/builder_observation.py b/cumulus_library/studies/core/builder_observation.py index d6b24515..50efc04a 100644 --- a/cumulus_library/studies/core/builder_observation.py +++ b/cumulus_library/studies/core/builder_observation.py @@ -2,7 +2,7 @@ from dataclasses import dataclass -from cumulus_library import base_table_builder, base_utils +import cumulus_library from cumulus_library.studies.core.core_templates import core_templates from cumulus_library.template_sql import sql_utils @@ -36,13 +36,13 @@ def __post_init__(self): self.target_table = f"core__observation_{table_suffix}" -class ObservationBuilder(base_table_builder.BaseTableBuilder): +class ObservationBuilder(cumulus_library.BaseTableBuilder): display_text = "Creating Observation tables..." def prepare_queries( self, *args, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, **kwargs, ): """constructs queries related to patient extensions of interest diff --git a/cumulus_library/studies/core/builder_patient.py b/cumulus_library/studies/core/builder_patient.py index aaddb913..793c5baa 100644 --- a/cumulus_library/studies/core/builder_patient.py +++ b/cumulus_library/studies/core/builder_patient.py @@ -1,7 +1,7 @@ """Module for extracting US core extensions from patient records""" -from cumulus_library import base_utils, databases -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library +from cumulus_library import databases from cumulus_library.studies.core.core_templates import core_templates from cumulus_library.template_sql import base_templates, sql_utils @@ -15,7 +15,7 @@ } -class PatientBuilder(BaseTableBuilder): +class PatientBuilder(cumulus_library.BaseTableBuilder): display_text = "Creating Patient tables..." @staticmethod @@ -57,7 +57,7 @@ def make_extension_query( def prepare_queries( self, *args, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, **kwargs, ): """constructs queries related to patient extensions of interest diff --git a/cumulus_library/studies/core/builder_prereq_tables.py b/cumulus_library/studies/core/builder_prereq_tables.py index e6df535c..00a1b85a 100644 --- a/cumulus_library/studies/core/builder_prereq_tables.py +++ b/cumulus_library/studies/core/builder_prereq_tables.py @@ -6,10 +6,10 @@ import sqlparse -from cumulus_library import base_table_builder +import cumulus_library -class CorePrereqTableBuilder(base_table_builder.BaseTableBuilder): +class CorePrereqTableBuilder(cumulus_library.BaseTableBuilder): display_text = "Creating core prerequisite tables..." def prepare_queries(self, *args, **kwargs): diff --git a/cumulus_library/studies/core/count_core.py b/cumulus_library/studies/core/count_core.py index bfed77a1..7471451f 100644 --- a/cumulus_library/studies/core/count_core.py +++ b/cumulus_library/studies/core/count_core.py @@ -1,9 +1,9 @@ from pathlib import Path -from cumulus_library.statistics import counts +import cumulus_library -class CoreCountsBuilder(counts.CountsBuilder): +class CoreCountsBuilder(cumulus_library.CountsBuilder): display_text = "Creating core counts..." def count_core_condition(self, duration: str = "month"): @@ -119,6 +119,6 @@ def prepare_queries(self, *args, **kwargs): ] -if __name__ == "__main__": +if __name__ == "__main__": # pragma: no cover builder = CoreCountsBuilder() builder.write_counts(f"{Path(__file__).resolve().parent}/count_core.sql") diff --git a/cumulus_library/studies/discovery/code_detection.py b/cumulus_library/studies/discovery/code_detection.py index 5a7f2217..fe427684 100644 --- a/cumulus_library/studies/discovery/code_detection.py +++ b/cumulus_library/studies/discovery/code_detection.py @@ -1,12 +1,13 @@ """Module for generating encounter codeableConcept table""" -from cumulus_library import base_table_builder, base_utils +import cumulus_library +from cumulus_library import base_utils from cumulus_library.studies.discovery import code_definitions from cumulus_library.studies.discovery.discovery_templates import discovery_templates from cumulus_library.template_sql import sql_utils -class CodeDetectionBuilder(base_table_builder.BaseTableBuilder): +class CodeDetectionBuilder(cumulus_library.BaseTableBuilder): display_text = "Selecting unique code systems..." def _check_coding_against_db(self, code_source, database): @@ -35,7 +36,7 @@ def _check_codes_in_fields(self, code_sources: list[dict], database) -> dict: def prepare_queries( self, *args, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, **kwargs, ): """Constructs queries related to condition codeableConcept diff --git a/cumulus_library/studies/vocab/vocab_icd_builder.py b/cumulus_library/studies/vocab/vocab_icd_builder.py index 115f16ec..e541521d 100644 --- a/cumulus_library/studies/vocab/vocab_icd_builder.py +++ b/cumulus_library/studies/vocab/vocab_icd_builder.py @@ -4,16 +4,16 @@ import pandas -from cumulus_library import base_table_builder, base_utils +import cumulus_library from cumulus_library.template_sql import base_templates -class VocabIcdRunner(base_table_builder.BaseTableBuilder): +class VocabIcdRunner(cumulus_library.BaseTableBuilder): display_text = "Creating ICD vocab..." def prepare_queries( self, - config: base_utils.StudyConfig, + config: cumulus_library.StudyConfig, *args, **kwargs, ): diff --git a/tests/test_data/study_dedicated_schema/module1.py b/tests/test_data/study_dedicated_schema/module1.py index 08d9d307..71aa0106 100644 --- a/tests/test_data/study_dedicated_schema/module1.py +++ b/tests/test_data/study_dedicated_schema/module1.py @@ -1,7 +1,7 @@ -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleOneRunner(BaseTableBuilder): +class ModuleOneRunner(cumulus_library.BaseTableBuilder): display_text = "module1" def prepare_queries(self, *args, **kwargs): diff --git a/tests/test_data/study_dedicated_schema/module2.py b/tests/test_data/study_dedicated_schema/module2.py index ab72183d..ce4a5eda 100644 --- a/tests/test_data/study_dedicated_schema/module2.py +++ b/tests/test_data/study_dedicated_schema/module2.py @@ -1,7 +1,7 @@ -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleTwoRunner(BaseTableBuilder): +class ModuleTwoRunner(cumulus_library.BaseTableBuilder): display_text = "module2" def prepare_queries(self, *args, **kwargs): diff --git a/tests/test_data/study_python_counts_valid/module1.py b/tests/test_data/study_python_counts_valid/module1.py index 0c0c2023..ecbaf6e1 100644 --- a/tests/test_data/study_python_counts_valid/module1.py +++ b/tests/test_data/study_python_counts_valid/module1.py @@ -1,7 +1,7 @@ -from cumulus_library.statistics.counts import CountsBuilder +import cumulus_library -class ModuleOneRunner(CountsBuilder): +class ModuleOneRunner(cumulus_library.CountsBuilder): display_text = "module1" def __init__(self): diff --git a/tests/test_data/study_python_counts_valid/module2.py b/tests/test_data/study_python_counts_valid/module2.py index 531d3f96..c6c7e80a 100644 --- a/tests/test_data/study_python_counts_valid/module2.py +++ b/tests/test_data/study_python_counts_valid/module2.py @@ -1,7 +1,7 @@ -from cumulus_library.statistics.counts import CountsBuilder +import cumulus_library -class ModuleTwoRunner(CountsBuilder): +class ModuleTwoRunner(cumulus_library.CountsBuilder): display_text = "module2" def __init__(self): diff --git a/tests/test_data/study_python_local_template/module1.py b/tests/test_data/study_python_local_template/module1.py index 2b1a28b6..1bad0b69 100644 --- a/tests/test_data/study_python_local_template/module1.py +++ b/tests/test_data/study_python_local_template/module1.py @@ -1,9 +1,9 @@ from study_python_local_template import local_template -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleOneRunner(BaseTableBuilder): +class ModuleOneRunner(cumulus_library.BaseTableBuilder): display_text = "module1" def prepare_queries(self, *args, **kwargs): diff --git a/tests/test_data/study_python_no_subclass/module1.py b/tests/test_data/study_python_no_subclass/module1.py index d9b680ec..ab7baefa 100644 --- a/tests/test_data/study_python_no_subclass/module1.py +++ b/tests/test_data/study_python_no_subclass/module1.py @@ -1,7 +1,7 @@ -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleOneRunner(BaseTableBuilder): +class ModuleOneRunner(cumulus_library.BaseTableBuilder): display_text = "Module 1" @classmethod diff --git a/tests/test_data/study_python_s3/module1.py b/tests/test_data/study_python_s3/module1.py index ae2b0598..b08f7f7f 100644 --- a/tests/test_data/study_python_s3/module1.py +++ b/tests/test_data/study_python_s3/module1.py @@ -1,7 +1,7 @@ -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleOneRunner(BaseTableBuilder): +class ModuleOneRunner(cumulus_library.BaseTableBuilder): display_text = "module1" def prepare_queries(self, *args, **kwargs): diff --git a/tests/test_data/study_python_s3/module2.py b/tests/test_data/study_python_s3/module2.py index 91bcd527..16284ca4 100644 --- a/tests/test_data/study_python_s3/module2.py +++ b/tests/test_data/study_python_s3/module2.py @@ -1,7 +1,7 @@ -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleTwoRunner(BaseTableBuilder): +class ModuleTwoRunner(cumulus_library.BaseTableBuilder): display_text = "module2" def prepare_queries(self, *args, **kwargs): diff --git a/tests/test_data/study_python_valid/module1.py b/tests/test_data/study_python_valid/module1.py index c09a1f2f..082751a3 100644 --- a/tests/test_data/study_python_valid/module1.py +++ b/tests/test_data/study_python_valid/module1.py @@ -1,7 +1,7 @@ -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleOneRunner(BaseTableBuilder): +class ModuleOneRunner(cumulus_library.BaseTableBuilder): display_text = "module1" def prepare_queries(self, *args, **kwargs): diff --git a/tests/test_data/study_python_valid/module2.py b/tests/test_data/study_python_valid/module2.py index b00a5cf5..ec91e9cb 100644 --- a/tests/test_data/study_python_valid/module2.py +++ b/tests/test_data/study_python_valid/module2.py @@ -1,7 +1,7 @@ -from cumulus_library.base_table_builder import BaseTableBuilder +import cumulus_library -class ModuleTwoRunner(BaseTableBuilder): +class ModuleTwoRunner(cumulus_library.BaseTableBuilder): display_text = "module2" def prepare_queries(self, *args, **kwargs): diff --git a/tests/test_discovery.py b/tests/test_discovery.py index 4bf9540d..29c58f94 100644 --- a/tests/test_discovery.py +++ b/tests/test_discovery.py @@ -2,6 +2,8 @@ import pathlib from unittest import mock +import pytest + from cumulus_library import cli, databases from cumulus_library.studies.discovery.discovery_templates import discovery_templates from tests import conftest @@ -144,3 +146,18 @@ def test_get_system_pairs(): ], ) assert query == expected + + +@mock.patch.dict(os.environ, clear=True) +@mock.patch("cumulus_library.studies.discovery.code_definitions.code_list", new=[{}]) +def test_bad_code_definition(tmp_path): + with pytest.raises(KeyError, match="Expected table_name and column_hierarchy keys"): + cli.main( + cli_args=conftest.duckdb_args( + [ + "build", + "--target=discovery", + ], + tmp_path, + ) + )