Skip to content

Commit 7ab1c10

Browse files
committed
Update default values in data models to use PydanticUndefined and adjust validation tests for required fields
1 parent d66b625 commit 7ab1c10

3 files changed

Lines changed: 50 additions & 44 deletions

File tree

middleware/sql_to_arc/src/middleware/sql_to_arc/models.py

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import Any, get_args, get_origin
99

1010
from pydantic import BaseModel, ConfigDict, Field, model_validator
11+
from pydantic_core import PydanticUndefined
1112

1213
logger = logging.getLogger(__name__)
1314

@@ -16,7 +17,7 @@ def spec_field(
1617
*,
1718
required: bool | None = None,
1819
allow_spec_override: bool = False,
19-
default: Any = None,
20+
default: Any = PydanticUndefined,
2021
**kwargs: Any,
2122
) -> Any:
2223
"""Define database-mapped fields with ARC spec metadata."""
@@ -66,7 +67,8 @@ def _field_metadata(field_info: Any) -> dict[str, Any]:
6667
@staticmethod
6768
def _field_default(field_info: Any) -> Any:
6869
"""Return default value for a field, including default_factory values."""
69-
return field_info.get_default(call_default_factory=True)
70+
val = field_info.get_default(call_default_factory=True)
71+
return None if val is PydanticUndefined else val
7072

7173
@staticmethod
7274
def _field_accepts_string(annotation: Any) -> bool:
@@ -252,8 +254,8 @@ class InvestigationRow(BaseRow):
252254
identifier: str = spec_field()
253255
title: str = spec_field()
254256
description_text: str = spec_field(default="", allow_spec_override=True)
255-
submission_date: datetime | None = spec_field()
256-
public_release_date: datetime | None = spec_field()
257+
submission_date: datetime | None = spec_field(default=None)
258+
public_release_date: datetime | None = spec_field(default=None)
257259

258260

259261
class StudyRow(BaseRow):
@@ -262,55 +264,55 @@ class StudyRow(BaseRow):
262264
identifier: str = spec_field()
263265
investigation_ref: str = spec_field()
264266
title: str = spec_field()
265-
description_text: str | None = spec_field()
266-
submission_date: datetime | None = spec_field()
267-
public_release_date: datetime | None = spec_field()
267+
description_text: str | None = spec_field(default=None)
268+
submission_date: datetime | None = spec_field(default=None)
269+
public_release_date: datetime | None = spec_field(default=None)
268270

269271

270272
class AssayRow(BaseRow):
271273
"""Pydantic model for assay database rows."""
272274

273275
identifier: str = spec_field()
274276
investigation_ref: str = spec_field()
275-
study_ref: str | None = spec_field()
276-
title: str | None = spec_field()
277-
description_text: str | None = spec_field()
278-
measurement_type_term: str | None = spec_field()
279-
measurement_type_uri: str | None = spec_field()
280-
measurement_type_version: str | None = spec_field()
281-
technology_type_term: str | None = spec_field()
282-
technology_type_uri: str | None = spec_field()
283-
technology_type_version: str | None = spec_field()
284-
technology_platform: str | None = spec_field()
277+
study_ref: str | None = spec_field(default=None)
278+
title: str | None = spec_field(default=None)
279+
description_text: str | None = spec_field(default=None)
280+
measurement_type_term: str | None = spec_field(default=None)
281+
measurement_type_uri: str | None = spec_field(default=None)
282+
measurement_type_version: str | None = spec_field(default=None)
283+
technology_type_term: str | None = spec_field(default=None)
284+
technology_type_uri: str | None = spec_field(default=None)
285+
technology_type_version: str | None = spec_field(default=None)
286+
technology_platform: str | None = spec_field(default=None)
285287

286288

287289
class PublicationRow(BaseRow):
288290
"""Pydantic model for publication database rows."""
289291

