From 54ac152642748d77fc2a72f7e37293d41b0a5cb5 Mon Sep 17 00:00:00 2001 From: "hotdata-automation[bot]" <267177015+hotdata-automation[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 15:54:46 +0000 Subject: [PATCH] chore: regenerate client from OpenAPI spec --- .openapi-generator/FILES | 3 ++ docs/ResultsApi.md | 34 ++++++++++--- docs/ResultsFormatQuery.md | 13 +++++ hotdata/__init__.py | 2 + hotdata/api/results_api.py | 70 ++++++++++++++++++++++++-- hotdata/models/__init__.py | 1 + hotdata/models/results_format_query.py | 38 ++++++++++++++ test/test_results_format_query.py | 34 +++++++++++++ 8 files changed, 185 insertions(+), 10 deletions(-) create mode 100644 docs/ResultsFormatQuery.md create mode 100644 hotdata/models/results_format_query.py create mode 100644 test/test_results_format_query.py diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 33bbea0..caacec3 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -98,6 +98,7 @@ docs/RefreshResponse.md docs/RefreshWarning.md docs/ResultInfo.md docs/ResultsApi.md +docs/ResultsFormatQuery.md docs/Sandbox.md docs/SandboxResponse.md docs/SandboxesApi.md @@ -247,6 +248,7 @@ hotdata/models/refresh_request.py hotdata/models/refresh_response.py hotdata/models/refresh_warning.py hotdata/models/result_info.py +hotdata/models/results_format_query.py hotdata/models/sandbox.py hotdata/models/sandbox_response.py hotdata/models/saved_query_dataset_source.py @@ -287,4 +289,5 @@ requirements.txt setup.cfg test-requirements.txt test/__init__.py +test/test_results_format_query.py tox.ini diff --git a/docs/ResultsApi.md b/docs/ResultsApi.md index 8949dee..fb2b74b 100644 --- a/docs/ResultsApi.md +++ b/docs/ResultsApi.md @@ -9,11 +9,23 @@ Method | HTTP request | Description # **get_result** -> GetResultResponse get_result(id) +> GetResultResponse get_result(id, offset=offset, limit=limit, format=format) Get result -Retrieve a persisted query result by ID. If the result is still being processed, only the status is returned. Once ready, the full column and row data is included in the response. +Retrieve a persisted query result by ID. The response format for the `ready` state is selected by `Accept` header or `?format=` query param; non-ready states use the same status codes and JSON body shape regardless of format. + +| Result status | Status × body | +|-----------------------|------------------------------------------------------------------------------| +| `ready` + JSON | 200 `application/json` — `GetResultResponse` with `columns`, `rows`, etc. | +| `ready` + Arrow | 200 `application/vnd.apache.arrow.stream` — schema, RecordBatches, EOS | +| `pending`/`processing`| 202 `application/json` `{status, result_id}` + `Retry-After` | +| `failed` | 409 `application/json` `{status, result_id, error_message}` | +| not found | 404 `application/json` (`ApiErrorResponse`) | + +`?format=arrow` (or `?format=json`) takes precedence over `Accept`. Use `?offset=N&limit=M` to slice the result; `offset` defaults to 0 and `limit` is unbounded by default. Both must be non-negative; invalid values return 400. When a finite `limit` doesn't reach the end of the result, a `Link` header with `rel="next"` points at the following page. + +Ready responses (both formats) carry `X-Total-Row-Count` (full result row count from parquet metadata, independent of offset/limit). The Arrow path streams end-to-end with no spawned task between the parquet reader and the wire — clients can disconnect at any time and the server stops reading. ### Example @@ -24,6 +36,7 @@ Retrieve a persisted query result by ID. If the result is still being processed, ```python import hotdata from hotdata.models.get_result_response import GetResultResponse +from hotdata.models.results_format_query import ResultsFormatQuery from hotdata.rest import ApiException from pprint import pprint @@ -60,10 +73,13 @@ with hotdata.ApiClient(configuration) as api_client: # Create an instance of the API class api_instance = hotdata.ResultsApi(api_client) id = 'id_example' # str | Result ID + offset = 56 # int | Rows to skip (default: 0) (optional) + limit = 56 # int | Maximum rows to return (default: unbounded) (optional) + format = hotdata.ResultsFormatQuery() # ResultsFormatQuery | `arrow` or `json` — overrides the `Accept` header. (optional) try: # Get result - api_response = api_instance.get_result(id) + api_response = api_instance.get_result(id, offset=offset, limit=limit, format=format) print("The response of ResultsApi->get_result:\n") pprint(api_response) except Exception as e: @@ -78,6 +94,9 @@ with hotdata.ApiClient(configuration) as api_client: Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **id** | **str**| Result ID | + **offset** | **int**| Rows to skip (default: 0) | [optional] + **limit** | **int**| Maximum rows to return (default: unbounded) | [optional] + **format** | [**ResultsFormatQuery**](.md)| `arrow` or `json` — overrides the `Accept` header. | [optional] ### Return type @@ -90,14 +109,17 @@ Name | Type | Description | Notes ### HTTP request headers - **Content-Type**: Not defined - - **Accept**: application/json + - **Accept**: application/json, application/vnd.apache.arrow.stream ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Result data | - | -**404** | Result not found | - | +**200** | Result data. JSON callers receive `GetResultResponse`. Arrow callers receive an Arrow IPC stream — a sequence of IPC messages: schema header, then RecordBatch messages, then EOS. | * Link - RFC 5988 `Link` header with `rel=\"next\"` pointing at the next page when a finite `limit` does not reach the end of the result.
* X-Total-Row-Count - Total rows in the full result, ignoring offset/limit. Present only when status is `ready`.
| +**202** | Result is still being computed (`pending` or `processing`). Poll the same URL. | * Retry-After - Suggested seconds before the next poll.
| +**400** | Invalid offset, limit, or format. | - | +**404** | Result not found. | - | +**409** | Result computation failed. Body carries `error_message` describing the failure. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/docs/ResultsFormatQuery.md b/docs/ResultsFormatQuery.md new file mode 100644 index 0000000..7332004 --- /dev/null +++ b/docs/ResultsFormatQuery.md @@ -0,0 +1,13 @@ +# ResultsFormatQuery + +Schema for the `?format=` query parameter on `GET /v1/results/{id}`. Documents the canonical values accepted (`arrow`, `json`). The handler's negotiator (`negotiate_results_format`) is intentionally permissive — case-insensitive, with unknown values falling through to the `Accept` header — so this enum only declares the spec-level contract for clients and SDK generators. + +## Enum + +* `ARROW` (value: `'arrow'`) + +* `JSON` (value: `'json'`) + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/hotdata/__init__.py b/hotdata/__init__.py index 157fc84..eb05ec8 100644 --- a/hotdata/__init__.py +++ b/hotdata/__init__.py @@ -136,6 +136,7 @@ "RefreshResponse", "RefreshWarning", "ResultInfo", + "ResultsFormatQuery", "Sandbox", "SandboxResponse", "SavedQueryDatasetSource", @@ -288,6 +289,7 @@ from hotdata.models.refresh_response import RefreshResponse as RefreshResponse from hotdata.models.refresh_warning import RefreshWarning as RefreshWarning from hotdata.models.result_info import ResultInfo as ResultInfo +from hotdata.models.results_format_query import ResultsFormatQuery as ResultsFormatQuery from hotdata.models.sandbox import Sandbox as Sandbox from hotdata.models.sandbox_response import SandboxResponse as SandboxResponse from hotdata.models.saved_query_dataset_source import SavedQueryDatasetSource as SavedQueryDatasetSource diff --git a/hotdata/api/results_api.py b/hotdata/api/results_api.py index 656d378..0fccd2d 100644 --- a/hotdata/api/results_api.py +++ b/hotdata/api/results_api.py @@ -21,6 +21,7 @@ from typing_extensions import Annotated from hotdata.models.get_result_response import GetResultResponse from hotdata.models.list_results_response import ListResultsResponse +from hotdata.models.results_format_query import ResultsFormatQuery from hotdata.api_client import ApiClient, RequestSerialized from hotdata.api_response import ApiResponse @@ -44,6 +45,9 @@ def __init__(self, api_client=None) -> None: def get_result( self, id: Annotated[StrictStr, Field(description="Result ID")], + offset: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Rows to skip (default: 0)")] = None, + limit: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Maximum rows to return (default: unbounded)")] = None, + format: Annotated[Optional[ResultsFormatQuery], Field(description="`arrow` or `json` — overrides the `Accept` header.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -59,10 +63,16 @@ def get_result( ) -> GetResultResponse: """Get result - Retrieve a persisted query result by ID. If the result is still being processed, only the status is returned. Once ready, the full column and row data is included in the response. + Retrieve a persisted query result by ID. The response format for the `ready` state is selected by `Accept` header or `?format=` query param; non-ready states use the same status codes and JSON body shape regardless of format. | Result status | Status × body | |-----------------------|------------------------------------------------------------------------------| | `ready` + JSON | 200 `application/json` — `GetResultResponse` with `columns`, `rows`, etc. | | `ready` + Arrow | 200 `application/vnd.apache.arrow.stream` — schema, RecordBatches, EOS | | `pending`/`processing`| 202 `application/json` `{status, result_id}` + `Retry-After` | | `failed` | 409 `application/json` `{status, result_id, error_message}` | | not found | 404 `application/json` (`ApiErrorResponse`) | `?format=arrow` (or `?format=json`) takes precedence over `Accept`. Use `?offset=N&limit=M` to slice the result; `offset` defaults to 0 and `limit` is unbounded by default. Both must be non-negative; invalid values return 400. When a finite `limit` doesn't reach the end of the result, a `Link` header with `rel=\"next\"` points at the following page. Ready responses (both formats) carry `X-Total-Row-Count` (full result row count from parquet metadata, independent of offset/limit). The Arrow path streams end-to-end with no spawned task between the parquet reader and the wire — clients can disconnect at any time and the server stops reading. :param id: Result ID (required) :type id: str + :param offset: Rows to skip (default: 0) + :type offset: int + :param limit: Maximum rows to return (default: unbounded) + :type limit: int + :param format: `arrow` or `json` — overrides the `Accept` header. + :type format: ResultsFormatQuery :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -87,6 +97,9 @@ def get_result( _param = self._get_result_serialize( id=id, + offset=offset, + limit=limit, + format=format, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -95,7 +108,10 @@ def get_result( _response_types_map: Dict[str, Optional[str]] = { '200': "GetResultResponse", + '202': "GetResultResponse", + '400': "ApiErrorResponse", '404': "ApiErrorResponse", + '409': "GetResultResponse", } response_data = self.api_client.call_api( *_param, @@ -112,6 +128,9 @@ def get_result( def get_result_with_http_info( self, id: Annotated[StrictStr, Field(description="Result ID")], + offset: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Rows to skip (default: 0)")] = None, + limit: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Maximum rows to return (default: unbounded)")] = None, + format: Annotated[Optional[ResultsFormatQuery], Field(description="`arrow` or `json` — overrides the `Accept` header.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -127,10 +146,16 @@ def get_result_with_http_info( ) -> ApiResponse[GetResultResponse]: """Get result - Retrieve a persisted query result by ID. If the result is still being processed, only the status is returned. Once ready, the full column and row data is included in the response. + Retrieve a persisted query result by ID. The response format for the `ready` state is selected by `Accept` header or `?format=` query param; non-ready states use the same status codes and JSON body shape regardless of format. | Result status | Status × body | |-----------------------|------------------------------------------------------------------------------| | `ready` + JSON | 200 `application/json` — `GetResultResponse` with `columns`, `rows`, etc. | | `ready` + Arrow | 200 `application/vnd.apache.arrow.stream` — schema, RecordBatches, EOS | | `pending`/`processing`| 202 `application/json` `{status, result_id}` + `Retry-After` | | `failed` | 409 `application/json` `{status, result_id, error_message}` | | not found | 404 `application/json` (`ApiErrorResponse`) | `?format=arrow` (or `?format=json`) takes precedence over `Accept`. Use `?offset=N&limit=M` to slice the result; `offset` defaults to 0 and `limit` is unbounded by default. Both must be non-negative; invalid values return 400. When a finite `limit` doesn't reach the end of the result, a `Link` header with `rel=\"next\"` points at the following page. Ready responses (both formats) carry `X-Total-Row-Count` (full result row count from parquet metadata, independent of offset/limit). The Arrow path streams end-to-end with no spawned task between the parquet reader and the wire — clients can disconnect at any time and the server stops reading. :param id: Result ID (required) :type id: str + :param offset: Rows to skip (default: 0) + :type offset: int + :param limit: Maximum rows to return (default: unbounded) + :type limit: int + :param format: `arrow` or `json` — overrides the `Accept` header. + :type format: ResultsFormatQuery :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -155,6 +180,9 @@ def get_result_with_http_info( _param = self._get_result_serialize( id=id, + offset=offset, + limit=limit, + format=format, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -163,7 +191,10 @@ def get_result_with_http_info( _response_types_map: Dict[str, Optional[str]] = { '200': "GetResultResponse", + '202': "GetResultResponse", + '400': "ApiErrorResponse", '404': "ApiErrorResponse", + '409': "GetResultResponse", } response_data = self.api_client.call_api( *_param, @@ -180,6 +211,9 @@ def get_result_with_http_info( def get_result_without_preload_content( self, id: Annotated[StrictStr, Field(description="Result ID")], + offset: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Rows to skip (default: 0)")] = None, + limit: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Maximum rows to return (default: unbounded)")] = None, + format: Annotated[Optional[ResultsFormatQuery], Field(description="`arrow` or `json` — overrides the `Accept` header.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -195,10 +229,16 @@ def get_result_without_preload_content( ) -> RESTResponseType: """Get result - Retrieve a persisted query result by ID. If the result is still being processed, only the status is returned. Once ready, the full column and row data is included in the response. + Retrieve a persisted query result by ID. The response format for the `ready` state is selected by `Accept` header or `?format=` query param; non-ready states use the same status codes and JSON body shape regardless of format. | Result status | Status × body | |-----------------------|------------------------------------------------------------------------------| | `ready` + JSON | 200 `application/json` — `GetResultResponse` with `columns`, `rows`, etc. | | `ready` + Arrow | 200 `application/vnd.apache.arrow.stream` — schema, RecordBatches, EOS | | `pending`/`processing`| 202 `application/json` `{status, result_id}` + `Retry-After` | | `failed` | 409 `application/json` `{status, result_id, error_message}` | | not found | 404 `application/json` (`ApiErrorResponse`) | `?format=arrow` (or `?format=json`) takes precedence over `Accept`. Use `?offset=N&limit=M` to slice the result; `offset` defaults to 0 and `limit` is unbounded by default. Both must be non-negative; invalid values return 400. When a finite `limit` doesn't reach the end of the result, a `Link` header with `rel=\"next\"` points at the following page. Ready responses (both formats) carry `X-Total-Row-Count` (full result row count from parquet metadata, independent of offset/limit). The Arrow path streams end-to-end with no spawned task between the parquet reader and the wire — clients can disconnect at any time and the server stops reading. :param id: Result ID (required) :type id: str + :param offset: Rows to skip (default: 0) + :type offset: int + :param limit: Maximum rows to return (default: unbounded) + :type limit: int + :param format: `arrow` or `json` — overrides the `Accept` header. + :type format: ResultsFormatQuery :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -223,6 +263,9 @@ def get_result_without_preload_content( _param = self._get_result_serialize( id=id, + offset=offset, + limit=limit, + format=format, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -231,7 +274,10 @@ def get_result_without_preload_content( _response_types_map: Dict[str, Optional[str]] = { '200': "GetResultResponse", + '202': "GetResultResponse", + '400': "ApiErrorResponse", '404': "ApiErrorResponse", + '409': "GetResultResponse", } response_data = self.api_client.call_api( *_param, @@ -243,6 +289,9 @@ def get_result_without_preload_content( def _get_result_serialize( self, id, + offset, + limit, + format, _request_auth, _content_type, _headers, @@ -267,6 +316,18 @@ def _get_result_serialize( if id is not None: _path_params['id'] = id # process the query parameters + if offset is not None: + + _query_params.append(('offset', offset)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + if format is not None: + + _query_params.append(('format', format.value)) + # process the header parameters # process the form parameters # process the body parameter @@ -276,7 +337,8 @@ def _get_result_serialize( if 'Accept' not in _header_params: _header_params['Accept'] = self.api_client.select_header_accept( [ - 'application/json' + 'application/json', + 'application/vnd.apache.arrow.stream' ] ) diff --git a/hotdata/models/__init__.py b/hotdata/models/__init__.py index 8ffe434..87966ce 100644 --- a/hotdata/models/__init__.py +++ b/hotdata/models/__init__.py @@ -100,6 +100,7 @@ from hotdata.models.refresh_response import RefreshResponse from hotdata.models.refresh_warning import RefreshWarning from hotdata.models.result_info import ResultInfo +from hotdata.models.results_format_query import ResultsFormatQuery from hotdata.models.sandbox import Sandbox from hotdata.models.sandbox_response import SandboxResponse from hotdata.models.saved_query_dataset_source import SavedQueryDatasetSource diff --git a/hotdata/models/results_format_query.py b/hotdata/models/results_format_query.py new file mode 100644 index 0000000..e286c45 --- /dev/null +++ b/hotdata/models/results_format_query.py @@ -0,0 +1,38 @@ +# coding: utf-8 + +""" + Hotdata API + + Powerful data platform API for datasets, queries, and analytics. + + The version of the OpenAPI document: 1.0.0 + Contact: developers@hotdata.dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +from enum import Enum +from typing_extensions import Self + + +class ResultsFormatQuery(str, Enum): + """ + Schema for the `?format=` query parameter on `GET /v1/results/{id}`. Documents the canonical values accepted (`arrow`, `json`). The handler's negotiator (`negotiate_results_format`) is intentionally permissive — case-insensitive, with unknown values falling through to the `Accept` header — so this enum only declares the spec-level contract for clients and SDK generators. + """ + + """ + allowed enum values + """ + ARROW = 'arrow' + JSON = 'json' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ResultsFormatQuery from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/test/test_results_format_query.py b/test/test_results_format_query.py new file mode 100644 index 0000000..7439b76 --- /dev/null +++ b/test/test_results_format_query.py @@ -0,0 +1,34 @@ +# coding: utf-8 + +""" + Hotdata API + + Powerful data platform API for datasets, queries, and analytics. + + The version of the OpenAPI document: 1.0.0 + Contact: developers@hotdata.dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from hotdata.models.results_format_query import ResultsFormatQuery + +class TestResultsFormatQuery(unittest.TestCase): + """ResultsFormatQuery unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testResultsFormatQuery(self): + """Test ResultsFormatQuery""" + # inst = ResultsFormatQuery() + +if __name__ == '__main__': + unittest.main()