From 4b9640f0fe1a81e16f73ef01bfaf12061c58df13 Mon Sep 17 00:00:00 2001 From: "Joseph T. French" Date: Thu, 30 Jul 2026 13:11:18 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20regenerate=20SDK=20=E2=80=94=20assert-m?= =?UTF-8?q?etrics=20op=20+=20external=20connection=20provider?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Picks up the integration-plane surface from robosystems #973/#974: the assert-metrics operation (typed request/response + envelope models), the 'external' connection provider with ExternalConnectionConfig (source_name registration), source_name on connection responses, and the registry-based event source description on create-event-block. --- .../api/connections/create_connection.py | 16 +- .../extensions_robo_ledger/assert_metrics.py | 322 ++++++++++++++++++ robosystems_client/graphql/schema.graphql | 2 +- robosystems_client/models/__init__.py | 18 + .../models/assert_metrics_request.py | 189 ++++++++++ .../models/assert_metrics_response.py | 126 +++++++ .../models/asserted_metric_lite.py | 125 +++++++ .../connection_provider_info_provider.py | 1 + .../models/connection_response.py | 21 ++ .../models/create_connection_request.py | 33 ++ .../create_connection_request_provider.py | 1 + .../models/create_event_block_request.py | 3 +- .../models/event_block_envelope.py | 4 +- .../models/external_connection_config.py | 91 +++++ .../list_connections_provider_type_0.py | 1 + robosystems_client/models/materialize_op.py | 4 +- .../models/metric_observation.py | 71 ++++ ...ration_envelope_assert_metrics_response.py | 158 +++++++++ ...envelope_assert_metrics_response_status.py | 10 + 19 files changed, 1187 insertions(+), 9 deletions(-) create mode 100644 robosystems_client/api/extensions_robo_ledger/assert_metrics.py create mode 100644 robosystems_client/models/assert_metrics_request.py create mode 100644 robosystems_client/models/assert_metrics_response.py create mode 100644 robosystems_client/models/asserted_metric_lite.py create mode 100644 robosystems_client/models/external_connection_config.py create mode 100644 robosystems_client/models/metric_observation.py create mode 100644 robosystems_client/models/operation_envelope_assert_metrics_response.py create mode 100644 robosystems_client/models/operation_envelope_assert_metrics_response_status.py diff --git a/robosystems_client/api/connections/create_connection.py b/robosystems_client/api/connections/create_connection.py index 178df36..a53979c 100644 --- a/robosystems_client/api/connections/create_connection.py +++ b/robosystems_client/api/connections/create_connection.py @@ -108,7 +108,9 @@ def sync_detailed( """Create Connection SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. One connection allowed per provider per graph. + activate. External: registers a source namespace for an integration that writes through the public + API. One connection allowed per provider per graph, except 'external' which allows one per + source_name. Args: graph_id (str): @@ -143,7 +145,9 @@ def sync( """Create Connection SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. One connection allowed per provider per graph. + activate. External: registers a source namespace for an integration that writes through the public + API. One connection allowed per provider per graph, except 'external' which allows one per + source_name. Args: graph_id (str): @@ -173,7 +177,9 @@ async def asyncio_detailed( """Create Connection SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. One connection allowed per provider per graph. + activate. External: registers a source namespace for an integration that writes through the public + API. One connection allowed per provider per graph, except 'external' which allows one per + source_name. Args: graph_id (str): @@ -206,7 +212,9 @@ async def asyncio( """Create Connection SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. One connection allowed per provider per graph. + activate. External: registers a source namespace for an integration that writes through the public + API. One connection allowed per provider per graph, except 'external' which allows one per + source_name. Args: graph_id (str): diff --git a/robosystems_client/api/extensions_robo_ledger/assert_metrics.py b/robosystems_client/api/extensions_robo_ledger/assert_metrics.py new file mode 100644 index 0000000..0991468 --- /dev/null +++ b/robosystems_client/api/extensions_robo_ledger/assert_metrics.py @@ -0,0 +1,322 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.assert_metrics_request import AssertMetricsRequest +from ...models.error_response import ErrorResponse +from ...models.operation_envelope_assert_metrics_response import ( + OperationEnvelopeAssertMetricsResponse, +) +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + graph_id: str, + *, + body: AssertMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + if not isinstance(idempotency_key, Unset): + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/extensions/roboledger/{graph_id}/operations/assert-metrics".format( + graph_id=quote(str(graph_id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | OperationEnvelopeAssertMetricsResponse | None: + if response.status_code == 200: + response_200 = OperationEnvelopeAssertMetricsResponse.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 422: + response_422 = ErrorResponse.from_dict(response.json()) + + return response_422 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | OperationEnvelopeAssertMetricsResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: AssertMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeAssertMetricsResponse]: + """Assert Metrics for a Metric Block + + Writes externally-observed metric values (usage counts, marketing numbers, hand-carried figures) + into the period's standing factset_type='metric' FactSet with AssertedProvenance — the observation + sibling of compute-metrics. One standing FactSet per (structure, entity, period_end); re-asserting a + period replaces its facts. Structures carrying Derive rules are compute-owned and rejected: asserted + and derived metric series keep disjoint structures. Observations must resolve to concepts on the + structure's presentation catalog. Deterministic and non-AI — no credits consumed. + + **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. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (AssertMetricsRequest): Request body for the ``assert-metrics`` operation. + + The observation sibling of ``compute-metrics``: writes externally- + observed values (usage counts, marketing numbers, hand-carried + figures) into the period's standing ``factset_type='metric'`` FactSet + with ``AssertedProvenance``. Re-asserting a period replaces its facts + — one standing FactSet per (structure, entity, period_end), the + accumulating time series. + + Structures carrying ``Derive`` rules are compute-owned + (``compute-metrics``) and rejected — asserted and derived metric + series keep disjoint structures. Asserted series are actuals; there + is no scenario axis. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeAssertMetricsResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + graph_id: str, + *, + client: AuthenticatedClient, + body: AssertMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeAssertMetricsResponse | None: + """Assert Metrics for a Metric Block + + Writes externally-observed metric values (usage counts, marketing numbers, hand-carried figures) + into the period's standing factset_type='metric' FactSet with AssertedProvenance — the observation + sibling of compute-metrics. One standing FactSet per (structure, entity, period_end); re-asserting a + period replaces its facts. Structures carrying Derive rules are compute-owned and rejected: asserted + and derived metric series keep disjoint structures. Observations must resolve to concepts on the + structure's presentation catalog. Deterministic and non-AI — no credits consumed. + + **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. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (AssertMetricsRequest): Request body for the ``assert-metrics`` operation. + + The observation sibling of ``compute-metrics``: writes externally- + observed values (usage counts, marketing numbers, hand-carried + figures) into the period's standing ``factset_type='metric'`` FactSet + with ``AssertedProvenance``. Re-asserting a period replaces its facts + — one standing FactSet per (structure, entity, period_end), the + accumulating time series. + + Structures carrying ``Derive`` rules are compute-owned + (``compute-metrics``) and rejected — asserted and derived metric + series keep disjoint structures. Asserted series are actuals; there + is no scenario axis. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeAssertMetricsResponse + """ + + return sync_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: AssertMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeAssertMetricsResponse]: + """Assert Metrics for a Metric Block + + Writes externally-observed metric values (usage counts, marketing numbers, hand-carried figures) + into the period's standing factset_type='metric' FactSet with AssertedProvenance — the observation + sibling of compute-metrics. One standing FactSet per (structure, entity, period_end); re-asserting a + period replaces its facts. Structures carrying Derive rules are compute-owned and rejected: asserted + and derived metric series keep disjoint structures. Observations must resolve to concepts on the + structure's presentation catalog. Deterministic and non-AI — no credits consumed. + + **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. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (AssertMetricsRequest): Request body for the ``assert-metrics`` operation. + + The observation sibling of ``compute-metrics``: writes externally- + observed values (usage counts, marketing numbers, hand-carried + figures) into the period's standing ``factset_type='metric'`` FactSet + with ``AssertedProvenance``. Re-asserting a period replaces its facts + — one standing FactSet per (structure, entity, period_end), the + accumulating time series. + + Structures carrying ``Derive`` rules are compute-owned + (``compute-metrics``) and rejected — asserted and derived metric + series keep disjoint structures. Asserted series are actuals; there + is no scenario axis. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeAssertMetricsResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + graph_id: str, + *, + client: AuthenticatedClient, + body: AssertMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeAssertMetricsResponse | None: + """Assert Metrics for a Metric Block + + Writes externally-observed metric values (usage counts, marketing numbers, hand-carried figures) + into the period's standing factset_type='metric' FactSet with AssertedProvenance — the observation + sibling of compute-metrics. One standing FactSet per (structure, entity, period_end); re-asserting a + period replaces its facts. Structures carrying Derive rules are compute-owned and rejected: asserted + and derived metric series keep disjoint structures. Observations must resolve to concepts on the + structure's presentation catalog. Deterministic and non-AI — no credits consumed. + + **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. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (AssertMetricsRequest): Request body for the ``assert-metrics`` operation. + + The observation sibling of ``compute-metrics``: writes externally- + observed values (usage counts, marketing numbers, hand-carried + figures) into the period's standing ``factset_type='metric'`` FactSet + with ``AssertedProvenance``. Re-asserting a period replaces its facts + — one standing FactSet per (structure, entity, period_end), the + accumulating time series. + + Structures carrying ``Derive`` rules are compute-owned + (``compute-metrics``) and rejected — asserted and derived metric + series keep disjoint structures. Asserted series are actuals; there + is no scenario axis. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeAssertMetricsResponse + """ + + return ( + await asyncio_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/robosystems_client/graphql/schema.graphql b/robosystems_client/graphql/schema.graphql index 7afa9a2..d6e029e 100644 --- a/robosystems_client/graphql/schema.graphql +++ b/robosystems_client/graphql/schema.graphql @@ -44,7 +44,7 @@ type Query { statement(reportId: String!, blockType: String!): Statement publishLists(limit: Int = null, offset: Int = null): PublishListList publishList(listId: String!): PublishListDetail - informationBlock(id: ID!, scenarioId: String = null, series: Boolean! = false, seriesHistory: Int = null, seriesForecast: Int = null): InformationBlock + informationBlock(id: ID!, scenarioId: String = null, series: Boolean = null, seriesHistory: Int = null, seriesForecast: Int = null): InformationBlock informationBlocks(blockType: String = null, category: String = null, limit: Int = null, offset: Int = null, scenarioId: String = null): [InformationBlock!]! taxonomyBlock(id: ID!): TaxonomyBlock taxonomyBlocks(taxonomyType: String = null, parentTaxonomyId: ID = null, category: String = null, limit: Int = null, offset: Int = null): [TaxonomyBlock!]! diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index df27b78..74eae2c 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -7,6 +7,9 @@ from .api_keys_response import APIKeysResponse from .artifact_response import ArtifactResponse from .artifact_response_template_type_0 import ArtifactResponseTemplateType0 +from .assert_metrics_request import AssertMetricsRequest +from .assert_metrics_response import AssertMetricsResponse +from .asserted_metric_lite import AssertedMetricLite from .association_response import AssociationResponse from .attribution_filter import AttributionFilter from .auth_response import AuthResponse @@ -215,6 +218,7 @@ from .execute_event_block_response_qb_error_type_0 import ( ExecuteEventBlockResponseQbErrorType0, ) +from .external_connection_config import ExternalConnectionConfig from .fact_lite import FactLite from .fact_set_lite import FactSetLite from .fact_set_lite_provenance_type_0 import FactSetLiteProvenanceType0 @@ -329,6 +333,7 @@ from .memory_record import MemoryRecord from .memory_record_provenance_type_0 import MemoryRecordProvenanceType0 from .metric_mechanics import MetricMechanics +from .metric_observation import MetricObservation from .o_auth_callback_request import OAuthCallbackRequest from .o_auth_callback_response import OAuthCallbackResponse from .o_auth_init_request import OAuthInitRequest @@ -344,6 +349,12 @@ from .operation_costs_ai_operations import OperationCostsAiOperations from .operation_costs_token_pricing import OperationCostsTokenPricing from .operation_envelope import OperationEnvelope +from .operation_envelope_assert_metrics_response import ( + OperationEnvelopeAssertMetricsResponse, +) +from .operation_envelope_assert_metrics_response_status import ( + OperationEnvelopeAssertMetricsResponseStatus, +) from .operation_envelope_association_response import ( OperationEnvelopeAssociationResponse, ) @@ -835,6 +846,9 @@ "APIKeysResponse", "ArtifactResponse", "ArtifactResponseTemplateType0", + "AssertedMetricLite", + "AssertMetricsRequest", + "AssertMetricsResponse", "AssociationResponse", "AttributionFilter", "AuthResponse", @@ -1005,6 +1019,7 @@ "ExecuteEventBlockRequest", "ExecuteEventBlockResponse", "ExecuteEventBlockResponseQbErrorType0", + "ExternalConnectionConfig", "FactLite", "FactSetLite", "FactSetLiteProvenanceType0", @@ -1101,6 +1116,7 @@ "MemoryRecord", "MemoryRecordProvenanceType0", "MetricMechanics", + "MetricObservation", "OAuthCallbackRequest", "OAuthCallbackResponse", "OAuthInitRequest", @@ -1112,6 +1128,8 @@ "OperationCostsAiOperations", "OperationCostsTokenPricing", "OperationEnvelope", + "OperationEnvelopeAssertMetricsResponse", + "OperationEnvelopeAssertMetricsResponseStatus", "OperationEnvelopeAssociationResponse", "OperationEnvelopeAssociationResponseStatus", "OperationEnvelopeBackfillPlanHistoryResponse", diff --git a/robosystems_client/models/assert_metrics_request.py b/robosystems_client/models/assert_metrics_request.py new file mode 100644 index 0000000..58578a9 --- /dev/null +++ b/robosystems_client/models/assert_metrics_request.py @@ -0,0 +1,189 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +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.metric_observation import MetricObservation + + +T = TypeVar("T", bound="AssertMetricsRequest") + + +@_attrs_define +class AssertMetricsRequest: + """Request body for the ``assert-metrics`` operation. + + The observation sibling of ``compute-metrics``: writes externally- + observed values (usage counts, marketing numbers, hand-carried + figures) into the period's standing ``factset_type='metric'`` FactSet + with ``AssertedProvenance``. Re-asserting a period replaces its facts + — one standing FactSet per (structure, entity, period_end), the + accumulating time series. + + Structures carrying ``Derive`` rules are compute-owned + (``compute-metrics``) and rejected — asserted and derived metric + series keep disjoint structures. Asserted series are actuals; there + is no scenario axis. + + Attributes: + structure_id (str): Metric block structure (block_type='metric') to assert into. + period_end (datetime.date): Period end the observations are for — instant concepts (a follower count at month + end) land as of this date; duration concepts (monthly downloads) end on it. + source_system (str): Identifier of the asserting system (e.g. 'content-machine') — recorded as the + AssertedProvenance source_system. + observations (list[MetricObservation]): Observed values, one per metric concept — duplicates rejected. + period_start (datetime.date | None | Unset): Window start for duration concepts and the standing FactSet's + period_start. Instant concepts ignore it. + entity_id (None | str | Unset): Entity to assert for. Defaults to the graph's earliest-created entity (the + primary entity for single-entity graphs). + basis_note (None | str | Unset): Free-text basis / source reference for the observations. + """ + + structure_id: str + period_end: datetime.date + source_system: str + observations: list[MetricObservation] + period_start: datetime.date | None | Unset = UNSET + entity_id: None | str | Unset = UNSET + basis_note: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + structure_id = self.structure_id + + period_end = self.period_end.isoformat() + + source_system = self.source_system + + observations = [] + for observations_item_data in self.observations: + observations_item = observations_item_data.to_dict() + observations.append(observations_item) + + period_start: None | str | Unset + if isinstance(self.period_start, Unset): + period_start = UNSET + elif isinstance(self.period_start, datetime.date): + period_start = self.period_start.isoformat() + else: + period_start = self.period_start + + entity_id: None | str | Unset + if isinstance(self.entity_id, Unset): + entity_id = UNSET + else: + entity_id = self.entity_id + + basis_note: None | str | Unset + if isinstance(self.basis_note, Unset): + basis_note = UNSET + else: + basis_note = self.basis_note + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "structure_id": structure_id, + "period_end": period_end, + "source_system": source_system, + "observations": observations, + } + ) + if period_start is not UNSET: + field_dict["period_start"] = period_start + if entity_id is not UNSET: + field_dict["entity_id"] = entity_id + if basis_note is not UNSET: + field_dict["basis_note"] = basis_note + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.metric_observation import MetricObservation + + d = dict(src_dict) + structure_id = d.pop("structure_id") + + period_end = datetime.date.fromisoformat(d.pop("period_end")) + + source_system = d.pop("source_system") + + observations = [] + _observations = d.pop("observations") + for observations_item_data in _observations: + observations_item = MetricObservation.from_dict(observations_item_data) + + observations.append(observations_item) + + def _parse_period_start(data: object) -> datetime.date | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + period_start_type_0 = datetime.date.fromisoformat(data) + + return period_start_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + period_start = _parse_period_start(d.pop("period_start", UNSET)) + + def _parse_entity_id(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + entity_id = _parse_entity_id(d.pop("entity_id", UNSET)) + + def _parse_basis_note(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + basis_note = _parse_basis_note(d.pop("basis_note", UNSET)) + + assert_metrics_request = cls( + structure_id=structure_id, + period_end=period_end, + source_system=source_system, + observations=observations, + period_start=period_start, + entity_id=entity_id, + basis_note=basis_note, + ) + + assert_metrics_request.additional_properties = d + return assert_metrics_request + + @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/assert_metrics_response.py b/robosystems_client/models/assert_metrics_response.py new file mode 100644 index 0000000..6a39547 --- /dev/null +++ b/robosystems_client/models/assert_metrics_response.py @@ -0,0 +1,126 @@ +from __future__ import annotations + +import datetime +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 + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.asserted_metric_lite import AssertedMetricLite + + +T = TypeVar("T", bound="AssertMetricsResponse") + + +@_attrs_define +class AssertMetricsResponse: + """Response for the ``assert-metrics`` operation. + + Attributes: + structure_id (str): + entity_id (str): + period_end (datetime.date): + fact_set_id (str): Standing metric FactSet the observations were written to. + asserted (list[AssertedMetricLite] | Unset): + replaced (bool | Unset): True when a prior standing set existed for the period and its facts were replaced. + Default: False. + """ + + structure_id: str + entity_id: str + period_end: datetime.date + fact_set_id: str + asserted: list[AssertedMetricLite] | Unset = UNSET + replaced: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + structure_id = self.structure_id + + entity_id = self.entity_id + + period_end = self.period_end.isoformat() + + fact_set_id = self.fact_set_id + + asserted: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.asserted, Unset): + asserted = [] + for asserted_item_data in self.asserted: + asserted_item = asserted_item_data.to_dict() + asserted.append(asserted_item) + + replaced = self.replaced + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "structure_id": structure_id, + "entity_id": entity_id, + "period_end": period_end, + "fact_set_id": fact_set_id, + } + ) + if asserted is not UNSET: + field_dict["asserted"] = asserted + if replaced is not UNSET: + field_dict["replaced"] = replaced + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.asserted_metric_lite import AssertedMetricLite + + d = dict(src_dict) + structure_id = d.pop("structure_id") + + entity_id = d.pop("entity_id") + + period_end = datetime.date.fromisoformat(d.pop("period_end")) + + fact_set_id = d.pop("fact_set_id") + + _asserted = d.pop("asserted", UNSET) + asserted: list[AssertedMetricLite] | Unset = UNSET + if _asserted is not UNSET: + asserted = [] + for asserted_item_data in _asserted: + asserted_item = AssertedMetricLite.from_dict(asserted_item_data) + + asserted.append(asserted_item) + + replaced = d.pop("replaced", UNSET) + + assert_metrics_response = cls( + structure_id=structure_id, + entity_id=entity_id, + period_end=period_end, + fact_set_id=fact_set_id, + asserted=asserted, + replaced=replaced, + ) + + assert_metrics_response.additional_properties = d + return assert_metrics_response + + @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/asserted_metric_lite.py b/robosystems_client/models/asserted_metric_lite.py new file mode 100644 index 0000000..4247088 --- /dev/null +++ b/robosystems_client/models/asserted_metric_lite.py @@ -0,0 +1,125 @@ +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="AssertedMetricLite") + + +@_attrs_define +class AssertedMetricLite: + """One metric written by an ``assert-metrics`` run. + + Attributes: + element_id (str): Metric element the fact was written for. + element_qname (str): Metric element qname. + name (str): Metric display name. + value (float): Asserted value. + unit (str): Fact unit — 'USD' for monetary, 'days' for days, else 'pure'. + period_type (str): 'instant' or 'duration'. + item_type (None | str | Unset): Format family from the metric element (monetary | ratio | percent | multiple | + days). None means untyped; fall back to unit. + """ + + element_id: str + element_qname: str + name: str + value: float + unit: str + period_type: str + item_type: 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_qname = self.element_qname + + name = self.name + + value = self.value + + unit = self.unit + + period_type = self.period_type + + item_type: None | str | Unset + if isinstance(self.item_type, Unset): + item_type = UNSET + else: + item_type = self.item_type + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "element_id": element_id, + "element_qname": element_qname, + "name": name, + "value": value, + "unit": unit, + "period_type": period_type, + } + ) + if item_type is not UNSET: + field_dict["item_type"] = item_type + + 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") + + element_qname = d.pop("element_qname") + + name = d.pop("name") + + value = d.pop("value") + + unit = d.pop("unit") + + period_type = d.pop("period_type") + + def _parse_item_type(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + item_type = _parse_item_type(d.pop("item_type", UNSET)) + + asserted_metric_lite = cls( + element_id=element_id, + element_qname=element_qname, + name=name, + value=value, + unit=unit, + period_type=period_type, + item_type=item_type, + ) + + asserted_metric_lite.additional_properties = d + return asserted_metric_lite + + @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/connection_provider_info_provider.py b/robosystems_client/models/connection_provider_info_provider.py index 265571e..3a3dfb4 100644 --- a/robosystems_client/models/connection_provider_info_provider.py +++ b/robosystems_client/models/connection_provider_info_provider.py @@ -2,6 +2,7 @@ class ConnectionProviderInfoProvider(str, Enum): + EXTERNAL = "external" QUICKBOOKS = "quickbooks" SEC = "sec" diff --git a/robosystems_client/models/connection_response.py b/robosystems_client/models/connection_response.py index 2caac86..c08f1c1 100644 --- a/robosystems_client/models/connection_response.py +++ b/robosystems_client/models/connection_response.py @@ -32,6 +32,8 @@ class ConnectionResponse: write_policy (None | str | Unset): Source-of-truth write policy: 'native' (RoboSystems is authoritative; no outbound write-back) or 'qb_authoritative' (QuickBooks is authoritative; RoboSystems-originated entries publish to QB). Set via the write-policy endpoint. + source_name (None | str | Unset): External-provider registered source slug — the value the integration stamps on + the events it emits. Null for platform providers. """ connection_id: str @@ -43,6 +45,7 @@ class ConnectionResponse: updated_at: datetime.datetime | None | str | Unset = UNSET last_sync: datetime.datetime | None | str | Unset = UNSET write_policy: None | str | Unset = UNSET + source_name: None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -88,6 +91,12 @@ def to_dict(self) -> dict[str, Any]: else: write_policy = self.write_policy + source_name: None | str | Unset + if isinstance(self.source_name, Unset): + source_name = UNSET + else: + source_name = self.source_name + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -107,6 +116,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["last_sync"] = last_sync if write_policy is not UNSET: field_dict["write_policy"] = write_policy + if source_name is not UNSET: + field_dict["source_name"] = source_name return field_dict @@ -188,6 +199,15 @@ def _parse_write_policy(data: object) -> None | str | Unset: write_policy = _parse_write_policy(d.pop("write_policy", UNSET)) + def _parse_source_name(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + source_name = _parse_source_name(d.pop("source_name", UNSET)) + connection_response = cls( connection_id=connection_id, provider=provider, @@ -198,6 +218,7 @@ def _parse_write_policy(data: object) -> None | str | Unset: updated_at=updated_at, last_sync=last_sync, write_policy=write_policy, + source_name=source_name, ) connection_response.additional_properties = d diff --git a/robosystems_client/models/create_connection_request.py b/robosystems_client/models/create_connection_request.py index d729f09..7fd34af 100644 --- a/robosystems_client/models/create_connection_request.py +++ b/robosystems_client/models/create_connection_request.py @@ -10,6 +10,7 @@ from ..types import UNSET, Unset if TYPE_CHECKING: + from ..models.external_connection_config import ExternalConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig from ..models.sec_connection_config import SECConnectionConfig @@ -27,15 +28,18 @@ class CreateConnectionRequest: entity from filing data). sec_config (None | SECConnectionConfig | Unset): quickbooks_config (None | QuickBooksConnectionConfig | Unset): + external_config (ExternalConnectionConfig | None | Unset): """ provider: CreateConnectionRequestProvider entity_id: None | str | Unset = UNSET sec_config: None | SECConnectionConfig | Unset = UNSET quickbooks_config: None | QuickBooksConnectionConfig | Unset = UNSET + external_config: ExternalConnectionConfig | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + from ..models.external_connection_config import ExternalConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig from ..models.sec_connection_config import SECConnectionConfig @@ -63,6 +67,14 @@ def to_dict(self) -> dict[str, Any]: else: quickbooks_config = self.quickbooks_config + external_config: dict[str, Any] | None | Unset + if isinstance(self.external_config, Unset): + external_config = UNSET + elif isinstance(self.external_config, ExternalConnectionConfig): + external_config = self.external_config.to_dict() + else: + external_config = self.external_config + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -76,11 +88,14 @@ def to_dict(self) -> dict[str, Any]: field_dict["sec_config"] = sec_config if quickbooks_config is not UNSET: field_dict["quickbooks_config"] = quickbooks_config + if external_config is not UNSET: + field_dict["external_config"] = external_config return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.external_connection_config import ExternalConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig from ..models.sec_connection_config import SECConnectionConfig @@ -132,11 +147,29 @@ def _parse_quickbooks_config( quickbooks_config = _parse_quickbooks_config(d.pop("quickbooks_config", UNSET)) + def _parse_external_config(data: object) -> ExternalConnectionConfig | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + external_config_type_0 = ExternalConnectionConfig.from_dict(data) + + return external_config_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(ExternalConnectionConfig | None | Unset, data) + + external_config = _parse_external_config(d.pop("external_config", UNSET)) + create_connection_request = cls( provider=provider, entity_id=entity_id, sec_config=sec_config, quickbooks_config=quickbooks_config, + external_config=external_config, ) create_connection_request.additional_properties = d diff --git a/robosystems_client/models/create_connection_request_provider.py b/robosystems_client/models/create_connection_request_provider.py index 9a63ab0..8d1265b 100644 --- a/robosystems_client/models/create_connection_request_provider.py +++ b/robosystems_client/models/create_connection_request_provider.py @@ -2,6 +2,7 @@ class CreateConnectionRequestProvider(str, Enum): + EXTERNAL = "external" QUICKBOOKS = "quickbooks" SEC = "sec" diff --git a/robosystems_client/models/create_event_block_request.py b/robosystems_client/models/create_event_block_request.py index c4921af..610cdf0 100644 --- a/robosystems_client/models/create_event_block_request.py +++ b/robosystems_client/models/create_event_block_request.py @@ -41,7 +41,8 @@ class CreateEventBlockRequest: (control, approval, reconciliation, inquiry) require event_class='support'. The DB CHECK rejects mismatched pairings. occurred_at (datetime.datetime): When the event happened in the real world - source (str): 'manual' | 'system' | 'schedule' | 'quickbooks' | 'xero' | 'plaid' + source (str): 'manual' | 'system' | 'schedule', a connected provider name (e.g. 'quickbooks'), or a source_name + registered via an 'external' connection. Validated against the graph's registered connections. event_class (CreateEventBlockRequestEventClass | Unset): REA event class. 'economic' events change resources and drive GL postings; 'support' events are audit-trail / value-chain primitives (typically captured with apply_handlers=False). Default: CreateEventBlockRequestEventClass.ECONOMIC. diff --git a/robosystems_client/models/event_block_envelope.py b/robosystems_client/models/event_block_envelope.py index 39b7622..72097a3 100644 --- a/robosystems_client/models/event_block_envelope.py +++ b/robosystems_client/models/event_block_envelope.py @@ -38,8 +38,8 @@ class EventBlockEnvelope: `fulfilled` (obligation discharged), `voided` (canceled — terminal), `superseded` (replaced by a corrected event — terminal). See `UpdateEventBlockRequest.transition_to` for the valid transition graph. occurred_at (datetime.datetime): When the event happened in the real world (UTC). - source (str): Capture source (`manual`, `system`, `schedule`, `quickbooks`, `xero`, `plaid`). Used for adapter - routing. + source (str): Capture source: `manual`, `system`, `schedule`, a connected provider name (e.g. `quickbooks`), or + a registered external source_name. Used for adapter routing. currency (str): ISO 4217 currency code for `amount`. metadata (EventBlockEnvelopeMetadata): Free-form payload — handler-specific keys when the event ran through a handler, otherwise whatever the adapter captured. diff --git a/robosystems_client/models/external_connection_config.py b/robosystems_client/models/external_connection_config.py new file mode 100644 index 0000000..d097bff --- /dev/null +++ b/robosystems_client/models/external_connection_config.py @@ -0,0 +1,91 @@ +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="ExternalConnectionConfig") + + +@_attrs_define +class ExternalConnectionConfig: + """External-integration connection configuration. + + Registers a source namespace for an integration the platform does not + run: the connection is registration + telemetry, not execution config. + The platform holds no credentials for the external source — the + integration authenticates to its own source and writes here through + the public API, stamping ``source_name`` on everything it emits. + + Attributes: + source_name (str): Source slug the integration stamps on the events it emits (lowercase letters, digits, '-', + '_'; must start with a letter). Unique per graph among live connections. + display_name (None | str | Unset): Human-readable label for the connections UI. + """ + + source_name: str + display_name: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + source_name = self.source_name + + display_name: None | str | Unset + if isinstance(self.display_name, Unset): + display_name = UNSET + else: + display_name = self.display_name + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "source_name": source_name, + } + ) + if display_name is not UNSET: + field_dict["display_name"] = display_name + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + source_name = d.pop("source_name") + + def _parse_display_name(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + display_name = _parse_display_name(d.pop("display_name", UNSET)) + + external_connection_config = cls( + source_name=source_name, + display_name=display_name, + ) + + external_connection_config.additional_properties = d + return external_connection_config + + @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/list_connections_provider_type_0.py b/robosystems_client/models/list_connections_provider_type_0.py index 9b93356..5327c98 100644 --- a/robosystems_client/models/list_connections_provider_type_0.py +++ b/robosystems_client/models/list_connections_provider_type_0.py @@ -2,6 +2,7 @@ class ListConnectionsProviderType0(str, Enum): + EXTERNAL = "external" QUICKBOOKS = "quickbooks" SEC = "sec" diff --git a/robosystems_client/models/materialize_op.py b/robosystems_client/models/materialize_op.py index 410ed23..f1c13d0 100644 --- a/robosystems_client/models/materialize_op.py +++ b/robosystems_client/models/materialize_op.py @@ -17,7 +17,9 @@ class MaterializeOp: Attributes: force (bool | Unset): Force materialization even if already up to date Default: False. - rebuild (bool | Unset): Rebuild the graph from scratch, dropping existing data Default: False. + rebuild (bool | Unset): Rebuild the graph from scratch, dropping existing data. Required (staged source) when + materializing new uploads into a graph that already contains materialized data — staging replays all uploaded + files, so a non-rebuild pass would re-copy ingested rows (409). Default: False. dry_run (bool | Unset): Validate tables without writing to the graph Default: False. source (None | str | Unset): Materialization source: 'extensions' for OLTP, omit for DuckDB staging tables materialize_embeddings (bool | Unset): Generate vector embeddings during materialization Default: False. diff --git a/robosystems_client/models/metric_observation.py b/robosystems_client/models/metric_observation.py new file mode 100644 index 0000000..4103f8d --- /dev/null +++ b/robosystems_client/models/metric_observation.py @@ -0,0 +1,71 @@ +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="MetricObservation") + + +@_attrs_define +class MetricObservation: + """One externally-observed value in an ``assert-metrics`` request. + + Attributes: + qname (str): Metric element qname (e.g. rsx:GithubStars). Must resolve to a concept on the structure's + presentation catalog. + value (float): Observed value. + """ + + qname: str + value: float + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + qname = self.qname + + value = self.value + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "qname": qname, + "value": value, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + qname = d.pop("qname") + + value = d.pop("value") + + metric_observation = cls( + qname=qname, + value=value, + ) + + metric_observation.additional_properties = d + return metric_observation + + @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/operation_envelope_assert_metrics_response.py b/robosystems_client/models/operation_envelope_assert_metrics_response.py new file mode 100644 index 0000000..2b74682 --- /dev/null +++ b/robosystems_client/models/operation_envelope_assert_metrics_response.py @@ -0,0 +1,158 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.operation_envelope_assert_metrics_response_status import ( + OperationEnvelopeAssertMetricsResponseStatus, +) +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.assert_metrics_response import AssertMetricsResponse + + +T = TypeVar("T", bound="OperationEnvelopeAssertMetricsResponse") + + +@_attrs_define +class OperationEnvelopeAssertMetricsResponse: + """ + Attributes: + operation (str): Kebab-case operation name + operation_id (str): op_-prefixed ULID for audit and SSE correlation + status (OperationEnvelopeAssertMetricsResponseStatus): Operation lifecycle state + at (str): ISO-8601 UTC timestamp + result (AssertMetricsResponse | None | Unset): Command-specific result payload + created_by (None | str | Unset): User ID that initiated the operation (null for legacy callers) + idempotent_replay (bool | Unset): True when this envelope came from the idempotency cache — the underlying + command did not execute again. False on fresh executions. Default: False. + """ + + operation: str + operation_id: str + status: OperationEnvelopeAssertMetricsResponseStatus + at: str + result: AssertMetricsResponse | None | Unset = UNSET + created_by: None | str | Unset = UNSET + idempotent_replay: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + from ..models.assert_metrics_response import AssertMetricsResponse + + operation = self.operation + + operation_id = self.operation_id + + status = self.status.value + + at = self.at + + result: dict[str, Any] | None | Unset + if isinstance(self.result, Unset): + result = UNSET + elif isinstance(self.result, AssertMetricsResponse): + result = self.result.to_dict() + else: + result = self.result + + created_by: None | str | Unset + if isinstance(self.created_by, Unset): + created_by = UNSET + else: + created_by = self.created_by + + idempotent_replay = self.idempotent_replay + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "operation": operation, + "operationId": operation_id, + "status": status, + "at": at, + } + ) + if result is not UNSET: + field_dict["result"] = result + if created_by is not UNSET: + field_dict["createdBy"] = created_by + if idempotent_replay is not UNSET: + field_dict["idempotentReplay"] = idempotent_replay + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.assert_metrics_response import AssertMetricsResponse + + d = dict(src_dict) + operation = d.pop("operation") + + operation_id = d.pop("operationId") + + status = OperationEnvelopeAssertMetricsResponseStatus(d.pop("status")) + + at = d.pop("at") + + def _parse_result(data: object) -> AssertMetricsResponse | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + result_type_0 = AssertMetricsResponse.from_dict(data) + + return result_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(AssertMetricsResponse | None | Unset, data) + + result = _parse_result(d.pop("result", UNSET)) + + def _parse_created_by(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + created_by = _parse_created_by(d.pop("createdBy", UNSET)) + + idempotent_replay = d.pop("idempotentReplay", UNSET) + + operation_envelope_assert_metrics_response = cls( + operation=operation, + operation_id=operation_id, + status=status, + at=at, + result=result, + created_by=created_by, + idempotent_replay=idempotent_replay, + ) + + operation_envelope_assert_metrics_response.additional_properties = d + return operation_envelope_assert_metrics_response + + @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/operation_envelope_assert_metrics_response_status.py b/robosystems_client/models/operation_envelope_assert_metrics_response_status.py new file mode 100644 index 0000000..7417eaa --- /dev/null +++ b/robosystems_client/models/operation_envelope_assert_metrics_response_status.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class OperationEnvelopeAssertMetricsResponseStatus(str, Enum): + COMPLETED = "completed" + FAILED = "failed" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value)