290292
investigation_ref: str = spec_field()
291293
target_type: str = spec_field()
292-
pubmed_id: str | None = spec_field()
293-
doi: str | None = spec_field()
294-
authors: str | None = spec_field()
295-
title: str | None = spec_field()
296-
status_term: str | None = spec_field()
297-
status_uri: str | None = spec_field()
298-
status_version: str | None = spec_field()
299-
target_ref: str | None = spec_field()
294+
pubmed_id: str | None = spec_field(default=None)
295+
doi: str | None = spec_field(default=None)
296+
authors: str | None = spec_field(default=None)
297+
title: str | None = spec_field(default=None)
298+
status_term: str | None = spec_field(default=None)
299+
status_uri: str | None = spec_field(default=None)
300+
status_version: str | None = spec_field(default=None)
301+
target_ref: str | None = spec_field(default=None)
300302

301303

302304
class ContactRow(BaseRow):
303305
"""Pydantic model for contact database rows."""
304306

305307
investigation_ref: str = spec_field()
306308
target_type: str = spec_field()
307-
last_name: str | None = spec_field()
308-
first_name: str | None = spec_field()
309-
mid_initials: str | None = spec_field()
310-
email: str | None = spec_field()
311-
phone: str | None = spec_field()
312-
fax: str | None = spec_field()
313-
postal_address: str | None = spec_field()
314-
affiliation: str | None = spec_field()
315-
roles: str | None = spec_field() # JSON string
316-
target_ref: str | None = spec_field()
309+
last_name: str | None = spec_field(default=None)
310+
first_name: str | None = spec_field(default=None)
311+
mid_initials: str | None = spec_field(default=None)
312+
email: str | None = spec_field(default=None)
313+
phone: str | None = spec_field(default=None)
314+
fax: str | None = spec_field(default=None)
315+
postal_address: str | None = spec_field(default=None)
316+
affiliation: str | None = spec_field(default=None)
317+
roles: str | None = spec_field(default=None) # JSON string
318+
target_ref: str | None = spec_field(default=None)

middleware/sql_to_arc/tests/unit/test_database_validation.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ async def test_validate_row_missing_optional_warns(caplog: pytest.LogCaptureFixt
5050
@pytest.mark.asyncio
5151
async def test_validate_row_description_text_exception() -> None:
5252
"""Test that missing required columns raise Exception."""
53-
# description_text is required and must exist.
54-
row = {"identifier": "1", "title": "Test"}
53+
# title is required and must exist.
54+
row = {"identifier": "1", "description_text": "Desc"}
5555

5656
with pytest.raises(Exception) as excinfo:
5757
InvestigationRow.model_validate(row)
5858

5959
assert "Missing required columns" in str(excinfo.value)
60-
assert "description_text" in str(excinfo.value)
60+
assert "title" in str(excinfo.value)
6161

6262

6363
@pytest.mark.asyncio

middleware/sql_to_arc/tests/unit/test_main.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,18 @@ async def test_process_investigations_flow(monkeypatch: pytest.MonkeyPatch) -> N
8989
mock_db = MagicMock()
9090

9191
# Mock DB stream methods
92-
async def mock_gen(data: list[Any]) -> AsyncGenerator[Any, None]:
92+
async def mock_gen(**kwargs: Any) -> AsyncGenerator[Any, None]:
93+
stats = kwargs.get("stats")
94+
data = [
95+
InvestigationRow(identifier="1", title="T1", description_text="D1"),
96+
InvestigationRow(identifier="2", title="T2", description_text="D2"),
97+
]
98+
if stats:
99+
stats.found_datasets += len(data)
93100
for item in data:
94101
yield item
95102

96-
mock_db.stream_investigations.side_effect = lambda **_: mock_gen([
97-
InvestigationRow(identifier="1", title="T1", description_text="D1"),
98-
InvestigationRow(identifier="2", title="T2", description_text="D2"),
99-
])
103+
mock_db.stream_investigations.side_effect = mock_gen
100104

101105
# Mock related data fetch
102106
async def mock_fetch_related(*_args: Any, **_kwargs: Any) -> RelatedDataBatch:
@@ -133,4 +137,4 @@ async def mock_process_inv(*args: Any, **kwargs: Any) -> None:
133137

134138
assert stats.found_datasets == 2 # noqa: PLR2004
135139
assert stats.total_studies == 1
136-
mock_db.stream_investigations.assert_called_with(limit=10)
140+
mock_db.stream_investigations.assert_called_with(stats=stats, limit=10)

0 commit comments

Comments
 (0)