diff --git a/robosystems_client/api/extensions_robo_ledger/build_fact_grid.py b/robosystems_client/api/extensions_robo_ledger/build_fact_grid.py index aa9a9cf..c3a83ae 100644 --- a/robosystems_client/api/extensions_robo_ledger/build_fact_grid.py +++ b/robosystems_client/api/extensions_robo_ledger/build_fact_grid.py @@ -112,8 +112,10 @@ def sync_detailed( """Build Fact Grid Queries LadybugDB `Fact` nodes by element qnames or canonical concepts, with filters for periods, - entities, form, and fiscal context. Returns a deduplicated pivot table. Works on both roboledger - tenant graphs (post-materialization) and the SEC shared repository. + entities, form, and fiscal context. Returns deduplicated facts plus the aspects they span — + arranging them into a table is the consumer's job, since collapsing cells safely requires the full + aspect signature. Works on both roboledger tenant graphs (post-materialization) and the SEC shared + repository. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -154,8 +156,10 @@ def sync( """Build Fact Grid Queries LadybugDB `Fact` nodes by element qnames or canonical concepts, with filters for periods, - entities, form, and fiscal context. Returns a deduplicated pivot table. Works on both roboledger - tenant graphs (post-materialization) and the SEC shared repository. + entities, form, and fiscal context. Returns deduplicated facts plus the aspects they span — + arranging them into a table is the consumer's job, since collapsing cells safely requires the full + aspect signature. Works on both roboledger tenant graphs (post-materialization) and the SEC shared + repository. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -191,8 +195,10 @@ async def asyncio_detailed( """Build Fact Grid Queries LadybugDB `Fact` nodes by element qnames or canonical concepts, with filters for periods, - entities, form, and fiscal context. Returns a deduplicated pivot table. Works on both roboledger - tenant graphs (post-materialization) and the SEC shared repository. + entities, form, and fiscal context. Returns deduplicated facts plus the aspects they span — + arranging them into a table is the consumer's job, since collapsing cells safely requires the full + aspect signature. Works on both roboledger tenant graphs (post-materialization) and the SEC shared + repository. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -231,8 +237,10 @@ async def asyncio( """Build Fact Grid Queries LadybugDB `Fact` nodes by element qnames or canonical concepts, with filters for periods, - entities, form, and fiscal context. Returns a deduplicated pivot table. Works on both roboledger - tenant graphs (post-materialization) and the SEC shared repository. + entities, form, and fiscal context. Returns deduplicated facts plus the aspects they span — + arranging them into a table is the consumer's job, since collapsing cells safely requires the full + aspect signature. Works on both roboledger tenant graphs (post-materialization) and the SEC shared + repository. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index 74eae2c..0c7ddb0 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -181,12 +181,15 @@ DetailedTransactionsResponseDateRange, ) from .detailed_transactions_response_summary import DetailedTransactionsResponseSummary +from .dimension import Dimension +from .dimension_type import DimensionType from .document_detail_response import DocumentDetailResponse from .document_list_item import DocumentListItem from .document_list_response import DocumentListResponse from .document_section import DocumentSection from .download_quota import DownloadQuota from .element_lite import ElementLite +from .element_summary import ElementSummary from .element_update_patch import ElementUpdatePatch from .element_update_patch_metadata_type_0 import ElementUpdatePatchMetadataType0 from .email_verification_request import EmailVerificationRequest @@ -220,6 +223,7 @@ ) from .external_connection_config import ExternalConnectionConfig from .fact_lite import FactLite +from .fact_record import FactRecord from .fact_set_lite import FactSetLite from .fact_set_lite_provenance_type_0 import FactSetLiteProvenanceType0 from .file_info import FileInfo @@ -830,13 +834,11 @@ from .verification_result_lite import VerificationResultLite from .verification_summary import VerificationSummary from .view_axis_config import ViewAxisConfig -from .view_axis_config_element_labels_type_0 import ViewAxisConfigElementLabelsType0 -from .view_axis_config_member_labels_type_0 import ViewAxisConfigMemberLabelsType0 from .view_config import ViewConfig from .view_metadata import ViewMetadata from .view_projections import ViewProjections from .view_response import ViewResponse -from .view_response_presentations import ViewResponsePresentations +from .view_response_summary_type_0 import ViewResponseSummaryType0 __all__ = ( "AccountInfo", @@ -990,12 +992,15 @@ "DetailedTransactionsResponse", "DetailedTransactionsResponseDateRange", "DetailedTransactionsResponseSummary", + "Dimension", + "DimensionType", "DocumentDetailResponse", "DocumentListItem", "DocumentListResponse", "DocumentSection", "DownloadQuota", "ElementLite", + "ElementSummary", "ElementUpdatePatch", "ElementUpdatePatchMetadataType0", "EmailVerificationRequest", @@ -1021,6 +1026,7 @@ "ExecuteEventBlockResponseQbErrorType0", "ExternalConnectionConfig", "FactLite", + "FactRecord", "FactSetLite", "FactSetLiteProvenanceType0", "FileInfo", @@ -1425,11 +1431,9 @@ "VerificationResultLite", "VerificationSummary", "ViewAxisConfig", - "ViewAxisConfigElementLabelsType0", - "ViewAxisConfigMemberLabelsType0", "ViewConfig", "ViewMetadata", "ViewProjections", "ViewResponse", - "ViewResponsePresentations", + "ViewResponseSummaryType0", ) diff --git a/robosystems_client/models/create_view_request.py b/robosystems_client/models/create_view_request.py index d56d1ff..22c3522 100644 --- a/robosystems_client/models/create_view_request.py +++ b/robosystems_client/models/create_view_request.py @@ -30,6 +30,8 @@ class CreateViewRequest: fiscal_period (None | str | Unset): Filter by fiscal period (e.g., 'FY', 'Q1', 'Q2', 'Q3') period_type (None | str | Unset): Filter by period type: 'annual', 'quarterly', or 'instant' include_summary (bool | Unset): Include summary statistics per element Default: False. + limit (int | Unset): Maximum facts to return. Applied after deduplication and sorting, so truncation keeps the + most recent periods. Check `metadata.truncated` to see whether more facts matched. Default: 250. view_config (ViewConfig | Unset): """ @@ -43,6 +45,7 @@ class CreateViewRequest: fiscal_period: None | str | Unset = UNSET period_type: None | str | Unset = UNSET include_summary: bool | Unset = False + limit: int | Unset = 250 view_config: ViewConfig | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -95,6 +98,8 @@ def to_dict(self) -> dict[str, Any]: include_summary = self.include_summary + limit = self.limit + view_config: dict[str, Any] | Unset = UNSET if not isinstance(self.view_config, Unset): view_config = self.view_config.to_dict() @@ -122,6 +127,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["period_type"] = period_type if include_summary is not UNSET: field_dict["include_summary"] = include_summary + if limit is not UNSET: + field_dict["limit"] = limit if view_config is not UNSET: field_dict["view_config"] = view_config @@ -187,6 +194,8 @@ def _parse_period_type(data: object) -> None | str | Unset: include_summary = d.pop("include_summary", UNSET) + limit = d.pop("limit", UNSET) + _view_config = d.pop("view_config", UNSET) view_config: ViewConfig | Unset if isinstance(_view_config, Unset): @@ -205,6 +214,7 @@ def _parse_period_type(data: object) -> None | str | Unset: fiscal_period=fiscal_period, period_type=period_type, include_summary=include_summary, + limit=limit, view_config=view_config, ) diff --git a/robosystems_client/models/dimension.py b/robosystems_client/models/dimension.py new file mode 100644 index 0000000..6dfb394 --- /dev/null +++ b/robosystems_client/models/dimension.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.dimension_type import DimensionType +from ..types import UNSET, Unset + +T = TypeVar("T", bound="Dimension") + + +@_attrs_define +class Dimension: + """ + Attributes: + name (str): Dimension name (e.g., 'Element', 'Period') + type_ (DimensionType): + members (list[str] | Unset): List of dimension members + """ + + name: str + type_: DimensionType + members: list[str] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + name = self.name + + type_ = self.type_.value + + members: list[str] | Unset = UNSET + if not isinstance(self.members, Unset): + members = self.members + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "name": name, + "type": type_, + } + ) + if members is not UNSET: + field_dict["members"] = members + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + name = d.pop("name") + + type_ = DimensionType(d.pop("type")) + + members = cast(list[str], d.pop("members", UNSET)) + + dimension = cls( + name=name, + type_=type_, + members=members, + ) + + dimension.additional_properties = d + return dimension + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/dimension_type.py b/robosystems_client/models/dimension_type.py new file mode 100644 index 0000000..b6826a1 --- /dev/null +++ b/robosystems_client/models/dimension_type.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class DimensionType(str, Enum): + ELEMENT = "element" + ENTITY = "entity" + PERIOD = "period" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/element_summary.py b/robosystems_client/models/element_summary.py new file mode 100644 index 0000000..9182591 --- /dev/null +++ b/robosystems_client/models/element_summary.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="ElementSummary") + + +@_attrs_define +class ElementSummary: + """ + Attributes: + count (int): Number of facts for this element + total (float): Sum of values across the returned facts + average (float): Mean value across the returned facts + min_ (float): Minimum value across the returned facts + max_ (float): Maximum value across the returned facts + """ + + count: int + total: float + average: float + min_: float + max_: float + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + count = self.count + + total = self.total + + average = self.average + + min_ = self.min_ + + max_ = self.max_ + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "count": count, + "total": total, + "average": average, + "min": min_, + "max": max_, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + count = d.pop("count") + + total = d.pop("total") + + average = d.pop("average") + + min_ = d.pop("min") + + max_ = d.pop("max") + + element_summary = cls( + count=count, + total=total, + average=average, + min_=min_, + max_=max_, + ) + + element_summary.additional_properties = d + return element_summary + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/fact_record.py b/robosystems_client/models/fact_record.py new file mode 100644 index 0000000..cdc52c4 --- /dev/null +++ b/robosystems_client/models/fact_record.py @@ -0,0 +1,183 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="FactRecord") + + +@_attrs_define +class FactRecord: + """ + Attributes: + element_id (str): Element qname (e.g., 'us-gaap:Assets') + element_name (None | str | Unset): Element local name + period_end (None | str | Unset): Period end date (YYYY-MM-DD) + value (float | None | Unset): Numeric fact value + unit (None | str | Unset): Unit of measure (e.g., 'USD') + entity_ticker (None | str | Unset): Entity ticker; present only when an entity filter was applied + entity_name (None | str | Unset): Entity name; present only when an entity filter was applied + """ + + element_id: str + element_name: None | str | Unset = UNSET + period_end: None | str | Unset = UNSET + value: float | None | Unset = UNSET + unit: None | str | Unset = UNSET + entity_ticker: None | str | Unset = UNSET + entity_name: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + element_id = self.element_id + + element_name: None | str | Unset + if isinstance(self.element_name, Unset): + element_name = UNSET + else: + element_name = self.element_name + + period_end: None | str | Unset + if isinstance(self.period_end, Unset): + period_end = UNSET + else: + period_end = self.period_end + + value: float | None | Unset + if isinstance(self.value, Unset): + value = UNSET + else: + value = self.value + + unit: None | str | Unset + if isinstance(self.unit, Unset): + unit = UNSET + else: + unit = self.unit + + entity_ticker: None | str | Unset + if isinstance(self.entity_ticker, Unset): + entity_ticker = UNSET + else: + entity_ticker = self.entity_ticker + + entity_name: None | str | Unset + if isinstance(self.entity_name, Unset): + entity_name = UNSET + else: + entity_name = self.entity_name + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "element_id": element_id, + } + ) + if element_name is not UNSET: + field_dict["element_name"] = element_name + if period_end is not UNSET: + field_dict["period_end"] = period_end + if value is not UNSET: + field_dict["value"] = value + if unit is not UNSET: + field_dict["unit"] = unit + if entity_ticker is not UNSET: + field_dict["entity_ticker"] = entity_ticker + if entity_name is not UNSET: + field_dict["entity_name"] = entity_name + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + element_id = d.pop("element_id") + + def _parse_element_name(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + element_name = _parse_element_name(d.pop("element_name", UNSET)) + + def _parse_period_end(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + period_end = _parse_period_end(d.pop("period_end", UNSET)) + + def _parse_value(data: object) -> float | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(float | None | Unset, data) + + value = _parse_value(d.pop("value", UNSET)) + + def _parse_unit(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + unit = _parse_unit(d.pop("unit", UNSET)) + + def _parse_entity_ticker(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + entity_ticker = _parse_entity_ticker(d.pop("entity_ticker", UNSET)) + + def _parse_entity_name(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + entity_name = _parse_entity_name(d.pop("entity_name", UNSET)) + + fact_record = cls( + element_id=element_id, + element_name=element_name, + period_end=period_end, + value=value, + unit=unit, + entity_ticker=entity_ticker, + entity_name=entity_name, + ) + + fact_record.additional_properties = d + return fact_record + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/view_axis_config.py b/robosystems_client/models/view_axis_config.py index e24c43d..7b479c2 100644 --- a/robosystems_client/models/view_axis_config.py +++ b/robosystems_client/models/view_axis_config.py @@ -1,69 +1,38 @@ from __future__ import annotations from collections.abc import Mapping -from typing import TYPE_CHECKING, Any, TypeVar, cast +from typing import Any, TypeVar, cast from attrs import define as _attrs_define from attrs import field as _attrs_field from ..types import UNSET, Unset -if TYPE_CHECKING: - from ..models.view_axis_config_element_labels_type_0 import ( - ViewAxisConfigElementLabelsType0, - ) - from ..models.view_axis_config_member_labels_type_0 import ( - ViewAxisConfigMemberLabelsType0, - ) - - T = TypeVar("T", bound="ViewAxisConfig") @_attrs_define class ViewAxisConfig: - """ - Attributes: - type_ (str): Axis type: 'element', 'period', 'dimension', 'entity' - dimension_axis (None | str | Unset): Dimension axis name for dimension-type axes - include_null_dimension (bool | Unset): Include facts where this dimension is NULL (default: false) Default: - False. - selected_members (list[str] | None | Unset): Specific members to include (e.g., ['2024-12-31', '2023-12-31']) - member_order (list[str] | None | Unset): Explicit ordering of members (overrides default sort) - member_labels (None | Unset | ViewAxisConfigMemberLabelsType0): Custom labels for members (e.g., {'2024-12-31': - 'Current Year'}) - element_order (list[str] | None | Unset): Element ordering for hierarchy display (e.g., ['us-gaap:Assets', 'us- - gaap:Cash', ...]) - element_labels (None | Unset | ViewAxisConfigElementLabelsType0): Custom labels for elements (e.g., {'us- - gaap:Cash': 'Cash and Cash Equivalents'}) + """Scoping configuration for one aspect of the fact query. + + Filtering only. Ordering and labelling are presentation concerns and + belong to the consumer that arranges the facts into a table. + + Attributes: + type_ (str): Axis type: 'element', 'period', 'entity' + include_null_dimension (bool | Unset): Include facts where this aspect is absent (default: false) Default: + False. + selected_members (list[str] | None | Unset): Specific members to include (e.g., ['2024-12-31', '2023-12-31']) """ type_: str - dimension_axis: None | str | Unset = UNSET include_null_dimension: bool | Unset = False selected_members: list[str] | None | Unset = UNSET - member_order: list[str] | None | Unset = UNSET - member_labels: None | Unset | ViewAxisConfigMemberLabelsType0 = UNSET - element_order: list[str] | None | Unset = UNSET - element_labels: None | Unset | ViewAxisConfigElementLabelsType0 = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: - from ..models.view_axis_config_element_labels_type_0 import ( - ViewAxisConfigElementLabelsType0, - ) - from ..models.view_axis_config_member_labels_type_0 import ( - ViewAxisConfigMemberLabelsType0, - ) - type_ = self.type_ - dimension_axis: None | str | Unset - if isinstance(self.dimension_axis, Unset): - dimension_axis = UNSET - else: - dimension_axis = self.dimension_axis - include_null_dimension = self.include_null_dimension selected_members: list[str] | None | Unset @@ -75,40 +44,6 @@ def to_dict(self) -> dict[str, Any]: else: selected_members = self.selected_members - member_order: list[str] | None | Unset - if isinstance(self.member_order, Unset): - member_order = UNSET - elif isinstance(self.member_order, list): - member_order = self.member_order - - else: - member_order = self.member_order - - member_labels: dict[str, Any] | None | Unset - if isinstance(self.member_labels, Unset): - member_labels = UNSET - elif isinstance(self.member_labels, ViewAxisConfigMemberLabelsType0): - member_labels = self.member_labels.to_dict() - else: - member_labels = self.member_labels - - element_order: list[str] | None | Unset - if isinstance(self.element_order, Unset): - element_order = UNSET - elif isinstance(self.element_order, list): - element_order = self.element_order - - else: - element_order = self.element_order - - element_labels: dict[str, Any] | None | Unset - if isinstance(self.element_labels, Unset): - element_labels = UNSET - elif isinstance(self.element_labels, ViewAxisConfigElementLabelsType0): - element_labels = self.element_labels.to_dict() - else: - element_labels = self.element_labels - field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -116,44 +51,18 @@ def to_dict(self) -> dict[str, Any]: "type": type_, } ) - if dimension_axis is not UNSET: - field_dict["dimension_axis"] = dimension_axis if include_null_dimension is not UNSET: field_dict["include_null_dimension"] = include_null_dimension if selected_members is not UNSET: field_dict["selected_members"] = selected_members - if member_order is not UNSET: - field_dict["member_order"] = member_order - if member_labels is not UNSET: - field_dict["member_labels"] = member_labels - if element_order is not UNSET: - field_dict["element_order"] = element_order - if element_labels is not UNSET: - field_dict["element_labels"] = element_labels return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.view_axis_config_element_labels_type_0 import ( - ViewAxisConfigElementLabelsType0, - ) - from ..models.view_axis_config_member_labels_type_0 import ( - ViewAxisConfigMemberLabelsType0, - ) - d = dict(src_dict) type_ = d.pop("type") - def _parse_dimension_axis(data: object) -> None | str | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - return cast(None | str | Unset, data) - - dimension_axis = _parse_dimension_axis(d.pop("dimension_axis", UNSET)) - include_null_dimension = d.pop("include_null_dimension", UNSET) def _parse_selected_members(data: object) -> list[str] | None | Unset: @@ -173,87 +82,10 @@ def _parse_selected_members(data: object) -> list[str] | None | Unset: selected_members = _parse_selected_members(d.pop("selected_members", UNSET)) - def _parse_member_order(data: object) -> list[str] | None | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, list): - raise TypeError() - member_order_type_0 = cast(list[str], data) - - return member_order_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(list[str] | None | Unset, data) - - member_order = _parse_member_order(d.pop("member_order", UNSET)) - - def _parse_member_labels( - data: object, - ) -> None | Unset | ViewAxisConfigMemberLabelsType0: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, dict): - raise TypeError() - member_labels_type_0 = ViewAxisConfigMemberLabelsType0.from_dict(data) - - return member_labels_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(None | Unset | ViewAxisConfigMemberLabelsType0, data) - - member_labels = _parse_member_labels(d.pop("member_labels", UNSET)) - - def _parse_element_order(data: object) -> list[str] | None | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, list): - raise TypeError() - element_order_type_0 = cast(list[str], data) - - return element_order_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(list[str] | None | Unset, data) - - element_order = _parse_element_order(d.pop("element_order", UNSET)) - - def _parse_element_labels( - data: object, - ) -> None | Unset | ViewAxisConfigElementLabelsType0: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, dict): - raise TypeError() - element_labels_type_0 = ViewAxisConfigElementLabelsType0.from_dict(data) - - return element_labels_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(None | Unset | ViewAxisConfigElementLabelsType0, data) - - element_labels = _parse_element_labels(d.pop("element_labels", UNSET)) - view_axis_config = cls( type_=type_, - dimension_axis=dimension_axis, include_null_dimension=include_null_dimension, selected_members=selected_members, - member_order=member_order, - member_labels=member_labels, - element_order=element_order, - element_labels=element_labels, ) view_axis_config.additional_properties = d diff --git a/robosystems_client/models/view_axis_config_element_labels_type_0.py b/robosystems_client/models/view_axis_config_element_labels_type_0.py deleted file mode 100644 index ec52c8c..0000000 --- a/robosystems_client/models/view_axis_config_element_labels_type_0.py +++ /dev/null @@ -1,47 +0,0 @@ -from __future__ import annotations - -from collections.abc import Mapping -from typing import Any, TypeVar - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -T = TypeVar("T", bound="ViewAxisConfigElementLabelsType0") - - -@_attrs_define -class ViewAxisConfigElementLabelsType0: - """ """ - - additional_properties: dict[str, str] = _attrs_field(init=False, factory=dict) - - def to_dict(self) -> dict[str, Any]: - - field_dict: dict[str, Any] = {} - field_dict.update(self.additional_properties) - - return field_dict - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - d = dict(src_dict) - view_axis_config_element_labels_type_0 = cls() - - view_axis_config_element_labels_type_0.additional_properties = d - return view_axis_config_element_labels_type_0 - - @property - def additional_keys(self) -> list[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> str: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: str) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/robosystems_client/models/view_axis_config_member_labels_type_0.py b/robosystems_client/models/view_axis_config_member_labels_type_0.py deleted file mode 100644 index 3d39ad4..0000000 --- a/robosystems_client/models/view_axis_config_member_labels_type_0.py +++ /dev/null @@ -1,47 +0,0 @@ -from __future__ import annotations - -from collections.abc import Mapping -from typing import Any, TypeVar - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -T = TypeVar("T", bound="ViewAxisConfigMemberLabelsType0") - - -@_attrs_define -class ViewAxisConfigMemberLabelsType0: - """ """ - - additional_properties: dict[str, str] = _attrs_field(init=False, factory=dict) - - def to_dict(self) -> dict[str, Any]: - - field_dict: dict[str, Any] = {} - field_dict.update(self.additional_properties) - - return field_dict - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - d = dict(src_dict) - view_axis_config_member_labels_type_0 = cls() - - view_axis_config_member_labels_type_0.additional_properties = d - return view_axis_config_member_labels_type_0 - - @property - def additional_keys(self) -> list[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> str: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: str) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/robosystems_client/models/view_config.py b/robosystems_client/models/view_config.py index 782f103..ed1240b 100644 --- a/robosystems_client/models/view_config.py +++ b/robosystems_client/models/view_config.py @@ -21,16 +21,10 @@ class ViewConfig: Attributes: rows (list[ViewAxisConfig] | Unset): Row axis configuration columns (list[ViewAxisConfig] | Unset): Column axis configuration - values (str | Unset): Field to use for values (default: numeric_value) Default: 'numeric_value'. - aggregation_function (str | Unset): Aggregation function: sum, average, count Default: 'sum'. - fill_value (float | Unset): Value to use for missing data Default: 0.0. """ rows: list[ViewAxisConfig] | Unset = UNSET columns: list[ViewAxisConfig] | Unset = UNSET - values: str | Unset = "numeric_value" - aggregation_function: str | Unset = "sum" - fill_value: float | Unset = 0.0 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -48,12 +42,6 @@ def to_dict(self) -> dict[str, Any]: columns_item = columns_item_data.to_dict() columns.append(columns_item) - values = self.values - - aggregation_function = self.aggregation_function - - fill_value = self.fill_value - field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({}) @@ -61,12 +49,6 @@ def to_dict(self) -> dict[str, Any]: field_dict["rows"] = rows if columns is not UNSET: field_dict["columns"] = columns - if values is not UNSET: - field_dict["values"] = values - if aggregation_function is not UNSET: - field_dict["aggregation_function"] = aggregation_function - if fill_value is not UNSET: - field_dict["fill_value"] = fill_value return field_dict @@ -93,18 +75,9 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: columns.append(columns_item) - values = d.pop("values", UNSET) - - aggregation_function = d.pop("aggregation_function", UNSET) - - fill_value = d.pop("fill_value", UNSET) - view_config = cls( rows=rows, columns=columns, - values=values, - aggregation_function=aggregation_function, - fill_value=fill_value, ) view_config.additional_properties = d diff --git a/robosystems_client/models/view_metadata.py b/robosystems_client/models/view_metadata.py index 036a170..066ad68 100644 --- a/robosystems_client/models/view_metadata.py +++ b/robosystems_client/models/view_metadata.py @@ -21,6 +21,8 @@ class ViewMetadata: source (str): Data source type period_start (None | str | Unset): Period start date period_end (None | str | Unset): Period end date + truncated (bool | Unset): True when more facts matched than `limit` allowed. The returned facts are the most + recent by period; narrow the filters or raise `limit` to see the rest. Default: False. """ view_id: str @@ -29,6 +31,7 @@ class ViewMetadata: source: str period_start: None | str | Unset = UNSET period_end: None | str | Unset = UNSET + truncated: bool | Unset = False additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -52,6 +55,8 @@ def to_dict(self) -> dict[str, Any]: else: period_end = self.period_end + truncated = self.truncated + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -66,6 +71,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["period_start"] = period_start if period_end is not UNSET: field_dict["period_end"] = period_end + if truncated is not UNSET: + field_dict["truncated"] = truncated return field_dict @@ -98,6 +105,8 @@ def _parse_period_end(data: object) -> None | str | Unset: period_end = _parse_period_end(d.pop("period_end", UNSET)) + truncated = d.pop("truncated", UNSET) + view_metadata = cls( view_id=view_id, facts_processed=facts_processed, @@ -105,6 +114,7 @@ def _parse_period_end(data: object) -> None | str | Unset: source=source, period_start=period_start, period_end=period_end, + truncated=truncated, ) view_metadata.additional_properties = d diff --git a/robosystems_client/models/view_response.py b/robosystems_client/models/view_response.py index 9606342..701aa73 100644 --- a/robosystems_client/models/view_response.py +++ b/robosystems_client/models/view_response.py @@ -1,14 +1,18 @@ from __future__ import annotations from collections.abc import Mapping -from typing import TYPE_CHECKING, Any, TypeVar +from typing import TYPE_CHECKING, Any, TypeVar, cast from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..types import UNSET, Unset + if TYPE_CHECKING: + from ..models.dimension import Dimension + from ..models.fact_record import FactRecord from ..models.view_metadata import ViewMetadata - from ..models.view_response_presentations import ViewResponsePresentations + from ..models.view_response_summary_type_0 import ViewResponseSummaryType0 T = TypeVar("T", bound="ViewResponse") @@ -16,45 +20,120 @@ @_attrs_define class ViewResponse: - """ - Attributes: - metadata (ViewMetadata): - presentations (ViewResponsePresentations): Presentation formats (pivot_table, narrative, etc.) + """Flat, deduplicated facts plus the aspects they span. + + No server-side pivot: each fact is returned as its own record so the + consumer can arrange cells on the full aspect signature. Summing across + entities, units, or elements that merely share a local name is a + presentation decision this endpoint refuses to make on the caller's behalf. + + Attributes: + metadata (ViewMetadata): + dimensions (list[Dimension] | Unset): Aspects spanned by the returned facts + facts (list[FactRecord] | Unset): Deduplicated fact records + summary (None | Unset | ViewResponseSummaryType0): Per-element aggregates, only when include_summary=true. Note + that `total` sums across every returned period, which is meaningful for duration facts and not for instants. """ metadata: ViewMetadata - presentations: ViewResponsePresentations + dimensions: list[Dimension] | Unset = UNSET + facts: list[FactRecord] | Unset = UNSET + summary: None | Unset | ViewResponseSummaryType0 = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + from ..models.view_response_summary_type_0 import ViewResponseSummaryType0 + metadata = self.metadata.to_dict() - presentations = self.presentations.to_dict() + dimensions: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.dimensions, Unset): + dimensions = [] + for dimensions_item_data in self.dimensions: + dimensions_item = dimensions_item_data.to_dict() + dimensions.append(dimensions_item) + + facts: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.facts, Unset): + facts = [] + for facts_item_data in self.facts: + facts_item = facts_item_data.to_dict() + facts.append(facts_item) + + summary: dict[str, Any] | None | Unset + if isinstance(self.summary, Unset): + summary = UNSET + elif isinstance(self.summary, ViewResponseSummaryType0): + summary = self.summary.to_dict() + else: + summary = self.summary field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( { "metadata": metadata, - "presentations": presentations, } ) + if dimensions is not UNSET: + field_dict["dimensions"] = dimensions + if facts is not UNSET: + field_dict["facts"] = facts + if summary is not UNSET: + field_dict["summary"] = summary return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.dimension import Dimension + from ..models.fact_record import FactRecord from ..models.view_metadata import ViewMetadata - from ..models.view_response_presentations import ViewResponsePresentations + from ..models.view_response_summary_type_0 import ViewResponseSummaryType0 d = dict(src_dict) metadata = ViewMetadata.from_dict(d.pop("metadata")) - presentations = ViewResponsePresentations.from_dict(d.pop("presentations")) + _dimensions = d.pop("dimensions", UNSET) + dimensions: list[Dimension] | Unset = UNSET + if _dimensions is not UNSET: + dimensions = [] + for dimensions_item_data in _dimensions: + dimensions_item = Dimension.from_dict(dimensions_item_data) + + dimensions.append(dimensions_item) + + _facts = d.pop("facts", UNSET) + facts: list[FactRecord] | Unset = UNSET + if _facts is not UNSET: + facts = [] + for facts_item_data in _facts: + facts_item = FactRecord.from_dict(facts_item_data) + + facts.append(facts_item) + + def _parse_summary(data: object) -> None | Unset | ViewResponseSummaryType0: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + summary_type_0 = ViewResponseSummaryType0.from_dict(data) + + return summary_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | ViewResponseSummaryType0, data) + + summary = _parse_summary(d.pop("summary", UNSET)) view_response = cls( metadata=metadata, - presentations=presentations, + dimensions=dimensions, + facts=facts, + summary=summary, ) view_response.additional_properties = d diff --git a/robosystems_client/models/view_response_presentations.py b/robosystems_client/models/view_response_presentations.py deleted file mode 100644 index bdf235a..0000000 --- a/robosystems_client/models/view_response_presentations.py +++ /dev/null @@ -1,47 +0,0 @@ -from __future__ import annotations - -from collections.abc import Mapping -from typing import Any, TypeVar - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -T = TypeVar("T", bound="ViewResponsePresentations") - - -@_attrs_define -class ViewResponsePresentations: - """Presentation formats (pivot_table, narrative, etc.)""" - - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) - - def to_dict(self) -> dict[str, Any]: - - field_dict: dict[str, Any] = {} - field_dict.update(self.additional_properties) - - return field_dict - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - d = dict(src_dict) - view_response_presentations = cls() - - view_response_presentations.additional_properties = d - return view_response_presentations - - @property - def additional_keys(self) -> list[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> Any: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: Any) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/robosystems_client/models/view_response_summary_type_0.py b/robosystems_client/models/view_response_summary_type_0.py new file mode 100644 index 0000000..e8587d4 --- /dev/null +++ b/robosystems_client/models/view_response_summary_type_0.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.element_summary import ElementSummary + + +T = TypeVar("T", bound="ViewResponseSummaryType0") + + +@_attrs_define +class ViewResponseSummaryType0: + """ """ + + additional_properties: dict[str, ElementSummary] = _attrs_field( + init=False, factory=dict + ) + + def to_dict(self) -> dict[str, Any]: + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.element_summary import ElementSummary + + d = dict(src_dict) + view_response_summary_type_0 = cls() + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = ElementSummary.from_dict(prop_dict) + + additional_properties[prop_name] = additional_property + + view_response_summary_type_0.additional_properties = additional_properties + return view_response_summary_type_0 + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> ElementSummary: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: ElementSummary) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties