-
Notifications
You must be signed in to change notification settings - Fork 8
Allow for decimal parsing in pydantic model #141
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
base: develop
Are you sure you want to change the base?
Changes from 2 commits
359b82e
3564f8e
63e39fc
4415866
c3bfaeb
2e0c875
2834697
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,14 @@ | ||
| from decimal import Decimal | ||
| from typing import Any, Dict, List, Optional | ||
|
|
||
| from pydantic import BaseModel | ||
| from pydantic import BaseModel, TypeAdapter | ||
|
simon-hirsch marked this conversation as resolved.
|
||
|
|
||
| from ..config.config import logger | ||
|
|
||
|
|
||
| _ANY_ADAPTER = TypeAdapter(Any) | ||
|
|
||
|
|
||
| def _deduplicate_records(records: List[Dict[str, Any]]) -> List[Dict[str, Any]]: | ||
| """Remove duplicate records while preserving order.""" | ||
| seen = set() | ||
|
|
@@ -17,6 +21,17 @@ | |
| return unique_records | ||
|
|
||
|
|
||
| def _coerce_decimals_to_float(value: Any) -> Any: | ||
| """Recursively convert Decimal values to float for downstream processing.""" | ||
| if isinstance(value, Decimal): | ||
| return float(value) | ||
| if isinstance(value, dict): | ||
| return {k: _coerce_decimals_to_float(v) for k, v in value.items()} | ||
| if isinstance(value, list): | ||
| return [_coerce_decimals_to_float(item) for item in value] | ||
| return value | ||
|
|
||
|
|
||
| def normalize_to_records( | ||
| data: Dict[str, Any] | List[Any] | Any, | ||
| parent_key: str = "", | ||
|
|
@@ -117,6 +132,7 @@ | |
| "time_series.m_rid", | ||
| ], | ||
| deduplicate: bool = True, | ||
| decimal_to_float: bool = True, | ||
| ) -> List[Dict[str, int | float | str | None]]: | ||
|
simon-hirsch marked this conversation as resolved.
|
||
| """ | ||
| Convert a Pydantic model or list of Pydantic models to a list of flattened records suitable for pandas DataFrame. | ||
|
|
@@ -138,6 +154,9 @@ | |
| Defaults to ["m_rid", "time_series.m_rid"]. | ||
| Pass None to disable field filtering. | ||
| deduplicate: Whether to remove duplicate records while preserving order. Defaults to True. | ||
| decimal_to_float: Whether to convert Decimal values to float in the returned | ||
| records. If False, uses JSON serialization semantics where | ||
| Decimal values are represented as strings. Defaults to True. | ||
|
|
||
| Returns: | ||
| List of flattened dictionaries (records) from all BaseModel instances. | ||
|
|
@@ -179,7 +198,14 @@ | |
| f"Expected data to be a BaseModel or list of BaseModel instances, got {type(data)}" | ||
| ) | ||
|
|
||
| data_dict = [item.model_dump(mode="json") for item in data_list] | ||
| if decimal_to_float: | ||
| # Keep Decimal values typed, coerce them, then normalize to JSON-compatible | ||
| # values so the output structure stays aligned with mode="json". | ||
| data_dict = [item.model_dump(mode="python") for item in data_list] | ||
| data_dict = [_coerce_decimals_to_float(item_dict) for item_dict in data_dict] | ||
| data_dict = [_ANY_ADAPTER.dump_python(item_dict, mode="json") for item_dict in data_dict] | ||
|
||
| else: | ||
| data_dict = [item.model_dump(mode="json") for item in data_list] | ||
| all_records = [] | ||
|
|
||
| if domain: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.