diff --git a/.fern/metadata.json b/.fern/metadata.json index c63cedf0..85ebee93 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -1,12 +1,12 @@ { "cliVersion": "4.71.5", "generatorName": "fernapi/fern-python-sdk", - "generatorVersion": "4.54.3", + "generatorVersion": "5.5.0", "generatorConfig": { "package_name": "truefoundry_sdk", + "use_request_defaults": "all", "pydantic_config": { "enum_type": "forward_compatible_python_enums", - "use_provided_defaults": true, "frozen": false }, "client": { @@ -22,6 +22,6 @@ "numpydoc": ">=1.7.0,<2.0.0" } }, - "originGitCommit": "9032a7936ba762178d26cc94a7500437e3d70f27", + "originGitCommit": "888851918afe3ee9c6c9292e9efabdd2941d3239", "sdkVersion": "0.0.0" } \ No newline at end of file diff --git a/README.md b/README.md index 433cba06..e67ed25c 100644 --- a/README.md +++ b/README.md @@ -42,16 +42,14 @@ Instantiate and use the client with the following: ```python from truefoundry_sdk import TrueFoundry -from truefoundry_sdk.applications import ( - ApplicationsListRequestDeviceTypeFilter, - ApplicationsListRequestLifecycleStage, -) +from truefoundry_sdk.applications import ApplicationsListRequestDeviceTypeFilter, ApplicationsListRequestLifecycleStage client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.applications.list( + +client.applications.list( limit=10, offset=0, application_id="applicationId", @@ -70,11 +68,6 @@ response = client.applications.list( lifecycle_stage=ApplicationsListRequestLifecycleStage.ACTIVE, is_recommendation_present_and_visible=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ``` ## Async Client @@ -83,21 +76,18 @@ The SDK also exports an `async` client so that you can make non-blocking calls t ```python import asyncio +from truefoundry_sdk.applications import ApplicationsListRequestDeviceTypeFilter, ApplicationsListRequestLifecycleStage from truefoundry_sdk import AsyncTrueFoundry -from truefoundry_sdk.applications import ( - ApplicationsListRequestDeviceTypeFilter, - ApplicationsListRequestLifecycleStage, -) client = AsyncTrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) async def main() -> None: - response = await client.applications.list( + await client.applications.list( limit=10, offset=0, application_id="applicationId", @@ -116,12 +106,6 @@ async def main() -> None: lifecycle_stage=ApplicationsListRequestLifecycleStage.ACTIVE, is_recommendation_present_and_visible=True, ) - async for item in response: - yield item - - # alternatively, you can paginate page-by-page - async for page in response.iter_pages(): - yield page asyncio.run(main()) @@ -148,27 +132,37 @@ Paginated requests will return a `SyncPager` or `AsyncPager`, which can be used ```python from truefoundry_sdk import TrueFoundry +from truefoundry_sdk.applications import ApplicationsListRequestDeviceTypeFilter, ApplicationsListRequestLifecycleStage client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.users.list( + +client.applications.list( limit=10, offset=0, - query="query", - show_invalid_users=True, + application_id="applicationId", + workspace_id="workspaceId", + application_name="applicationName", + fqn="fqn", + workspace_fqn="workspaceFqn", + application_type="applicationType", + name_search_query="nameSearchQuery", + environment_id="environmentId", + cluster_id="clusterId", + application_set_id="applicationSetId", + paused=True, + device_type_filter=ApplicationsListRequestDeviceTypeFilter.CPU, + last_deployed_by_subjects="lastDeployedBySubjects", + lifecycle_stage=ApplicationsListRequestLifecycleStage.ACTIVE, + is_recommendation_present_and_visible=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ``` ```python # You can also iterate through pages and access the typed response per page -pager = client.users.list(...) +pager = client.applications.list(...) for page in pager.iter_pages(): print(page.response) # access the typed response for each page for item in page: @@ -188,11 +182,7 @@ from truefoundry_sdk import TrueFoundry client = TrueFoundry( ..., ) -response = client.applications.with_raw_response.list(...) -print(response.headers) # access the response headers -print(response.status_code) # access the response status code -print(response.data) # access the underlying object -pager = client.users.list(...) +pager = client.applications.list(...) print(pager.response) # access the typed response for the first page for item in pager: print(item) # access the underlying object(s) @@ -227,14 +217,9 @@ client.applications.list(..., request_options={ The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level. ```python - from truefoundry_sdk import TrueFoundry -client = TrueFoundry( - ..., - timeout=20.0, -) - +client = TrueFoundry(..., timeout=20.0) # Override timeout for a specific method client.applications.list(..., request_options={ diff --git a/poetry.lock b/poetry.lock index 0fb0f8c2..a5ee6e32 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,142 @@ # This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +[[package]] +name = "aiohappyeyeballs" +version = "2.4.4" +description = "Happy Eyeballs for asyncio" +optional = true +python-versions = ">=3.8" +files = [ + {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, + {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, +] + +[[package]] +name = "aiohttp" +version = "3.10.11" +description = "Async http client/server framework (asyncio)" +optional = true +python-versions = ">=3.8" +files = [ + {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"}, + {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"}, + {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"}, + {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"}, + {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"}, + {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"}, + {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"}, + {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"}, + {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"}, + {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"}, + {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"}, + {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"}, + {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"}, + {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"}, +] + +[package.dependencies] +aiohappyeyeballs = ">=2.3.0" +aiosignal = ">=1.1.2" +async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.12.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = true +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + [[package]] name = "alabaster" version = "0.7.13" @@ -73,6 +210,36 @@ files = [ astroid = ["astroid (>=2,<5)"] test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"] +[[package]] +name = "async-timeout" +version = "5.0.1" +description = "Timeout context manager for asyncio programs" +optional = true +python-versions = ">=3.8" +files = [ + {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, + {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, +] + +[[package]] +name = "attrs" +version = "25.3.0" +description = "Classes Without Boilerplate" +optional = true +python-versions = ">=3.8" +files = [ + {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, + {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, +] + +[package.extras] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] + [[package]] name = "babel" version = "2.18.0" @@ -328,6 +495,107 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] +[[package]] +name = "frozenlist" +version = "1.5.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = true +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"}, + {file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"}, + {file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"}, + {file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"}, + {file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"}, + {file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"}, + {file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"}, + {file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"}, + {file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"}, + {file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"}, + {file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"}, + {file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"}, + {file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"}, + {file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"}, + {file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"}, +] + [[package]] name = "h11" version = "0.16.0" @@ -384,6 +652,21 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "httpx-aiohttp" +version = "0.1.8" +description = "Aiohttp transport for HTTPX" +optional = true +python-versions = ">=3.8" +files = [ + {file = "httpx_aiohttp-0.1.8-py3-none-any.whl", hash = "sha256:b7bd958d1331f3759a38a0ba22ad29832cb63ca69498c17735228055bf78fa7e"}, + {file = "httpx_aiohttp-0.1.8.tar.gz", hash = "sha256:756c5e74cdb568c3248ba63fe82bfe8bbe64b928728720f7eaac64b3cf46f308"}, +] + +[package.dependencies] +aiohttp = ">=3.10.0,<4" +httpx = ">=0.27.0" + [[package]] name = "idna" version = "3.11" @@ -601,6 +884,110 @@ files = [ [package.dependencies] traitlets = "*" +[[package]] +name = "multidict" +version = "6.1.0" +description = "multidict implementation" +optional = true +python-versions = ">=3.8" +files = [ + {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, + {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, + {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, + {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, + {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, + {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, + {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, + {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, + {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, + {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, + {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, + {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, + {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, + {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, + {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, + {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, + {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, + {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, + {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, + {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, + {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, + {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, + {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, + {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, + {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, + {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, + {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, + {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, + {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, + {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, + {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, + {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} + [[package]] name = "mypy" version = "1.13.0" @@ -766,6 +1153,113 @@ files = [ [package.dependencies] wcwidth = "*" +[[package]] +name = "propcache" +version = "0.2.0" +description = "Accelerated property cache" +optional = true +python-versions = ">=3.8" +files = [ + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, + {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, + {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, + {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, + {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, + {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, + {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, + {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, + {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, + {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, + {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, + {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, + {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, + {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, + {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, +] + [[package]] name = "ptyprocess" version = "0.7.0" @@ -1381,6 +1875,118 @@ files = [ {file = "wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159"}, ] +[[package]] +name = "yarl" +version = "1.15.2" +description = "Yet another URL library" +optional = true +python-versions = ">=3.8" +files = [ + {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e4ee8b8639070ff246ad3649294336b06db37a94bdea0d09ea491603e0be73b8"}, + {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7cf963a357c5f00cb55b1955df8bbe68d2f2f65de065160a1c26b85a1e44172"}, + {file = "yarl-1.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:43ebdcc120e2ca679dba01a779333a8ea76b50547b55e812b8b92818d604662c"}, + {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3433da95b51a75692dcf6cc8117a31410447c75a9a8187888f02ad45c0a86c50"}, + {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38d0124fa992dbacd0c48b1b755d3ee0a9f924f427f95b0ef376556a24debf01"}, + {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ded1b1803151dd0f20a8945508786d57c2f97a50289b16f2629f85433e546d47"}, + {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace4cad790f3bf872c082366c9edd7f8f8f77afe3992b134cfc810332206884f"}, + {file = "yarl-1.15.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c77494a2f2282d9bbbbcab7c227a4d1b4bb829875c96251f66fb5f3bae4fb053"}, + {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b7f227ca6db5a9fda0a2b935a2ea34a7267589ffc63c8045f0e4edb8d8dcf956"}, + {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:31561a5b4d8dbef1559b3600b045607cf804bae040f64b5f5bca77da38084a8a"}, + {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3e52474256a7db9dcf3c5f4ca0b300fdea6c21cca0148c8891d03a025649d935"}, + {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0e1af74a9529a1137c67c887ed9cde62cff53aa4d84a3adbec329f9ec47a3936"}, + {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:15c87339490100c63472a76d87fe7097a0835c705eb5ae79fd96e343473629ed"}, + {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:74abb8709ea54cc483c4fb57fb17bb66f8e0f04438cff6ded322074dbd17c7ec"}, + {file = "yarl-1.15.2-cp310-cp310-win32.whl", hash = "sha256:ffd591e22b22f9cb48e472529db6a47203c41c2c5911ff0a52e85723196c0d75"}, + {file = "yarl-1.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:1695497bb2a02a6de60064c9f077a4ae9c25c73624e0d43e3aa9d16d983073c2"}, + {file = "yarl-1.15.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9fcda20b2de7042cc35cf911702fa3d8311bd40055a14446c1e62403684afdc5"}, + {file = "yarl-1.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0545de8c688fbbf3088f9e8b801157923be4bf8e7b03e97c2ecd4dfa39e48e0e"}, + {file = "yarl-1.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbda058a9a68bec347962595f50546a8a4a34fd7b0654a7b9697917dc2bf810d"}, + {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ac2bc069f4a458634c26b101c2341b18da85cb96afe0015990507efec2e417"}, + {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd126498171f752dd85737ab1544329a4520c53eed3997f9b08aefbafb1cc53b"}, + {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3db817b4e95eb05c362e3b45dafe7144b18603e1211f4a5b36eb9522ecc62bcf"}, + {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:076b1ed2ac819933895b1a000904f62d615fe4533a5cf3e052ff9a1da560575c"}, + {file = "yarl-1.15.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8cfd847e6b9ecf9f2f2531c8427035f291ec286c0a4944b0a9fce58c6446046"}, + {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:32b66be100ac5739065496c74c4b7f3015cef792c3174982809274d7e51b3e04"}, + {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:34a2d76a1984cac04ff8b1bfc939ec9dc0914821264d4a9c8fd0ed6aa8d4cfd2"}, + {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0afad2cd484908f472c8fe2e8ef499facee54a0a6978be0e0cff67b1254fd747"}, + {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c68e820879ff39992c7f148113b46efcd6ec765a4865581f2902b3c43a5f4bbb"}, + {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:98f68df80ec6ca3015186b2677c208c096d646ef37bbf8b49764ab4a38183931"}, + {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c56ec1eacd0a5d35b8a29f468659c47f4fe61b2cab948ca756c39b7617f0aa5"}, + {file = "yarl-1.15.2-cp311-cp311-win32.whl", hash = "sha256:eedc3f247ee7b3808ea07205f3e7d7879bc19ad3e6222195cd5fbf9988853e4d"}, + {file = "yarl-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:0ccaa1bc98751fbfcf53dc8dfdb90d96e98838010fc254180dd6707a6e8bb179"}, + {file = "yarl-1.15.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:82d5161e8cb8f36ec778fd7ac4d740415d84030f5b9ef8fe4da54784a1f46c94"}, + {file = "yarl-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fa2bea05ff0a8fb4d8124498e00e02398f06d23cdadd0fe027d84a3f7afde31e"}, + {file = "yarl-1.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99e12d2bf587b44deb74e0d6170fec37adb489964dbca656ec41a7cd8f2ff178"}, + {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:243fbbbf003754fe41b5bdf10ce1e7f80bcc70732b5b54222c124d6b4c2ab31c"}, + {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:856b7f1a7b98a8c31823285786bd566cf06226ac4f38b3ef462f593c608a9bd6"}, + {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:553dad9af802a9ad1a6525e7528152a015b85fb8dbf764ebfc755c695f488367"}, + {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30c3ff305f6e06650a761c4393666f77384f1cc6c5c0251965d6bfa5fbc88f7f"}, + {file = "yarl-1.15.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:353665775be69bbfc6d54c8d134bfc533e332149faeddd631b0bc79df0897f46"}, + {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f4fe99ce44128c71233d0d72152db31ca119711dfc5f2c82385ad611d8d7f897"}, + {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9c1e3ff4b89cdd2e1a24c214f141e848b9e0451f08d7d4963cb4108d4d798f1f"}, + {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:711bdfae4e699a6d4f371137cbe9e740dc958530cb920eb6f43ff9551e17cfbc"}, + {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4388c72174868884f76affcdd3656544c426407e0043c89b684d22fb265e04a5"}, + {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f0e1844ad47c7bd5d6fa784f1d4accc5f4168b48999303a868fe0f8597bde715"}, + {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a5cafb02cf097a82d74403f7e0b6b9df3ffbfe8edf9415ea816314711764a27b"}, + {file = "yarl-1.15.2-cp312-cp312-win32.whl", hash = "sha256:156ececdf636143f508770bf8a3a0498de64da5abd890c7dbb42ca9e3b6c05b8"}, + {file = "yarl-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:435aca062444a7f0c884861d2e3ea79883bd1cd19d0a381928b69ae1b85bc51d"}, + {file = "yarl-1.15.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:416f2e3beaeae81e2f7a45dc711258be5bdc79c940a9a270b266c0bec038fb84"}, + {file = "yarl-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:173563f3696124372831007e3d4b9821746964a95968628f7075d9231ac6bb33"}, + {file = "yarl-1.15.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9ce2e0f6123a60bd1a7f5ae3b2c49b240c12c132847f17aa990b841a417598a2"}, + {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaea112aed589131f73d50d570a6864728bd7c0c66ef6c9154ed7b59f24da611"}, + {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4ca3b9f370f218cc2a0309542cab8d0acdfd66667e7c37d04d617012485f904"}, + {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23ec1d3c31882b2a8a69c801ef58ebf7bae2553211ebbddf04235be275a38548"}, + {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75119badf45f7183e10e348edff5a76a94dc19ba9287d94001ff05e81475967b"}, + {file = "yarl-1.15.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78e6fdc976ec966b99e4daa3812fac0274cc28cd2b24b0d92462e2e5ef90d368"}, + {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8657d3f37f781d987037f9cc20bbc8b40425fa14380c87da0cb8dfce7c92d0fb"}, + {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:93bed8a8084544c6efe8856c362af08a23e959340c87a95687fdbe9c9f280c8b"}, + {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:69d5856d526802cbda768d3e6246cd0d77450fa2a4bc2ea0ea14f0d972c2894b"}, + {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ccad2800dfdff34392448c4bf834be124f10a5bc102f254521d931c1c53c455a"}, + {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:a880372e2e5dbb9258a4e8ff43f13888039abb9dd6d515f28611c54361bc5644"}, + {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c998d0558805860503bc3a595994895ca0f7835e00668dadc673bbf7f5fbfcbe"}, + {file = "yarl-1.15.2-cp313-cp313-win32.whl", hash = "sha256:533a28754e7f7439f217550a497bb026c54072dbe16402b183fdbca2431935a9"}, + {file = "yarl-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:5838f2b79dc8f96fdc44077c9e4e2e33d7089b10788464609df788eb97d03aad"}, + {file = "yarl-1.15.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fbbb63bed5fcd70cd3dd23a087cd78e4675fb5a2963b8af53f945cbbca79ae16"}, + {file = "yarl-1.15.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2e93b88ecc8f74074012e18d679fb2e9c746f2a56f79cd5e2b1afcf2a8a786b"}, + {file = "yarl-1.15.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af8ff8d7dc07ce873f643de6dfbcd45dc3db2c87462e5c387267197f59e6d776"}, + {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66f629632220a4e7858b58e4857927dd01a850a4cef2fb4044c8662787165cf7"}, + {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:833547179c31f9bec39b49601d282d6f0ea1633620701288934c5f66d88c3e50"}, + {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2aa738e0282be54eede1e3f36b81f1e46aee7ec7602aa563e81e0e8d7b67963f"}, + {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a13a07532e8e1c4a5a3afff0ca4553da23409fad65def1b71186fb867eeae8d"}, + {file = "yarl-1.15.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c45817e3e6972109d1a2c65091504a537e257bc3c885b4e78a95baa96df6a3f8"}, + {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:670eb11325ed3a6209339974b276811867defe52f4188fe18dc49855774fa9cf"}, + {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:d417a4f6943112fae3924bae2af7112562285848d9bcee737fc4ff7cbd450e6c"}, + {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bc8936d06cd53fddd4892677d65e98af514c8d78c79864f418bbf78a4a2edde4"}, + {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:954dde77c404084c2544e572f342aef384240b3e434e06cecc71597e95fd1ce7"}, + {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:5bc0df728e4def5e15a754521e8882ba5a5121bd6b5a3a0ff7efda5d6558ab3d"}, + {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b71862a652f50babab4a43a487f157d26b464b1dedbcc0afda02fd64f3809d04"}, + {file = "yarl-1.15.2-cp38-cp38-win32.whl", hash = "sha256:63eab904f8630aed5a68f2d0aeab565dcfc595dc1bf0b91b71d9ddd43dea3aea"}, + {file = "yarl-1.15.2-cp38-cp38-win_amd64.whl", hash = "sha256:2cf441c4b6e538ba0d2591574f95d3fdd33f1efafa864faa077d9636ecc0c4e9"}, + {file = "yarl-1.15.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a32d58f4b521bb98b2c0aa9da407f8bd57ca81f34362bcb090e4a79e9924fefc"}, + {file = "yarl-1.15.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:766dcc00b943c089349d4060b935c76281f6be225e39994c2ccec3a2a36ad627"}, + {file = "yarl-1.15.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bed1b5dbf90bad3bfc19439258c97873eab453c71d8b6869c136346acfe497e7"}, + {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed20a4bdc635f36cb19e630bfc644181dd075839b6fc84cac51c0f381ac472e2"}, + {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d538df442c0d9665664ab6dd5fccd0110fa3b364914f9c85b3ef9b7b2e157980"}, + {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c6cf1d92edf936ceedc7afa61b07e9d78a27b15244aa46bbcd534c7458ee1b"}, + {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce44217ad99ffad8027d2fde0269ae368c86db66ea0571c62a000798d69401fb"}, + {file = "yarl-1.15.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47a6000a7e833ebfe5886b56a31cb2ff12120b1efd4578a6fcc38df16cc77bd"}, + {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e52f77a0cd246086afde8815039f3e16f8d2be51786c0a39b57104c563c5cbb0"}, + {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:f9ca0e6ce7774dc7830dc0cc4bb6b3eec769db667f230e7c770a628c1aa5681b"}, + {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:136f9db0f53c0206db38b8cd0c985c78ded5fd596c9a86ce5c0b92afb91c3a19"}, + {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:173866d9f7409c0fb514cf6e78952e65816600cb888c68b37b41147349fe0057"}, + {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:6e840553c9c494a35e449a987ca2c4f8372668ee954a03a9a9685075228e5036"}, + {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:458c0c65802d816a6b955cf3603186de79e8fdb46d4f19abaec4ef0a906f50a7"}, + {file = "yarl-1.15.2-cp39-cp39-win32.whl", hash = "sha256:5b48388ded01f6f2429a8c55012bdbd1c2a0c3735b3e73e221649e524c34a58d"}, + {file = "yarl-1.15.2-cp39-cp39-win_amd64.whl", hash = "sha256:81dadafb3aa124f86dc267a2168f71bbd2bfb163663661ab0038f6e4b8edb810"}, + {file = "yarl-1.15.2-py3-none-any.whl", hash = "sha256:0d3105efab7c5c091609abacad33afff33bdff0035bece164c98bcf5a85ef90a"}, + {file = "yarl-1.15.2.tar.gz", hash = "sha256:a39c36f4218a5bb668b4f06874d676d35a035ee668e6e7e3538835c703634b84"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" +propcache = ">=0.2.0" + [[package]] name = "zipp" version = "3.20.2" @@ -1400,7 +2006,10 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] +[extras] +aiohttp = ["aiohttp", "httpx-aiohttp"] + [metadata] lock-version = "2.0" python-versions = ">=3.8" -content-hash = "467d9c9c9207b7d74127c6809b14048829f83d64d12ccd46e8eae6d2b154ad09" +content-hash = "26f2271a4fdfe59582412a00827b9823b335d3a4339ec708219804b8c645da05" diff --git a/pyproject.toml b/pyproject.toml index 299affc5..7654e02b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,9 +39,11 @@ Repository = 'https://github.com/truefoundry/truefoundry-python-sdk' [tool.poetry.dependencies] python = ">=3.8" +aiohttp = { version = ">=3.10.0,<4", optional = true} httpx = ">=0.21.2" +httpx-aiohttp = { version = "0.1.8", optional = true} pydantic = ">= 1.9.2" -pydantic-core = ">=2.18.2" +pydantic-core = ">=2.18.2,<2.44.0" typing_extensions = ">= 4.0.0" [tool.poetry.group.dev.dependencies] @@ -59,6 +61,9 @@ ruff = "==0.11.5" [tool.pytest.ini_options] testpaths = [ "tests" ] asyncio_mode = "auto" +markers = [ + "aiohttp: tests that require httpx_aiohttp to be installed", +] [tool.mypy] plugins = ["pydantic.mypy"] @@ -90,3 +95,6 @@ section-order = ["future", "standard-library", "third-party", "first-party"] [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" + +[tool.poetry.extras] +aiohttp=["aiohttp", "httpx-aiohttp"] diff --git a/reference.md b/reference.md index 02741563..5f024d1f 100644 --- a/reference.md +++ b/reference.md @@ -1,5 +1,5 @@ # Reference -
client.apply(...) -> AsyncHttpResponse[TrueFoundryApplyResponse] +
client.apply(...) -> TrueFoundryApplyResponse
@@ -26,14 +26,16 @@ Applies a given manifest to create or update resources of specific types, such a
```python -from truefoundry_sdk import Collaborator, MlRepoManifest, TrueFoundry +from truefoundry_sdk import TrueFoundry, MlRepoManifest, Collaborator client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.apply( manifest=MlRepoManifest( + type="ml-repo", name="name", storage_integration_fqn="storage_integration_fqn", collaborators=[ @@ -87,7 +89,7 @@ client.apply(
-
client.delete(...) -> AsyncHttpResponse[None] +
client.delete(...)
@@ -114,14 +116,16 @@ Deletes resources of specific types, such as provider-account, cluster, workspac
```python -from truefoundry_sdk import Collaborator, MlRepoManifest, TrueFoundry +from truefoundry_sdk import TrueFoundry, MlRepoManifest, Collaborator client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.delete( manifest=MlRepoManifest( + type="ml-repo", name="name", storage_integration_fqn="storage_integration_fqn", collaborators=[ @@ -168,7 +172,7 @@ client.delete(
## Internal -
client.internal.get_id_from_fqn(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
client.internal.get_id_from_fqn(...) -> typing.Dict[str, typing.Any]
@@ -198,9 +202,10 @@ Get IDs associated with the FQN for various entity types, such as deployment, ap from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.get_id_from_fqn( type="type", fqn="fqn", @@ -249,7 +254,7 @@ client.internal.get_id_from_fqn(
## Users -
client.users.list(...) -> AsyncPager[User, ListUsersResponse] +
client.users.list(...) -> ListUsersResponse
@@ -279,20 +284,16 @@ List all users of tenant filtered by query and showInvalidUsers. Pagination is a from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.users.list( + +client.users.list( limit=10, offset=0, query="query", show_invalid_users=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -352,7 +353,7 @@ for page in response.iter_pages():
-
client.users.pre_register_users(...) -> AsyncHttpResponse[RegisterUsersResponse] +
client.users.pre_register_users(...) -> RegisterUsersResponse
@@ -382,9 +383,10 @@ This endpoint allows tenant administrators to register users within their tenant from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.pre_register_users( email="email", ) @@ -455,7 +457,7 @@ client.users.pre_register_users(
-
client.users.update_roles(...) -> AsyncHttpResponse[UpdateUserRolesResponse] +
client.users.update_roles(...) -> UpdateUserRolesResponse
@@ -485,12 +487,15 @@ This endpoint allows tenant administrators to update the roles of a user within from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.update_roles( email="email", - roles=["roles"], + roles=[ + "roles" + ], ) ``` @@ -515,7 +520,7 @@ client.users.update_roles(
-**roles:** `typing.Sequence[str]` — Role names for the user +**roles:** `typing.List[str]` — Role names for the user
@@ -543,7 +548,7 @@ client.users.update_roles(
-
client.users.get(...) -> AsyncHttpResponse[GetUserResponse] +
client.users.get(...) -> GetUserResponse
@@ -573,9 +578,10 @@ Get User associated with provided User id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.get( id="id", ) @@ -614,7 +620,7 @@ client.users.get(
-
client.users.delete(...) -> AsyncHttpResponse[DeleteUserResponse] +
client.users.delete(...) -> DeleteUserResponse
@@ -644,9 +650,10 @@ Delete user if they are not a collaborator in any resource and not part of any t from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.delete( id="id", tenant_name="tenantName", @@ -694,7 +701,7 @@ client.users.delete(
-
client.users.invite_user(...) -> AsyncHttpResponse[InviteUserResponse] +
client.users.invite_user(...) -> InviteUserResponse
@@ -724,9 +731,10 @@ Invite a user to the tenant from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.invite_user( accept_invite_client_url="/invite-accept", email="email", @@ -774,7 +782,7 @@ client.users.invite_user(
-
client.users.deactivate(...) -> AsyncHttpResponse[DeactivateUserResponse] +
client.users.deactivate(...) -> DeactivateUserResponse
@@ -804,9 +812,10 @@ Deactivate user associated with the provided email within the tenant. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.deactivate( email="email", ) @@ -853,7 +862,7 @@ client.users.deactivate(
-
client.users.activate(...) -> AsyncHttpResponse[ActivateUserResponse] +
client.users.activate(...) -> ActivateUserResponse
@@ -883,9 +892,10 @@ Activate user associated with the provided email within the tenant. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.activate( email="email", ) @@ -932,7 +942,7 @@ client.users.activate(
-
client.users.change_password(...) -> AsyncHttpResponse[ChangePasswordResponse] +
client.users.change_password(...) -> ChangePasswordResponse
@@ -962,9 +972,10 @@ Change password for the authenticated user. Requires clientId and loginId in the from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.change_password( login_id="loginId", new_password="newPassword", @@ -1021,7 +1032,7 @@ client.users.change_password(
-
client.users.get_resources(...) -> AsyncHttpResponse[GetUserResourcesResponse] +
client.users.get_resources(...) -> GetUserResourcesResponse
@@ -1051,9 +1062,10 @@ Get all resources associated with a user. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.get_resources( id="id", ) @@ -1092,7 +1104,7 @@ client.users.get_resources(
-
client.users.get_permissions(...) -> AsyncHttpResponse[GetUserPermissionsResponse] +
client.users.get_permissions(...) -> GetUserPermissionsResponse
@@ -1122,9 +1134,10 @@ Get all role bindings associated with a user, including team-inherited bindings. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.get_permissions( id="id", ) @@ -1163,7 +1176,7 @@ client.users.get_permissions(
-
client.users.get_teams(...) -> AsyncHttpResponse[GetUserTeamsResponse] +
client.users.get_teams(...) -> GetUserTeamsResponse
@@ -1193,9 +1206,10 @@ Get all teams associated with a user, including their role in each team. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.users.get_teams( id="id", ) @@ -1235,7 +1249,7 @@ client.users.get_teams(
## Teams -
client.teams.list(...) -> AsyncPager[Team, ListTeamsResponse] +
client.teams.list(...) -> ListTeamsResponse
@@ -1266,19 +1280,15 @@ from truefoundry_sdk import TrueFoundry from truefoundry_sdk.teams import TeamsListRequestType client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.teams.list( + +client.teams.list( limit=10, offset=0, type=TeamsListRequestType.TEAM, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -1330,7 +1340,7 @@ for page in response.iter_pages():
-
client.teams.create_or_update(...) -> AsyncHttpResponse[GetTeamResponse] +
client.teams.create_or_update(...) -> GetTeamResponse
@@ -1357,16 +1367,20 @@ Creates a new team or updates an existing team. It ensures that the team name is
```python -from truefoundry_sdk import TeamManifest, TrueFoundry +from truefoundry_sdk import TrueFoundry, TeamManifest client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.teams.create_or_update( manifest=TeamManifest( + type="team", name="name", - members=["members"], + members=[ + "members" + ], ), ) @@ -1412,7 +1426,7 @@ client.teams.create_or_update(
-
client.teams.get(...) -> AsyncHttpResponse[GetTeamResponse] +
client.teams.get(...) -> GetTeamResponse
@@ -1442,9 +1456,10 @@ Get Team associated with provided team id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.teams.get( id="id", ) @@ -1483,7 +1498,7 @@ client.teams.get(
-
client.teams.delete(...) -> AsyncHttpResponse[DeleteTeamResponse] +
client.teams.delete(...) -> DeleteTeamResponse
@@ -1513,9 +1528,10 @@ Deletes the Team associated with the provided Id. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.teams.delete( id="id", ) @@ -1554,7 +1570,7 @@ client.teams.delete(
-
client.teams.get_permissions(...) -> AsyncHttpResponse[GetTeamPermissionsResponse] +
client.teams.get_permissions(...) -> GetTeamPermissionsResponse
@@ -1584,9 +1600,10 @@ Get all role bindings associated with a team. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.teams.get_permissions( id="id", ) @@ -1626,7 +1643,7 @@ client.teams.get_permissions(
## PersonalAccessTokens -
client.personal_access_tokens.list(...) -> AsyncPager[VirtualAccount, ListPersonalAccessTokenResponse] +
client.personal_access_tokens.list(...) -> ListPersonalAccessTokenResponse
@@ -1656,19 +1673,15 @@ List Personal Access Tokens created by the user in the current tenant. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.personal_access_tokens.list( + +client.personal_access_tokens.list( limit=10, offset=0, name_search_query="nameSearchQuery", ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -1720,7 +1733,7 @@ for page in response.iter_pages():
-
client.personal_access_tokens.create(...) -> AsyncHttpResponse[CreatePersonalAccessTokenResponse] +
client.personal_access_tokens.create(...) -> CreatePersonalAccessTokenResponse
@@ -1750,9 +1763,10 @@ Create Personal Access Token from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.personal_access_tokens.create( name="name", ) @@ -1807,7 +1821,7 @@ client.personal_access_tokens.create(
-
client.personal_access_tokens.revoke_all(...) -> AsyncHttpResponse[RevokeAllPersonalAccessTokenResponse] +
client.personal_access_tokens.revoke_all(...) -> RevokeAllPersonalAccessTokenResponse
@@ -1837,9 +1851,10 @@ Revoke All Personal Access Tokens for the user with the given email from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.personal_access_tokens.revoke_all( email="email", ) @@ -1878,7 +1893,7 @@ client.personal_access_tokens.revoke_all(
-
client.personal_access_tokens.delete(...) -> AsyncHttpResponse[DeletePersonalAccessTokenResponse] +
client.personal_access_tokens.delete(...) -> DeletePersonalAccessTokenResponse
@@ -1908,9 +1923,10 @@ Delete Personal Access Token associated with the provided serviceAccountId from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.personal_access_tokens.delete( id="id", ) @@ -1949,7 +1965,7 @@ client.personal_access_tokens.delete(
-
client.personal_access_tokens.get(...) -> AsyncHttpResponse[GetOrCreatePersonalAccessTokenResponse] +
client.personal_access_tokens.get(...) -> GetOrCreatePersonalAccessTokenResponse
@@ -1979,9 +1995,10 @@ Get an existing Personal Access Token by name, if it doesn't exist, it will crea from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.personal_access_tokens.get( name="name", ) @@ -2021,7 +2038,7 @@ client.personal_access_tokens.get(
## VirtualAccounts -
client.virtual_accounts.list(...) -> AsyncPager[VirtualAccount, ListVirtualAccountResponse] +
client.virtual_accounts.list(...) -> ListVirtualAccountResponse
@@ -2051,21 +2068,17 @@ List virtual accounts for the tenant. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.virtual_accounts.list( + +client.virtual_accounts.list( limit=10, offset=0, name_search_query="nameSearchQuery", is_expired=True, filter="filter", ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -2141,7 +2154,7 @@ for page in response.iter_pages():
-
client.virtual_accounts.create_or_update(...) -> AsyncHttpResponse[GetVirtualAccountResponse] +
client.virtual_accounts.create_or_update(...) -> GetVirtualAccountResponse
@@ -2168,15 +2181,17 @@ Creates a new virtual account or updates an existing one based on the provided m
```python -from truefoundry_sdk import Permissions, TrueFoundry, VirtualAccountManifest +from truefoundry_sdk import TrueFoundry, VirtualAccountManifest, Permissions client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.virtual_accounts.create_or_update( manifest=VirtualAccountManifest( name="name", + type="virtual-account", permissions=[ Permissions( resource_fqn="resource_fqn", @@ -2229,7 +2244,7 @@ client.virtual_accounts.create_or_update(
-
client.virtual_accounts.get(...) -> AsyncHttpResponse[GetVirtualAccountResponse] +
client.virtual_accounts.get(...) -> GetVirtualAccountResponse
@@ -2259,9 +2274,10 @@ Get virtual account by id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.virtual_accounts.get( id="id", ) @@ -2300,7 +2316,7 @@ client.virtual_accounts.get(
-
client.virtual_accounts.delete(...) -> AsyncHttpResponse[DeleteVirtualAccountResponse] +
client.virtual_accounts.delete(...) -> DeleteVirtualAccountResponse
@@ -2330,9 +2346,10 @@ Delete a virtual account associated with the provided virtual account id. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.virtual_accounts.delete( id="id", ) @@ -2371,7 +2388,7 @@ client.virtual_accounts.delete(
-
client.virtual_accounts.get_token(...) -> AsyncHttpResponse[GetTokenForVirtualAccountResponse] +
client.virtual_accounts.get_token(...) -> GetTokenForVirtualAccountResponse
@@ -2401,9 +2418,10 @@ Get token for a virtual account by id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.virtual_accounts.get_token( id="id", ) @@ -2442,7 +2460,7 @@ client.virtual_accounts.get_token(
-
client.virtual_accounts.sync_to_secret_store(...) -> AsyncHttpResponse[SyncVirtualAccountTokenResponse] +
client.virtual_accounts.sync_to_secret_store(...) -> SyncVirtualAccountTokenResponse
@@ -2472,9 +2490,10 @@ Syncs the virtual account token to the configured secret store. Returns the upda from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.virtual_accounts.sync_to_secret_store( id="id", ) @@ -2513,7 +2532,7 @@ client.virtual_accounts.sync_to_secret_store(
-
client.virtual_accounts.regenerate_token(...) -> AsyncHttpResponse[GetTokenForVirtualAccountResponse] +
client.virtual_accounts.regenerate_token(...) -> GetTokenForVirtualAccountResponse
@@ -2543,12 +2562,13 @@ Regenerate token for a virtual account by id. The old token will remain valid fo from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.virtual_accounts.regenerate_token( id="id", - grace_period_in_days=30.0, + grace_period_in_days=30, ) ``` @@ -2593,7 +2613,7 @@ client.virtual_accounts.regenerate_token(
-
client.virtual_accounts.delete_jwt(...) -> AsyncHttpResponse[None] +
client.virtual_accounts.delete_jwt(...)
@@ -2623,9 +2643,10 @@ Delete a JWT for a virtual account by id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.virtual_accounts.delete_jwt( id="id", jwt_id="jwtId", @@ -2674,7 +2695,7 @@ client.virtual_accounts.delete_jwt(
## Clusters -
client.clusters.list(...) -> AsyncPager[Cluster, ListClustersResponse] +
client.clusters.list(...) -> ListClustersResponse
@@ -2704,18 +2725,14 @@ Retrieves a list of all latest Clusters. Pagination is available based on query from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.clusters.list( + +client.clusters.list( limit=10, offset=0, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -2759,7 +2776,7 @@ for page in response.iter_pages():
-
client.clusters.create_or_update(...) -> AsyncHttpResponse[GetClusterResponse] +
client.clusters.create_or_update(...) -> GetClusterResponse
@@ -2786,22 +2803,21 @@ Create or Update cluster with provided manifest
```python -from truefoundry_sdk import ( - ClusterManifest, - ClusterManifestClusterType, - Collaborator, - TrueFoundry, -) +from truefoundry_sdk import TrueFoundry, ClusterManifest, ClusterManifestClusterType, Collaborator client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.clusters.create_or_update( manifest=ClusterManifest( + type="cluster", name="name", cluster_type=ClusterManifestClusterType.AWS_EKS, - environment_names=["environment_names"], + environment_names=[ + "environment_names" + ], collaborators=[ Collaborator( subject="subject", @@ -2853,7 +2869,7 @@ client.clusters.create_or_update(
-
client.clusters.get(...) -> AsyncHttpResponse[GetClusterResponse] +
client.clusters.get(...) -> GetClusterResponse
@@ -2883,9 +2899,10 @@ Get cluster associated with provided id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.clusters.get( id="id", ) @@ -2924,7 +2941,7 @@ client.clusters.get(
-
client.clusters.delete(...) -> AsyncHttpResponse[ClustersDeleteResponse] +
client.clusters.delete(...) -> ClustersDeleteResponse
@@ -2954,9 +2971,10 @@ Delete cluster associated with provided cluster id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.clusters.delete( id="id", ) @@ -2995,7 +3013,7 @@ client.clusters.delete(
-
client.clusters.get_addons(...) -> AsyncHttpResponse[ListClusterAddonsResponse] +
client.clusters.get_addons(...) -> ListClusterAddonsResponse
@@ -3025,9 +3043,10 @@ List addons for the provided cluster. Pagination is available based on query par from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.clusters.get_addons( id="id", limit=10, @@ -3084,7 +3103,7 @@ client.clusters.get_addons(
-
client.clusters.is_connected(...) -> AsyncHttpResponse[IsClusterConnectedResponse] +
client.clusters.is_connected(...) -> IsClusterConnectedResponse
@@ -3114,9 +3133,10 @@ Get the status of provided cluster from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.clusters.is_connected( id="id", ) @@ -3156,7 +3176,7 @@ client.clusters.is_connected(
## Applications -
client.applications.list(...) -> AsyncPager[Application, ListApplicationsResponse] +
client.applications.list(...) -> ListApplicationsResponse
@@ -3184,16 +3204,14 @@ Retrieves a list of all latest applications. Supports filtering by application I ```python from truefoundry_sdk import TrueFoundry -from truefoundry_sdk.applications import ( - ApplicationsListRequestDeviceTypeFilter, - ApplicationsListRequestLifecycleStage, -) +from truefoundry_sdk.applications import ApplicationsListRequestDeviceTypeFilter, ApplicationsListRequestLifecycleStage client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.applications.list( + +client.applications.list( limit=10, offset=0, application_id="applicationId", @@ -3212,11 +3230,6 @@ response = client.applications.list( lifecycle_stage=ApplicationsListRequestLifecycleStage.ACTIVE, is_recommendation_present_and_visible=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -3380,7 +3393,7 @@ for page in response.iter_pages():
-
client.applications.create_or_update(...) -> AsyncHttpResponse[GetApplicationDeploymentResponse] +
client.applications.create_or_update(...) -> GetApplicationDeploymentResponse
@@ -3410,11 +3423,14 @@ Create a new Application Deployment based on the provided manifest. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.applications.create_or_update( - manifest={"key": "value"}, + manifest={ + "key": "value" + }, ) ``` @@ -3507,7 +3523,7 @@ client.applications.create_or_update(
-
client.applications.get(...) -> AsyncHttpResponse[GetApplicationResponse] +
client.applications.get(...) -> GetApplicationResponse
@@ -3537,9 +3553,10 @@ Get Application associated with the provided application ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.applications.get( id="id", ) @@ -3578,7 +3595,7 @@ client.applications.get(
-
client.applications.delete(...) -> AsyncHttpResponse[DeleteApplicationResponse] +
client.applications.delete(...) -> DeleteApplicationResponse
@@ -3608,9 +3625,10 @@ Delete Application associated with the provided application ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.applications.delete( id="id", ) @@ -3649,7 +3667,7 @@ client.applications.delete(
-
client.applications.redeploy(...) -> AsyncHttpResponse[GetApplicationDeploymentResponse] +
client.applications.redeploy(...) -> GetApplicationDeploymentResponse
@@ -3679,9 +3697,10 @@ Creates a new deployment with the same manifest as the given deployment. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.applications.redeploy( id="id", deployment_id="deploymentId", @@ -3729,7 +3748,7 @@ client.applications.redeploy(
-
client.applications.scale_to_zero(...) -> AsyncHttpResponse[None] +
client.applications.scale_to_zero(...)
@@ -3759,9 +3778,10 @@ Pause a running application by scaling to 0 replicas from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.applications.scale_to_zero( id="id", ) @@ -3800,7 +3820,7 @@ client.applications.scale_to_zero(
-
client.applications.scale_to_original(...) -> AsyncHttpResponse[Deployment] +
client.applications.scale_to_original(...) -> Deployment
@@ -3830,9 +3850,10 @@ Resume a paused application by scaling back to the original number of replicas from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.applications.scale_to_original( id="id", ) @@ -3871,7 +3892,7 @@ client.applications.scale_to_original(
-
client.applications.cancel_deployment(...) -> AsyncHttpResponse[ApplicationsCancelDeploymentResponse] +
client.applications.cancel_deployment(...) -> ApplicationsCancelDeploymentResponse
@@ -3901,9 +3922,10 @@ Cancel an ongoing deployment associated with the provided application ID and dep from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.applications.cancel_deployment( id="id", deployment_id="deploymentId", @@ -3952,7 +3974,7 @@ client.applications.cancel_deployment(
## ApplicationVersions -
client.application_versions.list(...) -> AsyncPager[Deployment, ListApplicationDeploymentsResponse] +
client.application_versions.list(...) -> ListApplicationDeploymentsResponse
@@ -3982,21 +4004,17 @@ Fetch all deployments for a given application ID with optional filters such as d from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.application_versions.list( + +client.application_versions.list( id="id", limit=10, offset=0, version="1", deployment_id="deployment123", ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -4064,7 +4082,7 @@ for page in response.iter_pages():
-
client.application_versions.get(...) -> AsyncHttpResponse[GetApplicationDeploymentResponse] +
client.application_versions.get(...) -> GetApplicationDeploymentResponse
@@ -4094,9 +4112,10 @@ Get Deployment associated with the provided application ID and deployment ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.application_versions.get( id="id", deployment_id="deploymentId", @@ -4145,7 +4164,7 @@ client.application_versions.get(
## Jobs -
client.jobs.list_runs(...) -> AsyncPager[JobRun, ListJobRunResponse] +
client.jobs.list_runs(...) -> ListJobRunResponse
@@ -4172,13 +4191,14 @@ List Job Runs for provided Job Id. Filter the data based on parameters passed in
```python -from truefoundry_sdk import JobRunsSortBy, SortDirection, TrueFoundry +from truefoundry_sdk import TrueFoundry, JobRunsSortBy, SortDirection client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.jobs.list_runs( + +client.jobs.list_runs( job_id="jobId", limit=10, offset=0, @@ -4186,11 +4206,6 @@ response = client.jobs.list_runs( sort_by=JobRunsSortBy.START_TIME, order=SortDirection.ASC, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -4290,7 +4305,7 @@ for page in response.iter_pages():
-
client.jobs.get_run(...) -> AsyncHttpResponse[GetJobRunResponse] +
client.jobs.get_run(...) -> GetJobRunResponse
@@ -4320,9 +4335,10 @@ Get Job Run for provided jobRunName and jobId from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.jobs.get_run( job_id="jobId", job_run_name="jobRunName", @@ -4370,7 +4386,7 @@ client.jobs.get_run(
-
client.jobs.delete_run(...) -> AsyncHttpResponse[DeleteJobRunResponse] +
client.jobs.delete_run(...) -> DeleteJobRunResponse
@@ -4400,9 +4416,10 @@ Delete Job Run for provided jobRunName and jobId from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.jobs.delete_run( job_id="jobId", job_run_name="jobRunName", @@ -4450,7 +4467,7 @@ client.jobs.delete_run(
-
client.jobs.trigger(...) -> AsyncHttpResponse[TriggerJobRunResponse] +
client.jobs.trigger(...) -> TriggerJobRunResponse
@@ -4480,9 +4497,10 @@ Trigger Job for provided deploymentId or applicationId from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.jobs.trigger() ``` @@ -4543,7 +4561,7 @@ client.jobs.trigger()
-
client.jobs.terminate(...) -> AsyncHttpResponse[TerminateJobResponse] +
client.jobs.terminate(...) -> TerminateJobResponse
@@ -4573,9 +4591,10 @@ Terminate Job for provided deploymentId and jobRunName from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.jobs.terminate( deployment_id="deploymentId", job_run_name="jobRunName", @@ -4624,7 +4643,7 @@ client.jobs.terminate(
## Environments -
client.environments.list(...) -> AsyncPager[Environment, ListEnvironmentsResponse] +
client.environments.list(...) -> ListEnvironmentsResponse
@@ -4654,18 +4673,14 @@ List environments, if no environments are found, default environments are create from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.environments.list( + +client.environments.list( limit=10, offset=0, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -4709,7 +4724,7 @@ for page in response.iter_pages():
-
client.environments.create_or_update(...) -> AsyncHttpResponse[GetEnvironmentResponse] +
client.environments.create_or_update(...) -> GetEnvironmentResponse
@@ -4736,19 +4751,16 @@ Creates a new Environment or updates an existing Environment.
```python -from truefoundry_sdk import ( - EnvironmentColor, - EnvironmentManifest, - EnvironmentOptimizeFor, - TrueFoundry, -) +from truefoundry_sdk import TrueFoundry, EnvironmentManifest, EnvironmentColor, EnvironmentOptimizeFor client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.environments.create_or_update( manifest=EnvironmentManifest( + type="environment", name="name", color=EnvironmentColor(), is_production=True, @@ -4798,7 +4810,7 @@ client.environments.create_or_update(
-
client.environments.get(...) -> AsyncHttpResponse[GetEnvironmentResponse] +
client.environments.get(...) -> GetEnvironmentResponse
@@ -4828,9 +4840,10 @@ Get Environment associated with the provided id. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.environments.get( id="id", ) @@ -4869,7 +4882,7 @@ client.environments.get(
-
client.environments.delete(...) -> AsyncHttpResponse[bool] +
client.environments.delete(...) -> bool
@@ -4899,9 +4912,10 @@ Delete Environment associated with the provided id. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.environments.delete( id="id", ) @@ -4941,7 +4955,7 @@ client.environments.delete(
## Workspaces -
client.workspaces.list(...) -> AsyncPager[Workspace, ListWorkspacesResponse] +
client.workspaces.list(...) -> ListWorkspacesResponse
@@ -4971,10 +4985,11 @@ List workspaces associated with the user. Optional filters include clusterId, fq from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.workspaces.list( + +client.workspaces.list( limit=10, offset=0, cluster_id="clusterId", @@ -4982,11 +4997,6 @@ response = client.workspaces.list( fqn="fqn", include_cluster=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -5062,7 +5072,7 @@ for page in response.iter_pages():
-
client.workspaces.create_or_update(...) -> AsyncHttpResponse[GetWorkspaceResponse] +
client.workspaces.create_or_update(...) -> GetWorkspaceResponse
@@ -5092,11 +5102,13 @@ Creates a new workspace or updates an existing one based on the provided manifes from truefoundry_sdk import TrueFoundry, WorkspaceManifest client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.workspaces.create_or_update( manifest=WorkspaceManifest( + type="workspace", cluster_fqn="cluster_fqn", name="name", ), @@ -5144,7 +5156,7 @@ client.workspaces.create_or_update(
-
client.workspaces.search(...) -> AsyncPager[Workspace, ListWorkspacesResponse] +
client.workspaces.search(...) -> ListWorkspacesResponse
@@ -5174,20 +5186,16 @@ List workspaces the user can read with optional structured `filter` (name, id, e from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.workspaces.search( + +client.workspaces.search( limit=10, offset=0, filter="filter", include_cluster=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -5247,7 +5255,7 @@ for page in response.iter_pages():
-
client.workspaces.get(...) -> AsyncHttpResponse[GetWorkspaceResponse] +
client.workspaces.get(...) -> GetWorkspaceResponse
@@ -5277,9 +5285,10 @@ Get workspace associated with provided workspace id from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.workspaces.get( id="id", ) @@ -5318,7 +5327,7 @@ client.workspaces.get(
-
client.workspaces.delete(...) -> AsyncHttpResponse[WorkspacesDeleteResponse] +
client.workspaces.delete(...) -> WorkspacesDeleteResponse
@@ -5350,9 +5359,10 @@ Deletes the workspace with the given workspace ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.workspaces.delete( id="id", ) @@ -5392,7 +5402,7 @@ client.workspaces.delete(
## Secrets -
client.secrets.list(...) -> AsyncPager[Secret, ListSecretsResponse] +
client.secrets.list(...) -> ListSecretsResponse
@@ -5422,15 +5432,11 @@ List secrets associated with a user filtered with optional parameters passed in from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.secrets.list() -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page + +client.secrets.list() ```
@@ -5462,7 +5468,7 @@ for page in response.iter_pages():
-**secret_fqns:** `typing.Optional[typing.Sequence[str]]` — Array of FQNs +**secret_fqns:** `typing.Optional[typing.List[str]]` — Array of FQNs
@@ -5498,7 +5504,7 @@ for page in response.iter_pages():
-
client.secrets.get(...) -> AsyncHttpResponse[GetSecretResponse] +
client.secrets.get(...) -> GetSecretResponse
@@ -5528,9 +5534,10 @@ Get Secret associated with provided id. The secret value is not returned if the from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.secrets.get( id="id", ) @@ -5569,7 +5576,7 @@ client.secrets.get(
-
client.secrets.delete(...) -> AsyncHttpResponse[float] +
client.secrets.delete(...) -> float
@@ -5599,9 +5606,10 @@ Deletes a secret and its versions along with its values. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.secrets.delete( id="id", force_delete=True, @@ -5650,7 +5658,7 @@ client.secrets.delete(
## SecretGroups -
client.secret_groups.list(...) -> AsyncPager[SecretGroup, ListSecretGroupResponse] +
client.secret_groups.list(...) -> ListSecretGroupResponse
@@ -5680,20 +5688,16 @@ List the secret groups associated with a user along with the associated secrets from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.secret_groups.list( + +client.secret_groups.list( limit=10, offset=0, fqn="fqn", search="search", ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -5753,7 +5757,7 @@ for page in response.iter_pages():
-
client.secret_groups.create(...) -> AsyncHttpResponse[GetSecretGroupResponse] +
client.secret_groups.create(...) -> GetSecretGroupResponse
@@ -5780,12 +5784,13 @@ Creates a secret group with secrets in it. A secret version for each of the crea
```python -from truefoundry_sdk import SecretInput, TrueFoundry +from truefoundry_sdk import TrueFoundry, SecretInput client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.secret_groups.create( name="name", integration_id="integrationId", @@ -5827,7 +5832,7 @@ client.secret_groups.create(
-**secrets:** `typing.Sequence[SecretInput]` — The secrets to be associated with the secret group +**secrets:** `typing.List[SecretInput]` — The secrets to be associated with the secret group
@@ -5847,7 +5852,7 @@ client.secret_groups.create(
-
client.secret_groups.create_or_update(...) -> AsyncHttpResponse[GetSecretGroupResponse] +
client.secret_groups.create_or_update(...) -> GetSecretGroupResponse
@@ -5874,14 +5879,16 @@ Creates a new secret group or updates an existing one based on the provided mani
```python -from truefoundry_sdk import Collaborator, SecretGroupManifest, TrueFoundry +from truefoundry_sdk import TrueFoundry, SecretGroupManifest, Collaborator client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.secret_groups.create_or_update( manifest=SecretGroupManifest( + type="secret-group", name="name", integration_fqn="integration_fqn", collaborators=[ @@ -5935,7 +5942,7 @@ client.secret_groups.create_or_update(
-
client.secret_groups.get(...) -> AsyncHttpResponse[GetSecretGroupResponse] +
client.secret_groups.get(...) -> GetSecretGroupResponse
@@ -5965,9 +5972,10 @@ Get Secret Group by id. This method does not return the secret values of the
-
client.secret_groups.update(...) -> AsyncHttpResponse[GetSecretGroupResponse] +
client.secret_groups.update(...) -> GetSecretGroupResponse
@@ -6036,9 +6044,10 @@ Updates the secrets in a secret group with new values. A new secret version is c from truefoundry_sdk import TrueFoundry, UpdateSecretInput client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.secret_groups.update( id="id", secrets=[ @@ -6070,7 +6079,7 @@ client.secret_groups.update(
-**secrets:** `typing.Sequence[UpdateSecretInput]` +**secrets:** `typing.List[UpdateSecretInput]`
@@ -6090,7 +6099,7 @@ client.secret_groups.update(
-
client.secret_groups.delete(...) -> AsyncHttpResponse[DeleteSecretGroupResponse] +
client.secret_groups.delete(...) -> DeleteSecretGroupResponse
@@ -6120,9 +6129,10 @@ Deletes the secret group, its associated secrets and secret versions of those se from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.secret_groups.delete( id="id", ) @@ -6162,7 +6172,7 @@ client.secret_groups.delete(
## Events -
client.events.get(...) -> AsyncHttpResponse[GetEventsResponse] +
client.events.get(...) -> GetEventsResponse
@@ -6192,9 +6202,10 @@ Get Events for Pod, Job Run, Application. The events are sourced from Kubernetes from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.events.get( start_ts="startTs", end_ts="endTs", @@ -6278,7 +6289,7 @@ client.events.get(
## Alerts -
client.alerts.list(...) -> AsyncHttpResponse[GetAlertsResponse] +
client.alerts.list(...) -> GetAlertsResponse
@@ -6305,12 +6316,13 @@ Get alerts for a given application or cluster filtered by start and end timestam
```python -from truefoundry_sdk import AlertStatus, TrueFoundry +from truefoundry_sdk import TrueFoundry, AlertStatus client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.alerts.list( start_ts="startTs", end_ts="endTs", @@ -6386,7 +6398,7 @@ client.alerts.list(
## Logs -
client.logs.get(...) -> AsyncHttpResponse[GetLogsResponse] +
client.logs.get(...) -> GetLogsResponse
@@ -6413,17 +6425,13 @@ Fetch logs for various workload components, including Services, Jobs, Workflows,
```python -from truefoundry_sdk import ( - LogsSearchFilterType, - LogsSearchOperatorType, - LogsSortingDirection, - TrueFoundry, -) +from truefoundry_sdk import TrueFoundry, LogsSortingDirection, LogsSearchFilterType, LogsSearchOperatorType client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.logs.get( start_ts=1000000, end_ts=1000000, @@ -6606,7 +6614,7 @@ client.logs.get(
## MlRepos -
client.ml_repos.create_or_update(...) -> AsyncHttpResponse[GetMlRepoResponse] +
client.ml_repos.create_or_update(...) -> GetMlRepoResponse
@@ -6633,14 +6641,16 @@ Creates or updates an MLRepo entity based on the provided manifest.
```python -from truefoundry_sdk import Collaborator, MlRepoManifest, TrueFoundry +from truefoundry_sdk import TrueFoundry, MlRepoManifest, Collaborator client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.ml_repos.create_or_update( manifest=MlRepoManifest( + type="ml-repo", name="name", storage_integration_fqn="storage_integration_fqn", collaborators=[ @@ -6694,7 +6704,7 @@ client.ml_repos.create_or_update(
-
client.ml_repos.get(...) -> AsyncHttpResponse[GetMlRepoResponse] +
client.ml_repos.get(...) -> GetMlRepoResponse
@@ -6724,9 +6734,10 @@ Get an ML Repo by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.ml_repos.get( id="id", ) @@ -6765,7 +6776,7 @@ client.ml_repos.get(
-
client.ml_repos.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.ml_repos.delete(...) -> EmptyResponse
@@ -6795,9 +6806,10 @@ Delete an ML Repo by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.ml_repos.delete( id="id", ) @@ -6836,7 +6848,7 @@ client.ml_repos.delete(
-
client.ml_repos.list(...) -> AsyncPager[MlRepo, ListMlReposResponse] +
client.ml_repos.list(...) -> ListMlReposResponse
@@ -6866,19 +6878,15 @@ List ML Repos with optional filtering by name. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.ml_repos.list( + +client.ml_repos.list( name="name", limit=1, offset=1, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -6931,7 +6939,7 @@ for page in response.iter_pages():
## Traces -
client.traces.query_spans(...) -> AsyncPager[TraceSpan, QuerySpansResponse] +
client.traces.query_spans(...) -> QuerySpansResponse
@@ -6947,17 +6955,13 @@ for page in response.iter_pages(): from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.traces.query_spans( + +client.traces.query_spans( start_time="startTime", ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -6989,7 +6993,7 @@ for page in response.iter_pages():
-**trace_ids:** `typing.Optional[typing.Sequence[str]]` — Array of trace IDs to filter by +**trace_ids:** `typing.Optional[typing.List[str]]` — Array of trace IDs to filter by
@@ -6997,7 +7001,7 @@ for page in response.iter_pages():
-**span_ids:** `typing.Optional[typing.Sequence[str]]` — Array of span IDs to filter by +**span_ids:** `typing.Optional[typing.List[str]]` — Array of span IDs to filter by
@@ -7005,7 +7009,7 @@ for page in response.iter_pages():
-**parent_span_ids:** `typing.Optional[typing.Sequence[str]]` — Array of parent span IDs to filter by +**parent_span_ids:** `typing.Optional[typing.List[str]]` — Array of parent span IDs to filter by
@@ -7013,7 +7017,7 @@ for page in response.iter_pages():
-**created_by_subject_types:** `typing.Optional[typing.Sequence[SubjectType]]` — Array of subject types to filter by +**created_by_subject_types:** `typing.Optional[typing.List[SubjectType]]` — Array of subject types to filter by
@@ -7021,7 +7025,7 @@ for page in response.iter_pages():
-**created_by_subject_slugs:** `typing.Optional[typing.Sequence[str]]` — Array of subject slugs to filter by +**created_by_subject_slugs:** `typing.Optional[typing.List[str]]` — Array of subject slugs to filter by
@@ -7029,7 +7033,7 @@ for page in response.iter_pages():
-**application_names:** `typing.Optional[typing.Sequence[str]]` — Array of application names to filter by +**application_names:** `typing.Optional[typing.List[str]]` — Array of application names to filter by
@@ -7077,7 +7081,7 @@ for page in response.iter_pages():
-**filters:** `typing.Optional[typing.Sequence[QuerySpansRequestFiltersItem]]` — Array of filters +**filters:** `typing.Optional[typing.List[QuerySpansRequestFiltersItem]]` — Array of filters
@@ -7106,7 +7110,7 @@ for page in response.iter_pages():
## Artifacts -
client.artifacts.get(...) -> AsyncHttpResponse[GetArtifactResponse] +
client.artifacts.get(...) -> GetArtifactResponse
@@ -7136,9 +7140,10 @@ Get an artifact by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifacts.get( id="id", ) @@ -7177,7 +7182,7 @@ client.artifacts.get(
-
client.artifacts.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.artifacts.delete(...) -> EmptyResponse
@@ -7207,9 +7212,10 @@ Delete an artifact by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifacts.delete( id="id", ) @@ -7248,7 +7254,7 @@ client.artifacts.delete(
-
client.artifacts.list(...) -> AsyncPager[Artifact, ListArtifactsResponse] +
client.artifacts.list(...) -> ListArtifactsResponse
@@ -7278,10 +7284,11 @@ List artifacts with optional filtering by FQN, ML Repo, name, or run ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.artifacts.list( + +client.artifacts.list( fqn="fqn", ml_repo_id="ml_repo_id", name="name", @@ -7290,11 +7297,6 @@ response = client.artifacts.list( run_id="run_id", include_empty_artifacts=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -7378,7 +7380,7 @@ for page in response.iter_pages():
-
client.artifacts.create_or_update(...) -> AsyncHttpResponse[GetArtifactVersionResponse] +
client.artifacts.create_or_update(...) -> GetArtifactVersionResponse
@@ -7405,22 +7407,24 @@ Create or update an artifact version.
```python -from truefoundry_sdk import ( - ArtifactManifest, - TrueFoundry, - TrueFoundryManagedSource, -) +from truefoundry_sdk import TrueFoundry, ArtifactManifest, TrueFoundryManagedSource client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifacts.create_or_update( manifest=ArtifactManifest( name="name", - metadata={"key": "value"}, + metadata={ + "key": "value" + }, ml_repo="ml_repo", - source=TrueFoundryManagedSource(), + type="artifact-version", + source=TrueFoundryManagedSource( + type="truefoundry", + ), ), ) @@ -7459,7 +7463,7 @@ client.artifacts.create_or_update(
## Prompts -
client.prompts.get(...) -> AsyncHttpResponse[GetPromptResponse] +
client.prompts.get(...) -> GetPromptResponse
@@ -7489,9 +7493,10 @@ Get a prompt by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.prompts.get( id="id", ) @@ -7530,7 +7535,7 @@ client.prompts.get(
-
client.prompts.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.prompts.delete(...) -> EmptyResponse
@@ -7560,9 +7565,10 @@ Delete a prompt by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.prompts.delete( id="id", ) @@ -7601,7 +7607,7 @@ client.prompts.delete(
-
client.prompts.list(...) -> AsyncPager[Prompt, ListPromptsResponse] +
client.prompts.list(...) -> ListPromptsResponse
@@ -7631,10 +7637,11 @@ List prompts with optional filtering by FQN, ML Repo, or name. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.prompts.list( + +client.prompts.list( fqn="fqn", ml_repo_id="ml_repo_id", name="name", @@ -7642,11 +7649,6 @@ response = client.prompts.list( limit=1, include_empty_prompts=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -7722,7 +7724,7 @@ for page in response.iter_pages():
-
client.prompts.create_or_update(...) -> AsyncHttpResponse[GetPromptVersionResponse] +
client.prompts.create_or_update(...) -> GetPromptVersionResponse
@@ -7749,19 +7751,24 @@ Create or update a prompt version.
```python -from truefoundry_sdk import ChatPromptManifest, SystemMessage, TrueFoundry +from truefoundry_sdk import TrueFoundry, ChatPromptManifest, SystemMessage client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.prompts.create_or_update( manifest=ChatPromptManifest( name="name", - metadata={"key": "value"}, + metadata={ + "key": "value" + }, ml_repo="ml_repo", + type="chat_prompt", messages=[ SystemMessage( + role="system", content="content", ) ], @@ -7803,7 +7810,7 @@ client.prompts.create_or_update(
## Models -
client.models.get(...) -> AsyncHttpResponse[GetModelResponse] +
client.models.get(...) -> GetModelResponse
@@ -7833,9 +7840,10 @@ Get a model by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.models.get( id="id", ) @@ -7874,7 +7882,7 @@ client.models.get(
-
client.models.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.models.delete(...) -> EmptyResponse
@@ -7904,9 +7912,10 @@ Delete a model by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.models.delete( id="id", ) @@ -7945,7 +7954,7 @@ client.models.delete(
-
client.models.list(...) -> AsyncPager[Model, ListModelsResponse] +
client.models.list(...) -> ListModelsResponse
@@ -7975,10 +7984,11 @@ List models with optional filtering by FQN, ML Repo, name, or run ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.models.list( + +client.models.list( fqn="fqn", ml_repo_id="ml_repo_id", name="name", @@ -7987,11 +7997,6 @@ response = client.models.list( run_id="run_id", include_empty_models=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -8075,7 +8080,7 @@ for page in response.iter_pages():
-
client.models.create_or_update(...) -> AsyncHttpResponse[GetModelVersionResponse] +
client.models.create_or_update(...) -> GetModelVersionResponse
@@ -8102,18 +8107,24 @@ Create or update a model version.
```python -from truefoundry_sdk import ModelManifest, TrueFoundry, TrueFoundryManagedSource +from truefoundry_sdk import TrueFoundry, ModelManifest, TrueFoundryManagedSource client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.models.create_or_update( manifest=ModelManifest( name="name", - metadata={"key": "value"}, + metadata={ + "key": "value" + }, ml_repo="ml_repo", - source=TrueFoundryManagedSource(), + type="model-version", + source=TrueFoundryManagedSource( + type="truefoundry", + ), ), ) @@ -8152,7 +8163,7 @@ client.models.create_or_update(
## ArtifactVersions -
client.artifact_versions.apply_tags(...) -> AsyncHttpResponse[EmptyResponse] +
client.artifact_versions.apply_tags(...) -> EmptyResponse
@@ -8182,12 +8193,15 @@ Apply tags to an artifact version. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifact_versions.apply_tags( artifact_version_id="artifact_version_id", - tags=["tags"], + tags=[ + "tags" + ], ) ``` @@ -8212,7 +8226,7 @@ client.artifact_versions.apply_tags(
-**tags:** `typing.Sequence[str]` — List of tags to apply to the artifact version +**tags:** `typing.List[str]` — List of tags to apply to the artifact version
@@ -8240,7 +8254,7 @@ client.artifact_versions.apply_tags(
-
client.artifact_versions.get(...) -> AsyncHttpResponse[GetArtifactVersionResponse] +
client.artifact_versions.get(...) -> GetArtifactVersionResponse
@@ -8270,9 +8284,10 @@ Get an artifact version by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifact_versions.get( id="id", ) @@ -8311,7 +8326,7 @@ client.artifact_versions.get(
-
client.artifact_versions.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.artifact_versions.delete(...) -> EmptyResponse
@@ -8341,9 +8356,10 @@ Delete an artifact version by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifact_versions.delete( id="id", ) @@ -8382,7 +8398,7 @@ client.artifact_versions.delete(
-
client.artifact_versions.list(...) -> AsyncPager[ArtifactVersion, ListArtifactVersionsResponse] +
client.artifact_versions.list(...) -> ListArtifactVersionsResponse
@@ -8412,10 +8428,11 @@ List artifact versions with optional filtering by tag, FQN, artifact ID, ML Repo from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.artifact_versions.list( + +client.artifact_versions.list( tag="tag", fqn="fqn", artifact_id="artifact_id", @@ -8426,11 +8443,6 @@ response = client.artifact_versions.list( limit=1, include_internal_metadata=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -8546,7 +8558,7 @@ for page in response.iter_pages():
-
client.artifact_versions.get_signed_urls(...) -> AsyncHttpResponse[GetSignedUrLsResponse] +
client.artifact_versions.get_signed_urls(...) -> GetSignedUrLsResponse
@@ -8573,15 +8585,18 @@ Get pre-signed URLs for reading or writing files in an artifact version.
```python -from truefoundry_sdk import Operation, TrueFoundry +from truefoundry_sdk import TrueFoundry, Operation client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifact_versions.get_signed_urls( id="id", - paths=["paths"], + paths=[ + "paths" + ], operation=Operation.READ, ) @@ -8599,23 +8614,7 @@ client.artifact_versions.get_signed_urls(
-**id:** `str` — ID of the artifact version to get signed URLs for - -
-
- -
-
- -**paths:** `typing.Sequence[str]` — List of relative file paths within the artifact version to get signed URLs for - -
-
- -
-
- -**operation:** `Operation` — Operation type for the signed URL (e.g., 'READ' or 'WRITE') +**request:** `GetSignedUrLsRequest`
@@ -8635,7 +8634,7 @@ client.artifact_versions.get_signed_urls(
-
client.artifact_versions.create_multi_part_upload(...) -> AsyncHttpResponse[MultiPartUploadResponse] +
client.artifact_versions.create_multi_part_upload(...) -> MultiPartUploadResponse
@@ -8665,9 +8664,10 @@ Create a multipart upload for large files in an artifact version. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifact_versions.create_multi_part_upload( id="id", path="path", @@ -8688,23 +8688,7 @@ client.artifact_versions.create_multi_part_upload(
-**id:** `str` — ID of the artifact version to upload files to - -
-
- -
-
- -**path:** `str` — Relative path within the artifact version where the file should be uploaded - -
-
- -
-
- -**num_parts:** `int` — Number of parts to split the upload into for multipart upload +**request:** `CreateMultiPartUploadRequest`
@@ -8724,7 +8708,7 @@ client.artifact_versions.create_multi_part_upload(
-
client.artifact_versions.stage(...) -> AsyncHttpResponse[StageArtifactResponse] +
client.artifact_versions.stage(...) -> StageArtifactResponse
@@ -8751,18 +8735,24 @@ Stage an artifact version for upload, returning storage location and version ID.
```python -from truefoundry_sdk import ModelManifest, TrueFoundry, TrueFoundryManagedSource +from truefoundry_sdk import TrueFoundry, ModelManifest, TrueFoundryManagedSource client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifact_versions.stage( manifest=ModelManifest( name="name", - metadata={"key": "value"}, + metadata={ + "key": "value" + }, ml_repo="ml_repo", - source=TrueFoundryManagedSource(), + type="model-version", + source=TrueFoundryManagedSource( + type="truefoundry", + ), ), ) @@ -8800,7 +8790,7 @@ client.artifact_versions.stage(
-
client.artifact_versions.list_files(...) -> AsyncPager[FileInfo, ListFilesResponse] +
client.artifact_versions.list_files(...) -> ListFilesResponse
@@ -8830,17 +8820,13 @@ List files and directories in an artifact version. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.artifact_versions.list_files( + +client.artifact_versions.list_files( id="id", ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -8856,31 +8842,7 @@ for page in response.iter_pages():
-**id:** `str` — ID of the artifact version to list files from - -
-
- -
-
- -**path:** `typing.Optional[str]` — Relative path within the artifact version to list files from (defaults to root) - -
-
- -
-
- -**limit:** `typing.Optional[int]` — Maximum number of files/directories to return - -
-
- -
-
- -**page_token:** `typing.Optional[str]` — Token to retrieve the next page of results +**request:** `ListFilesRequest`
@@ -8900,7 +8862,7 @@ for page in response.iter_pages():
-
client.artifact_versions.mark_stage_failure(...) -> AsyncHttpResponse[EmptyResponse] +
client.artifact_versions.mark_stage_failure(...) -> EmptyResponse
@@ -8930,9 +8892,10 @@ Mark a staged artifact version as failed. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.artifact_versions.mark_stage_failure( id="id", ) @@ -8972,7 +8935,7 @@ client.artifact_versions.mark_stage_failure(
## ModelVersions -
client.model_versions.apply_tags(...) -> AsyncHttpResponse[EmptyResponse] +
client.model_versions.apply_tags(...) -> EmptyResponse
@@ -9002,12 +8965,15 @@ Apply tags to a model version. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.model_versions.apply_tags( model_version_id="model_version_id", - tags=["tags"], + tags=[ + "tags" + ], ) ``` @@ -9032,7 +8998,7 @@ client.model_versions.apply_tags(
-**tags:** `typing.Sequence[str]` — List of tags to apply to the model version +**tags:** `typing.List[str]` — List of tags to apply to the model version
@@ -9060,7 +9026,7 @@ client.model_versions.apply_tags(
-
client.model_versions.get(...) -> AsyncHttpResponse[GetModelVersionResponse] +
client.model_versions.get(...) -> GetModelVersionResponse
@@ -9090,9 +9056,10 @@ Get a model version by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.model_versions.get( id="id", ) @@ -9131,7 +9098,7 @@ client.model_versions.get(
-
client.model_versions.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.model_versions.delete(...) -> EmptyResponse
@@ -9161,9 +9128,10 @@ Delete a model version by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.model_versions.delete( id="id", ) @@ -9202,7 +9170,7 @@ client.model_versions.delete(
-
client.model_versions.list(...) -> AsyncPager[ModelVersion, ListModelVersionsResponse] +
client.model_versions.list(...) -> ListModelVersionsResponse
@@ -9232,10 +9200,11 @@ List model versions with optional filtering by tag, FQN, model ID, ML Repo, name from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.model_versions.list( + +client.model_versions.list( tag="tag", fqn="fqn", model_id="model_id", @@ -9246,11 +9215,6 @@ response = client.model_versions.list( limit=1, include_internal_metadata=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -9367,7 +9331,7 @@ for page in response.iter_pages():
## PromptVersions -
client.prompt_versions.apply_tags(...) -> AsyncHttpResponse[EmptyResponse] +
client.prompt_versions.apply_tags(...) -> EmptyResponse
@@ -9397,12 +9361,15 @@ Apply tags to a prompt version. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.prompt_versions.apply_tags( prompt_version_id="prompt_version_id", - tags=["tags"], + tags=[ + "tags" + ], ) ``` @@ -9427,7 +9394,7 @@ client.prompt_versions.apply_tags(
-**tags:** `typing.Sequence[str]` — List of tags to apply to the prompt version +**tags:** `typing.List[str]` — List of tags to apply to the prompt version
@@ -9455,7 +9422,7 @@ client.prompt_versions.apply_tags(
-
client.prompt_versions.get(...) -> AsyncHttpResponse[GetPromptVersionResponse] +
client.prompt_versions.get(...) -> GetPromptVersionResponse
@@ -9485,9 +9452,10 @@ Get a prompt version by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.prompt_versions.get( id="id", ) @@ -9526,7 +9494,7 @@ client.prompt_versions.get(
-
client.prompt_versions.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.prompt_versions.delete(...) -> EmptyResponse
@@ -9556,9 +9524,10 @@ Delete a prompt version by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.prompt_versions.delete( id="id", ) @@ -9597,7 +9566,7 @@ client.prompt_versions.delete(
-
client.prompt_versions.list(...) -> AsyncPager[PromptVersion, ListPromptVersionsResponse] +
client.prompt_versions.list(...) -> ListPromptVersionsResponse
@@ -9627,10 +9596,11 @@ List prompt versions with optional filtering by tag, FQN, prompt ID, ML Repo, na from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.prompt_versions.list( + +client.prompt_versions.list( tag="tag", fqn="fqn", prompt_id="prompt_id", @@ -9640,11 +9610,6 @@ response = client.prompt_versions.list( offset=1, limit=1, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -9737,7 +9702,7 @@ for page in response.iter_pages():
## AgentSkills -
client.agent_skills.get(...) -> AsyncHttpResponse[GetAgentSkillResponse] +
client.agent_skills.get(...) -> GetAgentSkillResponse
@@ -9767,9 +9732,10 @@ Get an agent skill artifact by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.agent_skills.get( agent_skill_id="agent_skill_id", ) @@ -9808,7 +9774,7 @@ client.agent_skills.get(
-
client.agent_skills.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.agent_skills.delete(...) -> EmptyResponse
@@ -9838,9 +9804,10 @@ Delete an agent skill artifact by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.agent_skills.delete( agent_skill_id="agent_skill_id", ) @@ -9879,7 +9846,7 @@ client.agent_skills.delete(
-
client.agent_skills.list(...) -> AsyncPager[AgentSkill, ListAgentSkillsResponse] +
client.agent_skills.list(...) -> ListAgentSkillsResponse
@@ -9909,10 +9876,11 @@ List agent skills with optional filtering by FQN, ML Repo, or name. When present from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.agent_skills.list( + +client.agent_skills.list( fqn="fqn", ml_repo_id="ml_repo_id", name="name", @@ -9920,11 +9888,6 @@ response = client.agent_skills.list( limit=1, include_empty_agent_skills=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -10000,7 +9963,7 @@ for page in response.iter_pages():
-
client.agent_skills.create_or_update(...) -> AsyncHttpResponse[GetAgentSkillVersionResponse] +
client.agent_skills.create_or_update(...) -> GetAgentSkillVersionResponse
@@ -10027,22 +9990,23 @@ Create or update an agent skill version from a manifest.
```python -from truefoundry_sdk import ( - AgentSkillManifest, - AgentSkillSourceInline, - TrueFoundry, -) +from truefoundry_sdk import TrueFoundry, AgentSkillManifest, AgentSkillSourceInline client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.agent_skills.create_or_update( manifest=AgentSkillManifest( name="name", - metadata={"key": "value"}, + metadata={ + "key": "value" + }, ml_repo="ml_repo", + type="agent_skill", source=AgentSkillSourceInline( + type="inline", skill_md="skill_md", ), ), @@ -10083,7 +10047,7 @@ client.agent_skills.create_or_update(
## AgentSkillVersions -
client.agent_skill_versions.get(...) -> AsyncHttpResponse[GetAgentSkillVersionResponse] +
client.agent_skill_versions.get(...) -> GetAgentSkillVersionResponse
@@ -10099,9 +10063,10 @@ client.agent_skills.create_or_update( from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.agent_skill_versions.get( agent_skill_version_id="agent_skill_version_id", ) @@ -10140,7 +10105,7 @@ client.agent_skill_versions.get(
-
client.agent_skill_versions.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.agent_skill_versions.delete(...) -> EmptyResponse
@@ -10156,9 +10121,10 @@ client.agent_skill_versions.get( from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.agent_skill_versions.delete( agent_skill_version_id="agent_skill_version_id", ) @@ -10197,7 +10163,7 @@ client.agent_skill_versions.delete(
-
client.agent_skill_versions.list(...) -> AsyncPager[AgentSkillVersion, ListAgentSkillVersionsResponse] +
client.agent_skill_versions.list(...) -> ListAgentSkillVersionsResponse
@@ -10227,10 +10193,11 @@ List agent skill versions. Each manifest has `source.type` `blob-storage` and `d from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.agent_skill_versions.list( + +client.agent_skill_versions.list( fqn="fqn", agent_skill_id="agent_skill_id", ml_repo_id="ml_repo_id", @@ -10239,11 +10206,6 @@ response = client.agent_skill_versions.list( offset=1, limit=1, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -10328,7 +10290,7 @@ for page in response.iter_pages():
## DataDirectories -
client.data_directories.get(...) -> AsyncHttpResponse[GetDataDirectoryResponse] +
client.data_directories.get(...) -> GetDataDirectoryResponse
@@ -10358,9 +10320,10 @@ Get a data directory by its ID. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.data_directories.get( id="id", ) @@ -10399,7 +10362,7 @@ client.data_directories.get(
-
client.data_directories.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.data_directories.delete(...) -> EmptyResponse
@@ -10429,9 +10392,10 @@ Delete a data directory, optionally including its contents. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.data_directories.delete( id="id", delete_contents=True, @@ -10479,7 +10443,7 @@ client.data_directories.delete(
-
client.data_directories.list(...) -> AsyncPager[DataDirectory, ListDataDirectoriesResponse] +
client.data_directories.list(...) -> ListDataDirectoriesResponse
@@ -10509,21 +10473,17 @@ List data directories with optional filtering by FQN, ML Repo, or name. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.data_directories.list( + +client.data_directories.list( fqn="fqn", ml_repo_id="ml_repo_id", name="name", limit=1, offset=1, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -10591,7 +10551,7 @@ for page in response.iter_pages():
-
client.data_directories.create_or_update(...) -> AsyncHttpResponse[GetDataDirectoryResponse] +
client.data_directories.create_or_update(...) -> GetDataDirectoryResponse
@@ -10618,22 +10578,24 @@ Create or update a data directory.
```python -from truefoundry_sdk import ( - DataDirectoryManifest, - TrueFoundry, - TrueFoundryManagedSource, -) +from truefoundry_sdk import TrueFoundry, DataDirectoryManifest, TrueFoundryManagedSource client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.data_directories.create_or_update( manifest=DataDirectoryManifest( + type="data-dir", name="name", ml_repo="ml_repo", - metadata={"key": "value"}, - source=TrueFoundryManagedSource(), + metadata={ + "key": "value" + }, + source=TrueFoundryManagedSource( + type="truefoundry", + ), ), ) @@ -10671,7 +10633,7 @@ client.data_directories.create_or_update(
-
client.data_directories.list_files(...) -> AsyncPager[FileInfo, ListFilesResponse] +
client.data_directories.list_files(...) -> ListFilesResponse
@@ -10701,17 +10663,13 @@ List files and directories in a data directory. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.data_directories.list_files( + +client.data_directories.list_files( id="id", ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -10727,31 +10685,7 @@ for page in response.iter_pages():
-**id:** `str` — ID of the artifact version to list files from - -
-
- -
-
- -**path:** `typing.Optional[str]` — Relative path within the artifact version to list files from (defaults to root) - -
-
- -
-
- -**limit:** `typing.Optional[int]` — Maximum number of files/directories to return - -
-
- -
-
- -**page_token:** `typing.Optional[str]` — Token to retrieve the next page of results +**request:** `ListFilesRequest`
@@ -10771,7 +10705,7 @@ for page in response.iter_pages():
-
client.data_directories.delete_files(...) -> AsyncHttpResponse[EmptyResponse] +
client.data_directories.delete_files(...) -> EmptyResponse
@@ -10801,12 +10735,15 @@ Delete files from a data directory. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.data_directories.delete_files( id="id", - paths=["paths"], + paths=[ + "paths" + ], ) ``` @@ -10831,7 +10768,7 @@ client.data_directories.delete_files(
-**paths:** `typing.Sequence[str]` — List of relative file paths within the artifact version to delete +**paths:** `typing.List[str]` — List of relative file paths within the artifact version to delete
@@ -10851,7 +10788,7 @@ client.data_directories.delete_files(
-
client.data_directories.get_signed_urls(...) -> AsyncHttpResponse[GetSignedUrLsResponse] +
client.data_directories.get_signed_urls(...) -> GetSignedUrLsResponse
@@ -10878,15 +10815,18 @@ Get pre-signed URLs for reading or writing files in a data directory.
```python -from truefoundry_sdk import Operation, TrueFoundry +from truefoundry_sdk import TrueFoundry, Operation client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.data_directories.get_signed_urls( id="id", - paths=["paths"], + paths=[ + "paths" + ], operation=Operation.READ, ) @@ -10904,23 +10844,7 @@ client.data_directories.get_signed_urls(
-**id:** `str` — ID of the artifact version to get signed URLs for - -
-
- -
-
- -**paths:** `typing.Sequence[str]` — List of relative file paths within the artifact version to get signed URLs for - -
-
- -
-
- -**operation:** `Operation` — Operation type for the signed URL (e.g., 'READ' or 'WRITE') +**request:** `GetSignedUrLsRequest`
@@ -10940,7 +10864,7 @@ client.data_directories.get_signed_urls(
-
client.data_directories.create_multipart_upload(...) -> AsyncHttpResponse[MultiPartUploadResponse] +
client.data_directories.create_multipart_upload(...) -> MultiPartUploadResponse
@@ -10970,9 +10894,10 @@ Create a multipart upload for large files in a data directory. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.data_directories.create_multipart_upload( id="id", path="path", @@ -10993,23 +10918,7 @@ client.data_directories.create_multipart_upload(
-**id:** `str` — ID of the artifact version to upload files to - -
-
- -
-
- -**path:** `str` — Relative path within the artifact version where the file should be uploaded - -
-
- -
-
- -**num_parts:** `int` — Number of parts to split the upload into for multipart upload +**request:** `CreateMultiPartUploadRequest`
@@ -11030,7 +10939,7 @@ client.data_directories.create_multipart_upload(
## Internal Users -
client.internal.users.get_info() -> AsyncHttpResponse[Session] +
client.internal.users.get_info() -> Session
@@ -11060,9 +10969,10 @@ Get the user session details for the currently authenticated user from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.users.get_info() ``` @@ -11092,7 +11002,7 @@ client.internal.users.get_info()
## Internal AiGateway -
client.internal.ai_gateway.get_gateway_config(...) -> AsyncHttpResponse[GatewayConfiguration] +
client.internal.ai_gateway.get_gateway_config(...) -> GatewayConfiguration
@@ -11120,14 +11030,13 @@ Get Gateway configuration based on type for the tenant. ```python from truefoundry_sdk import TrueFoundry -from truefoundry_sdk.internal.ai_gateway import ( - AiGatewayGetGatewayConfigRequestType, -) +from truefoundry_sdk.internal.ai_gateway import AiGatewayGetGatewayConfigRequestType client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.ai_gateway.get_gateway_config( type=AiGatewayGetGatewayConfigRequestType.GATEWAY_RATE_LIMITING_CONFIG, ) @@ -11167,7 +11076,7 @@ client.internal.ai_gateway.get_gateway_config(
## Internal Clusters -
client.internal.clusters.get_autoprovisioning_state(...) -> AsyncHttpResponse[GetAutoProvisioningStateResponse] +
client.internal.clusters.get_autoprovisioning_state(...) -> GetAutoProvisioningStateResponse
@@ -11197,9 +11106,10 @@ Get the auto provisioning status for the provided cluster from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.clusters.get_autoprovisioning_state( id="id", ) @@ -11239,7 +11149,7 @@ client.internal.clusters.get_autoprovisioning_state(
## Internal Deployments -
client.internal.deployments.get_deployment_statuses(...) -> AsyncHttpResponse[typing.List[DeploymentStatus]] +
client.internal.deployments.get_deployment_statuses(...) -> typing.List[DeploymentStatus]
@@ -11269,9 +11179,10 @@ This endpoint returns all statuses for a specific deployment in a given applicat from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.deployments.get_deployment_statuses( id="id", deployment_id="deploymentId", @@ -11319,7 +11230,7 @@ client.internal.deployments.get_deployment_statuses(
-
client.internal.deployments.get_builds(...) -> AsyncHttpResponse[typing.List[DeploymentBuild]] +
client.internal.deployments.get_builds(...) -> typing.List[DeploymentBuild]
@@ -11349,9 +11260,10 @@ This endpoint returns all build details associated with a specific deployment in from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.deployments.get_builds( id="id", deployment_id="deploymentId", @@ -11399,7 +11311,7 @@ client.internal.deployments.get_builds(
-
client.internal.deployments.get_code_upload_url(...) -> AsyncHttpResponse[PresignedUrlObject] +
client.internal.deployments.get_code_upload_url(...) -> PresignedUrlObject
@@ -11429,9 +11341,10 @@ Generate presigned URL to upload code for given serviceName and workspaceFqn from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.deployments.get_code_upload_url( service_name="serviceName", workspace_fqn="workspaceFqn", @@ -11479,7 +11392,7 @@ client.internal.deployments.get_code_upload_url(
-
client.internal.deployments.get_suggested_endpoint(...) -> AsyncHttpResponse[GetSuggestedDeploymentEndpointResponse] +
client.internal.deployments.get_suggested_endpoint(...) -> GetSuggestedDeploymentEndpointResponse
@@ -11506,12 +11419,13 @@ Generate deployment endpoint based on the provided query parameters.
```python -from truefoundry_sdk import ApplicationType, TrueFoundry +from truefoundry_sdk import TrueFoundry, ApplicationType client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.deployments.get_suggested_endpoint( application_type=ApplicationType.ASYNC_SERVICE, application_name="applicationName", @@ -11596,7 +11510,7 @@ client.internal.deployments.get_suggested_endpoint(
## Internal Applications -
client.internal.applications.promote_rollout(...) -> AsyncHttpResponse[None] +
client.internal.applications.promote_rollout(...)
@@ -11626,9 +11540,10 @@ Promote an application rollout for canary and blue-green. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.applications.promote_rollout( id="id", full=True, @@ -11676,7 +11591,7 @@ client.internal.applications.promote_rollout(
-
client.internal.applications.get_pod_template_hash_to_deployment_version(...) -> AsyncHttpResponse[typing.Dict[str, float]] +
client.internal.applications.get_pod_template_hash_to_deployment_version(...) -> typing.Dict[str, float]
@@ -11706,9 +11621,10 @@ This endpoint fetches the pod template hash to deployment version map for a spec from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.applications.get_pod_template_hash_to_deployment_version( id="id", pod_template_hashes="podTemplateHashes", @@ -11757,7 +11673,7 @@ client.internal.applications.get_pod_template_hash_to_deployment_version(
## Internal Metrics -
client.internal.metrics.get_charts(...) -> AsyncHttpResponse[GetChartsResponse] +
client.internal.metrics.get_charts(...) -> GetChartsResponse
@@ -11788,9 +11704,10 @@ from truefoundry_sdk import TrueFoundry from truefoundry_sdk.internal.metrics import MetricsGetChartsRequestFilterEntity client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.metrics.get_charts( workspace_id="workspaceId", application_id="applicationId", @@ -11875,7 +11792,7 @@ client.internal.metrics.get_charts(
## Internal Vcs -
client.internal.vcs.get_repository_details(...) -> AsyncHttpResponse[GitRepositoryExistsResponse] +
client.internal.vcs.get_repository_details(...) -> GitRepositoryExistsResponse
@@ -11891,9 +11808,10 @@ client.internal.metrics.get_charts( from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.vcs.get_repository_details( repo_url="repoURL", ) @@ -11940,7 +11858,7 @@ client.internal.vcs.get_repository_details(
-
client.internal.vcs.get_authenticated_url(...) -> AsyncHttpResponse[GetAuthenticatedVcsurlResponse] +
client.internal.vcs.get_authenticated_url(...) -> GetAuthenticatedVcsurlResponse
@@ -11956,9 +11874,10 @@ client.internal.vcs.get_repository_details( from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.vcs.get_authenticated_url( repo_url="repoURL", ) @@ -11998,7 +11917,7 @@ client.internal.vcs.get_authenticated_url(
## Internal DockerRegistries -
client.internal.docker_registries.create_repository(...) -> AsyncHttpResponse[CreateDockerRepositoryResponse] +
client.internal.docker_registries.create_repository(...) -> CreateDockerRepositoryResponse
@@ -12028,9 +11947,10 @@ Create a docker repository in the provided workspace. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.docker_registries.create_repository( fqn="fqn", application_name="applicationName", @@ -12087,7 +12007,7 @@ client.internal.docker_registries.create_repository(
-
client.internal.docker_registries.get_credentials(...) -> AsyncHttpResponse[GetDockerRegistryCredentialsResponse] +
client.internal.docker_registries.get_credentials(...) -> GetDockerRegistryCredentialsResponse
@@ -12117,9 +12037,10 @@ Get docker registry credentials for building and pushing an image. from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.docker_registries.get_credentials( fqn="fqn", cluster_id="clusterId", @@ -12168,7 +12089,7 @@ client.internal.docker_registries.get_credentials(
## Internal Workflows -
client.internal.workflows.execute_workflow(...) -> AsyncHttpResponse[WorkflowsExecuteWorkflowResponse] +
client.internal.workflows.execute_workflow(...) -> WorkflowsExecuteWorkflowResponse
@@ -12198,9 +12119,10 @@ Execute a workflow for the specified application from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.workflows.execute_workflow( application_id="applicationId", ) @@ -12256,7 +12178,7 @@ client.internal.workflows.execute_workflow(
## Internal BuildLogs -
client.internal.build_logs.get(...) -> AsyncHttpResponse[LogsResponse] +
client.internal.build_logs.get(...) -> LogsResponse
@@ -12286,9 +12208,10 @@ Get logs for a given pipeline run by its name, with optional filters and time ra from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.build_logs.get( pipeline_run_name="pipelineRunName", start_ts="1635467890123456789", @@ -12381,10 +12304,7 @@ client.internal.build_logs.get(
## Internal ArtifactVersions -
client.internal.artifact_versions.list(...) -> AsyncPager[ - InternalListArtifactVersionsResponseDataItem, - InternalListArtifactVersionsResponse, -] +
client.internal.artifact_versions.list(...) -> InternalListArtifactVersionsResponse
@@ -12414,10 +12334,11 @@ List artifact versions with internal metadata, optionally including model versio from truefoundry_sdk import TrueFoundry client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) -response = client.internal.artifact_versions.list( + +client.internal.artifact_versions.list( tag="tag", fqn="fqn", artifact_id="artifact_id", @@ -12429,11 +12350,6 @@ response = client.internal.artifact_versions.list( include_internal_metadata=True, include_model_versions=True, ) -for item in response: - yield item -# alternatively, you can paginate page-by-page -for page in response.iter_pages(): - yield page ```
@@ -12558,7 +12474,7 @@ for page in response.iter_pages():
## Internal Ml -
client.internal.ml.apply(...) -> AsyncHttpResponse[ApplyMlEntityResponse] +
client.internal.ml.apply(...) -> ApplyMlEntityResponse
@@ -12585,18 +12501,24 @@ Create or update an ML entity (model, prompt, artifact, or data directory).
```python -from truefoundry_sdk import ModelManifest, TrueFoundry, TrueFoundryManagedSource +from truefoundry_sdk import TrueFoundry, ModelManifest, TrueFoundryManagedSource client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.ml.apply( manifest=ModelManifest( name="name", - metadata={"key": "value"}, + metadata={ + "key": "value" + }, ml_repo="ml_repo", - source=TrueFoundryManagedSource(), + type="model-version", + source=TrueFoundryManagedSource( + type="truefoundry", + ), ), ) @@ -12634,7 +12556,7 @@ client.internal.ml.apply(
-
client.internal.ml.delete(...) -> AsyncHttpResponse[EmptyResponse] +
client.internal.ml.delete(...) -> EmptyResponse
@@ -12661,18 +12583,24 @@ Delete an ML entity (model, prompt, artifact, agent skill, data directory, or ML
```python -from truefoundry_sdk import ModelManifest, TrueFoundry, TrueFoundryManagedSource +from truefoundry_sdk import TrueFoundry, ModelManifest, TrueFoundryManagedSource client = TrueFoundry( - api_key="YOUR_API_KEY", + api_key="", base_url="https://yourhost.com/path/to/api", ) + client.internal.ml.delete( manifest=ModelManifest( name="name", - metadata={"key": "value"}, + metadata={ + "key": "value" + }, ml_repo="ml_repo", - source=TrueFoundryManagedSource(), + type="model-version", + source=TrueFoundryManagedSource( + type="truefoundry", + ), ), ) diff --git a/requirements.txt b/requirements.txt index e80f640a..0141a1a5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ httpx>=0.21.2 pydantic>= 1.9.2 -pydantic-core>=2.18.2 +pydantic-core>=2.18.2,<2.44.0 typing_extensions>= 4.0.0 diff --git a/src/truefoundry_sdk/__init__.py b/src/truefoundry_sdk/__init__.py index aeac82ad..0a841cb6 100644 --- a/src/truefoundry_sdk/__init__.py +++ b/src/truefoundry_sdk/__init__.py @@ -1063,6 +1063,7 @@ virtual_accounts, workspaces, ) + from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient from .applications import ( ApplicationsCancelDeploymentResponse, ApplicationsListRequestDeviceTypeFilter, @@ -1344,6 +1345,8 @@ "DeepinfraKeyAuth": ".types", "DeepinfraModel": ".types", "DeepinfraProviderAccount": ".types", + "DefaultAioHttpClient": "._default_clients", + "DefaultAsyncHttpxClient": "._default_clients", "DeleteApplicationResponse": ".types", "DeleteJobRunResponse": ".types", "DeletePersonalAccessTokenResponse": ".types", @@ -2432,6 +2435,8 @@ def __dir__(): "DeepinfraKeyAuth", "DeepinfraModel", "DeepinfraProviderAccount", + "DefaultAioHttpClient", + "DefaultAsyncHttpxClient", "DeleteApplicationResponse", "DeleteJobRunResponse", "DeletePersonalAccessTokenResponse", diff --git a/src/truefoundry_sdk/_default_clients.py b/src/truefoundry_sdk/_default_clients.py new file mode 100644 index 00000000..84661579 --- /dev/null +++ b/src/truefoundry_sdk/_default_clients.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import httpx + +SDK_DEFAULT_TIMEOUT = 60 + +try: + import httpx_aiohttp # type: ignore[import-not-found] +except ImportError: + + class DefaultAioHttpClient(httpx.AsyncClient): # type: ignore + def __init__(self, **kwargs: typing.Any) -> None: + raise RuntimeError( + "To use the aiohttp client, install the aiohttp extra: pip install truefoundry-sdk[aiohttp]" + ) + +else: + + class DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore + def __init__(self, **kwargs: typing.Any) -> None: + kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT) + kwargs.setdefault("follow_redirects", True) + super().__init__(**kwargs) + + +class DefaultAsyncHttpxClient(httpx.AsyncClient): + def __init__(self, **kwargs: typing.Any) -> None: + kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT) + kwargs.setdefault("follow_redirects", True) + super().__init__(**kwargs) diff --git a/src/truefoundry_sdk/agent_skill_versions/raw_client.py b/src/truefoundry_sdk/agent_skill_versions/raw_client.py index ba63cb55..6370de14 100644 --- a/src/truefoundry_sdk/agent_skill_versions/raw_client.py +++ b/src/truefoundry_sdk/agent_skill_versions/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.unprocessable_entity_error import UnprocessableEntityError @@ -15,6 +16,7 @@ from ..types.empty_response import EmptyResponse from ..types.get_agent_skill_version_response import GetAgentSkillVersionResponse from ..types.list_agent_skill_versions_response import ListAgentSkillVersionsResponse +from pydantic import ValidationError class RawAgentSkillVersionsClient: @@ -38,7 +40,7 @@ def get( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skill-versions/{jsonable_encoder(agent_skill_version_id)}", + f"api/ml/v1/agent-skill-versions/{encode_path_param(agent_skill_version_id)}", method="GET", request_options=request_options, ) @@ -66,6 +68,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -85,7 +91,7 @@ def delete( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skill-versions/{jsonable_encoder(agent_skill_version_id)}", + f"api/ml/v1/agent-skill-versions/{encode_path_param(agent_skill_version_id)}", method="DELETE", request_options=request_options, ) @@ -113,6 +119,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -213,6 +223,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -237,7 +251,7 @@ async def get( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skill-versions/{jsonable_encoder(agent_skill_version_id)}", + f"api/ml/v1/agent-skill-versions/{encode_path_param(agent_skill_version_id)}", method="GET", request_options=request_options, ) @@ -265,6 +279,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -284,7 +302,7 @@ async def delete( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skill-versions/{jsonable_encoder(agent_skill_version_id)}", + f"api/ml/v1/agent-skill-versions/{encode_path_param(agent_skill_version_id)}", method="DELETE", request_options=request_options, ) @@ -312,6 +330,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -415,4 +437,8 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/agent_skills/raw_client.py b/src/truefoundry_sdk/agent_skills/raw_client.py index 48545bf3..b5e7b7df 100644 --- a/src/truefoundry_sdk/agent_skills/raw_client.py +++ b/src/truefoundry_sdk/agent_skills/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -18,6 +19,7 @@ from ..types.get_agent_skill_response import GetAgentSkillResponse from ..types.get_agent_skill_version_response import GetAgentSkillVersionResponse from ..types.list_agent_skills_response import ListAgentSkillsResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -46,7 +48,7 @@ def get( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skills/{jsonable_encoder(agent_skill_id)}", + f"api/ml/v1/agent-skills/{encode_path_param(agent_skill_id)}", method="GET", request_options=request_options, ) @@ -74,6 +76,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -95,7 +101,7 @@ def delete( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skills/{jsonable_encoder(agent_skill_id)}", + f"api/ml/v1/agent-skills/{encode_path_param(agent_skill_id)}", method="DELETE", request_options=request_options, ) @@ -123,6 +129,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -217,6 +227,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -276,6 +290,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -302,7 +320,7 @@ async def get( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skills/{jsonable_encoder(agent_skill_id)}", + f"api/ml/v1/agent-skills/{encode_path_param(agent_skill_id)}", method="GET", request_options=request_options, ) @@ -330,6 +348,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -351,7 +373,7 @@ async def delete( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/agent-skills/{jsonable_encoder(agent_skill_id)}", + f"api/ml/v1/agent-skills/{encode_path_param(agent_skill_id)}", method="DELETE", request_options=request_options, ) @@ -379,6 +401,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -476,6 +502,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -535,4 +565,8 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/alerts/raw_client.py b/src/truefoundry_sdk/alerts/raw_client.py index 430342fe..565af1a0 100644 --- a/src/truefoundry_sdk/alerts/raw_client.py +++ b/src/truefoundry_sdk/alerts/raw_client.py @@ -6,6 +6,7 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError @@ -13,6 +14,7 @@ from ..types.alert_status import AlertStatus from ..types.get_alerts_response import GetAlertsResponse from ..types.http_error import HttpError +from pydantic import ValidationError class RawAlertsClient: @@ -104,6 +106,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -196,4 +202,8 @@ async def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/application_versions/raw_client.py b/src/truefoundry_sdk/application_versions/raw_client.py index fb685a39..08b9cd2b 100644 --- a/src/truefoundry_sdk/application_versions/raw_client.py +++ b/src/truefoundry_sdk/application_versions/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.forbidden_error import ForbiddenError @@ -16,6 +17,7 @@ from ..types.get_application_deployment_response import GetApplicationDeploymentResponse from ..types.http_error import HttpError from ..types.list_application_deployments_response import ListApplicationDeploymentsResponse +from pydantic import ValidationError class RawApplicationVersionsClient: @@ -63,7 +65,7 @@ def list( offset = offset if offset is not None else 0 _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments", method="GET", params={ "limit": limit, @@ -118,6 +120,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -143,7 +149,7 @@ def get( Deployment details returned successfully. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}", method="GET", request_options=request_options, ) @@ -182,6 +188,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -230,7 +240,7 @@ async def list( offset = offset if offset is not None else 0 _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments", method="GET", params={ "limit": limit, @@ -288,6 +298,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -313,7 +327,7 @@ async def get( Deployment details returned successfully. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}", method="GET", request_options=request_options, ) @@ -352,4 +366,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/applications/raw_client.py b/src/truefoundry_sdk/applications/raw_client.py index 49f9dd55..6670d196 100644 --- a/src/truefoundry_sdk/applications/raw_client.py +++ b/src/truefoundry_sdk/applications/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError @@ -26,6 +27,7 @@ from .types.applications_cancel_deployment_response import ApplicationsCancelDeploymentResponse from .types.applications_list_request_device_type_filter import ApplicationsListRequestDeviceTypeFilter from .types.applications_list_request_lifecycle_stage import ApplicationsListRequestLifecycleStage +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -193,6 +195,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -324,6 +330,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -346,7 +356,7 @@ def get( Application details retrieved successfully """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}", + f"api/svc/v1/apps/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -385,6 +395,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -407,7 +421,7 @@ def delete( Delete application response. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}", + f"api/svc/v1/apps/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -446,6 +460,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def redeploy( @@ -471,7 +489,7 @@ def redeploy( Returns the new deployment. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/redeploy", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/redeploy", method="POST", request_options=request_options, ) @@ -510,6 +528,10 @@ def redeploy( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def scale_to_zero(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]: @@ -529,7 +551,7 @@ def scale_to_zero(self, id: str, *, request_options: typing.Optional[RequestOpti HttpResponse[None] """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/scale-to-zero", + f"api/svc/v1/apps/{encode_path_param(id)}/scale-to-zero", method="PATCH", request_options=request_options, ) @@ -583,6 +605,10 @@ def scale_to_zero(self, id: str, *, request_options: typing.Optional[RequestOpti _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def scale_to_original( @@ -605,7 +631,7 @@ def scale_to_original( Scales back a paused applicaion to the original number of replicas """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/scale-to-original", + f"api/svc/v1/apps/{encode_path_param(id)}/scale-to-original", method="PATCH", request_options=request_options, ) @@ -655,6 +681,10 @@ def scale_to_original( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def cancel_deployment( @@ -680,7 +710,7 @@ def cancel_deployment( Deployment cancelled successfully. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/cancel", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/cancel", method="POST", request_options=request_options, ) @@ -730,6 +760,10 @@ def cancel_deployment( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -898,6 +932,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -1029,6 +1067,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -1051,7 +1093,7 @@ async def get( Application details retrieved successfully """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}", + f"api/svc/v1/apps/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -1090,6 +1132,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -1112,7 +1158,7 @@ async def delete( Delete application response. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}", + f"api/svc/v1/apps/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -1151,6 +1197,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def redeploy( @@ -1176,7 +1226,7 @@ async def redeploy( Returns the new deployment. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/redeploy", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/redeploy", method="POST", request_options=request_options, ) @@ -1215,6 +1265,10 @@ async def redeploy( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def scale_to_zero( @@ -1236,7 +1290,7 @@ async def scale_to_zero( AsyncHttpResponse[None] """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/scale-to-zero", + f"api/svc/v1/apps/{encode_path_param(id)}/scale-to-zero", method="PATCH", request_options=request_options, ) @@ -1290,6 +1344,10 @@ async def scale_to_zero( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def scale_to_original( @@ -1312,7 +1370,7 @@ async def scale_to_original( Scales back a paused applicaion to the original number of replicas """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/scale-to-original", + f"api/svc/v1/apps/{encode_path_param(id)}/scale-to-original", method="PATCH", request_options=request_options, ) @@ -1362,6 +1420,10 @@ async def scale_to_original( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def cancel_deployment( @@ -1387,7 +1449,7 @@ async def cancel_deployment( Deployment cancelled successfully. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/cancel", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/cancel", method="POST", request_options=request_options, ) @@ -1437,4 +1499,8 @@ async def cancel_deployment( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/artifact_versions/raw_client.py b/src/truefoundry_sdk/artifact_versions/raw_client.py index c8157acd..b0814c3d 100644 --- a/src/truefoundry_sdk/artifact_versions/raw_client.py +++ b/src/truefoundry_sdk/artifact_versions/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -23,6 +24,7 @@ from ..types.operation import Operation from ..types.stage_artifact_response import StageArtifactResponse from .types.stage_artifact_request_manifest import StageArtifactRequestManifest +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -100,6 +102,10 @@ def apply_tags( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -121,7 +127,7 @@ def get( The artifact version data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifact-versions/{jsonable_encoder(id)}", + f"api/ml/v1/artifact-versions/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -149,6 +155,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -170,7 +180,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifact-versions/{jsonable_encoder(id)}", + f"api/ml/v1/artifact-versions/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -198,6 +208,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -322,6 +336,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_signed_urls( @@ -392,6 +410,10 @@ def get_signed_urls( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_multi_part_upload( @@ -457,6 +479,10 @@ def create_multi_part_upload( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def stage( @@ -516,6 +542,10 @@ def stage( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list_files( @@ -604,6 +634,10 @@ def list_files( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def mark_stage_failure( @@ -661,6 +695,10 @@ def mark_stage_failure( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -736,6 +774,10 @@ async def apply_tags( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -757,7 +799,7 @@ async def get( The artifact version data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifact-versions/{jsonable_encoder(id)}", + f"api/ml/v1/artifact-versions/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -785,6 +827,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -806,7 +852,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifact-versions/{jsonable_encoder(id)}", + f"api/ml/v1/artifact-versions/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -834,6 +880,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -961,6 +1011,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_signed_urls( @@ -1031,6 +1085,10 @@ async def get_signed_urls( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_multi_part_upload( @@ -1096,6 +1154,10 @@ async def create_multi_part_upload( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def stage( @@ -1155,6 +1217,10 @@ async def stage( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list_files( @@ -1246,6 +1312,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def mark_stage_failure( @@ -1303,4 +1373,8 @@ async def mark_stage_failure( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/artifacts/raw_client.py b/src/truefoundry_sdk/artifacts/raw_client.py index 94f02f9e..bf64b13b 100644 --- a/src/truefoundry_sdk/artifacts/raw_client.py +++ b/src/truefoundry_sdk/artifacts/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -18,6 +19,7 @@ from ..types.get_artifact_response import GetArtifactResponse from ..types.get_artifact_version_response import GetArtifactVersionResponse from ..types.list_artifacts_response import ListArtifactsResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -46,7 +48,7 @@ def get( The artifact data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifacts/{jsonable_encoder(id)}", + f"api/ml/v1/artifacts/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -74,6 +76,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -95,7 +101,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifacts/{jsonable_encoder(id)}", + f"api/ml/v1/artifacts/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -123,6 +129,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -223,6 +233,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -282,6 +296,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -308,7 +326,7 @@ async def get( The artifact data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifacts/{jsonable_encoder(id)}", + f"api/ml/v1/artifacts/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -336,6 +354,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -357,7 +379,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/artifacts/{jsonable_encoder(id)}", + f"api/ml/v1/artifacts/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -385,6 +407,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -488,6 +514,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -547,4 +577,8 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/base_client.py b/src/truefoundry_sdk/base_client.py index cf825ea8..38cfd5b6 100644 --- a/src/truefoundry_sdk/base_client.py +++ b/src/truefoundry_sdk/base_client.py @@ -8,6 +8,7 @@ import httpx from .core.api_error import ApiError from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .core.logging import LogConfig, Logger from .core.request_options import RequestOptions from .raw_base_client import AsyncRawBaseTrueFoundry, RawBaseTrueFoundry from .types.true_foundry_apply_request_manifest import TrueFoundryApplyRequestManifest @@ -68,6 +69,9 @@ class BaseTrueFoundry: httpx_client : typing.Optional[httpx.Client] The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + logging : typing.Optional[typing.Union[LogConfig, Logger]] + Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance. + Examples -------- from truefoundry_sdk import TrueFoundry @@ -87,6 +91,7 @@ def __init__( timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.Client] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): _defaulted_timeout = ( timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read @@ -103,6 +108,7 @@ def __init__( if follow_redirects is not None else httpx.Client(timeout=_defaulted_timeout), timeout=_defaulted_timeout, + logging=logging, ) self._raw_client = RawBaseTrueFoundry(client_wrapper=self._client_wrapper) self._internal: typing.Optional[InternalClient] = None @@ -453,6 +459,24 @@ def data_directories(self): return self._data_directories +def _make_default_async_client( + timeout: typing.Optional[float], + follow_redirects: typing.Optional[bool], +) -> httpx.AsyncClient: + try: + import httpx_aiohttp # type: ignore[import-not-found] + except ImportError: + pass + else: + if follow_redirects is not None: + return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout, follow_redirects=follow_redirects) + return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout) + + if follow_redirects is not None: + return httpx.AsyncClient(timeout=timeout, follow_redirects=follow_redirects) + return httpx.AsyncClient(timeout=timeout) + + class AsyncBaseTrueFoundry: """ Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. @@ -466,6 +490,9 @@ class AsyncBaseTrueFoundry: headers : typing.Optional[typing.Dict[str, str]] Additional headers to send with every request. + async_token : typing.Optional[typing.Callable[[], typing.Awaitable[str]]] + An async callable that returns a bearer token. Use this when token acquisition involves async I/O (e.g., refreshing tokens via an async HTTP client). When provided, this is used instead of the synchronous token for async requests. + timeout : typing.Optional[float] The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. @@ -475,6 +502,9 @@ class AsyncBaseTrueFoundry: httpx_client : typing.Optional[httpx.AsyncClient] The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + logging : typing.Optional[typing.Union[LogConfig, Logger]] + Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance. + Examples -------- from truefoundry_sdk import AsyncTrueFoundry @@ -491,9 +521,11 @@ def __init__( base_url: str, api_key: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = os.getenv("TFY_API_KEY"), headers: typing.Optional[typing.Dict[str, str]] = None, + async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None, timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.AsyncClient] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): _defaulted_timeout = ( timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read @@ -504,12 +536,12 @@ def __init__( base_url=base_url, api_key=api_key, headers=headers, + async_token=async_token, httpx_client=httpx_client if httpx_client is not None - else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects) - if follow_redirects is not None - else httpx.AsyncClient(timeout=_defaulted_timeout), + else _make_default_async_client(timeout=_defaulted_timeout, follow_redirects=follow_redirects), timeout=_defaulted_timeout, + logging=logging, ) self._raw_client = AsyncRawBaseTrueFoundry(client_wrapper=self._client_wrapper) self._internal: typing.Optional[AsyncInternalClient] = None diff --git a/src/truefoundry_sdk/clusters/raw_client.py b/src/truefoundry_sdk/clusters/raw_client.py index d549625c..d346f744 100644 --- a/src/truefoundry_sdk/clusters/raw_client.py +++ b/src/truefoundry_sdk/clusters/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -23,6 +24,7 @@ from ..types.list_cluster_addons_response import ListClusterAddonsResponse from ..types.list_clusters_response import ListClustersResponse from .types.clusters_delete_response import ClustersDeleteResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -100,6 +102,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -189,6 +195,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -211,7 +221,7 @@ def get( Return the cluster associated with provided id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}", + f"api/svc/v1/clusters/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -250,6 +260,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -272,7 +286,7 @@ def delete( Returns success message on successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}", + f"api/svc/v1/clusters/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -311,6 +325,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_addons( @@ -344,7 +362,7 @@ def get_addons( Returns a paginated list of addons for the cluster """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}/get-addons", + f"api/svc/v1/clusters/{encode_path_param(id)}/get-addons", method="GET", params={ "limit": limit, @@ -387,6 +405,10 @@ def get_addons( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def is_connected( @@ -409,7 +431,7 @@ def is_connected( Returns the status of provided cluster """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}/is-connected", + f"api/svc/v1/clusters/{encode_path_param(id)}/is-connected", method="GET", request_options=request_options, ) @@ -437,6 +459,10 @@ def is_connected( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -515,6 +541,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -604,6 +634,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -626,7 +660,7 @@ async def get( Return the cluster associated with provided id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}", + f"api/svc/v1/clusters/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -665,6 +699,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -687,7 +725,7 @@ async def delete( Returns success message on successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}", + f"api/svc/v1/clusters/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -726,6 +764,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_addons( @@ -759,7 +801,7 @@ async def get_addons( Returns a paginated list of addons for the cluster """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}/get-addons", + f"api/svc/v1/clusters/{encode_path_param(id)}/get-addons", method="GET", params={ "limit": limit, @@ -802,6 +844,10 @@ async def get_addons( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def is_connected( @@ -824,7 +870,7 @@ async def is_connected( Returns the status of provided cluster """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}/is-connected", + f"api/svc/v1/clusters/{encode_path_param(id)}/is-connected", method="GET", request_options=request_options, ) @@ -852,4 +898,8 @@ async def is_connected( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/core/__init__.py b/src/truefoundry_sdk/core/__init__.py index 3b5240ad..e2be580f 100644 --- a/src/truefoundry_sdk/core/__init__.py +++ b/src/truefoundry_sdk/core/__init__.py @@ -8,13 +8,14 @@ if typing.TYPE_CHECKING: from .api_error import ApiError from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper - from .custom_pagination import AsyncCustomPager, SyncCustomPager - from .datetime_utils import serialize_datetime + from .datetime_utils import Rfc2822DateTime, parse_rfc2822_datetime, serialize_datetime from .file import File, convert_file_dict_to_httpx_tuples, with_content_type from .http_client import AsyncHttpClient, HttpClient from .http_response import AsyncHttpResponse, HttpResponse - from .jsonable_encoder import jsonable_encoder + from .jsonable_encoder import encode_path_param, jsonable_encoder + from .logging import ConsoleLogger, ILogger, LogConfig, LogLevel, Logger, create_logger from .pagination import AsyncPager, SyncPager + from .parse_error import ParsingError from .pydantic_utilities import ( IS_PYDANTIC_V2, UniversalBaseModel, @@ -31,27 +32,35 @@ _dynamic_imports: typing.Dict[str, str] = { "ApiError": ".api_error", "AsyncClientWrapper": ".client_wrapper", - "AsyncCustomPager": ".custom_pagination", "AsyncHttpClient": ".http_client", "AsyncHttpResponse": ".http_response", "AsyncPager": ".pagination", "BaseClientWrapper": ".client_wrapper", + "ConsoleLogger": ".logging", "FieldMetadata": ".serialization", "File": ".file", "HttpClient": ".http_client", "HttpResponse": ".http_response", + "ILogger": ".logging", "IS_PYDANTIC_V2": ".pydantic_utilities", + "LogConfig": ".logging", + "LogLevel": ".logging", + "Logger": ".logging", + "ParsingError": ".parse_error", "RequestOptions": ".request_options", + "Rfc2822DateTime": ".datetime_utils", "SyncClientWrapper": ".client_wrapper", - "SyncCustomPager": ".custom_pagination", "SyncPager": ".pagination", "UniversalBaseModel": ".pydantic_utilities", "UniversalRootModel": ".pydantic_utilities", "convert_and_respect_annotation_metadata": ".serialization", "convert_file_dict_to_httpx_tuples": ".file", + "create_logger": ".logging", + "encode_path_param": ".jsonable_encoder", "encode_query": ".query_encoder", "jsonable_encoder": ".jsonable_encoder", "parse_obj_as": ".pydantic_utilities", + "parse_rfc2822_datetime": ".datetime_utils", "remove_none_from_dict": ".remove_none_from_dict", "serialize_datetime": ".datetime_utils", "universal_field_validator": ".pydantic_utilities", @@ -85,27 +94,35 @@ def __dir__(): __all__ = [ "ApiError", "AsyncClientWrapper", - "AsyncCustomPager", "AsyncHttpClient", "AsyncHttpResponse", "AsyncPager", "BaseClientWrapper", + "ConsoleLogger", "FieldMetadata", "File", "HttpClient", "HttpResponse", + "ILogger", "IS_PYDANTIC_V2", + "LogConfig", + "LogLevel", + "Logger", + "ParsingError", "RequestOptions", + "Rfc2822DateTime", "SyncClientWrapper", - "SyncCustomPager", "SyncPager", "UniversalBaseModel", "UniversalRootModel", "convert_and_respect_annotation_metadata", "convert_file_dict_to_httpx_tuples", + "create_logger", + "encode_path_param", "encode_query", "jsonable_encoder", "parse_obj_as", + "parse_rfc2822_datetime", "remove_none_from_dict", "serialize_datetime", "universal_field_validator", diff --git a/src/truefoundry_sdk/core/client_wrapper.py b/src/truefoundry_sdk/core/client_wrapper.py index 18d1f335..9cc2e02f 100644 --- a/src/truefoundry_sdk/core/client_wrapper.py +++ b/src/truefoundry_sdk/core/client_wrapper.py @@ -4,6 +4,7 @@ import httpx from .http_client import AsyncHttpClient, HttpClient +from .logging import LogConfig, Logger class BaseClientWrapper: @@ -14,11 +15,13 @@ def __init__( headers: typing.Optional[typing.Dict[str, str]] = None, base_url: str, timeout: typing.Optional[float] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self._api_key = api_key self._headers = headers self._base_url = base_url self._timeout = timeout + self._logging = logging def get_headers(self) -> typing.Dict[str, str]: import platform @@ -59,14 +62,16 @@ def __init__( headers: typing.Optional[typing.Dict[str, str]] = None, base_url: str, timeout: typing.Optional[float] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, httpx_client: httpx.Client, ): - super().__init__(api_key=api_key, headers=headers, base_url=base_url, timeout=timeout) + super().__init__(api_key=api_key, headers=headers, base_url=base_url, timeout=timeout, logging=logging) self.httpx_client = HttpClient( httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout, base_url=self.get_base_url, + logging_config=self._logging, ) @@ -78,10 +83,11 @@ def __init__( headers: typing.Optional[typing.Dict[str, str]] = None, base_url: str, timeout: typing.Optional[float] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None, httpx_client: httpx.AsyncClient, ): - super().__init__(api_key=api_key, headers=headers, base_url=base_url, timeout=timeout) + super().__init__(api_key=api_key, headers=headers, base_url=base_url, timeout=timeout, logging=logging) self._async_token = async_token self.httpx_client = AsyncHttpClient( httpx_client=httpx_client, @@ -89,6 +95,7 @@ def __init__( base_timeout=self.get_timeout, base_url=self.get_base_url, async_base_headers=self.async_get_headers, + logging_config=self._logging, ) async def async_get_headers(self) -> typing.Dict[str, str]: diff --git a/src/truefoundry_sdk/core/custom_pagination.py b/src/truefoundry_sdk/core/custom_pagination.py deleted file mode 100644 index 5de2c7a8..00000000 --- a/src/truefoundry_sdk/core/custom_pagination.py +++ /dev/null @@ -1,152 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -""" -Custom Pagination Support - -This file is designed to be modified by SDK users to implement their own -pagination logic. The generator will import SyncCustomPager and AsyncCustomPager -from this module when custom pagination is used. - -Users should: -1. Implement their custom pager (e.g., PayrocPager, MyCustomPager, etc.) -2. Create adapter classes (SyncCustomPager/AsyncCustomPager) that bridge - between the generated SDK code and their custom pager implementation -""" - -from __future__ import annotations - -from typing import Any, AsyncIterator, Generic, Iterator, TypeVar - -# Import the base utilities you'll need -# Adjust these imports based on your actual structure -try: - from .client_wrapper import AsyncClientWrapper, SyncClientWrapper -except ImportError: - # Fallback for type hints - AsyncClientWrapper = Any # type: ignore - SyncClientWrapper = Any # type: ignore - -TItem = TypeVar("TItem") -TResponse = TypeVar("TResponse") - - -class SyncCustomPager(Generic[TItem, TResponse]): - """ - Adapter for custom synchronous pagination. - - The generator will call this with: - SyncCustomPager(initial_response=response, client_wrapper=client_wrapper) - - Implement this class to extract pagination metadata from your response - and delegate to your custom pager implementation. - - Example implementation: - - class SyncCustomPager(Generic[TItem, TResponse]): - def __init__( - self, - *, - initial_response: TResponse, - client_wrapper: SyncClientWrapper, - ): - # Extract data and pagination metadata from response - data = initial_response.data # Adjust based on your response structure - links = initial_response.links - - # Initialize your custom pager - self._pager = MyCustomPager( - current_page=Page(data), - httpx_client=client_wrapper.httpx_client, - get_headers=client_wrapper.get_headers, - # ... other parameters - ) - - def __iter__(self): - return iter(self._pager) - - # Delegate other methods to your pager... - """ - - def __init__( - self, - *, - initial_response: TResponse, - client_wrapper: SyncClientWrapper, - ): - """ - Initialize the custom pager. - - Args: - initial_response: The parsed API response from the first request - client_wrapper: The client wrapper providing HTTP client and utilities - """ - raise NotImplementedError( - "SyncCustomPager must be implemented. " - "Please implement this class in core/custom_pagination.py to define your pagination logic. " - "See the class docstring for examples." - ) - - def __iter__(self) -> Iterator[TItem]: - """Iterate through all items across all pages.""" - raise NotImplementedError("Must implement __iter__ method") - - -class AsyncCustomPager(Generic[TItem, TResponse]): - """ - Adapter for custom asynchronous pagination. - - The generator will call this with: - AsyncCustomPager(initial_response=response, client_wrapper=client_wrapper) - - Implement this class to extract pagination metadata from your response - and delegate to your custom async pager implementation. - - Example implementation: - - class AsyncCustomPager(Generic[TItem, TResponse]): - def __init__( - self, - *, - initial_response: TResponse, - client_wrapper: AsyncClientWrapper, - ): - # Extract data and pagination metadata from response - data = initial_response.data # Adjust based on your response structure - links = initial_response.links - - # Initialize your custom async pager - self._pager = MyAsyncCustomPager( - current_page=Page(data), - httpx_client=client_wrapper.httpx_client, - get_headers=client_wrapper.get_headers, - # ... other parameters - ) - - async def __aiter__(self): - return self._pager.__aiter__() - - # Delegate other methods to your pager... - """ - - def __init__( - self, - *, - initial_response: TResponse, - client_wrapper: AsyncClientWrapper, - ): - """ - Initialize the custom async pager. - - Args: - initial_response: The parsed API response from the first request - client_wrapper: The client wrapper providing HTTP client and utilities - """ - raise NotImplementedError( - "AsyncCustomPager must be implemented. " - "Please implement this class in core/custom_pagination.py to define your pagination logic. " - "See the class docstring for examples." - ) - - async def __aiter__(self) -> AsyncIterator[TItem]: - """Asynchronously iterate through all items across all pages.""" - raise NotImplementedError("Must implement __aiter__ method") diff --git a/src/truefoundry_sdk/core/datetime_utils.py b/src/truefoundry_sdk/core/datetime_utils.py index 7c9864a9..a12b2ad0 100644 --- a/src/truefoundry_sdk/core/datetime_utils.py +++ b/src/truefoundry_sdk/core/datetime_utils.py @@ -1,6 +1,48 @@ # This file was auto-generated by Fern from our API Definition. import datetime as dt +from email.utils import parsedate_to_datetime +from typing import Any + +import pydantic + +IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") + + +def parse_rfc2822_datetime(v: Any) -> dt.datetime: + """ + Parse an RFC 2822 datetime string (e.g., "Wed, 02 Oct 2002 13:00:00 GMT") + into a datetime object. If the value is already a datetime, return it as-is. + Falls back to ISO 8601 parsing if RFC 2822 parsing fails. + """ + if isinstance(v, dt.datetime): + return v + if isinstance(v, str): + try: + return parsedate_to_datetime(v) + except Exception: + pass + # Fallback to ISO 8601 parsing + return dt.datetime.fromisoformat(v.replace("Z", "+00:00")) + raise ValueError(f"Expected str or datetime, got {type(v)}") + + +class Rfc2822DateTime(dt.datetime): + """A datetime subclass that parses RFC 2822 date strings. + + On Pydantic V1, uses __get_validators__ for pre-validation. + On Pydantic V2, uses __get_pydantic_core_schema__ for BeforeValidator-style parsing. + """ + + @classmethod + def __get_validators__(cls): # type: ignore[no-untyped-def] + yield parse_rfc2822_datetime + + @classmethod + def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> Any: # type: ignore[override] + from pydantic_core import core_schema + + return core_schema.no_info_before_validator_function(parse_rfc2822_datetime, core_schema.datetime_schema()) def serialize_datetime(v: dt.datetime) -> str: diff --git a/src/truefoundry_sdk/core/http_client.py b/src/truefoundry_sdk/core/http_client.py index 7c6c936f..f0a39ca8 100644 --- a/src/truefoundry_sdk/core/http_client.py +++ b/src/truefoundry_sdk/core/http_client.py @@ -12,6 +12,7 @@ from .file import File, convert_file_dict_to_httpx_tuples from .force_multipart import FORCE_MULTIPART from .jsonable_encoder import jsonable_encoder +from .logging import LogConfig, Logger, create_logger from .query_encoder import encode_query from .remove_none_from_dict import remove_none_from_dict as remove_none_from_dict from .request_options import RequestOptions @@ -117,11 +118,43 @@ def _retry_timeout(response: httpx.Response, retries: int) -> float: return _add_symmetric_jitter(backoff) +def _retry_timeout_from_retries(retries: int) -> float: + """Determine retry timeout using exponential backoff when no response is available.""" + backoff = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS) + return _add_symmetric_jitter(backoff) + + def _should_retry(response: httpx.Response) -> bool: retryable_400s = [429, 408, 409] return response.status_code >= 500 or response.status_code in retryable_400s +_SENSITIVE_HEADERS = frozenset( + { + "authorization", + "www-authenticate", + "x-api-key", + "api-key", + "apikey", + "x-api-token", + "x-auth-token", + "auth-token", + "cookie", + "set-cookie", + "proxy-authorization", + "proxy-authenticate", + "x-csrf-token", + "x-xsrf-token", + "x-session-token", + "x-access-token", + } +) + + +def _redact_headers(headers: typing.Dict[str, str]) -> typing.Dict[str, str]: + return {k: ("[REDACTED]" if k.lower() in _SENSITIVE_HEADERS else v) for k, v in headers.items()} + + def _build_url(base_url: str, path: typing.Optional[str]) -> str: """ Build a full URL by joining a base URL with a path. @@ -238,11 +271,15 @@ def __init__( base_timeout: typing.Callable[[], typing.Optional[float]], base_headers: typing.Callable[[], typing.Dict[str, str]], base_url: typing.Optional[typing.Callable[[], str]] = None, + base_max_retries: int = 2, + logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self.base_url = base_url self.base_timeout = base_timeout self.base_headers = base_headers + self.base_max_retries = base_max_retries self.httpx_client = httpx_client + self.logger = create_logger(logging_config) def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: base_url = maybe_base_url @@ -315,27 +352,64 @@ def request( ) ) - response = self.httpx_client.request( - method=method, - url=_build_url(base_url, path), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self.base_headers(), - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), - } - ) - ), - params=_encoded_params if _encoded_params else None, - json=json_body, - data=data_body, - content=content, - files=request_files, - timeout=timeout, + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) ) - max_retries: int = request_options.get("max_retries", 2) if request_options is not None else 2 + if self.logger.is_debug(): + self.logger.debug( + "Making HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + has_body=json_body is not None or data_body is not None, + ) + + max_retries: int = ( + request_options.get("max_retries", self.base_max_retries) + if request_options is not None + else self.base_max_retries + ) + + try: + response = self.httpx_client.request( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + except (httpx.ConnectError, httpx.RemoteProtocolError): + if retries < max_retries: + time.sleep(_retry_timeout_from_retries(retries=retries)) + return self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + data=data, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + force_multipart=force_multipart, + ) + raise + if _should_retry(response=response): if retries < max_retries: time.sleep(_retry_timeout(response=response, retries=retries)) @@ -345,12 +419,32 @@ def request( base_url=base_url, params=params, json=json, + data=data, content=content, files=files, headers=headers, request_options=request_options, retries=retries + 1, omit=omit, + force_multipart=force_multipart, + ) + + if self.logger.is_debug(): + if 200 <= response.status_code < 400: + self.logger.debug( + "HTTP request succeeded", + method=method, + url=_request_url, + status_code=response.status_code, + ) + + if self.logger.is_error(): + if response.status_code >= 400: + self.logger.error( + "HTTP request failed with error status", + method=method, + url=_request_url, + status_code=response.status_code, ) return response @@ -418,18 +512,29 @@ def stream( ) ) + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ) + + if self.logger.is_debug(): + self.logger.debug( + "Making streaming HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + ) + with self.httpx_client.stream( method=method, - url=_build_url(base_url, path), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self.base_headers(), - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), + url=_request_url, + headers=_request_headers, params=_encoded_params if _encoded_params else None, json=json_body, data=data_body, @@ -448,13 +553,17 @@ def __init__( base_timeout: typing.Callable[[], typing.Optional[float]], base_headers: typing.Callable[[], typing.Dict[str, str]], base_url: typing.Optional[typing.Callable[[], str]] = None, + base_max_retries: int = 2, async_base_headers: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Dict[str, str]]]] = None, + logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self.base_url = base_url self.base_timeout = base_timeout self.base_headers = base_headers + self.base_max_retries = base_max_retries self.async_base_headers = async_base_headers self.httpx_client = httpx_client + self.logger = create_logger(logging_config) async def _get_headers(self) -> typing.Dict[str, str]: if self.async_base_headers is not None: @@ -535,28 +644,64 @@ async def request( ) ) - # Add the input to each of these and do None-safety checks - response = await self.httpx_client.request( - method=method, - url=_build_url(base_url, path), - headers=jsonable_encoder( - remove_none_from_dict( - { - **_headers, - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), - } - ) - ), - params=_encoded_params if _encoded_params else None, - json=json_body, - data=data_body, - content=content, - files=request_files, - timeout=timeout, + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) ) - max_retries: int = request_options.get("max_retries", 2) if request_options is not None else 2 + if self.logger.is_debug(): + self.logger.debug( + "Making HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + has_body=json_body is not None or data_body is not None, + ) + + max_retries: int = ( + request_options.get("max_retries", self.base_max_retries) + if request_options is not None + else self.base_max_retries + ) + + try: + response = await self.httpx_client.request( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + except (httpx.ConnectError, httpx.RemoteProtocolError): + if retries < max_retries: + await asyncio.sleep(_retry_timeout_from_retries(retries=retries)) + return await self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + data=data, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + force_multipart=force_multipart, + ) + raise + if _should_retry(response=response): if retries < max_retries: await asyncio.sleep(_retry_timeout(response=response, retries=retries)) @@ -566,13 +711,34 @@ async def request( base_url=base_url, params=params, json=json, + data=data, content=content, files=files, headers=headers, request_options=request_options, retries=retries + 1, omit=omit, + force_multipart=force_multipart, + ) + + if self.logger.is_debug(): + if 200 <= response.status_code < 400: + self.logger.debug( + "HTTP request succeeded", + method=method, + url=_request_url, + status_code=response.status_code, ) + + if self.logger.is_error(): + if response.status_code >= 400: + self.logger.error( + "HTTP request failed with error status", + method=method, + url=_request_url, + status_code=response.status_code, + ) + return response @asynccontextmanager @@ -641,18 +807,29 @@ async def stream( ) ) + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ) + + if self.logger.is_debug(): + self.logger.debug( + "Making streaming HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + ) + async with self.httpx_client.stream( method=method, - url=_build_url(base_url, path), - headers=jsonable_encoder( - remove_none_from_dict( - { - **_headers, - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), + url=_request_url, + headers=_request_headers, params=_encoded_params if _encoded_params else None, json=json_body, data=data_body, diff --git a/src/truefoundry_sdk/core/jsonable_encoder.py b/src/truefoundry_sdk/core/jsonable_encoder.py index f8beaeaf..5b0902eb 100644 --- a/src/truefoundry_sdk/core/jsonable_encoder.py +++ b/src/truefoundry_sdk/core/jsonable_encoder.py @@ -106,3 +106,15 @@ def fallback_serializer(o: Any) -> Any: return jsonable_encoder(data, custom_encoder=custom_encoder) return to_jsonable_with_fallback(obj, fallback_serializer) + + +def encode_path_param(obj: Any) -> str: + """Encode a value for use in a URL path segment. + + Ensures proper string conversion for all types, including + booleans which need lowercase 'true'/'false' rather than + Python's 'True'/'False'. + """ + if isinstance(obj, bool): + return "true" if obj else "false" + return str(jsonable_encoder(obj)) diff --git a/src/truefoundry_sdk/core/logging.py b/src/truefoundry_sdk/core/logging.py new file mode 100644 index 00000000..e5e57245 --- /dev/null +++ b/src/truefoundry_sdk/core/logging.py @@ -0,0 +1,107 @@ +# This file was auto-generated by Fern from our API Definition. + +import logging +import typing + +LogLevel = typing.Literal["debug", "info", "warn", "error"] + +_LOG_LEVEL_MAP: typing.Dict[LogLevel, int] = { + "debug": 1, + "info": 2, + "warn": 3, + "error": 4, +} + + +class ILogger(typing.Protocol): + def debug(self, message: str, **kwargs: typing.Any) -> None: ... + def info(self, message: str, **kwargs: typing.Any) -> None: ... + def warn(self, message: str, **kwargs: typing.Any) -> None: ... + def error(self, message: str, **kwargs: typing.Any) -> None: ... + + +class ConsoleLogger: + _logger: logging.Logger + + def __init__(self) -> None: + self._logger = logging.getLogger("fern") + if not self._logger.handlers: + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter("%(levelname)s - %(message)s")) + self._logger.addHandler(handler) + self._logger.setLevel(logging.DEBUG) + + def debug(self, message: str, **kwargs: typing.Any) -> None: + self._logger.debug(message, extra=kwargs) + + def info(self, message: str, **kwargs: typing.Any) -> None: + self._logger.info(message, extra=kwargs) + + def warn(self, message: str, **kwargs: typing.Any) -> None: + self._logger.warning(message, extra=kwargs) + + def error(self, message: str, **kwargs: typing.Any) -> None: + self._logger.error(message, extra=kwargs) + + +class LogConfig(typing.TypedDict, total=False): + level: LogLevel + logger: ILogger + silent: bool + + +class Logger: + _level: int + _logger: ILogger + _silent: bool + + def __init__(self, *, level: LogLevel, logger: ILogger, silent: bool) -> None: + self._level = _LOG_LEVEL_MAP[level] + self._logger = logger + self._silent = silent + + def _should_log(self, level: LogLevel) -> bool: + return not self._silent and self._level <= _LOG_LEVEL_MAP[level] + + def is_debug(self) -> bool: + return self._should_log("debug") + + def is_info(self) -> bool: + return self._should_log("info") + + def is_warn(self) -> bool: + return self._should_log("warn") + + def is_error(self) -> bool: + return self._should_log("error") + + def debug(self, message: str, **kwargs: typing.Any) -> None: + if self.is_debug(): + self._logger.debug(message, **kwargs) + + def info(self, message: str, **kwargs: typing.Any) -> None: + if self.is_info(): + self._logger.info(message, **kwargs) + + def warn(self, message: str, **kwargs: typing.Any) -> None: + if self.is_warn(): + self._logger.warn(message, **kwargs) + + def error(self, message: str, **kwargs: typing.Any) -> None: + if self.is_error(): + self._logger.error(message, **kwargs) + + +_default_logger: Logger = Logger(level="info", logger=ConsoleLogger(), silent=True) + + +def create_logger(config: typing.Optional[typing.Union[LogConfig, Logger]] = None) -> Logger: + if config is None: + return _default_logger + if isinstance(config, Logger): + return config + return Logger( + level=config.get("level", "info"), + logger=config.get("logger", ConsoleLogger()), + silent=config.get("silent", True), + ) diff --git a/src/truefoundry_sdk/core/parse_error.py b/src/truefoundry_sdk/core/parse_error.py new file mode 100644 index 00000000..4527c6a8 --- /dev/null +++ b/src/truefoundry_sdk/core/parse_error.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Optional + + +class ParsingError(Exception): + """ + Raised when the SDK fails to parse/validate a response from the server. + This typically indicates that the server returned a response whose shape + does not match the expected schema. + """ + + headers: Optional[Dict[str, str]] + status_code: Optional[int] + body: Any + cause: Optional[Exception] + + def __init__( + self, + *, + headers: Optional[Dict[str, str]] = None, + status_code: Optional[int] = None, + body: Any = None, + cause: Optional[Exception] = None, + ) -> None: + self.headers = headers + self.status_code = status_code + self.body = body + self.cause = cause + super().__init__() + if cause is not None: + self.__cause__ = cause + + def __str__(self) -> str: + cause_str = f", cause: {self.cause}" if self.cause is not None else "" + return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}{cause_str}" diff --git a/src/truefoundry_sdk/core/pydantic_utilities.py b/src/truefoundry_sdk/core/pydantic_utilities.py index 789081b0..fea3a08d 100644 --- a/src/truefoundry_sdk/core/pydantic_utilities.py +++ b/src/truefoundry_sdk/core/pydantic_utilities.py @@ -26,6 +26,7 @@ import pydantic import typing_extensions +from pydantic.fields import FieldInfo as _FieldInfo _logger = logging.getLogger(__name__) @@ -35,22 +36,95 @@ IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") if IS_PYDANTIC_V2: - from pydantic.v1.datetime_parse import parse_date as parse_date - from pydantic.v1.datetime_parse import parse_datetime as parse_datetime - from pydantic.v1.fields import ModelField as ModelField - from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined] - from pydantic.v1.typing import get_args as get_args - from pydantic.v1.typing import get_origin as get_origin - from pydantic.v1.typing import is_literal_type as is_literal_type - from pydantic.v1.typing import is_union as is_union + _datetime_adapter = pydantic.TypeAdapter(dt.datetime) # type: ignore[attr-defined] + _date_adapter = pydantic.TypeAdapter(dt.date) # type: ignore[attr-defined] + + def parse_datetime(value: Any) -> dt.datetime: # type: ignore[misc] + if isinstance(value, dt.datetime): + return value + return _datetime_adapter.validate_python(value) + + def parse_date(value: Any) -> dt.date: # type: ignore[misc] + if isinstance(value, dt.datetime): + return value.date() + if isinstance(value, dt.date): + return value + return _date_adapter.validate_python(value) + + # Avoid importing from pydantic.v1 to maintain Python 3.14 compatibility. + from typing import get_args as get_args # type: ignore[assignment] + from typing import get_origin as get_origin # type: ignore[assignment] + + def is_literal_type(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc] + return typing_extensions.get_origin(tp) is typing_extensions.Literal + + def is_union(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc] + return tp is Union or typing_extensions.get_origin(tp) is Union # type: ignore[comparison-overlap] + + # Inline encoders_by_type to avoid importing from pydantic.v1.json + import re as _re + from collections import deque as _deque + from decimal import Decimal as _Decimal + from enum import Enum as _Enum + from ipaddress import ( + IPv4Address as _IPv4Address, + ) + from ipaddress import ( + IPv4Interface as _IPv4Interface, + ) + from ipaddress import ( + IPv4Network as _IPv4Network, + ) + from ipaddress import ( + IPv6Address as _IPv6Address, + ) + from ipaddress import ( + IPv6Interface as _IPv6Interface, + ) + from ipaddress import ( + IPv6Network as _IPv6Network, + ) + from pathlib import Path as _Path + from types import GeneratorType as _GeneratorType + from uuid import UUID as _UUID + + from pydantic.fields import FieldInfo as ModelField # type: ignore[no-redef, assignment] + + def _decimal_encoder(dec_value: Any) -> Any: + if dec_value.as_tuple().exponent >= 0: + return int(dec_value) + return float(dec_value) + + encoders_by_type: Dict[Type[Any], Callable[[Any], Any]] = { # type: ignore[no-redef] + bytes: lambda o: o.decode(), + dt.date: lambda o: o.isoformat(), + dt.datetime: lambda o: o.isoformat(), + dt.time: lambda o: o.isoformat(), + dt.timedelta: lambda td: td.total_seconds(), + _Decimal: _decimal_encoder, + _Enum: lambda o: o.value, + frozenset: list, + _deque: list, + _GeneratorType: list, + _IPv4Address: str, + _IPv4Interface: str, + _IPv4Network: str, + _IPv6Address: str, + _IPv6Interface: str, + _IPv6Network: str, + _Path: str, + _re.Pattern: lambda o: o.pattern, + set: list, + _UUID: str, + } else: from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef] from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef] - from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef] + from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef, assignment] from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef] from pydantic.typing import get_args as get_args # type: ignore[no-redef] from pydantic.typing import get_origin as get_origin # type: ignore[no-redef] - from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef] + from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef, assignment] from pydantic.typing import is_union as is_union # type: ignore[no-redef] from .datetime_utils import serialize_datetime @@ -537,7 +611,7 @@ def decorator(func: AnyCallable) -> AnyCallable: return decorator -PydanticField = Union[ModelField, pydantic.fields.FieldInfo] +PydanticField = Union[ModelField, _FieldInfo] def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]: diff --git a/src/truefoundry_sdk/data_directories/raw_client.py b/src/truefoundry_sdk/data_directories/raw_client.py index 267e3bbb..2bfe761e 100644 --- a/src/truefoundry_sdk/data_directories/raw_client.py +++ b/src/truefoundry_sdk/data_directories/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -22,6 +23,7 @@ from ..types.list_files_response import ListFilesResponse from ..types.multi_part_upload_response import MultiPartUploadResponse from ..types.operation import Operation +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -50,7 +52,7 @@ def get( The data directory data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/data-directories/{jsonable_encoder(id)}", + f"api/ml/v1/data-directories/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -78,6 +80,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -105,7 +111,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/data-directories/{jsonable_encoder(id)}", + f"api/ml/v1/data-directories/{encode_path_param(id)}", method="DELETE", params={ "delete_contents": delete_contents, @@ -136,6 +142,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -224,6 +234,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -283,6 +297,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list_files( @@ -371,6 +389,10 @@ def list_files( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete_files( @@ -432,6 +454,10 @@ def delete_files( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_signed_urls( @@ -502,6 +528,10 @@ def get_signed_urls( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_multipart_upload( @@ -567,6 +597,10 @@ def create_multipart_upload( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -593,7 +627,7 @@ async def get( The data directory data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/data-directories/{jsonable_encoder(id)}", + f"api/ml/v1/data-directories/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -621,6 +655,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -648,7 +686,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/data-directories/{jsonable_encoder(id)}", + f"api/ml/v1/data-directories/{encode_path_param(id)}", method="DELETE", params={ "delete_contents": delete_contents, @@ -679,6 +717,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -770,6 +812,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -829,6 +875,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list_files( @@ -920,6 +970,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete_files( @@ -981,6 +1035,10 @@ async def delete_files( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_signed_urls( @@ -1051,6 +1109,10 @@ async def get_signed_urls( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_multipart_upload( @@ -1116,4 +1178,8 @@ async def create_multipart_upload( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/environments/raw_client.py b/src/truefoundry_sdk/environments/raw_client.py index 42bf0255..ebde27e1 100644 --- a/src/truefoundry_sdk/environments/raw_client.py +++ b/src/truefoundry_sdk/environments/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -19,6 +20,7 @@ from ..types.get_environment_response import GetEnvironmentResponse from ..types.http_error import HttpError from ..types.list_environments_response import ListEnvironmentsResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -85,6 +87,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -152,6 +158,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -174,7 +184,7 @@ def get( Returns the Environment associated with the provided id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/environments/{jsonable_encoder(id)}", + f"api/svc/v1/environments/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -191,6 +201,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[bool]: @@ -211,7 +225,7 @@ def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = Returns true if the Environment is deleted successfully """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/environments/{jsonable_encoder(id)}", + f"api/svc/v1/environments/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -250,6 +264,10 @@ def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -317,6 +335,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -384,6 +406,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -406,7 +432,7 @@ async def get( Returns the Environment associated with the provided id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/environments/{jsonable_encoder(id)}", + f"api/svc/v1/environments/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -423,6 +449,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -445,7 +475,7 @@ async def delete( Returns true if the Environment is deleted successfully """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/environments/{jsonable_encoder(id)}", + f"api/svc/v1/environments/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -484,4 +514,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/events/raw_client.py b/src/truefoundry_sdk/events/raw_client.py index 80ada6d8..fd7dfbc9 100644 --- a/src/truefoundry_sdk/events/raw_client.py +++ b/src/truefoundry_sdk/events/raw_client.py @@ -6,6 +6,7 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError @@ -13,6 +14,7 @@ from ..errors.not_found_error import NotFoundError from ..types.get_events_response import GetEventsResponse from ..types.http_error import HttpError +from pydantic import ValidationError class RawEventsClient: @@ -120,6 +122,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -228,4 +234,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/ai_gateway/raw_client.py b/src/truefoundry_sdk/internal/ai_gateway/raw_client.py index 60880dd9..4efccb72 100644 --- a/src/truefoundry_sdk/internal/ai_gateway/raw_client.py +++ b/src/truefoundry_sdk/internal/ai_gateway/raw_client.py @@ -6,11 +6,13 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...types.gateway_configuration import GatewayConfiguration from .types.ai_gateway_get_gateway_config_request_type import AiGatewayGetGatewayConfigRequestType +from pydantic import ValidationError class RawAiGatewayClient: @@ -37,7 +39,7 @@ def get_gateway_config( Gateway configuration retrieved successfully """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/llm-gateway/config/{jsonable_encoder(type)}", + f"api/svc/v1/llm-gateway/config/{encode_path_param(type)}", method="GET", request_options=request_options, ) @@ -54,6 +56,10 @@ def get_gateway_config( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -81,7 +87,7 @@ async def get_gateway_config( Gateway configuration retrieved successfully """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/llm-gateway/config/{jsonable_encoder(type)}", + f"api/svc/v1/llm-gateway/config/{encode_path_param(type)}", method="GET", request_options=request_options, ) @@ -98,4 +104,8 @@ async def get_gateway_config( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/applications/raw_client.py b/src/truefoundry_sdk/internal/applications/raw_client.py index f0f62538..516ba969 100644 --- a/src/truefoundry_sdk/internal/applications/raw_client.py +++ b/src/truefoundry_sdk/internal/applications/raw_client.py @@ -6,12 +6,14 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.method_not_allowed_error import MethodNotAllowedError from ...errors.not_found_error import NotFoundError +from pydantic import ValidationError class RawApplicationsClient: @@ -40,7 +42,7 @@ def promote_rollout( HttpResponse[None] """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/rollout/promote", + f"api/svc/v1/apps/{encode_path_param(id)}/rollout/promote", method="POST", params={ "full": full, @@ -75,6 +77,10 @@ def promote_rollout( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_pod_template_hash_to_deployment_version( @@ -104,7 +110,7 @@ def get_pod_template_hash_to_deployment_version( Successfully retrieved the pod template hash to deployment version map. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/pod-template-hash-deployment-version-map", + f"api/svc/v1/apps/{encode_path_param(id)}/pod-template-hash-deployment-version-map", method="GET", params={ "podTemplateHashes": pod_template_hashes, @@ -135,6 +141,10 @@ def get_pod_template_hash_to_deployment_version( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -164,7 +174,7 @@ async def promote_rollout( AsyncHttpResponse[None] """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/rollout/promote", + f"api/svc/v1/apps/{encode_path_param(id)}/rollout/promote", method="POST", params={ "full": full, @@ -199,6 +209,10 @@ async def promote_rollout( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_pod_template_hash_to_deployment_version( @@ -228,7 +242,7 @@ async def get_pod_template_hash_to_deployment_version( Successfully retrieved the pod template hash to deployment version map. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/pod-template-hash-deployment-version-map", + f"api/svc/v1/apps/{encode_path_param(id)}/pod-template-hash-deployment-version-map", method="GET", params={ "podTemplateHashes": pod_template_hashes, @@ -259,4 +273,8 @@ async def get_pod_template_hash_to_deployment_version( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/artifact_versions/raw_client.py b/src/truefoundry_sdk/internal/artifact_versions/raw_client.py index 71e2a5b5..89679e71 100644 --- a/src/truefoundry_sdk/internal/artifact_versions/raw_client.py +++ b/src/truefoundry_sdk/internal/artifact_versions/raw_client.py @@ -6,11 +6,13 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.pagination import AsyncPager, SyncPager +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.internal_list_artifact_versions_response import InternalListArtifactVersionsResponse from ...types.internal_list_artifact_versions_response_data_item import InternalListArtifactVersionsResponseDataItem +from pydantic import ValidationError class RawArtifactVersionsClient: @@ -145,6 +147,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -283,4 +289,8 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/build_logs/raw_client.py b/src/truefoundry_sdk/internal/build_logs/raw_client.py index aa0cbb56..9f7afbbd 100644 --- a/src/truefoundry_sdk/internal/build_logs/raw_client.py +++ b/src/truefoundry_sdk/internal/build_logs/raw_client.py @@ -6,13 +6,15 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...core.serialization import convert_and_respect_annotation_metadata from ...errors.bad_request_error import BadRequestError from ...types.logs_filter_query import LogsFilterQuery from ...types.logs_response import LogsResponse +from pydantic import ValidationError class RawBuildLogsClient: @@ -66,7 +68,7 @@ def get( Successfully retrieved build logs for the pipeline run """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/build-logs/{jsonable_encoder(pipeline_run_name)}", + f"api/svc/v1/build-logs/{encode_path_param(pipeline_run_name)}", method="GET", params={ "startTs": start_ts, @@ -104,6 +106,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -158,7 +164,7 @@ async def get( Successfully retrieved build logs for the pipeline run """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/build-logs/{jsonable_encoder(pipeline_run_name)}", + f"api/svc/v1/build-logs/{encode_path_param(pipeline_run_name)}", method="GET", params={ "startTs": start_ts, @@ -196,4 +202,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/clusters/raw_client.py b/src/truefoundry_sdk/internal/clusters/raw_client.py index 1a68dcda..24143c34 100644 --- a/src/truefoundry_sdk/internal/clusters/raw_client.py +++ b/src/truefoundry_sdk/internal/clusters/raw_client.py @@ -6,12 +6,14 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.unauthorized_error import UnauthorizedError from ...types.get_auto_provisioning_state_response import GetAutoProvisioningStateResponse from ...types.http_error import HttpError +from pydantic import ValidationError class RawClustersClient: @@ -38,7 +40,7 @@ def get_autoprovisioning_state( Returns the auto provisioning status for the cluster """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}/autoprovisioning-state", + f"api/svc/v1/clusters/{encode_path_param(id)}/autoprovisioning-state", method="GET", request_options=request_options, ) @@ -66,6 +68,10 @@ def get_autoprovisioning_state( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -93,7 +99,7 @@ async def get_autoprovisioning_state( Returns the auto provisioning status for the cluster """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/clusters/{jsonable_encoder(id)}/autoprovisioning-state", + f"api/svc/v1/clusters/{encode_path_param(id)}/autoprovisioning-state", method="GET", request_options=request_options, ) @@ -121,4 +127,8 @@ async def get_autoprovisioning_state( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/deployments/raw_client.py b/src/truefoundry_sdk/internal/deployments/raw_client.py index 6b820904..e96b1cb4 100644 --- a/src/truefoundry_sdk/internal/deployments/raw_client.py +++ b/src/truefoundry_sdk/internal/deployments/raw_client.py @@ -6,7 +6,8 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError @@ -16,6 +17,7 @@ from ...types.deployment_status import DeploymentStatus from ...types.get_suggested_deployment_endpoint_response import GetSuggestedDeploymentEndpointResponse from ...types.presigned_url_object import PresignedUrlObject +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -48,7 +50,7 @@ def get_deployment_statuses( Deployment statuses returned successfully. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/statuses", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/statuses", method="GET", request_options=request_options, ) @@ -76,6 +78,10 @@ def get_deployment_statuses( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_builds( @@ -101,7 +107,7 @@ def get_builds( Deployment builds returned successfully. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/builds", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/builds", method="GET", request_options=request_options, ) @@ -129,6 +135,10 @@ def get_builds( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_code_upload_url( @@ -179,6 +189,10 @@ def get_code_upload_url( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_suggested_endpoint( @@ -260,6 +274,10 @@ def get_suggested_endpoint( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -290,7 +308,7 @@ async def get_deployment_statuses( Deployment statuses returned successfully. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/statuses", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/statuses", method="GET", request_options=request_options, ) @@ -318,6 +336,10 @@ async def get_deployment_statuses( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_builds( @@ -343,7 +365,7 @@ async def get_builds( Deployment builds returned successfully. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/apps/{jsonable_encoder(id)}/deployments/{jsonable_encoder(deployment_id)}/builds", + f"api/svc/v1/apps/{encode_path_param(id)}/deployments/{encode_path_param(deployment_id)}/builds", method="GET", request_options=request_options, ) @@ -371,6 +393,10 @@ async def get_builds( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_code_upload_url( @@ -421,6 +447,10 @@ async def get_code_upload_url( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_suggested_endpoint( @@ -502,4 +532,8 @@ async def get_suggested_endpoint( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/docker_registries/raw_client.py b/src/truefoundry_sdk/internal/docker_registries/raw_client.py index b6d1f3dc..f23aaaa7 100644 --- a/src/truefoundry_sdk/internal/docker_registries/raw_client.py +++ b/src/truefoundry_sdk/internal/docker_registries/raw_client.py @@ -6,11 +6,13 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.not_found_error import NotFoundError from ...types.create_docker_repository_response import CreateDockerRepositoryResponse from ...types.get_docker_registry_credentials_response import GetDockerRegistryCredentialsResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -88,6 +90,10 @@ def create_repository( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_credentials( @@ -138,6 +144,10 @@ def get_credentials( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -213,6 +223,10 @@ async def create_repository( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_credentials( @@ -263,4 +277,8 @@ async def get_credentials( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/metrics/raw_client.py b/src/truefoundry_sdk/internal/metrics/raw_client.py index 1b6b7d28..263ddf63 100644 --- a/src/truefoundry_sdk/internal/metrics/raw_client.py +++ b/src/truefoundry_sdk/internal/metrics/raw_client.py @@ -6,7 +6,8 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError @@ -14,6 +15,7 @@ from ...errors.not_found_error import NotFoundError from ...types.get_charts_response import GetChartsResponse from .types.metrics_get_charts_request_filter_entity import MetricsGetChartsRequestFilterEntity +from pydantic import ValidationError class RawMetricsClient: @@ -60,7 +62,7 @@ def get_charts( Charts have been successfully retrieved. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/metrics/{jsonable_encoder(workspace_id)}/charts", + f"api/svc/v1/metrics/{encode_path_param(workspace_id)}/charts", method="GET", params={ "applicationId": application_id, @@ -117,6 +119,10 @@ def get_charts( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -164,7 +170,7 @@ async def get_charts( Charts have been successfully retrieved. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/metrics/{jsonable_encoder(workspace_id)}/charts", + f"api/svc/v1/metrics/{encode_path_param(workspace_id)}/charts", method="GET", params={ "applicationId": application_id, @@ -221,4 +227,8 @@ async def get_charts( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/ml/raw_client.py b/src/truefoundry_sdk/internal/ml/raw_client.py index 7c1ad610..6d0e28cc 100644 --- a/src/truefoundry_sdk/internal/ml/raw_client.py +++ b/src/truefoundry_sdk/internal/ml/raw_client.py @@ -6,6 +6,7 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...core.serialization import convert_and_respect_annotation_metadata @@ -14,6 +15,7 @@ from ...types.empty_response import EmptyResponse from .types.apply_ml_entity_request_manifest import ApplyMlEntityRequestManifest from .types.delete_ml_entity_request_manifest import DeleteMlEntityRequestManifest +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -80,6 +82,10 @@ def apply( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -139,6 +145,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -203,6 +213,10 @@ async def apply( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -262,4 +276,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/raw_client.py b/src/truefoundry_sdk/internal/raw_client.py index cc90b88a..ba915ec2 100644 --- a/src/truefoundry_sdk/internal/raw_client.py +++ b/src/truefoundry_sdk/internal/raw_client.py @@ -6,11 +6,13 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError from ..errors.not_found_error import NotFoundError +from pydantic import ValidationError class RawInternalClient: @@ -40,7 +42,7 @@ def get_id_from_fqn( Returns the IDs for the specified entity type based on the provided FQN. For example, deploymentId, applicationId, and workspaceId for type deployment, or applicationId and workspaceId for type app. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/fqn/{jsonable_encoder(type)}", + f"api/svc/v1/fqn/{encode_path_param(type)}", method="GET", params={ "fqn": fqn, @@ -82,6 +84,10 @@ def get_id_from_fqn( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -112,7 +118,7 @@ async def get_id_from_fqn( Returns the IDs for the specified entity type based on the provided FQN. For example, deploymentId, applicationId, and workspaceId for type deployment, or applicationId and workspaceId for type app. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/fqn/{jsonable_encoder(type)}", + f"api/svc/v1/fqn/{encode_path_param(type)}", method="GET", params={ "fqn": fqn, @@ -154,4 +160,8 @@ async def get_id_from_fqn( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/users/raw_client.py b/src/truefoundry_sdk/internal/users/raw_client.py index ddc359a2..fbed119e 100644 --- a/src/truefoundry_sdk/internal/users/raw_client.py +++ b/src/truefoundry_sdk/internal/users/raw_client.py @@ -6,9 +6,11 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...types.session import Session +from pydantic import ValidationError class RawUsersClient: @@ -47,6 +49,10 @@ def get_info(self, *, request_options: typing.Optional[RequestOptions] = None) - _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -86,4 +92,8 @@ async def get_info(self, *, request_options: typing.Optional[RequestOptions] = N _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/vcs/raw_client.py b/src/truefoundry_sdk/internal/vcs/raw_client.py index fb35c9df..cda33908 100644 --- a/src/truefoundry_sdk/internal/vcs/raw_client.py +++ b/src/truefoundry_sdk/internal/vcs/raw_client.py @@ -6,10 +6,12 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...types.get_authenticated_vcsurl_response import GetAuthenticatedVcsurlResponse from ...types.git_repository_exists_response import GitRepositoryExistsResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -65,6 +67,10 @@ def get_repository_details( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_authenticated_url( @@ -109,6 +115,10 @@ def get_authenticated_url( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -162,6 +172,10 @@ async def get_repository_details( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_authenticated_url( @@ -206,4 +220,8 @@ async def get_authenticated_url( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/internal/workflows/raw_client.py b/src/truefoundry_sdk/internal/workflows/raw_client.py index 7ce6bb72..01a14081 100644 --- a/src/truefoundry_sdk/internal/workflows/raw_client.py +++ b/src/truefoundry_sdk/internal/workflows/raw_client.py @@ -6,12 +6,14 @@ from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.http_response import AsyncHttpResponse, HttpResponse -from ...core.jsonable_encoder import jsonable_encoder +from ...core.jsonable_encoder import encode_path_param +from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.not_found_error import NotFoundError from .types.workflows_execute_workflow_response import WorkflowsExecuteWorkflowResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -52,7 +54,7 @@ def execute_workflow( Returns execution name of the workflow """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/workflow/{jsonable_encoder(application_id)}/executions", + f"api/svc/v1/workflow/{encode_path_param(application_id)}/executions", method="POST", json={ "inputs": inputs, @@ -99,6 +101,10 @@ def execute_workflow( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -137,7 +143,7 @@ async def execute_workflow( Returns execution name of the workflow """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/workflow/{jsonable_encoder(application_id)}/executions", + f"api/svc/v1/workflow/{encode_path_param(application_id)}/executions", method="POST", json={ "inputs": inputs, @@ -184,4 +190,8 @@ async def execute_workflow( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/jobs/raw_client.py b/src/truefoundry_sdk/jobs/raw_client.py index fbc137b4..9df855f1 100644 --- a/src/truefoundry_sdk/jobs/raw_client.py +++ b/src/truefoundry_sdk/jobs/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -29,6 +30,7 @@ from ..types.terminate_job_response import TerminateJobResponse from ..types.trigger_job_run_response import TriggerJobRunResponse from .types.trigger_job_request_input import TriggerJobRequestInput +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -95,7 +97,7 @@ def list_runs( offset = offset if offset is not None else 0 _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/jobs/{jsonable_encoder(job_id)}/runs", + f"api/svc/v1/jobs/{encode_path_param(job_id)}/runs", method="GET", params={ "limit": limit, @@ -169,6 +171,10 @@ def list_runs( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_run( @@ -194,7 +200,7 @@ def get_run( Return JobRun details of the provided jobRunName """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/jobs/{jsonable_encoder(job_id)}/runs/{jsonable_encoder(job_run_name)}", + f"api/svc/v1/jobs/{encode_path_param(job_id)}/runs/{encode_path_param(job_run_name)}", method="GET", request_options=request_options, ) @@ -233,6 +239,10 @@ def get_run( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete_run( @@ -258,7 +268,7 @@ def delete_run( Job Run deleted """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/jobs/{jsonable_encoder(job_id)}/runs/{jsonable_encoder(job_run_name)}", + f"api/svc/v1/jobs/{encode_path_param(job_id)}/runs/{encode_path_param(job_run_name)}", method="DELETE", request_options=request_options, ) @@ -308,6 +318,10 @@ def delete_run( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def trigger( @@ -420,6 +434,10 @@ def trigger( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def terminate( @@ -510,6 +528,10 @@ def terminate( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -574,7 +596,7 @@ async def list_runs( offset = offset if offset is not None else 0 _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/jobs/{jsonable_encoder(job_id)}/runs", + f"api/svc/v1/jobs/{encode_path_param(job_id)}/runs", method="GET", params={ "limit": limit, @@ -651,6 +673,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_run( @@ -676,7 +702,7 @@ async def get_run( Return JobRun details of the provided jobRunName """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/jobs/{jsonable_encoder(job_id)}/runs/{jsonable_encoder(job_run_name)}", + f"api/svc/v1/jobs/{encode_path_param(job_id)}/runs/{encode_path_param(job_run_name)}", method="GET", request_options=request_options, ) @@ -715,6 +741,10 @@ async def get_run( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete_run( @@ -740,7 +770,7 @@ async def delete_run( Job Run deleted """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/jobs/{jsonable_encoder(job_id)}/runs/{jsonable_encoder(job_run_name)}", + f"api/svc/v1/jobs/{encode_path_param(job_id)}/runs/{encode_path_param(job_run_name)}", method="DELETE", request_options=request_options, ) @@ -790,6 +820,10 @@ async def delete_run( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def trigger( @@ -902,6 +936,10 @@ async def trigger( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def terminate( @@ -992,4 +1030,8 @@ async def terminate( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/logs/raw_client.py b/src/truefoundry_sdk/logs/raw_client.py index ddc35056..8abc89d7 100644 --- a/src/truefoundry_sdk/logs/raw_client.py +++ b/src/truefoundry_sdk/logs/raw_client.py @@ -6,6 +6,7 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError @@ -13,6 +14,7 @@ from ..types.logs_search_filter_type import LogsSearchFilterType from ..types.logs_search_operator_type import LogsSearchOperatorType from ..types.logs_sorting_direction import LogsSortingDirection +from pydantic import ValidationError class RawLogsClient: @@ -153,6 +155,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -294,4 +300,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/ml_repos/raw_client.py b/src/truefoundry_sdk/ml_repos/raw_client.py index 194a8c48..f7a4ad6f 100644 --- a/src/truefoundry_sdk/ml_repos/raw_client.py +++ b/src/truefoundry_sdk/ml_repos/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -21,6 +22,7 @@ from ..types.list_ml_repos_response import ListMlReposResponse from ..types.ml_repo import MlRepo from ..types.ml_repo_manifest import MlRepoManifest +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -128,6 +130,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -149,7 +155,7 @@ def get( The ML Repo data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/ml-repos/{jsonable_encoder(id)}", + f"api/ml/v1/ml-repos/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -177,6 +183,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -198,7 +208,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/ml-repos/{jsonable_encoder(id)}", + f"api/ml/v1/ml-repos/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -226,6 +236,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -302,6 +316,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -407,6 +425,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -428,7 +450,7 @@ async def get( The ML Repo data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/ml-repos/{jsonable_encoder(id)}", + f"api/ml/v1/ml-repos/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -456,6 +478,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -477,7 +503,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/ml-repos/{jsonable_encoder(id)}", + f"api/ml/v1/ml-repos/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -505,6 +531,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -584,4 +614,8 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/model_versions/raw_client.py b/src/truefoundry_sdk/model_versions/raw_client.py index 57598932..7ecb3d89 100644 --- a/src/truefoundry_sdk/model_versions/raw_client.py +++ b/src/truefoundry_sdk/model_versions/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.unprocessable_entity_error import UnprocessableEntityError @@ -15,6 +16,7 @@ from ..types.get_model_version_response import GetModelVersionResponse from ..types.list_model_versions_response import ListModelVersionsResponse from ..types.model_version import ModelVersion +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -92,6 +94,10 @@ def apply_tags( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -113,7 +119,7 @@ def get( The model version data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/model-versions/{jsonable_encoder(id)}", + f"api/ml/v1/model-versions/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -141,6 +147,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -162,7 +172,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/model-versions/{jsonable_encoder(id)}", + f"api/ml/v1/model-versions/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -190,6 +200,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -314,6 +328,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -389,6 +407,10 @@ async def apply_tags( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -410,7 +432,7 @@ async def get( The model version data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/model-versions/{jsonable_encoder(id)}", + f"api/ml/v1/model-versions/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -438,6 +460,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -459,7 +485,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/model-versions/{jsonable_encoder(id)}", + f"api/ml/v1/model-versions/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -487,6 +513,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -614,4 +644,8 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/models/raw_client.py b/src/truefoundry_sdk/models/raw_client.py index 63d808dd..e8115cb2 100644 --- a/src/truefoundry_sdk/models/raw_client.py +++ b/src/truefoundry_sdk/models/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -18,6 +19,7 @@ from ..types.list_models_response import ListModelsResponse from ..types.model import Model from ..types.model_manifest import ModelManifest +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -46,7 +48,7 @@ def get( The model data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/models/{jsonable_encoder(id)}", + f"api/ml/v1/models/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -74,6 +76,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -95,7 +101,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/models/{jsonable_encoder(id)}", + f"api/ml/v1/models/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -123,6 +129,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -223,6 +233,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -282,6 +296,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -308,7 +326,7 @@ async def get( The model data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/models/{jsonable_encoder(id)}", + f"api/ml/v1/models/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -336,6 +354,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -357,7 +379,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/models/{jsonable_encoder(id)}", + f"api/ml/v1/models/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -385,6 +407,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -488,6 +514,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -547,4 +577,8 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/personal_access_tokens/raw_client.py b/src/truefoundry_sdk/personal_access_tokens/raw_client.py index 39d85efe..0b9474dd 100644 --- a/src/truefoundry_sdk/personal_access_tokens/raw_client.py +++ b/src/truefoundry_sdk/personal_access_tokens/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError @@ -20,6 +21,7 @@ from ..types.list_personal_access_token_response import ListPersonalAccessTokenResponse from ..types.revoke_all_personal_access_token_response import RevokeAllPersonalAccessTokenResponse from ..types.virtual_account import VirtualAccount +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -92,6 +94,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create( @@ -173,6 +179,10 @@ def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def revoke_all( @@ -230,6 +240,10 @@ def revoke_all( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -252,7 +266,7 @@ def delete( Personal Access Token deleted successfully """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/personal-access-tokens/{jsonable_encoder(id)}", + f"api/svc/v1/personal-access-tokens/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -280,6 +294,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -301,7 +319,7 @@ def get( Personal Access Token found successfully and returned with token """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/personal-access-tokens/{jsonable_encoder(name)}", + f"api/svc/v1/personal-access-tokens/{encode_path_param(name)}", method="GET", request_options=request_options, ) @@ -329,6 +347,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -402,6 +424,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create( @@ -483,6 +509,10 @@ async def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def revoke_all( @@ -540,6 +570,10 @@ async def revoke_all( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -562,7 +596,7 @@ async def delete( Personal Access Token deleted successfully """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/personal-access-tokens/{jsonable_encoder(id)}", + f"api/svc/v1/personal-access-tokens/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -590,6 +624,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -611,7 +649,7 @@ async def get( Personal Access Token found successfully and returned with token """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/personal-access-tokens/{jsonable_encoder(name)}", + f"api/svc/v1/personal-access-tokens/{encode_path_param(name)}", method="GET", request_options=request_options, ) @@ -639,4 +677,8 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/prompt_versions/raw_client.py b/src/truefoundry_sdk/prompt_versions/raw_client.py index b3ea68a7..43b80cd7 100644 --- a/src/truefoundry_sdk/prompt_versions/raw_client.py +++ b/src/truefoundry_sdk/prompt_versions/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.unprocessable_entity_error import UnprocessableEntityError @@ -15,6 +16,7 @@ from ..types.get_prompt_version_response import GetPromptVersionResponse from ..types.list_prompt_versions_response import ListPromptVersionsResponse from ..types.prompt_version import PromptVersion +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -92,6 +94,10 @@ def apply_tags( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -113,7 +119,7 @@ def get( The prompt version data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompt-versions/{jsonable_encoder(id)}", + f"api/ml/v1/prompt-versions/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -141,6 +147,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -162,7 +172,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompt-versions/{jsonable_encoder(id)}", + f"api/ml/v1/prompt-versions/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -190,6 +200,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -296,6 +310,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -371,6 +389,10 @@ async def apply_tags( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -392,7 +414,7 @@ async def get( The prompt version data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompt-versions/{jsonable_encoder(id)}", + f"api/ml/v1/prompt-versions/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -420,6 +442,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -441,7 +467,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompt-versions/{jsonable_encoder(id)}", + f"api/ml/v1/prompt-versions/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -469,6 +495,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -578,4 +608,8 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/prompts/raw_client.py b/src/truefoundry_sdk/prompts/raw_client.py index 5dce0cd9..4b3a6ff9 100644 --- a/src/truefoundry_sdk/prompts/raw_client.py +++ b/src/truefoundry_sdk/prompts/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -18,6 +19,7 @@ from ..types.get_prompt_version_response import GetPromptVersionResponse from ..types.list_prompts_response import ListPromptsResponse from ..types.prompt import Prompt +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -46,7 +48,7 @@ def get( The prompt data """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompts/{jsonable_encoder(id)}", + f"api/ml/v1/prompts/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -74,6 +76,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -95,7 +101,7 @@ def delete( Empty response indicating successful deletion """ _response = self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompts/{jsonable_encoder(id)}", + f"api/ml/v1/prompts/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -123,6 +129,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def list( @@ -217,6 +227,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -276,6 +290,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -302,7 +320,7 @@ async def get( The prompt data """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompts/{jsonable_encoder(id)}", + f"api/ml/v1/prompts/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -330,6 +348,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -351,7 +373,7 @@ async def delete( Empty response indicating successful deletion """ _response = await self._client_wrapper.httpx_client.request( - f"api/ml/v1/prompts/{jsonable_encoder(id)}", + f"api/ml/v1/prompts/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -379,6 +401,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def list( @@ -476,6 +502,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -535,4 +565,8 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/raw_base_client.py b/src/truefoundry_sdk/raw_base_client.py index 5247df4d..4030190b 100644 --- a/src/truefoundry_sdk/raw_base_client.py +++ b/src/truefoundry_sdk/raw_base_client.py @@ -6,12 +6,14 @@ from .core.api_error import ApiError from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .core.http_response import AsyncHttpResponse, HttpResponse +from .core.parse_error import ParsingError from .core.pydantic_utilities import parse_obj_as from .core.request_options import RequestOptions from .core.serialization import convert_and_respect_annotation_metadata from .types.true_foundry_apply_request_manifest import TrueFoundryApplyRequestManifest from .types.true_foundry_apply_response import TrueFoundryApplyResponse from .types.true_foundry_delete_request_manifest import TrueFoundryDeleteRequestManifest +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -75,6 +77,10 @@ def apply( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -115,6 +121,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -176,6 +186,10 @@ async def apply( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -216,4 +230,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/secret_groups/raw_client.py b/src/truefoundry_sdk/secret_groups/raw_client.py index 463af059..7de0ac42 100644 --- a/src/truefoundry_sdk/secret_groups/raw_client.py +++ b/src/truefoundry_sdk/secret_groups/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -25,6 +26,7 @@ from ..types.secret_group_manifest import SecretGroupManifest from ..types.secret_input import SecretInput from ..types.update_secret_input import UpdateSecretInput +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -103,6 +105,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create( @@ -186,6 +192,10 @@ def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -297,6 +307,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -319,7 +333,7 @@ def get( Returns the Secret Group associated with provided id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/secret-groups/{jsonable_encoder(id)}", + f"api/svc/v1/secret-groups/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -358,6 +372,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def update( @@ -386,7 +404,7 @@ def update( Returns the updated secret group without associated secrets. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/secret-groups/{jsonable_encoder(id)}", + f"api/svc/v1/secret-groups/{encode_path_param(id)}", method="PUT", json={ "secrets": convert_and_respect_annotation_metadata( @@ -456,6 +474,10 @@ def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -478,7 +500,7 @@ def delete( Deletes Secret Group. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/secret-groups/{jsonable_encoder(id)}", + f"api/svc/v1/secret-groups/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -517,6 +539,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -596,6 +622,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create( @@ -679,6 +709,10 @@ async def create( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -790,6 +824,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -812,7 +850,7 @@ async def get( Returns the Secret Group associated with provided id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/secret-groups/{jsonable_encoder(id)}", + f"api/svc/v1/secret-groups/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -851,6 +889,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def update( @@ -879,7 +921,7 @@ async def update( Returns the updated secret group without associated secrets. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/secret-groups/{jsonable_encoder(id)}", + f"api/svc/v1/secret-groups/{encode_path_param(id)}", method="PUT", json={ "secrets": convert_and_respect_annotation_metadata( @@ -949,6 +991,10 @@ async def update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -971,7 +1017,7 @@ async def delete( Deletes Secret Group. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/secret-groups/{jsonable_encoder(id)}", + f"api/svc/v1/secret-groups/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -1010,4 +1056,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/secrets/raw_client.py b/src/truefoundry_sdk/secrets/raw_client.py index ff668387..e36d9bc0 100644 --- a/src/truefoundry_sdk/secrets/raw_client.py +++ b/src/truefoundry_sdk/secrets/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.failed_dependency_error import FailedDependencyError @@ -17,6 +18,7 @@ from ..types.http_error import HttpError from ..types.list_secrets_response import ListSecretsResponse from ..types.secret import Secret +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -127,6 +129,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -149,7 +155,7 @@ def get( Returns the Secret associated with provided id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/secrets/{jsonable_encoder(id)}", + f"api/svc/v1/secrets/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -188,6 +194,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -217,7 +227,7 @@ def delete( Deletes a secret and its versions along with its values and returns the count of the deleted secrets. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/secrets/{jsonable_encoder(id)}", + f"api/svc/v1/secrets/{encode_path_param(id)}", method="DELETE", params={ "forceDelete": force_delete, @@ -270,6 +280,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -381,6 +395,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -403,7 +421,7 @@ async def get( Returns the Secret associated with provided id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/secrets/{jsonable_encoder(id)}", + f"api/svc/v1/secrets/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -442,6 +460,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -471,7 +493,7 @@ async def delete( Deletes a secret and its versions along with its values and returns the count of the deleted secrets. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/secrets/{jsonable_encoder(id)}", + f"api/svc/v1/secrets/{encode_path_param(id)}", method="DELETE", params={ "forceDelete": force_delete, @@ -524,4 +546,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/teams/raw_client.py b/src/truefoundry_sdk/teams/raw_client.py index 2f32a8a8..d63756c0 100644 --- a/src/truefoundry_sdk/teams/raw_client.py +++ b/src/truefoundry_sdk/teams/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -23,6 +24,7 @@ from ..types.team import Team from ..types.team_manifest import TeamManifest from .types.teams_list_request_type import TeamsListRequestType +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -95,6 +97,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -173,6 +179,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[GetTeamResponse]: @@ -193,7 +203,7 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non Returns the Team associated with provided team id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/teams/{jsonable_encoder(id)}", + f"api/svc/v1/teams/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -221,6 +231,10 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -243,7 +257,7 @@ def delete( Successfully deleted the team. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/teams/{jsonable_encoder(id)}", + f"api/svc/v1/teams/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -282,6 +296,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_permissions( @@ -304,7 +322,7 @@ def get_permissions( Returns role bindings for the team. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/teams/{jsonable_encoder(id)}/permissions", + f"api/svc/v1/teams/{encode_path_param(id)}/permissions", method="GET", request_options=request_options, ) @@ -343,6 +361,10 @@ def get_permissions( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -416,6 +438,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -494,6 +520,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -516,7 +546,7 @@ async def get( Returns the Team associated with provided team id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/teams/{jsonable_encoder(id)}", + f"api/svc/v1/teams/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -544,6 +574,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -566,7 +600,7 @@ async def delete( Successfully deleted the team. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/teams/{jsonable_encoder(id)}", + f"api/svc/v1/teams/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -605,6 +639,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_permissions( @@ -627,7 +665,7 @@ async def get_permissions( Returns role bindings for the team. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/teams/{jsonable_encoder(id)}/permissions", + f"api/svc/v1/teams/{encode_path_param(id)}/permissions", method="GET", request_options=request_options, ) @@ -666,4 +704,8 @@ async def get_permissions( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/traces/raw_client.py b/src/truefoundry_sdk/traces/raw_client.py index 4ae7c14a..2c3d1d40 100644 --- a/src/truefoundry_sdk/traces/raw_client.py +++ b/src/truefoundry_sdk/traces/raw_client.py @@ -6,6 +6,7 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -14,6 +15,7 @@ from ..types.subject_type import SubjectType from ..types.trace_span import TraceSpan from .types.query_spans_request_filters_item import QuerySpansRequestFiltersItem +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -164,6 +166,10 @@ def query_spans( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -315,4 +321,8 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/types/non_negative_float.py b/src/truefoundry_sdk/types/non_negative_float.py index da8968da..940f6df3 100644 --- a/src/truefoundry_sdk/types/non_negative_float.py +++ b/src/truefoundry_sdk/types/non_negative_float.py @@ -1,3 +1,6 @@ # This file was auto-generated by Fern from our API Definition. NonNegativeFloat = float +""" ++uiProps={"allowDecimal":true, "allowNegative":false} +""" diff --git a/src/truefoundry_sdk/users/raw_client.py b/src/truefoundry_sdk/users/raw_client.py index 05212206..c5b736a6 100644 --- a/src/truefoundry_sdk/users/raw_client.py +++ b/src/truefoundry_sdk/users/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError @@ -30,6 +31,7 @@ from ..types.register_users_response import RegisterUsersResponse from ..types.update_user_roles_response import UpdateUserRolesResponse from ..types.user import User +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -107,6 +109,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def pre_register_users( @@ -209,6 +215,10 @@ def pre_register_users( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def update_roles( @@ -301,6 +311,10 @@ def update_roles( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[GetUserResponse]: @@ -321,7 +335,7 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non Returns the User associated with provided User id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}", + f"api/svc/v1/users/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -349,6 +363,10 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -378,7 +396,7 @@ def delete( User has been successfully deleted. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}", + f"api/svc/v1/users/{encode_path_param(id)}", method="DELETE", params={ "tenantName": tenant_name, @@ -431,6 +449,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def invite_user( @@ -514,6 +536,10 @@ def invite_user( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def deactivate( @@ -590,6 +616,10 @@ def deactivate( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def activate( @@ -666,6 +696,10 @@ def activate( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def change_password( @@ -725,6 +759,10 @@ def change_password( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_resources( @@ -747,7 +785,7 @@ def get_resources( Returns all resources for the user. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}/resources", + f"api/svc/v1/users/{encode_path_param(id)}/resources", method="GET", request_options=request_options, ) @@ -786,6 +824,10 @@ def get_resources( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_permissions( @@ -808,7 +850,7 @@ def get_permissions( Returns role bindings for the user (including team-inherited). """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}/permissions", + f"api/svc/v1/users/{encode_path_param(id)}/permissions", method="GET", request_options=request_options, ) @@ -847,6 +889,10 @@ def get_permissions( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_teams( @@ -869,7 +915,7 @@ def get_teams( Returns all teams for the user with their roles. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}/teams", + f"api/svc/v1/users/{encode_path_param(id)}/teams", method="GET", request_options=request_options, ) @@ -908,6 +954,10 @@ def get_teams( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -986,6 +1036,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def pre_register_users( @@ -1088,6 +1142,10 @@ async def pre_register_users( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def update_roles( @@ -1180,6 +1238,10 @@ async def update_roles( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -1202,7 +1264,7 @@ async def get( Returns the User associated with provided User id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}", + f"api/svc/v1/users/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -1230,6 +1292,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -1259,7 +1325,7 @@ async def delete( User has been successfully deleted. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}", + f"api/svc/v1/users/{encode_path_param(id)}", method="DELETE", params={ "tenantName": tenant_name, @@ -1312,6 +1378,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def invite_user( @@ -1395,6 +1465,10 @@ async def invite_user( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def deactivate( @@ -1471,6 +1545,10 @@ async def deactivate( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def activate( @@ -1547,6 +1625,10 @@ async def activate( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def change_password( @@ -1606,6 +1688,10 @@ async def change_password( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_resources( @@ -1628,7 +1714,7 @@ async def get_resources( Returns all resources for the user. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}/resources", + f"api/svc/v1/users/{encode_path_param(id)}/resources", method="GET", request_options=request_options, ) @@ -1667,6 +1753,10 @@ async def get_resources( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_permissions( @@ -1689,7 +1779,7 @@ async def get_permissions( Returns role bindings for the user (including team-inherited). """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}/permissions", + f"api/svc/v1/users/{encode_path_param(id)}/permissions", method="GET", request_options=request_options, ) @@ -1728,6 +1818,10 @@ async def get_permissions( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_teams( @@ -1750,7 +1844,7 @@ async def get_teams( Returns all teams for the user with their roles. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/users/{jsonable_encoder(id)}/teams", + f"api/svc/v1/users/{encode_path_param(id)}/teams", method="GET", request_options=request_options, ) @@ -1789,4 +1883,8 @@ async def get_teams( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/virtual_accounts/raw_client.py b/src/truefoundry_sdk/virtual_accounts/raw_client.py index 659adf86..ef0df19f 100644 --- a/src/truefoundry_sdk/virtual_accounts/raw_client.py +++ b/src/truefoundry_sdk/virtual_accounts/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -21,6 +22,7 @@ from ..types.sync_virtual_account_token_response import SyncVirtualAccountTokenResponse from ..types.virtual_account import VirtualAccount from ..types.virtual_account_manifest import VirtualAccountManifest +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -111,6 +113,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -189,6 +195,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -211,7 +221,7 @@ def get( Returns the virtual account associated with the provided virtual account id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -239,6 +249,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -261,7 +275,7 @@ def delete( Virtual account deleted successfully """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -289,6 +303,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get_token( @@ -311,7 +329,7 @@ def get_token( Token for the virtual account """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/token", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/token", method="GET", request_options=request_options, ) @@ -328,6 +346,10 @@ def get_token( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def sync_to_secret_store( @@ -350,7 +372,7 @@ def sync_to_secret_store( Token synced successfully to secret store """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/sync-to-secret-store", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/sync-to-secret-store", method="POST", request_options=request_options, ) @@ -389,6 +411,10 @@ def sync_to_secret_store( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def regenerate_token( @@ -414,7 +440,7 @@ def regenerate_token( Token for the virtual account """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/regenerate-token", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/regenerate-token", method="POST", json={ "gracePeriodInDays": grace_period_in_days, @@ -438,6 +464,10 @@ def regenerate_token( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete_jwt( @@ -462,7 +492,7 @@ def delete_jwt( HttpResponse[None] """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/jwt/{jsonable_encoder(jwt_id)}", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/jwt/{encode_path_param(jwt_id)}", method="DELETE", request_options=request_options, ) @@ -472,6 +502,10 @@ def delete_jwt( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -563,6 +597,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -641,6 +679,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -663,7 +705,7 @@ async def get( Returns the virtual account associated with the provided virtual account id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -691,6 +733,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -713,7 +759,7 @@ async def delete( Virtual account deleted successfully """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -741,6 +787,10 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get_token( @@ -763,7 +813,7 @@ async def get_token( Token for the virtual account """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/token", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/token", method="GET", request_options=request_options, ) @@ -780,6 +830,10 @@ async def get_token( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def sync_to_secret_store( @@ -802,7 +856,7 @@ async def sync_to_secret_store( Token synced successfully to secret store """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/sync-to-secret-store", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/sync-to-secret-store", method="POST", request_options=request_options, ) @@ -841,6 +895,10 @@ async def sync_to_secret_store( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def regenerate_token( @@ -866,7 +924,7 @@ async def regenerate_token( Token for the virtual account """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/regenerate-token", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/regenerate-token", method="POST", json={ "gracePeriodInDays": grace_period_in_days, @@ -890,6 +948,10 @@ async def regenerate_token( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete_jwt( @@ -914,7 +976,7 @@ async def delete_jwt( AsyncHttpResponse[None] """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/virtual-accounts/{jsonable_encoder(id)}/jwt/{jsonable_encoder(jwt_id)}", + f"api/svc/v1/virtual-accounts/{encode_path_param(id)}/jwt/{encode_path_param(jwt_id)}", method="DELETE", request_options=request_options, ) @@ -924,4 +986,8 @@ async def delete_jwt( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/truefoundry_sdk/workspaces/raw_client.py b/src/truefoundry_sdk/workspaces/raw_client.py index 56b37d86..0ef1120d 100644 --- a/src/truefoundry_sdk/workspaces/raw_client.py +++ b/src/truefoundry_sdk/workspaces/raw_client.py @@ -6,8 +6,9 @@ from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse -from ..core.jsonable_encoder import jsonable_encoder +from ..core.jsonable_encoder import encode_path_param from ..core.pagination import AsyncPager, SyncPager +from ..core.parse_error import ParsingError from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata @@ -22,6 +23,7 @@ from ..types.workspace import Workspace from ..types.workspace_manifest import WorkspaceManifest from .types.workspaces_delete_response import WorkspacesDeleteResponse +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -112,6 +114,10 @@ def list( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_or_update( @@ -214,6 +220,10 @@ def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def search( @@ -285,6 +295,10 @@ def search( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def get( @@ -307,7 +321,7 @@ def get( Returns the workspaces associated with provided workspace id """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/workspaces/{jsonable_encoder(id)}", + f"api/svc/v1/workspaces/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -335,6 +349,10 @@ def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def delete( @@ -359,7 +377,7 @@ def delete( Successfully deletes the workspace and returns the workspace details along with a confirmation message. """ _response = self._client_wrapper.httpx_client.request( - f"api/svc/v1/workspaces/{jsonable_encoder(id)}", + f"api/svc/v1/workspaces/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -398,6 +416,10 @@ def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) @@ -489,6 +511,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_or_update( @@ -591,6 +617,10 @@ async def create_or_update( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def search( @@ -665,6 +695,10 @@ async def _get_next(): _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def get( @@ -687,7 +721,7 @@ async def get( Returns the workspaces associated with provided workspace id """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/workspaces/{jsonable_encoder(id)}", + f"api/svc/v1/workspaces/{encode_path_param(id)}", method="GET", request_options=request_options, ) @@ -715,6 +749,10 @@ async def get( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def delete( @@ -739,7 +777,7 @@ async def delete( Successfully deletes the workspace and returns the workspace details along with a confirmation message. """ _response = await self._client_wrapper.httpx_client.request( - f"api/svc/v1/workspaces/{jsonable_encoder(id)}", + f"api/svc/v1/workspaces/{encode_path_param(id)}", method="DELETE", request_options=request_options, ) @@ -778,4 +816,8 @@ async def delete( _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..25710dbe --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,21 @@ +import pytest + + +def _has_httpx_aiohttp() -> bool: + """Check if httpx_aiohttp is importable.""" + try: + import httpx_aiohttp # type: ignore[import-not-found] # noqa: F401 + + return True + except ImportError: + return False + + +def pytest_collection_modifyitems(config: pytest.Config, items: list) -> None: + """Auto-skip @pytest.mark.aiohttp tests when httpx_aiohttp is not installed.""" + if _has_httpx_aiohttp(): + return + skip_aiohttp = pytest.mark.skip(reason="httpx_aiohttp not installed") + for item in items: + if "aiohttp" in item.keywords: + item.add_marker(skip_aiohttp) diff --git a/tests/test_aiohttp_autodetect.py b/tests/test_aiohttp_autodetect.py new file mode 100644 index 00000000..69daf0bd --- /dev/null +++ b/tests/test_aiohttp_autodetect.py @@ -0,0 +1,116 @@ +import importlib +import sys +import unittest +from unittest import mock + +import httpx +import pytest + + +class TestMakeDefaultAsyncClientWithoutAiohttp(unittest.TestCase): + """Tests for _make_default_async_client when httpx_aiohttp is NOT installed.""" + + def test_returns_httpx_async_client(self) -> None: + """When httpx_aiohttp is not installed, returns plain httpx.AsyncClient.""" + with mock.patch.dict(sys.modules, {"httpx_aiohttp": None}): + from truefoundry_sdk.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=True) + self.assertIsInstance(client, httpx.AsyncClient) + self.assertEqual(client.timeout.read, 60) + self.assertTrue(client.follow_redirects) + + def test_follow_redirects_none(self) -> None: + """When follow_redirects is None, omits it from httpx.AsyncClient.""" + with mock.patch.dict(sys.modules, {"httpx_aiohttp": None}): + from truefoundry_sdk.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=None) + self.assertIsInstance(client, httpx.AsyncClient) + self.assertFalse(client.follow_redirects) + + def test_explicit_httpx_client_bypasses_autodetect(self) -> None: + """When user passes httpx_client explicitly, _make_default_async_client is not called.""" + + explicit_client = httpx.AsyncClient(timeout=120) + with mock.patch("truefoundry_sdk.base_client._make_default_async_client") as mock_make: + # Replicate the generated conditional: httpx_client if httpx_client is not None else _make_default_async_client(...) + result = explicit_client if explicit_client is not None else mock_make(timeout=60, follow_redirects=True) + mock_make.assert_not_called() + self.assertIs(result, explicit_client) + + +@pytest.mark.aiohttp +class TestMakeDefaultAsyncClientWithAiohttp(unittest.TestCase): + """Tests for _make_default_async_client when httpx_aiohttp IS installed.""" + + def test_returns_aiohttp_client(self) -> None: + """When httpx_aiohttp is installed, returns HttpxAiohttpClient.""" + import httpx_aiohttp # type: ignore[import-not-found] + + from truefoundry_sdk.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=True) + self.assertIsInstance(client, httpx_aiohttp.HttpxAiohttpClient) + self.assertEqual(client.timeout.read, 60) + self.assertTrue(client.follow_redirects) + + def test_follow_redirects_none(self) -> None: + """When httpx_aiohttp is installed and follow_redirects is None, omits it.""" + import httpx_aiohttp # type: ignore[import-not-found] + + from truefoundry_sdk.base_client import _make_default_async_client + + client = _make_default_async_client(timeout=60, follow_redirects=None) + self.assertIsInstance(client, httpx_aiohttp.HttpxAiohttpClient) + self.assertFalse(client.follow_redirects) + + +class TestDefaultClientsWithoutAiohttp(unittest.TestCase): + """Tests for _default_clients.py convenience classes (no aiohttp).""" + + def test_default_async_httpx_client_defaults(self) -> None: + """DefaultAsyncHttpxClient applies SDK defaults.""" + from truefoundry_sdk._default_clients import SDK_DEFAULT_TIMEOUT, DefaultAsyncHttpxClient + + client = DefaultAsyncHttpxClient() + self.assertIsInstance(client, httpx.AsyncClient) + self.assertEqual(client.timeout.read, SDK_DEFAULT_TIMEOUT) + self.assertTrue(client.follow_redirects) + + def test_default_async_httpx_client_overrides(self) -> None: + """DefaultAsyncHttpxClient allows overriding defaults.""" + from truefoundry_sdk._default_clients import DefaultAsyncHttpxClient + + client = DefaultAsyncHttpxClient(timeout=30, follow_redirects=False) + self.assertEqual(client.timeout.read, 30) + self.assertFalse(client.follow_redirects) + + def test_default_aiohttp_client_raises_without_package(self) -> None: + """DefaultAioHttpClient raises RuntimeError when httpx_aiohttp not installed.""" + import truefoundry_sdk._default_clients + + with mock.patch.dict(sys.modules, {"httpx_aiohttp": None}): + importlib.reload(truefoundry_sdk._default_clients) + + with self.assertRaises(RuntimeError) as ctx: + truefoundry_sdk._default_clients.DefaultAioHttpClient() + self.assertIn("pip install truefoundry-sdk[aiohttp]", str(ctx.exception)) + + importlib.reload(truefoundry_sdk._default_clients) + + +@pytest.mark.aiohttp +class TestDefaultClientsWithAiohttp(unittest.TestCase): + """Tests for _default_clients.py when httpx_aiohttp IS installed.""" + + def test_default_aiohttp_client_defaults(self) -> None: + """DefaultAioHttpClient works when httpx_aiohttp is installed.""" + import httpx_aiohttp # type: ignore[import-not-found] + + from truefoundry_sdk._default_clients import SDK_DEFAULT_TIMEOUT, DefaultAioHttpClient + + client = DefaultAioHttpClient() + self.assertIsInstance(client, httpx_aiohttp.HttpxAiohttpClient) + self.assertEqual(client.timeout.read, SDK_DEFAULT_TIMEOUT) + self.assertTrue(client.follow_redirects) diff --git a/tests/utils/test_http_client.py b/tests/utils/test_http_client.py index e2083580..bf0dbcc7 100644 --- a/tests/utils/test_http_client.py +++ b/tests/utils/test_http_client.py @@ -1,7 +1,9 @@ # This file was auto-generated by Fern from our API Definition. from typing import Any, Dict +from unittest.mock import AsyncMock, MagicMock, patch +import httpx import pytest from truefoundry_sdk.core.http_client import ( @@ -298,3 +300,363 @@ def test_preserves_base_url_path_prefix_trailing_slash() -> None: """Test that path prefixes in base URL are preserved.""" result = _build_url("https://cloud.example.com/org/tenant/api/", "/users") assert result == "https://cloud.example.com/org/tenant/api/users" + + +# --------------------------------------------------------------------------- +# Connection error retry tests +# --------------------------------------------------------------------------- + + +def _make_sync_http_client(mock_client: Any) -> HttpClient: + return HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + ) + + +def _make_async_http_client(mock_client: Any) -> AsyncHttpClient: + return AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + async_base_headers=None, + ) + + +@patch("truefoundry_sdk.core.http_client.time.sleep", return_value=None) +def test_sync_retries_on_connect_error(mock_sleep: MagicMock) -> None: + """Sync: connection error retries on httpx.ConnectError.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + http_client = _make_sync_http_client(mock_client) + + response = http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@patch("truefoundry_sdk.core.http_client.time.sleep", return_value=None) +def test_sync_retries_on_remote_protocol_error(mock_sleep: MagicMock) -> None: + """Sync: connection error retries on httpx.RemoteProtocolError.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.RemoteProtocolError("Remote end closed connection without response"), + _DummyResponse(), + ] + http_client = _make_sync_http_client(mock_client) + + response = http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@patch("truefoundry_sdk.core.http_client.time.sleep", return_value=None) +def test_sync_connection_error_exhausts_retries(mock_sleep: MagicMock) -> None: + """Sync: connection error exhausts retries then raises.""" + mock_client = MagicMock() + mock_client.request.side_effect = httpx.ConnectError("connection failed") + http_client = _make_sync_http_client(mock_client) + + with pytest.raises(httpx.ConnectError): + http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + assert mock_sleep.call_count == 2 + + +@patch("truefoundry_sdk.core.http_client.time.sleep", return_value=None) +def test_sync_connection_error_respects_max_retries_zero(mock_sleep: MagicMock) -> None: + """Sync: connection error respects max_retries=0.""" + mock_client = MagicMock() + mock_client.request.side_effect = httpx.ConnectError("connection failed") + http_client = _make_sync_http_client(mock_client) + + with pytest.raises(httpx.ConnectError): + http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 0}, + ) + + # No retries, just the initial attempt + assert mock_client.request.call_count == 1 + mock_sleep.assert_not_called() + + +@pytest.mark.asyncio +@patch("truefoundry_sdk.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_retries_on_connect_error(mock_sleep: AsyncMock) -> None: + """Async: connection error retries on httpx.ConnectError.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + ) + http_client = _make_async_http_client(mock_client) + + response = await http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@pytest.mark.asyncio +@patch("truefoundry_sdk.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_retries_on_remote_protocol_error(mock_sleep: AsyncMock) -> None: + """Async: connection error retries on httpx.RemoteProtocolError.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.RemoteProtocolError("Remote end closed connection without response"), + _DummyResponse(), + ] + ) + http_client = _make_async_http_client(mock_client) + + response = await http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + assert mock_client.request.call_count == 2 + mock_sleep.assert_called_once() + + +@pytest.mark.asyncio +@patch("truefoundry_sdk.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_connection_error_exhausts_retries(mock_sleep: AsyncMock) -> None: + """Async: connection error exhausts retries then raises.""" + mock_client = MagicMock() + mock_client.request = AsyncMock(side_effect=httpx.ConnectError("connection failed")) + http_client = _make_async_http_client(mock_client) + + with pytest.raises(httpx.ConnectError): + await http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + assert mock_sleep.call_count == 2 + + +# --------------------------------------------------------------------------- +# base_max_retries constructor parameter tests +# --------------------------------------------------------------------------- + + +def test_sync_http_client_default_base_max_retries() -> None: + """HttpClient defaults to base_max_retries=2.""" + http_client = HttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + ) + assert http_client.base_max_retries == 2 + + +def test_async_http_client_default_base_max_retries() -> None: + """AsyncHttpClient defaults to base_max_retries=2.""" + http_client = AsyncHttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + ) + assert http_client.base_max_retries == 2 + + +def test_sync_http_client_custom_base_max_retries() -> None: + """HttpClient accepts a custom base_max_retries value.""" + http_client = HttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_max_retries=5, + ) + assert http_client.base_max_retries == 5 + + +def test_async_http_client_custom_base_max_retries() -> None: + """AsyncHttpClient accepts a custom base_max_retries value.""" + http_client = AsyncHttpClient( + httpx_client=MagicMock(), # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_max_retries=5, + ) + assert http_client.base_max_retries == 5 + + +@patch("truefoundry_sdk.core.http_client.time.sleep", return_value=None) +def test_sync_base_max_retries_zero_disables_retries(mock_sleep: MagicMock) -> None: + """Sync: base_max_retries=0 disables retries when no request_options override.""" + mock_client = MagicMock() + mock_client.request.side_effect = httpx.ConnectError("connection failed") + http_client = HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, + ) + + with pytest.raises(httpx.ConnectError): + http_client.request(path="/test", method="GET") + + # No retries, just the initial attempt + assert mock_client.request.call_count == 1 + mock_sleep.assert_not_called() + + +@pytest.mark.asyncio +@patch("truefoundry_sdk.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_base_max_retries_zero_disables_retries(mock_sleep: AsyncMock) -> None: + """Async: base_max_retries=0 disables retries when no request_options override.""" + mock_client = MagicMock() + mock_client.request = AsyncMock(side_effect=httpx.ConnectError("connection failed")) + http_client = AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, + ) + + with pytest.raises(httpx.ConnectError): + await http_client.request(path="/test", method="GET") + + # No retries, just the initial attempt + assert mock_client.request.call_count == 1 + mock_sleep.assert_not_called() + + +@patch("truefoundry_sdk.core.http_client.time.sleep", return_value=None) +def test_sync_request_options_override_base_max_retries(mock_sleep: MagicMock) -> None: + """Sync: request_options max_retries overrides base_max_retries.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.ConnectError("connection failed"), + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + http_client = HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, # base says no retries + ) + + # But request_options overrides to allow 2 retries + response = http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + assert response.status_code == 200 + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + + +@pytest.mark.asyncio +@patch("truefoundry_sdk.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_request_options_override_base_max_retries(mock_sleep: AsyncMock) -> None: + """Async: request_options max_retries overrides base_max_retries.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.ConnectError("connection failed"), + httpx.ConnectError("connection failed"), + _DummyResponse(), + ] + ) + http_client = AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=0, # base says no retries + ) + + # But request_options overrides to allow 2 retries + response = await http_client.request( + path="/test", + method="GET", + request_options={"max_retries": 2}, + ) + + assert response.status_code == 200 + # 1 initial + 2 retries = 3 total attempts + assert mock_client.request.call_count == 3 + + +@patch("truefoundry_sdk.core.http_client.time.sleep", return_value=None) +def test_sync_base_max_retries_used_as_default(mock_sleep: MagicMock) -> None: + """Sync: base_max_retries is used when request_options has no max_retries.""" + mock_client = MagicMock() + mock_client.request.side_effect = [ + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + _DummyResponse(), + ] + http_client = HttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=3, + ) + + response = http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + # 1 initial + 3 retries = 4 total attempts + assert mock_client.request.call_count == 4 + + +@pytest.mark.asyncio +@patch("truefoundry_sdk.core.http_client.asyncio.sleep", new_callable=AsyncMock) +async def test_async_base_max_retries_used_as_default(mock_sleep: AsyncMock) -> None: + """Async: base_max_retries is used when request_options has no max_retries.""" + mock_client = MagicMock() + mock_client.request = AsyncMock( + side_effect=[ + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + httpx.ConnectError("fail"), + _DummyResponse(), + ] + ) + http_client = AsyncHttpClient( + httpx_client=mock_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + base_max_retries=3, + ) + + response = await http_client.request(path="/test", method="GET") + + assert response.status_code == 200 + # 1 initial + 3 retries = 4 total attempts + assert mock_client.request.call_count == 4