From 364a253d359136a0569312b98c4e445c3ca5bd2d Mon Sep 17 00:00:00 2001 From: quinnwai Date: Thu, 16 Oct 2025 10:58:18 -0700 Subject: [PATCH 1/7] get subj of subj (patient) in docref --- gen3_tracker/meta/dataframer.py | 24 +++++-- gen3_tracker/meta/entities.py | 1 + tests/unit/dataframer/test_dataframer.py | 89 ++++++++++++++---------- 3 files changed, 73 insertions(+), 41 deletions(-) diff --git a/gen3_tracker/meta/dataframer.py b/gen3_tracker/meta/dataframer.py index 17c6c49..81c4fac 100644 --- a/gen3_tracker/meta/dataframer.py +++ b/gen3_tracker/meta/dataframer.py @@ -495,7 +495,7 @@ def flattened_research_subjects(self) -> Generator[dict, None, None]: ).simplified # return with .subject (ie Patient) fields - patient = get_subject(self, research_subject) + _, patient = get_subject(self, research_subject) flat_research_subject.update(patient) # get condition code, eg enrollment diagnosis @@ -528,7 +528,7 @@ def flattened_medication_administrations(self) -> Generator[dict, None, None]: resource=medication_administration ).simplified - patient = get_subject(self, medication_administration) + _, patient = get_subject(self, medication_administration) flat_medication_administration.update(patient) yield flat_medication_administration @@ -561,7 +561,14 @@ def flattened_document_reference( flat_doc_ref = SimplifiedResource.build(resource=doc_ref).simplified # extract the corresponding .subject and append its fields - flat_doc_ref.update(get_subject(self, doc_ref)) + + raw_subject, simplified_subject = get_subject(self, doc_ref) + flat_doc_ref.update(simplified_subject) + + # extract the subject of the .subject and append its fields + # eg: a specimen is associated with a patients + _, simplified_subject_of_subject = get_subject(self, raw_subject) + flat_doc_ref.update(simplified_subject_of_subject) # populate observation data associated with the document reference document if doc_ref["id"] in observation_by_focus_id: @@ -606,7 +613,8 @@ def flattened_specimen(self, specimen: dict, observation_by_id: dict) -> dict: flat_specimen = SimplifiedResource.build(resource=specimen).simplified # extract its .subject and append its fields (including id) - flat_specimen.update(get_subject(self, specimen)) + _, simplified_subject = get_subject(self, specimen) + flat_specimen.update(simplified_subject) # populate observation codes for each associated observation if specimen["id"] in observation_by_id: @@ -726,7 +734,10 @@ def is_number(s): def get_subject(db: LocalFHIRDatabase, resource: dict) -> dict: - """get the resource's subject field if it exists""" + """ + get the resource's subject if it exists + Return both the raw subject and its simplified version + """ # ensure resource has subject field subject_key = get_nested_value(resource, ["subject", "reference"]) @@ -740,7 +751,8 @@ def get_subject(db: LocalFHIRDatabase, resource: dict) -> dict: assert row, f"{subject_key} not found in database" _, _, raw_subject = row subject = json.loads(raw_subject) - return traverse(subject) + + return subject, traverse(subject) def get_resources_by_reference( diff --git a/gen3_tracker/meta/entities.py b/gen3_tracker/meta/entities.py index eeb1f5a..d415856 100644 --- a/gen3_tracker/meta/entities.py +++ b/gen3_tracker/meta/entities.py @@ -517,6 +517,7 @@ def values(self) -> dict: for parent_dict in self.resource["parent"] ] ) + return _values diff --git a/tests/unit/dataframer/test_dataframer.py b/tests/unit/dataframer/test_dataframer.py index b5a9f69..cc890bf 100644 --- a/tests/unit/dataframer/test_dataframer.py +++ b/tests/unit/dataframer/test_dataframer.py @@ -5,7 +5,10 @@ from gen3_tracker.common import read_ndjson_file -from gen3_tracker.meta.dataframer import LocalFHIRDatabase, validate_and_transform_graphql_field_name +from gen3_tracker.meta.dataframer import ( + LocalFHIRDatabase, + validate_and_transform_graphql_field_name, +) from gen3_tracker.meta.entities import SimplifiedResource from pathlib import Path @@ -274,7 +277,16 @@ def htan_resources(htan_db): @pytest.fixture() -def docref_row(simplified_resources, document_reference_key): +def patient_row_as_subject(): + return { + "patient_active": True, + "patient_id": "bc4e1aa6-cb52-40e9-8f20-594d9c84f920", + "patient_identifier": "patientX_1234", + } + + +@pytest.fixture() +def docref_row(simplified_resources, document_reference_key, patient_row_as_subject): """Based on metadata files, create expected DocumentReference row, populated with any Observations that focus on it""" return { **simplified_resources[document_reference_key], @@ -296,22 +308,23 @@ def docref_row(simplified_resources, document_reference_key): "specimen_id": "60c67a06-ea2d-4d24-9249-418dc77a16a9", "specimen_identifier": "specimen_1234_labA", "specimen_processing": "Double-Spun", + **patient_row_as_subject, } @pytest.fixture() -def research_subject_row(simplified_resources, research_subject_key): +def research_subject_row( + simplified_resources, research_subject_key, patient_row_as_subject +): """Based on metadata files, create an expected Observations dataframe""" return { **simplified_resources[research_subject_key], - "patient_active": True, - "patient_id": "bc4e1aa6-cb52-40e9-8f20-594d9c84f920", - "patient_identifier": "patientX_1234", + **patient_row_as_subject, } @pytest.fixture() -def specimen_row(simplified_resources, specimen_key): +def specimen_row(simplified_resources, specimen_key, patient_row_as_subject): return { **simplified_resources[specimen_key], "sample_type": "Primary Solid Tumor", @@ -325,9 +338,7 @@ def specimen_row(simplified_resources, specimen_key): "biopsy_procedure_type": "Biopsy - Core", "biopsy_anatomical_location": "top axillary lymph node", "percent_tumor": "30", - "patient_identifier": "patientX_1234", - "patient_id": "bc4e1aa6-cb52-40e9-8f20-594d9c84f920", - "patient_active": True, + **patient_row_as_subject, } @@ -377,7 +388,9 @@ def test_htan_simplified(htan_resources): simplified = SimplifiedResource.build(resource=resource).simplified for key, value in simplified.items(): transformed_key = validate_and_transform_graphql_field_name(key) - assert key == transformed_key, f'Key "{key}" in {resource_type} was not transformed to valid GraphQL. Should be "{transformed_key}"' + assert ( + key == transformed_key + ), f'Key "{key}" in {resource_type} was not transformed to valid GraphQL. Should be "{transformed_key}"' def test_flattened_document_references(local_db, docref_row): @@ -413,30 +426,36 @@ def test_flattened_research_subjects(local_db, research_subject_row): # Using pytest.mark.parametrize to test multiple inputs and expected outputs -@pytest.mark.parametrize("input_name, expected_output", [ - ("user_name", "user_name"), - ("123fieldName", "_123fieldName"), - ("product-id", "product_id"), - ("item Name", "item_Name"), - ("my_field_with spaces and!@", "my_field_with_spaces_and__"), - ("__typename", "_typename"), # Valid, but reserved for introspection - ("__schema", "_schema"), # Valid, but reserved for introspection - ("__type", "_type", ), # Valid, but reserved for introspection - ("validFieldName", "validFieldName"), - ("anotherValid_Field", "anotherValid_Field"), - ("field_with_hyphen-and-space", "field_with_hyphen_and_space"), - ("", "_"), # becomes a single underscore - (" leading_space", "__leading_space"), - ("trailing_space ", "trailing_space__"), - ("some.field", "some_field"), - ("0_number_start", "_0_number_start"), - ("Cell Morphology Assessment", "Cell_Morphology_Assessment"), - ("Image ID", "Image_ID"), - ("Pixels BigEndian", "Pixels_BigEndian"), - ("Fixative Type", "Fixative_Type"), - ("Storage Method", "Storage_Method"), - ("Tumor Tissue Type", "Tumor_Tissue_Type"), -]) +@pytest.mark.parametrize( + "input_name, expected_output", + [ + ("user_name", "user_name"), + ("123fieldName", "_123fieldName"), + ("product-id", "product_id"), + ("item Name", "item_Name"), + ("my_field_with spaces and!@", "my_field_with_spaces_and__"), + ("__typename", "_typename"), # Valid, but reserved for introspection + ("__schema", "_schema"), # Valid, but reserved for introspection + ( + "__type", + "_type", + ), # Valid, but reserved for introspection + ("validFieldName", "validFieldName"), + ("anotherValid_Field", "anotherValid_Field"), + ("field_with_hyphen-and-space", "field_with_hyphen_and_space"), + ("", "_"), # becomes a single underscore + (" leading_space", "__leading_space"), + ("trailing_space ", "trailing_space__"), + ("some.field", "some_field"), + ("0_number_start", "_0_number_start"), + ("Cell Morphology Assessment", "Cell_Morphology_Assessment"), + ("Image ID", "Image_ID"), + ("Pixels BigEndian", "Pixels_BigEndian"), + ("Fixative Type", "Fixative_Type"), + ("Storage Method", "Storage_Method"), + ("Tumor Tissue Type", "Tumor_Tissue_Type"), + ], +) def test_validate_and_transform_graphql_field_name(input_name, expected_output): """ Tests the validate_and_transform_graphql_field_name function with various inputs. From 7dc14bc6b08de68783c014e0055700fa89bd947c Mon Sep 17 00:00:00 2001 From: quinnwai Date: Thu, 16 Oct 2025 11:01:37 -0700 Subject: [PATCH 2/7] linting --- tests/integration/test_end_to_end_workflow.py | 1 - tests/integration/test_rm_file.py | 107 +++++++++++------- tests/unit/test_indexclient.py | 7 +- tests/unit/test_none_fields.py | 3 +- 4 files changed, 72 insertions(+), 46 deletions(-) diff --git a/tests/integration/test_end_to_end_workflow.py b/tests/integration/test_end_to_end_workflow.py index 7d9a957..b07dec6 100644 --- a/tests/integration/test_end_to_end_workflow.py +++ b/tests/integration/test_end_to_end_workflow.py @@ -132,7 +132,6 @@ def test_simple_workflow(runner: CliRunner, project_id, tmpdir) -> None: # check the files exist in the cloned directory run_command("ls -l") - assert Path( "my-project-data/hello.txt" ).exists(), "hello.txt does not exist in the cloned directory." diff --git a/tests/integration/test_rm_file.py b/tests/integration/test_rm_file.py index ad1d7e7..4eab156 100644 --- a/tests/integration/test_rm_file.py +++ b/tests/integration/test_rm_file.py @@ -118,7 +118,7 @@ def test_rm_committed(runner: CliRunner, project_id, tmpdir) -> None: object_id = dvc.object_id auth = ensure_auth(config=default()) - ok = '' + ok = "" try: validate_document_in_grip(object_id, auth=auth, project_id=project_id) except Exception as e: @@ -129,7 +129,7 @@ def test_rm_committed(runner: CliRunner, project_id, tmpdir) -> None: except Exception as e: ok = ok + f" Elastic validation failed: {e}" - assert ok == '', ok + assert ok == "", ok # remove the project from the server. # TODO note, this does not remove the files from the bucket (UChicago bug) @@ -184,7 +184,10 @@ def test_rm_pushed(runner: CliRunner, project_id, tmpdir) -> None: run( runner, ["--debug", "meta", "init", "--bundle"], - expected_files=[Path("META/DocumentReference.ndjson"), Path("META/Bundle.ndjson")], + expected_files=[ + Path("META/DocumentReference.ndjson"), + Path("META/Bundle.ndjson"), + ], ) # commit the re-created meta @@ -209,7 +212,7 @@ def test_rm_pushed(runner: CliRunner, project_id, tmpdir) -> None: object_id = dvc.object_id auth = ensure_auth(config=default()) - ok = '' + ok = "" try: validate_document_in_grip(object_id, auth=auth, project_id=project_id) @@ -222,18 +225,26 @@ def test_rm_pushed(runner: CliRunner, project_id, tmpdir) -> None: ok = ok + f" Elastic validation failed: {e}" try: - validate_document_in_grip(expected_missing_object_id, auth=auth, project_id=project_id) - ok = ok + f" Grip validation failed should not have found: {expected_missing_object_id}" + validate_document_in_grip( + expected_missing_object_id, auth=auth, project_id=project_id + ) + ok = ( + ok + + f" Grip validation failed should not have found: {expected_missing_object_id}" + ) except Exception: pass try: validate_document_in_elastic(expected_missing_object_id, auth=auth) - ok = ok + f" Elastic validation failed should not have found: {expected_missing_object_id}" + ok = ( + ok + + f" Elastic validation failed should not have found: {expected_missing_object_id}" + ) except Exception: pass - assert ok == '', ok + assert ok == "", ok # remove the project from the server. # TODO note, this does not remove the files from the bucket (UChicago bug) @@ -288,7 +299,10 @@ def test_rm_commit_all(runner: CliRunner, project_id, tmpdir) -> None: run( runner, ["--debug", "meta", "init", "--bundle"], - expected_files=[Path("META/DocumentReference.ndjson"), Path("META/Bundle.ndjson")], + expected_files=[ + Path("META/DocumentReference.ndjson"), + Path("META/Bundle.ndjson"), + ], ) # commit the re-created meta @@ -313,7 +327,7 @@ def test_rm_commit_all(runner: CliRunner, project_id, tmpdir) -> None: object_id = dvc.object_id auth = ensure_auth(config=default()) - ok = '' + ok = "" try: validate_document_in_grip(object_id, auth=auth, project_id=project_id) @@ -326,18 +340,26 @@ def test_rm_commit_all(runner: CliRunner, project_id, tmpdir) -> None: ok = ok + f" Elastic validation failed: {e}" try: - validate_document_in_grip(expected_missing_object_id, auth=auth, project_id=project_id) - ok = ok + f" Grip validation failed should not have found: {expected_missing_object_id}" + validate_document_in_grip( + expected_missing_object_id, auth=auth, project_id=project_id + ) + ok = ( + ok + + f" Grip validation failed should not have found: {expected_missing_object_id}" + ) except Exception: pass try: validate_document_in_elastic(expected_missing_object_id, auth=auth) - ok = ok + f" Elastic validation failed should not have found: {expected_missing_object_id}" + ok = ( + ok + + f" Elastic validation failed should not have found: {expected_missing_object_id}" + ) except Exception: pass - assert ok == '', ok + assert ok == "", ok # remove the project from the server. # TODO note, this does not remove the files from the bucket (UChicago bug) @@ -373,33 +395,20 @@ def test_rm_pushed_links(runner: CliRunner, project_id, tmpdir) -> None: # Get the path of the platform temporary directory e.g. /tmp # we use the actual string '/tmp' as opposed to using the tempfile module provided in tmpdit # to ensure we can link to a file outside the project working dir - temp_dir = '/tmp' - if os.environ.get('TMP', None): - temp_dir = os.environ.get('TMP') + temp_dir = "/tmp" + if os.environ.get("TMP", None): + temp_dir = os.environ.get("TMP") test_file = Path(temp_dir) / "hello-g3t-integration-test.txt" test_file.write_text("hello\n") os.symlink(str(test_file), "hello4.txt") - run( - runner, - ["--debug", "add", "hello.txt"] - ) - run( - runner, - ["--debug", "add", "hello2.txt"] - ) + run(runner, ["--debug", "add", "hello.txt"]) + run(runner, ["--debug", "add", "hello2.txt"]) # should fail since the target file does not exist - run( - runner, - ["--debug", "add", "hello3.txt"], - expected_exit_code=1 - ) + run(runner, ["--debug", "add", "hello3.txt"], expected_exit_code=1) # should work since the target file exists - run( - runner, - ["--debug", "add", "hello4.txt"] - ) + run(runner, ["--debug", "add", "hello4.txt"]) # create the meta files run( @@ -435,7 +444,10 @@ def test_rm_pushed_links(runner: CliRunner, project_id, tmpdir) -> None: run( runner, ["--debug", "meta", "init", "--bundle"], - expected_files=[Path("META/DocumentReference.ndjson"), Path("META/Bundle.ndjson")], + expected_files=[ + Path("META/DocumentReference.ndjson"), + Path("META/Bundle.ndjson"), + ], ) # commit the re-created meta @@ -463,7 +475,7 @@ def test_rm_pushed_links(runner: CliRunner, project_id, tmpdir) -> None: object_id = dvc.object_id auth = ensure_auth(config=default()) - ok = '' + ok = "" try: validate_document_in_grip(object_id, auth=auth, project_id=project_id) @@ -476,18 +488,26 @@ def test_rm_pushed_links(runner: CliRunner, project_id, tmpdir) -> None: ok = ok + f" Elastic validation failed: {e}" try: - validate_document_in_grip(expected_missing_object_id, auth=auth, project_id=project_id) - ok = ok + f" Grip validation failed should not have found: {expected_missing_object_id}" + validate_document_in_grip( + expected_missing_object_id, auth=auth, project_id=project_id + ) + ok = ( + ok + + f" Grip validation failed should not have found: {expected_missing_object_id}" + ) except Exception: pass try: validate_document_in_elastic(expected_missing_object_id, auth=auth) - ok = ok + f" Elastic validation failed should not have found: {expected_missing_object_id}" + ok = ( + ok + + f" Elastic validation failed should not have found: {expected_missing_object_id}" + ) except Exception: pass - assert ok == '', ok + assert ok == "", ok # remove the project from the server. # TODO note, this does not remove the files from the bucket (UChicago bug) @@ -517,7 +537,12 @@ def read_dvc(file_path="MANIFEST/my-project-data/hello.txt.dvc"): return dvc -def _create_project(project_id, runner, add_files=True, files=("my-project-data/hello.txt", "my-project-data/hello2.txt")) -> list[str]: +def _create_project( + project_id, + runner, + add_files=True, + files=("my-project-data/hello.txt", "my-project-data/hello2.txt"), +) -> list[str]: """Create a project and add files to it.""" assert os.environ.get( diff --git a/tests/unit/test_indexclient.py b/tests/unit/test_indexclient.py index 6fcab88..22e8c9d 100644 --- a/tests/unit/test_indexclient.py +++ b/tests/unit/test_indexclient.py @@ -10,7 +10,10 @@ def index_client(): Fixture to provide an index client for testing. This is a placeholder and should be replaced with actual client initialization. """ - with patch('gen3.auth.Gen3Auth.get_access_token', return_value="accesstoken:///mock_access_token"): + with patch( + "gen3.auth.Gen3Auth.get_access_token", + return_value="accesstoken:///mock_access_token", + ): yield Gen3Index(auth_provider=Gen3Auth(endpoint="https://example.com/auth")) @@ -33,4 +36,4 @@ def test_authorization_header_present(index_client: Gen3Index): auth: Gen3Auth = mock_get.call_args[1].get("auth", None) assert auth is not None, "Auth object should not be None" auth_value = auth._get_auth_value() - assert auth_value == 'bearer accesstoken:///mock_access_token' + assert auth_value == "bearer accesstoken:///mock_access_token" diff --git a/tests/unit/test_none_fields.py b/tests/unit/test_none_fields.py index 40245b0..8e9394b 100644 --- a/tests/unit/test_none_fields.py +++ b/tests/unit/test_none_fields.py @@ -1,8 +1,7 @@ - - def test_none(): """Test None fields.""" from fhir.resources.patient import Patient + patient_dict = {"multipleBirthInteger": None, "name": None} patient = Patient.validate(patient_dict) assert patient From 8d5198c9fba960bf70999ec263d31cbd6cd0a140 Mon Sep 17 00:00:00 2001 From: quinnwai Date: Thu, 16 Oct 2025 11:05:14 -0700 Subject: [PATCH 3/7] bump --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e25f9b0..f5ed669 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name='gen3_tracker', - version='0.0.7rc24', + version='0.0.7rc25', description='A CLI for adding version control to Gen3 data submission projects.', long_description=long_description, long_description_content_type='text/markdown', From 14147e8b117a827b0f5866b951492ca61d953c49 Mon Sep 17 00:00:00 2001 From: quinnwai Date: Thu, 16 Oct 2025 13:53:16 -0700 Subject: [PATCH 4/7] add patient observations to research subject --- gen3_tracker/meta/dataframer.py | 53 ++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/gen3_tracker/meta/dataframer.py b/gen3_tracker/meta/dataframer.py index 81c4fac..7bb09ee 100644 --- a/gen3_tracker/meta/dataframer.py +++ b/gen3_tracker/meta/dataframer.py @@ -477,17 +477,21 @@ def select_coding(self, resource): def flattened_research_subjects(self) -> Generator[dict, None, None]: - # get all observations with a Observation.subject=Patient, mapped from patient ID to observation + # setup resource_type = "ResearchSubject" - conditions_by_patient_id = get_conditions_by_subject(self, "Patient") + patient_type = "Patient" + cursor = self.connect() + + # grab associated conditions + observations via patient ID at once + conditions_by_patient_id = get_conditions_by_subject(self, patient_type) + observations_by_patient_id = get_observations_by_focus(self, patient_type) # get all ResearchSubjects - cursor = self.connect() cursor.execute( "SELECT * FROM resources where resource_type = ?", (resource_type,) ) - # get research subject and associated .subject patient + # add in new fields to existing research subject for _, _, raw_research_subject in cursor.fetchall(): research_subject = json.loads(raw_research_subject) flat_research_subject = SimplifiedResource.build( @@ -498,6 +502,13 @@ def flattened_research_subjects(self) -> Generator[dict, None, None]: _, patient = get_subject(self, research_subject) flat_research_subject.update(patient) + # add patient observation values + flat_research_subject = update_with_observations( + flat_research_subject, + patient["patient_id"], + observations_by_patient_id, + ) + # get condition code, eg enrollment diagnosis if patient["patient_id"] in conditions_by_patient_id: conditions = conditions_by_patient_id[patient["patient_id"]] @@ -571,13 +582,7 @@ def flattened_document_reference( flat_doc_ref.update(simplified_subject_of_subject) # populate observation data associated with the document reference document - if doc_ref["id"] in observation_by_focus_id: - associated_observations = observation_by_focus_id[doc_ref["id"]] - - # TODO: assumes there are no duplicate column names in each observation - for observation in associated_observations: - flat_observation = SimplifiedResource.build(resource=observation).values - flat_doc_ref.update(flat_observation) + update_with_observations(flat_doc_ref, doc_ref["id"], observation_by_focus_id) # TODO: test this based on fhir-gdc if "basedOn" in doc_ref: @@ -617,13 +622,7 @@ def flattened_specimen(self, specimen: dict, observation_by_id: dict) -> dict: flat_specimen.update(simplified_subject) # populate observation codes for each associated observation - if specimen["id"] in observation_by_id: - observations = observation_by_id[specimen["id"]] - - # TODO: assumes there are no duplicate column names in each observation - for observation in observations: - flat_observation = SimplifiedResource.build(resource=observation).values - flat_specimen.update(flat_observation) + update_with_observations(flat_specimen, specimen["id"], observation_by_id) return flat_specimen @@ -733,6 +732,11 @@ def is_number(s): return False +#################### +# MACROS / HELPERS # +#################### + + def get_subject(db: LocalFHIRDatabase, resource: dict) -> dict: """ get the resource's subject if it exists @@ -816,3 +820,16 @@ def get_conditions_by_subject( ) -> dict[str, list]: """get all Conditions that have a subject of resource type subject_type""" return get_resources_by_reference(db, "Condition", "subject", subject_type) + + +def update_with_observations(resource, id, observations_by_id): + """update a resource with the observations associated with the provided ID""" + if id in observations_by_id: + associated_observations = observations_by_id[id] + + # TODO: assumes there are no duplicate column names in each observation + for observation in associated_observations: + flat_observation = SimplifiedResource.build(resource=observation).values + resource.update(flat_observation) + + return resource From ff5e63515f0d3fdc581203708ce1455e2c2138df Mon Sep 17 00:00:00 2001 From: quinnwai Date: Thu, 16 Oct 2025 15:08:20 -0700 Subject: [PATCH 5/7] bump --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f5ed669..9133785 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name='gen3_tracker', - version='0.0.7rc25', + version='0.0.7rc26', description='A CLI for adding version control to Gen3 data submission projects.', long_description=long_description, long_description_content_type='text/markdown', From 177ecbe0f9f36043d935f70ca293d82a5123def0 Mon Sep 17 00:00:00 2001 From: quinnwai Date: Thu, 16 Oct 2025 17:22:54 -0700 Subject: [PATCH 6/7] patch I think --- gen3_tracker/meta/dataframer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen3_tracker/meta/dataframer.py b/gen3_tracker/meta/dataframer.py index 7bb09ee..300a43c 100644 --- a/gen3_tracker/meta/dataframer.py +++ b/gen3_tracker/meta/dataframer.py @@ -746,7 +746,7 @@ def get_subject(db: LocalFHIRDatabase, resource: dict) -> dict: # ensure resource has subject field subject_key = get_nested_value(resource, ["subject", "reference"]) if subject_key is None: - return {} + return {}, {} # traverse the resource of the subject and return its values cursor = db.connect() From de47b22661ccd40c6f1aec3ee38d9efcd56f3565 Mon Sep 17 00:00:00 2001 From: quinnwai Date: Thu, 16 Oct 2025 17:26:55 -0700 Subject: [PATCH 7/7] bumperino --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9133785..7e9cec6 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name='gen3_tracker', - version='0.0.7rc26', + version='0.0.7rc27', description='A CLI for adding version control to Gen3 data submission projects.', long_description=long_description, long_description_content_type='text/markdown',