From 00250bbfc900cb7003e3e77239ced58934b6d826 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 02:22:47 +0000 Subject: [PATCH 01/38] fix(perf): skip traversing types for NotGiven values --- src/asktable/_utils/_transform.py | 11 +++++++++++ tests/test_transform.py | 9 ++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/asktable/_utils/_transform.py b/src/asktable/_utils/_transform.py index 3ec62081..3b2b8e00 100644 --- a/src/asktable/_utils/_transform.py +++ b/src/asktable/_utils/_transform.py @@ -12,6 +12,7 @@ from ._utils import ( is_list, + is_given, is_mapping, is_iterable, ) @@ -258,6 +259,11 @@ def _transform_typeddict( result: dict[str, object] = {} annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): + if not is_given(value): + # we don't need to include `NotGiven` values here as they'll + # be stripped out before the request is sent anyway + continue + type_ = annotations.get(key) if type_ is None: # we do not have a type annotation for this field, leave it as is @@ -415,6 +421,11 @@ async def _async_transform_typeddict( result: dict[str, object] = {} annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): + if not is_given(value): + # we don't need to include `NotGiven` values here as they'll + # be stripped out before the request is sent anyway + continue + type_ = annotations.get(key) if type_ is None: # we do not have a type annotation for this field, leave it as is diff --git a/tests/test_transform.py b/tests/test_transform.py index a8a384a5..33ea35d8 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,7 +8,7 @@ import pytest -from asktable._types import Base64FileInput +from asktable._types import NOT_GIVEN, Base64FileInput from asktable._utils import ( PropertyInfo, transform as _transform, @@ -444,3 +444,10 @@ async def test_transform_skipping(use_async: bool) -> None: # iterables of ints are converted to a list data = iter([1, 2, 3]) assert await transform(data, Iterable[int], use_async) == [1, 2, 3] + + +@parametrize +@pytest.mark.asyncio +async def test_strips_notgiven(use_async: bool) -> None: + assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} + assert await transform({"foo_bar": NOT_GIVEN}, Foo1, use_async) == {} From 4ce95f7c3a5f0b7568ad63d0bb6fe8dade3d20ff Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 02:23:57 +0000 Subject: [PATCH 02/38] fix(perf): optimize some hot paths --- src/asktable/_utils/_transform.py | 14 +++++++++++++- src/asktable/_utils/_typing.py | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/asktable/_utils/_transform.py b/src/asktable/_utils/_transform.py index 3b2b8e00..b0cc20a7 100644 --- a/src/asktable/_utils/_transform.py +++ b/src/asktable/_utils/_transform.py @@ -5,7 +5,7 @@ import pathlib from typing import Any, Mapping, TypeVar, cast from datetime import date, datetime -from typing_extensions import Literal, get_args, override, get_type_hints +from typing_extensions import Literal, get_args, override, get_type_hints as _get_type_hints import anyio import pydantic @@ -13,6 +13,7 @@ from ._utils import ( is_list, is_given, + lru_cache, is_mapping, is_iterable, ) @@ -109,6 +110,7 @@ class Params(TypedDict, total=False): return cast(_T, transformed) +@lru_cache(maxsize=8096) def _get_annotated_type(type_: type) -> type | None: """If the given type is an `Annotated` type then it is returned, if not `None` is returned. @@ -433,3 +435,13 @@ async def _async_transform_typeddict( else: result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(value, annotation=type_) return result + + +@lru_cache(maxsize=8096) +def get_type_hints( + obj: Any, + globalns: dict[str, Any] | None = None, + localns: Mapping[str, Any] | None = None, + include_extras: bool = False, +) -> dict[str, Any]: + return _get_type_hints(obj, globalns=globalns, localns=localns, include_extras=include_extras) diff --git a/src/asktable/_utils/_typing.py b/src/asktable/_utils/_typing.py index 278749b1..1958820f 100644 --- a/src/asktable/_utils/_typing.py +++ b/src/asktable/_utils/_typing.py @@ -13,6 +13,7 @@ get_origin, ) +from ._utils import lru_cache from .._types import InheritsGeneric from .._compat import is_union as _is_union @@ -66,6 +67,7 @@ def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]: # Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]] +@lru_cache(maxsize=8096) def strip_annotated_type(typ: type) -> type: if is_required_type(typ) or is_annotated_type(typ): return strip_annotated_type(cast(type, get_args(typ)[0])) From c1a4b25eda6192bfb974f1aa6b21ae35f4ea762e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 02:32:54 +0000 Subject: [PATCH 03/38] chore(internal): update pyright settings --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 1ca6d95b..cabbe8c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -147,6 +147,7 @@ exclude = [ ] reportImplicitOverride = true +reportOverlappingOverload = false reportImportCycles = false reportPrivateUsage = false From b4af709160aa14f36bef3a624c069b21290ded66 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 02:34:26 +0000 Subject: [PATCH 04/38] chore(client): minor internal fixes --- src/asktable/_base_client.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/asktable/_base_client.py b/src/asktable/_base_client.py index b43d29e9..18d1f6a8 100644 --- a/src/asktable/_base_client.py +++ b/src/asktable/_base_client.py @@ -409,7 +409,8 @@ def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0 idempotency_header = self._idempotency_header if idempotency_header and options.method.lower() != "get" and idempotency_header not in headers: - headers[idempotency_header] = options.idempotency_key or self._idempotency_key() + options.idempotency_key = options.idempotency_key or self._idempotency_key() + headers[idempotency_header] = options.idempotency_key # Don't set these headers if they were already set or removed by the caller. We check # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case. @@ -943,6 +944,10 @@ def _request( request = self._build_request(options, retries_taken=retries_taken) self._prepare_request(request) + if options.idempotency_key: + # ensure the idempotency key is reused between requests + input_options.idempotency_key = options.idempotency_key + kwargs: HttpxSendArgs = {} if self.custom_auth is not None: kwargs["auth"] = self.custom_auth @@ -1475,6 +1480,10 @@ async def _request( request = self._build_request(options, retries_taken=retries_taken) await self._prepare_request(request) + if options.idempotency_key: + # ensure the idempotency key is reused between requests + input_options.idempotency_key = options.idempotency_key + kwargs: HttpxSendArgs = {} if self.custom_auth is not None: kwargs["auth"] = self.custom_auth From b56ec6cc156694361cbd43a2d8590813f30a47c0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Apr 2025 02:28:41 +0000 Subject: [PATCH 05/38] chore(internal): bump pyright version --- pyproject.toml | 2 +- requirements-dev.lock | 2 +- src/asktable/_base_client.py | 6 +++++- src/asktable/_models.py | 1 - src/asktable/_utils/_typing.py | 2 +- tests/conftest.py | 2 +- tests/test_models.py | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cabbe8c6..17a28b1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ Repository = "https://github.com/DataMini/asktable-python" managed = true # version pins are in requirements-dev.lock dev-dependencies = [ - "pyright>=1.1.359", + "pyright==1.1.399", "mypy", "respx", "pytest", diff --git a/requirements-dev.lock b/requirements-dev.lock index a151188f..19fed616 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -69,7 +69,7 @@ pydantic-core==2.27.1 # via pydantic pygments==2.18.0 # via rich -pyright==1.1.392.post0 +pyright==1.1.399 pytest==8.3.3 # via pytest-asyncio pytest-asyncio==0.24.0 diff --git a/src/asktable/_base_client.py b/src/asktable/_base_client.py index 18d1f6a8..5028f2b3 100644 --- a/src/asktable/_base_client.py +++ b/src/asktable/_base_client.py @@ -98,7 +98,11 @@ _AsyncStreamT = TypeVar("_AsyncStreamT", bound=AsyncStream[Any]) if TYPE_CHECKING: - from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT + from httpx._config import ( + DEFAULT_TIMEOUT_CONFIG, # pyright: ignore[reportPrivateImportUsage] + ) + + HTTPX_DEFAULT_TIMEOUT = DEFAULT_TIMEOUT_CONFIG else: try: from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT diff --git a/src/asktable/_models.py b/src/asktable/_models.py index 34935716..58b9263e 100644 --- a/src/asktable/_models.py +++ b/src/asktable/_models.py @@ -19,7 +19,6 @@ ) import pydantic -import pydantic.generics from pydantic.fields import FieldInfo from ._types import ( diff --git a/src/asktable/_utils/_typing.py b/src/asktable/_utils/_typing.py index 1958820f..1bac9542 100644 --- a/src/asktable/_utils/_typing.py +++ b/src/asktable/_utils/_typing.py @@ -110,7 +110,7 @@ class MyResponse(Foo[_T]): ``` """ cls = cast(object, get_origin(typ) or typ) - if cls in generic_bases: + if cls in generic_bases: # pyright: ignore[reportUnnecessaryContains] # we're given the class directly return extract_type_arg(typ, index) diff --git a/tests/conftest.py b/tests/conftest.py index 769bda69..fe426c1f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,7 +10,7 @@ from asktable import Asktable, AsyncAsktable if TYPE_CHECKING: - from _pytest.fixtures import FixtureRequest + from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] pytest.register_assert_rewrite("tests.utils") diff --git a/tests/test_models.py b/tests/test_models.py index 89906cad..572cdb75 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -832,7 +832,7 @@ class B(BaseModel): @pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") def test_type_alias_type() -> None: - Alias = TypeAliasType("Alias", str) + Alias = TypeAliasType("Alias", str) # pyright: ignore class Model(BaseModel): alias: Alias From 7e7f8c56783a125505f587d6f206da00da98f438 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Apr 2025 02:29:19 +0000 Subject: [PATCH 06/38] chore(internal): base client updates --- src/asktable/_base_client.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/asktable/_base_client.py b/src/asktable/_base_client.py index 5028f2b3..5944509e 100644 --- a/src/asktable/_base_client.py +++ b/src/asktable/_base_client.py @@ -119,6 +119,7 @@ class PageInfo: url: URL | NotGiven params: Query | NotGiven + json: Body | NotGiven @overload def __init__( @@ -134,19 +135,30 @@ def __init__( params: Query, ) -> None: ... + @overload + def __init__( + self, + *, + json: Body, + ) -> None: ... + def __init__( self, *, url: URL | NotGiven = NOT_GIVEN, + json: Body | NotGiven = NOT_GIVEN, params: Query | NotGiven = NOT_GIVEN, ) -> None: self.url = url + self.json = json self.params = params @override def __repr__(self) -> str: if self.url: return f"{self.__class__.__name__}(url={self.url})" + if self.json: + return f"{self.__class__.__name__}(json={self.json})" return f"{self.__class__.__name__}(params={self.params})" @@ -195,6 +207,19 @@ def _info_to_options(self, info: PageInfo) -> FinalRequestOptions: options.url = str(url) return options + if not isinstance(info.json, NotGiven): + if not is_mapping(info.json): + raise TypeError("Pagination is only supported with mappings") + + if not options.json_data: + options.json_data = {**info.json} + else: + if not is_mapping(options.json_data): + raise TypeError("Pagination is only supported with mappings") + + options.json_data = {**options.json_data, **info.json} + return options + raise ValueError("Unexpected PageInfo state") From 4e84f01f5b52e119f73cab72e4ea3ceaa1889e42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 19 Apr 2025 02:32:18 +0000 Subject: [PATCH 07/38] chore(internal): update models test --- tests/test_models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 572cdb75..8184554c 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -492,12 +492,15 @@ class Model(BaseModel): resource_id: Optional[str] = None m = Model.construct() + assert m.resource_id is None assert "resource_id" not in m.model_fields_set m = Model.construct(resource_id=None) + assert m.resource_id is None assert "resource_id" in m.model_fields_set m = Model.construct(resource_id="foo") + assert m.resource_id == "foo" assert "resource_id" in m.model_fields_set From f51cedc6e85b7300ae989972c02c2f4303c7838a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 03:00:14 +0000 Subject: [PATCH 08/38] chore(ci): add timeout thresholds for CI jobs --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81f6dc20..04b083ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ on: jobs: lint: + timeout-minutes: 10 name: lint runs-on: ubuntu-latest steps: @@ -30,6 +31,7 @@ jobs: run: ./scripts/lint test: + timeout-minutes: 10 name: test runs-on: ubuntu-latest steps: From bb1b5a84fbea13e655f968639f3e5edf584914ad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 03:00:46 +0000 Subject: [PATCH 09/38] chore(internal): import reformatting --- src/asktable/_client.py | 5 +---- src/asktable/resources/answers.py | 5 +---- src/asktable/resources/auth.py | 5 +---- src/asktable/resources/bots.py | 5 +---- src/asktable/resources/business_glossary.py | 11 ++--------- src/asktable/resources/chats/chats.py | 5 +---- src/asktable/resources/chats/messages.py | 5 +---- src/asktable/resources/datasources/datasources.py | 7 +------ src/asktable/resources/datasources/indexes.py | 5 +---- src/asktable/resources/datasources/meta.py | 5 +---- src/asktable/resources/datasources/upload_params.py | 5 +---- src/asktable/resources/extapis/extapis.py | 5 +---- src/asktable/resources/extapis/routes.py | 5 +---- src/asktable/resources/integration.py | 5 +---- src/asktable/resources/policies.py | 5 +---- src/asktable/resources/polish.py | 5 +---- src/asktable/resources/preferences.py | 5 +---- src/asktable/resources/project.py | 5 +---- src/asktable/resources/roles.py | 5 +---- src/asktable/resources/scores.py | 5 +---- src/asktable/resources/securetunnels.py | 5 +---- src/asktable/resources/sqls.py | 5 +---- src/asktable/resources/sys/projects/api_keys.py | 5 +---- src/asktable/resources/sys/projects/projects.py | 5 +---- src/asktable/resources/trainings.py | 5 +---- 25 files changed, 26 insertions(+), 107 deletions(-) diff --git a/src/asktable/_client.py b/src/asktable/_client.py index 3e986563..bd58763f 100644 --- a/src/asktable/_client.py +++ b/src/asktable/_client.py @@ -19,10 +19,7 @@ ProxiesTypes, RequestOptions, ) -from ._utils import ( - is_given, - get_async_library, -) +from ._utils import is_given, get_async_library from ._version import __version__ from .resources import ( auth, diff --git a/src/asktable/resources/answers.py b/src/asktable/resources/answers.py index 155a89bd..8dbd2955 100644 --- a/src/asktable/resources/answers.py +++ b/src/asktable/resources/answers.py @@ -8,10 +8,7 @@ from ..types import answer_list_params, answer_create_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/auth.py b/src/asktable/resources/auth.py index b8ed671d..065e06f1 100644 --- a/src/asktable/resources/auth.py +++ b/src/asktable/resources/auth.py @@ -9,10 +9,7 @@ from ..types import auth_create_token_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/bots.py b/src/asktable/resources/bots.py index 1cfc9725..13932733 100644 --- a/src/asktable/resources/bots.py +++ b/src/asktable/resources/bots.py @@ -8,10 +8,7 @@ from ..types import bot_list_params, bot_create_params, bot_invite_params, bot_update_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/business_glossary.py b/src/asktable/resources/business_glossary.py index 18700d43..7416e3bc 100644 --- a/src/asktable/resources/business_glossary.py +++ b/src/asktable/resources/business_glossary.py @@ -6,16 +6,9 @@ import httpx -from ..types import ( - business_glossary_list_params, - business_glossary_create_params, - business_glossary_update_params, -) +from ..types import business_glossary_list_params, business_glossary_create_params, business_glossary_update_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/chats/chats.py b/src/asktable/resources/chats/chats.py index 123f7d69..fd159838 100644 --- a/src/asktable/resources/chats/chats.py +++ b/src/asktable/resources/chats/chats.py @@ -8,10 +8,7 @@ from ...types import chat_list_params, chat_create_params from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import ( - maybe_transform, - async_maybe_transform, -) +from ..._utils import maybe_transform, async_maybe_transform from .messages import ( MessagesResource, AsyncMessagesResource, diff --git a/src/asktable/resources/chats/messages.py b/src/asktable/resources/chats/messages.py index 8ad81c31..7c3ca18a 100644 --- a/src/asktable/resources/chats/messages.py +++ b/src/asktable/resources/chats/messages.py @@ -7,10 +7,7 @@ import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import ( - maybe_transform, - async_maybe_transform, -) +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( diff --git a/src/asktable/resources/datasources/datasources.py b/src/asktable/resources/datasources/datasources.py index a2b1b03e..1bcc4596 100644 --- a/src/asktable/resources/datasources/datasources.py +++ b/src/asktable/resources/datasources/datasources.py @@ -31,12 +31,7 @@ AsyncIndexesResourceWithStreamingResponse, ) from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes -from ..._utils import ( - extract_files, - maybe_transform, - deepcopy_minimal, - async_maybe_transform, -) +from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( diff --git a/src/asktable/resources/datasources/indexes.py b/src/asktable/resources/datasources/indexes.py index a4df4476..3ffd6f4a 100644 --- a/src/asktable/resources/datasources/indexes.py +++ b/src/asktable/resources/datasources/indexes.py @@ -5,10 +5,7 @@ import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import ( - maybe_transform, - async_maybe_transform, -) +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( diff --git a/src/asktable/resources/datasources/meta.py b/src/asktable/resources/datasources/meta.py index ab219d17..431f1fba 100644 --- a/src/asktable/resources/datasources/meta.py +++ b/src/asktable/resources/datasources/meta.py @@ -7,10 +7,7 @@ import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import ( - maybe_transform, - async_maybe_transform, -) +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( diff --git a/src/asktable/resources/datasources/upload_params.py b/src/asktable/resources/datasources/upload_params.py index 54fd1d93..01578571 100644 --- a/src/asktable/resources/datasources/upload_params.py +++ b/src/asktable/resources/datasources/upload_params.py @@ -7,10 +7,7 @@ import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import ( - maybe_transform, - async_maybe_transform, -) +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( diff --git a/src/asktable/resources/extapis/extapis.py b/src/asktable/resources/extapis/extapis.py index 9c392981..080c9361 100644 --- a/src/asktable/resources/extapis/extapis.py +++ b/src/asktable/resources/extapis/extapis.py @@ -16,10 +16,7 @@ ) from ...types import extapi_list_params, extapi_create_params, extapi_update_params from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import ( - maybe_transform, - async_maybe_transform, -) +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( diff --git a/src/asktable/resources/extapis/routes.py b/src/asktable/resources/extapis/routes.py index 2551affa..2f168725 100644 --- a/src/asktable/resources/extapis/routes.py +++ b/src/asktable/resources/extapis/routes.py @@ -9,10 +9,7 @@ import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import ( - maybe_transform, - async_maybe_transform, -) +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( diff --git a/src/asktable/resources/integration.py b/src/asktable/resources/integration.py index f4384669..e82d2672 100644 --- a/src/asktable/resources/integration.py +++ b/src/asktable/resources/integration.py @@ -8,10 +8,7 @@ from ..types import integration_excel_csv_ask_params, integration_create_excel_ds_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/policies.py b/src/asktable/resources/policies.py index 7452080f..3c8c9b28 100644 --- a/src/asktable/resources/policies.py +++ b/src/asktable/resources/policies.py @@ -9,10 +9,7 @@ from ..types import policy_list_params, policy_create_params, policy_update_params from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/polish.py b/src/asktable/resources/polish.py index 3343078e..23df7f15 100644 --- a/src/asktable/resources/polish.py +++ b/src/asktable/resources/polish.py @@ -8,10 +8,7 @@ from ..types import polish_create_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/preferences.py b/src/asktable/resources/preferences.py index 886db40e..a96452be 100644 --- a/src/asktable/resources/preferences.py +++ b/src/asktable/resources/preferences.py @@ -8,10 +8,7 @@ from ..types import preference_create_params, preference_update_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/project.py b/src/asktable/resources/project.py index 3208457e..5624ab32 100644 --- a/src/asktable/resources/project.py +++ b/src/asktable/resources/project.py @@ -8,10 +8,7 @@ from ..types import project_update_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/roles.py b/src/asktable/resources/roles.py index 6d64fcde..ec37d440 100644 --- a/src/asktable/resources/roles.py +++ b/src/asktable/resources/roles.py @@ -8,10 +8,7 @@ from ..types import role_list_params, role_create_params, role_update_params, role_get_variables_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/scores.py b/src/asktable/resources/scores.py index cf0b5112..343a17e8 100644 --- a/src/asktable/resources/scores.py +++ b/src/asktable/resources/scores.py @@ -6,10 +6,7 @@ from ..types import score_create_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/securetunnels.py b/src/asktable/resources/securetunnels.py index 2614f8e1..13476a28 100644 --- a/src/asktable/resources/securetunnels.py +++ b/src/asktable/resources/securetunnels.py @@ -13,10 +13,7 @@ securetunnel_list_links_params, ) from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/sqls.py b/src/asktable/resources/sqls.py index 367f98b0..2804eaef 100644 --- a/src/asktable/resources/sqls.py +++ b/src/asktable/resources/sqls.py @@ -8,10 +8,7 @@ from ..types import sql_list_params, sql_create_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( diff --git a/src/asktable/resources/sys/projects/api_keys.py b/src/asktable/resources/sys/projects/api_keys.py index 11d84397..4b17a377 100644 --- a/src/asktable/resources/sys/projects/api_keys.py +++ b/src/asktable/resources/sys/projects/api_keys.py @@ -8,10 +8,7 @@ import httpx from ...._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ...._utils import ( - maybe_transform, - async_maybe_transform, -) +from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import ( diff --git a/src/asktable/resources/sys/projects/projects.py b/src/asktable/resources/sys/projects/projects.py index 5d91c1ed..eb8edeb3 100644 --- a/src/asktable/resources/sys/projects/projects.py +++ b/src/asktable/resources/sys/projects/projects.py @@ -15,10 +15,7 @@ AsyncAPIKeysResourceWithStreamingResponse, ) from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ...._utils import ( - maybe_transform, - async_maybe_transform, -) +from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import ( diff --git a/src/asktable/resources/trainings.py b/src/asktable/resources/trainings.py index 0a7f0922..6812639c 100644 --- a/src/asktable/resources/trainings.py +++ b/src/asktable/resources/trainings.py @@ -8,10 +8,7 @@ from ..types import training_list_params, training_create_params, training_delete_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import ( - maybe_transform, - async_maybe_transform, -) +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( From 12bba1b329d0149f1b8065c983efbddda6a1a1d1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 03:02:11 +0000 Subject: [PATCH 10/38] chore(internal): fix list file params --- src/asktable/_utils/_utils.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/asktable/_utils/_utils.py b/src/asktable/_utils/_utils.py index e5811bba..ea3cf3f2 100644 --- a/src/asktable/_utils/_utils.py +++ b/src/asktable/_utils/_utils.py @@ -72,8 +72,16 @@ def _extract_items( from .._files import assert_is_file_content # We have exhausted the path, return the entry we found. - assert_is_file_content(obj, key=flattened_key) assert flattened_key is not None + + if is_list(obj): + files: list[tuple[str, FileTypes]] = [] + for entry in obj: + assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "") + files.append((flattened_key + "[]", cast(FileTypes, entry))) + return files + + assert_is_file_content(obj, key=flattened_key) return [(flattened_key, cast(FileTypes, obj))] index += 1 From af64ff050f75fae9c6368c6c0d105197f227397c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 03:02:40 +0000 Subject: [PATCH 11/38] chore(internal): refactor retries to not use recursion --- src/asktable/_base_client.py | 414 +++++++++++++++-------------------- 1 file changed, 175 insertions(+), 239 deletions(-) diff --git a/src/asktable/_base_client.py b/src/asktable/_base_client.py index 5944509e..5d4a145a 100644 --- a/src/asktable/_base_client.py +++ b/src/asktable/_base_client.py @@ -437,8 +437,7 @@ def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0 headers = httpx.Headers(headers_dict) idempotency_header = self._idempotency_header - if idempotency_header and options.method.lower() != "get" and idempotency_header not in headers: - options.idempotency_key = options.idempotency_key or self._idempotency_key() + if idempotency_header and options.idempotency_key and idempotency_header not in headers: headers[idempotency_header] = options.idempotency_key # Don't set these headers if they were already set or removed by the caller. We check @@ -903,7 +902,6 @@ def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, - remaining_retries: Optional[int] = None, *, stream: Literal[True], stream_cls: Type[_StreamT], @@ -914,7 +912,6 @@ def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, - remaining_retries: Optional[int] = None, *, stream: Literal[False] = False, ) -> ResponseT: ... @@ -924,7 +921,6 @@ def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, - remaining_retries: Optional[int] = None, *, stream: bool = False, stream_cls: Type[_StreamT] | None = None, @@ -934,125 +930,109 @@ def request( self, cast_to: Type[ResponseT], options: FinalRequestOptions, - remaining_retries: Optional[int] = None, *, stream: bool = False, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: - if remaining_retries is not None: - retries_taken = options.get_max_retries(self.max_retries) - remaining_retries - else: - retries_taken = 0 - - return self._request( - cast_to=cast_to, - options=options, - stream=stream, - stream_cls=stream_cls, - retries_taken=retries_taken, - ) + cast_to = self._maybe_override_cast_to(cast_to, options) - def _request( - self, - *, - cast_to: Type[ResponseT], - options: FinalRequestOptions, - retries_taken: int, - stream: bool, - stream_cls: type[_StreamT] | None, - ) -> ResponseT | _StreamT: # create a copy of the options we were given so that if the # options are mutated later & we then retry, the retries are # given the original options input_options = model_copy(options) - - cast_to = self._maybe_override_cast_to(cast_to, options) - options = self._prepare_options(options) - - remaining_retries = options.get_max_retries(self.max_retries) - retries_taken - request = self._build_request(options, retries_taken=retries_taken) - self._prepare_request(request) - - if options.idempotency_key: + if input_options.idempotency_key is None and input_options.method.lower() != "get": # ensure the idempotency key is reused between requests - input_options.idempotency_key = options.idempotency_key + input_options.idempotency_key = self._idempotency_key() - kwargs: HttpxSendArgs = {} - if self.custom_auth is not None: - kwargs["auth"] = self.custom_auth + response: httpx.Response | None = None + max_retries = input_options.get_max_retries(self.max_retries) - log.debug("Sending HTTP Request: %s %s", request.method, request.url) + retries_taken = 0 + for retries_taken in range(max_retries + 1): + options = model_copy(input_options) + options = self._prepare_options(options) - try: - response = self._client.send( - request, - stream=stream or self._should_stream_response_body(request=request), - **kwargs, - ) - except httpx.TimeoutException as err: - log.debug("Encountered httpx.TimeoutException", exc_info=True) + remaining_retries = max_retries - retries_taken + request = self._build_request(options, retries_taken=retries_taken) + self._prepare_request(request) - if remaining_retries > 0: - return self._retry_request( - input_options, - cast_to, - retries_taken=retries_taken, - stream=stream, - stream_cls=stream_cls, - response_headers=None, - ) + kwargs: HttpxSendArgs = {} + if self.custom_auth is not None: + kwargs["auth"] = self.custom_auth - log.debug("Raising timeout error") - raise APITimeoutError(request=request) from err - except Exception as err: - log.debug("Encountered Exception", exc_info=True) + log.debug("Sending HTTP Request: %s %s", request.method, request.url) - if remaining_retries > 0: - return self._retry_request( - input_options, - cast_to, - retries_taken=retries_taken, - stream=stream, - stream_cls=stream_cls, - response_headers=None, + response = None + try: + response = self._client.send( + request, + stream=stream or self._should_stream_response_body(request=request), + **kwargs, ) + except httpx.TimeoutException as err: + log.debug("Encountered httpx.TimeoutException", exc_info=True) + + if remaining_retries > 0: + self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising timeout error") + raise APITimeoutError(request=request) from err + except Exception as err: + log.debug("Encountered Exception", exc_info=True) + + if remaining_retries > 0: + self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising connection error") + raise APIConnectionError(request=request) from err + + log.debug( + 'HTTP Response: %s %s "%i %s" %s', + request.method, + request.url, + response.status_code, + response.reason_phrase, + response.headers, + ) - log.debug("Raising connection error") - raise APIConnectionError(request=request) from err - - log.debug( - 'HTTP Response: %s %s "%i %s" %s', - request.method, - request.url, - response.status_code, - response.reason_phrase, - response.headers, - ) + try: + response.raise_for_status() + except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code + log.debug("Encountered httpx.HTTPStatusError", exc_info=True) + + if remaining_retries > 0 and self._should_retry(err.response): + err.response.close() + self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=response, + ) + continue - try: - response.raise_for_status() - except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code - log.debug("Encountered httpx.HTTPStatusError", exc_info=True) - - if remaining_retries > 0 and self._should_retry(err.response): - err.response.close() - return self._retry_request( - input_options, - cast_to, - retries_taken=retries_taken, - response_headers=err.response.headers, - stream=stream, - stream_cls=stream_cls, - ) + # If the response is streamed then we need to explicitly read the response + # to completion before attempting to access the response text. + if not err.response.is_closed: + err.response.read() - # If the response is streamed then we need to explicitly read the response - # to completion before attempting to access the response text. - if not err.response.is_closed: - err.response.read() + log.debug("Re-raising status error") + raise self._make_status_error_from_response(err.response) from None - log.debug("Re-raising status error") - raise self._make_status_error_from_response(err.response) from None + break + assert response is not None, "could not resolve response (should never happen)" return self._process_response( cast_to=cast_to, options=options, @@ -1062,37 +1042,20 @@ def _request( retries_taken=retries_taken, ) - def _retry_request( - self, - options: FinalRequestOptions, - cast_to: Type[ResponseT], - *, - retries_taken: int, - response_headers: httpx.Headers | None, - stream: bool, - stream_cls: type[_StreamT] | None, - ) -> ResponseT | _StreamT: - remaining_retries = options.get_max_retries(self.max_retries) - retries_taken + def _sleep_for_retry( + self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None + ) -> None: + remaining_retries = max_retries - retries_taken if remaining_retries == 1: log.debug("1 retry left") else: log.debug("%i retries left", remaining_retries) - timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers) + timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None) log.info("Retrying request to %s in %f seconds", options.url, timeout) - # In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a - # different thread if necessary. time.sleep(timeout) - return self._request( - options=options, - cast_to=cast_to, - retries_taken=retries_taken + 1, - stream=stream, - stream_cls=stream_cls, - ) - def _process_response( self, *, @@ -1436,7 +1399,6 @@ async def request( options: FinalRequestOptions, *, stream: Literal[False] = False, - remaining_retries: Optional[int] = None, ) -> ResponseT: ... @overload @@ -1447,7 +1409,6 @@ async def request( *, stream: Literal[True], stream_cls: type[_AsyncStreamT], - remaining_retries: Optional[int] = None, ) -> _AsyncStreamT: ... @overload @@ -1458,7 +1419,6 @@ async def request( *, stream: bool, stream_cls: type[_AsyncStreamT] | None = None, - remaining_retries: Optional[int] = None, ) -> ResponseT | _AsyncStreamT: ... async def request( @@ -1468,120 +1428,111 @@ async def request( *, stream: bool = False, stream_cls: type[_AsyncStreamT] | None = None, - remaining_retries: Optional[int] = None, - ) -> ResponseT | _AsyncStreamT: - if remaining_retries is not None: - retries_taken = options.get_max_retries(self.max_retries) - remaining_retries - else: - retries_taken = 0 - - return await self._request( - cast_to=cast_to, - options=options, - stream=stream, - stream_cls=stream_cls, - retries_taken=retries_taken, - ) - - async def _request( - self, - cast_to: Type[ResponseT], - options: FinalRequestOptions, - *, - stream: bool, - stream_cls: type[_AsyncStreamT] | None, - retries_taken: int, ) -> ResponseT | _AsyncStreamT: if self._platform is None: # `get_platform` can make blocking IO calls so we # execute it earlier while we are in an async context self._platform = await asyncify(get_platform)() + cast_to = self._maybe_override_cast_to(cast_to, options) + # create a copy of the options we were given so that if the # options are mutated later & we then retry, the retries are # given the original options input_options = model_copy(options) - - cast_to = self._maybe_override_cast_to(cast_to, options) - options = await self._prepare_options(options) - - remaining_retries = options.get_max_retries(self.max_retries) - retries_taken - request = self._build_request(options, retries_taken=retries_taken) - await self._prepare_request(request) - - if options.idempotency_key: + if input_options.idempotency_key is None and input_options.method.lower() != "get": # ensure the idempotency key is reused between requests - input_options.idempotency_key = options.idempotency_key + input_options.idempotency_key = self._idempotency_key() - kwargs: HttpxSendArgs = {} - if self.custom_auth is not None: - kwargs["auth"] = self.custom_auth + response: httpx.Response | None = None + max_retries = input_options.get_max_retries(self.max_retries) - try: - response = await self._client.send( - request, - stream=stream or self._should_stream_response_body(request=request), - **kwargs, - ) - except httpx.TimeoutException as err: - log.debug("Encountered httpx.TimeoutException", exc_info=True) + retries_taken = 0 + for retries_taken in range(max_retries + 1): + options = model_copy(input_options) + options = await self._prepare_options(options) - if remaining_retries > 0: - return await self._retry_request( - input_options, - cast_to, - retries_taken=retries_taken, - stream=stream, - stream_cls=stream_cls, - response_headers=None, - ) + remaining_retries = max_retries - retries_taken + request = self._build_request(options, retries_taken=retries_taken) + await self._prepare_request(request) - log.debug("Raising timeout error") - raise APITimeoutError(request=request) from err - except Exception as err: - log.debug("Encountered Exception", exc_info=True) + kwargs: HttpxSendArgs = {} + if self.custom_auth is not None: + kwargs["auth"] = self.custom_auth - if remaining_retries > 0: - return await self._retry_request( - input_options, - cast_to, - retries_taken=retries_taken, - stream=stream, - stream_cls=stream_cls, - response_headers=None, - ) + log.debug("Sending HTTP Request: %s %s", request.method, request.url) - log.debug("Raising connection error") - raise APIConnectionError(request=request) from err + response = None + try: + response = await self._client.send( + request, + stream=stream or self._should_stream_response_body(request=request), + **kwargs, + ) + except httpx.TimeoutException as err: + log.debug("Encountered httpx.TimeoutException", exc_info=True) + + if remaining_retries > 0: + await self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising timeout error") + raise APITimeoutError(request=request) from err + except Exception as err: + log.debug("Encountered Exception", exc_info=True) + + if remaining_retries > 0: + await self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising connection error") + raise APIConnectionError(request=request) from err + + log.debug( + 'HTTP Response: %s %s "%i %s" %s', + request.method, + request.url, + response.status_code, + response.reason_phrase, + response.headers, + ) - log.debug( - 'HTTP Request: %s %s "%i %s"', request.method, request.url, response.status_code, response.reason_phrase - ) + try: + response.raise_for_status() + except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code + log.debug("Encountered httpx.HTTPStatusError", exc_info=True) + + if remaining_retries > 0 and self._should_retry(err.response): + await err.response.aclose() + await self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=response, + ) + continue - try: - response.raise_for_status() - except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code - log.debug("Encountered httpx.HTTPStatusError", exc_info=True) - - if remaining_retries > 0 and self._should_retry(err.response): - await err.response.aclose() - return await self._retry_request( - input_options, - cast_to, - retries_taken=retries_taken, - response_headers=err.response.headers, - stream=stream, - stream_cls=stream_cls, - ) + # If the response is streamed then we need to explicitly read the response + # to completion before attempting to access the response text. + if not err.response.is_closed: + await err.response.aread() - # If the response is streamed then we need to explicitly read the response - # to completion before attempting to access the response text. - if not err.response.is_closed: - await err.response.aread() + log.debug("Re-raising status error") + raise self._make_status_error_from_response(err.response) from None - log.debug("Re-raising status error") - raise self._make_status_error_from_response(err.response) from None + break + assert response is not None, "could not resolve response (should never happen)" return await self._process_response( cast_to=cast_to, options=options, @@ -1591,35 +1542,20 @@ async def _request( retries_taken=retries_taken, ) - async def _retry_request( - self, - options: FinalRequestOptions, - cast_to: Type[ResponseT], - *, - retries_taken: int, - response_headers: httpx.Headers | None, - stream: bool, - stream_cls: type[_AsyncStreamT] | None, - ) -> ResponseT | _AsyncStreamT: - remaining_retries = options.get_max_retries(self.max_retries) - retries_taken + async def _sleep_for_retry( + self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None + ) -> None: + remaining_retries = max_retries - retries_taken if remaining_retries == 1: log.debug("1 retry left") else: log.debug("%i retries left", remaining_retries) - timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers) + timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None) log.info("Retrying request to %s in %f seconds", options.url, timeout) await anyio.sleep(timeout) - return await self._request( - options=options, - cast_to=cast_to, - retries_taken=retries_taken + 1, - stream=stream, - stream_cls=stream_cls, - ) - async def _process_response( self, *, From c16373dba54d24f705650aa38d3b4c1a772f23ff Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 03:03:27 +0000 Subject: [PATCH 12/38] fix(pydantic v1): more robust ModelField.annotation check --- src/asktable/_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/asktable/_models.py b/src/asktable/_models.py index 58b9263e..798956f1 100644 --- a/src/asktable/_models.py +++ b/src/asktable/_models.py @@ -626,8 +626,8 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, # Note: if one variant defines an alias then they all should discriminator_alias = field_info.alias - if field_info.annotation and is_literal_type(field_info.annotation): - for entry in get_args(field_info.annotation): + if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation): + for entry in get_args(annotation): if isinstance(entry, str): mapping[entry] = variant From 317b682b9de2a8803f8d2be7be7a9ed8ad1e961c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 09:18:58 +0000 Subject: [PATCH 13/38] feat(api): api update --- .stats.yml | 4 ++-- src/asktable/resources/business_glossary.py | 8 ++++++++ src/asktable/resources/policies.py | 8 ++++---- src/asktable/resources/roles.py | 8 ++++---- .../types/business_glossary_update_params.py | 3 +++ src/asktable/types/policy_create_params.py | 2 +- src/asktable/types/policy_update_params.py | 2 +- src/asktable/types/role.py | 1 - src/asktable/types/role_create_params.py | 2 +- src/asktable/types/role_update_params.py | 2 +- src/asktable/types/shared/policy.py | 1 - src/asktable/types/training_create_params.py | 3 +++ .../types/training_create_response.py | 3 +++ src/asktable/types/training_list_response.py | 3 +++ tests/api_resources/test_business_glossary.py | 2 ++ tests/api_resources/test_policies.py | 20 +++++++++---------- tests/api_resources/test_roles.py | 20 +++++++++---------- 17 files changed, 56 insertions(+), 36 deletions(-) diff --git a/.stats.yml b/.stats.yml index a75fdfa0..abc6ff93 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-5f188889fe648ea83d57911900fe61825d9d7d1446fce966ffca7a9bbe2e3079.yml -openapi_spec_hash: 42af219a138819686969b60410be0cb6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-0648628a17a22c2764d0bd87e1664a7687aa28186a191228c9cdfe7dc9f99120.yml +openapi_spec_hash: 58c39f097e0b9fd6827e5087f7c76c76 config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/resources/business_glossary.py b/src/asktable/resources/business_glossary.py index 7416e3bc..2eed15db 100644 --- a/src/asktable/resources/business_glossary.py +++ b/src/asktable/resources/business_glossary.py @@ -115,6 +115,7 @@ def update( self, entry_id: str, *, + active: Optional[bool] | NotGiven = NOT_GIVEN, aliases: Optional[List[str]] | NotGiven = NOT_GIVEN, definition: Optional[str] | NotGiven = NOT_GIVEN, payload: Optional[object] | NotGiven = NOT_GIVEN, @@ -130,6 +131,8 @@ def update( 更新业务术语 Args: + active: 业务术语是否生效 + aliases: 业务术语同义词 definition: 业务术语定义 @@ -152,6 +155,7 @@ def update( f"/v1/business-glossary/{entry_id}", body=maybe_transform( { + "active": active, "aliases": aliases, "definition": definition, "payload": payload, @@ -339,6 +343,7 @@ async def update( self, entry_id: str, *, + active: Optional[bool] | NotGiven = NOT_GIVEN, aliases: Optional[List[str]] | NotGiven = NOT_GIVEN, definition: Optional[str] | NotGiven = NOT_GIVEN, payload: Optional[object] | NotGiven = NOT_GIVEN, @@ -354,6 +359,8 @@ async def update( 更新业务术语 Args: + active: 业务术语是否生效 + aliases: 业务术语同义词 definition: 业务术语定义 @@ -376,6 +383,7 @@ async def update( f"/v1/business-glossary/{entry_id}", body=await async_maybe_transform( { + "active": active, "aliases": aliases, "definition": definition, "payload": payload, diff --git a/src/asktable/resources/policies.py b/src/asktable/resources/policies.py index 3c8c9b28..fc27f2c4 100644 --- a/src/asktable/resources/policies.py +++ b/src/asktable/resources/policies.py @@ -64,7 +64,7 @@ def create( Args: dataset_config: 数据集配置 - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 permission: 权限 @@ -145,7 +145,7 @@ def update( Args: dataset_config: 数据集配置 - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 permission: 权限 @@ -304,7 +304,7 @@ async def create( Args: dataset_config: 数据集配置 - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 permission: 权限 @@ -385,7 +385,7 @@ async def update( Args: dataset_config: 数据集配置 - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 permission: 权限 diff --git a/src/asktable/resources/roles.py b/src/asktable/resources/roles.py index ec37d440..c05f9a91 100644 --- a/src/asktable/resources/roles.py +++ b/src/asktable/resources/roles.py @@ -61,7 +61,7 @@ def create( 创建一个新的角色 Args: - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 policy_ids: 策略列表。注意:如果为空或者不传则不绑定策略 @@ -138,7 +138,7 @@ def update( 更新某个角色 Args: - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 policy_ids: 策略列表。注意:如果为空或者不传则不绑定策略 @@ -374,7 +374,7 @@ async def create( 创建一个新的角色 Args: - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 policy_ids: 策略列表。注意:如果为空或者不传则不绑定策略 @@ -451,7 +451,7 @@ async def update( 更新某个角色 Args: - name: 名称,小写英文字母,数字和下划线组合,不超过 64 个字符 + name: 名称 policy_ids: 策略列表。注意:如果为空或者不传则不绑定策略 diff --git a/src/asktable/types/business_glossary_update_params.py b/src/asktable/types/business_glossary_update_params.py index ea78c5db..89bad224 100644 --- a/src/asktable/types/business_glossary_update_params.py +++ b/src/asktable/types/business_glossary_update_params.py @@ -9,6 +9,9 @@ class BusinessGlossaryUpdateParams(TypedDict, total=False): + active: Optional[bool] + """业务术语是否生效""" + aliases: Optional[List[str]] """业务术语同义词""" diff --git a/src/asktable/types/policy_create_params.py b/src/asktable/types/policy_create_params.py index 3c53d086..808408d7 100644 --- a/src/asktable/types/policy_create_params.py +++ b/src/asktable/types/policy_create_params.py @@ -13,7 +13,7 @@ class PolicyCreateParams(TypedDict, total=False): """数据集配置""" name: Required[str] - """名称,小写英文字母,数字和下划线组合,不超过 64 个字符""" + """名称""" permission: Required[Literal["allow", "deny"]] """权限""" diff --git a/src/asktable/types/policy_update_params.py b/src/asktable/types/policy_update_params.py index dfe7e6e4..26d949bf 100644 --- a/src/asktable/types/policy_update_params.py +++ b/src/asktable/types/policy_update_params.py @@ -13,7 +13,7 @@ class PolicyUpdateParams(TypedDict, total=False): """数据集配置""" name: Optional[str] - """名称,小写英文字母,数字和下划线组合,不超过 64 个字符""" + """名称""" permission: Optional[Literal["allow", "deny"]] """权限""" diff --git a/src/asktable/types/role.py b/src/asktable/types/role.py index 19e7fad9..5683f5c5 100644 --- a/src/asktable/types/role.py +++ b/src/asktable/types/role.py @@ -18,7 +18,6 @@ class Role(BaseModel): modified_at: datetime name: str - """名称,小写英文字母,数字和下划线组合,不超过 64 个字符""" project_id: str diff --git a/src/asktable/types/role_create_params.py b/src/asktable/types/role_create_params.py index 4b4dab67..4750a3e0 100644 --- a/src/asktable/types/role_create_params.py +++ b/src/asktable/types/role_create_params.py @@ -10,7 +10,7 @@ class RoleCreateParams(TypedDict, total=False): name: Required[str] - """名称,小写英文字母,数字和下划线组合,不超过 64 个字符""" + """名称""" policy_ids: Optional[List[str]] """策略列表。注意:如果为空或者不传则不绑定策略""" diff --git a/src/asktable/types/role_update_params.py b/src/asktable/types/role_update_params.py index 8495f380..6cb3bb99 100644 --- a/src/asktable/types/role_update_params.py +++ b/src/asktable/types/role_update_params.py @@ -10,7 +10,7 @@ class RoleUpdateParams(TypedDict, total=False): name: Optional[str] - """名称,小写英文字母,数字和下划线组合,不超过 64 个字符""" + """名称""" policy_ids: Optional[List[str]] """策略列表。注意:如果为空或者不传则不绑定策略""" diff --git a/src/asktable/types/shared/policy.py b/src/asktable/types/shared/policy.py index d87698e2..0fd1b6db 100644 --- a/src/asktable/types/shared/policy.py +++ b/src/asktable/types/shared/policy.py @@ -50,7 +50,6 @@ class Policy(BaseModel): modified_at: datetime name: str - """名称,小写英文字母,数字和下划线组合,不超过 64 个字符""" permission: Literal["allow", "deny"] """权限""" diff --git a/src/asktable/types/training_create_params.py b/src/asktable/types/training_create_params.py index 9e7f2a70..f8dec4df 100644 --- a/src/asktable/types/training_create_params.py +++ b/src/asktable/types/training_create_params.py @@ -22,6 +22,9 @@ class Body(TypedDict, total=False): sql: Required[str] """用户问题对应的 SQL""" + active: bool + """是否启用""" + chat_id: Optional[str] """聊天 ID""" diff --git a/src/asktable/types/training_create_response.py b/src/asktable/types/training_create_response.py index 97788641..1300e978 100644 --- a/src/asktable/types/training_create_response.py +++ b/src/asktable/types/training_create_response.py @@ -30,6 +30,9 @@ class TrainingCreateResponseItem(BaseModel): sql: str """用户问题对应的 SQL""" + active: Optional[bool] = None + """是否启用""" + chat_id: Optional[str] = None """聊天 ID""" diff --git a/src/asktable/types/training_list_response.py b/src/asktable/types/training_list_response.py index 54e63cb5..d9868dab 100644 --- a/src/asktable/types/training_list_response.py +++ b/src/asktable/types/training_list_response.py @@ -30,6 +30,9 @@ class TrainingListResponse(BaseModel): sql: str """用户问题对应的 SQL""" + active: Optional[bool] = None + """是否启用""" + chat_id: Optional[str] = None """聊天 ID""" diff --git a/tests/api_resources/test_business_glossary.py b/tests/api_resources/test_business_glossary.py index ede95e7a..744c497e 100644 --- a/tests/api_resources/test_business_glossary.py +++ b/tests/api_resources/test_business_glossary.py @@ -117,6 +117,7 @@ def test_method_update(self, client: Asktable) -> None: def test_method_update_with_all_params(self, client: Asktable) -> None: business_glossary = client.business_glossary.update( entry_id="entry_id", + active=True, aliases=["string"], definition="definition", payload={}, @@ -326,6 +327,7 @@ async def test_method_update(self, async_client: AsyncAsktable) -> None: async def test_method_update_with_all_params(self, async_client: AsyncAsktable) -> None: business_glossary = await async_client.business_glossary.update( entry_id="entry_id", + active=True, aliases=["string"], definition="definition", payload={}, diff --git a/tests/api_resources/test_policies.py b/tests/api_resources/test_policies.py index 1c03eafa..0323ef89 100644 --- a/tests/api_resources/test_policies.py +++ b/tests/api_resources/test_policies.py @@ -22,7 +22,7 @@ class TestPolicies: def test_method_create(self, client: Asktable) -> None: policy = client.policies.create( dataset_config={"datasource_ids": ["string"]}, - name="name", + name="policy_name", permission="allow", ) assert_matches_type(Policy, policy, path=["response"]) @@ -47,7 +47,7 @@ def test_method_create_with_all_params(self, client: Asktable) -> None: ], }, }, - name="name", + name="policy_name", permission="allow", ) assert_matches_type(Policy, policy, path=["response"]) @@ -56,7 +56,7 @@ def test_method_create_with_all_params(self, client: Asktable) -> None: def test_raw_response_create(self, client: Asktable) -> None: response = client.policies.with_raw_response.create( dataset_config={"datasource_ids": ["string"]}, - name="name", + name="policy_name", permission="allow", ) @@ -69,7 +69,7 @@ def test_raw_response_create(self, client: Asktable) -> None: def test_streaming_response_create(self, client: Asktable) -> None: with client.policies.with_streaming_response.create( dataset_config={"datasource_ids": ["string"]}, - name="name", + name="policy_name", permission="allow", ) as response: assert not response.is_closed @@ -183,7 +183,7 @@ def test_method_update_with_all_params(self, client: Asktable) -> None: ], }, }, - name="name", + name="policy_name", permission="allow", ) assert_matches_type(Policy, policy, path=["response"]) @@ -300,7 +300,7 @@ class TestAsyncPolicies: async def test_method_create(self, async_client: AsyncAsktable) -> None: policy = await async_client.policies.create( dataset_config={"datasource_ids": ["string"]}, - name="name", + name="policy_name", permission="allow", ) assert_matches_type(Policy, policy, path=["response"]) @@ -325,7 +325,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncAsktable) ], }, }, - name="name", + name="policy_name", permission="allow", ) assert_matches_type(Policy, policy, path=["response"]) @@ -334,7 +334,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncAsktable) async def test_raw_response_create(self, async_client: AsyncAsktable) -> None: response = await async_client.policies.with_raw_response.create( dataset_config={"datasource_ids": ["string"]}, - name="name", + name="policy_name", permission="allow", ) @@ -347,7 +347,7 @@ async def test_raw_response_create(self, async_client: AsyncAsktable) -> None: async def test_streaming_response_create(self, async_client: AsyncAsktable) -> None: async with async_client.policies.with_streaming_response.create( dataset_config={"datasource_ids": ["string"]}, - name="name", + name="policy_name", permission="allow", ) as response: assert not response.is_closed @@ -461,7 +461,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncAsktable) ], }, }, - name="name", + name="policy_name", permission="allow", ) assert_matches_type(Policy, policy, path=["response"]) diff --git a/tests/api_resources/test_roles.py b/tests/api_resources/test_roles.py index 8f83b821..37f39920 100644 --- a/tests/api_resources/test_roles.py +++ b/tests/api_resources/test_roles.py @@ -24,14 +24,14 @@ class TestRoles: @parametrize def test_method_create(self, client: Asktable) -> None: role = client.roles.create( - name="name", + name="role_name", ) assert_matches_type(Role, role, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: Asktable) -> None: role = client.roles.create( - name="name", + name="role_name", policy_ids=["policy_6uOnay1xDNsxLoHmCGf3", "policy_6uOnay1xDNsxLoHmCGf2"], ) assert_matches_type(Role, role, path=["response"]) @@ -39,7 +39,7 @@ def test_method_create_with_all_params(self, client: Asktable) -> None: @parametrize def test_raw_response_create(self, client: Asktable) -> None: response = client.roles.with_raw_response.create( - name="name", + name="role_name", ) assert response.is_closed is True @@ -50,7 +50,7 @@ def test_raw_response_create(self, client: Asktable) -> None: @parametrize def test_streaming_response_create(self, client: Asktable) -> None: with client.roles.with_streaming_response.create( - name="name", + name="role_name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -109,7 +109,7 @@ def test_method_update(self, client: Asktable) -> None: def test_method_update_with_all_params(self, client: Asktable) -> None: role = client.roles.update( role_id="role_id", - name="name", + name="role_name", policy_ids=["policy_6uOnay1xDNsxLoHmCGf3", "policy_6uOnay1xDNsxLoHmCGf2"], ) assert_matches_type(Role, role, path=["response"]) @@ -310,14 +310,14 @@ class TestAsyncRoles: @parametrize async def test_method_create(self, async_client: AsyncAsktable) -> None: role = await async_client.roles.create( - name="name", + name="role_name", ) assert_matches_type(Role, role, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncAsktable) -> None: role = await async_client.roles.create( - name="name", + name="role_name", policy_ids=["policy_6uOnay1xDNsxLoHmCGf3", "policy_6uOnay1xDNsxLoHmCGf2"], ) assert_matches_type(Role, role, path=["response"]) @@ -325,7 +325,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncAsktable) @parametrize async def test_raw_response_create(self, async_client: AsyncAsktable) -> None: response = await async_client.roles.with_raw_response.create( - name="name", + name="role_name", ) assert response.is_closed is True @@ -336,7 +336,7 @@ async def test_raw_response_create(self, async_client: AsyncAsktable) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncAsktable) -> None: async with async_client.roles.with_streaming_response.create( - name="name", + name="role_name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -395,7 +395,7 @@ async def test_method_update(self, async_client: AsyncAsktable) -> None: async def test_method_update_with_all_params(self, async_client: AsyncAsktable) -> None: role = await async_client.roles.update( role_id="role_id", - name="name", + name="role_name", policy_ids=["policy_6uOnay1xDNsxLoHmCGf3", "policy_6uOnay1xDNsxLoHmCGf2"], ) assert_matches_type(Role, role, path=["response"]) From 1f83169570f13ba1ede9c92a23e610018d39f8e0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 24 Apr 2025 02:24:51 +0000 Subject: [PATCH 14/38] chore(internal): minor formatting changes --- src/asktable/types/file_ask_response.py | 1 - src/asktable/types/polish_create_response.py | 1 - src/asktable/types/sys/model_group.py | 1 - 3 files changed, 3 deletions(-) diff --git a/src/asktable/types/file_ask_response.py b/src/asktable/types/file_ask_response.py index a870ad8c..bbf7f554 100644 --- a/src/asktable/types/file_ask_response.py +++ b/src/asktable/types/file_ask_response.py @@ -1,6 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - from .._models import BaseModel from .datasource import Datasource from .answer_response import AnswerResponse diff --git a/src/asktable/types/polish_create_response.py b/src/asktable/types/polish_create_response.py index b92795cc..888e42c3 100644 --- a/src/asktable/types/polish_create_response.py +++ b/src/asktable/types/polish_create_response.py @@ -1,6 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - from .._models import BaseModel __all__ = ["PolishCreateResponse"] diff --git a/src/asktable/types/sys/model_group.py b/src/asktable/types/sys/model_group.py index 8d700122..d37d6270 100644 --- a/src/asktable/types/sys/model_group.py +++ b/src/asktable/types/sys/model_group.py @@ -1,6 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - from ..._models import BaseModel __all__ = ["ModelGroup"] From 3719d1bf1db482d5f08368b6162d67c878e48369 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 24 Apr 2025 02:25:21 +0000 Subject: [PATCH 15/38] chore(internal): codegen related update --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/publish-pypi.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04b083ca..33820422 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,18 +1,18 @@ name: CI on: push: - branches: - - main - pull_request: - branches: - - main - - next + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: timeout-minutes: 10 name: lint - runs-on: ubuntu-latest + runs-on: depot-ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -33,7 +33,7 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ubuntu-latest + runs-on: depot-ubuntu-24.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 188841d6..0b75a3cd 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -11,7 +11,7 @@ on: jobs: publish: name: publish - runs-on: ubuntu-latest + runs-on: depot-ubuntu-24.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 1800bc5b..712e041a 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -8,7 +8,7 @@ on: jobs: release_doctor: name: release doctor - runs-on: ubuntu-latest + runs-on: depot-ubuntu-24.04 if: github.repository == 'DataMini/asktable-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: From 6c155eb595e7227c769e953a5040b577f85f494c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 24 Apr 2025 02:25:50 +0000 Subject: [PATCH 16/38] chore(ci): only use depot for staging repos --- .github/workflows/ci.yml | 4 ++-- .github/workflows/publish-pypi.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33820422..d604b7e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: depot-ubuntu-24.04 + runs-on: ${{ github.repository == 'stainless-sdks/asktable-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - uses: actions/checkout@v4 @@ -33,7 +33,7 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: depot-ubuntu-24.04 + runs-on: ${{ github.repository == 'stainless-sdks/asktable-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 0b75a3cd..188841d6 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -11,7 +11,7 @@ on: jobs: publish: name: publish - runs-on: depot-ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 712e041a..1800bc5b 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -8,7 +8,7 @@ on: jobs: release_doctor: name: release doctor - runs-on: depot-ubuntu-24.04 + runs-on: ubuntu-latest if: github.repository == 'DataMini/asktable-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: From 3bff15dcccae660478bd3e6a30aa609e4bcc186f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 24 Apr 2025 02:27:22 +0000 Subject: [PATCH 17/38] chore: broadly detect json family of content-type headers --- src/asktable/_response.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/asktable/_response.py b/src/asktable/_response.py index e7528b55..0c91a6f9 100644 --- a/src/asktable/_response.py +++ b/src/asktable/_response.py @@ -233,7 +233,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: # split is required to handle cases where additional information is included # in the response, e.g. application/json; charset=utf-8 content_type, *_ = response.headers.get("content-type", "*").split(";") - if content_type != "application/json": + if not content_type.endswith("json"): if is_basemodel(cast_to): try: data = response.json() From d281683e91508252a9acff201a1f45efc23fdb0b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:19:16 +0000 Subject: [PATCH 18/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index abc6ff93..b1f3432e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-0648628a17a22c2764d0bd87e1664a7687aa28186a191228c9cdfe7dc9f99120.yml -openapi_spec_hash: 58c39f097e0b9fd6827e5087f7c76c76 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-6a550adde09a0b42a44b98e83c45064687dc1d7540789f8d0fabb66f2ae84e39.yml +openapi_spec_hash: 1412ef9cabd0756e983e400f6fa3933c config_hash: a572ab842ea60ce13f1d1a1358440cbe From 8cfc98987196f71dc9b1ac788a66e7fb7a6b62c9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 11:19:33 +0000 Subject: [PATCH 19/38] feat(api): api update --- .stats.yml | 4 ++-- src/asktable/types/business_glossary_create_params.py | 3 +++ src/asktable/types/entry.py | 3 +++ src/asktable/types/entry_with_definition.py | 3 +++ src/asktable/types/policy_create_params.py | 3 +++ src/asktable/types/policy_update_params.py | 3 +++ src/asktable/types/training_create_response.py | 4 ++++ src/asktable/types/training_list_response.py | 4 ++++ 8 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b1f3432e..b5bbb25e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-6a550adde09a0b42a44b98e83c45064687dc1d7540789f8d0fabb66f2ae84e39.yml -openapi_spec_hash: 1412ef9cabd0756e983e400f6fa3933c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-45d2602f83b88dbbc665744d25d5d9785032f68fcbed81c798ae70ed4ab28355.yml +openapi_spec_hash: 166267ae1e2f2c0505fb591b83400cbc config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/types/business_glossary_create_params.py b/src/asktable/types/business_glossary_create_params.py index 08220cef..e9f3d42d 100644 --- a/src/asktable/types/business_glossary_create_params.py +++ b/src/asktable/types/business_glossary_create_params.py @@ -19,6 +19,9 @@ class Body(TypedDict, total=False): term: Required[str] """业务术语""" + active: bool + """业务术语是否生效""" + aliases: Optional[List[str]] """业务术语同义词""" diff --git a/src/asktable/types/entry.py b/src/asktable/types/entry.py index d493a3ef..a4140a5d 100644 --- a/src/asktable/types/entry.py +++ b/src/asktable/types/entry.py @@ -24,6 +24,9 @@ class Entry(BaseModel): term: str """业务术语""" + active: Optional[bool] = None + """业务术语是否生效""" + aliases: Optional[List[str]] = None """业务术语同义词""" diff --git a/src/asktable/types/entry_with_definition.py b/src/asktable/types/entry_with_definition.py index d7011a9e..9b76baff 100644 --- a/src/asktable/types/entry_with_definition.py +++ b/src/asktable/types/entry_with_definition.py @@ -27,6 +27,9 @@ class EntryWithDefinition(BaseModel): term: str """业务术语""" + active: Optional[bool] = None + """业务术语是否生效""" + aliases: Optional[List[str]] = None """业务术语同义词""" diff --git a/src/asktable/types/policy_create_params.py b/src/asktable/types/policy_create_params.py index 808408d7..9630207c 100644 --- a/src/asktable/types/policy_create_params.py +++ b/src/asktable/types/policy_create_params.py @@ -87,4 +87,7 @@ class DatasetConfig(TypedDict, total=False): - 暂不支持对字段使用函数计算,比如不支持 "YEAR(public.user.created_at) = 2023" - 暂不支持多个过滤条件的组合,,比如不支持 "uid = {{user_id}} AND city_id = {{city_id}}" + - 支持中文 Unicode 编码范围:4E00-9FFF(查询是否支持参考 + :https://www.unicode.org/cgi-bin/GetUnihanData.pl, 编码范围参考 + :https://www.unicode.org/charts/PDF/U4E00.pdf) """ diff --git a/src/asktable/types/policy_update_params.py b/src/asktable/types/policy_update_params.py index 26d949bf..dc1675b2 100644 --- a/src/asktable/types/policy_update_params.py +++ b/src/asktable/types/policy_update_params.py @@ -107,4 +107,7 @@ class DatasetConfig(TypedDict, total=False): - 暂不支持对字段使用函数计算,比如不支持 "YEAR(public.user.created_at) = 2023" - 暂不支持多个过滤条件的组合,,比如不支持 "uid = {{user_id}} AND city_id = {{city_id}}" + - 支持中文 Unicode 编码范围:4E00-9FFF(查询是否支持参考 + :https://www.unicode.org/cgi-bin/GetUnihanData.pl, 编码范围参考 + :https://www.unicode.org/charts/PDF/U4E00.pdf) """ diff --git a/src/asktable/types/training_create_response.py b/src/asktable/types/training_create_response.py index 1300e978..278021f5 100644 --- a/src/asktable/types/training_create_response.py +++ b/src/asktable/types/training_create_response.py @@ -14,10 +14,14 @@ class TrainingCreateResponseItem(BaseModel): """训练数据 ID""" created_at: datetime + """创建时间""" datasource_id: str """数据源 ID""" + modified_at: datetime + """更新时间""" + project_id: str """项目 ID""" diff --git a/src/asktable/types/training_list_response.py b/src/asktable/types/training_list_response.py index d9868dab..bc22d53a 100644 --- a/src/asktable/types/training_list_response.py +++ b/src/asktable/types/training_list_response.py @@ -14,10 +14,14 @@ class TrainingListResponse(BaseModel): """训练数据 ID""" created_at: datetime + """创建时间""" datasource_id: str """数据源 ID""" + modified_at: datetime + """更新时间""" + project_id: str """项目 ID""" From 0f46ea87dc8c1ff2e97e587744384b93aec5c642 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 10:20:08 +0000 Subject: [PATCH 20/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b5bbb25e..030c79a7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-45d2602f83b88dbbc665744d25d5d9785032f68fcbed81c798ae70ed4ab28355.yml -openapi_spec_hash: 166267ae1e2f2c0505fb591b83400cbc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-92d74a4318e57a489eb71dfddc5ce8e6568e3120d6cac3217a3cf73a0810a837.yml +openapi_spec_hash: 266b01a339179a175b7d91866560d18d config_hash: a572ab842ea60ce13f1d1a1358440cbe From 79c1774d4d811f45d947711c509911d5b0880e72 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 03:39:57 +0000 Subject: [PATCH 21/38] chore(internal): avoid errors for isinstance checks on proxies --- src/asktable/_utils/_proxy.py | 5 ++++- tests/test_utils/test_proxy.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/asktable/_utils/_proxy.py b/src/asktable/_utils/_proxy.py index ffd883e9..0f239a33 100644 --- a/src/asktable/_utils/_proxy.py +++ b/src/asktable/_utils/_proxy.py @@ -46,7 +46,10 @@ def __dir__(self) -> Iterable[str]: @property # type: ignore @override def __class__(self) -> type: # pyright: ignore - proxied = self.__get_proxied__() + try: + proxied = self.__get_proxied__() + except Exception: + return type(self) if issubclass(type(proxied), LazyProxy): return type(proxied) return proxied.__class__ diff --git a/tests/test_utils/test_proxy.py b/tests/test_utils/test_proxy.py index 14dbd6ab..c2d771cd 100644 --- a/tests/test_utils/test_proxy.py +++ b/tests/test_utils/test_proxy.py @@ -21,3 +21,14 @@ def test_recursive_proxy() -> None: assert dir(proxy) == [] assert type(proxy).__name__ == "RecursiveLazyProxy" assert type(operator.attrgetter("name.foo.bar.baz")(proxy)).__name__ == "RecursiveLazyProxy" + + +def test_isinstance_does_not_error() -> None: + class AlwaysErrorProxy(LazyProxy[Any]): + @override + def __load__(self) -> Any: + raise RuntimeError("Mocking missing dependency") + + proxy = AlwaysErrorProxy() + assert not isinstance(proxy, dict) + assert isinstance(proxy, LazyProxy) From e082d60e17dacc06f1a3091454db8d522bf8e7a2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 03:14:19 +0000 Subject: [PATCH 22/38] fix(package): support direct resource imports --- src/asktable/__init__.py | 5 +++++ src/asktable/_utils/_resources_proxy.py | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/asktable/_utils/_resources_proxy.py diff --git a/src/asktable/__init__.py b/src/asktable/__init__.py index 2bf9f563..76486c01 100644 --- a/src/asktable/__init__.py +++ b/src/asktable/__init__.py @@ -1,5 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import typing as _t + from . import types from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes from ._utils import file_from_path @@ -78,6 +80,9 @@ "DefaultAsyncHttpxClient", ] +if not _t.TYPE_CHECKING: + from ._utils._resources_proxy import resources as resources + _setup_logging() # Update the __module__ attribute for exported symbols so that diff --git a/src/asktable/_utils/_resources_proxy.py b/src/asktable/_utils/_resources_proxy.py new file mode 100644 index 00000000..d9107701 --- /dev/null +++ b/src/asktable/_utils/_resources_proxy.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from typing import Any +from typing_extensions import override + +from ._proxy import LazyProxy + + +class ResourcesProxy(LazyProxy[Any]): + """A proxy for the `asktable.resources` module. + + This is used so that we can lazily import `asktable.resources` only when + needed *and* so that users can just import `asktable` and reference `asktable.resources` + """ + + @override + def __load__(self) -> Any: + import importlib + + mod = importlib.import_module("asktable.resources") + return mod + + +resources = ResourcesProxy().__as_proxied__() From eef43f5e6e27c16d4dabfd1bfffcdcbd3a3d81f1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 06:20:13 +0000 Subject: [PATCH 23/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 030c79a7..7f9774b7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-92d74a4318e57a489eb71dfddc5ce8e6568e3120d6cac3217a3cf73a0810a837.yml -openapi_spec_hash: 266b01a339179a175b7d91866560d18d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-4541926153d34a6396c3c7aa1699d8ccd712436d7cc53b992d82cc826bd34957.yml +openapi_spec_hash: 387458b128396a8efa79b080be37ebe3 config_hash: a572ab842ea60ce13f1d1a1358440cbe From 8fda6da68f5c439b69572ad06df119915475acd4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 13:20:30 +0000 Subject: [PATCH 24/38] feat(api): api update --- .stats.yml | 4 ++-- .../resources/datasources/datasources.py | 20 +++++++++++++++++++ src/asktable/types/datasource.py | 5 +++++ .../types/datasource_create_params.py | 5 +++++ .../types/datasource_retrieve_response.py | 5 +++++ .../types/datasource_update_params.py | 5 +++++ 6 files changed, 42 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7f9774b7..b5c9850a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-4541926153d34a6396c3c7aa1699d8ccd712436d7cc53b992d82cc826bd34957.yml -openapi_spec_hash: 387458b128396a8efa79b080be37ebe3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-29394e9288138b62c46bfe93fdef8ecacf70e8e30689814c28f8d9298e5687f9.yml +openapi_spec_hash: 8aa3b1782f1fead9b4b724205fb28e12 config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/resources/datasources/datasources.py b/src/asktable/resources/datasources/datasources.py index 1bcc4596..2c8f988d 100644 --- a/src/asktable/resources/datasources/datasources.py +++ b/src/asktable/resources/datasources/datasources.py @@ -108,6 +108,11 @@ def create( "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ], access_config: Optional[datasource_create_params.AccessConfig] | NotGiven = NOT_GIVEN, name: Optional[str] | NotGiven = NOT_GIVEN, @@ -208,6 +213,11 @@ def update( "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ] ] | NotGiven = NOT_GIVEN, @@ -590,6 +600,11 @@ async def create( "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ], access_config: Optional[datasource_create_params.AccessConfig] | NotGiven = NOT_GIVEN, name: Optional[str] | NotGiven = NOT_GIVEN, @@ -690,6 +705,11 @@ async def update( "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ] ] | NotGiven = NOT_GIVEN, diff --git a/src/asktable/types/datasource.py b/src/asktable/types/datasource.py index 8cfe326c..002d6f36 100644 --- a/src/asktable/types/datasource.py +++ b/src/asktable/types/datasource.py @@ -32,6 +32,11 @@ class Datasource(BaseModel): "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ] """数据源引擎""" diff --git a/src/asktable/types/datasource_create_params.py b/src/asktable/types/datasource_create_params.py index 8ddc93cb..43d6ba62 100644 --- a/src/asktable/types/datasource_create_params.py +++ b/src/asktable/types/datasource_create_params.py @@ -31,6 +31,11 @@ class DatasourceCreateParams(TypedDict, total=False): "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ] ] """数据源引擎""" diff --git a/src/asktable/types/datasource_retrieve_response.py b/src/asktable/types/datasource_retrieve_response.py index 50a24de8..62a749dd 100644 --- a/src/asktable/types/datasource_retrieve_response.py +++ b/src/asktable/types/datasource_retrieve_response.py @@ -77,6 +77,11 @@ class DatasourceRetrieveResponse(BaseModel): "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ] """数据源引擎""" diff --git a/src/asktable/types/datasource_update_params.py b/src/asktable/types/datasource_update_params.py index 4abe181d..33a09c62 100644 --- a/src/asktable/types/datasource_update_params.py +++ b/src/asktable/types/datasource_update_params.py @@ -37,6 +37,11 @@ class DatasourceUpdateParams(TypedDict, total=False): "adbmysql", "adbpostgres", "xugu", + "doris", + "greenplum", + "selectdb", + "databend", + "sqlserver", ] ] """数据源引擎""" From c07ffc7f166f204f6913ec23fc038d9e1e33c18d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 15:20:29 +0000 Subject: [PATCH 25/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b5c9850a..7645af06 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-29394e9288138b62c46bfe93fdef8ecacf70e8e30689814c28f8d9298e5687f9.yml -openapi_spec_hash: 8aa3b1782f1fead9b4b724205fb28e12 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-6d5e2f0f71b815615a7da38dd2b7ff2638417c4a1dc71f4a3cb72b149df02d78.yml +openapi_spec_hash: ccc1f086f23edd4c1b106ad69a20fc53 config_hash: a572ab842ea60ce13f1d1a1358440cbe From f1879ec78dbeb8ccaa35808f398a2cb4dcdb05ea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 16:20:27 +0000 Subject: [PATCH 26/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7645af06..92f9ed1e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-6d5e2f0f71b815615a7da38dd2b7ff2638417c4a1dc71f4a3cb72b149df02d78.yml -openapi_spec_hash: ccc1f086f23edd4c1b106ad69a20fc53 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-5431edd8fc296f7bda00b9dd59dade97af9cac92d2f988b2ca13f1aad131c8b8.yml +openapi_spec_hash: 206d7bd1eceab32b3a7fa1ac11fc47e0 config_hash: a572ab842ea60ce13f1d1a1358440cbe From da9ab061804792f2f6ab50879397e0ea4f0ac76d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 10:20:25 +0000 Subject: [PATCH 27/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 92f9ed1e..8a8dbf68 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-5431edd8fc296f7bda00b9dd59dade97af9cac92d2f988b2ca13f1aad131c8b8.yml -openapi_spec_hash: 206d7bd1eceab32b3a7fa1ac11fc47e0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-3f2b2e30a57117b6f50c49eff27d4d5e78a9d12b54553eacc8818b56aebf4888.yml +openapi_spec_hash: eae6f61ffd2d174b8b4c77aefc42d3d8 config_hash: a572ab842ea60ce13f1d1a1358440cbe From ed6c603a22bc79cf74791566cef81b536dc0d0b3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 04:17:57 +0000 Subject: [PATCH 28/38] chore(ci): upload sdks to package manager --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ scripts/utils/upload-artifact.sh | 25 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100755 scripts/utils/upload-artifact.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d604b7e2..4631164a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,30 @@ jobs: - name: Run lints run: ./scripts/lint + upload: + if: github.repository == 'stainless-sdks/asktable-python' + timeout-minutes: 10 + name: upload + permissions: + contents: read + id-token: write + runs-on: depot-ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - name: Get GitHub OIDC Token + id: github-oidc + uses: actions/github-script@v6 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Upload tarball + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + run: ./scripts/utils/upload-artifact.sh + test: timeout-minutes: 10 name: test diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh new file mode 100755 index 00000000..25f461b9 --- /dev/null +++ b/scripts/utils/upload-artifact.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -exuo pipefail + +RESPONSE=$(curl -X POST "$URL" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + +SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') + +if [[ "$SIGNED_URL" == "null" ]]; then + echo -e "\033[31mFailed to get signed URL.\033[0m" + exit 1 +fi + +UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \ + -H "Content-Type: application/gzip" \ + --data-binary @- "$SIGNED_URL" 2>&1) + +if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then + echo -e "\033[32mUploaded build to Stainless storage.\033[0m" + echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/asktable-python/$SHA'\033[0m" +else + echo -e "\033[31mFailed to upload artifact.\033[0m" + exit 1 +fi From 02f7bb02172f9ac58153e92c2acc063c876fd63b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 16 May 2025 03:26:35 +0000 Subject: [PATCH 29/38] chore(ci): fix installation instructions --- scripts/utils/upload-artifact.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 25f461b9..2acefac1 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -18,7 +18,7 @@ UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \ if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" - echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/asktable-python/$SHA'\033[0m" + echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/asktable-python/$SHA'\033[0m" else echo -e "\033[31mFailed to upload artifact.\033[0m" exit 1 From 78f5da836afd5b934164c6ccdfb636f054f01553 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 05:20:26 +0000 Subject: [PATCH 30/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8a8dbf68..57857736 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-3f2b2e30a57117b6f50c49eff27d4d5e78a9d12b54553eacc8818b56aebf4888.yml -openapi_spec_hash: eae6f61ffd2d174b8b4c77aefc42d3d8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-347ba6f1bb3b3128b6a5829a65109846e55cf65efafecbd35d4f9b913287c1de.yml +openapi_spec_hash: e3f93153621b5c4deb0cad05f301b84f config_hash: a572ab842ea60ce13f1d1a1358440cbe From dc90fe3f3b0829913fde1a288eb8f3ff6fbf7e6d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 13:20:41 +0000 Subject: [PATCH 31/38] feat(api): api update --- .stats.yml | 4 ++-- src/asktable/types/datasource_create_params.py | 2 +- .../types/datasource_retrieve_response.py | 14 ++++++++++++-- src/asktable/types/datasource_update_params.py | 16 +++++++++++++--- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 57857736..fe5472db 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-347ba6f1bb3b3128b6a5829a65109846e55cf65efafecbd35d4f9b913287c1de.yml -openapi_spec_hash: e3f93153621b5c4deb0cad05f301b84f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-a329ffede4f799bba101f6a406e2572043d763f4d73abce6f137771379ad456e.yml +openapi_spec_hash: b93a7a91e2a3297f8bcd14c452f3b808 config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/types/datasource_create_params.py b/src/asktable/types/datasource_create_params.py index 43d6ba62..86c29436 100644 --- a/src/asktable/types/datasource_create_params.py +++ b/src/asktable/types/datasource_create_params.py @@ -75,7 +75,7 @@ class AccessConfigAccessConfigConnectionCreate(TypedDict, total=False): class AccessConfigAccessConfigFileCreate(TypedDict, total=False): files: Required[List[str]] - """数据源文件列表""" + """数据源文件 URL 列表, 创建时可以传入 URL""" AccessConfig: TypeAlias = Union[AccessConfigAccessConfigConnectionCreate, AccessConfigAccessConfigFileCreate] diff --git a/src/asktable/types/datasource_retrieve_response.py b/src/asktable/types/datasource_retrieve_response.py index 62a749dd..b8df16fd 100644 --- a/src/asktable/types/datasource_retrieve_response.py +++ b/src/asktable/types/datasource_retrieve_response.py @@ -11,6 +11,7 @@ "AccessConfig", "AccessConfigAccessConfigConnectionResponse", "AccessConfigAccessConfigFileResponse", + "AccessConfigAccessConfigFileResponseFile", ] @@ -46,9 +47,18 @@ class AccessConfigAccessConfigConnectionResponse(BaseModel): """数据库用户名""" +class AccessConfigAccessConfigFileResponseFile(BaseModel): + id: str + + filename: str + + custom_config: Optional[object] = None + """文件自定义配置""" + + class AccessConfigAccessConfigFileResponse(BaseModel): - files: List[str] - """数据源文件列表""" + files: List[AccessConfigAccessConfigFileResponseFile] + """数据源文件 ID 列表""" AccessConfig: TypeAlias = Union[AccessConfigAccessConfigConnectionResponse, AccessConfigAccessConfigFileResponse, None] diff --git a/src/asktable/types/datasource_update_params.py b/src/asktable/types/datasource_update_params.py index 33a09c62..68aa28d4 100644 --- a/src/asktable/types/datasource_update_params.py +++ b/src/asktable/types/datasource_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Union, Optional +from typing import Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict __all__ = [ @@ -10,6 +10,7 @@ "AccessConfig", "AccessConfigAccessConfigConnectionUpdate", "AccessConfigAccessConfigFileUpdate", + "AccessConfigAccessConfigFileUpdateFile", ] @@ -94,9 +95,18 @@ class AccessConfigAccessConfigConnectionUpdate(TypedDict, total=False): """数据库用户名""" +class AccessConfigAccessConfigFileUpdateFile(TypedDict, total=False): + id: Required[str] + + filename: Required[str] + + custom_config: Optional[object] + """文件自定义配置""" + + class AccessConfigAccessConfigFileUpdate(TypedDict, total=False): - files: Required[List[str]] - """数据源文件列表""" + files: Required[Iterable[AccessConfigAccessConfigFileUpdateFile]] + """数据源文件 ID 列表""" AccessConfig: TypeAlias = Union[AccessConfigAccessConfigConnectionUpdate, AccessConfigAccessConfigFileUpdate] From 59323c47691cef0b342d34589f45e5748b8d6d73 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 09:20:32 +0000 Subject: [PATCH 32/38] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index fe5472db..1b78d88a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-a329ffede4f799bba101f6a406e2572043d763f4d73abce6f137771379ad456e.yml -openapi_spec_hash: b93a7a91e2a3297f8bcd14c452f3b808 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-e016b9102a8314050cfff60bd371d2ff4b2a737122c261279e1a03f0a88ebe5c.yml +openapi_spec_hash: 6d997fcedcb4db1962c2d688cc92341c config_hash: a572ab842ea60ce13f1d1a1358440cbe From 8f09ac84dd9df377925ec5ed214037c1c5b23d48 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 02:34:45 +0000 Subject: [PATCH 33/38] chore(docs): grammar improvements --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 6cf7553c..e9a4fcb9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,11 +16,11 @@ before making any information public. ## Reporting Non-SDK Related Security Issues If you encounter security issues that are not directly related to SDKs but pertain to the services -or products provided by Asktable please follow the respective company's security reporting guidelines. +or products provided by Asktable, please follow the respective company's security reporting guidelines. ### Asktable Terms and Policies -Please contact hi@datamini.ai for any questions or concerns regarding security of our services. +Please contact hi@datamini.ai for any questions or concerns regarding the security of our services. --- From 18a5eafaf07afc7c59141e957104728fe2d413b5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 09:20:36 +0000 Subject: [PATCH 34/38] feat(api): api update --- .stats.yml | 4 ++-- src/asktable/resources/datasources/datasources.py | 4 ++++ src/asktable/resources/sqls.py | 8 ++++++++ src/asktable/types/datasource.py | 1 + src/asktable/types/datasource_create_params.py | 1 + src/asktable/types/datasource_retrieve_response.py | 1 + src/asktable/types/datasource_update_params.py | 1 + src/asktable/types/query_response.py | 6 ++++++ src/asktable/types/sql_create_params.py | 3 +++ tests/api_resources/test_sqls.py | 2 ++ 10 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1b78d88a..0c4a7dc5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-e016b9102a8314050cfff60bd371d2ff4b2a737122c261279e1a03f0a88ebe5c.yml -openapi_spec_hash: 6d997fcedcb4db1962c2d688cc92341c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-c69602c033b50a9e3b770858aaa45bd0cc6578dfbd8bf0130d11e15a18edb3b4.yml +openapi_spec_hash: 82eb79d2638703a11db4890a0014f75b config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/resources/datasources/datasources.py b/src/asktable/resources/datasources/datasources.py index 2c8f988d..7589685d 100644 --- a/src/asktable/resources/datasources/datasources.py +++ b/src/asktable/resources/datasources/datasources.py @@ -113,6 +113,7 @@ def create( "selectdb", "databend", "sqlserver", + "mogdb", ], access_config: Optional[datasource_create_params.AccessConfig] | NotGiven = NOT_GIVEN, name: Optional[str] | NotGiven = NOT_GIVEN, @@ -218,6 +219,7 @@ def update( "selectdb", "databend", "sqlserver", + "mogdb", ] ] | NotGiven = NOT_GIVEN, @@ -605,6 +607,7 @@ async def create( "selectdb", "databend", "sqlserver", + "mogdb", ], access_config: Optional[datasource_create_params.AccessConfig] | NotGiven = NOT_GIVEN, name: Optional[str] | NotGiven = NOT_GIVEN, @@ -710,6 +713,7 @@ async def update( "selectdb", "databend", "sqlserver", + "mogdb", ] ] | NotGiven = NOT_GIVEN, diff --git a/src/asktable/resources/sqls.py b/src/asktable/resources/sqls.py index 2804eaef..da03cc57 100644 --- a/src/asktable/resources/sqls.py +++ b/src/asktable/resources/sqls.py @@ -51,6 +51,7 @@ def create( question: str, role_id: Optional[str] | NotGiven = NOT_GIVEN, role_variables: Optional[object] | NotGiven = NOT_GIVEN, + separate_params: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -71,6 +72,8 @@ def create( role_variables: 在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递 + separate_params: 是否将参数分开传递 + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -87,6 +90,7 @@ def create( "question": question, "role_id": role_id, "role_variables": role_variables, + "separate_params": separate_params, }, sql_create_params.SqlCreateParams, ), @@ -175,6 +179,7 @@ async def create( question: str, role_id: Optional[str] | NotGiven = NOT_GIVEN, role_variables: Optional[object] | NotGiven = NOT_GIVEN, + separate_params: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -195,6 +200,8 @@ async def create( role_variables: 在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递 + separate_params: 是否将参数分开传递 + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -211,6 +218,7 @@ async def create( "question": question, "role_id": role_id, "role_variables": role_variables, + "separate_params": separate_params, }, sql_create_params.SqlCreateParams, ), diff --git a/src/asktable/types/datasource.py b/src/asktable/types/datasource.py index 002d6f36..70a1ae18 100644 --- a/src/asktable/types/datasource.py +++ b/src/asktable/types/datasource.py @@ -37,6 +37,7 @@ class Datasource(BaseModel): "selectdb", "databend", "sqlserver", + "mogdb", ] """数据源引擎""" diff --git a/src/asktable/types/datasource_create_params.py b/src/asktable/types/datasource_create_params.py index 86c29436..afd362b0 100644 --- a/src/asktable/types/datasource_create_params.py +++ b/src/asktable/types/datasource_create_params.py @@ -36,6 +36,7 @@ class DatasourceCreateParams(TypedDict, total=False): "selectdb", "databend", "sqlserver", + "mogdb", ] ] """数据源引擎""" diff --git a/src/asktable/types/datasource_retrieve_response.py b/src/asktable/types/datasource_retrieve_response.py index b8df16fd..d244225c 100644 --- a/src/asktable/types/datasource_retrieve_response.py +++ b/src/asktable/types/datasource_retrieve_response.py @@ -92,6 +92,7 @@ class DatasourceRetrieveResponse(BaseModel): "selectdb", "databend", "sqlserver", + "mogdb", ] """数据源引擎""" diff --git a/src/asktable/types/datasource_update_params.py b/src/asktable/types/datasource_update_params.py index 68aa28d4..ff22daff 100644 --- a/src/asktable/types/datasource_update_params.py +++ b/src/asktable/types/datasource_update_params.py @@ -43,6 +43,7 @@ class DatasourceUpdateParams(TypedDict, total=False): "selectdb", "databend", "sqlserver", + "mogdb", ] ] """数据源引擎""" diff --git a/src/asktable/types/query_response.py b/src/asktable/types/query_response.py index c8234056..3e9c299a 100644 --- a/src/asktable/types/query_response.py +++ b/src/asktable/types/query_response.py @@ -12,6 +12,9 @@ class Query(BaseModel): sql: str """SQL 语句""" + params: Optional[object] = None + """参数""" + class Request(BaseModel): datasource_id: str @@ -29,6 +32,9 @@ class Request(BaseModel): role_variables: Optional[object] = None """在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递""" + separate_params: Optional[bool] = None + """是否将参数分开传递""" + class QueryResponse(BaseModel): id: str diff --git a/src/asktable/types/sql_create_params.py b/src/asktable/types/sql_create_params.py index 52d3cfb1..8d8e2cc7 100644 --- a/src/asktable/types/sql_create_params.py +++ b/src/asktable/types/sql_create_params.py @@ -23,3 +23,6 @@ class SqlCreateParams(TypedDict, total=False): role_variables: Optional[object] """在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递""" + + separate_params: bool + """是否将参数分开传递""" diff --git a/tests/api_resources/test_sqls.py b/tests/api_resources/test_sqls.py index 9ba2d05f..57ac482d 100644 --- a/tests/api_resources/test_sqls.py +++ b/tests/api_resources/test_sqls.py @@ -33,6 +33,7 @@ def test_method_create_with_all_params(self, client: Asktable) -> None: question="question", role_id="role_id", role_variables={}, + separate_params=True, ) assert_matches_type(QueryResponse, sql, path=["response"]) @@ -115,6 +116,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncAsktable) question="question", role_id="role_id", role_variables={}, + separate_params=True, ) assert_matches_type(QueryResponse, sql, path=["response"]) From 07d802a94360a7e66e0594b5ba39b9fc4916a56d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 24 May 2025 11:20:32 +0000 Subject: [PATCH 35/38] feat(api): api update --- .stats.yml | 4 ++-- src/asktable/resources/datasources/datasources.py | 4 ++-- src/asktable/types/datasource_update_field_params.py | 4 +++- src/asktable/types/datasources/meta_create_params.py | 2 +- src/asktable/types/datasources/meta_update_params.py | 2 +- src/asktable/types/meta.py | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0c4a7dc5..3e2a2f6e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-c69602c033b50a9e3b770858aaa45bd0cc6578dfbd8bf0130d11e15a18edb3b4.yml -openapi_spec_hash: 82eb79d2638703a11db4890a0014f75b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-0d2c202b105ede34bc28a2532b7ff64cfb703b35a0e4ac110c663308f3db2ac5.yml +openapi_spec_hash: 144caed1d3c1d1d2dd4af71dcb80ca2d config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/resources/datasources/datasources.py b/src/asktable/resources/datasources/datasources.py index 7589685d..239b7943 100644 --- a/src/asktable/resources/datasources/datasources.py +++ b/src/asktable/resources/datasources/datasources.py @@ -495,7 +495,7 @@ def update_field( schema_name: str, table_name: str, identifiable_type: Optional[ - Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company"] + Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] ] | NotGiven = NOT_GIVEN, visibility: Optional[bool] | NotGiven = NOT_GIVEN, @@ -989,7 +989,7 @@ async def update_field( schema_name: str, table_name: str, identifiable_type: Optional[ - Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company"] + Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] ] | NotGiven = NOT_GIVEN, visibility: Optional[bool] | NotGiven = NOT_GIVEN, diff --git a/src/asktable/types/datasource_update_field_params.py b/src/asktable/types/datasource_update_field_params.py index f756bdf4..977caae5 100644 --- a/src/asktable/types/datasource_update_field_params.py +++ b/src/asktable/types/datasource_update_field_params.py @@ -15,7 +15,9 @@ class DatasourceUpdateFieldParams(TypedDict, total=False): table_name: Required[str] - identifiable_type: Optional[Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company"]] + identifiable_type: Optional[ + Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] + ] """identifiable type""" visibility: Optional[bool] diff --git a/src/asktable/types/datasources/meta_create_params.py b/src/asktable/types/datasources/meta_create_params.py index 4d452ff8..86783588 100644 --- a/src/asktable/types/datasources/meta_create_params.py +++ b/src/asktable/types/datasources/meta_create_params.py @@ -28,7 +28,7 @@ class MetaSchemasTablesFields(TypedDict, total=False): data_type: Optional[str] """field data type""" - identifiable_type: Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company"] + identifiable_type: Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] """identifiable type""" sample_data: Optional[str] diff --git a/src/asktable/types/datasources/meta_update_params.py b/src/asktable/types/datasources/meta_update_params.py index 862f0776..2a14b685 100644 --- a/src/asktable/types/datasources/meta_update_params.py +++ b/src/asktable/types/datasources/meta_update_params.py @@ -26,7 +26,7 @@ class MetaSchemasTablesFields(TypedDict, total=False): data_type: Optional[str] """field data type""" - identifiable_type: Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company"] + identifiable_type: Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] """identifiable type""" sample_data: Optional[str] diff --git a/src/asktable/types/meta.py b/src/asktable/types/meta.py index 05cd5f20..f94d2037 100644 --- a/src/asktable/types/meta.py +++ b/src/asktable/types/meta.py @@ -35,7 +35,7 @@ class SchemasTablesFields(BaseModel): """field data type""" identifiable_type: Optional[ - Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company"] + Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] ] = None """identifiable type""" From 558ab837046be3f9e902a2e073096217bda1438e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 08:20:30 +0000 Subject: [PATCH 36/38] feat(api): api update --- .stats.yml | 4 ++-- src/asktable/resources/sqls.py | 16 ++++++++-------- src/asktable/types/query_response.py | 9 ++++++--- src/asktable/types/sql_create_params.py | 6 +++--- tests/api_resources/test_sqls.py | 4 ++-- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3e2a2f6e..364945f0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-0d2c202b105ede34bc28a2532b7ff64cfb703b35a0e4ac110c663308f3db2ac5.yml -openapi_spec_hash: 144caed1d3c1d1d2dd4af71dcb80ca2d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-a1d971d9b78dce18435845fd9ff02282e95647ffee9b7406fb5f5cd0078c630b.yml +openapi_spec_hash: ca7ca362f716b3a9b065f74f14ba43bc config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/resources/sqls.py b/src/asktable/resources/sqls.py index da03cc57..fc871c84 100644 --- a/src/asktable/resources/sqls.py +++ b/src/asktable/resources/sqls.py @@ -49,9 +49,9 @@ def create( *, datasource_id: str, question: str, + parameterize: bool | NotGiven = NOT_GIVEN, role_id: Optional[str] | NotGiven = NOT_GIVEN, role_variables: Optional[object] | NotGiven = NOT_GIVEN, - separate_params: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -67,13 +67,13 @@ def create( question: 查询语句 + parameterize: 是否将参数分开传递 + role_id: 角色 ID,将扮演这个角色来执行对话,用于权限控制。若无,则跳过鉴权,即可查询所有 数据 role_variables: 在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递 - separate_params: 是否将参数分开传递 - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -88,9 +88,9 @@ def create( { "datasource_id": datasource_id, "question": question, + "parameterize": parameterize, "role_id": role_id, "role_variables": role_variables, - "separate_params": separate_params, }, sql_create_params.SqlCreateParams, ), @@ -177,9 +177,9 @@ async def create( *, datasource_id: str, question: str, + parameterize: bool | NotGiven = NOT_GIVEN, role_id: Optional[str] | NotGiven = NOT_GIVEN, role_variables: Optional[object] | NotGiven = NOT_GIVEN, - separate_params: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -195,13 +195,13 @@ async def create( question: 查询语句 + parameterize: 是否将参数分开传递 + role_id: 角色 ID,将扮演这个角色来执行对话,用于权限控制。若无,则跳过鉴权,即可查询所有 数据 role_variables: 在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递 - separate_params: 是否将参数分开传递 - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -216,9 +216,9 @@ async def create( { "datasource_id": datasource_id, "question": question, + "parameterize": parameterize, "role_id": role_id, "role_variables": role_variables, - "separate_params": separate_params, }, sql_create_params.SqlCreateParams, ), diff --git a/src/asktable/types/query_response.py b/src/asktable/types/query_response.py index 3e9c299a..b71c43fc 100644 --- a/src/asktable/types/query_response.py +++ b/src/asktable/types/query_response.py @@ -12,6 +12,9 @@ class Query(BaseModel): sql: str """SQL 语句""" + parameterized_sql: Optional[str] = None + """参数化后的 SQL 语句""" + params: Optional[object] = None """参数""" @@ -23,6 +26,9 @@ class Request(BaseModel): question: str """查询语句""" + parameterize: Optional[bool] = None + """是否将参数分开传递""" + role_id: Optional[str] = None """ 角色 ID,将扮演这个角色来执行对话,用于权限控制。若无,则跳过鉴权,即可查询所有 @@ -32,9 +38,6 @@ class Request(BaseModel): role_variables: Optional[object] = None """在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递""" - separate_params: Optional[bool] = None - """是否将参数分开传递""" - class QueryResponse(BaseModel): id: str diff --git a/src/asktable/types/sql_create_params.py b/src/asktable/types/sql_create_params.py index 8d8e2cc7..515dbd47 100644 --- a/src/asktable/types/sql_create_params.py +++ b/src/asktable/types/sql_create_params.py @@ -15,6 +15,9 @@ class SqlCreateParams(TypedDict, total=False): question: Required[str] """查询语句""" + parameterize: bool + """是否将参数分开传递""" + role_id: Optional[str] """ 角色 ID,将扮演这个角色来执行对话,用于权限控制。若无,则跳过鉴权,即可查询所有 @@ -23,6 +26,3 @@ class SqlCreateParams(TypedDict, total=False): role_variables: Optional[object] """在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递""" - - separate_params: bool - """是否将参数分开传递""" diff --git a/tests/api_resources/test_sqls.py b/tests/api_resources/test_sqls.py index 57ac482d..258ae9a0 100644 --- a/tests/api_resources/test_sqls.py +++ b/tests/api_resources/test_sqls.py @@ -31,9 +31,9 @@ def test_method_create_with_all_params(self, client: Asktable) -> None: sql = client.sqls.create( datasource_id="datasource_id", question="question", + parameterize=True, role_id="role_id", role_variables={}, - separate_params=True, ) assert_matches_type(QueryResponse, sql, path=["response"]) @@ -114,9 +114,9 @@ async def test_method_create_with_all_params(self, async_client: AsyncAsktable) sql = await async_client.sqls.create( datasource_id="datasource_id", question="question", + parameterize=True, role_id="role_id", role_variables={}, - separate_params=True, ) assert_matches_type(QueryResponse, sql, path=["response"]) From 84767d7648a7df94f1caf85628576ea948d94475 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 13:18:19 +0000 Subject: [PATCH 37/38] feat(api): api update --- .stats.yml | 4 ++-- src/asktable/types/answer_response.py | 12 +++++++++++- src/asktable/types/query_response.py | 10 +++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 364945f0..499f0df9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 96 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-a1d971d9b78dce18435845fd9ff02282e95647ffee9b7406fb5f5cd0078c630b.yml -openapi_spec_hash: ca7ca362f716b3a9b065f74f14ba43bc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-fd9a749a4afed8a45757ab4e83984c36c56cf6f4f0d53b80d4d5e0022869c3e1.yml +openapi_spec_hash: d5cf0471c4e715bdfbf597de3f591ef1 config_hash: a572ab842ea60ce13f1d1a1358440cbe diff --git a/src/asktable/types/answer_response.py b/src/asktable/types/answer_response.py index 3bc03be2..04112480 100644 --- a/src/asktable/types/answer_response.py +++ b/src/asktable/types/answer_response.py @@ -5,7 +5,7 @@ from .._models import BaseModel -__all__ = ["AnswerResponse", "Answer", "AnswerAttachment", "Request"] +__all__ = ["AnswerResponse", "Answer", "AnswerAttachment", "Request", "Timing"] class AnswerAttachment(BaseModel): @@ -44,6 +44,14 @@ class Request(BaseModel): """是否同时将数据,作为 json 格式的附件一起返回""" +class Timing(BaseModel): + accessor_duration: Optional[float] = None + + llm_duration: Optional[float] = None + + total_duration: Optional[float] = None + + class AnswerResponse(BaseModel): id: str @@ -63,4 +71,6 @@ class AnswerResponse(BaseModel): err_msg: Optional[str] = None + timing: Optional[Timing] = None + trace_id: Optional[str] = None diff --git a/src/asktable/types/query_response.py b/src/asktable/types/query_response.py index b71c43fc..f57289fb 100644 --- a/src/asktable/types/query_response.py +++ b/src/asktable/types/query_response.py @@ -5,7 +5,7 @@ from .._models import BaseModel -__all__ = ["QueryResponse", "Query", "Request"] +__all__ = ["QueryResponse", "Query", "Request", "Timing"] class Query(BaseModel): @@ -39,6 +39,12 @@ class Request(BaseModel): """在扮演这个角色时需要传递的变量值,用 Key-Value 形式传递""" +class Timing(BaseModel): + llm_duration: Optional[float] = None + + total_duration: Optional[float] = None + + class QueryResponse(BaseModel): id: str @@ -58,4 +64,6 @@ class QueryResponse(BaseModel): err_msg: Optional[str] = None + timing: Optional[Timing] = None + trace_id: Optional[str] = None From 179cefd447693c4ad2e91e1d7f40ccfa22ab436f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 13:18:46 +0000 Subject: [PATCH 38/38] release: 5.4.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 44 +++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/asktable/_version.py | 2 +- 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fb1ef4a0..5f7bf255 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "5.3.1" + ".": "5.4.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 62733995..820ef2c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,49 @@ # Changelog +## 5.4.0 (2025-05-27) + +Full Changelog: [v5.3.1...v5.4.0](https://github.com/DataMini/asktable-python/compare/v5.3.1...v5.4.0) + +### Features + +* **api:** api update ([84767d7](https://github.com/DataMini/asktable-python/commit/84767d7648a7df94f1caf85628576ea948d94475)) +* **api:** api update ([558ab83](https://github.com/DataMini/asktable-python/commit/558ab837046be3f9e902a2e073096217bda1438e)) +* **api:** api update ([07d802a](https://github.com/DataMini/asktable-python/commit/07d802a94360a7e66e0594b5ba39b9fc4916a56d)) +* **api:** api update ([18a5eaf](https://github.com/DataMini/asktable-python/commit/18a5eafaf07afc7c59141e957104728fe2d413b5)) +* **api:** api update ([dc90fe3](https://github.com/DataMini/asktable-python/commit/dc90fe3f3b0829913fde1a288eb8f3ff6fbf7e6d)) +* **api:** api update ([8fda6da](https://github.com/DataMini/asktable-python/commit/8fda6da68f5c439b69572ad06df119915475acd4)) +* **api:** api update ([8cfc989](https://github.com/DataMini/asktable-python/commit/8cfc98987196f71dc9b1ac788a66e7fb7a6b62c9)) +* **api:** api update ([317b682](https://github.com/DataMini/asktable-python/commit/317b682b9de2a8803f8d2be7be7a9ed8ad1e961c)) + + +### Bug Fixes + +* **package:** support direct resource imports ([e082d60](https://github.com/DataMini/asktable-python/commit/e082d60e17dacc06f1a3091454db8d522bf8e7a2)) +* **perf:** optimize some hot paths ([4ce95f7](https://github.com/DataMini/asktable-python/commit/4ce95f7c3a5f0b7568ad63d0bb6fe8dade3d20ff)) +* **perf:** skip traversing types for NotGiven values ([00250bb](https://github.com/DataMini/asktable-python/commit/00250bbfc900cb7003e3e77239ced58934b6d826)) +* **pydantic v1:** more robust ModelField.annotation check ([c16373d](https://github.com/DataMini/asktable-python/commit/c16373dba54d24f705650aa38d3b4c1a772f23ff)) + + +### Chores + +* broadly detect json family of content-type headers ([3bff15d](https://github.com/DataMini/asktable-python/commit/3bff15dcccae660478bd3e6a30aa609e4bcc186f)) +* **ci:** add timeout thresholds for CI jobs ([f51cedc](https://github.com/DataMini/asktable-python/commit/f51cedc6e85b7300ae989972c02c2f4303c7838a)) +* **ci:** fix installation instructions ([02f7bb0](https://github.com/DataMini/asktable-python/commit/02f7bb02172f9ac58153e92c2acc063c876fd63b)) +* **ci:** only use depot for staging repos ([6c155eb](https://github.com/DataMini/asktable-python/commit/6c155eb595e7227c769e953a5040b577f85f494c)) +* **ci:** upload sdks to package manager ([ed6c603](https://github.com/DataMini/asktable-python/commit/ed6c603a22bc79cf74791566cef81b536dc0d0b3)) +* **client:** minor internal fixes ([b4af709](https://github.com/DataMini/asktable-python/commit/b4af709160aa14f36bef3a624c069b21290ded66)) +* **docs:** grammar improvements ([8f09ac8](https://github.com/DataMini/asktable-python/commit/8f09ac84dd9df377925ec5ed214037c1c5b23d48)) +* **internal:** avoid errors for isinstance checks on proxies ([79c1774](https://github.com/DataMini/asktable-python/commit/79c1774d4d811f45d947711c509911d5b0880e72)) +* **internal:** base client updates ([7e7f8c5](https://github.com/DataMini/asktable-python/commit/7e7f8c56783a125505f587d6f206da00da98f438)) +* **internal:** bump pyright version ([b56ec6c](https://github.com/DataMini/asktable-python/commit/b56ec6cc156694361cbd43a2d8590813f30a47c0)) +* **internal:** codegen related update ([3719d1b](https://github.com/DataMini/asktable-python/commit/3719d1bf1db482d5f08368b6162d67c878e48369)) +* **internal:** fix list file params ([12bba1b](https://github.com/DataMini/asktable-python/commit/12bba1b329d0149f1b8065c983efbddda6a1a1d1)) +* **internal:** import reformatting ([bb1b5a8](https://github.com/DataMini/asktable-python/commit/bb1b5a84fbea13e655f968639f3e5edf584914ad)) +* **internal:** minor formatting changes ([1f83169](https://github.com/DataMini/asktable-python/commit/1f83169570f13ba1ede9c92a23e610018d39f8e0)) +* **internal:** refactor retries to not use recursion ([af64ff0](https://github.com/DataMini/asktable-python/commit/af64ff050f75fae9c6368c6c0d105197f227397c)) +* **internal:** update models test ([4e84f01](https://github.com/DataMini/asktable-python/commit/4e84f01f5b52e119f73cab72e4ea3ceaa1889e42)) +* **internal:** update pyright settings ([c1a4b25](https://github.com/DataMini/asktable-python/commit/c1a4b25eda6192bfb974f1aa6b21ae35f4ea762e)) + ## 5.3.1 (2025-04-10) Full Changelog: [v5.3.0...v5.3.1](https://github.com/DataMini/asktable-python/compare/v5.3.0...v5.3.1) diff --git a/pyproject.toml b/pyproject.toml index 17a28b1a..c1ce99ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "asktable" -version = "5.3.1" +version = "5.4.0" description = "The official Python library for the Asktable API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/asktable/_version.py b/src/asktable/_version.py index cf688864..d445532a 100644 --- a/src/asktable/_version.py +++ b/src/asktable/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "asktable" -__version__ = "5.3.1" # x-release-please-version +__version__ = "5.4.0" # x-release-please-version