diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ccc7f01..cb20fc47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,13 +36,13 @@ jobs: run: ./scripts/lint build: - if: github.repository == 'stainless-sdks/asktable-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork timeout-minutes: 10 name: build permissions: contents: read id-token: write - 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 @@ -61,12 +61,14 @@ jobs: run: rye build - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/asktable-python' id: github-oidc uses: actions/github-script@v6 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball + if: github.repository == 'stainless-sdks/asktable-python' env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} diff --git a/.gitignore b/.gitignore index 87797408..95ceb189 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .prism.log -.vscode _dev __pycache__ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f425d970..8d050425 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "5.5.0" + ".": "5.6.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index b3408abe..f2896c95 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 107 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-420512609e3f9f33f8a5b2d0086d4d3152b78935f1dc689cf4c5adf245241ba8.yml -openapi_spec_hash: a0055c3c329900b7a66dc27f4bea86cb +configured_endpoints: 105 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/datamini%2Fasktable-9700b1610662cf5565932faaf0ef502cae2c2a8fc9504381570b8f4780fce757.yml +openapi_spec_hash: 740fbb5e75123194c130ec62b4c2b956 config_hash: acdf4142177ed1932c2d82372693f811 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..5b010307 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.analysis.importFormat": "relative", +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 320a4033..1fc4a9a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,49 @@ # Changelog +## 5.6.0 (2025-12-26) + +Full Changelog: [v5.5.0...v5.6.0](https://github.com/DataMini/asktable-python/compare/v5.5.0...v5.6.0) + +### Features + +* **api:** api update ([692c5e4](https://github.com/DataMini/asktable-python/commit/692c5e4a06ed72d630cae83806a89eb36316e647)) +* **api:** api update ([a62c00a](https://github.com/DataMini/asktable-python/commit/a62c00ae12cbc0efdbcb4bdf02480ddbb36d693a)) +* **api:** api update ([94adaea](https://github.com/DataMini/asktable-python/commit/94adaeae5c0a3ab51b8d4f9ef9acba27d87efc06)) +* **api:** api update ([d79fd22](https://github.com/DataMini/asktable-python/commit/d79fd224c090d22b32cc02776c5fd32ea56d2a7b)) +* **api:** api update ([d3cbda0](https://github.com/DataMini/asktable-python/commit/d3cbda00e41261e559ba2111b843b1b10f9fb772)) +* **api:** api update ([8e94324](https://github.com/DataMini/asktable-python/commit/8e94324216695bc96c20ed8b066a342d35b1f377)) +* **api:** api update ([689b9c0](https://github.com/DataMini/asktable-python/commit/689b9c0c7863e30ea3a614607c1aac22f5745b52)) +* **api:** api update ([8e2933a](https://github.com/DataMini/asktable-python/commit/8e2933a2a07175e5b2a817f9243df5952b19a9fa)) +* **api:** api update ([8fa327a](https://github.com/DataMini/asktable-python/commit/8fa327a7bb92dc4b4aeb81ff356989c13712166d)) +* **api:** api update ([7a17247](https://github.com/DataMini/asktable-python/commit/7a17247ed3d0cb95ec279c1627b51dfb2ce48572)) +* **api:** api update ([fd21534](https://github.com/DataMini/asktable-python/commit/fd2153419e2ba1424b40398fef454d01db6d4a79)) +* **client:** support file upload requests ([e9bac63](https://github.com/DataMini/asktable-python/commit/e9bac63f9b86123f21df0343e44bd9423e053bbe)) +* improve future compat with pydantic v3 ([7d6836d](https://github.com/DataMini/asktable-python/commit/7d6836dc486cd6287e806f18177b2c4afb1be2e5)) +* **types:** replace List[str] with SequenceNotStr in params ([be4a6d6](https://github.com/DataMini/asktable-python/commit/be4a6d685ff133354c4b242992de4a80f475c2d4)) + + +### Bug Fixes + +* avoid newer type syntax ([2bc84ae](https://github.com/DataMini/asktable-python/commit/2bc84ae95415f7377dcbf554faf6d057605f5c74)) +* **parsing:** ignore empty metadata ([8c48f1b](https://github.com/DataMini/asktable-python/commit/8c48f1b05dbebb99a432ab9fd7b57f8aed109d60)) +* **parsing:** parse extra field types ([40c9351](https://github.com/DataMini/asktable-python/commit/40c9351059a44df1f640f5791a126e175ebadad6)) + + +### Chores + +* **internal:** add Sequence related utils ([d34ae74](https://github.com/DataMini/asktable-python/commit/d34ae74d7dd281b8b1bc806aec5965a042550d88)) +* **internal:** change ci workflow machines ([1781814](https://github.com/DataMini/asktable-python/commit/17818149ddfaa3397db71e1a6a2500b997576a97)) +* **internal:** fix ruff target version ([47ae330](https://github.com/DataMini/asktable-python/commit/47ae33089939da844b9fc6f96ea1d7a56d57887e)) +* **internal:** move mypy configurations to `pyproject.toml` file ([3a81ab1](https://github.com/DataMini/asktable-python/commit/3a81ab10fc9090dd6e0c850ebf4d2bc5dd0774aa)) +* **internal:** update comment in script ([595c402](https://github.com/DataMini/asktable-python/commit/595c4022caf668b57ad4dab50ec2e8a7dc3227af)) +* **internal:** update pydantic dependency ([7768ab5](https://github.com/DataMini/asktable-python/commit/7768ab57521d3e09e550013c14b188e6aeb62fd1)) +* **internal:** update pyright exclude list ([5bf3c78](https://github.com/DataMini/asktable-python/commit/5bf3c78a9d79882f1c2e7e4245187cbb1813229d)) +* **project:** add settings file for vscode ([1641a3d](https://github.com/DataMini/asktable-python/commit/1641a3d8c4a5647a81b6292b3fd8805ab3132bb8)) +* **tests:** simplify `get_platform` test ([f8251b5](https://github.com/DataMini/asktable-python/commit/f8251b5a76926a6603865967d8e94071a72f5d26)) +* **types:** change optional parameter type from NotGiven to Omit ([e2ab3d3](https://github.com/DataMini/asktable-python/commit/e2ab3d3508972ea2ac5df4ab1824036070eaf732)) +* update @stainless-api/prism-cli to v5.15.0 ([5d3abad](https://github.com/DataMini/asktable-python/commit/5d3abad79640464784e731af282d02600606db98)) +* update github action ([653ff06](https://github.com/DataMini/asktable-python/commit/653ff06315c440c09e931828916b8ff38a41d6bd)) + ## 5.5.0 (2025-07-19) Full Changelog: [v5.4.0...v5.5.0](https://github.com/DataMini/asktable-python/compare/v5.4.0...v5.5.0) diff --git a/README.md b/README.md index cab856b6..a32428d2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![PyPI version](https://img.shields.io/pypi/v/asktable.svg?label=pypi%20(stable))](https://pypi.org/project/asktable/) -The Asktable Python library provides convenient access to the Asktable REST API from any Python 3.8+ +The Asktable Python library provides convenient access to the Asktable REST API from any Python 3.9+ application. The library includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). @@ -83,6 +83,7 @@ pip install asktable[aiohttp] Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: ```python +import os import asyncio from asktable import DefaultAioHttpClient from asktable import AsyncAsktable @@ -90,7 +91,7 @@ from asktable import AsyncAsktable async def main() -> None: async with AsyncAsktable( - api_key="My API Key", + api_key=os.environ.get("ASKTABLE_API_KEY"), # This is the default and can be omitted http_client=DefaultAioHttpClient(), ) as client: datasource = await client.datasources.create( @@ -469,7 +470,7 @@ print(asktable.__version__) ## Requirements -Python 3.8 or higher. +Python 3.9 or higher. ## Contributing diff --git a/api.md b/api.md index 4d02c1ed..998db553 100644 --- a/api.md +++ b/api.md @@ -6,16 +6,6 @@ from asktable.types import Policy # Sys -Types: - -```python -from asktable.types import SyUpdateConfigResponse -``` - -Methods: - -- client.sys.update_config(\*\*params) -> SyUpdateConfigResponse - ## Projects Types: @@ -229,12 +219,6 @@ Methods: - client.sqls.create(\*\*params) -> QueryResponse - client.sqls.list(\*\*params) -> SyncPage[QueryResponse] -# Caches - -Methods: - -- client.caches.delete(cache_id) -> None - # Integration Types: diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index b0156385..00000000 --- a/mypy.ini +++ /dev/null @@ -1,50 +0,0 @@ -[mypy] -pretty = True -show_error_codes = True - -# Exclude _files.py because mypy isn't smart enough to apply -# the correct type narrowing and as this is an internal module -# it's fine to just use Pyright. -# -# We also exclude our `tests` as mypy doesn't always infer -# types correctly and Pyright will still catch any type errors. -exclude = ^(src/asktable/_files\.py|_dev/.*\.py|tests/.*)$ - -strict_equality = True -implicit_reexport = True -check_untyped_defs = True -no_implicit_optional = True - -warn_return_any = True -warn_unreachable = True -warn_unused_configs = True - -# Turn these options off as it could cause conflicts -# with the Pyright options. -warn_unused_ignores = False -warn_redundant_casts = False - -disallow_any_generics = True -disallow_untyped_defs = True -disallow_untyped_calls = True -disallow_subclassing_any = True -disallow_incomplete_defs = True -disallow_untyped_decorators = True -cache_fine_grained = True - -# By default, mypy reports an error if you assign a value to the result -# of a function call that doesn't return anything. We do this in our test -# cases: -# ``` -# result = ... -# assert result is None -# ``` -# Changing this codegen to make mypy happy would increase complexity -# and would not be worth it. -disable_error_code = func-returns-value,overload-cannot-match - -# https://github.com/python/mypy/issues/12162 -[mypy.overrides] -module = "black.files.*" -ignore_errors = true -ignore_missing_imports = true diff --git a/pyproject.toml b/pyproject.toml index 371a4680..1039ef73 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,30 +1,32 @@ [project] name = "asktable" -version = "5.5.0" +version = "5.6.0" description = "The official Python library for the Asktable API" dynamic = ["readme"] license = "Apache-2.0" authors = [ { name = "Asktable", email = "hi@datamini.ai" }, ] + dependencies = [ - "httpx>=0.23.0, <1", - "pydantic>=1.9.0, <3", - "typing-extensions>=4.10, <5", - "anyio>=3.5.0, <5", - "distro>=1.7.0, <2", - "sniffio", + "httpx>=0.23.0, <1", + "pydantic>=1.9.0, <3", + "typing-extensions>=4.10, <5", + "anyio>=3.5.0, <5", + "distro>=1.7.0, <2", + "sniffio", ] -requires-python = ">= 3.8" + +requires-python = ">= 3.9" classifiers = [ "Typing :: Typed", "Intended Audience :: Developers", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Operating System :: OS Independent", "Operating System :: POSIX", "Operating System :: MacOS", @@ -39,14 +41,14 @@ Homepage = "https://github.com/DataMini/asktable-python" Repository = "https://github.com/DataMini/asktable-python" [project.optional-dependencies] -aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] +aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] [tool.rye] managed = true # version pins are in requirements-dev.lock dev-dependencies = [ "pyright==1.1.399", - "mypy", + "mypy==1.17", "respx", "pytest", "pytest-asyncio", @@ -56,7 +58,6 @@ dev-dependencies = [ "dirty-equals>=0.6.0", "importlib-metadata>=6.7.0", "rich>=13.7.1", - "nest_asyncio==1.6.0", "pytest-xdist>=3.6.1", ] @@ -142,12 +143,13 @@ filterwarnings = [ # there are a couple of flags that are still disabled by # default in strict mode as they are experimental and niche. typeCheckingMode = "strict" -pythonVersion = "3.8" +pythonVersion = "3.9" exclude = [ "_dev", ".venv", ".nox", + ".git", ] reportImplicitOverride = true @@ -156,10 +158,62 @@ reportOverlappingOverload = false reportImportCycles = false reportPrivateUsage = false +[tool.mypy] +pretty = true +show_error_codes = true + +# Exclude _files.py because mypy isn't smart enough to apply +# the correct type narrowing and as this is an internal module +# it's fine to just use Pyright. +# +# We also exclude our `tests` as mypy doesn't always infer +# types correctly and Pyright will still catch any type errors. +exclude = ['src/asktable/_files.py', '_dev/.*.py', 'tests/.*'] + +strict_equality = true +implicit_reexport = true +check_untyped_defs = true +no_implicit_optional = true + +warn_return_any = true +warn_unreachable = true +warn_unused_configs = true + +# Turn these options off as it could cause conflicts +# with the Pyright options. +warn_unused_ignores = false +warn_redundant_casts = false + +disallow_any_generics = true +disallow_untyped_defs = true +disallow_untyped_calls = true +disallow_subclassing_any = true +disallow_incomplete_defs = true +disallow_untyped_decorators = true +cache_fine_grained = true + +# By default, mypy reports an error if you assign a value to the result +# of a function call that doesn't return anything. We do this in our test +# cases: +# ``` +# result = ... +# assert result is None +# ``` +# Changing this codegen to make mypy happy would increase complexity +# and would not be worth it. +disable_error_code = "func-returns-value,overload-cannot-match" + +# https://github.com/python/mypy/issues/12162 +[[tool.mypy.overrides]] +module = "black.files.*" +ignore_errors = true +ignore_missing_imports = true + + [tool.ruff] line-length = 120 output-format = "grouped" -target-version = "py37" +target-version = "py38" [tool.ruff.format] docstring-code-format = true @@ -172,6 +226,8 @@ select = [ "B", # remove unused imports "F401", + # check for missing future annotations + "FA102", # bare except statements "E722", # unused arguments @@ -194,6 +250,8 @@ unfixable = [ "T203", ] +extend-safe-fixes = ["FA102"] + [tool.ruff.lint.flake8-tidy-imports.banned-api] "functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" diff --git a/requirements-dev.lock b/requirements-dev.lock index 9701ab71..6ff2ffd0 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -12,40 +12,45 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.12.8 +aiohttp==3.13.2 # via asktable # via httpx-aiohttp -aiosignal==1.3.2 +aiosignal==1.4.0 # via aiohttp -annotated-types==0.6.0 +annotated-types==0.7.0 # via pydantic -anyio==4.4.0 +anyio==4.12.0 # via asktable # via httpx -argcomplete==3.1.2 +argcomplete==3.6.3 # via nox async-timeout==5.0.1 # via aiohttp -attrs==25.3.0 +attrs==25.4.0 # via aiohttp -certifi==2023.7.22 + # via nox +backports-asyncio-runner==1.2.0 + # via pytest-asyncio +certifi==2025.11.12 # via httpcore # via httpx -colorlog==6.7.0 +colorlog==6.10.1 + # via nox +dependency-groups==1.3.1 # via nox -dirty-equals==0.6.0 -distlib==0.3.7 +dirty-equals==0.11 +distlib==0.4.0 # via virtualenv -distro==1.8.0 +distro==1.9.0 # via asktable -exceptiongroup==1.2.2 +exceptiongroup==1.3.1 # via anyio # via pytest -execnet==2.1.1 +execnet==2.1.2 # via pytest-xdist -filelock==3.12.4 +filelock==3.19.1 # via virtualenv -frozenlist==1.6.2 +frozenlist==1.8.0 # via aiohttp # via aiosignal h11==0.16.0 @@ -56,80 +61,89 @@ httpx==0.28.1 # via asktable # via httpx-aiohttp # via respx -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via asktable -idna==3.4 +humanize==4.13.0 + # via nox +idna==3.11 # via anyio # via httpx # via yarl -importlib-metadata==7.0.0 -iniconfig==2.0.0 +importlib-metadata==8.7.0 +iniconfig==2.1.0 # via pytest markdown-it-py==3.0.0 # via rich mdurl==0.1.2 # via markdown-it-py -multidict==6.4.4 +multidict==6.7.0 # via aiohttp # via yarl -mypy==1.14.1 -mypy-extensions==1.0.0 +mypy==1.17.0 +mypy-extensions==1.1.0 # via mypy -nest-asyncio==1.6.0 -nodeenv==1.8.0 +nodeenv==1.9.1 # via pyright -nox==2023.4.22 -packaging==23.2 +nox==2025.11.12 +packaging==25.0 + # via dependency-groups # via nox # via pytest -platformdirs==3.11.0 +pathspec==0.12.1 + # via mypy +platformdirs==4.4.0 # via virtualenv -pluggy==1.5.0 +pluggy==1.6.0 # via pytest -propcache==0.3.1 +propcache==0.4.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.12.5 # via asktable -pydantic-core==2.27.1 +pydantic-core==2.41.5 # via pydantic -pygments==2.18.0 +pygments==2.19.2 + # via pytest # via rich pyright==1.1.399 -pytest==8.3.3 +pytest==8.4.2 # via pytest-asyncio # via pytest-xdist -pytest-asyncio==0.24.0 -pytest-xdist==3.7.0 -python-dateutil==2.8.2 +pytest-asyncio==1.2.0 +pytest-xdist==3.8.0 +python-dateutil==2.9.0.post0 # via time-machine -pytz==2023.3.post1 - # via dirty-equals respx==0.22.0 -rich==13.7.1 -ruff==0.9.4 -setuptools==68.2.2 - # via nodeenv -six==1.16.0 +rich==14.2.0 +ruff==0.14.7 +six==1.17.0 # via python-dateutil -sniffio==1.3.0 - # via anyio +sniffio==1.3.1 # via asktable -time-machine==2.9.0 -tomli==2.0.2 +time-machine==2.19.0 +tomli==2.3.0 + # via dependency-groups # via mypy + # via nox # via pytest -typing-extensions==4.12.2 +typing-extensions==4.15.0 + # via aiosignal # via anyio # via asktable + # via exceptiongroup # via multidict # via mypy # via pydantic # via pydantic-core # via pyright -virtualenv==20.24.5 + # via pytest-asyncio + # via typing-inspection + # via virtualenv +typing-inspection==0.4.2 + # via pydantic +virtualenv==20.35.4 # via nox -yarl==1.20.0 +yarl==1.22.0 # via aiohttp -zipp==3.17.0 +zipp==3.23.0 # via importlib-metadata diff --git a/requirements.lock b/requirements.lock index ac6e943f..ff194072 100644 --- a/requirements.lock +++ b/requirements.lock @@ -12,28 +12,28 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.12.8 +aiohttp==3.13.2 # via asktable # via httpx-aiohttp -aiosignal==1.3.2 +aiosignal==1.4.0 # via aiohttp -annotated-types==0.6.0 +annotated-types==0.7.0 # via pydantic -anyio==4.4.0 +anyio==4.12.0 # via asktable # via httpx async-timeout==5.0.1 # via aiohttp -attrs==25.3.0 +attrs==25.4.0 # via aiohttp -certifi==2023.7.22 +certifi==2025.11.12 # via httpcore # via httpx -distro==1.8.0 +distro==1.9.0 # via asktable -exceptiongroup==1.2.2 +exceptiongroup==1.3.1 # via anyio -frozenlist==1.6.2 +frozenlist==1.8.0 # via aiohttp # via aiosignal h11==0.16.0 @@ -43,30 +43,34 @@ httpcore==1.0.9 httpx==0.28.1 # via asktable # via httpx-aiohttp -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via asktable -idna==3.4 +idna==3.11 # via anyio # via httpx # via yarl -multidict==6.4.4 +multidict==6.7.0 # via aiohttp # via yarl -propcache==0.3.1 +propcache==0.4.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.12.5 # via asktable -pydantic-core==2.27.1 +pydantic-core==2.41.5 # via pydantic -sniffio==1.3.0 - # via anyio +sniffio==1.3.1 # via asktable -typing-extensions==4.12.2 +typing-extensions==4.15.0 + # via aiosignal # via anyio # via asktable + # via exceptiongroup # via multidict # via pydantic # via pydantic-core -yarl==1.20.0 + # via typing-inspection +typing-inspection==0.4.2 + # via pydantic +yarl==1.22.0 # via aiohttp diff --git a/scripts/bootstrap b/scripts/bootstrap index e84fe62c..b430fee3 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if ! command -v rye >/dev/null 2>&1 && [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi diff --git a/scripts/lint b/scripts/lint index c49721d9..6d495229 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,8 +4,13 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running lints" -rye run lint +if [ "$1" = "--fix" ]; then + echo "==> Running lints with --fix" + rye run fix:ruff +else + echo "==> Running lints" + rye run lint +fi echo "==> Making sure it imports" rye run python -c 'import asktable' diff --git a/scripts/mock b/scripts/mock index d2814ae6..0b28f6ea 100755 --- a/scripts/mock +++ b/scripts/mock @@ -21,7 +21,7 @@ echo "==> Starting mock server with URL ${URL}" # Run prism mock on the given spec if [ "$1" == "--daemon" ]; then - npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & # Wait for server to come online echo -n "Waiting for server" @@ -37,5 +37,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" fi diff --git a/scripts/test b/scripts/test index 2b878456..dbeda2d2 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! prism_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the prism command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" echo exit 1 diff --git a/src/asktable/__init__.py b/src/asktable/__init__.py index 03765db6..38566e5b 100644 --- a/src/asktable/__init__.py +++ b/src/asktable/__init__.py @@ -3,7 +3,7 @@ import typing as _t from . import types -from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given from ._utils import file_from_path from ._client import ( Client, @@ -48,7 +48,9 @@ "ProxiesTypes", "NotGiven", "NOT_GIVEN", + "not_given", "Omit", + "omit", "AsktableError", "APIError", "APIStatusError", diff --git a/src/asktable/_base_client.py b/src/asktable/_base_client.py index 4678a3ee..2128dcdf 100644 --- a/src/asktable/_base_client.py +++ b/src/asktable/_base_client.py @@ -42,7 +42,6 @@ from ._qs import Querystring from ._files import to_httpx_files, async_to_httpx_files from ._types import ( - NOT_GIVEN, Body, Omit, Query, @@ -57,9 +56,10 @@ RequestOptions, HttpxRequestFiles, ModelBuilderProtocol, + not_given, ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping -from ._compat import PYDANTIC_V2, model_copy, model_dump +from ._compat import PYDANTIC_V1, model_copy, model_dump from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type from ._response import ( APIResponse, @@ -145,9 +145,9 @@ def __init__( def __init__( self, *, - url: URL | NotGiven = NOT_GIVEN, - json: Body | NotGiven = NOT_GIVEN, - params: Query | NotGiven = NOT_GIVEN, + url: URL | NotGiven = not_given, + json: Body | NotGiven = not_given, + params: Query | NotGiven = not_given, ) -> None: self.url = url self.json = json @@ -232,7 +232,7 @@ def _set_private_attributes( model: Type[_T], options: FinalRequestOptions, ) -> None: - if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None: + if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} self._model = model @@ -320,7 +320,7 @@ def _set_private_attributes( client: AsyncAPIClient, options: FinalRequestOptions, ) -> None: - if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None: + if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} self._model = model @@ -532,7 +532,10 @@ def _build_request( is_body_allowed = options.method.lower() != "get" if is_body_allowed: - kwargs["json"] = json_data if is_given(json_data) else None + if isinstance(json_data, bytes): + kwargs["content"] = json_data + else: + kwargs["json"] = json_data if is_given(json_data) else None kwargs["files"] = files else: headers.pop("Content-Type", None) @@ -592,7 +595,7 @@ def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalReques # we internally support defining a temporary header to override the # default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response` # see _response.py for implementation details - override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, NOT_GIVEN) + override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, not_given) if is_given(override_cast_to): options.headers = headers return cast(Type[ResponseT], override_cast_to) @@ -822,7 +825,7 @@ def __init__( version: str, base_url: str | URL, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1244,9 +1247,12 @@ def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + opts = FinalRequestOptions.construct( + method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + ) return self.request(cast_to, opts) def put( @@ -1353,7 +1359,7 @@ def __init__( base_url: str | URL, _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1764,9 +1770,12 @@ async def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + opts = FinalRequestOptions.construct( + method="patch", url=path, json_data=body, files=await async_to_httpx_files(files), **options + ) return await self.request(cast_to, opts) async def put( @@ -1815,8 +1824,8 @@ def make_request_options( extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - post_parser: PostParser | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + post_parser: PostParser | NotGiven = not_given, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} diff --git a/src/asktable/_client.py b/src/asktable/_client.py index 5c06a135..a9923d71 100644 --- a/src/asktable/_client.py +++ b/src/asktable/_client.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from typing import Any, Union, Mapping +from typing import TYPE_CHECKING, Any, Mapping from typing_extensions import Self, override import httpx @@ -11,35 +11,17 @@ from . import _exceptions from ._qs import Querystring from ._types import ( - NOT_GIVEN, Omit, Timeout, NotGiven, Transport, ProxiesTypes, RequestOptions, + not_given, ) from ._utils import is_given, get_async_library +from ._compat import cached_property from ._version import __version__ -from .resources import ( - auth, - bots, - sqls, - files, - roles, - caches, - polish, - scores, - answers, - project, - policies, - trainings, - dataframes, - integration, - preferences, - securetunnels, - business_glossary, -) from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import AsktableError, APIStatusError from ._base_client import ( @@ -47,11 +29,52 @@ SyncAPIClient, AsyncAPIClient, ) -from .resources.ats import ats -from .resources.sys import sys -from .resources.user import user -from .resources.chats import chats -from .resources.datasources import datasources + +if TYPE_CHECKING: + from .resources import ( + ats, + sys, + auth, + bots, + sqls, + user, + chats, + files, + roles, + polish, + scores, + answers, + project, + policies, + trainings, + dataframes, + datasources, + integration, + preferences, + securetunnels, + business_glossary, + ) + from .resources.auth import AuthResource, AsyncAuthResource + from .resources.bots import BotsResource, AsyncBotsResource + from .resources.sqls import SqlsResource, AsyncSqlsResource + from .resources.files import FilesResource, AsyncFilesResource + from .resources.roles import RolesResource, AsyncRolesResource + from .resources.polish import PolishResource, AsyncPolishResource + from .resources.scores import ScoresResource, AsyncScoresResource + from .resources.answers import AnswersResource, AsyncAnswersResource + from .resources.ats.ats import ATSResource, AsyncATSResource + from .resources.project import ProjectResource, AsyncProjectResource + from .resources.sys.sys import SysResource, AsyncSysResource + from .resources.policies import PoliciesResource, AsyncPoliciesResource + from .resources.trainings import TrainingsResource, AsyncTrainingsResource + from .resources.user.user import UserResource, AsyncUserResource + from .resources.dataframes import DataframesResource, AsyncDataframesResource + from .resources.chats.chats import ChatsResource, AsyncChatsResource + from .resources.integration import IntegrationResource, AsyncIntegrationResource + from .resources.preferences import PreferencesResource, AsyncPreferencesResource + from .resources.securetunnels import SecuretunnelsResource, AsyncSecuretunnelsResource + from .resources.business_glossary import BusinessGlossaryResource, AsyncBusinessGlossaryResource + from .resources.datasources.datasources import DatasourcesResource, AsyncDatasourcesResource __all__ = [ "Timeout", @@ -66,31 +89,6 @@ class Asktable(SyncAPIClient): - sys: sys.SysResource - securetunnels: securetunnels.SecuretunnelsResource - roles: roles.RolesResource - policies: policies.PoliciesResource - chats: chats.ChatsResource - datasources: datasources.DatasourcesResource - bots: bots.BotsResource - auth: auth.AuthResource - answers: answers.AnswersResource - sqls: sqls.SqlsResource - caches: caches.CachesResource - integration: integration.IntegrationResource - business_glossary: business_glossary.BusinessGlossaryResource - preferences: preferences.PreferencesResource - trainings: trainings.TrainingsResource - project: project.ProjectResource - scores: scores.ScoresResource - files: files.FilesResource - dataframes: dataframes.DataframesResource - polish: polish.PolishResource - user: user.UserResource - ats: ats.ATSResource - with_raw_response: AsktableWithRawResponse - with_streaming_response: AsktableWithStreamedResponse - # client options api_key: str @@ -99,7 +97,7 @@ def __init__( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -145,30 +143,139 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.sys = sys.SysResource(self) - self.securetunnels = securetunnels.SecuretunnelsResource(self) - self.roles = roles.RolesResource(self) - self.policies = policies.PoliciesResource(self) - self.chats = chats.ChatsResource(self) - self.datasources = datasources.DatasourcesResource(self) - self.bots = bots.BotsResource(self) - self.auth = auth.AuthResource(self) - self.answers = answers.AnswersResource(self) - self.sqls = sqls.SqlsResource(self) - self.caches = caches.CachesResource(self) - self.integration = integration.IntegrationResource(self) - self.business_glossary = business_glossary.BusinessGlossaryResource(self) - self.preferences = preferences.PreferencesResource(self) - self.trainings = trainings.TrainingsResource(self) - self.project = project.ProjectResource(self) - self.scores = scores.ScoresResource(self) - self.files = files.FilesResource(self) - self.dataframes = dataframes.DataframesResource(self) - self.polish = polish.PolishResource(self) - self.user = user.UserResource(self) - self.ats = ats.ATSResource(self) - self.with_raw_response = AsktableWithRawResponse(self) - self.with_streaming_response = AsktableWithStreamedResponse(self) + @cached_property + def sys(self) -> SysResource: + from .resources.sys import SysResource + + return SysResource(self) + + @cached_property + def securetunnels(self) -> SecuretunnelsResource: + from .resources.securetunnels import SecuretunnelsResource + + return SecuretunnelsResource(self) + + @cached_property + def roles(self) -> RolesResource: + from .resources.roles import RolesResource + + return RolesResource(self) + + @cached_property + def policies(self) -> PoliciesResource: + from .resources.policies import PoliciesResource + + return PoliciesResource(self) + + @cached_property + def chats(self) -> ChatsResource: + from .resources.chats import ChatsResource + + return ChatsResource(self) + + @cached_property + def datasources(self) -> DatasourcesResource: + from .resources.datasources import DatasourcesResource + + return DatasourcesResource(self) + + @cached_property + def bots(self) -> BotsResource: + from .resources.bots import BotsResource + + return BotsResource(self) + + @cached_property + def auth(self) -> AuthResource: + from .resources.auth import AuthResource + + return AuthResource(self) + + @cached_property + def answers(self) -> AnswersResource: + from .resources.answers import AnswersResource + + return AnswersResource(self) + + @cached_property + def sqls(self) -> SqlsResource: + from .resources.sqls import SqlsResource + + return SqlsResource(self) + + @cached_property + def integration(self) -> IntegrationResource: + from .resources.integration import IntegrationResource + + return IntegrationResource(self) + + @cached_property + def business_glossary(self) -> BusinessGlossaryResource: + from .resources.business_glossary import BusinessGlossaryResource + + return BusinessGlossaryResource(self) + + @cached_property + def preferences(self) -> PreferencesResource: + from .resources.preferences import PreferencesResource + + return PreferencesResource(self) + + @cached_property + def trainings(self) -> TrainingsResource: + from .resources.trainings import TrainingsResource + + return TrainingsResource(self) + + @cached_property + def project(self) -> ProjectResource: + from .resources.project import ProjectResource + + return ProjectResource(self) + + @cached_property + def scores(self) -> ScoresResource: + from .resources.scores import ScoresResource + + return ScoresResource(self) + + @cached_property + def files(self) -> FilesResource: + from .resources.files import FilesResource + + return FilesResource(self) + + @cached_property + def dataframes(self) -> DataframesResource: + from .resources.dataframes import DataframesResource + + return DataframesResource(self) + + @cached_property + def polish(self) -> PolishResource: + from .resources.polish import PolishResource + + return PolishResource(self) + + @cached_property + def user(self) -> UserResource: + from .resources.user import UserResource + + return UserResource(self) + + @cached_property + def ats(self) -> ATSResource: + from .resources.ats import ATSResource + + return ATSResource(self) + + @cached_property + def with_raw_response(self) -> AsktableWithRawResponse: + return AsktableWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsktableWithStreamedResponse: + return AsktableWithStreamedResponse(self) @property @override @@ -195,9 +302,9 @@ def copy( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -276,31 +383,6 @@ def _make_status_error( class AsyncAsktable(AsyncAPIClient): - sys: sys.AsyncSysResource - securetunnels: securetunnels.AsyncSecuretunnelsResource - roles: roles.AsyncRolesResource - policies: policies.AsyncPoliciesResource - chats: chats.AsyncChatsResource - datasources: datasources.AsyncDatasourcesResource - bots: bots.AsyncBotsResource - auth: auth.AsyncAuthResource - answers: answers.AsyncAnswersResource - sqls: sqls.AsyncSqlsResource - caches: caches.AsyncCachesResource - integration: integration.AsyncIntegrationResource - business_glossary: business_glossary.AsyncBusinessGlossaryResource - preferences: preferences.AsyncPreferencesResource - trainings: trainings.AsyncTrainingsResource - project: project.AsyncProjectResource - scores: scores.AsyncScoresResource - files: files.AsyncFilesResource - dataframes: dataframes.AsyncDataframesResource - polish: polish.AsyncPolishResource - user: user.AsyncUserResource - ats: ats.AsyncATSResource - with_raw_response: AsyncAsktableWithRawResponse - with_streaming_response: AsyncAsktableWithStreamedResponse - # client options api_key: str @@ -309,7 +391,7 @@ def __init__( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -355,30 +437,139 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.sys = sys.AsyncSysResource(self) - self.securetunnels = securetunnels.AsyncSecuretunnelsResource(self) - self.roles = roles.AsyncRolesResource(self) - self.policies = policies.AsyncPoliciesResource(self) - self.chats = chats.AsyncChatsResource(self) - self.datasources = datasources.AsyncDatasourcesResource(self) - self.bots = bots.AsyncBotsResource(self) - self.auth = auth.AsyncAuthResource(self) - self.answers = answers.AsyncAnswersResource(self) - self.sqls = sqls.AsyncSqlsResource(self) - self.caches = caches.AsyncCachesResource(self) - self.integration = integration.AsyncIntegrationResource(self) - self.business_glossary = business_glossary.AsyncBusinessGlossaryResource(self) - self.preferences = preferences.AsyncPreferencesResource(self) - self.trainings = trainings.AsyncTrainingsResource(self) - self.project = project.AsyncProjectResource(self) - self.scores = scores.AsyncScoresResource(self) - self.files = files.AsyncFilesResource(self) - self.dataframes = dataframes.AsyncDataframesResource(self) - self.polish = polish.AsyncPolishResource(self) - self.user = user.AsyncUserResource(self) - self.ats = ats.AsyncATSResource(self) - self.with_raw_response = AsyncAsktableWithRawResponse(self) - self.with_streaming_response = AsyncAsktableWithStreamedResponse(self) + @cached_property + def sys(self) -> AsyncSysResource: + from .resources.sys import AsyncSysResource + + return AsyncSysResource(self) + + @cached_property + def securetunnels(self) -> AsyncSecuretunnelsResource: + from .resources.securetunnels import AsyncSecuretunnelsResource + + return AsyncSecuretunnelsResource(self) + + @cached_property + def roles(self) -> AsyncRolesResource: + from .resources.roles import AsyncRolesResource + + return AsyncRolesResource(self) + + @cached_property + def policies(self) -> AsyncPoliciesResource: + from .resources.policies import AsyncPoliciesResource + + return AsyncPoliciesResource(self) + + @cached_property + def chats(self) -> AsyncChatsResource: + from .resources.chats import AsyncChatsResource + + return AsyncChatsResource(self) + + @cached_property + def datasources(self) -> AsyncDatasourcesResource: + from .resources.datasources import AsyncDatasourcesResource + + return AsyncDatasourcesResource(self) + + @cached_property + def bots(self) -> AsyncBotsResource: + from .resources.bots import AsyncBotsResource + + return AsyncBotsResource(self) + + @cached_property + def auth(self) -> AsyncAuthResource: + from .resources.auth import AsyncAuthResource + + return AsyncAuthResource(self) + + @cached_property + def answers(self) -> AsyncAnswersResource: + from .resources.answers import AsyncAnswersResource + + return AsyncAnswersResource(self) + + @cached_property + def sqls(self) -> AsyncSqlsResource: + from .resources.sqls import AsyncSqlsResource + + return AsyncSqlsResource(self) + + @cached_property + def integration(self) -> AsyncIntegrationResource: + from .resources.integration import AsyncIntegrationResource + + return AsyncIntegrationResource(self) + + @cached_property + def business_glossary(self) -> AsyncBusinessGlossaryResource: + from .resources.business_glossary import AsyncBusinessGlossaryResource + + return AsyncBusinessGlossaryResource(self) + + @cached_property + def preferences(self) -> AsyncPreferencesResource: + from .resources.preferences import AsyncPreferencesResource + + return AsyncPreferencesResource(self) + + @cached_property + def trainings(self) -> AsyncTrainingsResource: + from .resources.trainings import AsyncTrainingsResource + + return AsyncTrainingsResource(self) + + @cached_property + def project(self) -> AsyncProjectResource: + from .resources.project import AsyncProjectResource + + return AsyncProjectResource(self) + + @cached_property + def scores(self) -> AsyncScoresResource: + from .resources.scores import AsyncScoresResource + + return AsyncScoresResource(self) + + @cached_property + def files(self) -> AsyncFilesResource: + from .resources.files import AsyncFilesResource + + return AsyncFilesResource(self) + + @cached_property + def dataframes(self) -> AsyncDataframesResource: + from .resources.dataframes import AsyncDataframesResource + + return AsyncDataframesResource(self) + + @cached_property + def polish(self) -> AsyncPolishResource: + from .resources.polish import AsyncPolishResource + + return AsyncPolishResource(self) + + @cached_property + def user(self) -> AsyncUserResource: + from .resources.user import AsyncUserResource + + return AsyncUserResource(self) + + @cached_property + def ats(self) -> AsyncATSResource: + from .resources.ats import AsyncATSResource + + return AsyncATSResource(self) + + @cached_property + def with_raw_response(self) -> AsyncAsktableWithRawResponse: + return AsyncAsktableWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAsktableWithStreamedResponse: + return AsyncAsktableWithStreamedResponse(self) @property @override @@ -405,9 +596,9 @@ def copy( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -486,113 +677,535 @@ def _make_status_error( class AsktableWithRawResponse: + _client: Asktable + def __init__(self, client: Asktable) -> None: - self.sys = sys.SysResourceWithRawResponse(client.sys) - self.securetunnels = securetunnels.SecuretunnelsResourceWithRawResponse(client.securetunnels) - self.roles = roles.RolesResourceWithRawResponse(client.roles) - self.policies = policies.PoliciesResourceWithRawResponse(client.policies) - self.chats = chats.ChatsResourceWithRawResponse(client.chats) - self.datasources = datasources.DatasourcesResourceWithRawResponse(client.datasources) - self.bots = bots.BotsResourceWithRawResponse(client.bots) - self.auth = auth.AuthResourceWithRawResponse(client.auth) - self.answers = answers.AnswersResourceWithRawResponse(client.answers) - self.sqls = sqls.SqlsResourceWithRawResponse(client.sqls) - self.caches = caches.CachesResourceWithRawResponse(client.caches) - self.integration = integration.IntegrationResourceWithRawResponse(client.integration) - self.business_glossary = business_glossary.BusinessGlossaryResourceWithRawResponse(client.business_glossary) - self.preferences = preferences.PreferencesResourceWithRawResponse(client.preferences) - self.trainings = trainings.TrainingsResourceWithRawResponse(client.trainings) - self.project = project.ProjectResourceWithRawResponse(client.project) - self.scores = scores.ScoresResourceWithRawResponse(client.scores) - self.files = files.FilesResourceWithRawResponse(client.files) - self.dataframes = dataframes.DataframesResourceWithRawResponse(client.dataframes) - self.polish = polish.PolishResourceWithRawResponse(client.polish) - self.user = user.UserResourceWithRawResponse(client.user) - self.ats = ats.ATSResourceWithRawResponse(client.ats) + self._client = client + + @cached_property + def sys(self) -> sys.SysResourceWithRawResponse: + from .resources.sys import SysResourceWithRawResponse + + return SysResourceWithRawResponse(self._client.sys) + + @cached_property + def securetunnels(self) -> securetunnels.SecuretunnelsResourceWithRawResponse: + from .resources.securetunnels import SecuretunnelsResourceWithRawResponse + + return SecuretunnelsResourceWithRawResponse(self._client.securetunnels) + + @cached_property + def roles(self) -> roles.RolesResourceWithRawResponse: + from .resources.roles import RolesResourceWithRawResponse + + return RolesResourceWithRawResponse(self._client.roles) + + @cached_property + def policies(self) -> policies.PoliciesResourceWithRawResponse: + from .resources.policies import PoliciesResourceWithRawResponse + + return PoliciesResourceWithRawResponse(self._client.policies) + + @cached_property + def chats(self) -> chats.ChatsResourceWithRawResponse: + from .resources.chats import ChatsResourceWithRawResponse + + return ChatsResourceWithRawResponse(self._client.chats) + + @cached_property + def datasources(self) -> datasources.DatasourcesResourceWithRawResponse: + from .resources.datasources import DatasourcesResourceWithRawResponse + + return DatasourcesResourceWithRawResponse(self._client.datasources) + + @cached_property + def bots(self) -> bots.BotsResourceWithRawResponse: + from .resources.bots import BotsResourceWithRawResponse + + return BotsResourceWithRawResponse(self._client.bots) + + @cached_property + def auth(self) -> auth.AuthResourceWithRawResponse: + from .resources.auth import AuthResourceWithRawResponse + + return AuthResourceWithRawResponse(self._client.auth) + + @cached_property + def answers(self) -> answers.AnswersResourceWithRawResponse: + from .resources.answers import AnswersResourceWithRawResponse + + return AnswersResourceWithRawResponse(self._client.answers) + + @cached_property + def sqls(self) -> sqls.SqlsResourceWithRawResponse: + from .resources.sqls import SqlsResourceWithRawResponse + + return SqlsResourceWithRawResponse(self._client.sqls) + + @cached_property + def integration(self) -> integration.IntegrationResourceWithRawResponse: + from .resources.integration import IntegrationResourceWithRawResponse + + return IntegrationResourceWithRawResponse(self._client.integration) + + @cached_property + def business_glossary(self) -> business_glossary.BusinessGlossaryResourceWithRawResponse: + from .resources.business_glossary import BusinessGlossaryResourceWithRawResponse + + return BusinessGlossaryResourceWithRawResponse(self._client.business_glossary) + + @cached_property + def preferences(self) -> preferences.PreferencesResourceWithRawResponse: + from .resources.preferences import PreferencesResourceWithRawResponse + + return PreferencesResourceWithRawResponse(self._client.preferences) + + @cached_property + def trainings(self) -> trainings.TrainingsResourceWithRawResponse: + from .resources.trainings import TrainingsResourceWithRawResponse + + return TrainingsResourceWithRawResponse(self._client.trainings) + + @cached_property + def project(self) -> project.ProjectResourceWithRawResponse: + from .resources.project import ProjectResourceWithRawResponse + + return ProjectResourceWithRawResponse(self._client.project) + + @cached_property + def scores(self) -> scores.ScoresResourceWithRawResponse: + from .resources.scores import ScoresResourceWithRawResponse + + return ScoresResourceWithRawResponse(self._client.scores) + + @cached_property + def files(self) -> files.FilesResourceWithRawResponse: + from .resources.files import FilesResourceWithRawResponse + + return FilesResourceWithRawResponse(self._client.files) + + @cached_property + def dataframes(self) -> dataframes.DataframesResourceWithRawResponse: + from .resources.dataframes import DataframesResourceWithRawResponse + + return DataframesResourceWithRawResponse(self._client.dataframes) + + @cached_property + def polish(self) -> polish.PolishResourceWithRawResponse: + from .resources.polish import PolishResourceWithRawResponse + + return PolishResourceWithRawResponse(self._client.polish) + + @cached_property + def user(self) -> user.UserResourceWithRawResponse: + from .resources.user import UserResourceWithRawResponse + + return UserResourceWithRawResponse(self._client.user) + + @cached_property + def ats(self) -> ats.ATSResourceWithRawResponse: + from .resources.ats import ATSResourceWithRawResponse + + return ATSResourceWithRawResponse(self._client.ats) class AsyncAsktableWithRawResponse: + _client: AsyncAsktable + def __init__(self, client: AsyncAsktable) -> None: - self.sys = sys.AsyncSysResourceWithRawResponse(client.sys) - self.securetunnels = securetunnels.AsyncSecuretunnelsResourceWithRawResponse(client.securetunnels) - self.roles = roles.AsyncRolesResourceWithRawResponse(client.roles) - self.policies = policies.AsyncPoliciesResourceWithRawResponse(client.policies) - self.chats = chats.AsyncChatsResourceWithRawResponse(client.chats) - self.datasources = datasources.AsyncDatasourcesResourceWithRawResponse(client.datasources) - self.bots = bots.AsyncBotsResourceWithRawResponse(client.bots) - self.auth = auth.AsyncAuthResourceWithRawResponse(client.auth) - self.answers = answers.AsyncAnswersResourceWithRawResponse(client.answers) - self.sqls = sqls.AsyncSqlsResourceWithRawResponse(client.sqls) - self.caches = caches.AsyncCachesResourceWithRawResponse(client.caches) - self.integration = integration.AsyncIntegrationResourceWithRawResponse(client.integration) - self.business_glossary = business_glossary.AsyncBusinessGlossaryResourceWithRawResponse( - client.business_glossary - ) - self.preferences = preferences.AsyncPreferencesResourceWithRawResponse(client.preferences) - self.trainings = trainings.AsyncTrainingsResourceWithRawResponse(client.trainings) - self.project = project.AsyncProjectResourceWithRawResponse(client.project) - self.scores = scores.AsyncScoresResourceWithRawResponse(client.scores) - self.files = files.AsyncFilesResourceWithRawResponse(client.files) - self.dataframes = dataframes.AsyncDataframesResourceWithRawResponse(client.dataframes) - self.polish = polish.AsyncPolishResourceWithRawResponse(client.polish) - self.user = user.AsyncUserResourceWithRawResponse(client.user) - self.ats = ats.AsyncATSResourceWithRawResponse(client.ats) + self._client = client + + @cached_property + def sys(self) -> sys.AsyncSysResourceWithRawResponse: + from .resources.sys import AsyncSysResourceWithRawResponse + + return AsyncSysResourceWithRawResponse(self._client.sys) + + @cached_property + def securetunnels(self) -> securetunnels.AsyncSecuretunnelsResourceWithRawResponse: + from .resources.securetunnels import AsyncSecuretunnelsResourceWithRawResponse + + return AsyncSecuretunnelsResourceWithRawResponse(self._client.securetunnels) + + @cached_property + def roles(self) -> roles.AsyncRolesResourceWithRawResponse: + from .resources.roles import AsyncRolesResourceWithRawResponse + + return AsyncRolesResourceWithRawResponse(self._client.roles) + + @cached_property + def policies(self) -> policies.AsyncPoliciesResourceWithRawResponse: + from .resources.policies import AsyncPoliciesResourceWithRawResponse + + return AsyncPoliciesResourceWithRawResponse(self._client.policies) + + @cached_property + def chats(self) -> chats.AsyncChatsResourceWithRawResponse: + from .resources.chats import AsyncChatsResourceWithRawResponse + + return AsyncChatsResourceWithRawResponse(self._client.chats) + + @cached_property + def datasources(self) -> datasources.AsyncDatasourcesResourceWithRawResponse: + from .resources.datasources import AsyncDatasourcesResourceWithRawResponse + + return AsyncDatasourcesResourceWithRawResponse(self._client.datasources) + + @cached_property + def bots(self) -> bots.AsyncBotsResourceWithRawResponse: + from .resources.bots import AsyncBotsResourceWithRawResponse + + return AsyncBotsResourceWithRawResponse(self._client.bots) + + @cached_property + def auth(self) -> auth.AsyncAuthResourceWithRawResponse: + from .resources.auth import AsyncAuthResourceWithRawResponse + + return AsyncAuthResourceWithRawResponse(self._client.auth) + + @cached_property + def answers(self) -> answers.AsyncAnswersResourceWithRawResponse: + from .resources.answers import AsyncAnswersResourceWithRawResponse + + return AsyncAnswersResourceWithRawResponse(self._client.answers) + + @cached_property + def sqls(self) -> sqls.AsyncSqlsResourceWithRawResponse: + from .resources.sqls import AsyncSqlsResourceWithRawResponse + + return AsyncSqlsResourceWithRawResponse(self._client.sqls) + + @cached_property + def integration(self) -> integration.AsyncIntegrationResourceWithRawResponse: + from .resources.integration import AsyncIntegrationResourceWithRawResponse + + return AsyncIntegrationResourceWithRawResponse(self._client.integration) + + @cached_property + def business_glossary(self) -> business_glossary.AsyncBusinessGlossaryResourceWithRawResponse: + from .resources.business_glossary import AsyncBusinessGlossaryResourceWithRawResponse + + return AsyncBusinessGlossaryResourceWithRawResponse(self._client.business_glossary) + + @cached_property + def preferences(self) -> preferences.AsyncPreferencesResourceWithRawResponse: + from .resources.preferences import AsyncPreferencesResourceWithRawResponse + + return AsyncPreferencesResourceWithRawResponse(self._client.preferences) + + @cached_property + def trainings(self) -> trainings.AsyncTrainingsResourceWithRawResponse: + from .resources.trainings import AsyncTrainingsResourceWithRawResponse + + return AsyncTrainingsResourceWithRawResponse(self._client.trainings) + + @cached_property + def project(self) -> project.AsyncProjectResourceWithRawResponse: + from .resources.project import AsyncProjectResourceWithRawResponse + + return AsyncProjectResourceWithRawResponse(self._client.project) + + @cached_property + def scores(self) -> scores.AsyncScoresResourceWithRawResponse: + from .resources.scores import AsyncScoresResourceWithRawResponse + + return AsyncScoresResourceWithRawResponse(self._client.scores) + + @cached_property + def files(self) -> files.AsyncFilesResourceWithRawResponse: + from .resources.files import AsyncFilesResourceWithRawResponse + + return AsyncFilesResourceWithRawResponse(self._client.files) + + @cached_property + def dataframes(self) -> dataframes.AsyncDataframesResourceWithRawResponse: + from .resources.dataframes import AsyncDataframesResourceWithRawResponse + + return AsyncDataframesResourceWithRawResponse(self._client.dataframes) + + @cached_property + def polish(self) -> polish.AsyncPolishResourceWithRawResponse: + from .resources.polish import AsyncPolishResourceWithRawResponse + + return AsyncPolishResourceWithRawResponse(self._client.polish) + + @cached_property + def user(self) -> user.AsyncUserResourceWithRawResponse: + from .resources.user import AsyncUserResourceWithRawResponse + + return AsyncUserResourceWithRawResponse(self._client.user) + + @cached_property + def ats(self) -> ats.AsyncATSResourceWithRawResponse: + from .resources.ats import AsyncATSResourceWithRawResponse + + return AsyncATSResourceWithRawResponse(self._client.ats) class AsktableWithStreamedResponse: + _client: Asktable + def __init__(self, client: Asktable) -> None: - self.sys = sys.SysResourceWithStreamingResponse(client.sys) - self.securetunnels = securetunnels.SecuretunnelsResourceWithStreamingResponse(client.securetunnels) - self.roles = roles.RolesResourceWithStreamingResponse(client.roles) - self.policies = policies.PoliciesResourceWithStreamingResponse(client.policies) - self.chats = chats.ChatsResourceWithStreamingResponse(client.chats) - self.datasources = datasources.DatasourcesResourceWithStreamingResponse(client.datasources) - self.bots = bots.BotsResourceWithStreamingResponse(client.bots) - self.auth = auth.AuthResourceWithStreamingResponse(client.auth) - self.answers = answers.AnswersResourceWithStreamingResponse(client.answers) - self.sqls = sqls.SqlsResourceWithStreamingResponse(client.sqls) - self.caches = caches.CachesResourceWithStreamingResponse(client.caches) - self.integration = integration.IntegrationResourceWithStreamingResponse(client.integration) - self.business_glossary = business_glossary.BusinessGlossaryResourceWithStreamingResponse( - client.business_glossary - ) - self.preferences = preferences.PreferencesResourceWithStreamingResponse(client.preferences) - self.trainings = trainings.TrainingsResourceWithStreamingResponse(client.trainings) - self.project = project.ProjectResourceWithStreamingResponse(client.project) - self.scores = scores.ScoresResourceWithStreamingResponse(client.scores) - self.files = files.FilesResourceWithStreamingResponse(client.files) - self.dataframes = dataframes.DataframesResourceWithStreamingResponse(client.dataframes) - self.polish = polish.PolishResourceWithStreamingResponse(client.polish) - self.user = user.UserResourceWithStreamingResponse(client.user) - self.ats = ats.ATSResourceWithStreamingResponse(client.ats) + self._client = client + + @cached_property + def sys(self) -> sys.SysResourceWithStreamingResponse: + from .resources.sys import SysResourceWithStreamingResponse + + return SysResourceWithStreamingResponse(self._client.sys) + + @cached_property + def securetunnels(self) -> securetunnels.SecuretunnelsResourceWithStreamingResponse: + from .resources.securetunnels import SecuretunnelsResourceWithStreamingResponse + + return SecuretunnelsResourceWithStreamingResponse(self._client.securetunnels) + + @cached_property + def roles(self) -> roles.RolesResourceWithStreamingResponse: + from .resources.roles import RolesResourceWithStreamingResponse + + return RolesResourceWithStreamingResponse(self._client.roles) + + @cached_property + def policies(self) -> policies.PoliciesResourceWithStreamingResponse: + from .resources.policies import PoliciesResourceWithStreamingResponse + + return PoliciesResourceWithStreamingResponse(self._client.policies) + + @cached_property + def chats(self) -> chats.ChatsResourceWithStreamingResponse: + from .resources.chats import ChatsResourceWithStreamingResponse + + return ChatsResourceWithStreamingResponse(self._client.chats) + + @cached_property + def datasources(self) -> datasources.DatasourcesResourceWithStreamingResponse: + from .resources.datasources import DatasourcesResourceWithStreamingResponse + + return DatasourcesResourceWithStreamingResponse(self._client.datasources) + + @cached_property + def bots(self) -> bots.BotsResourceWithStreamingResponse: + from .resources.bots import BotsResourceWithStreamingResponse + + return BotsResourceWithStreamingResponse(self._client.bots) + + @cached_property + def auth(self) -> auth.AuthResourceWithStreamingResponse: + from .resources.auth import AuthResourceWithStreamingResponse + + return AuthResourceWithStreamingResponse(self._client.auth) + + @cached_property + def answers(self) -> answers.AnswersResourceWithStreamingResponse: + from .resources.answers import AnswersResourceWithStreamingResponse + + return AnswersResourceWithStreamingResponse(self._client.answers) + + @cached_property + def sqls(self) -> sqls.SqlsResourceWithStreamingResponse: + from .resources.sqls import SqlsResourceWithStreamingResponse + + return SqlsResourceWithStreamingResponse(self._client.sqls) + + @cached_property + def integration(self) -> integration.IntegrationResourceWithStreamingResponse: + from .resources.integration import IntegrationResourceWithStreamingResponse + + return IntegrationResourceWithStreamingResponse(self._client.integration) + + @cached_property + def business_glossary(self) -> business_glossary.BusinessGlossaryResourceWithStreamingResponse: + from .resources.business_glossary import BusinessGlossaryResourceWithStreamingResponse + + return BusinessGlossaryResourceWithStreamingResponse(self._client.business_glossary) + + @cached_property + def preferences(self) -> preferences.PreferencesResourceWithStreamingResponse: + from .resources.preferences import PreferencesResourceWithStreamingResponse + + return PreferencesResourceWithStreamingResponse(self._client.preferences) + + @cached_property + def trainings(self) -> trainings.TrainingsResourceWithStreamingResponse: + from .resources.trainings import TrainingsResourceWithStreamingResponse + + return TrainingsResourceWithStreamingResponse(self._client.trainings) + + @cached_property + def project(self) -> project.ProjectResourceWithStreamingResponse: + from .resources.project import ProjectResourceWithStreamingResponse + + return ProjectResourceWithStreamingResponse(self._client.project) + + @cached_property + def scores(self) -> scores.ScoresResourceWithStreamingResponse: + from .resources.scores import ScoresResourceWithStreamingResponse + + return ScoresResourceWithStreamingResponse(self._client.scores) + + @cached_property + def files(self) -> files.FilesResourceWithStreamingResponse: + from .resources.files import FilesResourceWithStreamingResponse + + return FilesResourceWithStreamingResponse(self._client.files) + + @cached_property + def dataframes(self) -> dataframes.DataframesResourceWithStreamingResponse: + from .resources.dataframes import DataframesResourceWithStreamingResponse + + return DataframesResourceWithStreamingResponse(self._client.dataframes) + + @cached_property + def polish(self) -> polish.PolishResourceWithStreamingResponse: + from .resources.polish import PolishResourceWithStreamingResponse + + return PolishResourceWithStreamingResponse(self._client.polish) + + @cached_property + def user(self) -> user.UserResourceWithStreamingResponse: + from .resources.user import UserResourceWithStreamingResponse + + return UserResourceWithStreamingResponse(self._client.user) + + @cached_property + def ats(self) -> ats.ATSResourceWithStreamingResponse: + from .resources.ats import ATSResourceWithStreamingResponse + + return ATSResourceWithStreamingResponse(self._client.ats) class AsyncAsktableWithStreamedResponse: + _client: AsyncAsktable + def __init__(self, client: AsyncAsktable) -> None: - self.sys = sys.AsyncSysResourceWithStreamingResponse(client.sys) - self.securetunnels = securetunnels.AsyncSecuretunnelsResourceWithStreamingResponse(client.securetunnels) - self.roles = roles.AsyncRolesResourceWithStreamingResponse(client.roles) - self.policies = policies.AsyncPoliciesResourceWithStreamingResponse(client.policies) - self.chats = chats.AsyncChatsResourceWithStreamingResponse(client.chats) - self.datasources = datasources.AsyncDatasourcesResourceWithStreamingResponse(client.datasources) - self.bots = bots.AsyncBotsResourceWithStreamingResponse(client.bots) - self.auth = auth.AsyncAuthResourceWithStreamingResponse(client.auth) - self.answers = answers.AsyncAnswersResourceWithStreamingResponse(client.answers) - self.sqls = sqls.AsyncSqlsResourceWithStreamingResponse(client.sqls) - self.caches = caches.AsyncCachesResourceWithStreamingResponse(client.caches) - self.integration = integration.AsyncIntegrationResourceWithStreamingResponse(client.integration) - self.business_glossary = business_glossary.AsyncBusinessGlossaryResourceWithStreamingResponse( - client.business_glossary - ) - self.preferences = preferences.AsyncPreferencesResourceWithStreamingResponse(client.preferences) - self.trainings = trainings.AsyncTrainingsResourceWithStreamingResponse(client.trainings) - self.project = project.AsyncProjectResourceWithStreamingResponse(client.project) - self.scores = scores.AsyncScoresResourceWithStreamingResponse(client.scores) - self.files = files.AsyncFilesResourceWithStreamingResponse(client.files) - self.dataframes = dataframes.AsyncDataframesResourceWithStreamingResponse(client.dataframes) - self.polish = polish.AsyncPolishResourceWithStreamingResponse(client.polish) - self.user = user.AsyncUserResourceWithStreamingResponse(client.user) - self.ats = ats.AsyncATSResourceWithStreamingResponse(client.ats) + self._client = client + + @cached_property + def sys(self) -> sys.AsyncSysResourceWithStreamingResponse: + from .resources.sys import AsyncSysResourceWithStreamingResponse + + return AsyncSysResourceWithStreamingResponse(self._client.sys) + + @cached_property + def securetunnels(self) -> securetunnels.AsyncSecuretunnelsResourceWithStreamingResponse: + from .resources.securetunnels import AsyncSecuretunnelsResourceWithStreamingResponse + + return AsyncSecuretunnelsResourceWithStreamingResponse(self._client.securetunnels) + + @cached_property + def roles(self) -> roles.AsyncRolesResourceWithStreamingResponse: + from .resources.roles import AsyncRolesResourceWithStreamingResponse + + return AsyncRolesResourceWithStreamingResponse(self._client.roles) + + @cached_property + def policies(self) -> policies.AsyncPoliciesResourceWithStreamingResponse: + from .resources.policies import AsyncPoliciesResourceWithStreamingResponse + + return AsyncPoliciesResourceWithStreamingResponse(self._client.policies) + + @cached_property + def chats(self) -> chats.AsyncChatsResourceWithStreamingResponse: + from .resources.chats import AsyncChatsResourceWithStreamingResponse + + return AsyncChatsResourceWithStreamingResponse(self._client.chats) + + @cached_property + def datasources(self) -> datasources.AsyncDatasourcesResourceWithStreamingResponse: + from .resources.datasources import AsyncDatasourcesResourceWithStreamingResponse + + return AsyncDatasourcesResourceWithStreamingResponse(self._client.datasources) + + @cached_property + def bots(self) -> bots.AsyncBotsResourceWithStreamingResponse: + from .resources.bots import AsyncBotsResourceWithStreamingResponse + + return AsyncBotsResourceWithStreamingResponse(self._client.bots) + + @cached_property + def auth(self) -> auth.AsyncAuthResourceWithStreamingResponse: + from .resources.auth import AsyncAuthResourceWithStreamingResponse + + return AsyncAuthResourceWithStreamingResponse(self._client.auth) + + @cached_property + def answers(self) -> answers.AsyncAnswersResourceWithStreamingResponse: + from .resources.answers import AsyncAnswersResourceWithStreamingResponse + + return AsyncAnswersResourceWithStreamingResponse(self._client.answers) + + @cached_property + def sqls(self) -> sqls.AsyncSqlsResourceWithStreamingResponse: + from .resources.sqls import AsyncSqlsResourceWithStreamingResponse + + return AsyncSqlsResourceWithStreamingResponse(self._client.sqls) + + @cached_property + def integration(self) -> integration.AsyncIntegrationResourceWithStreamingResponse: + from .resources.integration import AsyncIntegrationResourceWithStreamingResponse + + return AsyncIntegrationResourceWithStreamingResponse(self._client.integration) + + @cached_property + def business_glossary(self) -> business_glossary.AsyncBusinessGlossaryResourceWithStreamingResponse: + from .resources.business_glossary import AsyncBusinessGlossaryResourceWithStreamingResponse + + return AsyncBusinessGlossaryResourceWithStreamingResponse(self._client.business_glossary) + + @cached_property + def preferences(self) -> preferences.AsyncPreferencesResourceWithStreamingResponse: + from .resources.preferences import AsyncPreferencesResourceWithStreamingResponse + + return AsyncPreferencesResourceWithStreamingResponse(self._client.preferences) + + @cached_property + def trainings(self) -> trainings.AsyncTrainingsResourceWithStreamingResponse: + from .resources.trainings import AsyncTrainingsResourceWithStreamingResponse + + return AsyncTrainingsResourceWithStreamingResponse(self._client.trainings) + + @cached_property + def project(self) -> project.AsyncProjectResourceWithStreamingResponse: + from .resources.project import AsyncProjectResourceWithStreamingResponse + + return AsyncProjectResourceWithStreamingResponse(self._client.project) + + @cached_property + def scores(self) -> scores.AsyncScoresResourceWithStreamingResponse: + from .resources.scores import AsyncScoresResourceWithStreamingResponse + + return AsyncScoresResourceWithStreamingResponse(self._client.scores) + + @cached_property + def files(self) -> files.AsyncFilesResourceWithStreamingResponse: + from .resources.files import AsyncFilesResourceWithStreamingResponse + + return AsyncFilesResourceWithStreamingResponse(self._client.files) + + @cached_property + def dataframes(self) -> dataframes.AsyncDataframesResourceWithStreamingResponse: + from .resources.dataframes import AsyncDataframesResourceWithStreamingResponse + + return AsyncDataframesResourceWithStreamingResponse(self._client.dataframes) + + @cached_property + def polish(self) -> polish.AsyncPolishResourceWithStreamingResponse: + from .resources.polish import AsyncPolishResourceWithStreamingResponse + + return AsyncPolishResourceWithStreamingResponse(self._client.polish) + + @cached_property + def user(self) -> user.AsyncUserResourceWithStreamingResponse: + from .resources.user import AsyncUserResourceWithStreamingResponse + + return AsyncUserResourceWithStreamingResponse(self._client.user) + + @cached_property + def ats(self) -> ats.AsyncATSResourceWithStreamingResponse: + from .resources.ats import AsyncATSResourceWithStreamingResponse + + return AsyncATSResourceWithStreamingResponse(self._client.ats) Client = Asktable diff --git a/src/asktable/_compat.py b/src/asktable/_compat.py index 92d9ee61..bdef67f0 100644 --- a/src/asktable/_compat.py +++ b/src/asktable/_compat.py @@ -12,14 +12,13 @@ _T = TypeVar("_T") _ModelT = TypeVar("_ModelT", bound=pydantic.BaseModel) -# --------------- Pydantic v2 compatibility --------------- +# --------------- Pydantic v2, v3 compatibility --------------- # Pyright incorrectly reports some of our functions as overriding a method when they don't # pyright: reportIncompatibleMethodOverride=false -PYDANTIC_V2 = pydantic.VERSION.startswith("2.") +PYDANTIC_V1 = pydantic.VERSION.startswith("1.") -# v1 re-exports if TYPE_CHECKING: def parse_date(value: date | StrBytesIntFloat) -> date: # noqa: ARG001 @@ -44,90 +43,92 @@ def is_typeddict(type_: type[Any]) -> bool: # noqa: ARG001 ... else: - if PYDANTIC_V2: - from pydantic.v1.typing import ( + # v1 re-exports + if PYDANTIC_V1: + from pydantic.typing import ( get_args as get_args, is_union as is_union, get_origin as get_origin, is_typeddict as is_typeddict, is_literal_type as is_literal_type, ) - from pydantic.v1.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime + from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime else: - from pydantic.typing import ( + from ._utils import ( get_args as get_args, is_union as is_union, get_origin as get_origin, + parse_date as parse_date, is_typeddict as is_typeddict, + parse_datetime as parse_datetime, is_literal_type as is_literal_type, ) - from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime # refactored config if TYPE_CHECKING: from pydantic import ConfigDict as ConfigDict else: - if PYDANTIC_V2: - from pydantic import ConfigDict - else: + if PYDANTIC_V1: # TODO: provide an error message here? ConfigDict = None + else: + from pydantic import ConfigDict as ConfigDict # renamed methods / properties def parse_obj(model: type[_ModelT], value: object) -> _ModelT: - if PYDANTIC_V2: - return model.model_validate(value) - else: + if PYDANTIC_V1: return cast(_ModelT, model.parse_obj(value)) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + else: + return model.model_validate(value) def field_is_required(field: FieldInfo) -> bool: - if PYDANTIC_V2: - return field.is_required() - return field.required # type: ignore + if PYDANTIC_V1: + return field.required # type: ignore + return field.is_required() def field_get_default(field: FieldInfo) -> Any: value = field.get_default() - if PYDANTIC_V2: - from pydantic_core import PydanticUndefined - - if value == PydanticUndefined: - return None + if PYDANTIC_V1: return value + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None return value def field_outer_type(field: FieldInfo) -> Any: - if PYDANTIC_V2: - return field.annotation - return field.outer_type_ # type: ignore + if PYDANTIC_V1: + return field.outer_type_ # type: ignore + return field.annotation def get_model_config(model: type[pydantic.BaseModel]) -> Any: - if PYDANTIC_V2: - return model.model_config - return model.__config__ # type: ignore + if PYDANTIC_V1: + return model.__config__ # type: ignore + return model.model_config def get_model_fields(model: type[pydantic.BaseModel]) -> dict[str, FieldInfo]: - if PYDANTIC_V2: - return model.model_fields - return model.__fields__ # type: ignore + if PYDANTIC_V1: + return model.__fields__ # type: ignore + return model.model_fields def model_copy(model: _ModelT, *, deep: bool = False) -> _ModelT: - if PYDANTIC_V2: - return model.model_copy(deep=deep) - return model.copy(deep=deep) # type: ignore + if PYDANTIC_V1: + return model.copy(deep=deep) # type: ignore + return model.model_copy(deep=deep) def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: - if PYDANTIC_V2: - return model.model_dump_json(indent=indent) - return model.json(indent=indent) # type: ignore + if PYDANTIC_V1: + return model.json(indent=indent) # type: ignore + return model.model_dump_json(indent=indent) def model_dump( @@ -139,14 +140,14 @@ def model_dump( warnings: bool = True, mode: Literal["json", "python"] = "python", ) -> dict[str, Any]: - if PYDANTIC_V2 or hasattr(model, "model_dump"): + if (not PYDANTIC_V1) or hasattr(model, "model_dump"): return model.model_dump( mode=mode, exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, # warnings are not supported in Pydantic v1 - warnings=warnings if PYDANTIC_V2 else True, + warnings=True if PYDANTIC_V1 else warnings, ) return cast( "dict[str, Any]", @@ -159,9 +160,9 @@ def model_dump( def model_parse(model: type[_ModelT], data: Any) -> _ModelT: - if PYDANTIC_V2: - return model.model_validate(data) - return model.parse_obj(data) # pyright: ignore[reportDeprecated] + if PYDANTIC_V1: + return model.parse_obj(data) # pyright: ignore[reportDeprecated] + return model.model_validate(data) # generic models @@ -170,17 +171,16 @@ def model_parse(model: type[_ModelT], data: Any) -> _ModelT: class GenericModel(pydantic.BaseModel): ... else: - if PYDANTIC_V2: + if PYDANTIC_V1: + import pydantic.generics + + class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... + else: # there no longer needs to be a distinction in v2 but # we still have to create our own subclass to avoid # inconsistent MRO ordering errors class GenericModel(pydantic.BaseModel): ... - else: - import pydantic.generics - - class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... - # cached properties if TYPE_CHECKING: diff --git a/src/asktable/_files.py b/src/asktable/_files.py index 25ff804f..978df31d 100644 --- a/src/asktable/_files.py +++ b/src/asktable/_files.py @@ -69,12 +69,12 @@ def _transform_file(file: FileTypes) -> HttpxFileTypes: return file if is_tuple_t(file): - return (file[0], _read_file_content(file[1]), *file[2:]) + return (file[0], read_file_content(file[1]), *file[2:]) raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") -def _read_file_content(file: FileContent) -> HttpxFileContent: +def read_file_content(file: FileContent) -> HttpxFileContent: if isinstance(file, os.PathLike): return pathlib.Path(file).read_bytes() return file @@ -111,12 +111,12 @@ async def _async_transform_file(file: FileTypes) -> HttpxFileTypes: return file if is_tuple_t(file): - return (file[0], await _async_read_file_content(file[1]), *file[2:]) + return (file[0], await async_read_file_content(file[1]), *file[2:]) raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") -async def _async_read_file_content(file: FileContent) -> HttpxFileContent: +async def async_read_file_content(file: FileContent) -> HttpxFileContent: if isinstance(file, os.PathLike): return await anyio.Path(file).read_bytes() diff --git a/src/asktable/_models.py b/src/asktable/_models.py index 528d5680..ca9500b2 100644 --- a/src/asktable/_models.py +++ b/src/asktable/_models.py @@ -2,6 +2,7 @@ import os import inspect +import weakref from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast from datetime import date, datetime from typing_extensions import ( @@ -50,7 +51,7 @@ strip_annotated_type, ) from ._compat import ( - PYDANTIC_V2, + PYDANTIC_V1, ConfigDict, GenericModel as BaseGenericModel, get_args, @@ -81,11 +82,7 @@ class _ConfigProtocol(Protocol): class BaseModel(pydantic.BaseModel): - if PYDANTIC_V2: - model_config: ClassVar[ConfigDict] = ConfigDict( - extra="allow", defer_build=coerce_boolean(os.environ.get("DEFER_PYDANTIC_BUILD", "true")) - ) - else: + if PYDANTIC_V1: @property @override @@ -95,6 +92,10 @@ def model_fields_set(self) -> set[str]: class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] extra: Any = pydantic.Extra.allow # type: ignore + else: + model_config: ClassVar[ConfigDict] = ConfigDict( + extra="allow", defer_build=coerce_boolean(os.environ.get("DEFER_PYDANTIC_BUILD", "true")) + ) def to_dict( self, @@ -208,28 +209,32 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride] else: fields_values[name] = field_get_default(field) + extra_field_type = _get_extra_fields_type(__cls) + _extra = {} for key, value in values.items(): if key not in model_fields: - if PYDANTIC_V2: - _extra[key] = value - else: + parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value + + if PYDANTIC_V1: _fields_set.add(key) - fields_values[key] = value + fields_values[key] = parsed + else: + _extra[key] = parsed object.__setattr__(m, "__dict__", fields_values) - if PYDANTIC_V2: - # these properties are copied from Pydantic's `model_construct()` method - object.__setattr__(m, "__pydantic_private__", None) - object.__setattr__(m, "__pydantic_extra__", _extra) - object.__setattr__(m, "__pydantic_fields_set__", _fields_set) - else: + if PYDANTIC_V1: # init_private_attributes() does not exist in v2 m._init_private_attributes() # type: ignore # copied from Pydantic v1's `construct()` method object.__setattr__(m, "__fields_set__", _fields_set) + else: + # these properties are copied from Pydantic's `model_construct()` method + object.__setattr__(m, "__pydantic_private__", None) + object.__setattr__(m, "__pydantic_extra__", _extra) + object.__setattr__(m, "__pydantic_fields_set__", _fields_set) return m @@ -239,7 +244,7 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride] # although not in practice model_construct = construct - if not PYDANTIC_V2: + if PYDANTIC_V1: # we define aliases for some of the new pydantic v2 methods so # that we can just document these methods without having to specify # a specific pydantic version as some users may not know which @@ -252,13 +257,15 @@ def model_dump( mode: Literal["json", "python"] | str = "python", include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + context: Any | None = None, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, + exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, - context: dict[str, Any] | None = None, + fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> dict[str, Any]: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump @@ -267,16 +274,24 @@ def model_dump( Args: mode: The mode in which `to_python` should run. - If mode is 'json', the dictionary will only contain JSON serializable types. - If mode is 'python', the dictionary may contain any Python objects. - include: A list of fields to include in the output. - exclude: A list of fields to exclude from the output. + If mode is 'json', the output will only contain JSON serializable types. + If mode is 'python', the output may contain non-JSON-serializable Python objects. + include: A set of fields to include in the output. + exclude: A set of fields to exclude from the output. + context: Additional context to pass to the serializer. by_alias: Whether to use the field's alias in the dictionary key if defined. - exclude_unset: Whether to exclude fields that are unset or None from the output. - exclude_defaults: Whether to exclude fields that are set to their default value from the output. - exclude_none: Whether to exclude fields that have a value of `None` from the output. - round_trip: Whether to enable serialization and deserialization round-trip support. - warnings: Whether to log warnings when invalid fields are encountered. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that are set to their default value. + exclude_none: Whether to exclude fields that have a value of `None`. + exclude_computed_fields: Whether to exclude computed fields. + While this can be useful for round-tripping, it is usually recommended to use the dedicated + `round_trip` parameter instead. + round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. + warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, + "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. + fallback: A function to call when an unknown value is encountered. If not provided, + a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. + serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. Returns: A dictionary representation of the model. @@ -291,31 +306,38 @@ def model_dump( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") + if exclude_computed_fields != False: + raise ValueError("exclude_computed_fields is only supported in Pydantic v2") dumped = super().dict( # pyright: ignore[reportDeprecated] include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, ) - return cast(dict[str, Any], json_safe(dumped)) if mode == "json" else dumped + return cast("dict[str, Any]", json_safe(dumped)) if mode == "json" else dumped @override def model_dump_json( self, *, indent: int | None = None, + ensure_ascii: bool = False, include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + context: Any | None = None, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, + exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, - context: dict[str, Any] | None = None, + fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> str: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump_json @@ -344,11 +366,17 @@ def model_dump_json( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") + if ensure_ascii != False: + raise ValueError("ensure_ascii is only supported in Pydantic v2") + if exclude_computed_fields != False: + raise ValueError("exclude_computed_fields is only supported in Pydantic v2") return super().json( # type: ignore[reportDeprecated] indent=indent, include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, @@ -359,10 +387,10 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) - if PYDANTIC_V2: - type_ = field.annotation - else: + if PYDANTIC_V1: type_ = cast(type, field.outer_type_) # type: ignore + else: + type_ = field.annotation # type: ignore if type_ is None: raise RuntimeError(f"Unexpected field type is None for {key}") @@ -370,6 +398,23 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object: return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None)) +def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: + if PYDANTIC_V1: + # TODO + return None + + schema = cls.__pydantic_core_schema__ + if schema["type"] == "model": + fields = schema["schema"] + if fields["type"] == "model-fields": + extras = fields.get("extras_schema") + if extras and "cls" in extras: + # mypy can't narrow the type + return extras["cls"] # type: ignore[no-any-return] + + return None + + def is_basemodel(type_: type) -> bool: """Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`""" if is_union(type_): @@ -439,7 +484,7 @@ def construct_type(*, value: object, type_: object, metadata: Optional[List[Any] type_ = type_.__value__ # type: ignore[unreachable] # unwrap `Annotated[T, ...]` -> `T` - if metadata is not None: + if metadata is not None and len(metadata) > 0: meta: tuple[Any, ...] = tuple(metadata) elif is_annotated_type(type_): meta = get_args(type_)[1:] @@ -546,6 +591,9 @@ class CachedDiscriminatorType(Protocol): __discriminator__: DiscriminatorDetails +DISCRIMINATOR_CACHE: weakref.WeakKeyDictionary[type, DiscriminatorDetails] = weakref.WeakKeyDictionary() + + class DiscriminatorDetails: field_name: str """The name of the discriminator field in the variant class, e.g. @@ -588,8 +636,9 @@ def __init__( def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None: - if isinstance(union, CachedDiscriminatorType): - return union.__discriminator__ + cached = DISCRIMINATOR_CACHE.get(union) + if cached is not None: + return cached discriminator_field_name: str | None = None @@ -607,30 +656,30 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, for variant in get_args(union): variant = strip_annotated_type(variant) if is_basemodel_type(variant): - if PYDANTIC_V2: - field = _extract_field_schema_pv2(variant, discriminator_field_name) - if not field: + if PYDANTIC_V1: + field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + if not field_info: continue # Note: if one variant defines an alias then they all should - discriminator_alias = field.get("serialization_alias") - - field_schema = field["schema"] + discriminator_alias = field_info.alias - if field_schema["type"] == "literal": - for entry in cast("LiteralSchema", field_schema)["expected"]: + 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 else: - field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] - if not field_info: + field = _extract_field_schema_pv2(variant, discriminator_field_name) + if not field: continue # Note: if one variant defines an alias then they all should - discriminator_alias = field_info.alias + discriminator_alias = field.get("serialization_alias") - if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation): - for entry in get_args(annotation): + field_schema = field["schema"] + + if field_schema["type"] == "literal": + for entry in cast("LiteralSchema", field_schema)["expected"]: if isinstance(entry, str): mapping[entry] = variant @@ -642,7 +691,7 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, discriminator_field=discriminator_field_name, discriminator_alias=discriminator_alias, ) - cast(CachedDiscriminatorType, union).__discriminator__ = details + DISCRIMINATOR_CACHE.setdefault(union, details) return details @@ -693,7 +742,7 @@ class GenericModel(BaseGenericModel, BaseModel): pass -if PYDANTIC_V2: +if not PYDANTIC_V1: from pydantic import TypeAdapter as _TypeAdapter _CachedTypeAdapter = cast("TypeAdapter[object]", lru_cache(maxsize=None)(_TypeAdapter)) @@ -761,12 +810,12 @@ class FinalRequestOptions(pydantic.BaseModel): json_data: Union[Body, None] = None extra_json: Union[AnyMapping, None] = None - if PYDANTIC_V2: - model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True) - else: + if PYDANTIC_V1: class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] arbitrary_types_allowed: bool = True + else: + model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True) def get_max_retries(self, max_retries: int) -> int: if isinstance(self.max_retries, NotGiven): @@ -799,9 +848,9 @@ def construct( # type: ignore key: strip_not_given(value) for key, value in values.items() } - if PYDANTIC_V2: - return super().model_construct(_fields_set, **kwargs) - return cast(FinalRequestOptions, super().construct(_fields_set, **kwargs)) # pyright: ignore[reportDeprecated] + if PYDANTIC_V1: + return cast(FinalRequestOptions, super().construct(_fields_set, **kwargs)) # pyright: ignore[reportDeprecated] + return super().model_construct(_fields_set, **kwargs) if not TYPE_CHECKING: # type checkers incorrectly complain about this assignment diff --git a/src/asktable/_qs.py b/src/asktable/_qs.py index 274320ca..ada6fd3f 100644 --- a/src/asktable/_qs.py +++ b/src/asktable/_qs.py @@ -4,7 +4,7 @@ from urllib.parse import parse_qs, urlencode from typing_extensions import Literal, get_args -from ._types import NOT_GIVEN, NotGiven, NotGivenOr +from ._types import NotGiven, not_given from ._utils import flatten _T = TypeVar("_T") @@ -41,8 +41,8 @@ def stringify( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> str: return urlencode( self.stringify_items( @@ -56,8 +56,8 @@ def stringify_items( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> list[tuple[str, str]]: opts = Options( qs=self, @@ -143,8 +143,8 @@ def __init__( self, qs: Querystring = _qs, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> None: self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format diff --git a/src/asktable/_streaming.py b/src/asktable/_streaming.py index d37e4a40..c26001ef 100644 --- a/src/asktable/_streaming.py +++ b/src/asktable/_streaming.py @@ -54,12 +54,12 @@ def __stream__(self) -> Iterator[_T]: process_data = self._client._process_response_data iterator = self._iter_events() - for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) - - # Ensure the entire stream is consumed - for _sse in iterator: - ... + try: + for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + finally: + # Ensure the response is closed even if the consumer doesn't read all data + response.close() def __enter__(self) -> Self: return self @@ -118,12 +118,12 @@ async def __stream__(self) -> AsyncIterator[_T]: process_data = self._client._process_response_data iterator = self._iter_events() - async for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) - - # Ensure the entire stream is consumed - async for _sse in iterator: - ... + try: + async for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + finally: + # Ensure the response is closed even if the consumer doesn't read all data + await response.aclose() async def __aenter__(self) -> Self: return self diff --git a/src/asktable/_types.py b/src/asktable/_types.py index 6a08b156..2fc8bc04 100644 --- a/src/asktable/_types.py +++ b/src/asktable/_types.py @@ -13,10 +13,21 @@ Mapping, TypeVar, Callable, + Iterator, Optional, Sequence, ) -from typing_extensions import Set, Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable +from typing_extensions import ( + Set, + Literal, + Protocol, + TypeAlias, + TypedDict, + SupportsIndex, + overload, + override, + runtime_checkable, +) import httpx import pydantic @@ -106,18 +117,21 @@ class RequestOptions(TypedDict, total=False): # Sentinel class used until PEP 0661 is accepted class NotGiven: """ - A sentinel singleton class used to distinguish omitted keyword arguments - from those passed in with the value None (which may have different behavior). + For parameters with a meaningful None value, we need to distinguish between + the user explicitly passing None, and the user not passing the parameter at + all. + + User code shouldn't need to use not_given directly. For example: ```py - def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ... + def create(timeout: Timeout | None | NotGiven = not_given): ... - get(timeout=1) # 1s timeout - get(timeout=None) # No timeout - get() # Default timeout behavior, which may not be statically known at the method definition. + create(timeout=1) # 1s timeout + create(timeout=None) # No timeout + create() # Default timeout behavior ``` """ @@ -129,13 +143,14 @@ def __repr__(self) -> str: return "NOT_GIVEN" -NotGivenOr = Union[_T, NotGiven] +not_given = NotGiven() +# for backwards compatibility: NOT_GIVEN = NotGiven() class Omit: - """In certain situations you need to be able to represent a case where a default value has - to be explicitly removed and `None` is not an appropriate substitute, for example: + """ + To explicitly omit something from being sent in a request, use `omit`. ```py # as the default `Content-Type` header is `application/json` that will be sent @@ -145,8 +160,8 @@ class Omit: # to look something like: 'multipart/form-data; boundary=0d8382fcf5f8c3be01ca2e11002d2983' client.post(..., headers={"Content-Type": "multipart/form-data"}) - # instead you can remove the default `application/json` header by passing Omit - client.post(..., headers={"Content-Type": Omit()}) + # instead you can remove the default `application/json` header by passing omit + client.post(..., headers={"Content-Type": omit}) ``` """ @@ -154,6 +169,9 @@ def __bool__(self) -> Literal[False]: return False +omit = Omit() + + @runtime_checkable class ModelBuilderProtocol(Protocol): @classmethod @@ -217,3 +235,27 @@ class _GenericAlias(Protocol): class HttpxSendArgs(TypedDict, total=False): auth: httpx.Auth follow_redirects: bool + + +_T_co = TypeVar("_T_co", covariant=True) + + +if TYPE_CHECKING: + # This works because str.__contains__ does not accept object (either in typeshed or at runtime) + # https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285 + # + # Note: index() and count() methods are intentionally omitted to allow pyright to properly + # infer TypedDict types when dict literals are used in lists assigned to SequenceNotStr. + class SequenceNotStr(Protocol[_T_co]): + @overload + def __getitem__(self, index: SupportsIndex, /) -> _T_co: ... + @overload + def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ... + def __contains__(self, value: object, /) -> bool: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[_T_co]: ... + def __reversed__(self) -> Iterator[_T_co]: ... +else: + # just point this to a normal `Sequence` at runtime to avoid having to special case + # deserializing our custom sequence type + SequenceNotStr = Sequence diff --git a/src/asktable/_utils/__init__.py b/src/asktable/_utils/__init__.py index d4fda26f..dc64e29a 100644 --- a/src/asktable/_utils/__init__.py +++ b/src/asktable/_utils/__init__.py @@ -10,7 +10,6 @@ lru_cache as lru_cache, is_mapping as is_mapping, is_tuple_t as is_tuple_t, - parse_date as parse_date, is_iterable as is_iterable, is_sequence as is_sequence, coerce_float as coerce_float, @@ -23,7 +22,6 @@ coerce_boolean as coerce_boolean, coerce_integer as coerce_integer, file_from_path as file_from_path, - parse_datetime as parse_datetime, strip_not_given as strip_not_given, deepcopy_minimal as deepcopy_minimal, get_async_library as get_async_library, @@ -32,12 +30,20 @@ maybe_coerce_boolean as maybe_coerce_boolean, maybe_coerce_integer as maybe_coerce_integer, ) +from ._compat import ( + get_args as get_args, + is_union as is_union, + get_origin as get_origin, + is_typeddict as is_typeddict, + is_literal_type as is_literal_type, +) from ._typing import ( is_list_type as is_list_type, is_union_type as is_union_type, extract_type_arg as extract_type_arg, is_iterable_type as is_iterable_type, is_required_type as is_required_type, + is_sequence_type as is_sequence_type, is_annotated_type as is_annotated_type, is_type_alias_type as is_type_alias_type, strip_annotated_type as strip_annotated_type, @@ -55,3 +61,4 @@ function_has_argument as function_has_argument, assert_signatures_in_sync as assert_signatures_in_sync, ) +from ._datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime diff --git a/src/asktable/_utils/_compat.py b/src/asktable/_utils/_compat.py new file mode 100644 index 00000000..dd703233 --- /dev/null +++ b/src/asktable/_utils/_compat.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +import sys +import typing_extensions +from typing import Any, Type, Union, Literal, Optional +from datetime import date, datetime +from typing_extensions import get_args as _get_args, get_origin as _get_origin + +from .._types import StrBytesIntFloat +from ._datetime_parse import parse_date as _parse_date, parse_datetime as _parse_datetime + +_LITERAL_TYPES = {Literal, typing_extensions.Literal} + + +def get_args(tp: type[Any]) -> tuple[Any, ...]: + return _get_args(tp) + + +def get_origin(tp: type[Any]) -> type[Any] | None: + return _get_origin(tp) + + +def is_union(tp: Optional[Type[Any]]) -> bool: + if sys.version_info < (3, 10): + return tp is Union # type: ignore[comparison-overlap] + else: + import types + + return tp is Union or tp is types.UnionType + + +def is_typeddict(tp: Type[Any]) -> bool: + return typing_extensions.is_typeddict(tp) + + +def is_literal_type(tp: Type[Any]) -> bool: + return get_origin(tp) in _LITERAL_TYPES + + +def parse_date(value: Union[date, StrBytesIntFloat]) -> date: + return _parse_date(value) + + +def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: + return _parse_datetime(value) diff --git a/src/asktable/_utils/_datetime_parse.py b/src/asktable/_utils/_datetime_parse.py new file mode 100644 index 00000000..7cb9d9e6 --- /dev/null +++ b/src/asktable/_utils/_datetime_parse.py @@ -0,0 +1,136 @@ +""" +This file contains code from https://github.com/pydantic/pydantic/blob/main/pydantic/v1/datetime_parse.py +without the Pydantic v1 specific errors. +""" + +from __future__ import annotations + +import re +from typing import Dict, Union, Optional +from datetime import date, datetime, timezone, timedelta + +from .._types import StrBytesIntFloat + +date_expr = r"(?P\d{4})-(?P\d{1,2})-(?P\d{1,2})" +time_expr = ( + r"(?P\d{1,2}):(?P\d{1,2})" + r"(?::(?P\d{1,2})(?:\.(?P\d{1,6})\d{0,6})?)?" + r"(?PZ|[+-]\d{2}(?::?\d{2})?)?$" +) + +date_re = re.compile(f"{date_expr}$") +datetime_re = re.compile(f"{date_expr}[T ]{time_expr}") + + +EPOCH = datetime(1970, 1, 1) +# if greater than this, the number is in ms, if less than or equal it's in seconds +# (in seconds this is 11th October 2603, in ms it's 20th August 1970) +MS_WATERSHED = int(2e10) +# slightly more than datetime.max in ns - (datetime.max - EPOCH).total_seconds() * 1e9 +MAX_NUMBER = int(3e20) + + +def _get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]: + if isinstance(value, (int, float)): + return value + try: + return float(value) + except ValueError: + return None + except TypeError: + raise TypeError(f"invalid type; expected {native_expected_type}, string, bytes, int or float") from None + + +def _from_unix_seconds(seconds: Union[int, float]) -> datetime: + if seconds > MAX_NUMBER: + return datetime.max + elif seconds < -MAX_NUMBER: + return datetime.min + + while abs(seconds) > MS_WATERSHED: + seconds /= 1000 + dt = EPOCH + timedelta(seconds=seconds) + return dt.replace(tzinfo=timezone.utc) + + +def _parse_timezone(value: Optional[str]) -> Union[None, int, timezone]: + if value == "Z": + return timezone.utc + elif value is not None: + offset_mins = int(value[-2:]) if len(value) > 3 else 0 + offset = 60 * int(value[1:3]) + offset_mins + if value[0] == "-": + offset = -offset + return timezone(timedelta(minutes=offset)) + else: + return None + + +def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: + """ + Parse a datetime/int/float/string and return a datetime.datetime. + + This function supports time zone offsets. When the input contains one, + the output uses a timezone with a fixed offset from UTC. + + Raise ValueError if the input is well formatted but not a valid datetime. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, datetime): + return value + + number = _get_numeric(value, "datetime") + if number is not None: + return _from_unix_seconds(number) + + if isinstance(value, bytes): + value = value.decode() + + assert not isinstance(value, (float, int)) + + match = datetime_re.match(value) + if match is None: + raise ValueError("invalid datetime format") + + kw = match.groupdict() + if kw["microsecond"]: + kw["microsecond"] = kw["microsecond"].ljust(6, "0") + + tzinfo = _parse_timezone(kw.pop("tzinfo")) + kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None} + kw_["tzinfo"] = tzinfo + + return datetime(**kw_) # type: ignore + + +def parse_date(value: Union[date, StrBytesIntFloat]) -> date: + """ + Parse a date/int/float/string and return a datetime.date. + + Raise ValueError if the input is well formatted but not a valid date. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, date): + if isinstance(value, datetime): + return value.date() + else: + return value + + number = _get_numeric(value, "date") + if number is not None: + return _from_unix_seconds(number).date() + + if isinstance(value, bytes): + value = value.decode() + + assert not isinstance(value, (float, int)) + match = date_re.match(value) + if match is None: + raise ValueError("invalid date format") + + kw = {k: int(v) for k, v in match.groupdict().items()} + + try: + return date(**kw) + except ValueError: + raise ValueError("invalid date format") from None diff --git a/src/asktable/_utils/_sync.py b/src/asktable/_utils/_sync.py index ad7ec71b..f6027c18 100644 --- a/src/asktable/_utils/_sync.py +++ b/src/asktable/_utils/_sync.py @@ -1,10 +1,8 @@ from __future__ import annotations -import sys import asyncio import functools -import contextvars -from typing import Any, TypeVar, Callable, Awaitable +from typing import TypeVar, Callable, Awaitable from typing_extensions import ParamSpec import anyio @@ -15,34 +13,11 @@ T_ParamSpec = ParamSpec("T_ParamSpec") -if sys.version_info >= (3, 9): - _asyncio_to_thread = asyncio.to_thread -else: - # backport of https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread - # for Python 3.8 support - async def _asyncio_to_thread( - func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs - ) -> Any: - """Asynchronously run function *func* in a separate thread. - - Any *args and **kwargs supplied for this function are directly passed - to *func*. Also, the current :class:`contextvars.Context` is propagated, - allowing context variables from the main thread to be accessed in the - separate thread. - - Returns a coroutine that can be awaited to get the eventual result of *func*. - """ - loop = asyncio.events.get_running_loop() - ctx = contextvars.copy_context() - func_call = functools.partial(ctx.run, func, *args, **kwargs) - return await loop.run_in_executor(None, func_call) - - async def to_thread( func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs ) -> T_Retval: if sniffio.current_async_library() == "asyncio": - return await _asyncio_to_thread(func, *args, **kwargs) + return await asyncio.to_thread(func, *args, **kwargs) return await anyio.to_thread.run_sync( functools.partial(func, *args, **kwargs), @@ -53,10 +28,7 @@ async def to_thread( def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]: """ Take a blocking function and create an async one that receives the same - positional and keyword arguments. For python version 3.9 and above, it uses - asyncio.to_thread to run the function in a separate thread. For python version - 3.8, it uses locally defined copy of the asyncio.to_thread function which was - introduced in python 3.9. + positional and keyword arguments. Usage: diff --git a/src/asktable/_utils/_transform.py b/src/asktable/_utils/_transform.py index b0cc20a7..52075492 100644 --- a/src/asktable/_utils/_transform.py +++ b/src/asktable/_utils/_transform.py @@ -16,18 +16,20 @@ lru_cache, is_mapping, is_iterable, + is_sequence, ) from .._files import is_base64_file_input +from ._compat import get_origin, is_typeddict from ._typing import ( is_list_type, is_union_type, extract_type_arg, is_iterable_type, is_required_type, + is_sequence_type, is_annotated_type, strip_annotated_type, ) -from .._compat import get_origin, model_dump, is_typeddict _T = TypeVar("_T") @@ -167,6 +169,8 @@ def _transform_recursive( Defaults to the same value as the `annotation` argument. """ + from .._compat import model_dump + if inner_type is None: inner_type = annotation @@ -184,6 +188,8 @@ def _transform_recursive( (is_list_type(stripped_type) and is_list(data)) # Iterable[T] or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) + # Sequence[T] + or (is_sequence_type(stripped_type) and is_sequence(data) and not isinstance(data, str)) ): # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually # intended as an iterable, so we don't transform it. @@ -262,7 +268,7 @@ def _transform_typeddict( 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 + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue @@ -329,6 +335,8 @@ async def _async_transform_recursive( Defaults to the same value as the `annotation` argument. """ + from .._compat import model_dump + if inner_type is None: inner_type = annotation @@ -346,6 +354,8 @@ async def _async_transform_recursive( (is_list_type(stripped_type) and is_list(data)) # Iterable[T] or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) + # Sequence[T] + or (is_sequence_type(stripped_type) and is_sequence(data) and not isinstance(data, str)) ): # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually # intended as an iterable, so we don't transform it. @@ -424,7 +434,7 @@ async def _async_transform_typeddict( 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 + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue diff --git a/src/asktable/_utils/_typing.py b/src/asktable/_utils/_typing.py index 1bac9542..193109f3 100644 --- a/src/asktable/_utils/_typing.py +++ b/src/asktable/_utils/_typing.py @@ -15,7 +15,7 @@ from ._utils import lru_cache from .._types import InheritsGeneric -from .._compat import is_union as _is_union +from ._compat import is_union as _is_union def is_annotated_type(typ: type) -> bool: @@ -26,6 +26,11 @@ def is_list_type(typ: type) -> bool: return (get_origin(typ) or typ) == list +def is_sequence_type(typ: type) -> bool: + origin = get_origin(typ) or typ + return origin == typing_extensions.Sequence or origin == typing.Sequence or origin == _c_abc.Sequence + + def is_iterable_type(typ: type) -> bool: """If the given type is `typing.Iterable[T]`""" origin = get_origin(typ) or typ diff --git a/src/asktable/_utils/_utils.py b/src/asktable/_utils/_utils.py index ea3cf3f2..eec7f4a1 100644 --- a/src/asktable/_utils/_utils.py +++ b/src/asktable/_utils/_utils.py @@ -21,8 +21,7 @@ import sniffio -from .._types import NotGiven, FileTypes, NotGivenOr, HeadersLike -from .._compat import parse_date as parse_date, parse_datetime as parse_datetime +from .._types import Omit, NotGiven, FileTypes, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -64,7 +63,7 @@ def _extract_items( try: key = path[index] except IndexError: - if isinstance(obj, NotGiven): + if not is_given(obj): # no value was provided - we can safely ignore return [] @@ -127,14 +126,14 @@ def _extract_items( return [] -def is_given(obj: NotGivenOr[_T]) -> TypeGuard[_T]: - return not isinstance(obj, NotGiven) +def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]: + return not isinstance(obj, NotGiven) and not isinstance(obj, Omit) # Type safe methods for narrowing types with TypeVars. # The default narrowing for isinstance(obj, dict) is dict[unknown, unknown], # however this cause Pyright to rightfully report errors. As we know we don't -# care about the contained types we can safely use `object` in it's place. +# care about the contained types we can safely use `object` in its place. # # There are two separate functions defined, `is_*` and `is_*_t` for different use cases. # `is_*` is for when you're dealing with an unknown input diff --git a/src/asktable/_version.py b/src/asktable/_version.py index 118411d8..62ce948e 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.5.0" # x-release-please-version +__version__ = "5.6.0" # x-release-please-version diff --git a/src/asktable/resources/__init__.py b/src/asktable/resources/__init__.py index 14a5d79a..d9f6dab5 100644 --- a/src/asktable/resources/__init__.py +++ b/src/asktable/resources/__init__.py @@ -72,14 +72,6 @@ RolesResourceWithStreamingResponse, AsyncRolesResourceWithStreamingResponse, ) -from .caches import ( - CachesResource, - AsyncCachesResource, - CachesResourceWithRawResponse, - AsyncCachesResourceWithRawResponse, - CachesResourceWithStreamingResponse, - AsyncCachesResourceWithStreamingResponse, -) from .polish import ( PolishResource, AsyncPolishResource, @@ -238,12 +230,6 @@ "AsyncSqlsResourceWithRawResponse", "SqlsResourceWithStreamingResponse", "AsyncSqlsResourceWithStreamingResponse", - "CachesResource", - "AsyncCachesResource", - "CachesResourceWithRawResponse", - "AsyncCachesResourceWithRawResponse", - "CachesResourceWithStreamingResponse", - "AsyncCachesResourceWithStreamingResponse", "IntegrationResource", "AsyncIntegrationResource", "IntegrationResourceWithRawResponse", diff --git a/src/asktable/resources/answers.py b/src/asktable/resources/answers.py index 8dbd2955..9d9e5f4a 100644 --- a/src/asktable/resources/answers.py +++ b/src/asktable/resources/answers.py @@ -7,7 +7,7 @@ import httpx from ..types import answer_list_params, answer_create_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -49,16 +49,16 @@ def create( *, datasource_id: str, question: str, - max_rows: Optional[int] | NotGiven = NOT_GIVEN, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[object] | NotGiven = NOT_GIVEN, - with_json: Optional[bool] | NotGiven = NOT_GIVEN, + max_rows: Optional[int] | Omit = omit, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, + with_json: Optional[bool] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AnswerResponse: """ 发起查询的请求 @@ -107,15 +107,15 @@ def create( def list( self, *, - datasource_id: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + datasource_id: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[AnswerResponse]: """ 获取所有的 Q2A 记录 @@ -181,16 +181,16 @@ async def create( *, datasource_id: str, question: str, - max_rows: Optional[int] | NotGiven = NOT_GIVEN, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[object] | NotGiven = NOT_GIVEN, - with_json: Optional[bool] | NotGiven = NOT_GIVEN, + max_rows: Optional[int] | Omit = omit, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, + with_json: Optional[bool] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AnswerResponse: """ 发起查询的请求 @@ -239,15 +239,15 @@ async def create( def list( self, *, - datasource_id: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + datasource_id: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[AnswerResponse, AsyncPage[AnswerResponse]]: """ 获取所有的 Q2A 记录 diff --git a/src/asktable/resources/ats/ats.py b/src/asktable/resources/ats/ats.py index 64276c0d..0ef6a647 100644 --- a/src/asktable/resources/ats/ats.py +++ b/src/asktable/resources/ats/ats.py @@ -13,7 +13,7 @@ AsyncTaskResourceWithStreamingResponse, ) from ...types import ats_list_params, ats_create_params, ats_delete_params, ats_update_params -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from .test_case import ( @@ -79,7 +79,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ATSCreateResponse: """ Create Test Set Endpoint @@ -121,7 +121,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ATSRetrieveResponse: """ Get Test Set Endpoint @@ -155,7 +155,7 @@ def update( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ATSUpdateResponse: """ Update Test Set Endpoint @@ -186,14 +186,14 @@ def list( self, *, datasource_id: str, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[ATSListResponse]: """ Get Test Sets Endpoint @@ -243,7 +243,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Test Set Endpoint @@ -312,7 +312,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ATSCreateResponse: """ Create Test Set Endpoint @@ -354,7 +354,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ATSRetrieveResponse: """ Get Test Set Endpoint @@ -388,7 +388,7 @@ async def update( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ATSUpdateResponse: """ Update Test Set Endpoint @@ -419,14 +419,14 @@ def list( self, *, datasource_id: str, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ATSListResponse, AsyncPage[ATSListResponse]]: """ Get Test Sets Endpoint @@ -476,7 +476,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Test Set Endpoint diff --git a/src/asktable/resources/ats/task.py b/src/asktable/resources/ats/task.py index 7950fed9..8c384687 100644 --- a/src/asktable/resources/ats/task.py +++ b/src/asktable/resources/ats/task.py @@ -2,11 +2,9 @@ from __future__ import annotations -from typing import List - import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -57,7 +55,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRetrieveResponse: """ Get Test Task Endpoint @@ -87,14 +85,14 @@ def list( self, ats_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[TaskListResponse]: """ Get Test Tasks Endpoint @@ -138,14 +136,14 @@ def get_case_tasks( ats_task_id: str, *, ats_id: str, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGetCaseTasksResponse: """ Get Test Case Tasks Endpoint @@ -190,13 +188,13 @@ def run( ats_id: str, *, datasource_id: str, - specific_case_ids: List[str], + specific_case_ids: SequenceNotStr[str], # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResponse: """ Run Task Endpoint @@ -262,7 +260,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRetrieveResponse: """ Get Test Task Endpoint @@ -292,14 +290,14 @@ def list( self, ats_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[TaskListResponse, AsyncPage[TaskListResponse]]: """ Get Test Tasks Endpoint @@ -343,14 +341,14 @@ async def get_case_tasks( ats_task_id: str, *, ats_id: str, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGetCaseTasksResponse: """ Get Test Case Tasks Endpoint @@ -395,13 +393,13 @@ async def run( ats_id: str, *, datasource_id: str, - specific_case_ids: List[str], + specific_case_ids: SequenceNotStr[str], # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResponse: """ Run Task Endpoint diff --git a/src/asktable/resources/ats/test_case.py b/src/asktable/resources/ats/test_case.py index 58852a1a..a08fa3c9 100644 --- a/src/asktable/resources/ats/test_case.py +++ b/src/asktable/resources/ats/test_case.py @@ -6,7 +6,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -55,14 +55,14 @@ def create( *, expected_sql: str, question: str, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[object] | NotGiven = NOT_GIVEN, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TestCaseCreateResponse: """ Create Test Case Endpoint @@ -113,7 +113,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TestCaseRetrieveResponse: """ Get Test Case Endpoint @@ -146,14 +146,14 @@ def update( ats_id: str, expected_sql: str, question: str, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[object] | NotGiven = NOT_GIVEN, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TestCaseUpdateResponse: """ Update Test Case Endpoint @@ -200,14 +200,14 @@ def list( self, ats_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[TestCaseListResponse]: """ Get Test Cases Endpoint @@ -256,7 +256,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Test Case Endpoint @@ -309,14 +309,14 @@ async def create( *, expected_sql: str, question: str, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[object] | NotGiven = NOT_GIVEN, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TestCaseCreateResponse: """ Create Test Case Endpoint @@ -367,7 +367,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TestCaseRetrieveResponse: """ Get Test Case Endpoint @@ -400,14 +400,14 @@ async def update( ats_id: str, expected_sql: str, question: str, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[object] | NotGiven = NOT_GIVEN, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TestCaseUpdateResponse: """ Update Test Case Endpoint @@ -454,14 +454,14 @@ def list( self, ats_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[TestCaseListResponse, AsyncPage[TestCaseListResponse]]: """ Get Test Cases Endpoint @@ -510,7 +510,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Test Case Endpoint diff --git a/src/asktable/resources/auth.py b/src/asktable/resources/auth.py index 065e06f1..75b3433f 100644 --- a/src/asktable/resources/auth.py +++ b/src/asktable/resources/auth.py @@ -8,7 +8,7 @@ import httpx from ..types import auth_create_token_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -47,16 +47,16 @@ def with_streaming_response(self) -> AuthResourceWithStreamingResponse: def create_token( self, *, - ak_role: Literal["sys", "admin", "asker", "visitor"] | NotGiven = NOT_GIVEN, - chat_role: Optional[auth_create_token_params.ChatRole] | NotGiven = NOT_GIVEN, - token_ttl: int | NotGiven = NOT_GIVEN, - user_profile: Optional[object] | NotGiven = NOT_GIVEN, + ak_role: Literal["sys", "admin", "asker", "visitor"] | Omit = omit, + chat_role: Optional[auth_create_token_params.ChatRole] | Omit = omit, + token_ttl: int | Omit = omit, + user_profile: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Create Token @@ -103,7 +103,7 @@ def me( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AuthMeResponse: """获取当前登录的 TokenID""" return self._get( @@ -138,16 +138,16 @@ def with_streaming_response(self) -> AsyncAuthResourceWithStreamingResponse: async def create_token( self, *, - ak_role: Literal["sys", "admin", "asker", "visitor"] | NotGiven = NOT_GIVEN, - chat_role: Optional[auth_create_token_params.ChatRole] | NotGiven = NOT_GIVEN, - token_ttl: int | NotGiven = NOT_GIVEN, - user_profile: Optional[object] | NotGiven = NOT_GIVEN, + ak_role: Literal["sys", "admin", "asker", "visitor"] | Omit = omit, + chat_role: Optional[auth_create_token_params.ChatRole] | Omit = omit, + token_ttl: int | Omit = omit, + user_profile: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Create Token @@ -194,7 +194,7 @@ async def me( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AuthMeResponse: """获取当前登录的 TokenID""" return await self._get( diff --git a/src/asktable/resources/bots.py b/src/asktable/resources/bots.py index a64fb2d0..7f31c95d 100644 --- a/src/asktable/resources/bots.py +++ b/src/asktable/resources/bots.py @@ -2,12 +2,12 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import Iterable, Optional import httpx 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 .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -47,25 +47,24 @@ def with_streaming_response(self) -> BotsResourceWithStreamingResponse: def create( self, *, - datasource_ids: List[str], + datasource_ids: SequenceNotStr[str], name: str, - color_theme: Optional[str] | NotGiven = NOT_GIVEN, - debug: bool | NotGiven = NOT_GIVEN, - extapi_ids: List[str] | NotGiven = NOT_GIVEN, - interaction_rules: Iterable[bot_create_params.InteractionRule] | NotGiven = NOT_GIVEN, - magic_input: Optional[str] | NotGiven = NOT_GIVEN, - max_rows: int | NotGiven = NOT_GIVEN, - publish: bool | NotGiven = NOT_GIVEN, - query_balance: Optional[int] | NotGiven = NOT_GIVEN, - sample_questions: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhooks: List[str] | NotGiven = NOT_GIVEN, - welcome_message: Optional[str] | NotGiven = NOT_GIVEN, + color_theme: Optional[str] | Omit = omit, + debug: bool | Omit = omit, + interaction_rules: Iterable[bot_create_params.InteractionRule] | Omit = omit, + magic_input: Optional[str] | Omit = omit, + max_rows: int | Omit = omit, + publish: bool | Omit = omit, + query_balance: Optional[int] | Omit = omit, + sample_questions: Optional[SequenceNotStr[str]] | Omit = omit, + webhooks: SequenceNotStr[str] | Omit = omit, + welcome_message: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chatbot: """ 创建一个新的 Bot @@ -79,8 +78,6 @@ def create( debug: 调试模式 - extapi_ids: 扩展 API ID 列表,扩展 API ID 的逗号分隔列表。 - interaction_rules: 交互规则列表,用于定义 bot 的行为规则 magic_input: 魔法提示词 @@ -113,7 +110,6 @@ def create( "name": name, "color_theme": color_theme, "debug": debug, - "extapi_ids": extapi_ids, "interaction_rules": interaction_rules, "magic_input": magic_input, "max_rows": max_rows, @@ -140,7 +136,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chatbot: """ 获取某个 Bot @@ -168,26 +164,25 @@ def update( self, bot_id: str, *, - avatar_url: Optional[str] | NotGiven = NOT_GIVEN, - color_theme: Optional[str] | NotGiven = NOT_GIVEN, - datasource_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - debug: Optional[bool] | NotGiven = NOT_GIVEN, - extapi_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - interaction_rules: Optional[Iterable[bot_update_params.InteractionRule]] | NotGiven = NOT_GIVEN, - magic_input: Optional[str] | NotGiven = NOT_GIVEN, - max_rows: Optional[int] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - publish: Optional[bool] | NotGiven = NOT_GIVEN, - query_balance: Optional[int] | NotGiven = NOT_GIVEN, - sample_questions: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhooks: Optional[List[str]] | NotGiven = NOT_GIVEN, - welcome_message: Optional[str] | NotGiven = NOT_GIVEN, + avatar_url: Optional[str] | Omit = omit, + color_theme: Optional[str] | Omit = omit, + datasource_ids: Optional[SequenceNotStr[str]] | Omit = omit, + debug: Optional[bool] | Omit = omit, + interaction_rules: Optional[Iterable[bot_update_params.InteractionRule]] | Omit = omit, + magic_input: Optional[str] | Omit = omit, + max_rows: Optional[int] | Omit = omit, + name: Optional[str] | Omit = omit, + publish: Optional[bool] | Omit = omit, + query_balance: Optional[int] | Omit = omit, + sample_questions: Optional[SequenceNotStr[str]] | Omit = omit, + webhooks: Optional[SequenceNotStr[str]] | Omit = omit, + welcome_message: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chatbot: """ 更新某个 Bot @@ -201,8 +196,6 @@ def update( debug: 调试模式 - extapi_ids: 扩展 API ID 列表,扩展 API ID 的逗号分隔列表。 - interaction_rules: 交互规则列表,用于定义 bot 的行为规则 magic_input: 魔法提示词 @@ -239,7 +232,6 @@ def update( "color_theme": color_theme, "datasource_ids": datasource_ids, "debug": debug, - "extapi_ids": extapi_ids, "interaction_rules": interaction_rules, "magic_input": magic_input, "max_rows": max_rows, @@ -261,16 +253,16 @@ def update( def list( self, *, - bot_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + bot_ids: Optional[SequenceNotStr[str]] | Omit = omit, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Chatbot]: """ 查询所有 Bot @@ -322,7 +314,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除某个 Bot @@ -356,7 +348,7 @@ def invite( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 邀请用户加入对话 @@ -408,25 +400,24 @@ def with_streaming_response(self) -> AsyncBotsResourceWithStreamingResponse: async def create( self, *, - datasource_ids: List[str], + datasource_ids: SequenceNotStr[str], name: str, - color_theme: Optional[str] | NotGiven = NOT_GIVEN, - debug: bool | NotGiven = NOT_GIVEN, - extapi_ids: List[str] | NotGiven = NOT_GIVEN, - interaction_rules: Iterable[bot_create_params.InteractionRule] | NotGiven = NOT_GIVEN, - magic_input: Optional[str] | NotGiven = NOT_GIVEN, - max_rows: int | NotGiven = NOT_GIVEN, - publish: bool | NotGiven = NOT_GIVEN, - query_balance: Optional[int] | NotGiven = NOT_GIVEN, - sample_questions: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhooks: List[str] | NotGiven = NOT_GIVEN, - welcome_message: Optional[str] | NotGiven = NOT_GIVEN, + color_theme: Optional[str] | Omit = omit, + debug: bool | Omit = omit, + interaction_rules: Iterable[bot_create_params.InteractionRule] | Omit = omit, + magic_input: Optional[str] | Omit = omit, + max_rows: int | Omit = omit, + publish: bool | Omit = omit, + query_balance: Optional[int] | Omit = omit, + sample_questions: Optional[SequenceNotStr[str]] | Omit = omit, + webhooks: SequenceNotStr[str] | Omit = omit, + welcome_message: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chatbot: """ 创建一个新的 Bot @@ -440,8 +431,6 @@ async def create( debug: 调试模式 - extapi_ids: 扩展 API ID 列表,扩展 API ID 的逗号分隔列表。 - interaction_rules: 交互规则列表,用于定义 bot 的行为规则 magic_input: 魔法提示词 @@ -474,7 +463,6 @@ async def create( "name": name, "color_theme": color_theme, "debug": debug, - "extapi_ids": extapi_ids, "interaction_rules": interaction_rules, "magic_input": magic_input, "max_rows": max_rows, @@ -501,7 +489,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chatbot: """ 获取某个 Bot @@ -529,26 +517,25 @@ async def update( self, bot_id: str, *, - avatar_url: Optional[str] | NotGiven = NOT_GIVEN, - color_theme: Optional[str] | NotGiven = NOT_GIVEN, - datasource_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - debug: Optional[bool] | NotGiven = NOT_GIVEN, - extapi_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - interaction_rules: Optional[Iterable[bot_update_params.InteractionRule]] | NotGiven = NOT_GIVEN, - magic_input: Optional[str] | NotGiven = NOT_GIVEN, - max_rows: Optional[int] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - publish: Optional[bool] | NotGiven = NOT_GIVEN, - query_balance: Optional[int] | NotGiven = NOT_GIVEN, - sample_questions: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhooks: Optional[List[str]] | NotGiven = NOT_GIVEN, - welcome_message: Optional[str] | NotGiven = NOT_GIVEN, + avatar_url: Optional[str] | Omit = omit, + color_theme: Optional[str] | Omit = omit, + datasource_ids: Optional[SequenceNotStr[str]] | Omit = omit, + debug: Optional[bool] | Omit = omit, + interaction_rules: Optional[Iterable[bot_update_params.InteractionRule]] | Omit = omit, + magic_input: Optional[str] | Omit = omit, + max_rows: Optional[int] | Omit = omit, + name: Optional[str] | Omit = omit, + publish: Optional[bool] | Omit = omit, + query_balance: Optional[int] | Omit = omit, + sample_questions: Optional[SequenceNotStr[str]] | Omit = omit, + webhooks: Optional[SequenceNotStr[str]] | Omit = omit, + welcome_message: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chatbot: """ 更新某个 Bot @@ -562,8 +549,6 @@ async def update( debug: 调试模式 - extapi_ids: 扩展 API ID 列表,扩展 API ID 的逗号分隔列表。 - interaction_rules: 交互规则列表,用于定义 bot 的行为规则 magic_input: 魔法提示词 @@ -600,7 +585,6 @@ async def update( "color_theme": color_theme, "datasource_ids": datasource_ids, "debug": debug, - "extapi_ids": extapi_ids, "interaction_rules": interaction_rules, "magic_input": magic_input, "max_rows": max_rows, @@ -622,16 +606,16 @@ async def update( def list( self, *, - bot_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + bot_ids: Optional[SequenceNotStr[str]] | Omit = omit, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Chatbot, AsyncPage[Chatbot]]: """ 查询所有 Bot @@ -683,7 +667,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除某个 Bot @@ -717,7 +701,7 @@ async def invite( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 邀请用户加入对话 diff --git a/src/asktable/resources/business_glossary.py b/src/asktable/resources/business_glossary.py index 2eed15db..a65ad951 100644 --- a/src/asktable/resources/business_glossary.py +++ b/src/asktable/resources/business_glossary.py @@ -2,12 +2,12 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import Iterable, Optional import httpx 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 .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -55,7 +55,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BusinessGlossaryCreateResponse: """ 创建业务术语 @@ -87,7 +87,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EntryWithDefinition: """ 获取某个业务术语 @@ -115,17 +115,17 @@ 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, - term: Optional[str] | NotGiven = NOT_GIVEN, + active: Optional[bool] | Omit = omit, + aliases: Optional[SequenceNotStr[str]] | Omit = omit, + definition: Optional[str] | Omit = omit, + payload: Optional[object] | Omit = omit, + term: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Entry: """ 更新业务术语 @@ -172,15 +172,15 @@ def update( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, - term: str | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, + term: str | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[EntryWithDefinition]: """ 查询所有业务术语 @@ -229,7 +229,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除某个业务术语 @@ -283,7 +283,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BusinessGlossaryCreateResponse: """ 创建业务术语 @@ -315,7 +315,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EntryWithDefinition: """ 获取某个业务术语 @@ -343,17 +343,17 @@ 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, - term: Optional[str] | NotGiven = NOT_GIVEN, + active: Optional[bool] | Omit = omit, + aliases: Optional[SequenceNotStr[str]] | Omit = omit, + definition: Optional[str] | Omit = omit, + payload: Optional[object] | Omit = omit, + term: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Entry: """ 更新业务术语 @@ -400,15 +400,15 @@ async def update( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, - term: str | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, + term: str | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[EntryWithDefinition, AsyncPage[EntryWithDefinition]]: """ 查询所有业务术语 @@ -457,7 +457,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除某个业务术语 diff --git a/src/asktable/resources/caches.py b/src/asktable/resources/caches.py deleted file mode 100644 index b89b7d6b..00000000 --- a/src/asktable/resources/caches.py +++ /dev/null @@ -1,164 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from .._base_client import make_request_options - -__all__ = ["CachesResource", "AsyncCachesResource"] - - -class CachesResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> CachesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/DataMini/asktable-python#accessing-raw-response-data-eg-headers - """ - return CachesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> CachesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/DataMini/asktable-python#with_streaming_response - """ - return CachesResourceWithStreamingResponse(self) - - def delete( - self, - cache_id: str, - *, - # 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: - """ - 清除缓存 - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not cache_id: - raise ValueError(f"Expected a non-empty value for `cache_id` but received {cache_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/v1/caches/{cache_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class AsyncCachesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncCachesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/DataMini/asktable-python#accessing-raw-response-data-eg-headers - """ - return AsyncCachesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncCachesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/DataMini/asktable-python#with_streaming_response - """ - return AsyncCachesResourceWithStreamingResponse(self) - - async def delete( - self, - cache_id: str, - *, - # 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: - """ - 清除缓存 - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not cache_id: - raise ValueError(f"Expected a non-empty value for `cache_id` but received {cache_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._delete( - f"/v1/caches/{cache_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class CachesResourceWithRawResponse: - def __init__(self, caches: CachesResource) -> None: - self._caches = caches - - self.delete = to_raw_response_wrapper( - caches.delete, - ) - - -class AsyncCachesResourceWithRawResponse: - def __init__(self, caches: AsyncCachesResource) -> None: - self._caches = caches - - self.delete = async_to_raw_response_wrapper( - caches.delete, - ) - - -class CachesResourceWithStreamingResponse: - def __init__(self, caches: CachesResource) -> None: - self._caches = caches - - self.delete = to_streamed_response_wrapper( - caches.delete, - ) - - -class AsyncCachesResourceWithStreamingResponse: - def __init__(self, caches: AsyncCachesResource) -> None: - self._caches = caches - - self.delete = async_to_streamed_response_wrapper( - caches.delete, - ) diff --git a/src/asktable/resources/chats/chats.py b/src/asktable/resources/chats/chats.py index fd159838..3f7e3591 100644 --- a/src/asktable/resources/chats/chats.py +++ b/src/asktable/resources/chats/chats.py @@ -7,7 +7,7 @@ import httpx from ...types import chat_list_params, chat_create_params -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from .messages import ( MessagesResource, @@ -60,17 +60,17 @@ def with_streaming_response(self) -> ChatsResourceWithStreamingResponse: def create( self, *, - bot_id: Optional[str] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[Dict[str, Union[str, int, bool]]] | NotGiven = NOT_GIVEN, - user_profile: Optional[Dict[str, Union[str, int, bool]]] | NotGiven = NOT_GIVEN, + bot_id: Optional[str] | Omit = omit, + name: Optional[str] | Omit = omit, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[Dict[str, Union[str, int, bool]]] | Omit = omit, + user_profile: Optional[Dict[str, Union[str, int, bool]]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chat: """ 创建对话 @@ -123,7 +123,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatRetrieveResponse: """ 获取某个对话 @@ -150,14 +150,14 @@ def retrieve( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Chat]: """ 查询对话列表 @@ -203,7 +203,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ 删除某个对话(包含消息) @@ -256,17 +256,17 @@ def with_streaming_response(self) -> AsyncChatsResourceWithStreamingResponse: async def create( self, *, - bot_id: Optional[str] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - role_variables: Optional[Dict[str, Union[str, int, bool]]] | NotGiven = NOT_GIVEN, - user_profile: Optional[Dict[str, Union[str, int, bool]]] | NotGiven = NOT_GIVEN, + bot_id: Optional[str] | Omit = omit, + name: Optional[str] | Omit = omit, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[Dict[str, Union[str, int, bool]]] | Omit = omit, + user_profile: Optional[Dict[str, Union[str, int, bool]]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Chat: """ 创建对话 @@ -319,7 +319,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatRetrieveResponse: """ 获取某个对话 @@ -346,14 +346,14 @@ async def retrieve( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Chat, AsyncPage[Chat]]: """ 查询对话列表 @@ -399,7 +399,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ 删除某个对话(包含消息) diff --git a/src/asktable/resources/chats/messages.py b/src/asktable/resources/chats/messages.py index 7c3ca18a..8c891817 100644 --- a/src/asktable/resources/chats/messages.py +++ b/src/asktable/resources/chats/messages.py @@ -6,7 +6,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -56,7 +56,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageCreateResponse: """ Send a message to the chat @@ -99,7 +99,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageRetrieveResponse: """ 查询某条消息 @@ -134,14 +134,14 @@ def list( self, chat_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[MessageListResponse]: """ 查询所有的消息 @@ -211,7 +211,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageCreateResponse: """ Send a message to the chat @@ -256,7 +256,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageRetrieveResponse: """ 查询某条消息 @@ -291,14 +291,14 @@ def list( self, chat_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[MessageListResponse, AsyncPage[MessageListResponse]]: """ 查询所有的消息 diff --git a/src/asktable/resources/dataframes.py b/src/asktable/resources/dataframes.py index 4320689d..43a49cea 100644 --- a/src/asktable/resources/dataframes.py +++ b/src/asktable/resources/dataframes.py @@ -4,7 +4,7 @@ import httpx -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Query, Headers, NotGiven, not_given from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -48,7 +48,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DataframeRetrieveResponse: """ Get Dataframe @@ -102,7 +102,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DataframeRetrieveResponse: """ Get Dataframe diff --git a/src/asktable/resources/datasources/datasources.py b/src/asktable/resources/datasources/datasources.py index 239b7943..e0bf68de 100644 --- a/src/asktable/resources/datasources/datasources.py +++ b/src/asktable/resources/datasources/datasources.py @@ -30,7 +30,7 @@ IndexesResourceWithStreamingResponse, AsyncIndexesResourceWithStreamingResponse, ) -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes +from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -114,15 +114,18 @@ def create( "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ], - access_config: Optional[datasource_create_params.AccessConfig] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + access_config: Optional[datasource_create_params.AccessConfig] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Datasource: """ 创建一个新的数据源 @@ -167,7 +170,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DatasourceRetrieveResponse: """ 根据 id 获取指定数据源 @@ -195,8 +198,8 @@ def update( self, datasource_id: str, *, - access_config: Optional[datasource_update_params.AccessConfig] | NotGiven = NOT_GIVEN, - desc: Optional[str] | NotGiven = NOT_GIVEN, + access_config: Optional[datasource_update_params.AccessConfig] | Omit = omit, + desc: Optional[str] | Omit = omit, engine: Optional[ Literal[ "mysql", @@ -220,22 +223,25 @@ def update( "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ] ] - | NotGiven = NOT_GIVEN, - field_count: Optional[int] | NotGiven = NOT_GIVEN, - meta_error: Optional[str] | NotGiven = NOT_GIVEN, - meta_status: Optional[Literal["processing", "failed", "success", "unprocessed"]] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - sample_questions: Optional[str] | NotGiven = NOT_GIVEN, - schema_count: Optional[int] | NotGiven = NOT_GIVEN, - table_count: Optional[int] | NotGiven = NOT_GIVEN, + | Omit = omit, + field_count: Optional[int] | Omit = omit, + meta_error: Optional[str] | Omit = omit, + meta_status: Optional[Literal["processing", "failed", "success", "unprocessed"]] | Omit = omit, + name: Optional[str] | Omit = omit, + sample_questions: Optional[str] | Omit = omit, + schema_count: Optional[int] | Omit = omit, + table_count: Optional[int] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Datasource: """ 更新指定数据源信息 @@ -297,15 +303,15 @@ def update( def list( self, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Datasource]: """ 获取所有的数据源 @@ -352,7 +358,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 根据 id 删除指定数据源 @@ -386,7 +392,7 @@ def add_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 为数据源添加文件 @@ -428,7 +434,7 @@ def delete_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除数据源的单个文件 @@ -463,7 +469,7 @@ def retrieve_runtime_meta( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DatasourceRetrieveRuntimeMetaResponse: """ 获取指定数据源的运行时元数据 @@ -497,14 +503,14 @@ def update_field( identifiable_type: Optional[ Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] ] - | NotGiven = NOT_GIVEN, - visibility: Optional[bool] | NotGiven = NOT_GIVEN, + | Omit = omit, + visibility: Optional[bool] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 更新数据源的某个字段的描述 @@ -608,15 +614,18 @@ async def create( "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ], - access_config: Optional[datasource_create_params.AccessConfig] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + access_config: Optional[datasource_create_params.AccessConfig] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Datasource: """ 创建一个新的数据源 @@ -661,7 +670,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DatasourceRetrieveResponse: """ 根据 id 获取指定数据源 @@ -689,8 +698,8 @@ async def update( self, datasource_id: str, *, - access_config: Optional[datasource_update_params.AccessConfig] | NotGiven = NOT_GIVEN, - desc: Optional[str] | NotGiven = NOT_GIVEN, + access_config: Optional[datasource_update_params.AccessConfig] | Omit = omit, + desc: Optional[str] | Omit = omit, engine: Optional[ Literal[ "mysql", @@ -714,22 +723,25 @@ async def update( "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ] ] - | NotGiven = NOT_GIVEN, - field_count: Optional[int] | NotGiven = NOT_GIVEN, - meta_error: Optional[str] | NotGiven = NOT_GIVEN, - meta_status: Optional[Literal["processing", "failed", "success", "unprocessed"]] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - sample_questions: Optional[str] | NotGiven = NOT_GIVEN, - schema_count: Optional[int] | NotGiven = NOT_GIVEN, - table_count: Optional[int] | NotGiven = NOT_GIVEN, + | Omit = omit, + field_count: Optional[int] | Omit = omit, + meta_error: Optional[str] | Omit = omit, + meta_status: Optional[Literal["processing", "failed", "success", "unprocessed"]] | Omit = omit, + name: Optional[str] | Omit = omit, + sample_questions: Optional[str] | Omit = omit, + schema_count: Optional[int] | Omit = omit, + table_count: Optional[int] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Datasource: """ 更新指定数据源信息 @@ -791,15 +803,15 @@ async def update( def list( self, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Datasource, AsyncPage[Datasource]]: """ 获取所有的数据源 @@ -846,7 +858,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 根据 id 删除指定数据源 @@ -880,7 +892,7 @@ async def add_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 为数据源添加文件 @@ -922,7 +934,7 @@ async def delete_file( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除数据源的单个文件 @@ -957,7 +969,7 @@ async def retrieve_runtime_meta( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DatasourceRetrieveRuntimeMetaResponse: """ 获取指定数据源的运行时元数据 @@ -991,14 +1003,14 @@ async def update_field( identifiable_type: Optional[ Literal["plain", "person_name", "email", "ssn", "id", "phone", "address", "company", "bank_card"] ] - | NotGiven = NOT_GIVEN, - visibility: Optional[bool] | NotGiven = NOT_GIVEN, + | Omit = omit, + visibility: Optional[bool] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 更新数据源的某个字段的描述 diff --git a/src/asktable/resources/datasources/indexes.py b/src/asktable/resources/datasources/indexes.py index 3ffd6f4a..64148b70 100644 --- a/src/asktable/resources/datasources/indexes.py +++ b/src/asktable/resources/datasources/indexes.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -49,13 +49,13 @@ def create( field_name: str, schema_name: str, table_name: str, - async_process: bool | NotGiven = NOT_GIVEN, + async_process: bool | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 创建索引 Args: ds_id: 数据源 ID index: 索引创建参数,包含 @@ -102,14 +102,14 @@ def list( self, ds_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Index]: """ 获取数据源的所有索引 Args: ds_id: 数据源 ID Returns: 索引列表,包含索引的完整信 @@ -159,7 +159,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除索引 Args: ds_id: 数据源 ID index_id: 索引 ID @@ -213,13 +213,13 @@ async def create( field_name: str, schema_name: str, table_name: str, - async_process: bool | NotGiven = NOT_GIVEN, + async_process: bool | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 创建索引 Args: ds_id: 数据源 ID index: 索引创建参数,包含 @@ -268,14 +268,14 @@ def list( self, ds_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Index, AsyncPage[Index]]: """ 获取数据源的所有索引 Args: ds_id: 数据源 ID Returns: 索引列表,包含索引的完整信 @@ -325,7 +325,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除索引 Args: ds_id: 数据源 ID index_id: 索引 ID diff --git a/src/asktable/resources/datasources/meta.py b/src/asktable/resources/datasources/meta.py index 431f1fba..3c5ddde1 100644 --- a/src/asktable/resources/datasources/meta.py +++ b/src/asktable/resources/datasources/meta.py @@ -2,11 +2,11 @@ from __future__ import annotations -from typing import Dict, List, Optional +from typing import Dict, Optional import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -47,16 +47,16 @@ def create( self, datasource_id: str, *, - async_process_meta: bool | NotGiven = NOT_GIVEN, - value_index: bool | NotGiven = NOT_GIVEN, - meta: Optional[meta_create_params.Meta] | NotGiven = NOT_GIVEN, - selected_tables: Optional[Dict[str, List[str]]] | NotGiven = NOT_GIVEN, + async_process_meta: bool | Omit = omit, + value_index: bool | Omit = omit, + meta: Optional[meta_create_params.Meta] | Omit = omit, + selected_tables: Optional[Dict[str, SequenceNotStr[str]]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 创建数据源的 meta,如果已经存在,则删除旧的 @@ -110,7 +110,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Meta: """ 从数据源中获取最新的元数据 @@ -138,15 +138,15 @@ def update( self, datasource_id: str, *, - async_process_meta: bool | NotGiven = NOT_GIVEN, - meta: Optional[meta_update_params.Meta] | NotGiven = NOT_GIVEN, - selected_tables: Optional[Dict[str, List[str]]] | NotGiven = NOT_GIVEN, + async_process_meta: bool | Omit = omit, + meta: Optional[meta_update_params.Meta] | Omit = omit, + selected_tables: Optional[Dict[str, SequenceNotStr[str]]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 用于更新 DB 类型的数据源的 Meta(增加新表或者删除老表) @@ -191,7 +191,7 @@ def annotate( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 修改数据 meta 的描述,用来修改表和字段的备注 @@ -241,16 +241,16 @@ async def create( self, datasource_id: str, *, - async_process_meta: bool | NotGiven = NOT_GIVEN, - value_index: bool | NotGiven = NOT_GIVEN, - meta: Optional[meta_create_params.Meta] | NotGiven = NOT_GIVEN, - selected_tables: Optional[Dict[str, List[str]]] | NotGiven = NOT_GIVEN, + async_process_meta: bool | Omit = omit, + value_index: bool | Omit = omit, + meta: Optional[meta_create_params.Meta] | Omit = omit, + selected_tables: Optional[Dict[str, SequenceNotStr[str]]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 创建数据源的 meta,如果已经存在,则删除旧的 @@ -304,7 +304,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Meta: """ 从数据源中获取最新的元数据 @@ -332,15 +332,15 @@ async def update( self, datasource_id: str, *, - async_process_meta: bool | NotGiven = NOT_GIVEN, - meta: Optional[meta_update_params.Meta] | NotGiven = NOT_GIVEN, - selected_tables: Optional[Dict[str, List[str]]] | NotGiven = NOT_GIVEN, + async_process_meta: bool | Omit = omit, + meta: Optional[meta_update_params.Meta] | Omit = omit, + selected_tables: Optional[Dict[str, SequenceNotStr[str]]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 用于更新 DB 类型的数据源的 Meta(增加新表或者删除老表) @@ -387,7 +387,7 @@ async def annotate( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 修改数据 meta 的描述,用来修改表和字段的备注 diff --git a/src/asktable/resources/datasources/upload_params.py b/src/asktable/resources/datasources/upload_params.py index 01578571..bb5637e0 100644 --- a/src/asktable/resources/datasources/upload_params.py +++ b/src/asktable/resources/datasources/upload_params.py @@ -6,7 +6,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -45,14 +45,14 @@ def with_streaming_response(self) -> UploadParamsResourceWithStreamingResponse: def create( self, *, - expiration: Optional[int] | NotGiven = NOT_GIVEN, - file_max_size: Optional[int] | NotGiven = NOT_GIVEN, + expiration: Optional[int] | Omit = omit, + file_max_size: Optional[int] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 获取 OSS 签名参数 @@ -109,14 +109,14 @@ def with_streaming_response(self) -> AsyncUploadParamsResourceWithStreamingRespo async def create( self, *, - expiration: Optional[int] | NotGiven = NOT_GIVEN, - file_max_size: Optional[int] | NotGiven = NOT_GIVEN, + expiration: Optional[int] | Omit = omit, + file_max_size: Optional[int] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 获取 OSS 签名参数 diff --git a/src/asktable/resources/files.py b/src/asktable/resources/files.py index 6673a7bf..88983f93 100644 --- a/src/asktable/resources/files.py +++ b/src/asktable/resources/files.py @@ -4,7 +4,7 @@ import httpx -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Query, Headers, NotGiven, not_given from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -47,7 +47,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 获取文件 @@ -101,7 +101,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 获取文件 diff --git a/src/asktable/resources/integration.py b/src/asktable/resources/integration.py index e82d2672..b3dbb640 100644 --- a/src/asktable/resources/integration.py +++ b/src/asktable/resources/integration.py @@ -7,7 +7,7 @@ import httpx from ..types import integration_excel_csv_ask_params, integration_create_excel_ds_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -48,13 +48,13 @@ def create_excel_ds( self, *, file_url: str, - value_index: bool | NotGiven = NOT_GIVEN, + value_index: bool | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Datasource: """ 通过 Excel/CSV 文件 URL 创建数据源 @@ -91,13 +91,13 @@ def excel_csv_ask( *, file_url: str, question: str, - with_json: Optional[bool] | NotGiven = NOT_GIVEN, + with_json: Optional[bool] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileAskResponse: """ 通过 Excel/CSV 文件 URL 添加数据并提问 @@ -158,13 +158,13 @@ async def create_excel_ds( self, *, file_url: str, - value_index: bool | NotGiven = NOT_GIVEN, + value_index: bool | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Datasource: """ 通过 Excel/CSV 文件 URL 创建数据源 @@ -201,13 +201,13 @@ async def excel_csv_ask( *, file_url: str, question: str, - with_json: Optional[bool] | NotGiven = NOT_GIVEN, + with_json: Optional[bool] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileAskResponse: """ 通过 Excel/CSV 文件 URL 添加数据并提问 diff --git a/src/asktable/resources/policies.py b/src/asktable/resources/policies.py index fc27f2c4..ba28635e 100644 --- a/src/asktable/resources/policies.py +++ b/src/asktable/resources/policies.py @@ -2,13 +2,13 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import Literal import httpx from ..types import policy_list_params, policy_create_params, policy_update_params -from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -56,7 +56,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Policy: """ 定义一个新的策略 @@ -101,7 +101,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Policy: """ 获取某个策略 @@ -129,15 +129,15 @@ def update( self, policy_id: str, *, - dataset_config: Optional[policy_update_params.DatasetConfig] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - permission: Optional[Literal["allow", "deny"]] | NotGiven = NOT_GIVEN, + dataset_config: Optional[policy_update_params.DatasetConfig] | Omit = omit, + name: Optional[str] | Omit = omit, + permission: Optional[Literal["allow", "deny"]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Policy: """ 更新某个策略 @@ -178,16 +178,16 @@ def update( def list( self, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - policy_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + policy_ids: Optional[SequenceNotStr[str]] | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Policy]: """ 查询所有策略 @@ -239,7 +239,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ 删除某个策略 @@ -296,7 +296,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Policy: """ 定义一个新的策略 @@ -341,7 +341,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Policy: """ 获取某个策略 @@ -369,15 +369,15 @@ async def update( self, policy_id: str, *, - dataset_config: Optional[policy_update_params.DatasetConfig] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - permission: Optional[Literal["allow", "deny"]] | NotGiven = NOT_GIVEN, + dataset_config: Optional[policy_update_params.DatasetConfig] | Omit = omit, + name: Optional[str] | Omit = omit, + permission: Optional[Literal["allow", "deny"]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Policy: """ 更新某个策略 @@ -418,16 +418,16 @@ async def update( def list( self, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - policy_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + policy_ids: Optional[SequenceNotStr[str]] | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Policy, AsyncPage[Policy]]: """ 查询所有策略 @@ -479,7 +479,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ 删除某个策略 diff --git a/src/asktable/resources/polish.py b/src/asktable/resources/polish.py index 23df7f15..4cacff21 100644 --- a/src/asktable/resources/polish.py +++ b/src/asktable/resources/polish.py @@ -7,7 +7,7 @@ import httpx from ..types import polish_create_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -48,13 +48,13 @@ def create( *, max_word_count: int, user_desc: str, - polish_mode: Literal[0] | NotGiven = NOT_GIVEN, + polish_mode: Literal[0] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PolishCreateResponse: """ Polish Table Desc @@ -116,13 +116,13 @@ async def create( *, max_word_count: int, user_desc: str, - polish_mode: Literal[0] | NotGiven = NOT_GIVEN, + polish_mode: Literal[0] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PolishCreateResponse: """ Polish Table Desc diff --git a/src/asktable/resources/preferences.py b/src/asktable/resources/preferences.py index a96452be..69b0313c 100644 --- a/src/asktable/resources/preferences.py +++ b/src/asktable/resources/preferences.py @@ -7,7 +7,7 @@ import httpx from ..types import preference_create_params, preference_update_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -49,13 +49,13 @@ def create( self, *, general_preference: str, - sql_preference: Optional[str] | NotGiven = NOT_GIVEN, + sql_preference: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PreferenceCreateResponse: """ 创建偏好设置 @@ -96,7 +96,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PreferenceRetrieveResponse: """获取偏好设置""" return self._get( @@ -110,14 +110,14 @@ def retrieve( def update( self, *, - general_preference: Optional[str] | NotGiven = NOT_GIVEN, - sql_preference: Optional[str] | NotGiven = NOT_GIVEN, + general_preference: Optional[str] | Omit = omit, + sql_preference: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PreferenceUpdateResponse: """ 更新偏好设置 @@ -158,7 +158,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """删除偏好设置""" return self._delete( @@ -194,13 +194,13 @@ async def create( self, *, general_preference: str, - sql_preference: Optional[str] | NotGiven = NOT_GIVEN, + sql_preference: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PreferenceCreateResponse: """ 创建偏好设置 @@ -241,7 +241,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PreferenceRetrieveResponse: """获取偏好设置""" return await self._get( @@ -255,14 +255,14 @@ async def retrieve( async def update( self, *, - general_preference: Optional[str] | NotGiven = NOT_GIVEN, - sql_preference: Optional[str] | NotGiven = NOT_GIVEN, + general_preference: Optional[str] | Omit = omit, + sql_preference: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PreferenceUpdateResponse: """ 更新偏好设置 @@ -303,7 +303,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """删除偏好设置""" return await self._delete( diff --git a/src/asktable/resources/project.py b/src/asktable/resources/project.py index 5624ab32..f3033d69 100644 --- a/src/asktable/resources/project.py +++ b/src/asktable/resources/project.py @@ -7,7 +7,7 @@ import httpx from ..types import project_update_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -52,7 +52,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """Get My Project""" return self._get( @@ -66,14 +66,14 @@ def retrieve( def update( self, *, - llm_model_group: Optional[str] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + llm_model_group: Optional[str] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Update My Project @@ -114,7 +114,7 @@ def list_model_groups( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProjectListModelGroupsResponse: """Get Llm Model Groups""" return self._get( @@ -154,7 +154,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """Get My Project""" return await self._get( @@ -168,14 +168,14 @@ async def retrieve( async def update( self, *, - llm_model_group: Optional[str] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + llm_model_group: Optional[str] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Update My Project @@ -216,7 +216,7 @@ async def list_model_groups( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProjectListModelGroupsResponse: """Get Llm Model Groups""" return await self._get( diff --git a/src/asktable/resources/roles.py b/src/asktable/resources/roles.py index c05f9a91..44bf5e85 100644 --- a/src/asktable/resources/roles.py +++ b/src/asktable/resources/roles.py @@ -2,12 +2,12 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional import httpx 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 .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -49,13 +49,13 @@ def create( self, *, name: str, - policy_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, + policy_ids: Optional[SequenceNotStr[str]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Role: """ 创建一个新的角色 @@ -97,7 +97,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Role: """ 获取某个角色 @@ -125,14 +125,14 @@ def update( self, role_id: str, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - policy_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + policy_ids: Optional[SequenceNotStr[str]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Role: """ 更新某个角色 @@ -170,16 +170,16 @@ def update( def list( self, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - role_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + role_ids: Optional[SequenceNotStr[str]] | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Role]: """ 查询所有的角色 @@ -231,7 +231,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除某个角色 @@ -264,7 +264,7 @@ def get_polices( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RoleGetPolicesResponse: """ 查询某个角色的所有策略 @@ -292,14 +292,14 @@ def get_variables( self, role_id: str, *, - bot_id: Optional[str] | NotGiven = NOT_GIVEN, - datasource_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, + bot_id: Optional[str] | Omit = omit, + datasource_ids: Optional[SequenceNotStr[str]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 查询某个角色的所有变量 @@ -362,13 +362,13 @@ async def create( self, *, name: str, - policy_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, + policy_ids: Optional[SequenceNotStr[str]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Role: """ 创建一个新的角色 @@ -410,7 +410,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Role: """ 获取某个角色 @@ -438,14 +438,14 @@ async def update( self, role_id: str, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - policy_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + policy_ids: Optional[SequenceNotStr[str]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Role: """ 更新某个角色 @@ -483,16 +483,16 @@ async def update( def list( self, *, - name: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - role_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + name: Optional[str] | Omit = omit, + page: int | Omit = omit, + role_ids: Optional[SequenceNotStr[str]] | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Role, AsyncPage[Role]]: """ 查询所有的角色 @@ -544,7 +544,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 删除某个角色 @@ -577,7 +577,7 @@ async def get_polices( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RoleGetPolicesResponse: """ 查询某个角色的所有策略 @@ -605,14 +605,14 @@ async def get_variables( self, role_id: str, *, - bot_id: Optional[str] | NotGiven = NOT_GIVEN, - datasource_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, + bot_id: Optional[str] | Omit = omit, + datasource_ids: Optional[SequenceNotStr[str]] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ 查询某个角色的所有变量 diff --git a/src/asktable/resources/scores.py b/src/asktable/resources/scores.py index 343a17e8..28a7c15b 100644 --- a/src/asktable/resources/scores.py +++ b/src/asktable/resources/scores.py @@ -5,7 +5,7 @@ import httpx from ..types import score_create_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Query, Headers, NotGiven, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -52,7 +52,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ScoreCreateResponse: """ Score @@ -123,7 +123,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ScoreCreateResponse: """ Score diff --git a/src/asktable/resources/securetunnels.py b/src/asktable/resources/securetunnels.py index 13476a28..94972d7c 100644 --- a/src/asktable/resources/securetunnels.py +++ b/src/asktable/resources/securetunnels.py @@ -12,7 +12,7 @@ securetunnel_update_params, securetunnel_list_links_params, ) -from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -59,7 +59,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecureTunnel: """ 创建安全隧道 @@ -93,7 +93,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecureTunnel: """ 获取某个 ATST @@ -121,15 +121,15 @@ def update( self, securetunnel_id: str, *, - client_info: Optional[object] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - unique_key: Optional[str] | NotGiven = NOT_GIVEN, + client_info: Optional[object] | Omit = omit, + name: Optional[str] | Omit = omit, + unique_key: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecureTunnel: """ 更新某个 ATST @@ -170,14 +170,14 @@ def update( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[SecureTunnel]: """ 查询安全隧道列表 @@ -223,7 +223,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ 删除某个 ATST @@ -252,14 +252,14 @@ def list_links( self, securetunnel_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[SecuretunnelListLinksResponse]: """ 查询安全隧道的所有 Link @@ -328,7 +328,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecureTunnel: """ 创建安全隧道 @@ -362,7 +362,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecureTunnel: """ 获取某个 ATST @@ -390,15 +390,15 @@ async def update( self, securetunnel_id: str, *, - client_info: Optional[object] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, - unique_key: Optional[str] | NotGiven = NOT_GIVEN, + client_info: Optional[object] | Omit = omit, + name: Optional[str] | Omit = omit, + unique_key: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecureTunnel: """ 更新某个 ATST @@ -439,14 +439,14 @@ async def update( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[SecureTunnel, AsyncPage[SecureTunnel]]: """ 查询安全隧道列表 @@ -492,7 +492,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ 删除某个 ATST @@ -521,14 +521,14 @@ def list_links( self, securetunnel_id: str, *, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[SecuretunnelListLinksResponse, AsyncPage[SecuretunnelListLinksResponse]]: """ 查询安全隧道的所有 Link diff --git a/src/asktable/resources/sqls.py b/src/asktable/resources/sqls.py index fc871c84..8680b02a 100644 --- a/src/asktable/resources/sqls.py +++ b/src/asktable/resources/sqls.py @@ -7,7 +7,7 @@ import httpx from ..types import sql_list_params, sql_create_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -49,15 +49,15 @@ 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, + parameterize: bool | Omit = omit, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> QueryResponse: """ 发起生成 sql 的请求 @@ -103,15 +103,15 @@ def create( def list( self, *, - datasource_id: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + datasource_id: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[QueryResponse]: """ 获取所有的 Q2S 记录 @@ -177,15 +177,15 @@ 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, + parameterize: bool | Omit = omit, + role_id: Optional[str] | Omit = omit, + role_variables: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> QueryResponse: """ 发起生成 sql 的请求 @@ -231,15 +231,15 @@ async def create( def list( self, *, - datasource_id: Optional[str] | NotGiven = NOT_GIVEN, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + datasource_id: Optional[str] | Omit = omit, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[QueryResponse, AsyncPage[QueryResponse]]: """ 获取所有的 Q2S 记录 diff --git a/src/asktable/resources/sys/projects/api_keys.py b/src/asktable/resources/sys/projects/api_keys.py index 4b17a377..a95de033 100644 --- a/src/asktable/resources/sys/projects/api_keys.py +++ b/src/asktable/resources/sys/projects/api_keys.py @@ -7,7 +7,7 @@ import httpx -from ...._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource @@ -55,7 +55,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> APIKeyCreateResponse: """ 创建 API Key @@ -91,7 +91,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> APIKeyListResponse: """ List Api Keys @@ -125,7 +125,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete Api Key View @@ -156,16 +156,16 @@ def create_token( self, project_id: str, *, - ak_role: Literal["sys", "admin", "asker", "visitor"] | NotGiven = NOT_GIVEN, - chat_role: Optional[api_key_create_token_params.ChatRole] | NotGiven = NOT_GIVEN, - token_ttl: int | NotGiven = NOT_GIVEN, - user_profile: Optional[object] | NotGiven = NOT_GIVEN, + ak_role: Literal["sys", "admin", "asker", "visitor"] | Omit = omit, + chat_role: Optional[api_key_create_token_params.ChatRole] | Omit = omit, + token_ttl: int | Omit = omit, + user_profile: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Create Token @@ -237,7 +237,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> APIKeyCreateResponse: """ 创建 API Key @@ -273,7 +273,7 @@ async def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> APIKeyListResponse: """ List Api Keys @@ -307,7 +307,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete Api Key View @@ -338,16 +338,16 @@ async def create_token( self, project_id: str, *, - ak_role: Literal["sys", "admin", "asker", "visitor"] | NotGiven = NOT_GIVEN, - chat_role: Optional[api_key_create_token_params.ChatRole] | NotGiven = NOT_GIVEN, - token_ttl: int | NotGiven = NOT_GIVEN, - user_profile: Optional[object] | NotGiven = NOT_GIVEN, + ak_role: Literal["sys", "admin", "asker", "visitor"] | Omit = omit, + chat_role: Optional[api_key_create_token_params.ChatRole] | Omit = omit, + token_ttl: int | Omit = omit, + user_profile: Optional[object] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Create Token diff --git a/src/asktable/resources/sys/projects/projects.py b/src/asktable/resources/sys/projects/projects.py index 6c7c5f13..32b6cc5b 100644 --- a/src/asktable/resources/sys/projects/projects.py +++ b/src/asktable/resources/sys/projects/projects.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional import httpx @@ -14,7 +14,7 @@ APIKeysResourceWithStreamingResponse, AsyncAPIKeysResourceWithStreamingResponse, ) -from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ...._utils import maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource @@ -66,7 +66,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Create New Project @@ -100,7 +100,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Get Project @@ -128,15 +128,15 @@ def update( self, project_id: str, *, - llm_model_group: Optional[str] | NotGiven = NOT_GIVEN, - locked: Optional[bool] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + llm_model_group: Optional[str] | Omit = omit, + locked: Optional[bool] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Update Project @@ -177,15 +177,15 @@ def update( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - project_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + project_ids: Optional[SequenceNotStr[str]] | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[Project]: """ Get Projects @@ -234,7 +234,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Project @@ -267,7 +267,7 @@ def export( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Export Project @@ -300,7 +300,7 @@ def import_( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Import Project @@ -331,7 +331,7 @@ def model_groups( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProjectModelGroupsResponse: """Get Llm Model Groups""" return self._get( @@ -376,7 +376,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Create New Project @@ -410,7 +410,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Get Project @@ -438,15 +438,15 @@ async def update( self, project_id: str, *, - llm_model_group: Optional[str] | NotGiven = NOT_GIVEN, - locked: Optional[bool] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + llm_model_group: Optional[str] | Omit = omit, + locked: Optional[bool] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Update Project @@ -487,15 +487,15 @@ async def update( def list( self, *, - page: int | NotGiven = NOT_GIVEN, - project_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + project_ids: Optional[SequenceNotStr[str]] | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Project, AsyncPage[Project]]: """ Get Projects @@ -544,7 +544,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Project @@ -577,7 +577,7 @@ async def export( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Export Project @@ -610,7 +610,7 @@ async def import_( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Import Project @@ -641,7 +641,7 @@ async def model_groups( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProjectModelGroupsResponse: """Get Llm Model Groups""" return await self._get( diff --git a/src/asktable/resources/sys/sys.py b/src/asktable/resources/sys/sys.py index 3ab1213c..27f630db 100644 --- a/src/asktable/resources/sys/sys.py +++ b/src/asktable/resources/sys/sys.py @@ -2,22 +2,8 @@ from __future__ import annotations -from typing import Optional - -import httpx - -from ...types import sy_update_config_params -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options from .projects.projects import ( ProjectsResource, AsyncProjectsResource, @@ -26,7 +12,6 @@ ProjectsResourceWithStreamingResponse, AsyncProjectsResourceWithStreamingResponse, ) -from ...types.sy_update_config_response import SyUpdateConfigResponse __all__ = ["SysResource", "AsyncSysResource"] @@ -55,42 +40,6 @@ def with_streaming_response(self) -> SysResourceWithStreamingResponse: """ return SysResourceWithStreamingResponse(self) - def update_config( - self, - *, - global_table_limit: Optional[int] | 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> SyUpdateConfigResponse: - """ - Update Config - - Args: - global_table_limit: 表限制数量 - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._patch( - "/v1/sys/config", - body=maybe_transform( - {"global_table_limit": global_table_limit}, sy_update_config_params.SyUpdateConfigParams - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=SyUpdateConfigResponse, - ) - class AsyncSysResource(AsyncAPIResource): @cached_property @@ -116,51 +65,11 @@ def with_streaming_response(self) -> AsyncSysResourceWithStreamingResponse: """ return AsyncSysResourceWithStreamingResponse(self) - async def update_config( - self, - *, - global_table_limit: Optional[int] | 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> SyUpdateConfigResponse: - """ - Update Config - - Args: - global_table_limit: 表限制数量 - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._patch( - "/v1/sys/config", - body=await async_maybe_transform( - {"global_table_limit": global_table_limit}, sy_update_config_params.SyUpdateConfigParams - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=SyUpdateConfigResponse, - ) - class SysResourceWithRawResponse: def __init__(self, sys: SysResource) -> None: self._sys = sys - self.update_config = to_raw_response_wrapper( - sys.update_config, - ) - @cached_property def projects(self) -> ProjectsResourceWithRawResponse: return ProjectsResourceWithRawResponse(self._sys.projects) @@ -170,10 +79,6 @@ class AsyncSysResourceWithRawResponse: def __init__(self, sys: AsyncSysResource) -> None: self._sys = sys - self.update_config = async_to_raw_response_wrapper( - sys.update_config, - ) - @cached_property def projects(self) -> AsyncProjectsResourceWithRawResponse: return AsyncProjectsResourceWithRawResponse(self._sys.projects) @@ -183,10 +88,6 @@ class SysResourceWithStreamingResponse: def __init__(self, sys: SysResource) -> None: self._sys = sys - self.update_config = to_streamed_response_wrapper( - sys.update_config, - ) - @cached_property def projects(self) -> ProjectsResourceWithStreamingResponse: return ProjectsResourceWithStreamingResponse(self._sys.projects) @@ -196,10 +97,6 @@ class AsyncSysResourceWithStreamingResponse: def __init__(self, sys: AsyncSysResource) -> None: self._sys = sys - self.update_config = async_to_streamed_response_wrapper( - sys.update_config, - ) - @cached_property def projects(self) -> AsyncProjectsResourceWithStreamingResponse: return AsyncProjectsResourceWithStreamingResponse(self._sys.projects) diff --git a/src/asktable/resources/trainings.py b/src/asktable/resources/trainings.py index 98882a5c..4037eaf0 100644 --- a/src/asktable/resources/trainings.py +++ b/src/asktable/resources/trainings.py @@ -7,7 +7,7 @@ import httpx from ..types import training_list_params, training_create_params, training_delete_params, training_update_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -56,7 +56,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TrainingCreateResponse: """ Create Training Pair @@ -90,16 +90,16 @@ def update( id: str, *, datasource_id: str, - active: Optional[bool] | NotGiven = NOT_GIVEN, - question: Optional[str] | NotGiven = NOT_GIVEN, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - sql: Optional[str] | NotGiven = NOT_GIVEN, + active: Optional[bool] | Omit = omit, + question: Optional[str] | Omit = omit, + role_id: Optional[str] | Omit = omit, + sql: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TrainingUpdateResponse: """ Update Training Pair @@ -150,14 +150,14 @@ def list( self, *, datasource_id: str, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncPage[TrainingListResponse]: """ Get Training Pairs @@ -207,7 +207,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Training Pair @@ -268,7 +268,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TrainingCreateResponse: """ Create Training Pair @@ -304,16 +304,16 @@ async def update( id: str, *, datasource_id: str, - active: Optional[bool] | NotGiven = NOT_GIVEN, - question: Optional[str] | NotGiven = NOT_GIVEN, - role_id: Optional[str] | NotGiven = NOT_GIVEN, - sql: Optional[str] | NotGiven = NOT_GIVEN, + active: Optional[bool] | Omit = omit, + question: Optional[str] | Omit = omit, + role_id: Optional[str] | Omit = omit, + sql: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TrainingUpdateResponse: """ Update Training Pair @@ -366,14 +366,14 @@ def list( self, *, datasource_id: str, - page: int | NotGiven = NOT_GIVEN, - size: int | NotGiven = NOT_GIVEN, + page: int | Omit = omit, + size: int | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[TrainingListResponse, AsyncPage[TrainingListResponse]]: """ Get Training Pairs @@ -423,7 +423,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> object: """ Delete Training Pair diff --git a/src/asktable/resources/user/projects.py b/src/asktable/resources/user/projects.py index 27ba7426..929f5a70 100644 --- a/src/asktable/resources/user/projects.py +++ b/src/asktable/resources/user/projects.py @@ -6,7 +6,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -52,7 +52,7 @@ def retrieve_model_groups( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProjectRetrieveModelGroupsResponse: """Get Llm Model Groups""" return self._get( @@ -71,7 +71,7 @@ def retrieve_my_project( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """Get My Project""" return self._get( @@ -85,14 +85,14 @@ def retrieve_my_project( def update_my_project( self, *, - llm_model_group: Optional[str] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + llm_model_group: Optional[str] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Update My Project @@ -154,7 +154,7 @@ async def retrieve_model_groups( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProjectRetrieveModelGroupsResponse: """Get Llm Model Groups""" return await self._get( @@ -173,7 +173,7 @@ async def retrieve_my_project( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """Get My Project""" return await self._get( @@ -187,14 +187,14 @@ async def retrieve_my_project( async def update_my_project( self, *, - llm_model_group: Optional[str] | NotGiven = NOT_GIVEN, - name: Optional[str] | NotGiven = NOT_GIVEN, + llm_model_group: Optional[str] | Omit = omit, + name: Optional[str] | Omit = omit, # 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, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: """ Update My Project diff --git a/src/asktable/types/__init__.py b/src/asktable/types/__init__.py index 640c9f4b..066786d0 100644 --- a/src/asktable/types/__init__.py +++ b/src/asktable/types/__init__.py @@ -55,7 +55,6 @@ from .training_delete_params import TrainingDeleteParams as TrainingDeleteParams from .training_list_response import TrainingListResponse as TrainingListResponse from .training_update_params import TrainingUpdateParams as TrainingUpdateParams -from .sy_update_config_params import SyUpdateConfigParams as SyUpdateConfigParams from .auth_create_token_params import AuthCreateTokenParams as AuthCreateTokenParams from .datasource_create_params import DatasourceCreateParams as DatasourceCreateParams from .datasource_update_params import DatasourceUpdateParams as DatasourceUpdateParams @@ -66,7 +65,6 @@ from .training_update_response import TrainingUpdateResponse as TrainingUpdateResponse from .role_get_polices_response import RoleGetPolicesResponse as RoleGetPolicesResponse from .role_get_variables_params import RoleGetVariablesParams as RoleGetVariablesParams -from .sy_update_config_response import SyUpdateConfigResponse as SyUpdateConfigResponse from .datasource_add_file_params import DatasourceAddFileParams as DatasourceAddFileParams from .preference_create_response import PreferenceCreateResponse as PreferenceCreateResponse from .preference_update_response import PreferenceUpdateResponse as PreferenceUpdateResponse diff --git a/src/asktable/types/ai_message.py b/src/asktable/types/ai_message.py index 986e1827..157a7dcc 100644 --- a/src/asktable/types/ai_message.py +++ b/src/asktable/types/ai_message.py @@ -12,7 +12,7 @@ class ContentAttachment(BaseModel): info: object - type: str + type: Literal["data_json"] """The type of the attachment""" diff --git a/src/asktable/types/answer_response.py b/src/asktable/types/answer_response.py index 04112480..7043de0f 100644 --- a/src/asktable/types/answer_response.py +++ b/src/asktable/types/answer_response.py @@ -2,6 +2,7 @@ from typing import List, Optional from datetime import datetime +from typing_extensions import Literal from .._models import BaseModel @@ -11,7 +12,7 @@ class AnswerAttachment(BaseModel): info: object - type: str + type: Literal["data_json"] """The type of the attachment""" diff --git a/src/asktable/types/ats/task_get_case_tasks_response.py b/src/asktable/types/ats/task_get_case_tasks_response.py index 0592193e..37821e0c 100644 --- a/src/asktable/types/ats/task_get_case_tasks_response.py +++ b/src/asktable/types/ats/task_get_case_tasks_response.py @@ -2,10 +2,19 @@ from typing import List, Union, Optional from datetime import datetime +from typing_extensions import Literal from ..._models import BaseModel -__all__ = ["TaskGetCaseTasksResponse", "Item"] +__all__ = ["TaskGetCaseTasksResponse", "Item", "ItemCompareLog"] + + +class ItemCompareLog(BaseModel): + check: str + + level: Literal["ERROR", "WARNING", "INFO"] + + message: str class Item(BaseModel): @@ -33,6 +42,9 @@ class Item(BaseModel): atc_id: Optional[str] = None """对应的测试用例 ID""" + compare_logs: Optional[List[ItemCompareLog]] = None + """测试样本生成 sql 和预期 sql 的对比日志""" + duration: Optional[float] = None """测试用例执行时间,单位为秒""" @@ -60,6 +72,9 @@ class Item(BaseModel): task_id: Optional[str] = None """测试调用接口对应任务的 id""" + trace_id: Optional[str] = None + """测试样本运行时对应的 trace_id""" + class TaskGetCaseTasksResponse(BaseModel): items: List[Item] diff --git a/src/asktable/types/ats/task_list_response.py b/src/asktable/types/ats/task_list_response.py index a3591ca0..5a0d599a 100644 --- a/src/asktable/types/ats/task_list_response.py +++ b/src/asktable/types/ats/task_list_response.py @@ -3,9 +3,27 @@ from typing import Optional from datetime import datetime +from pydantic import Field as FieldInfo + from ..._models import BaseModel -__all__ = ["TaskListResponse"] +__all__ = ["TaskListResponse", "ModelGroup"] + + +class ModelGroup(BaseModel): + """运行使用的模型组""" + + agent: str + + fast: str + + name: str + + omni: str + + sql: str + + report: Optional[str] = None class TaskListResponse(BaseModel): @@ -45,5 +63,8 @@ class TaskListResponse(BaseModel): last_run: Optional[datetime] = None """上次测试运行时间""" + api_model_group: Optional[ModelGroup] = FieldInfo(alias="model_group", default=None) + """运行使用的模型组""" + status_message: Optional[str] = None """测试日志""" diff --git a/src/asktable/types/ats/task_retrieve_response.py b/src/asktable/types/ats/task_retrieve_response.py index bc81d5bc..178a9c8f 100644 --- a/src/asktable/types/ats/task_retrieve_response.py +++ b/src/asktable/types/ats/task_retrieve_response.py @@ -3,9 +3,27 @@ from typing import Optional from datetime import datetime +from pydantic import Field as FieldInfo + from ..._models import BaseModel -__all__ = ["TaskRetrieveResponse"] +__all__ = ["TaskRetrieveResponse", "ModelGroup"] + + +class ModelGroup(BaseModel): + """运行使用的模型组""" + + agent: str + + fast: str + + name: str + + omni: str + + sql: str + + report: Optional[str] = None class TaskRetrieveResponse(BaseModel): @@ -45,5 +63,8 @@ class TaskRetrieveResponse(BaseModel): last_run: Optional[datetime] = None """上次测试运行时间""" + api_model_group: Optional[ModelGroup] = FieldInfo(alias="model_group", default=None) + """运行使用的模型组""" + status_message: Optional[str] = None """测试日志""" diff --git a/src/asktable/types/ats/task_run_params.py b/src/asktable/types/ats/task_run_params.py index b86b4193..a397edcb 100644 --- a/src/asktable/types/ats/task_run_params.py +++ b/src/asktable/types/ats/task_run_params.py @@ -2,9 +2,10 @@ from __future__ import annotations -from typing import List from typing_extensions import Required, TypedDict +from ..._types import SequenceNotStr + __all__ = ["TaskRunParams"] @@ -12,5 +13,5 @@ class TaskRunParams(TypedDict, total=False): datasource_id: Required[str] """数据源 ID""" - specific_case_ids: Required[List[str]] + specific_case_ids: Required[SequenceNotStr[str]] """测试用例 ID 列表""" diff --git a/src/asktable/types/ats/task_run_response.py b/src/asktable/types/ats/task_run_response.py index fbc3533c..3e291d48 100644 --- a/src/asktable/types/ats/task_run_response.py +++ b/src/asktable/types/ats/task_run_response.py @@ -3,9 +3,27 @@ from typing import Optional from datetime import datetime +from pydantic import Field as FieldInfo + from ..._models import BaseModel -__all__ = ["TaskRunResponse"] +__all__ = ["TaskRunResponse", "ModelGroup"] + + +class ModelGroup(BaseModel): + """运行使用的模型组""" + + agent: str + + fast: str + + name: str + + omni: str + + sql: str + + report: Optional[str] = None class TaskRunResponse(BaseModel): @@ -45,5 +63,8 @@ class TaskRunResponse(BaseModel): last_run: Optional[datetime] = None """上次测试运行时间""" + api_model_group: Optional[ModelGroup] = FieldInfo(alias="model_group", default=None) + """运行使用的模型组""" + status_message: Optional[str] = None """测试日志""" diff --git a/src/asktable/types/auth_create_token_params.py b/src/asktable/types/auth_create_token_params.py index 7764745b..2fea46ba 100644 --- a/src/asktable/types/auth_create_token_params.py +++ b/src/asktable/types/auth_create_token_params.py @@ -23,6 +23,8 @@ class AuthCreateTokenParams(TypedDict, total=False): class ChatRole(TypedDict, total=False): + """The chat role""" + role_id: Optional[str] """The chat role ID""" diff --git a/src/asktable/types/bot_create_params.py b/src/asktable/types/bot_create_params.py index e2a2f550..9cadd984 100644 --- a/src/asktable/types/bot_create_params.py +++ b/src/asktable/types/bot_create_params.py @@ -2,14 +2,16 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import Iterable, Optional from typing_extensions import Literal, Required, TypedDict +from .._types import SequenceNotStr + __all__ = ["BotCreateParams", "InteractionRule"] class BotCreateParams(TypedDict, total=False): - datasource_ids: Required[List[str]] + datasource_ids: Required[SequenceNotStr[str]] """数据源 ID,目前只支持 1 个数据源。""" name: Required[str] @@ -21,9 +23,6 @@ class BotCreateParams(TypedDict, total=False): debug: bool """调试模式""" - extapi_ids: List[str] - """扩展 API ID 列表,扩展 API ID 的逗号分隔列表。""" - interaction_rules: Iterable[InteractionRule] """交互规则列表,用于定义 bot 的行为规则""" @@ -39,10 +38,10 @@ class BotCreateParams(TypedDict, total=False): query_balance: Optional[int] """bot 的查询次数,默认是 None,表示无限次查询,入参为大于等于 0 的整数""" - sample_questions: Optional[List[str]] + sample_questions: Optional[SequenceNotStr[str]] """示例问题列表""" - webhooks: List[str] + webhooks: SequenceNotStr[str] """Webhook URL 列表""" welcome_message: Optional[str] @@ -58,4 +57,4 @@ class InteractionRule(TypedDict, total=False): version: Required[Literal["1.0.0"]] - words: Required[List[str]] + words: Required[SequenceNotStr[str]] diff --git a/src/asktable/types/bot_list_params.py b/src/asktable/types/bot_list_params.py index 2463c813..063a000f 100644 --- a/src/asktable/types/bot_list_params.py +++ b/src/asktable/types/bot_list_params.py @@ -2,14 +2,16 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import TypedDict +from .._types import SequenceNotStr + __all__ = ["BotListParams"] class BotListParams(TypedDict, total=False): - bot_ids: Optional[List[str]] + bot_ids: Optional[SequenceNotStr[str]] """Bot ID""" name: Optional[str] diff --git a/src/asktable/types/bot_update_params.py b/src/asktable/types/bot_update_params.py index e08d5a37..fc5b2ba9 100644 --- a/src/asktable/types/bot_update_params.py +++ b/src/asktable/types/bot_update_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import Iterable, Optional from typing_extensions import Literal, Required, TypedDict +from .._types import SequenceNotStr + __all__ = ["BotUpdateParams", "InteractionRule"] @@ -15,15 +17,12 @@ class BotUpdateParams(TypedDict, total=False): color_theme: Optional[str] """颜色主题""" - datasource_ids: Optional[List[str]] + datasource_ids: Optional[SequenceNotStr[str]] """数据源 ID,目前只支持 1 个数据源。""" debug: Optional[bool] """调试模式""" - extapi_ids: Optional[List[str]] - """扩展 API ID 列表,扩展 API ID 的逗号分隔列表。""" - interaction_rules: Optional[Iterable[InteractionRule]] """交互规则列表,用于定义 bot 的行为规则""" @@ -42,10 +41,10 @@ class BotUpdateParams(TypedDict, total=False): query_balance: Optional[int] """bot 的查询次数,默认是 None,表示无限次查询,入参为大于等于 0 的整数""" - sample_questions: Optional[List[str]] + sample_questions: Optional[SequenceNotStr[str]] """示例问题列表""" - webhooks: Optional[List[str]] + webhooks: Optional[SequenceNotStr[str]] """Webhook URL 列表""" welcome_message: Optional[str] @@ -61,4 +60,4 @@ class InteractionRule(TypedDict, total=False): version: Required[Literal["1.0.0"]] - words: Required[List[str]] + words: Required[SequenceNotStr[str]] diff --git a/src/asktable/types/business_glossary_create_params.py b/src/asktable/types/business_glossary_create_params.py index e9f3d42d..e9b8fd0f 100644 --- a/src/asktable/types/business_glossary_create_params.py +++ b/src/asktable/types/business_glossary_create_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import Iterable, Optional from typing_extensions import Required, TypedDict +from .._types import SequenceNotStr + __all__ = ["BusinessGlossaryCreateParams", "Body"] @@ -13,6 +15,8 @@ class BusinessGlossaryCreateParams(TypedDict, total=False): class Body(TypedDict, total=False): + """Schema for creating a new document""" + definition: Required[str] """业务术语定义""" @@ -22,7 +26,7 @@ class Body(TypedDict, total=False): active: bool """业务术语是否生效""" - aliases: Optional[List[str]] + aliases: Optional[SequenceNotStr[str]] """业务术语同义词""" payload: Optional[object] diff --git a/src/asktable/types/business_glossary_update_params.py b/src/asktable/types/business_glossary_update_params.py index 89bad224..092cebe8 100644 --- a/src/asktable/types/business_glossary_update_params.py +++ b/src/asktable/types/business_glossary_update_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import TypedDict +from .._types import SequenceNotStr + __all__ = ["BusinessGlossaryUpdateParams"] @@ -12,7 +14,7 @@ class BusinessGlossaryUpdateParams(TypedDict, total=False): active: Optional[bool] """业务术语是否生效""" - aliases: Optional[List[str]] + aliases: Optional[SequenceNotStr[str]] """业务术语同义词""" definition: Optional[str] diff --git a/src/asktable/types/chatbot.py b/src/asktable/types/chatbot.py index 2c37b41b..1bd6bd60 100644 --- a/src/asktable/types/chatbot.py +++ b/src/asktable/types/chatbot.py @@ -45,9 +45,6 @@ class Chatbot(BaseModel): debug: Optional[bool] = None """调试模式""" - extapi_ids: Optional[List[str]] = None - """扩展 API ID 列表,扩展 API ID 的逗号分隔列表。""" - interaction_rules: Optional[List[InteractionRule]] = None """交互规则列表,用于定义 bot 的行为规则""" diff --git a/src/asktable/types/datasource.py b/src/asktable/types/datasource.py index 70a1ae18..319103ca 100644 --- a/src/asktable/types/datasource.py +++ b/src/asktable/types/datasource.py @@ -38,6 +38,9 @@ class Datasource(BaseModel): "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ] """数据源引擎""" diff --git a/src/asktable/types/datasource_create_params.py b/src/asktable/types/datasource_create_params.py index afd362b0..f92c937f 100644 --- a/src/asktable/types/datasource_create_params.py +++ b/src/asktable/types/datasource_create_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Union, Optional +from typing import Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict +from .._types import SequenceNotStr + __all__ = [ "DatasourceCreateParams", "AccessConfig", @@ -37,6 +39,9 @@ class DatasourceCreateParams(TypedDict, total=False): "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ] ] """数据源引擎""" @@ -75,7 +80,7 @@ class AccessConfigAccessConfigConnectionCreate(TypedDict, total=False): class AccessConfigAccessConfigFileCreate(TypedDict, total=False): - files: Required[List[str]] + files: Required[SequenceNotStr[str]] """数据源文件 URL 列表, 创建时可以传入 URL""" diff --git a/src/asktable/types/datasource_retrieve_response.py b/src/asktable/types/datasource_retrieve_response.py index d244225c..01ad31a3 100644 --- a/src/asktable/types/datasource_retrieve_response.py +++ b/src/asktable/types/datasource_retrieve_response.py @@ -93,6 +93,9 @@ class DatasourceRetrieveResponse(BaseModel): "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ] """数据源引擎""" diff --git a/src/asktable/types/datasource_update_params.py b/src/asktable/types/datasource_update_params.py index ff22daff..3397d6d7 100644 --- a/src/asktable/types/datasource_update_params.py +++ b/src/asktable/types/datasource_update_params.py @@ -44,6 +44,9 @@ class DatasourceUpdateParams(TypedDict, total=False): "databend", "sqlserver", "mogdb", + "hologres", + "maxcompute", + "dap", ] ] """数据源引擎""" diff --git a/src/asktable/types/datasources/meta_create_params.py b/src/asktable/types/datasources/meta_create_params.py index 86783588..caebf645 100644 --- a/src/asktable/types/datasources/meta_create_params.py +++ b/src/asktable/types/datasources/meta_create_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import Dict, List, Optional +from typing import Dict, Optional from typing_extensions import Literal, Required, TypedDict +from ..._types import SequenceNotStr + __all__ = ["MetaCreateParams", "Meta", "MetaSchemas", "MetaSchemasTables", "MetaSchemasTablesFields"] @@ -15,7 +17,7 @@ class MetaCreateParams(TypedDict, total=False): meta: Optional[Meta] - selected_tables: Optional[Dict[str, List[str]]] + selected_tables: Optional[Dict[str, SequenceNotStr[str]]] class MetaSchemasTablesFields(TypedDict, total=False): diff --git a/src/asktable/types/datasources/meta_update_params.py b/src/asktable/types/datasources/meta_update_params.py index 2a14b685..bf1938eb 100644 --- a/src/asktable/types/datasources/meta_update_params.py +++ b/src/asktable/types/datasources/meta_update_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import Dict, List, Optional +from typing import Dict, Optional from typing_extensions import Literal, Required, TypedDict +from ..._types import SequenceNotStr + __all__ = ["MetaUpdateParams", "Meta", "MetaSchemas", "MetaSchemasTables", "MetaSchemasTablesFields"] @@ -13,7 +15,7 @@ class MetaUpdateParams(TypedDict, total=False): meta: Optional[Meta] - selected_tables: Optional[Dict[str, List[str]]] + selected_tables: Optional[Dict[str, SequenceNotStr[str]]] class MetaSchemasTablesFields(TypedDict, total=False): diff --git a/src/asktable/types/entry.py b/src/asktable/types/entry.py index a4140a5d..16afd695 100644 --- a/src/asktable/types/entry.py +++ b/src/asktable/types/entry.py @@ -9,6 +9,8 @@ class Entry(BaseModel): + """Schema for document response""" + id: str """业务术语 ID""" diff --git a/src/asktable/types/index.py b/src/asktable/types/index.py index a558c037..ea46e49f 100644 --- a/src/asktable/types/index.py +++ b/src/asktable/types/index.py @@ -9,6 +9,8 @@ class Index(BaseModel): + """索引响应模型""" + id: str """索引 ID""" diff --git a/src/asktable/types/policy_create_params.py b/src/asktable/types/policy_create_params.py index 9630207c..64ca1c7b 100644 --- a/src/asktable/types/policy_create_params.py +++ b/src/asktable/types/policy_create_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import Dict, List, Optional +from typing import Dict, Optional from typing_extensions import Literal, Required, TypedDict +from .._types import SequenceNotStr + __all__ = ["PolicyCreateParams", "DatasetConfig", "DatasetConfigRegexPatterns"] @@ -20,6 +22,12 @@ class PolicyCreateParams(TypedDict, total=False): class DatasetConfigRegexPatterns(TypedDict, total=False): + """ + 正则表达式。 + - 描述:用于匹配指定数据源中Schema(DB)、Table和Field名称的三个正则表达式,即同时满足这三个正则表达式的DB、Table和Field才被允许访问。 + - 注意:此字段为可选项。如果未提供,则默认包含指定数据源的所有数据。 + """ + fields_regex_pattern: Optional[str] """Field 正则表达式,空值默认全选""" @@ -31,7 +39,9 @@ class DatasetConfigRegexPatterns(TypedDict, total=False): class DatasetConfig(TypedDict, total=False): - datasource_ids: Required[List[str]] + """数据集配置""" + + datasource_ids: Required[SequenceNotStr[str]] """ 数据源 ID 列表,必填。 - 描述:用于指定策略适用的数据源。可以使用通配符 _ 表示所 有数据源。 - 示例:["ds_id_1","ds_id_2"],["_"]。 @@ -44,7 +54,7 @@ class DatasetConfig(TypedDict, total=False): 注意:此字段为可选项。如果未提供,则默认包含指定数据源的所有数据。 """ - rows_filters: Optional[Dict[str, List[str]]] + rows_filters: Optional[Dict[str, SequenceNotStr[str]]] """行级别过滤器。 - 描述:指定行级别的过滤器,满足条件的行才可访问。 用户在查询数据的时候会自动对 diff --git a/src/asktable/types/policy_list_params.py b/src/asktable/types/policy_list_params.py index 5a9e7ea6..a8e91ab3 100644 --- a/src/asktable/types/policy_list_params.py +++ b/src/asktable/types/policy_list_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import TypedDict +from .._types import SequenceNotStr + __all__ = ["PolicyListParams"] @@ -15,7 +17,7 @@ class PolicyListParams(TypedDict, total=False): page: int """Page number""" - policy_ids: Optional[List[str]] + policy_ids: Optional[SequenceNotStr[str]] """策略 ID 列表""" size: int diff --git a/src/asktable/types/policy_update_params.py b/src/asktable/types/policy_update_params.py index dc1675b2..3aae252d 100644 --- a/src/asktable/types/policy_update_params.py +++ b/src/asktable/types/policy_update_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import Dict, List, Iterable, Optional +from typing import Dict, Iterable, Optional from typing_extensions import Literal, Required, TypedDict +from .._types import SequenceNotStr + __all__ = ["PolicyUpdateParams", "DatasetConfig", "DatasetConfigRegexPatterns", "DatasetConfigRowsFilter"] @@ -20,6 +22,12 @@ class PolicyUpdateParams(TypedDict, total=False): class DatasetConfigRegexPatterns(TypedDict, total=False): + """ + 正则表达式。 + - 描述:用于匹配指定数据源中Schema(DB)、Table和Field名称的三个正则表达式,即同时满足这三个正则表达式的DB、Table和Field才被允许访问。 + - 注意:此字段为可选项。如果未提供,则默认包含指定数据源的所有数据。 + """ + fields_regex_pattern: Optional[str] """Field 正则表达式,空值默认全选""" @@ -46,12 +54,14 @@ class DatasetConfigRowsFilter(TypedDict, total=False): table_regex: Required[str] """Table regex pattern""" - variables: List[str] + variables: SequenceNotStr[str] """Jinja2 variables in the condition""" class DatasetConfig(TypedDict, total=False): - datasource_ids: Required[List[str]] + """数据集配置""" + + datasource_ids: Required[SequenceNotStr[str]] """ 数据源 ID 列表,必填。 - 描述:用于指定策略适用的数据源。可以使用通配符 _ 表示所 有数据源。 - 示例:["ds_id_1","ds_id_2"],["_"]。 diff --git a/src/asktable/types/preference_create_response.py b/src/asktable/types/preference_create_response.py index 9016f33f..07844536 100644 --- a/src/asktable/types/preference_create_response.py +++ b/src/asktable/types/preference_create_response.py @@ -8,6 +8,8 @@ class PreferenceCreateResponse(BaseModel): + """Schema for preference response""" + id: str """偏好设置 ID""" diff --git a/src/asktable/types/preference_retrieve_response.py b/src/asktable/types/preference_retrieve_response.py index 36afa791..587c5d14 100644 --- a/src/asktable/types/preference_retrieve_response.py +++ b/src/asktable/types/preference_retrieve_response.py @@ -8,6 +8,8 @@ class PreferenceRetrieveResponse(BaseModel): + """Schema for preference response""" + id: str """偏好设置 ID""" diff --git a/src/asktable/types/preference_update_response.py b/src/asktable/types/preference_update_response.py index a317deae..e5b309bd 100644 --- a/src/asktable/types/preference_update_response.py +++ b/src/asktable/types/preference_update_response.py @@ -8,6 +8,8 @@ class PreferenceUpdateResponse(BaseModel): + """Schema for preference response""" + id: str """偏好设置 ID""" diff --git a/src/asktable/types/role_create_params.py b/src/asktable/types/role_create_params.py index 4750a3e0..4e0679c7 100644 --- a/src/asktable/types/role_create_params.py +++ b/src/asktable/types/role_create_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import Required, TypedDict +from .._types import SequenceNotStr + __all__ = ["RoleCreateParams"] @@ -12,5 +14,5 @@ class RoleCreateParams(TypedDict, total=False): name: Required[str] """名称""" - policy_ids: Optional[List[str]] + policy_ids: Optional[SequenceNotStr[str]] """策略列表。注意:如果为空或者不传则不绑定策略""" diff --git a/src/asktable/types/role_get_variables_params.py b/src/asktable/types/role_get_variables_params.py index cebb567c..35a79f86 100644 --- a/src/asktable/types/role_get_variables_params.py +++ b/src/asktable/types/role_get_variables_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import TypedDict +from .._types import SequenceNotStr + __all__ = ["RoleGetVariablesParams"] @@ -12,5 +14,5 @@ class RoleGetVariablesParams(TypedDict, total=False): bot_id: Optional[str] """Bot ID""" - datasource_ids: Optional[List[str]] + datasource_ids: Optional[SequenceNotStr[str]] """数据源 ID 列表""" diff --git a/src/asktable/types/role_list_params.py b/src/asktable/types/role_list_params.py index 851c0904..a5e6e489 100644 --- a/src/asktable/types/role_list_params.py +++ b/src/asktable/types/role_list_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import TypedDict +from .._types import SequenceNotStr + __all__ = ["RoleListParams"] @@ -15,7 +17,7 @@ class RoleListParams(TypedDict, total=False): page: int """Page number""" - role_ids: Optional[List[str]] + role_ids: Optional[SequenceNotStr[str]] """角色 ID 列表""" size: int diff --git a/src/asktable/types/role_update_params.py b/src/asktable/types/role_update_params.py index 6cb3bb99..2cb20bea 100644 --- a/src/asktable/types/role_update_params.py +++ b/src/asktable/types/role_update_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import TypedDict +from .._types import SequenceNotStr + __all__ = ["RoleUpdateParams"] @@ -12,5 +14,5 @@ class RoleUpdateParams(TypedDict, total=False): name: Optional[str] """名称""" - policy_ids: Optional[List[str]] + policy_ids: Optional[SequenceNotStr[str]] """策略列表。注意:如果为空或者不传则不绑定策略""" diff --git a/src/asktable/types/shared/policy.py b/src/asktable/types/shared/policy.py index 0fd1b6db..ac3aef11 100644 --- a/src/asktable/types/shared/policy.py +++ b/src/asktable/types/shared/policy.py @@ -10,6 +10,12 @@ class DatasetConfigRegexPatterns(BaseModel): + """ + 正则表达式。 + - 描述:用于匹配指定数据源中Schema(DB)、Table和Field名称的三个正则表达式,即同时满足这三个正则表达式的DB、Table和Field才被允许访问。 + - 注意:此字段为可选项。如果未提供,则默认包含指定数据源的所有数据。 + """ + fields_regex_pattern: Optional[str] = None """Field 正则表达式,空值默认全选""" diff --git a/src/asktable/types/sy_update_config_params.py b/src/asktable/types/sy_update_config_params.py deleted file mode 100644 index fd7c7246..00000000 --- a/src/asktable/types/sy_update_config_params.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import TypedDict - -__all__ = ["SyUpdateConfigParams"] - - -class SyUpdateConfigParams(TypedDict, total=False): - global_table_limit: Optional[int] - """表限制数量""" diff --git a/src/asktable/types/sy_update_config_response.py b/src/asktable/types/sy_update_config_response.py deleted file mode 100644 index 9d77316d..00000000 --- a/src/asktable/types/sy_update_config_response.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from .._models import BaseModel - -__all__ = ["SyUpdateConfigResponse"] - - -class SyUpdateConfigResponse(BaseModel): - global_table_limit: Optional[int] = None - """表限制数量""" diff --git a/src/asktable/types/sys/model_group.py b/src/asktable/types/sys/model_group.py index d37d6270..82382099 100644 --- a/src/asktable/types/sys/model_group.py +++ b/src/asktable/types/sys/model_group.py @@ -15,14 +15,14 @@ class ModelGroup(BaseModel): fast: str """快速模型""" - image: str - """图片模型""" - name: str """模型组名称""" omni: str """通用模型""" + report: str + """报告模型""" + sql: str """SQL 模型""" diff --git a/src/asktable/types/sys/project_list_params.py b/src/asktable/types/sys/project_list_params.py index f0b103dc..661b42ad 100644 --- a/src/asktable/types/sys/project_list_params.py +++ b/src/asktable/types/sys/project_list_params.py @@ -2,9 +2,11 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import TypedDict +from ..._types import SequenceNotStr + __all__ = ["ProjectListParams"] @@ -12,7 +14,7 @@ class ProjectListParams(TypedDict, total=False): page: int """Page number""" - project_ids: Optional[List[str]] + project_ids: Optional[SequenceNotStr[str]] """项目 ID 列表""" size: int diff --git a/src/asktable/types/sys/projects/api_key_create_token_params.py b/src/asktable/types/sys/projects/api_key_create_token_params.py index 212976c8..e65d75c2 100644 --- a/src/asktable/types/sys/projects/api_key_create_token_params.py +++ b/src/asktable/types/sys/projects/api_key_create_token_params.py @@ -23,6 +23,8 @@ class APIKeyCreateTokenParams(TypedDict, total=False): class ChatRole(TypedDict, total=False): + """The chat role""" + role_id: Optional[str] """The chat role ID""" diff --git a/src/asktable/types/tool_message.py b/src/asktable/types/tool_message.py index bbbea211..b2cd5d54 100644 --- a/src/asktable/types/tool_message.py +++ b/src/asktable/types/tool_message.py @@ -12,7 +12,7 @@ class ContentAttachment(BaseModel): info: object - type: str + type: Literal["data_json"] """The type of the attachment""" diff --git a/src/asktable/types/user_message.py b/src/asktable/types/user_message.py index c7ea626b..bb9e2fcd 100644 --- a/src/asktable/types/user_message.py +++ b/src/asktable/types/user_message.py @@ -12,7 +12,7 @@ class ContentAttachment(BaseModel): info: object - type: str + type: Literal["data_json"] """The type of the attachment""" diff --git a/tests/api_resources/test_bots.py b/tests/api_resources/test_bots.py index 09b2a320..abccfcf0 100644 --- a/tests/api_resources/test_bots.py +++ b/tests/api_resources/test_bots.py @@ -33,7 +33,6 @@ def test_method_create_with_all_params(self, client: Asktable) -> None: name="name", color_theme="default", debug=True, - extapi_ids=["string"], interaction_rules=[ { "enabled": True, @@ -132,7 +131,6 @@ def test_method_update_with_all_params(self, client: Asktable) -> None: color_theme="default", datasource_ids=["ds_sJAbnNOUzu3R4DdCCOwe"], debug=True, - extapi_ids=["string"], interaction_rules=[ { "enabled": True, @@ -320,7 +318,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncAsktable) name="name", color_theme="default", debug=True, - extapi_ids=["string"], interaction_rules=[ { "enabled": True, @@ -419,7 +416,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncAsktable) color_theme="default", datasource_ids=["ds_sJAbnNOUzu3R4DdCCOwe"], debug=True, - extapi_ids=["string"], interaction_rules=[ { "enabled": True, diff --git a/tests/api_resources/test_caches.py b/tests/api_resources/test_caches.py deleted file mode 100644 index 637c192e..00000000 --- a/tests/api_resources/test_caches.py +++ /dev/null @@ -1,98 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from asktable import Asktable, AsyncAsktable - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestCaches: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_delete(self, client: Asktable) -> None: - cach = client.caches.delete( - "cache_id", - ) - assert cach is None - - @parametrize - def test_raw_response_delete(self, client: Asktable) -> None: - response = client.caches.with_raw_response.delete( - "cache_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - cach = response.parse() - assert cach is None - - @parametrize - def test_streaming_response_delete(self, client: Asktable) -> None: - with client.caches.with_streaming_response.delete( - "cache_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - cach = response.parse() - assert cach is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_delete(self, client: Asktable) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `cache_id` but received ''"): - client.caches.with_raw_response.delete( - "", - ) - - -class TestAsyncCaches: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_delete(self, async_client: AsyncAsktable) -> None: - cach = await async_client.caches.delete( - "cache_id", - ) - assert cach is None - - @parametrize - async def test_raw_response_delete(self, async_client: AsyncAsktable) -> None: - response = await async_client.caches.with_raw_response.delete( - "cache_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - cach = await response.parse() - assert cach is None - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncAsktable) -> None: - async with async_client.caches.with_streaming_response.delete( - "cache_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - cach = await response.parse() - assert cach is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_delete(self, async_client: AsyncAsktable) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `cache_id` but received ''"): - await async_client.caches.with_raw_response.delete( - "", - ) diff --git a/tests/api_resources/test_sys.py b/tests/api_resources/test_sys.py deleted file mode 100644 index 67abf960..00000000 --- a/tests/api_resources/test_sys.py +++ /dev/null @@ -1,88 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from asktable import Asktable, AsyncAsktable -from tests.utils import assert_matches_type -from asktable.types import SyUpdateConfigResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestSys: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_update_config(self, client: Asktable) -> None: - sy = client.sys.update_config() - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - @parametrize - def test_method_update_config_with_all_params(self, client: Asktable) -> None: - sy = client.sys.update_config( - global_table_limit=0, - ) - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - @parametrize - def test_raw_response_update_config(self, client: Asktable) -> None: - response = client.sys.with_raw_response.update_config() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - sy = response.parse() - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - @parametrize - def test_streaming_response_update_config(self, client: Asktable) -> None: - with client.sys.with_streaming_response.update_config() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - sy = response.parse() - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncSys: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_update_config(self, async_client: AsyncAsktable) -> None: - sy = await async_client.sys.update_config() - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - @parametrize - async def test_method_update_config_with_all_params(self, async_client: AsyncAsktable) -> None: - sy = await async_client.sys.update_config( - global_table_limit=0, - ) - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - @parametrize - async def test_raw_response_update_config(self, async_client: AsyncAsktable) -> None: - response = await async_client.sys.with_raw_response.update_config() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - sy = await response.parse() - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - @parametrize - async def test_streaming_response_update_config(self, async_client: AsyncAsktable) -> None: - async with async_client.sys.with_streaming_response.update_config() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - sy = await response.parse() - assert_matches_type(SyUpdateConfigResponse, sy, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/test_client.py b/tests/test_client.py index 76c130aa..8bd5d5c3 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -6,13 +6,10 @@ import os import sys import json -import time import asyncio import inspect -import subprocess import tracemalloc from typing import Any, Union, cast -from textwrap import dedent from unittest import mock from typing_extensions import Literal @@ -23,14 +20,17 @@ from asktable import Asktable, AsyncAsktable, APIResponseValidationError from asktable._types import Omit +from asktable._utils import asyncify from asktable._models import BaseModel, FinalRequestOptions from asktable._exceptions import APIStatusError, APITimeoutError, APIResponseValidationError from asktable._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, + OtherPlatform, DefaultHttpxClient, DefaultAsyncHttpxClient, + get_platform, make_request_options, ) @@ -59,51 +59,49 @@ def _get_open_connections(client: Asktable | AsyncAsktable) -> int: class TestAsktable: - client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - @pytest.mark.respx(base_url=base_url) - def test_raw_response(self, respx_mock: MockRouter) -> None: + def test_raw_response(self, respx_mock: MockRouter, client: Asktable) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.post("/foo", cast_to=httpx.Response) + response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) - def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + def test_raw_response_for_binary(self, respx_mock: MockRouter, client: Asktable) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) - response = self.client.post("/foo", cast_to=httpx.Response) + response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} - def test_copy(self) -> None: - copied = self.client.copy() - assert id(copied) != id(self.client) + def test_copy(self, client: Asktable) -> None: + copied = client.copy() + assert id(copied) != id(client) - copied = self.client.copy(api_key="another My API Key") + copied = client.copy(api_key="another My API Key") assert copied.api_key == "another My API Key" - assert self.client.api_key == "My API Key" + assert client.api_key == "My API Key" - def test_copy_default_options(self) -> None: + def test_copy_default_options(self, client: Asktable) -> None: # options that have a default are overridden correctly - copied = self.client.copy(max_retries=7) + copied = client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 2 + assert client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout - assert isinstance(self.client.timeout, httpx.Timeout) - copied = self.client.copy(timeout=None) + assert isinstance(client.timeout, httpx.Timeout) + copied = client.copy(timeout=None) assert copied.timeout is None - assert isinstance(self.client.timeout, httpx.Timeout) + assert isinstance(client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: client = Asktable( @@ -138,6 +136,7 @@ def test_copy_default_headers(self) -> None: match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + client.close() def test_copy_default_query(self) -> None: client = Asktable( @@ -175,13 +174,15 @@ def test_copy_default_query(self) -> None: ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) - def test_copy_signature(self) -> None: + client.close() + + def test_copy_signature(self, client: Asktable) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. - self.client.__init__, # type: ignore[misc] + client.__init__, # type: ignore[misc] ) - copy_signature = inspect.signature(self.client.copy) + copy_signature = inspect.signature(client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): @@ -192,12 +193,12 @@ def test_copy_signature(self) -> None: assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self) -> None: + def test_copy_build_request(self, client: Asktable) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: - client = self.client.copy() - client._build_request(options) + client_copy = client.copy() + client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) @@ -254,14 +255,12 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic print(frame) raise AssertionError() - def test_request_timeout(self) -> None: - request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + def test_request_timeout(self, client: Asktable) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = self.client._build_request( - FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) - ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0))) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(100.0) @@ -274,6 +273,8 @@ def test_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) + client.close() + def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: @@ -285,6 +286,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) + client.close() + # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: client = Asktable( @@ -295,6 +298,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT + client.close() + # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = Asktable( @@ -305,6 +310,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default + client.close() + async def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): async with httpx.AsyncClient() as http_client: @@ -316,14 +323,14 @@ async def test_invalid_http_client(self) -> None: ) def test_default_headers_option(self) -> None: - client = Asktable( + test_client = Asktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = Asktable( + test_client2 = Asktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -332,10 +339,13 @@ def test_default_headers_option(self) -> None: "X-Stainless-Lang": "my-overriding-header", }, ) - request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" + test_client.close() + test_client2.close() + def test_default_query_option(self) -> None: client = Asktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} @@ -354,8 +364,10 @@ def test_default_query_option(self) -> None: url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - def test_request_extra_json(self) -> None: - request = self.client._build_request( + client.close() + + def test_request_extra_json(self, client: Asktable) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -366,7 +378,7 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -377,7 +389,7 @@ def test_request_extra_json(self) -> None: assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -388,8 +400,8 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} - def test_request_extra_headers(self) -> None: - request = self.client._build_request( + def test_request_extra_headers(self, client: Asktable) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -399,7 +411,7 @@ def test_request_extra_headers(self) -> None: assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash - request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", @@ -410,8 +422,8 @@ def test_request_extra_headers(self) -> None: ) assert request.headers.get("X-Bar") == "false" - def test_request_extra_query(self) -> None: - request = self.client._build_request( + def test_request_extra_query(self, client: Asktable) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -424,7 +436,7 @@ def test_request_extra_query(self) -> None: assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -438,7 +450,7 @@ def test_request_extra_query(self) -> None: assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -481,7 +493,7 @@ def test_multipart_repeating_array(self, client: Asktable) -> None: ] @pytest.mark.respx(base_url=base_url) - def test_basic_union_response(self, respx_mock: MockRouter) -> None: + def test_basic_union_response(self, respx_mock: MockRouter, client: Asktable) -> None: class Model1(BaseModel): name: str @@ -490,12 +502,12 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) - def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + def test_union_response_different_types(self, respx_mock: MockRouter, client: Asktable) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): @@ -506,18 +518,18 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter, client: Asktable) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ @@ -533,7 +545,7 @@ class Model(BaseModel): ) ) - response = self.client.get("/foo", cast_to=Model) + response = client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 @@ -545,6 +557,8 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" + client.close() + def test_base_url_env(self) -> None: with update_env(ASKTABLE_BASE_URL="http://localhost:5000/from/env"): client = Asktable(api_key=api_key, _strict_response_validation=True) @@ -572,6 +586,7 @@ def test_base_url_trailing_slash(self, client: Asktable) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + client.close() @pytest.mark.parametrize( "client", @@ -595,6 +610,7 @@ def test_base_url_no_trailing_slash(self, client: Asktable) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + client.close() @pytest.mark.parametrize( "client", @@ -618,35 +634,36 @@ def test_absolute_request_url(self, client: Asktable) -> None: ), ) assert request.url == "https://myapi.com/foo" + client.close() def test_copied_client_does_not_close_http(self) -> None: - client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - assert not client.is_closed() + test_client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) + assert not test_client.is_closed() - copied = client.copy() - assert copied is not client + copied = test_client.copy() + assert copied is not test_client del copied - assert not client.is_closed() + assert not test_client.is_closed() def test_client_context_manager(self) -> None: - client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - with client as c2: - assert c2 is client + test_client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) + with test_client as c2: + assert c2 is test_client assert not c2.is_closed() - assert not client.is_closed() - assert client.is_closed() + assert not test_client.is_closed() + assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) - def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + def test_client_response_validation_error(self, respx_mock: MockRouter, client: Asktable) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: - self.client.get("/foo", cast_to=Model) + client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) @@ -666,11 +683,14 @@ class Model(BaseModel): with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) - client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=False) + non_strict_client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=False) - response = client.get("/foo", cast_to=Model) + response = non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] + strict_client.close() + non_strict_client.close() + @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ @@ -693,9 +713,9 @@ class Model(BaseModel): ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = Asktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - + def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, client: Asktable + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) @@ -709,7 +729,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien with pytest.raises(APITimeoutError): client.datasources.with_streaming_response.create(engine="mysql").__enter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(client) == 0 @mock.patch("asktable._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -718,7 +738,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client with pytest.raises(APIStatusError): client.datasources.with_streaming_response.create(engine="mysql").__enter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("asktable._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @@ -824,83 +844,77 @@ def test_default_client_creation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - def test_follow_redirects(self, respx_mock: MockRouter) -> None: + def test_follow_redirects(self, respx_mock: MockRouter, client: Asktable) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - response = self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + response = client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) - def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + def test_follow_redirects_disabled(self, respx_mock: MockRouter, client: Asktable) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: - self.client.post( - "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response - ) + client.post("/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response) assert exc_info.value.response.status_code == 302 assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" class TestAsyncAsktable: - client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_raw_response(self, respx_mock: MockRouter) -> None: + async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncAsktable) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.post("/foo", cast_to=httpx.Response) + response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + async def test_raw_response_for_binary(self, respx_mock: MockRouter, async_client: AsyncAsktable) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) - response = await self.client.post("/foo", cast_to=httpx.Response) + response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} - def test_copy(self) -> None: - copied = self.client.copy() - assert id(copied) != id(self.client) + def test_copy(self, async_client: AsyncAsktable) -> None: + copied = async_client.copy() + assert id(copied) != id(async_client) - copied = self.client.copy(api_key="another My API Key") + copied = async_client.copy(api_key="another My API Key") assert copied.api_key == "another My API Key" - assert self.client.api_key == "My API Key" + assert async_client.api_key == "My API Key" - def test_copy_default_options(self) -> None: + def test_copy_default_options(self, async_client: AsyncAsktable) -> None: # options that have a default are overridden correctly - copied = self.client.copy(max_retries=7) + copied = async_client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 2 + assert async_client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout - assert isinstance(self.client.timeout, httpx.Timeout) - copied = self.client.copy(timeout=None) + assert isinstance(async_client.timeout, httpx.Timeout) + copied = async_client.copy(timeout=None) assert copied.timeout is None - assert isinstance(self.client.timeout, httpx.Timeout) + assert isinstance(async_client.timeout, httpx.Timeout) - def test_copy_default_headers(self) -> None: + async def test_copy_default_headers(self) -> None: client = AsyncAsktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) @@ -933,8 +947,9 @@ def test_copy_default_headers(self) -> None: match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + await client.close() - def test_copy_default_query(self) -> None: + async def test_copy_default_query(self) -> None: client = AsyncAsktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) @@ -970,13 +985,15 @@ def test_copy_default_query(self) -> None: ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) - def test_copy_signature(self) -> None: + await client.close() + + def test_copy_signature(self, async_client: AsyncAsktable) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. - self.client.__init__, # type: ignore[misc] + async_client.__init__, # type: ignore[misc] ) - copy_signature = inspect.signature(self.client.copy) + copy_signature = inspect.signature(async_client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): @@ -987,12 +1004,12 @@ def test_copy_signature(self) -> None: assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self) -> None: + def test_copy_build_request(self, async_client: AsyncAsktable) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: - client = self.client.copy() - client._build_request(options) + client_copy = async_client.copy() + client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) @@ -1049,12 +1066,12 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic print(frame) raise AssertionError() - async def test_request_timeout(self) -> None: - request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + async def test_request_timeout(self, async_client: AsyncAsktable) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = self.client._build_request( + request = async_client._build_request( FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) ) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore @@ -1069,6 +1086,8 @@ async def test_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) + await client.close() + async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: @@ -1080,6 +1099,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) + await client.close() + # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: client = AsyncAsktable( @@ -1090,6 +1111,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT + await client.close() + # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = AsyncAsktable( @@ -1100,6 +1123,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default + await client.close() + def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): with httpx.Client() as http_client: @@ -1110,15 +1135,15 @@ def test_invalid_http_client(self) -> None: http_client=cast(Any, http_client), ) - def test_default_headers_option(self) -> None: - client = AsyncAsktable( + async def test_default_headers_option(self) -> None: + test_client = AsyncAsktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = AsyncAsktable( + test_client2 = AsyncAsktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -1127,11 +1152,14 @@ def test_default_headers_option(self) -> None: "X-Stainless-Lang": "my-overriding-header", }, ) - request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" - def test_default_query_option(self) -> None: + await test_client.close() + await test_client2.close() + + async def test_default_query_option(self) -> None: client = AsyncAsktable( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) @@ -1149,8 +1177,10 @@ def test_default_query_option(self) -> None: url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - def test_request_extra_json(self) -> None: - request = self.client._build_request( + await client.close() + + def test_request_extra_json(self, client: Asktable) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1161,7 +1191,7 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1172,7 +1202,7 @@ def test_request_extra_json(self) -> None: assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1183,8 +1213,8 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} - def test_request_extra_headers(self) -> None: - request = self.client._build_request( + def test_request_extra_headers(self, client: Asktable) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1194,7 +1224,7 @@ def test_request_extra_headers(self) -> None: assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash - request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1205,8 +1235,8 @@ def test_request_extra_headers(self) -> None: ) assert request.headers.get("X-Bar") == "false" - def test_request_extra_query(self) -> None: - request = self.client._build_request( + def test_request_extra_query(self, client: Asktable) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1219,7 +1249,7 @@ def test_request_extra_query(self) -> None: assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1233,7 +1263,7 @@ def test_request_extra_query(self) -> None: assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1276,7 +1306,7 @@ def test_multipart_repeating_array(self, async_client: AsyncAsktable) -> None: ] @pytest.mark.respx(base_url=base_url) - async def test_basic_union_response(self, respx_mock: MockRouter) -> None: + async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncAsktable) -> None: class Model1(BaseModel): name: str @@ -1285,12 +1315,12 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) - async def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + async def test_union_response_different_types(self, respx_mock: MockRouter, async_client: AsyncAsktable) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): @@ -1301,18 +1331,20 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - async def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + async def test_non_application_json_content_type_for_json_data( + self, respx_mock: MockRouter, async_client: AsyncAsktable + ) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ @@ -1328,11 +1360,11 @@ class Model(BaseModel): ) ) - response = await self.client.get("/foo", cast_to=Model) + response = await async_client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 - def test_base_url_setter(self) -> None: + async def test_base_url_setter(self) -> None: client = AsyncAsktable( base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True ) @@ -1342,7 +1374,9 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" - def test_base_url_env(self) -> None: + await client.close() + + async def test_base_url_env(self) -> None: with update_env(ASKTABLE_BASE_URL="http://localhost:5000/from/env"): client = AsyncAsktable(api_key=api_key, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @@ -1362,7 +1396,7 @@ def test_base_url_env(self) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_trailing_slash(self, client: AsyncAsktable) -> None: + async def test_base_url_trailing_slash(self, client: AsyncAsktable) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1371,6 +1405,7 @@ def test_base_url_trailing_slash(self, client: AsyncAsktable) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + await client.close() @pytest.mark.parametrize( "client", @@ -1387,7 +1422,7 @@ def test_base_url_trailing_slash(self, client: AsyncAsktable) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_no_trailing_slash(self, client: AsyncAsktable) -> None: + async def test_base_url_no_trailing_slash(self, client: AsyncAsktable) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1396,6 +1431,7 @@ def test_base_url_no_trailing_slash(self, client: AsyncAsktable) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + await client.close() @pytest.mark.parametrize( "client", @@ -1412,7 +1448,7 @@ def test_base_url_no_trailing_slash(self, client: AsyncAsktable) -> None: ], ids=["standard", "custom http client"], ) - def test_absolute_request_url(self, client: AsyncAsktable) -> None: + async def test_absolute_request_url(self, client: AsyncAsktable) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1421,37 +1457,37 @@ def test_absolute_request_url(self, client: AsyncAsktable) -> None: ), ) assert request.url == "https://myapi.com/foo" + await client.close() async def test_copied_client_does_not_close_http(self) -> None: - client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - assert not client.is_closed() + test_client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) + assert not test_client.is_closed() - copied = client.copy() - assert copied is not client + copied = test_client.copy() + assert copied is not test_client del copied await asyncio.sleep(0.2) - assert not client.is_closed() + assert not test_client.is_closed() async def test_client_context_manager(self) -> None: - client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - async with client as c2: - assert c2 is client + test_client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) + async with test_client as c2: + assert c2 is test_client assert not c2.is_closed() - assert not client.is_closed() - assert client.is_closed() + assert not test_client.is_closed() + assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + async def test_client_response_validation_error(self, respx_mock: MockRouter, async_client: AsyncAsktable) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: - await self.client.get("/foo", cast_to=Model) + await async_client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) @@ -1462,7 +1498,6 @@ async def test_client_max_retries_validation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: class Model(BaseModel): name: str @@ -1474,11 +1509,14 @@ class Model(BaseModel): with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) - client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=False) + non_strict_client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=False) - response = await client.get("/foo", cast_to=Model) + response = await non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] + await strict_client.close() + await non_strict_client.close() + @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ @@ -1501,13 +1539,12 @@ class Model(BaseModel): ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - @pytest.mark.asyncio - async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = AsyncAsktable(base_url=base_url, api_key=api_key, _strict_response_validation=True) - + async def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncAsktable + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) - calculated = client._calculate_retry_timeout(remaining_retries, options, headers) + calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("asktable._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @@ -1520,7 +1557,7 @@ async def test_retrying_timeout_errors_doesnt_leak( with pytest.raises(APITimeoutError): await async_client.datasources.with_streaming_response.create(engine="mysql").__aenter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(async_client) == 0 @mock.patch("asktable._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -1531,12 +1568,11 @@ async def test_retrying_status_errors_doesnt_leak( with pytest.raises(APIStatusError): await async_client.datasources.with_streaming_response.create(engine="mysql").__aenter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(async_client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("asktable._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio @pytest.mark.parametrize("failure_mode", ["status", "exception"]) async def test_retries_taken( self, @@ -1568,7 +1604,6 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("asktable._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_omit_retry_count_header( self, async_client: AsyncAsktable, failures_before_success: int, respx_mock: MockRouter ) -> None: @@ -1594,7 +1629,6 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("asktable._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_overwrite_retry_count_header( self, async_client: AsyncAsktable, failures_before_success: int, respx_mock: MockRouter ) -> None: @@ -1617,50 +1651,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert response.http_request.headers.get("x-stainless-retry-count") == "42" - def test_get_platform(self) -> None: - # A previous implementation of asyncify could leave threads unterminated when - # used with nest_asyncio. - # - # Since nest_asyncio.apply() is global and cannot be un-applied, this - # test is run in a separate process to avoid affecting other tests. - test_code = dedent(""" - import asyncio - import nest_asyncio - import threading - - from asktable._utils import asyncify - from asktable._base_client import get_platform - - async def test_main() -> None: - result = await asyncify(get_platform)() - print(result) - for thread in threading.enumerate(): - print(thread.name) - - nest_asyncio.apply() - asyncio.run(test_main()) - """) - with subprocess.Popen( - [sys.executable, "-c", test_code], - text=True, - ) as process: - timeout = 10 # seconds - - start_time = time.monotonic() - while True: - return_code = process.poll() - if return_code is not None: - if return_code != 0: - raise AssertionError("calling get_platform using asyncify resulted in a non-zero exit code") - - # success - break - - if time.monotonic() - start_time > timeout: - process.kill() - raise AssertionError("calling get_platform using asyncify resulted in a hung process") - - time.sleep(0.1) + async def test_get_platform(self) -> None: + platform = await asyncify(get_platform)() + assert isinstance(platform, (str, OtherPlatform)) async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly @@ -1685,26 +1678,26 @@ async def test_default_client_creation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects(self, respx_mock: MockRouter) -> None: + async def test_follow_redirects(self, respx_mock: MockRouter, async_client: AsyncAsktable) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - response = await self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + response = await async_client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + async def test_follow_redirects_disabled(self, respx_mock: MockRouter, async_client: AsyncAsktable) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: - await self.client.post( + await async_client.post( "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response ) diff --git a/tests/test_models.py b/tests/test_models.py index 7864490f..e9493521 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,5 +1,5 @@ import json -from typing import Any, Dict, List, Union, Optional, cast +from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast from datetime import datetime, timezone from typing_extensions import Literal, Annotated, TypeAliasType @@ -8,8 +8,8 @@ from pydantic import Field from asktable._utils import PropertyInfo -from asktable._compat import PYDANTIC_V2, parse_obj, model_dump, model_json -from asktable._models import BaseModel, construct_type +from asktable._compat import PYDANTIC_V1, parse_obj, model_dump, model_json +from asktable._models import DISCRIMINATOR_CACHE, BaseModel, construct_type class BasicModel(BaseModel): @@ -294,12 +294,12 @@ class Model(BaseModel): assert cast(bool, m.foo) is True m = Model.construct(foo={"name": 3}) - if PYDANTIC_V2: - assert isinstance(m.foo, Submodel1) - assert m.foo.name == 3 # type: ignore - else: + if PYDANTIC_V1: assert isinstance(m.foo, Submodel2) assert m.foo.name == "3" + else: + assert isinstance(m.foo, Submodel1) + assert m.foo.name == 3 # type: ignore def test_list_of_unions() -> None: @@ -426,10 +426,10 @@ class Model(BaseModel): expected = datetime(2019, 12, 27, 18, 11, 19, 117000, tzinfo=timezone.utc) - if PYDANTIC_V2: - expected_json = '{"created_at":"2019-12-27T18:11:19.117000Z"}' - else: + if PYDANTIC_V1: expected_json = '{"created_at": "2019-12-27T18:11:19.117000+00:00"}' + else: + expected_json = '{"created_at":"2019-12-27T18:11:19.117000Z"}' model = Model.construct(created_at="2019-12-27T18:11:19.117Z") assert model.created_at == expected @@ -531,7 +531,7 @@ class Model2(BaseModel): assert m4.to_dict(mode="python") == {"created_at": datetime.fromisoformat(time_str)} assert m4.to_dict(mode="json") == {"created_at": time_str} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.to_dict(warnings=False) @@ -556,7 +556,7 @@ class Model(BaseModel): assert m3.model_dump() == {"foo": None} assert m3.model_dump(exclude_none=True) == {} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): m.model_dump(round_trip=True) @@ -580,10 +580,10 @@ class Model(BaseModel): assert json.loads(m.to_json()) == {"FOO": "hello"} assert json.loads(m.to_json(use_api_names=False)) == {"foo": "hello"} - if PYDANTIC_V2: - assert m.to_json(indent=None) == '{"FOO":"hello"}' - else: + if PYDANTIC_V1: assert m.to_json(indent=None) == '{"FOO": "hello"}' + else: + assert m.to_json(indent=None) == '{"FOO":"hello"}' m2 = Model() assert json.loads(m2.to_json()) == {} @@ -595,7 +595,7 @@ class Model(BaseModel): assert json.loads(m3.to_json()) == {"FOO": None} assert json.loads(m3.to_json(exclude_none=True)) == {} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.to_json(warnings=False) @@ -622,7 +622,7 @@ class Model(BaseModel): assert json.loads(m3.model_dump_json()) == {"foo": None} assert json.loads(m3.model_dump_json(exclude_none=True)) == {} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): m.model_dump_json(round_trip=True) @@ -679,12 +679,12 @@ class B(BaseModel): ) assert isinstance(m, A) assert m.type == "a" - if PYDANTIC_V2: - assert m.data == 100 # type: ignore[comparison-overlap] - else: + if PYDANTIC_V1: # pydantic v1 automatically converts inputs to strings # if the expected type is a str assert m.data == "100" + else: + assert m.data == 100 # type: ignore[comparison-overlap] def test_discriminated_unions_unknown_variant() -> None: @@ -768,12 +768,12 @@ class B(BaseModel): ) assert isinstance(m, A) assert m.foo_type == "a" - if PYDANTIC_V2: - assert m.data == 100 # type: ignore[comparison-overlap] - else: + if PYDANTIC_V1: # pydantic v1 automatically converts inputs to strings # if the expected type is a str assert m.data == "100" + else: + assert m.data == 100 # type: ignore[comparison-overlap] def test_discriminated_unions_overlapping_discriminators_invalid_data() -> None: @@ -809,7 +809,7 @@ class B(BaseModel): UnionType = cast(Any, Union[A, B]) - assert not hasattr(UnionType, "__discriminator__") + assert not DISCRIMINATOR_CACHE.get(UnionType) m = construct_type( value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) @@ -818,7 +818,7 @@ class B(BaseModel): assert m.type == "b" assert m.data == "foo" # type: ignore[comparison-overlap] - discriminator = UnionType.__discriminator__ + discriminator = DISCRIMINATOR_CACHE.get(UnionType) assert discriminator is not None m = construct_type( @@ -830,10 +830,10 @@ class B(BaseModel): # if the discriminator details object stays the same between invocations then # we hit the cache - assert UnionType.__discriminator__ is discriminator + assert DISCRIMINATOR_CACHE.get(UnionType) is discriminator -@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +@pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") def test_type_alias_type() -> None: Alias = TypeAliasType("Alias", str) # pyright: ignore @@ -849,7 +849,7 @@ class Model(BaseModel): assert m.union == "bar" -@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +@pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") def test_field_named_cls() -> None: class Model(BaseModel): cls: str @@ -934,3 +934,30 @@ class Type2(BaseModel): ) assert isinstance(model, Type1) assert isinstance(model.value, InnerType2) + + +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2 for now") +def test_extra_properties() -> None: + class Item(BaseModel): + prop: int + + class Model(BaseModel): + __pydantic_extra__: Dict[str, Item] = Field(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + other: str + + if TYPE_CHECKING: + + def __getattr__(self, attr: str) -> Item: ... + + model = construct_type( + type_=Model, + value={ + "a": {"prop": 1}, + "other": "foo", + }, + ) + assert isinstance(model, Model) + assert model.a.prop == 1 + assert isinstance(model.a, Item) + assert model.other == "foo" diff --git a/tests/test_transform.py b/tests/test_transform.py index 33ea35d8..35192dc9 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,14 +8,14 @@ import pytest -from asktable._types import NOT_GIVEN, Base64FileInput +from asktable._types import Base64FileInput, omit, not_given from asktable._utils import ( PropertyInfo, transform as _transform, parse_datetime, async_transform as _async_transform, ) -from asktable._compat import PYDANTIC_V2 +from asktable._compat import PYDANTIC_V1 from asktable._models import BaseModel _T = TypeVar("_T") @@ -189,7 +189,7 @@ class DateModel(BaseModel): @pytest.mark.asyncio async def test_iso8601_format(use_async: bool) -> None: dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") - tz = "Z" if PYDANTIC_V2 else "+00:00" + tz = "+00:00" if PYDANTIC_V1 else "Z" assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692" + tz} # type: ignore[comparison-overlap] @@ -297,11 +297,11 @@ async def test_pydantic_unknown_field(use_async: bool) -> None: @pytest.mark.asyncio async def test_pydantic_mismatched_types(use_async: bool) -> None: model = MyModel.construct(foo=True) - if PYDANTIC_V2: + if PYDANTIC_V1: + params = await transform(model, Any, use_async) + else: with pytest.warns(UserWarning): params = await transform(model, Any, use_async) - else: - params = await transform(model, Any, use_async) assert cast(Any, params) == {"foo": True} @@ -309,11 +309,11 @@ async def test_pydantic_mismatched_types(use_async: bool) -> None: @pytest.mark.asyncio async def test_pydantic_mismatched_object_type(use_async: bool) -> None: model = MyModel.construct(foo=MyModel.construct(hello="world")) - if PYDANTIC_V2: + if PYDANTIC_V1: + params = await transform(model, Any, use_async) + else: with pytest.warns(UserWarning): params = await transform(model, Any, use_async) - else: - params = await transform(model, Any, use_async) assert cast(Any, params) == {"foo": {"hello": "world"}} @@ -450,4 +450,11 @@ async def test_transform_skipping(use_async: bool) -> None: @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) == {} + assert await transform({"foo_bar": not_given}, Foo1, use_async) == {} + + +@parametrize +@pytest.mark.asyncio +async def test_strips_omit(use_async: bool) -> None: + assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} + assert await transform({"foo_bar": omit}, Foo1, use_async) == {} diff --git a/tests/test_utils/test_datetime_parse.py b/tests/test_utils/test_datetime_parse.py new file mode 100644 index 00000000..e710e2d2 --- /dev/null +++ b/tests/test_utils/test_datetime_parse.py @@ -0,0 +1,110 @@ +""" +Copied from https://github.com/pydantic/pydantic/blob/v1.10.22/tests/test_datetime_parse.py +with modifications so it works without pydantic v1 imports. +""" + +from typing import Type, Union +from datetime import date, datetime, timezone, timedelta + +import pytest + +from asktable._utils import parse_date, parse_datetime + + +def create_tz(minutes: int) -> timezone: + return timezone(timedelta(minutes=minutes)) + + +@pytest.mark.parametrize( + "value,result", + [ + # Valid inputs + ("1494012444.883309", date(2017, 5, 5)), + (b"1494012444.883309", date(2017, 5, 5)), + (1_494_012_444.883_309, date(2017, 5, 5)), + ("1494012444", date(2017, 5, 5)), + (1_494_012_444, date(2017, 5, 5)), + (0, date(1970, 1, 1)), + ("2012-04-23", date(2012, 4, 23)), + (b"2012-04-23", date(2012, 4, 23)), + ("2012-4-9", date(2012, 4, 9)), + (date(2012, 4, 9), date(2012, 4, 9)), + (datetime(2012, 4, 9, 12, 15), date(2012, 4, 9)), + # Invalid inputs + ("x20120423", ValueError), + ("2012-04-56", ValueError), + (19_999_999_999, date(2603, 10, 11)), # just before watershed + (20_000_000_001, date(1970, 8, 20)), # just after watershed + (1_549_316_052, date(2019, 2, 4)), # nowish in s + (1_549_316_052_104, date(2019, 2, 4)), # nowish in ms + (1_549_316_052_104_324, date(2019, 2, 4)), # nowish in μs + (1_549_316_052_104_324_096, date(2019, 2, 4)), # nowish in ns + ("infinity", date(9999, 12, 31)), + ("inf", date(9999, 12, 31)), + (float("inf"), date(9999, 12, 31)), + ("infinity ", date(9999, 12, 31)), + (int("1" + "0" * 100), date(9999, 12, 31)), + (1e1000, date(9999, 12, 31)), + ("-infinity", date(1, 1, 1)), + ("-inf", date(1, 1, 1)), + ("nan", ValueError), + ], +) +def test_date_parsing(value: Union[str, bytes, int, float], result: Union[date, Type[Exception]]) -> None: + if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] + with pytest.raises(result): + parse_date(value) + else: + assert parse_date(value) == result + + +@pytest.mark.parametrize( + "value,result", + [ + # Valid inputs + # values in seconds + ("1494012444.883309", datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), + (1_494_012_444.883_309, datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), + ("1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + (b"1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + (1_494_012_444, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + # values in ms + ("1494012444000.883309", datetime(2017, 5, 5, 19, 27, 24, 883, tzinfo=timezone.utc)), + ("-1494012444000.883309", datetime(1922, 8, 29, 4, 32, 35, 999117, tzinfo=timezone.utc)), + (1_494_012_444_000, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + ("2012-04-23T09:15:00", datetime(2012, 4, 23, 9, 15)), + ("2012-4-9 4:8:16", datetime(2012, 4, 9, 4, 8, 16)), + ("2012-04-23T09:15:00Z", datetime(2012, 4, 23, 9, 15, 0, 0, timezone.utc)), + ("2012-4-9 4:8:16-0320", datetime(2012, 4, 9, 4, 8, 16, 0, create_tz(-200))), + ("2012-04-23T10:20:30.400+02:30", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(150))), + ("2012-04-23T10:20:30.400+02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(120))), + ("2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), + (b"2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), + (datetime(2017, 5, 5), datetime(2017, 5, 5)), + (0, datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc)), + # Invalid inputs + ("x20120423091500", ValueError), + ("2012-04-56T09:15:90", ValueError), + ("2012-04-23T11:05:00-25:00", ValueError), + (19_999_999_999, datetime(2603, 10, 11, 11, 33, 19, tzinfo=timezone.utc)), # just before watershed + (20_000_000_001, datetime(1970, 8, 20, 11, 33, 20, 1000, tzinfo=timezone.utc)), # just after watershed + (1_549_316_052, datetime(2019, 2, 4, 21, 34, 12, 0, tzinfo=timezone.utc)), # nowish in s + (1_549_316_052_104, datetime(2019, 2, 4, 21, 34, 12, 104_000, tzinfo=timezone.utc)), # nowish in ms + (1_549_316_052_104_324, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in μs + (1_549_316_052_104_324_096, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in ns + ("infinity", datetime(9999, 12, 31, 23, 59, 59, 999999)), + ("inf", datetime(9999, 12, 31, 23, 59, 59, 999999)), + ("inf ", datetime(9999, 12, 31, 23, 59, 59, 999999)), + (1e50, datetime(9999, 12, 31, 23, 59, 59, 999999)), + (float("inf"), datetime(9999, 12, 31, 23, 59, 59, 999999)), + ("-infinity", datetime(1, 1, 1, 0, 0)), + ("-inf", datetime(1, 1, 1, 0, 0)), + ("nan", ValueError), + ], +) +def test_datetime_parsing(value: Union[str, bytes, int, float], result: Union[datetime, Type[Exception]]) -> None: + if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] + with pytest.raises(result): + parse_datetime(value) + else: + assert parse_datetime(value) == result diff --git a/tests/utils.py b/tests/utils.py index 7497343a..b84eaf23 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -4,7 +4,7 @@ import inspect import traceback import contextlib -from typing import Any, TypeVar, Iterator, cast +from typing import Any, TypeVar, Iterator, Sequence, cast from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type @@ -15,10 +15,11 @@ is_list_type, is_union_type, extract_type_arg, + is_sequence_type, is_annotated_type, is_type_alias_type, ) -from asktable._compat import PYDANTIC_V2, field_outer_type, get_model_fields +from asktable._compat import PYDANTIC_V1, field_outer_type, get_model_fields from asktable._models import BaseModel BaseModelT = TypeVar("BaseModelT", bound=BaseModel) @@ -27,12 +28,12 @@ def assert_matches_model(model: type[BaseModelT], value: BaseModelT, *, path: list[str]) -> bool: for name, field in get_model_fields(model).items(): field_value = getattr(value, name) - if PYDANTIC_V2: - allow_none = False - else: + if PYDANTIC_V1: # in v1 nullability was structured differently # https://docs.pydantic.dev/2.0/migration/#required-optional-and-nullable-fields allow_none = getattr(field, "allow_none", False) + else: + allow_none = False assert_matches_type( field_outer_type(field), @@ -71,6 +72,13 @@ def assert_matches_type( if is_list_type(type_): return _assert_list_type(type_, value) + if is_sequence_type(type_): + assert isinstance(value, Sequence) + inner_type = get_args(type_)[0] + for entry in value: # type: ignore + assert_type(inner_type, entry) # type: ignore + return + if origin == str: assert isinstance(value, str) elif origin == int: