diff --git a/.fern/metadata.json b/.fern/metadata.json index 8141518..87b6087 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -5,9 +5,9 @@ "generatorConfig": { "client_class_name": "Wavix" }, - "originGitCommit": "1498ee51f17678c87170c7d44e0568dbebd562b6", + "originGitCommit": "d29c16cfdf89e832f7792c0c920d6935e231f140", "originGitCommitIsDirty": false, "invokedBy": "manual", - "requestedVersion": "1.0.0", - "sdkVersion": "1.0.0" + "requestedVersion": "1.1.1", + "sdkVersion": "1.1.1" } \ No newline at end of file diff --git a/.fern/replay.lock b/.fern/replay.lock new file mode 100644 index 0000000..05b5a4c --- /dev/null +++ b/.fern/replay.lock @@ -0,0 +1,16 @@ +# DO NOT EDIT MANUALLY - Managed by Fern Replay +version: "1.0" +generations: + - commit_sha: 953cb4637b1754043a53d2712610e9d04ba128da + tree_hash: 93d0b63cf19d5ed7f7ad2f5460a7d8e283d9a233 + timestamp: 2026-09-23T07:48:16.908Z + cli_version: unknown + generator_versions: {} + - commit_sha: 6b508b41c6492c2ec5f96a92f62d2805d413d3d1 + tree_hash: 777bcb81277b94c1f51d795c66f3e87afaba9718 + timestamp: 2026-09-23T07:48:17.300Z + cli_version: unknown + generator_versions: + fernapi/fern-python-sdk: 5.14.18 +current_generation: 6b508b41c6492c2ec5f96a92f62d2805d413d3d1 +patches: [] diff --git a/.fernignore b/.fernignore index 00017a4..981a31a 100644 --- a/.fernignore +++ b/.fernignore @@ -3,3 +3,6 @@ LICENSE README.md .fernignore SECURITY.md +.fern/replay.lock +.fern/replay.yml +.gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..74928d6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.fern/replay.lock linguist-generated=true diff --git a/poetry.lock b/poetry.lock index bef81c0..32e8e78 100644 --- a/poetry.lock +++ b/poetry.lock @@ -15,132 +15,132 @@ files = [ [[package]] name = "aiohttp" -version = "3.14.1" +version = "3.14.3" description = "Async http client/server framework (asyncio)" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"aiohttp\"" files = [ - {file = "aiohttp-3.14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8f6bb621e5863cfe8fe5ff5468002d200ec31f30f1280b259dc505b02595099e"}, - {file = "aiohttp-3.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f7215cb3933784f79ed20e5f050e15984f390424339b22375d5a53c933a0491"}, - {file = "aiohttp-3.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9d4e294455b23a68c9b8f042d0e8e377a265bcb15332753695f6e5b6819e0ce"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b238af795833d5731d049d82bc84b768ae6f8f97f0495963b3ed9935c5901cc3"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e4e5e0ae56914ecdbf446493addefc0159053dd53962cef37d7839f37f73d505"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:092e4ce3619a7c6dee52a6bdabda973d9b34b66781f840ce93c7e0cec30cf521"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb33777ea21e8b7ecde0e6fc84f598be0a1192eab1a63bc746d75aa75d38e7bd"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23119f8fd4f5d16902ed459b63b100bcd269628075162bddac56cc7b5273b3fb"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:57fc6745a4b7d0f5a9eb4f40a69718be6c0bc1b8368cc9fe89e90118719f4f42"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6fd35beba67c4183b09375c5fff9accb47524191a244a99f95fd4472f5402c2b"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:672b9d65f42eb877f5c3f234a4547e4e1a226ca8c2eed879bb34670a0ce51192"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:24ba13339fed9251d9b1a1bec8c7ab84c0d1675d79d33501e11f94f8b9a84e05"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:94da27378da0610e341c4d30de29a191672683cc82b8f9556e8f7c7212a020fe"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:52cdac9432d8b4a719f35094a818d95adcae0f0b4fe9b9b921909e0c87de9e7d"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:672ac254412a24d0d0cf00a9e6c238877e4be5e5fa2d188832c1244f45f31966"}, - {file = "aiohttp-3.14.1-cp310-cp310-win32.whl", hash = "sha256:2fe3607e71acc6ebb0ec8e492a247bf7a291226192dc0084236dfc12478916f6"}, - {file = "aiohttp-3.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:30099eda75a53c32efb0920e9c33c195314d2cc1c680fbfd30894932ac5f27df"}, - {file = "aiohttp-3.14.1-cp310-cp310-win_arm64.whl", hash = "sha256:5a837f49d901f9e368651b676912bff1104ed8c1a83b280bcd7b29adccef5c9c"}, - {file = "aiohttp-3.14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aa00140699487bd435fde4342d85c94cb256b7cd3a5b9c3396c67f19922afda2"}, - {file = "aiohttp-3.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c1af67559445498b502030c35c59db59966f47041ca9de5b4e707f86bd10b5f"}, - {file = "aiohttp-3.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d44ec478e713ee7f29b439f7eb8dc2b9d4079e11ae114d2c2ac3d5daf30516c8"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3b1a184a9a8f548a6b73f1e26b96b052193e4b3175ed7342aaf1151a1f00a04"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5f2504bc0322437c9a1ff6d3333ca56c7477b727c995f036b976ae17b98372c8"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73f05ea02013e02512c3bf42714f1208c57168c779cc6fe23516e4543089d0a6"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:797457503c2d426bee06eef808d07b31ede30b65e054444e7de64cad0061b7af"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b821a1f7dedf7e37450654e620038ac3b2e81e8fa6ea269337e97101978ec730"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4cd96b5ba05d67ed0cf00b5b405c8cd99586d8e3481e8ee0a831057591af7621"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d459b98a932296c6f0e94f87511a0b1b90a8a02c30a50e60a297619cd5a58ee"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:764457a7be60825fb770a644852ff717bcbb5042f189f2bd16df61a81b3f6573"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f7a16ef45b081454ef844502d87a848876c490c4cb5c650c230f6ec79ed2c1e7"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2fbc3ed048b3475b9f0cbcb9978e9d2d3511acd91ead203af26ed9f0056004cf"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bedb0cd073cc2dc035e30aeb99444389d3cd2113afe4ef9fcd23d439f5bade85"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b6feea921016eb3d4e04d65fc4e9ca402d1a3801f562aef94989f54694917af3"}, - {file = "aiohttp-3.14.1-cp311-cp311-win32.whl", hash = "sha256:313701e488100074ce99850404ee36e741abf6330179fec908a1944ecf570126"}, - {file = "aiohttp-3.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:03ab4530fdcb3a543a122ba4b65ac9919da9fe9f78a03d328a6e38ff962f7aa5"}, - {file = "aiohttp-3.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:486f7d16ed54c39c2cbd7ca71fd8ba2b8bb7860df65bd7b6ed640bab96a38a8b"}, - {file = "aiohttp-3.14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d35143e27778b4bb0fb189562d7f275bff79c62ab8e98459717c0ea617ff2480"}, - {file = "aiohttp-3.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bcfb80a2cc36fba2534e5e5b5264dc7ae6fcd9bf15256da3e53d2f499e6fa29d"}, - {file = "aiohttp-3.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27fd7c91e51729b4f7e1577865fa6d34c9adccbc39aabe9000285b48af9f0ec2"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c567bf9eaf664280116a8688f63016e6b32db2505908e2bdaca1b6438142f2"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f5e6ff2bdbb8f4cd3fbe41f99e25bbcd58e3bf9f13d3dd31a11e7917251cc77a"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f73e01dc37122325caf079982621262f96d74823c179038a82fddfc50359264"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb2c0c80d431c0d03f2c7dbf125150fedd4f0de17366a7ca33f7ccb822391842"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6fc1a85fa7194a1a7d19f44e8609180f4a8eb5fa4c7ed8b4355f080fad235c"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:686b6c0d3911ec387b444ddf5dc62fb7f7c0a7d5186a7861626496a5ab4aff95"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c6fa4dc7ad6f8109c70bb1499e589f76b0b792baf39f9b017eb92c8a81d0a199"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:87a5eea1b2a5e21e1ebdbb33ad4165359189327e63fc4e4894693e7f821ac817"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c1421eb01d4fd608d88cc8290211d177a58532b55ad94076fb349c5bf467f0a"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:34b257ec41345c1e8f2df68fa908a7952f5de932723871eb633ecbbff396c9a4"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:de538791a80e5d862addbc183f70f0158ac9b9bb872bb147f1fd2a683691e087"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f71173be42d3241d428f760122febb748de0623f44308a6f120d0dd9ec572e3"}, - {file = "aiohttp-3.14.1-cp312-cp312-win32.whl", hash = "sha256:ec8dc383ee57ea3e883477dcca3f11b65d58199f1080acaf4cd6ad9a99698be4"}, - {file = "aiohttp-3.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2aa92c87868cd13674989f9ee83e5f9f7ea4237589b728048e1f0c8f6caa3271"}, - {file = "aiohttp-3.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:2c840c90759922cb5e6dda94596e079a30fb5a5ba548e7e0dc00574703940847"}, - {file = "aiohttp-3.14.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:b3a03285a7f9c7b016324574a6d92a1c895da6b978cb8f1deee3ac72bc6da178"}, - {file = "aiohttp-3.14.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:2a73f487ab8ef5abbb24b7aa9b73e98eaba9e9e031804ff2416f02eca315ccaf"}, - {file = "aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:915fbb7b41b115192259f8c9ae58f3ddc444d2b5579917270211858e606a4afd"}, - {file = "aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:7fb4bdf95b0561a79f259f9d28fbc109728c5ee7f27aff6391f0ca703a329abe"}, - {file = "aiohttp-3.14.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1b9748363260121d2927704f5d4fc498150669ca3ae93625986ee89c8f80dcd4"}, - {file = "aiohttp-3.14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:86a6dab78b0e43e2897a3bbe15745aa60dc5423ca437b7b0b164c069bf91b876"}, - {file = "aiohttp-3.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dfd6e47d3c44c2279907607f73a4240b88c69eb8b90da7e2441a8045dfd21da"}, - {file = "aiohttp-3.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:317acd9f8602858dc7d59679812c376c7f0b97bcbbf16e0d6237f54141d8a8a6"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd869c427324e5cb15195793de951295710db28be7d818247f3097b4ab5d4b96"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93b032b5ec3255473c143627d21a69ac74ae12f7f33974cb587c564d11b1066f"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f234b4deb12f3ad59127e037bc57c40c21e45b45282df7d3a55a0f409f595296"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9af6779bfb46abf124068327abcdf9ce95c9ef8287a3e8da76ccf2d0f16c28fa"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:faccab372e66bc76d5731525e7f1143c922271725b9d38c9f97edcc66266b451"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f380468b09d2a81633ee863b0ec5648d364bd17bb8ecfb8c2f387f7ac1faf42c"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:97e704dcd26271f5bda3fa07c3ce0fb76d6d3f8659f4baa1a24442cc9ba177ca"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:269b76ac5394092b95bc4a098f4fc6c191c083c3bd12775d1e30e663132f6a09"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0b3e614340c889d575451696374c9d17affd54cd607ca0babed8f8c37b9397"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5663ee9257cfa1add7253a7da3035a02f31b6600ec48261585e1800a81533080"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:603a2c834142172ffddc054067f5ec0ca65d57a0aa98a71bc81952573208e345"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb21957bb8aca671c1765e32f58164cf0c50e6bf41c0bbbd16da20732ecaf588"}, - {file = "aiohttp-3.14.1-cp313-cp313-win32.whl", hash = "sha256:e509a55f681e6158c20f70f102f9cf61fb20fbc382272bc6d94b7343f2582780"}, - {file = "aiohttp-3.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:1ac8531b638959718e18c2207fbfe297819875da46a740b29dfa29beba64355a"}, - {file = "aiohttp-3.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:250d14af67f6b6a1a4a811049b1afa69d61d617fca6bf33149b3ab1a6dbcf7b8"}, - {file = "aiohttp-3.14.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:7c106c26852ca1c2047c6b80384f17100b4e439af276f21ef3d4e2f450ae7e15"}, - {file = "aiohttp-3.14.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:20205f7f5ade7aaec9f4b500549bbc071b046453aed72f9c06dcab87896a83e8"}, - {file = "aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:62a759436b29e677181a9e76bab8b8f689a29cb9c535f45f7c48c9c830d3f8c3"}, - {file = "aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:2964cbf553df4d7a57348da44d961d871895fc1ee4e8c322b2a95612c7b17fba"}, - {file = "aiohttp-3.14.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:237651caadc3a59badd39319c54642b5299e9cc98a3a194310e55d5bb9f5e397"}, - {file = "aiohttp-3.14.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:896e12dfdbbab9d8f7e16d2b28c6769a60126fa92095d1ebf9473d02593a2448"}, - {file = "aiohttp-3.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d03f281ed22579314ba00821ce20115a7c0ac430660b4cc05704a3f818b3e004"}, - {file = "aiohttp-3.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07eabb979d236335fed927e137a928c9adfb7df3b9ec7aa31726f133a62be983"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4fe1f1087cbadb280b5e1bb054a4f00d1423c74d6626c5e48400d871d34ecefe"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:367a9314fdc79dab0fac96e216cb41dd73c85bdca85306ce8999118ba7e0f333"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a24f677ebe83749039e7bdf862ff0bbb16818ae4193d4ef96505e269375bcce0"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c83afe0ba876be7e943d2e0ba645809ad441575d2840c895c21ee5de93b9377a"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:634e385930fb6d2d479cf3aa66515955863b77a5e3c2b5894ca259a25b308602"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeea07c4397bbc57719c4eed8f9c284874d4f175f9b6d57f7a1546b976d455ca"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:335c0cc3e3545ce98dcb9cfcb836f40c3411f43fa03dab757597d80c89af8a35"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ae6be797afdef264e8a84864a85b196ca06045586481b3df8a967322fd2fa844"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:8560b4d712474335d08907db7973f71912d3a9a8f1dee992ec06b5d2fe359496"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7edd08e0a5deb1e8564a2fcd8f4561014a3f05252334671bbf55ddd47db0e5"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b6ff7fcee63287ae57b5df3e4f5957ce032122802509246dec1a5bcc55904c95"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ffbb2f4ec1ceaff7e07d43922954da26b223d188bf30658e561b98e23089444"}, - {file = "aiohttp-3.14.1-cp314-cp314-win32.whl", hash = "sha256:a9875b46d910cff3ea2f5962f9d266b465459fe634e22556ab9bd6fc1192eea0"}, - {file = "aiohttp-3.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:af8b4b81a960eeaf1234971ac3cd0ba5901f3cd42eae42a46b4d089a8b492719"}, - {file = "aiohttp-3.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:cf4491381b1b57425c315a56a439251b1bdac07b2275f19a8c44bc57744532ec"}, - {file = "aiohttp-3.14.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:819c054312f1af92947e6a55883d1b66feefab11531a7fc45e0fb9b63880b5c2"}, - {file = "aiohttp-3.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10ee9c1753a8f706345b22496c79fbddb5be0599e0823f3738b1534058e25340"}, - {file = "aiohttp-3.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1601cc37baf5750ccacae618ec2daf020769581695550e3b654a911f859c563d"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d6e0ac9da31c9c04c84e1c0182ad8d6df35965a85cae29cd71d089621b3ae94"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e8f2d660c350b3d0e259c7a7e3d9b7fc8b41210cbcc3d4a7076ff0a5e5c2fdc"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4691802dda97be727f79d86818acaad7eb8e9252626a1d6b519fedbb92d5e251"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c389c482a7e9b9dc3ee2701ac46c4125297a3818875b9c305ddb603c04828fd1"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc0cacab7ba4e56f0f81c82a98c09bed2f39c940107b03a34b168bdf7597edd3"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:979ed4717f59b8bb12e3963378fa285d93d367e15bcd66c721311826d3c44a6c"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38e1e7daaea81df51c952e18483f323d878499a1e2bfe564790e0f9701d6f203"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4132e72c608fe9fecb8f409113567605915b83e9bdd3ea56538d2f9cd35002f1"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:eefd9cc9b6d4a2db5f00a26bc3e4f9acf71926a6ec557cd56c9c6f27c290b665"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b165790117eea512d7f3fb22f1f6dad3d55a7189571993eb015591c1401276d1"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ed09c7eb1c391271c2ed0314a51903e72a3acb653d5ccfc264cdf3ef11f8269d"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:99abd37084b82f5830c635fddd0b4993b9742a66eb746dacf433c8590e8f9e3c"}, - {file = "aiohttp-3.14.1-cp314-cp314t-win32.whl", hash = "sha256:47ddf841cdecc810749921d25606dee45857d12d2ad5ddb7b5bd7eab12e4b365"}, - {file = "aiohttp-3.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5e78b522b7a6e27e0b25d19b247b75039ac4c94f99823e3c9e53ae1603a9f7e9"}, - {file = "aiohttp-3.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:90d53f1609c29ccc2193945ef732428382a28f78d0456ae4d3daf0d48b74f0f6"}, - {file = "aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035"}, + {file = "aiohttp-3.14.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:eb0495d778817619273c108784292be161a924b9f5ae5cbbc70a2caa6838250b"}, + {file = "aiohttp-3.14.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3c200cf9757edd785051dc699c7ecbec22110dbfcb3fefc7a9f9695eda8ea7a"}, + {file = "aiohttp-3.14.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd51ebf9d3a00c074df4ede271023f4d2dba289bcc740b88191872716014e3c5"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:134ac5ddcf61c6fad984b9a5727d83492ada43d63471db20fb73042c13fca62f"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:70c987b27534f9ae1a723f47ae921571d616da21d3208282bf4c52af5164ac43"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1b59533861b70a2185c8f4f350f791f39d64358ef6944ce71c5240c9ec0982c9"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1c5281acc88b92396f88c7e1e2748f8466689df22b80170e4f51efa712fb47a8"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48d67b87db6279c044760787eb01f6413032c2e6f3ba1cafaa492b1c8e578479"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f53bcd52f585e1ac3e590d61434eb61f9a88c38df041b4ea126d97144344a77b"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0fdea2281997af69da84c77ffa6f5938a0285f21fb3887c249d67419ca865b3d"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cda5fd5c95ad7a125a2e8464acc78b98b94c475a3780d6aa0aa157c93f470f4d"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6debfa7312ff9d4c124dc71d72e9a0a4b9e0879e48ba6fcb42bef5c3300289e2"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:f4e05329faa0ea1a404b37de4f034fd2c2defcca06a68dc6745e4e56c88e8a48"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a3a8296e7ab5c295f53f1041487cb088e1480775aafbf7fe545d93b770a0f96f"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5373dc80ad1aa2fb9ad95c83f24eef418bbda3a61375f128e5b0192e4f3f9b32"}, + {file = "aiohttp-3.14.3-cp310-cp310-win32.whl", hash = "sha256:a3e22975f905b89a55a488c2a08f2fdb2186175349e917d48985cc468a3d4c6e"}, + {file = "aiohttp-3.14.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdd0e2834dce1a26c1bbe26464861e16bbe217042cbff619247c11594472518c"}, + {file = "aiohttp-3.14.3-cp310-cp310-win_arm64.whl", hash = "sha256:eac645b09bcfdf73df7536331f0678c1086ea250981118ddb5199e17ccef72bb"}, + {file = "aiohttp-3.14.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e568e14940c09955aa51f4e645b6daa18a581c5dcfcd73744dcc86a856e3ced3"}, + {file = "aiohttp-3.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:54cfcdee2770dac994417cbb0ee1f3eb0e7cb6b30c79bf44f2c02ff79ec5124a"}, + {file = "aiohttp-3.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:21c016079415ed3fd676963e9793700a566d85dbbd6bfc564b9b2d209147dcc8"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6088ec9894113802bddb3c09e974929aed2c7b3a8c456219b8aab4481f1a239"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:16ea7e24c309fb7c0bbd505d149abe4fe4dccfb8db911db7dbec0921bc889a6f"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56f355e79f71aef2a85c80305cc915f894b170dba76de5fe84f6351939b83c06"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:18c441d0a8fca6de8d1f546849b9f0ab20d435993e2c5b59562b2fae6be2f929"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53e7b4ce82b54a8bcc71b3b67a5cbd177ca1d7f592cbc92cd38b7349f73482db"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f55119f7bf25f49ed210f6096090715da24f2943c62102448915fde3c62877ce"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9aa6e61fdf20105c4144e755bd586008ff450791d67b1c8146fdc15959c4d51c"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ccd4893707b3e2a13e39c90d43cf80edf2e4d0457935bcc103bf2346214c3f15"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2466434105a4e03113c36ec775cc2ebe6676b62eae326fa670bb607ef788c1c"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ba59d59aba08ac02fc03b0c8983ccd5ee39a199d0552ce9e6d2b4845b34d59ae"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ed099d105449c4f9e84f24af203cd131349d4761d8813fa7e02c32e7128cd910"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:152516815ef926786a0b6ae2b8f1fd2e0c71582dee0b435636865316fd4891b7"}, + {file = "aiohttp-3.14.3-cp311-cp311-win32.whl", hash = "sha256:a4af35c443e0b1a1bd6a8af3f3485d7fda15c142751a00f3ff8090f0b93346fa"}, + {file = "aiohttp-3.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:e1e74298bab6ee0d6e749ed4fd1901c7e604bdda32c03d787a2cc71c46d0433d"}, + {file = "aiohttp-3.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:03cd2bde3d7f085b64e549c985f4bb928cad7e8ecf5323bfca320db548d81b39"}, + {file = "aiohttp-3.14.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:39aded8c7f3b935b54aab1d8d73c70ec0ee2d3ec3b943e0e86611bc150ba47f5"}, + {file = "aiohttp-3.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5bcb6ff3fdab1258a192679ff1a05d44f59626430aa05cd1a9d2447423599228"}, + {file = "aiohttp-3.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:617105e2c3018ee38d0c8ce5ee3c84f621a6d8b9f723202aacaff28449ca91ee"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f631fe87a6f30df5fbe6d79640b25e4cffb38c31c7fb6f10871517b84b0f8c1a"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a94dbaae5ae27bd849c93570669bff91e0510f33a80805738e3de72a7be0447b"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8f2f1c4c032c7cedd7d8da6f54c97b70266c6570c3108d3fdffee7188bb70529"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ea05e1f97ceea523942d9b2a7d7c0359d781d683d6b043f5943a602b14da4787"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:543906c127fb1d929b95076db19b83fa2d46751006ff1e23b093aa5ac4d8db42"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0a5ff2dfbb9ce645fa5b8ef3e02c6c0b9cc3f6030ff863d0c51fffc50cb5541b"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:041badb8f84396357c4d3ad26de6afd7a32b112f43d3c63045c0c8278cfd2043"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:530125ee1163c4219af35dc3aa1206e541e7b31b6efc1a3f93b70a136f65d427"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8653fd547c93a61aadc612007790f5555cdd18946fa48cf45e26d8ea4ea473d"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:89176250f686cb9853c0fb7ead90e639e915b84a6f43eedc2a4e7ec21f1037f0"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3a26434dafe408229ff3403458ca58de24fb51936504decac49ce6755f77e59d"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d1558173930a5a8d3069cee5c92fc91c87c4dbcb099debbb3622053717145a19"}, + {file = "aiohttp-3.14.3-cp312-cp312-win32.whl", hash = "sha256:16100ad3ab8d649fdfbee87602d9d2dcdca9df0b9eda8a1b5fdc0d41f96da559"}, + {file = "aiohttp-3.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:33a2d7c28d33797a2e99923dffa63f83d908a19b6bf26cfe80fa790aa5e1a75a"}, + {file = "aiohttp-3.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:362a3fd481769cac1a824514bcd86fda51c65e8fe6e051099e008fddde6db17c"}, + {file = "aiohttp-3.14.3-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:2e9878ae68e4a5f1c0abe4dd497dbc3d51946f5837b56759e2a02e78fa90ef86"}, + {file = "aiohttp-3.14.3-cp313-cp313-android_21_x86_64.whl", hash = "sha256:f3d2669fe7dec7fc359ecdb5984b29b50d85d5d00f8c1cb61de4f4a24ee42627"}, + {file = "aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:cc7cb243a68167172f48c1fd43cee91ec4b1d40cefd190edd43369d1a6bc9c82"}, + {file = "aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:78253b573e6ffab5028924fc98bc281aae05445969982a10864bc360dea2016c"}, + {file = "aiohttp-3.14.3-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7041d52c3a7fa20c9e8c182b534704abb19502c8bdcbde7ab23bfda6f642394f"}, + {file = "aiohttp-3.14.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ac74facc01463f138b0da5580329cfcc82818dea5656e83ddcd11268fc12ff80"}, + {file = "aiohttp-3.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d6218d92e450824e9b4881f44e8c09f1853b490f9a64130801024a4793b1b3b0"}, + {file = "aiohttp-3.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:11fb37ef075669eee52ab1928fbf6e1741fada40409fa309ebde9607a962aebf"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55bdcc472aafe2de4a253045cc128007a64f1e0264fb675791e132ea5edaa3bd"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c39846c3aad97a8530c89d7a3869a8f8e9e3762c6ac0504481e5c80948f7e807"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5895ef58c4620afe02fa16044f023dc4dafec08158f9d08874a46a7dbc0341b8"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa9467a8113aa69d3d7c55a70ef0b7c636010a40993f3df9d9d0d73b3eb7ef24"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7d2deec16eeedf55f2c7cf75b521ea3856a5177e123844f8fd0f114ce252cb5"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dd54d0e8717de95939766febac482ac0474d8ac3b048115f9f2b1d23a16e7db4"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:df82f3787c940c94986b34222d59c9e38843fba85139f36e85255a82ad5355a9"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:42a67efc36300d052fb4508a53e8b6901b9284b599ae63945c377569c5fcc1e1"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7a75aa63cbf9b21cfaf60dc2657e19df2c2867d91707d653fee171ffeedd1371"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e92eb8acc45eb6a9f4935071a77edf5b85cc6f8dfad5cd99e97653c26593cdde"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b014a6ed7cf912e787149fdc529166d3ceabac23f26efeea3158c9aba2354e7e"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d4f72af88ac2474bb5bca640030320e3d38a0163a1d7533500e87be458eef71"}, + {file = "aiohttp-3.14.3-cp313-cp313-win32.whl", hash = "sha256:5f08ec777f35ee70720233b8b9811d3bb5d728137f30ac91b7457709c3261ac0"}, + {file = "aiohttp-3.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:dff9461ec275f22135650d5ba4b4931a11f3958df7dfbb8db630000d4dee0883"}, + {file = "aiohttp-3.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:ddcac3c6b382e81f1dd0499199d4136b877beb4cb5ef770bbbfba56c4b8f55d2"}, + {file = "aiohttp-3.14.3-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:49f7325beb0f85ef4aef5f48f490269575f83e6e2acad00a1d80b807eb027062"}, + {file = "aiohttp-3.14.3-cp314-cp314-android_24_x86_64.whl", hash = "sha256:e3be98a7c30b8c25d573dafba7171d66dfb05ee6a9070fc46535464ff97700a6"}, + {file = "aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:614c61d478b83953e261d02bb2df750f17227cd33ef8002945bf5aebbde21919"}, + {file = "aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:1caa7b0d05f3e3a36f87788c59e970a7ee1cefcfcbb924a9f138c4a6551c9cb7"}, + {file = "aiohttp-3.14.3-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:dfa68deb2a443bdaa3ea5297b0699c1464f08aef3812b486d1348eee61b07dc0"}, + {file = "aiohttp-3.14.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:e72ee89e28d907a18f46959b4eb0bb06701cc7f8cf4366e00029e2ccfaaf5924"}, + {file = "aiohttp-3.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ad4c8b7488d745d2ca4838ebd8ae5ba9b56341d30b1da43640e4ce87f9f49646"}, + {file = "aiohttp-3.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:db332af25642007330fca8be5c4d194caf2bea7a7fc84415aff3497af5dfee6b"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25bd2708db6bdf6a6630dd37bdcdfcb47c4434d22ac69c64665b802910140b30"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:cef89a58e628c4efcac3275c2d68083f82426dcdc89c1492a6f654f9f7ea6ab9"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c23ec8ee9d5ab2f5421f9c7fffce208435607af27fd46d4a44e031954352838f"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e2667f0bbe7eb6c74eae5e9691441ad186e5845ca3cff63230fc09c4e7514f5d"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18cb43369747b2ae007bd2655fb8e63a099c2ff1d207962943636dac989b3147"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d77640cc618c1d99fc4f8589c0f24a730adfa54eb1e57ef7bf0c8dfb78da898c"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:53e5179d8abb5710f8e83ba207c41c8d1261fcffd4616500e15ca2b7a33be10a"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:cd817772b2fcf2b8c0905795318485f9ec16eae60b29feb7f4c77085311637f0"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4e3ac92d90e92773b2362d506068e9a948192bd553e743c5b2429e28527c8661"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3f42e9b78301f11c8f861746175d8b9c1ccef713fcad9eab396e2f6db8ed4a22"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9d9edccfe496b476db5f398d97b865e9a6752bcf8aec4eef8390ce20fb64bb41"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c5ec8fb1bcc31a8466f74aaf26c345d5c386fa4bd08a3f0eb9c7a4a3fe8b5bf"}, + {file = "aiohttp-3.14.3-cp314-cp314-win32.whl", hash = "sha256:38901a84da3ce22249f6e860bf8f90d141bcab7da090cc398f8bb58c0e44b7da"}, + {file = "aiohttp-3.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:8b3b60de05f3dcb6f6a00f818bb2ec781cee4de0645f59ccaf99b1d1823b6100"}, + {file = "aiohttp-3.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:1576145bdceeb92382d899751e12743a3a5b8e460a841e3e50543859e54864dc"}, + {file = "aiohttp-3.14.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:8800c996b01c2772a783e3e46f3e1abd5823029adca0df54231960de9bfefa5b"}, + {file = "aiohttp-3.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ebe8e504f058fe91223351cecd2d9d6946c9d241bb0250d898ffbdf584cc72b0"}, + {file = "aiohttp-3.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:30402d03a7c0ff52bce290b57e564e9079fd9d0cb545c8aba73f86a103162d2e"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fc7b5bfec6573f3ae844f457fdde5adeb713f8b8e4a81ad64fc207b49383716"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8a5fd34f7f7410d1730d5c2ba873cacb2eed3fede366feb268a70ba22581ed8f"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:270d3dace9ca2f10f0da5d8ebe519b7a310fc6112ed916e32df5866df0888553"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3ae5b3a59436d089b5395d910121a390feed4d00578eb95a0fd1a329fe963100"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2498f0fe69ead802f9675beca44a7c21c62fdaa4ec5145ea1c3ad6edbee29f85"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a0dc483c00da8b673abbb367eb6f8d8f4bcec30eb58529ea13cb42e7fd2dfa33"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c7d3a97c678d34fc5b59da671ee9cd630096ddc643e7b5a30d54a2a6f3574d3f"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:f8fb78a83c9e5f741ca3a68cfb455c1f5bb83b4e7249a3848b3cd78d0a8563b0"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:74ab5b6a9fb13e873e5a90946588baecaf488745e1db1a4a5c433f971f035098"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd52f811e65f6fb634b1047159657c98f52b407f8efec907bcfc09da9a4c0a25"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:f0f177d1b195b9e06376cfd7d308d8a1b920909a609d03ac82a8c73bbb16d3b9"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:498c6c623134f8e09a3c4e60bcd607a0b4590dd7dbf08dd40851b27cbb520ccb"}, + {file = "aiohttp-3.14.3-cp314-cp314t-win32.whl", hash = "sha256:b304db572b4368edd8dda8a2274f73156fe15558fca4a917cb8a09fc47af5963"}, + {file = "aiohttp-3.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b20032766aedf6261c7a566585a40867d092ac03a0d81592d5370ef9b054f99b"}, + {file = "aiohttp-3.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:2e1161602f45a54de2ce0905243a95f58cb42dcd378402f3697f5e0b21e9d2e7"}, + {file = "aiohttp-3.14.3.tar.gz", hash = "sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc"}, ] [package.dependencies] @@ -176,32 +176,32 @@ typing-extensions = {version = ">=4.2", markers = "python_version < \"3.13\""} [[package]] name = "annotated-types" -version = "0.7.0" +version = "0.8.0" description = "Reusable constraint types to use with typing.Annotated" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, + {file = "annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0"}, + {file = "annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7"}, ] [[package]] name = "anyio" -version = "4.14.1" +version = "4.15.1" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72"}, - {file = "anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e"}, + {file = "anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101"}, + {file = "anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94"}, ] [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} +typing_extensions = {version = ">=4.16.0", markers = "python_version < \"3.15\""} [package.extras] trio = ["trio (>=0.32.0)"] @@ -247,14 +247,14 @@ files = [ [[package]] name = "certifi" -version = "2026.6.17" +version = "2026.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"}, - {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"}, + {file = "certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775"}, + {file = "certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55"}, ] [[package]] @@ -523,18 +523,18 @@ httpx = ">=0.27.0" [[package]] name = "idna" -version = "3.18" +version = "3.20" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2"}, - {file = "idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848"}, + {file = "idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c"}, + {file = "idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44"}, ] [package.extras] -all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +all = ["coverage (>=7.10.0)", "hypothesis (>=6.141.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.16.0)", "ty (>=0.0.37)"] [[package]] name = "iniconfig" @@ -550,159 +550,184 @@ files = [ [[package]] name = "multidict" -version = "6.7.1" +version = "6.9.1" description = "multidict implementation" optional = true -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] markers = "extra == \"aiohttp\"" files = [ - {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5"}, - {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8"}, - {file = "multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505"}, - {file = "multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122"}, - {file = "multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df"}, - {file = "multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db"}, - {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d"}, - {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e"}, - {file = "multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa"}, - {file = "multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a"}, - {file = "multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b"}, - {file = "multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6"}, - {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172"}, - {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd"}, - {file = "multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba"}, - {file = "multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511"}, - {file = "multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19"}, - {file = "multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf"}, - {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23"}, - {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2"}, - {file = "multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33"}, - {file = "multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3"}, - {file = "multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5"}, - {file = "multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df"}, - {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1"}, - {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963"}, - {file = "multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108"}, - {file = "multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32"}, - {file = "multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8"}, - {file = "multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118"}, - {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee"}, - {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2"}, - {file = "multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b"}, - {file = "multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d"}, - {file = "multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f"}, - {file = "multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5"}, - {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581"}, - {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a"}, - {file = "multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2"}, - {file = "multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7"}, - {file = "multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5"}, - {file = "multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2"}, - {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f"}, - {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358"}, - {file = "multidict-6.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5"}, - {file = "multidict-6.7.1-cp39-cp39-win32.whl", hash = "sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0"}, - {file = "multidict-6.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4"}, - {file = "multidict-6.7.1-cp39-cp39-win_arm64.whl", hash = "sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9"}, - {file = "multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56"}, - {file = "multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d"}, + {file = "multidict-6.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aef74e9beabbd6c4aafc091dabff86d046ccf013ce1e4396c0fbb01b4cad9de8"}, + {file = "multidict-6.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1ca5ebe6d454f1e5496cf052386a559f1080bf2de75bf327ebca0a6003b79f19"}, + {file = "multidict-6.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f6d0c4b70f783305e73f9944d8efe6be1022550f0974ba0ae9d8893c0350fa"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8050e75af7e4c6e2d5260b84eeedb618f3e452e66473432e085b5d1b81429299"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4736d350371337825cac1793c9f7c40701c32a03912548c2a7608e51679cbb96"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:02fe09dc197b8ae7e355371e51e5dce2f39060cd5a8badf94904527e23a3f188"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad4528cdce058b684f75fad1faf4a6a6c992fe2f08376370ca66e4ce5916a84a"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8885e3808aedbd6725b921fb67dacaae0678933561ddd47c2b01315198c70e2e"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3b6e6840421c83ccb60398e333b44f910b0907bb409597685ab2eedd1e22eab"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c9648ed33dc8179e4ec04bbc73bd7f0038e1e81217a69467f61f02a78bf07e88"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d9d6544790ba50438a9c1a903c3c4afb1ec8a7832db5518549275b40ef0dd4b1"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1c9f3c25df6c9d3bbae4f6fd3f514b1c5c740a2110f56ccf36069c85417e289c"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cf22b43f35b7dbb9f71e8ee2041b5c00029cdfc28ede3a2f31cf8906f9a6c126"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8ed78ccad4c7b421804f5d524b7740946a7ef75d89dc0dac52e9d7c24c472410"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:e3b1aa25f01238886a6baed9e13b9a9240ed344346c79ae280ae65e8603b21d5"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bc94a68ea5e18f8e85dc6b522bcb53093f692c8eb62b4837ac047da73956cbe4"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73533644e1f69ea1164d56cc6505f564c6c44072b646b66d67df2d31fed0348c"}, + {file = "multidict-6.9.1-cp310-cp310-win32.whl", hash = "sha256:66987aa68b0f7c2a1cc5f388ca962b8ed92b10f79de38d6d0d8c716154f519d9"}, + {file = "multidict-6.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a32b78c1e52ebd8e247bb68300b90b233300d8816faa008ed0713bc539fb6af0"}, + {file = "multidict-6.9.1-cp310-cp310-win_arm64.whl", hash = "sha256:ab64ace1a68682d191d9bedd9d4c939406ad86b1d9f628180410644249ad46c2"}, + {file = "multidict-6.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:910d4260512660484c0dc1588a316fbb35a40c081c36fc51d1225351af17cfe4"}, + {file = "multidict-6.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:33fa55b990f81c2927e01399ace0d18926c69d69baa8cdaa819424132fb97987"}, + {file = "multidict-6.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:369b5aa01b241cd3fea6890bdbb11a1425d87bf1515831500d518f4223e9d72c"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:803f8b575a71b1b299d677c28db0653459c79b5308874efec813f17b7457c7f1"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8a65621b98984a62e59403009591b8a5a7736273aefe1cab64cfb85b365cc07"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:13849a1d4f54c3809ae721e9e83ab28f5ea602f33660cb84eb6ef261eac706c1"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd9a137a4a9becda3094f3831cd026380f75f6855e051eefe4c73ade524f1cc3"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9ae9614c317c50836689ce2dfde07c05fe0b16378562e2221746c3913ede3c80"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8f1e362c9352b50ed120f001046fdbb80810c9d56580f4c3fc13bbe30823387"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0dd655518f136febd96c05131a76a863e32fc2a1d7acd4e3c959e3ceb77d8345"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c5d675da8f1cb5650271c8ad5e95c0a3e5a183c105e72d953b12877b1c8d0fd"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:658f90f49cf5af2441cad0a2b801c3ef520471989a1ec55bcb25b255b2ca8d2f"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:43124fe172ada86d03ac3c8dc8179091341f6724d5e5d5b160e1587e4cd3761b"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f0adc22a4eb31e545221d93fc73a0f6a8cc2379d0f4309f71d1d17ba938b82"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7fc59e9ba821b220944ccfe0f89c9dc4745f6d097569992356eb03869f21e953"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:87cc632c88ee5dc80e12681047839304d98ee5c9a708d686505767001c9b8b9a"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b828cf64d62dc09ac183f03c1aeedd164ade96a2ce4934109452edf29de1dd13"}, + {file = "multidict-6.9.1-cp311-cp311-win32.whl", hash = "sha256:2c1aeb92eea59d824f004341b26d5e4b47a8a441cf9726769b9a90abf9d0e08f"}, + {file = "multidict-6.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:5f89dad732280e7a10b74d40b91364f88e13c3f2c08c2ef83a8cd42f7a61af2e"}, + {file = "multidict-6.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:5800368526647146978389dfaa46da3356291e9f0fff9a4ef12e8c2bef964a0d"}, + {file = "multidict-6.9.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:29138fef49828542e859828107e42e50d0e587c513b7eb4b2d92bade2b0860fe"}, + {file = "multidict-6.9.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:19e31815d41cefc365489e591d105d2baceb2f65aa75d29471fbdbda8651e006"}, + {file = "multidict-6.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6ed30be8918e18c8bed0a2e8b70639ecf02feb61ed00ca2e41cfcb2a50fa3f42"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:637f4ae36264bd7b8d9a60193acddc1d735ad52e8ed53a19931ea6d921fea8e5"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35fc236507fb1b3138f0af5ecd5f94ed752d4d6d826248eae425f86204013eea"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e58952f04772f59f11c6e007471449809a30165188669bca8fdb19dde40a8f24"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d35a4f1c63f07fbb8c8f9946dea98b21eddf6c57421585f71d91864be3ba2a24"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b5f8771aaaed7f80e84a4e471d2f29ab6721e4595075e54d03ae1ed951b2000a"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:976fd7689d69ec78d67d31d38d396d8adb562f7e8368279f76aed4aa451fa06d"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:95052e8777a86bae87c0bd0b5ab22d809e3d1d02bf69e3e66ddda5ba75a05805"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1a8adfcaf96f587ab138476eaddef95f29b8a2a8a9afbfea8d2fd62180995d02"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1a53de2772cfb74559df2eb4456ec4eeb908435ec55a84b69370d9d745d62aa8"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f2ce963299d42fa3f22a90adc0fdf174792ffef5ff4c7ffb68260548fb05580"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5b30ddf7234e611ca877575b62840e6af5977f92f1f9d532eedbb05a44ff8004"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:63ada7ee2e9345695f9e9bc4c65d72222253f07b1ac94fd0e37555cc6f3c7f60"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3c95601ed98fad3f6e2f8fe809c3b526b0fab31ef525e00a155e227f3d17f58a"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c148e8b596000dd3e4bfe206e70f3e666be18d72032e0012555f2373c52e35d6"}, + {file = "multidict-6.9.1-cp312-cp312-win32.whl", hash = "sha256:f9dad513626a33670f17cddc6078e30e311f444c957e8dbfc5b2b4603c8b4edb"}, + {file = "multidict-6.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:a16a1dc8529f9e734a41c3b856f3eae7ebacdc061dde3f8a844e0c7889c97203"}, + {file = "multidict-6.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:361f7206cf341ba94fb015688f5c8b480f8e63bd58a4c14a48aeca7851a241cc"}, + {file = "multidict-6.9.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:d7bf9e43282d69561618e8a0ea33368d532ebef42f15c096f427090521dd74f3"}, + {file = "multidict-6.9.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:03d47df72f084f757c1cb771188d5f4e3a805e4abc4d67e32509272343ae9382"}, + {file = "multidict-6.9.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6bc94fe17c3c56e5418f79515b786b101845f70609b0d19d0c1ba13448e5633a"}, + {file = "multidict-6.9.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8f2973bbd2bebd9d2e0cd6394c1292a1a19ccd56bdcbe1e174059f1a39be5b40"}, + {file = "multidict-6.9.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de7738b8c0bb74c4cc16bbd7fb49fc2bcf6430dba11b3432cd52768ae40933e8"}, + {file = "multidict-6.9.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e5ccad4b7bac125722f48d6f862bed3b514d8526deea06316bb72f152cd30a7c"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a49ff5cdb33654cb7d6a3c377aa2a83ddefaa1db31eb10bcf3c180aa84f9af8a"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b22ff30006a2f28f8bff878fb93413cbe3a4d1fd517c28081d848c90e9cfd2c8"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3adf06c66041aa21eeb8a71e82379b74773298c8e6d3d839b151aae441a99b94"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:963a8d8f97057082679523d0fd4c53a38f86bc58cabe4556faef682ae53fa2fa"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b66ccc5c2cdd26e74fa5d4c29ffae424cc6148bf93ce574821783fb3b6d452c5"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7fd79c521f6290c69125fa2b85fa65d9e657e6a8ffaf722dc881b926bef4aa5c"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d804e4caf5d5da37d6dac1325da5629ebef1e27a294c2b568b295814aa36c7b"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bb0d664505f4b112f384cffeee82e91e3f6448d8e574989479db4439b68cba05"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9e14d17773b1b3c758ff153659a1824608a0cb562c45f484b5ed8a433428444a"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:083735b7f395894e43adb278d5dae901448883a835ff8f1977e285fefdb10418"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b65121091567847a8cb520d364ab22ba90e00d3cc55fa9eb34bb439f0684bcd1"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ea999ae6e80e66ad5eea287860951b033d0104ca34d6d87c7b5125ebe0e12721"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:095d900c242e00fbe5f321ee072e7278b4153e78c5ce9c1efde167d62c1e4771"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6441cc837aea58be7d9baef1b2383eb8311ab9303f500f99ac90b584cd78bb14"}, + {file = "multidict-6.9.1-cp313-cp313-win32.whl", hash = "sha256:9c4880d017555d70dea367dd49271830842d48e3891c2da97da7ce8c4abcee40"}, + {file = "multidict-6.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:ac51cd64bae51c462ea58ad2492c9b8209667a4ef60c45c4a304518b67598d5d"}, + {file = "multidict-6.9.1-cp313-cp313-win_arm64.whl", hash = "sha256:37a9ebe00c698279213d56e6c64e1962ab1e092918270649b397cac3dc196ca4"}, + {file = "multidict-6.9.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:fc0dcb22fa9aeabfe3fa4e0430099acff985ec5d77a851382f76cc6146e780e5"}, + {file = "multidict-6.9.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:024123f0ab402ab33828e24eb80fa8f25167d0d3783ba5f287e39ed741e6abf9"}, + {file = "multidict-6.9.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:af1b5a92315048c3e36bbebfa7d4760a9c3e910bc4166f11b20d77d20d6bcfca"}, + {file = "multidict-6.9.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:b2483da477932ad1983d1d33c18bc3771c6fb00cfbaaed70a875fd547ef8e840"}, + {file = "multidict-6.9.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:db4d697b18b6ef5528b1f36bfa25072cd2a421869f5963bc0e92c8a34b9e2800"}, + {file = "multidict-6.9.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:854fd2f1bc6e8a56b89910b5cd7261a8b40f13ebb31572da985ce59c7da0886d"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:03731f6fc036180700c9dc2308205a48e5ca6f3ff03087739ab746f294022201"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989261c5f1735a165f2e4e87cf6d5f17ab734fa18f9ad0383d5adfcdaefce701"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b4c9e5d05b126b267ac048a89a0e2d9b48b1b648add62d4872906304a8590610"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9d0a21cf76153de8f2d96a877991d6bc59b9ab5180b949e50db73cc193b4a694"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7386aa18d98d6b8af44b92173654ec469237fda35f8e8523e43b581a86f476a"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b69651732c64afb691e50cdc3387cae305e0eeff8804fe3e3ce203876494932a"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1fee9a16d88a1c4865610de31ef5c666671020d7a81d1f510eaf3c97d00ebeba"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7814bbee202acd3bd240204c17d8b87a4c48c81064fd8674dbe527d94d5a4290"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:95f273bea318a194f656527ee2ed19494327bc500b8e87d9358e3222579aa28d"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:73bcafa21a78d0776b3ee7cd2a63c66f968eb7db8e8d594e32d7329950f6e828"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1a938761c77e0e6edb0c93d02f4e988d44a69e5195e5a3b893e5553311347132"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:37245ca4105386194dd1d292a6f2aae09bfe1bd7ac6f9ec25093e3cf8e9b143b"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f0700527dd5bfa8b7204b08330542f4f388899d3c14d885d8a368992e0eb562d"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6b7e54fd883671d1a8810704851c044b7173287c552b9f5c3d9e0eb9f00ae194"}, + {file = "multidict-6.9.1-cp314-cp314-win32.whl", hash = "sha256:e81ae656b9935ac4528a71f96bb7a14d949778ed1897c573d3e7ebb9187f8841"}, + {file = "multidict-6.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:acddcac38adc8342ba48aba98896faa7928854bebb62542362138655b5367ee3"}, + {file = "multidict-6.9.1-cp314-cp314-win_arm64.whl", hash = "sha256:32217133dddc58c927805cf6c0731d8144584176b768042ee886d51e71860bc9"}, + {file = "multidict-6.9.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0b2fb8c349d1103863750b5d8cb5ace766917f4b35f3d883c8f778853eaa9f76"}, + {file = "multidict-6.9.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:56d834b74c993a7d7cb2b8ab33a0d55c3e0d4a3d2f2da2808a4ad3d79189711b"}, + {file = "multidict-6.9.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:783ba7d845d79ce976afd9c1e91a4e5714671defa198ee789e8b23316083a485"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d718fa1b5f0d0dd75e86fbbc5b0c93ea3a5d65216c85c61cd5d7cdddfe08455"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a313bad717dde740959d50850c315b75fd4eb0c5e6b4dc8535db0f1c369be125"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ef01d29fca550ab871fd99154f82c6472aacf8e7def272dfb07b460123850390"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f3bd290711c6e9486173a6ee7cd4e7f00c3971c7908c1ec1b6e5437c5e4c6f9"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:81cdc537e0a42e3c0170752fcadbe450246d5c3b4b7231d6eb9672456605ac94"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8b193bf7a443c97d81c47052f60c486071a4bdef4a573fa2514f920089414d45"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7a0c98f6a636adf0d7edd60c61589eaf52d149239af754d0bfeb0effedba53a8"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6e6b7e3a1520c39a2772f414cd9ddf5995f77e4e823dfa1522af383addd465a3"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ca65cced0d67a9039e93bcd98a369920e499bf98296844ff56ead01c9085321f"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:372c063f37480f62c1ae32dc3a1a0a5942b180c883f99789075a8a8ec3c4e709"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:827c92145b3b976b39430129c89d213b250dacbe5fce678e9a03940e6e848983"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9b0124b9c17e9890f0819b2e7a5f65ec9a2f5aabd6c8e7ad090c1675cf70dee6"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:23136f5a564654eb61061ec6d5620a4c1ea32c8f552b65e9982a12b72bff601b"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f2524ec55b3e65cbe235a8b3c36e2af3b635be02ed05e20c94e70c5c943c009e"}, + {file = "multidict-6.9.1-cp314-cp314t-win32.whl", hash = "sha256:35ba0263bae5dd3ad5aad767cc9afc01a8598c7dae30f1b3b2de98b1b32c28bd"}, + {file = "multidict-6.9.1-cp314-cp314t-win_amd64.whl", hash = "sha256:7c8d5882ba25ac0282258be435d8a05aa0cbcacfce15799154a338f847f159b9"}, + {file = "multidict-6.9.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ac348379cf4de5538a0a213be1532d289aa801ec5d267c5909446b9ea2f8e2c3"}, + {file = "multidict-6.9.1-cp315-cp315-android_24_x86_64.whl", hash = "sha256:f04551dce5a7db8c9659f2e4245494c182d0663b83661803e08d46bfcae5eda1"}, + {file = "multidict-6.9.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:c0c88085affd35c33e124e36930c5ad96aff9294ce195eaa0fd9cec962b64a82"}, + {file = "multidict-6.9.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a8b75dd3d3638d9a19f23e84af4ffab3b8940422c0df2da2a77005ef5aa3d7ea"}, + {file = "multidict-6.9.1-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:006c4478de0a1876f4834e14255776286f09b9846b505fe63f67f9d173a9487c"}, + {file = "multidict-6.9.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:2784090c30a586d5b45197bd9c32f87fb927216cde302f6cfd76d76577e90f08"}, + {file = "multidict-6.9.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:7c708566da8014b120a64b1eb6d200c6c0c8cb36296383723cdb6fc82038270b"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:042fb0196047e786936a730bd302de83143950da45f2c16078da8f35e1cf7919"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2212a0c842c723d919ea4a22a9296cb6b244b386e4e6ea92adfc7fbf3095519"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd882aa29bf402b62bf1fd7c19fd5df4b6528cf468a908864b39368572b662a9"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c57541034d12b215ab0a2bfa371d1a8a198da18176d0426c27105b9161a6862d"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d73fed4e37158ff00cd271871170b79e40138db51e625fd352fa17c6acb34f67"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:79da2491348b30810728050b4a8ec0416f85884125c2fd44655b3d01150d9c3e"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b4da208a63434d21a3df64d29758e650fc4aa8cb05848554b76949c296539cca"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:877ca17fdcfdf5c397493a71e5ff97a87bb181417fe717fdadc77c08c09301ac"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:40aec5299e1ed71fbb988389059da381c3c1a60e0c649acceb2a35d9b128848e"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:4a409ccc42aefec904038695d5d7fd6d8f3af2721b7b6401d55135ec7d6d298e"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:0a5769559e3312dd96731fbe15b4abb6033368ac1cad5a98dadd21946a4c7d6c"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:03fac50ddfd8302175b77863a015eccfae76767cda5506eef86df559ba861e1f"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:5ecace251ccfa705bf3d7d35c5032cf750f5c629809740405697bce5c118c4a4"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:ecc89dbd4155b2f8a47f4bbd89242a35ed15e8e0ec581cab5ac65fa38407329d"}, + {file = "multidict-6.9.1-cp315-cp315-win32.whl", hash = "sha256:a3ffe881246d28a862f1985824f484cb7361f44d6b99c4c620436ef56462f38d"}, + {file = "multidict-6.9.1-cp315-cp315-win_amd64.whl", hash = "sha256:59c123d0e948d760a5f930f316cfefa07e8d632ab84327c0693ee6a88171154f"}, + {file = "multidict-6.9.1-cp315-cp315-win_arm64.whl", hash = "sha256:31199204b3ced121ff5407a2c342326a5d27e3870abbf94bd80dbd2451b7bc8f"}, + {file = "multidict-6.9.1-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:8879510a76940670517ea1cb589978da44b86e286ec3e50d664ef330817afce7"}, + {file = "multidict-6.9.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:aec65b53a07f580606593f877eefbb29a45939bfc0d3fe6e6d9f42b41b749f68"}, + {file = "multidict-6.9.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:14c56f73e78faa1f68bbb826197cd5871994e70e841b8590829c35912ece5c64"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:38c9986f9ce50c459b10de216a05f4bd7ed5ac63887d56e500a52bb464b861ce"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15db6a102cbaf1949cf028ecf080aac76d20bcd29ad4e092574db6c6b7af78a5"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bd82c4977196681a499bb6ca9e462afbc5c91c1c15b6a991dfbd72733fea4dd2"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bb58ba73a3f96f9a3e46b1fab69929d7edbbddb3133ee74b5c3c54074a53c4f1"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c6eecfab7ce4cd9487ff8ba936fe38cdfd68c04faf3d5c710363c6a8e695659"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c62e71e6289d78c0108d8aeb495f8bd3cad4bc1632fedddc9297ddf287ecc20"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:539c2cd5fed0947c135cd7eabaaac55f48300dfa1de0f3ca4edb5efa6606f471"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:3100d169ceb7bc8f05f89a6db11d1b21f119975fc26f29dc45a472e3569f0879"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:696477ad71385c4795e3b8e4cf10b0d2c28c2a1ca6a955e031cb1e62993e9ee3"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:f5844e7befc707367807586f550fa97e23dcfef0728f02b98c7bc498a961a5df"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:abc7c2e4b47bfe6a9aea434d3fdebb9597ee636e914e92ba352f2068b9142f4c"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:7ab379f95caee071a37cbd8be86d4c65accc651d391f9f97748fef006f38769c"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:557a4e1708df428ebe6c3081c83a273d275dad2446ce0d81fc648ac71afdb18d"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:475d04d5192eba487a3e2f935976340baa24529046e9c1c9c7a3b7bf80445ae1"}, + {file = "multidict-6.9.1-cp315-cp315t-win32.whl", hash = "sha256:10083a8a0f4e1b26b599889e90b9802504ce5d3f7722f925bbb7ca47dd22a7c1"}, + {file = "multidict-6.9.1-cp315-cp315t-win_amd64.whl", hash = "sha256:e96ca64383efa107262ee3949f047af5ee4f1845ba09463466c04d35a83bd3ec"}, + {file = "multidict-6.9.1-cp315-cp315t-win_arm64.whl", hash = "sha256:501ed8b02a5990c67a91c732843609d43a6be1f7576fcdfc867331239f37fbd3"}, + {file = "multidict-6.9.1-py3-none-any.whl", hash = "sha256:7bf6478188f4e47bf5686e8a33da4ae28bf43b1b2528d9ee144d28492bfac60b"}, + {file = "multidict-6.9.1.tar.gz", hash = "sha256:0f06e60fa190aa7abd0914c2a766736fdc8e9f34878c4346338534b73d1b20e2"}, ] [package.dependencies] @@ -776,14 +801,14 @@ files = [ [[package]] name = "packaging" -version = "26.2" +version = "26.3" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"}, - {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"}, + {file = "packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c"}, + {file = "packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79"}, ] [[package]] @@ -804,151 +829,168 @@ testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "propcache" -version = "0.5.2" +version = "0.5.4" description = "Accelerated property cache" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"aiohttp\"" files = [ - {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b"}, - {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c"}, - {file = "propcache-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bf3be92233808fcd338eba0fb4d0b59ec5772af4f4ecfcec450d1bfc0f8b5eb"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f8ea531c794b9d6274acd4e8d2c2ebcac590a4361d27482edd3010b79f1325e"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:decfca4c79dd53ebab484b00cc4b6717d8c369f86e74aa4ca395a64ac651495e"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4621064bbf28fa77ff64dd5d94367c04684c67d3a5bf1dff25f0cd0d98a38f3b"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b96db7141a592cbc968daf1feea83a118e6ab378af4abbc72b248c895414c22d"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ca071adabaab6e9219924bbe00af821f1ee7de113a9eca1cdc292de3d120f4d"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e4294d04a94dcab1b3bccd8b66d962dcad411a1d19414b2a41d1445f1de32ad0"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a0e399a2eccb91ed18721f86aa85757727400b6865c89e88934781deb9c8498b"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:823581fd5cb08b12a48bfa11fe962a7916766b6170c17b028fbdf762b85eb9bf"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:949c91d1a990cf3b2e8188dfcfb25005e0b834a06c63fa4ef9f360878ce21ecf"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:cc1177027eda740fdb152706bd215a3f124e3eea15afc39f2cb9fe351b50619e"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b05d643f944a8c3c4bd86d65ffd87bf3264b617f87791940302bc474d2ff5274"}, - {file = "propcache-0.5.2-cp310-cp310-win32.whl", hash = "sha256:8114f28879e0904748e831c3a7774261bd9e75f49be089f389a76f959dcd13fe"}, - {file = "propcache-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:5fcb98e7598b1ee0addab320d90f65b530297a867dbfe9de52ea838077e16e3d"}, - {file = "propcache-0.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:04dc2390d9edbbaef7461f33322555976ffddf0b650a038649d026358714e6c5"}, - {file = "propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78"}, - {file = "propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959"}, - {file = "propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f"}, - {file = "propcache-0.5.2-cp311-cp311-win32.whl", hash = "sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0"}, - {file = "propcache-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82"}, - {file = "propcache-0.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab"}, - {file = "propcache-0.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba"}, - {file = "propcache-0.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a"}, - {file = "propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a"}, - {file = "propcache-0.5.2-cp312-cp312-win32.whl", hash = "sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031"}, - {file = "propcache-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42"}, - {file = "propcache-0.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84"}, - {file = "propcache-0.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a"}, - {file = "propcache-0.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117"}, - {file = "propcache-0.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4"}, - {file = "propcache-0.5.2-cp313-cp313-win32.whl", hash = "sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d"}, - {file = "propcache-0.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757"}, - {file = "propcache-0.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f"}, - {file = "propcache-0.5.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d"}, - {file = "propcache-0.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa"}, - {file = "propcache-0.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568"}, - {file = "propcache-0.5.2-cp313-cp313t-win32.whl", hash = "sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191"}, - {file = "propcache-0.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7"}, - {file = "propcache-0.5.2-cp313-cp313t-win_arm64.whl", hash = "sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96"}, - {file = "propcache-0.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999"}, - {file = "propcache-0.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e"}, - {file = "propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4"}, - {file = "propcache-0.5.2-cp314-cp314-win32.whl", hash = "sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0"}, - {file = "propcache-0.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c"}, - {file = "propcache-0.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0"}, - {file = "propcache-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb"}, - {file = "propcache-0.5.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078"}, - {file = "propcache-0.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2"}, - {file = "propcache-0.5.2-cp314-cp314t-win32.whl", hash = "sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821"}, - {file = "propcache-0.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370"}, - {file = "propcache-0.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6"}, - {file = "propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe"}, - {file = "propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427"}, + {file = "propcache-0.5.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b77c313314524ca9c38fbd70f73515d04597ac58c40c939bc0e71eeb4abff680"}, + {file = "propcache-0.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8f911c395cef73c510bac566da9507bb6a43e7763d0c79138dc60ee53f11207e"}, + {file = "propcache-0.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d83b12902eb8bce151259c86c03ba746600b2d994543de46e370cecf96c452f2"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9281e922c072158c91974d4589f1dbe0fee6d467f284c28e463f9f5a4d933f4"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9f3551b8a35c1df3e7ea4d2d86edee15f0dde1bddd434a71744048683544d0ef"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ec6a85f424afa8d23e0d9a094e5dbb6eda01da91c92b9183cd433768247ffc97"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f574e460d1c8a08384a016fdb09ccf3543433263ed6b2f97104f979e64ea57c2"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d8e017eeb7482bed34cdb0d61cf2bcfc88d104bbab296a17cd16a6af8aabc70e"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f273dcf7149a50527c4fd1f55cfe9eac0f60753f5af544b4c9352578e20c0874"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:fc2461ecc45f17893f8207e73b46ea8ba93e33630e51cf4af3fbc21d47462b1a"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:279655a16973f1ee2bd2fe79973137681642fd9ae0d89215bba263726eb0dc3a"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:e9f165403b81fea7e89c932d89046a1e3d9a3a60e8d7ef2f249dccdcb0982bf5"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1783582065a1f07f9d9ee1e992e13f15d7dc8fb1eb3a7476d43eb3f2e69d26bb"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d605bb239b796e82a81c6709548b2bd460ab73b4590cb0c83de8a2dd9694d0f"}, + {file = "propcache-0.5.4-cp310-cp310-win32.whl", hash = "sha256:141fdbd73748db0cf7636035030aaac383d2efde8f34e7bc24594cc776d225b8"}, + {file = "propcache-0.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:146f48a9e4812611a7581003b1a39de56c34967046310c4171a68ef908c9a745"}, + {file = "propcache-0.5.4-cp310-cp310-win_arm64.whl", hash = "sha256:6c7599df2b57ebeea8de011b5f2f7b85de95e76037d43d34b95e328430275487"}, + {file = "propcache-0.5.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:897d1ddf6716e8f47200f7aad9a0efa6cc7586df66c6defa572f9eab379c078e"}, + {file = "propcache-0.5.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9cbfff4423eef4cc6cafc021469641a2b835f610b2647a6c5281903e21b8670d"}, + {file = "propcache-0.5.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fc24f209c1b7f7f688b66b98293954f5504279760999b58920ee12dd8471c1d"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62530ca89187827e4a4fe733f971abe81a7542eeea48ff61995f19b64d7199c8"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fc3f7599528db40b1efa0889a620116e2704144495273d66066e8164e45838"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4f2d880ff60f45898f4acfa152aac8d04e3ee627d90ff4003491bf92239d5757"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e9368e87a3efc285e559131092c5db643eb8e56de4ee42064d5baec22ef2bb5"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:004e685b315646c410771836e72a44f143bbe624f29653a42687815069a303d5"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:594eb4c6ec35e7179b058481f4e9f02521b56de16fa577c4b85c76fb1bf8a9f8"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:2dba2f02d2d5c09ef8a0e6c1a42aeaa451f4be9898cb00b04fe98717da2eb23b"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c3ef2818d63bc86071e9d2989ae75a1bc32b8f7059cfd9f5abbbee70c32e2ed6"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:dd2ac8f5b643454c2cc6b6118b13da16e88f4a6434fc3ba61aca384029f04f36"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4054acf80d40456a0537f2913b349718649d8d6458a14ab7f48d0ce28c30869d"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40e94adb1e7d39ff28a8bd8d8b8fbd1df6b9f40976dbe379134f1ce058e532dd"}, + {file = "propcache-0.5.4-cp311-cp311-win32.whl", hash = "sha256:9f86f7259efe2c951f43e57d471c9b41daa5bfc7db9f67189059cf1ae6d77fd9"}, + {file = "propcache-0.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:e904d4d01f36bd6e197590be1533c44e06058771e0746dd073a8ebb3ef880858"}, + {file = "propcache-0.5.4-cp311-cp311-win_arm64.whl", hash = "sha256:d42a9a856a4a6e2f6c10f1318c07e7daa498d6593abe745c71dae4521a26ca39"}, + {file = "propcache-0.5.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b28f41fa3b8c6900457f858ec5b03998f3a6d535fbc1bb2edec5961ea05ec429"}, + {file = "propcache-0.5.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:dcbf346a318a5e30063f547630b02bb787ce2f45b6368d5da143660b6a3835d8"}, + {file = "propcache-0.5.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:87a3caecf8095e48dc72f84bfa42e23a848cf410cc9cc13031fba4869b706a21"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60a64cbccaa11b7760ce705a14ada17ba459e7ca9f23ba587eb013821032d7ef"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a74bfa37147cc08fb29df10bd9c16f40fa7f860cd3a6d2fff853323a94f6e17f"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a4d7a54719b67338a305dca2ce6aafe366817df94ddfd4b5514374356f5ca546"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2814ecd8e818f487bee4b0f921bc4d1c176cc5fc71ac0f072d0fa67eda4ac14b"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6af4693716bfb03f1752ef1b30faa593db2c01d5272e9b8564a1549452a979ab"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4fbc1a15dc8cd1689508758d626b372b1f09d28d9577667feaf9e6bfcd8efcbc"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cdee8205a44d0be91bbac4c41b95d86641b72dfc7aef1279400e4fda3f26a937"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9a2a8a50a93dee0268a860a07fa3b4bd968f8ce4dbd794957da772f395368526"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7ffafcbfc7b549ab940047e505c831eabac5e67de53e1bc174adbc5285c55944"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d1f5a500bfcbb2c0ab85e98a0dcd70f5899d34efe365a0187700369a79603031"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a235f73d6e020855dc29dff012d920c02ee0feab8d73a24185a7569f4be1161"}, + {file = "propcache-0.5.4-cp312-cp312-win32.whl", hash = "sha256:b3083bfe87f95c756e610bd8025f26cbd1cd4aaa03a422f2d65efb7a97cd53d8"}, + {file = "propcache-0.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:98914de2c4d7f0f9f4a8c6ea4bf05841f4175796941e3ef7d47eb718f22311fb"}, + {file = "propcache-0.5.4-cp312-cp312-win_arm64.whl", hash = "sha256:8876b39961e33d912afe3c1bee18ee564fdad0206f873cc15d522756b7f50737"}, + {file = "propcache-0.5.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:36c0d9db44b523ef93d03341b1c42d69ff01d673c053d1b1c6c3a363bcaa39ba"}, + {file = "propcache-0.5.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1d52a05dc417279f7e5c7618c5dfbbc29923aaf9bc0a5c1802ddcebf54c61a0"}, + {file = "propcache-0.5.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44149f46500a0a41b95b4d99c2e586a77319539730607b9892974a092788b111"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dbab5f5ff6897c81f355d079010cdae85b02e5a0b518b5251523b8ad8ae9ac3c"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c3e98c55bde2bcf7db3c70d1aed7ae9aa8aebbf19a250c66645cde44cdb8b867"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db3ae52ccc150dbc84704e9d642743897f3e1c54742ff34cacb661e52e3818a9"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f85915e00dcb1cd9f2f890ead064ed40a27df06f0db65be427b29482ae357572"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c2ba30a89035b57b73e00475de948521602f543d79ce01db10b04b36c4c76fc8"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ae58f361bd5dae942717c65d3413b478c70aea9c462599e7b9adad3731db3894"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:96f7c5c15656040ddcbc51e56dc59b58aa25999d743c126abd425b9766ab43e9"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7cc528e760a8af06f2b13e9b9f362cd90c7c718ea61228a96dbd31ba16ed7f47"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:425f8cc86ab5018b4b8d4a23bc8e74d964bd3d757c3702e301aa79be76c53f6c"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:a5793c7698a53f56f4a1889a4737c7eeb1b7ad0842fa6b1abca22913ff79c8c1"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c02c0e570c5c7e077b0181a9f3cdb7d4c3617d1cda6b5c95bd5d34022923d82c"}, + {file = "propcache-0.5.4-cp313-cp313-win32.whl", hash = "sha256:3e413d7a4a9b4866b7a761d6060d434b64d23cd35122eda3b026a0bbe8196b25"}, + {file = "propcache-0.5.4-cp313-cp313-win_amd64.whl", hash = "sha256:0c889f6fa84957bc7e8b4eab71fd16a0455068d5045e3aa40c733071d2b2fd77"}, + {file = "propcache-0.5.4-cp313-cp313-win_arm64.whl", hash = "sha256:69fc35c0779522da366c563e5faf203ffc1f8ff0021d5b1337fa4efa5be73177"}, + {file = "propcache-0.5.4-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:e6720ba44ad7e72174314d0e1fb0172494cff5c73a3a8a2159c3d2402ff15565"}, + {file = "propcache-0.5.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4cfe0a92ae30151869e67a4b5f5e105e4e03ad30b3f38e5211b5bf77d0881993"}, + {file = "propcache-0.5.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d759d05634f1b038fb625a66662a8c85e5a8fec912da381b5149ddac107482b"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:251c63dd46a0659bb875cb254dc4c1e79ee91a847c737cd62373295afc2235dc"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7a8d5ff04eb1f85698a78d20c62a14676e7b960dcafde09a388d60ad377d355d"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b9100a93b372418d8688f3f2a3e5b45c64d70ca4d6176e121aca1e3bfc1e32f"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc07876cfb079b6f6f36d21ce75784ad6c2c6b563eeac0ed26c2fa2669b85df9"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0951315a6b3142ee2167404d707743f0157c110091342b1aa0accac5cf0e4acf"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bee7d3aed13d56f54e681df38c3a23031bc9e3863f687d9d598825c9146acd7d"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4e985382be6d15da8d0c2710a6fa7b9070fc9ecdeefb7f580e88373984ec8be3"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:9e9ab13760aa8b6d0881ae7cb04fd891d8d490cd2554ea8e79bb278399169bcc"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:1b2f3bec4261a94019575481c726c29850f72e27907773c75b1de421e20e9f9d"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:720cf832eb2d0b0dfee129cb3335a26f6ce3cc45ee1187e8f0731758caa16792"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fb0a5be8d9aa213150e8d8148a42aca4984b285bcad1e69587dc4298edd929b"}, + {file = "propcache-0.5.4-cp314-cp314-win32.whl", hash = "sha256:30cc1cebaf9aef49db06357a50398323ae04d70460c0491837d026ab7d6452ea"}, + {file = "propcache-0.5.4-cp314-cp314-win_amd64.whl", hash = "sha256:0a095db8e15a6020db149ecbed6461939fe74f6acaa3ae8b702a1fe8c38cd983"}, + {file = "propcache-0.5.4-cp314-cp314-win_arm64.whl", hash = "sha256:45488d1a5f9ab5bd90aaa1ca20f50fe1922b8ffad71a2009d2adf41355897aac"}, + {file = "propcache-0.5.4-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:53eaa697c4d0422ff4cb714d00231b43352064d97b944033b30c1d57cc506ec0"}, + {file = "propcache-0.5.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:886b59c4d28ca97dd23b025fdfc50a0356be934efbbbca89ad26230067f86fe5"}, + {file = "propcache-0.5.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fa15757fea1dfcd5b7745cad9f4638929605531bd4018ab2adff7955f1a403d"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6f0093ac3e9daada202c2082439d414a625c57184727a46e112a3fb2a81cb788"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3cd3a7edb6b95b9b33998135ebfa18d709da82290fb8f27c858970b5a12c8b56"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c174bfd1c48a1b51a3078e95586dde718374bac79719ab3541ec9e74aec40574"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a219f0ac59817a9114dd2aa57c13180f993e819ba658c7ddab4b66ed1ee0d370"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:17a7400cec0256f0a71ae71f9da398f9894c956ff6668a1c9d317b3367316320"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:978f28401afbc76cdc3df9e1717b4229a06b626a1dcc75db4e1f2beb3884c3e9"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4a1f4f5ffa55dce6307631f3cb2948e117e665966ea512e0d502b16c24f567e7"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:213bb68d9ced5cf2bf717b1071bf2b09b4b04c426256f9fe6d054c60318424c4"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:286867fb156488c251a3721766e380ac4495e4fd6b51aaa1403d89ce7f4359d9"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:445ee3bfb46e85838387fb3c536a73cc0b994dc192b004e40e170adc54aa2a7e"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:48cb48c5346a97de792254af77715aa2529c2a1ebc5f586aa0aae44a02f1fe57"}, + {file = "propcache-0.5.4-cp314-cp314t-win32.whl", hash = "sha256:03b229037d25b801e7af53fd52b9fc49d9439b036fca1e087e02780631adfa97"}, + {file = "propcache-0.5.4-cp314-cp314t-win_amd64.whl", hash = "sha256:8a1fc236528c457cd739c88abe823da851b7ab645d72792f88658114cc340c12"}, + {file = "propcache-0.5.4-cp314-cp314t-win_arm64.whl", hash = "sha256:135036c5cfc93864affb0f9af9a27e5d7a71cb7bd745e7b6dbfc2d56cc30e827"}, + {file = "propcache-0.5.4-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:45bf2e730ab8905d0527fe05a86500f406e64305c34cc81ebe64b4617cab9760"}, + {file = "propcache-0.5.4-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:31eb43ba2edc704ab2ec27815315dd8a19def0fb16215be4cfe8d32fe78ffd51"}, + {file = "propcache-0.5.4-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:174507f82d3594622acb1dd2dafecf2d899d6d506335494e7107767bf05f3aae"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50e337653721d20ead710da33bf44487fbe8a0db8782714b60306481e9f95b51"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0d21d0d2c82bbfeb1677a9711f38df968f9837576102bb4add1bd449d28d88f1"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccf4f7a79e26bb7efb06ecd50c177833b71df05cbc748701372325e6bcc17f6f"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23278f808cd81d5ada7184a76606b925fb3389c60e1077b2cd7da7b1fcf0553c"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e738ab81179510ce79b2eac9a6ecf47feffd9e76d1c72e403005dddb6e36c06c"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:a419ee85e654927baabda3929c03c0cc1112bf472ff0dfd6142f4e3a81ca4162"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:b61805357d966680acf68b3b6d49772631ed9df44ebece10ff1460e117a7da8a"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:58134228927cee6c047d626c08e60a81be604a20578a12ce752cc5c9a84d4826"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:350b272b2279f4135a64fc0c304a5d08e28a137c9573442c606152446638a831"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:45bebbe252550fec975ba3b62bc6f931643cfd3b5464ef47619cf3fef154e01c"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:ada748108a43d29b7c328ba7db3755327cd94f028bcc1a7ee3f0addcfacd9c38"}, + {file = "propcache-0.5.4-cp315-cp315-win32.whl", hash = "sha256:ee19113bce2f3acd46432050688b70f61acd6857d75abb9ec96341b7e9ced123"}, + {file = "propcache-0.5.4-cp315-cp315-win_amd64.whl", hash = "sha256:ceb3e879afac028f93d272c957814695dc5569e4904262dbee92f6c41bd5e4a3"}, + {file = "propcache-0.5.4-cp315-cp315-win_arm64.whl", hash = "sha256:c83acbce9f2b5e3f5f5eda9e53d2001fed22fcdfef81274a9e02d8fd53b70a30"}, + {file = "propcache-0.5.4-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:a5e8ef588c109725dc713ba69aadcac00a1ef90c2ce9c0a8c7075128f569f47f"}, + {file = "propcache-0.5.4-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:4d86476a935c88963d9b8e1a9a0d38188790e9622169bfbafa173046846709d3"}, + {file = "propcache-0.5.4-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:f5470694918830da62fac9e69133b53d23b736d7070e587b27a4a2be37e08e68"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10ef33a68a61ce317e095fd2e202a592ea92392b90944a78c993f0d9a73ab06c"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5cacf3c9efd09df409dc33654dd077e1c245ba8fb747b0f0236ef41b7c49b589"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:770e8209d018175fc0063936fa9583b6d27e88c5ad31543f3383d66080efdd62"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03969626faf0783a592dfa17e28eac06018bd0b44dafae6943d53b92421a7f72"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ef3b928d9c984322b5c44e6964d8dbc653da87d2d8ee1647fa6da43072e650a9"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:7177c43eddf10a0893c4fec52ebb408fdcd7f7d63962caace9180d8f81b14ece"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:420162a77f94eb1cf5ef7893f500016dabd548e73de956785a1dd899cc73006a"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:3eb2e820e8e2101407da93f17c57cbb7d225461955fc60105daaba14cd421ee2"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:13e52b6e0bde97dee98ab66552dbff2931649c96f1ac432eac299fe689ec373b"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:12682126712ddc19b70ff819debbd279e58adf1f0c8f8f8138c18ade2044b284"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:3af0c8642b2da4815d86e631232ac8286e17644fad907c19508aa8e7cb4ba8ad"}, + {file = "propcache-0.5.4-cp315-cp315t-win32.whl", hash = "sha256:1df8d8561b21465c5dd56110a01caf897e026d065b4b84e98a488209094272ec"}, + {file = "propcache-0.5.4-cp315-cp315t-win_amd64.whl", hash = "sha256:02c0a34f16889cf800f10f0247a564d8ce6eeab6ffcd7c87198f769067eb8432"}, + {file = "propcache-0.5.4-cp315-cp315t-win_arm64.whl", hash = "sha256:dc4242ca653c9b30ab51c5f8193323e7bc0928f897ee9103201e59a43abcb72e"}, + {file = "propcache-0.5.4-py3-none-any.whl", hash = "sha256:62c60aec739ed00124573cce1178138fd690c7676352d67a37328c1cf51d7468"}, + {file = "propcache-0.5.4.tar.gz", hash = "sha256:ff6b113f50bc066a698db5d944d2c6dc7507168dd3341e255a8892fd0715a558"}, ] [[package]] name = "pydantic" -version = "2.13.4" +version = "2.13.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, - {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, + {file = "pydantic-2.13.5-py3-none-any.whl", hash = "sha256:346a034f080da3755d8e9cb5e00e8b07de1d39e4f6e2c87d8ab7cafa0b269a73"}, + {file = "pydantic-2.13.5.tar.gz", hash = "sha256:51a9c5f7b2f8e636f04c6cada605d9b6a3bf1348fdf945a3d8869b19bba0ee08"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.46.4" +pydantic-core = "2.46.5" typing-extensions = ">=4.14.1" typing-inspection = ">=0.4.2" @@ -958,132 +1000,132 @@ timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows [[package]] name = "pydantic-core" -version = "2.46.4" +version = "2.46.5" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, - {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d"}, - {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4"}, - {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f"}, - {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39"}, - {file = "pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d"}, - {file = "pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf"}, - {file = "pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594"}, - {file = "pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3"}, - {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848"}, - {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3"}, - {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109"}, - {file = "pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda"}, - {file = "pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33"}, - {file = "pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d"}, - {file = "pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2"}, - {file = "pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b"}, - {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458"}, - {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b"}, - {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c"}, - {file = "pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894"}, - {file = "pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89"}, - {file = "pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a"}, - {file = "pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008"}, - {file = "pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e"}, - {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd"}, - {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be"}, - {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d"}, - {file = "pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb"}, - {file = "pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292"}, - {file = "pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d"}, - {file = "pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb"}, - {file = "pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb"}, - {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898"}, - {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e"}, - {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519"}, - {file = "pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4"}, - {file = "pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac"}, - {file = "pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596"}, - {file = "pydantic_core-2.46.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:fd8b3d9fd264be37976686c7f65cd52a83f5e84f4bfd2adf9c1d469676bbb6ae"}, - {file = "pydantic_core-2.46.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9f444c499b3eefd3a92e348059471ea0c3a6e303d9c1cec09fa748fd9f895201"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3447661d99f75a3683a4cf5c87da72f2161964611864dbbeac7fbb118bb4bfc0"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b9bab013d1c7a79d3501ff86d0bc9c31bf587db4551677b96bec07df78c6b15"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d995260fdf4e1db774581b4900e0f832abe3c7c84996726bbc161b19c8f29e76"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13a646d65d09fbf1bc6b3a9635d30095c8e7e5cc419ff35ecc563c5fd04cd49"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432c179df7874eeb73307aad2df0755e1ae0efa61ff0ea89b93e194411ae3928"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:e68b7a074f65a2fd746c52a7ce6142ab7006074ac269ace0c25cd8ba171f8066"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4a05d69cba51d852c5c3e92758653245a50c0b646ced0cf05bd793ed592839d6"}, - {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:228ee9bae8bef5b1e97ec58302f80357c37199e0d0a99174e138d28e6957b9d9"}, - {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:10e17cbb10a330363733efc4d7c4d0dd827ac0909b8f6a6542298fed1ea62f29"}, - {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:91a06d2e259ecfbd8c901d70c3c507900458498142b3026a296b7de4d1322cc9"}, - {file = "pydantic_core-2.46.4-cp39-cp39-win32.whl", hash = "sha256:d80ee3d731373b24cebbc10d689ca4ee1875caf0d5703a245db18efd4dd37fc1"}, - {file = "pydantic_core-2.46.4-cp39-cp39-win_amd64.whl", hash = "sha256:3be77f45df024d789a672ae34f8b06fb346c4f9f46ea714956660ea4862e89ac"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983"}, - {file = "pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1"}, + {file = "pydantic_core-2.46.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:657b40d6240c0a7b6a64b30f22d1e3aa631c7e846c621b0c0f6d1d75e2e15ea6"}, + {file = "pydantic_core-2.46.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ecb42011e12ee19cafbc312887cbf3546959fe02fbad44f272d4be5baa997615"}, + {file = "pydantic_core-2.46.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dedce55295becb61921e386b99d4f2706045306e7fa52249a33004c837379fb"}, + {file = "pydantic_core-2.46.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9f47b8a949e60f027f0aa0a6f6c7b7e9c55cbf4380d10b344e282fa4e7ab1e1b"}, + {file = "pydantic_core-2.46.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:200aa3dc9f8d54f0754f43247c0bad0999fdcfbfd2488384dd44f37279271fe6"}, + {file = "pydantic_core-2.46.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d30e1a4f138b8951063e9a394752a9179b51da288ffa507b1e659222f4c1793"}, + {file = "pydantic_core-2.46.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:850a08d167dde16db8702c274f320c7be9d7da6f6dff2b58b18f9e815bd94f5b"}, + {file = "pydantic_core-2.46.5-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:c3471e5c4a949c26ec00a77f01df59096aa9495877de76fd60a980f8ee6be461"}, + {file = "pydantic_core-2.46.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a3e26b6a8274211bddee2d0e4d0d42778f17a34510f49d2ec44b58abfc41736"}, + {file = "pydantic_core-2.46.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fc5d783bd4a2387e97b8a2d5ec781cfb92b3d893bf82370548e99db5915935d3"}, + {file = "pydantic_core-2.46.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:356c8368cbc321050b169595683a2e1d63413b1e0e2868b330af9fc14c616d3f"}, + {file = "pydantic_core-2.46.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eb7d8d0e5886a89a55d2eef490e272fa965a9d57c6b29a5b5088a7997ec2cad1"}, + {file = "pydantic_core-2.46.5-cp310-cp310-win32.whl", hash = "sha256:4d44cf99ddebf875f9b68cc267aa684c99b7b44fe63ee1cac4ec163807290069"}, + {file = "pydantic_core-2.46.5-cp310-cp310-win_amd64.whl", hash = "sha256:1e5aad1220a1192c42341c8fd4a8686657e73ab2a920c970bdc4de334fe3193d"}, + {file = "pydantic_core-2.46.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a1dee1b804ff4d11c663636cf15d2ea47e9f79cd56c033fb1cbf08924842a48f"}, + {file = "pydantic_core-2.46.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d625a186a65201c23a9e3b8ed9c47e90a026e03256608cc91851c6709096844f"}, + {file = "pydantic_core-2.46.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f8507560a9284e1370bb048ed4282012fbef4e8d109875b95e884d228552061"}, + {file = "pydantic_core-2.46.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f93c5fe914d75fbec9a49209b00da5f08e9e467d69da2b1510c81940cfd10be"}, + {file = "pydantic_core-2.46.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c767f552b21b10f774aeac128e828eafb796adfa1b666a18bf6321453c3a"}, + {file = "pydantic_core-2.46.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:701b2e04b560eeb4bddf7a25ab8ca476176e34fdbd9a0e18196f0d12d4685f0b"}, + {file = "pydantic_core-2.46.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49776eab08766a08dfff7012f8b422dcd7e25e43b316eedf0477c24fcfa84b7c"}, + {file = "pydantic_core-2.46.5-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:a2468d93d181667a7abd66e1b64bb9f76f361b0fef8faddf687456453576f5ee"}, + {file = "pydantic_core-2.46.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:53feb344243bb9510a9dec7bf3cf1b64d88a98af5dc7872a5160465f8b198c8e"}, + {file = "pydantic_core-2.46.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cd5214352ae68f3b5e9af7768bdc5253695ee069675db3480518420b3be881f2"}, + {file = "pydantic_core-2.46.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:9432f3598db432cb51c5b37fdbf29a60fcccc79e30d37a05022776a6bc4ab689"}, + {file = "pydantic_core-2.46.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8feeac04b5794e513e710af2f9c87d49f31a6dc47967bb264a1fed61a8989bec"}, + {file = "pydantic_core-2.46.5-cp311-cp311-win32.whl", hash = "sha256:892a881d5f68c2b9ea304b7a6c2c60d9343df578a311b0f86b94bc8f1ffe8129"}, + {file = "pydantic_core-2.46.5-cp311-cp311-win_amd64.whl", hash = "sha256:40375c2d05acec10323e45dfe2077ac44bc74659008614af5069034e2cfc781c"}, + {file = "pydantic_core-2.46.5-cp311-cp311-win_arm64.whl", hash = "sha256:28a6a556cd3b6066bea827857f9d9cce027c96f776e512f544a581f9e42161f8"}, + {file = "pydantic_core-2.46.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b9fe6fb92520e3fd61f2e49000b6911b188824f089b75973ea06d6267f0b476d"}, + {file = "pydantic_core-2.46.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a39ac25a9a2fa4072efdb429833c4a4c8009a51ff9eea3eeae131713cd27991e"}, + {file = "pydantic_core-2.46.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fdc8b93a41521988916eeaa271173fcca7fa0803d62f87675aac8dcec1c8e29"}, + {file = "pydantic_core-2.46.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b98134087d9de723658d17a42c7d0da8d6e2ef08015dee7dc93889047315f5e4"}, + {file = "pydantic_core-2.46.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e652ab17569c94bff5475520f907b7148b8c24036a8ebbe5cf7cf7493d28579a"}, + {file = "pydantic_core-2.46.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d925f3d9afd05a8c0fb3a1031463a8d59ebe5e2afad297e29c78be19e13b4e62"}, + {file = "pydantic_core-2.46.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fc5be0abd4a407e200d844b404e33639a554e7bd0d448e7b9ae181be4789ac2"}, + {file = "pydantic_core-2.46.5-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:816ff0a6550ffc06c098ccd2e0698600f9aa7da192a79eaa6f9af504a35db869"}, + {file = "pydantic_core-2.46.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c7ea57fc63aa7da93a1bd2d644e6577befae10c52c4e36377635eea1056a74f5"}, + {file = "pydantic_core-2.46.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:efd62a42486f1bda5d24cb4f63d15a3c7768375fe83d36f9417b4ad7a2fb20b3"}, + {file = "pydantic_core-2.46.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:2bc9419666990c06d7397831f2126a1ecc3594aaa3ff7de5bf2d066802f4e07b"}, + {file = "pydantic_core-2.46.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:18a09e1e1011b462f2e32774f25859ef1223d5c2b0546a633cf56654710721e0"}, + {file = "pydantic_core-2.46.5-cp312-cp312-win32.whl", hash = "sha256:5cb482e9e84c851f4e623fe4acc1ced89168cf1fe18f7089db4548c8f5bbb65b"}, + {file = "pydantic_core-2.46.5-cp312-cp312-win_amd64.whl", hash = "sha256:5e81740c09e310f5aa5cbd3e434a01c154d4bef93241c7877b39f211d2b78ba8"}, + {file = "pydantic_core-2.46.5-cp312-cp312-win_arm64.whl", hash = "sha256:f7b0ec93a2893de856652154d73b7ba622f26fa97726487dcac373de5f4c6084"}, + {file = "pydantic_core-2.46.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:b7ca9034437b6022f941f4857459562ee00a560b97e7cce8a0ec5a74fc6766e0"}, + {file = "pydantic_core-2.46.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f332f0e72a5a0400141f830744e141bf9f97917878dbe968669e8a7fefea78ff"}, + {file = "pydantic_core-2.46.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:193375f3548919d3f0b60936ca113ada3e38f264f91b9b8e0508efaad57be931"}, + {file = "pydantic_core-2.46.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:79bdfa52f843137045b2d081cc05c120ba6665d29b7559c2c47690906f39279f"}, + {file = "pydantic_core-2.46.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:24922243639cbdac66c75fcb6fd6495a9cb52b213d62f9a0d16f0310b1ff8038"}, + {file = "pydantic_core-2.46.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c76fe65e607be28c7fd4d56fc3c42b1583aa058ce3408b7ad0fd540171d31f9f"}, + {file = "pydantic_core-2.46.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f7b393a8b3da82f5c1fc0751e6d01ac6c55b93c18226a60bdfba4a724efafd1"}, + {file = "pydantic_core-2.46.5-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:7ac031912d54f3d83ef3b3eb98dfabc1608802e2202263d25957eeed40b94761"}, + {file = "pydantic_core-2.46.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:837b396ca3d7b74091ca623f6cbd8351bd42d670a79c2683e79fb089f06a2de5"}, + {file = "pydantic_core-2.46.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:5ee239d575f80b08eca11f6e20f90c4c695de7825c67eefe6091fbf20dda648e"}, + {file = "pydantic_core-2.46.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:e80675d75ae2cd14372cb65cad5400d9347a3d3f6c13000183f22dfd027283ed"}, + {file = "pydantic_core-2.46.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:9c4b71f10dd532fb7a5cbc8f58707779e64f03a258c2bf8bfbaecfcd9970b519"}, + {file = "pydantic_core-2.46.5-cp313-cp313-win32.whl", hash = "sha256:97bf8de4d541598c94a59344eeb988a94c08ff76b5723c41f6567ec18c7892ea"}, + {file = "pydantic_core-2.46.5-cp313-cp313-win_amd64.whl", hash = "sha256:15f4a94963c95accac15b7b657bb177d3ad82bb90b0d0526d9a9b85079925db5"}, + {file = "pydantic_core-2.46.5-cp313-cp313-win_arm64.whl", hash = "sha256:d22a945598fb91236b4dd793a6e42e4f3dd7740bb5aace5ebd7d4c08d13bb575"}, + {file = "pydantic_core-2.46.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c1c43ad4339643d70ebb8124e1305a7dab423001eff58bb41a0f731adbc98355"}, + {file = "pydantic_core-2.46.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1a353f84de772f423b5ffb11d7ae352fbbef0f446f3c0b0af0f8236d7233606e"}, + {file = "pydantic_core-2.46.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5086029a57366b8cf81b130a43908738095c270c21a8d7f0e8bdfdb89718e2f3"}, + {file = "pydantic_core-2.46.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46c25dda9d092a06c08db76ffe0a197107904d0dfac653f7d5306bbcd6d6119c"}, + {file = "pydantic_core-2.46.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:37ea7b83c935e5b0d68c9449b82651accf78a10828b2c02b2f2d9e9496446c21"}, + {file = "pydantic_core-2.46.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e64e88d5585bea9ce95861079de72006c7fa6d3df4e3a3b65ba31eb979c15c9f"}, + {file = "pydantic_core-2.46.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d510bac3ee52247af28ed4bb18a1e799f040ac60fd2bf5ccd4c92f1fbe786f"}, + {file = "pydantic_core-2.46.5-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:a2a5e1d0ff29adddc9f6d6821a66302e4493f8ca898b715b6b1182c2c201ea0a"}, + {file = "pydantic_core-2.46.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:03b9666e41e35d8909852ba191a0607520f81b74eaf12ccf8737005dbb313821"}, + {file = "pydantic_core-2.46.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:a91c17edf6eea2402cb5457b4c89e99bc5ed1004aa34c4adf1d4258c1a5c22c2"}, + {file = "pydantic_core-2.46.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b49924c73a235e969511bf2aabdff3beebf9820931f646c80274d5d780010c47"}, + {file = "pydantic_core-2.46.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:2cbd9a5eff05e51c447c34dfa4632145b26b09120cf04bd0c871e44c1a5e1c9a"}, + {file = "pydantic_core-2.46.5-cp314-cp314-win32.whl", hash = "sha256:2d5d76654becf5efd62c9e51c3756c67b49498b0c9a40884934c40807adbd074"}, + {file = "pydantic_core-2.46.5-cp314-cp314-win_amd64.whl", hash = "sha256:fa10ef4112775900e7a0661068635eb67b2ab824fbde764de6e0e21982a93db0"}, + {file = "pydantic_core-2.46.5-cp314-cp314-win_arm64.whl", hash = "sha256:045ab3b6d308439e32b81cc173bba5b9018bc6ed896afd0c65b3b009b1699af5"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8816f3d218beb4b787de5c9759c259b8fa61f9dec42dc7811f320a33771778b7"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bce57638e08ac148e5778cce7feb968307a727d66f8e2274a543d0cf0c9ad6a3"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:976e1128455aa595ea04c79ccfedff1aaeab96ee013fcc916bed120c4f0ad94f"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b891faeedeafba41b2983e5001a81b6a915b69544c7e7570d1989ce1c36ac7"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f194189415698233dd1114a093a9b56e61e2c57e11b469be3b0506f46f0771c"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82a36973cf8a2ef5406f4fe2edbf8ed0c99629535d959e0b100c76a32535a111"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdbb78909f52b981d3b2d56b97328d71eb0b974c36bd77c920123a7ebb192829"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:52e24eacdb536cade636aa90fb851835222becff8484b7001fdc78cb0290f2aa"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:37ae34309d7bd8c0d61ab839668058f2a7962ea1fc51d105d2db228fe0618034"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:0cdbada856a1c69a7624a64d3d9aefe79300bd6ef827b43a4f265010b9b55184"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:545f26c504b27c3758439a5e6d9349931f0a04f855668d5fe323c89e82300a38"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:ff218293c9c806138dca139765e3b067621be52bcd93cdc14c7711be7ddc90a9"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-win32.whl", hash = "sha256:97cf3eb53a8cccacf9d46686a0926186c9bfb5574f2ed66d3639d5fe117cd3a9"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-win_amd64.whl", hash = "sha256:d2f9fc07a8042a8f95925b35c4f04f469707c981fc33245b6ca187cf5d2dd290"}, + {file = "pydantic_core-2.46.5-cp314-cp314t-win_arm64.whl", hash = "sha256:acf8a67ba51f4ca9ddbd0e6b3000a65ac51ab734661778b3e7ba64d99a710f2f"}, + {file = "pydantic_core-2.46.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c583b927a8838dab890706a6fa7573fbb8b70e24000ef9f7238e2d6f6435a5ed"}, + {file = "pydantic_core-2.46.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdc8b74ecc48c0cb1e9607a05ec4e9e88db60a19ffcc9a1d5f9088ede40c8dc0"}, + {file = "pydantic_core-2.46.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b10e3e8fd7ddc2bd915848a2768e44c15b22936f1cc54c462ad1164deb02655"}, + {file = "pydantic_core-2.46.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f077d0b97ab11fa7dcc633fca53515f290bca8a8a633e966d5b6d1879d9ed01a"}, + {file = "pydantic_core-2.46.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b0fc826b16c55e561e5d2a0c5c77b051ba1d92808118c4e4b5390f5e0cf191d"}, + {file = "pydantic_core-2.46.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef3fbbf161dc9351a2fe0422e51b129f9e97e42385bd0320b309c15f7d287dd8"}, + {file = "pydantic_core-2.46.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:978e7b97d4824b5be09c69fb70507cbde3b0323fc147332ca40a94d9a6a0ebbf"}, + {file = "pydantic_core-2.46.5-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:9b68938dd5b0c783d88ff8e2dcc69451b5eb936fe212d516b21b9d5567f6d464"}, + {file = "pydantic_core-2.46.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:771cf63ae0b1b50dd22e5f3e3549fab5f3f4ff1635d352a9e1a97fe01c7b2e64"}, + {file = "pydantic_core-2.46.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7c6be839a5a8312626b32029a415644a0846b420bc8b52b95b28cd92da162168"}, + {file = "pydantic_core-2.46.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:895395f8918627b04efb1ad2a4cf605387143300ba03304cd1dfa6d03f5e095e"}, + {file = "pydantic_core-2.46.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fc8515076c11f3cfdf4fb142dcca0fe384b1230a3b5415458ac84f3e0903ec13"}, + {file = "pydantic_core-2.46.5-cp39-cp39-win32.whl", hash = "sha256:3d2652072b2d774947ba5cf78a9e59644ac62ee572daf6dd2e1dfe905e15b2b7"}, + {file = "pydantic_core-2.46.5-cp39-cp39-win_amd64.whl", hash = "sha256:3aa166e99c4f2985407fb8714aebede877ecb5455cf321b606adca926d30d5a0"}, + {file = "pydantic_core-2.46.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:c14ad3bdc85ee7f318742c457ca3968a92126d144b15721c759033bfb06296c2"}, + {file = "pydantic_core-2.46.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0bddb4020d8f04175865ccd17eff3040874fc11fb593f424edb452653b4b947c"}, + {file = "pydantic_core-2.46.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2471fd51c61c610e1dcf7de44d7299283661654d11264ab4802b303368d69c47"}, + {file = "pydantic_core-2.46.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10ec717381bdbfafef34607824db4c91de69ff085e4fca3b2af91b4fa17e68a"}, + {file = "pydantic_core-2.46.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:013d6f3483d81e02e7c328831808f336c8596ee33b4bd4026b9ffb1e960b8942"}, + {file = "pydantic_core-2.46.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:e9c134bb666dd54b778b9fc0d2b50cbb7f979b9e3716f26a88c9ab3b6fc1dd0f"}, + {file = "pydantic_core-2.46.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:347ec774390c87326a2e4929d58d3f7e8763a104d5d35f4cd595a4c952366433"}, + {file = "pydantic_core-2.46.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e24d8f05fa2d28513d94e877e9c75ad66175376209b3977f916e240e623193c"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ab4b66edffb32d9e951efb3814bd104b8367a7501b81b955cacb5726d897389f"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:337639ba62a11acde6ef3aeb08c8ea755f8ef1fe5e513356c0f36a2b0d7568b0"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:413a717a410d0c817ef5b786a059415550b3794e1d0c2abffd9efb93a3d9f7b4"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1e449def1945a462c464331254e5a44fca7c3b4f9aedf59ec2f50f8066dd8e25"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a445486499897b88a7d6c310c88ed64dd37b1b59bfd7ae9107490bbb362f47d6"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2d330aaba8621b1edcec8ae2c4050f63b84ccf6d98723a8f212e9684713abf0e"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b6acfb46a814762367fb7ba0828b0a17d441b92ce249a0e007474c9072662dda"}, + {file = "pydantic_core-2.46.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d0a24b40877af2de4950252be9d21eaf7fb07660f3c2cae1f56c6b599ada5266"}, + {file = "pydantic_core-2.46.5.tar.gz", hash = "sha256:10416c15b8839ecc4ef4d0885da76da6fd0f67333a0eb8aff6d93c4b8f2910fc"}, ] [package.dependencies] @@ -1091,14 +1133,14 @@ typing-extensions = ">=4.14.1" [[package]] name = "pygments" -version = "2.20.0" +version = "2.21.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, - {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, + {file = "pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9"}, + {file = "pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c"}, ] [package.extras] @@ -1285,14 +1327,14 @@ files = [ [[package]] name = "types-python-dateutil" -version = "2.9.0.20260518" +version = "2.9.0.20260807" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_python_dateutil-2.9.0.20260518-py3-none-any.whl", hash = "sha256:d6a9c5bd0de61460c8fdef8ab2b400f956a1a1075cce08d4e2b4434e478c50b8"}, - {file = "types_python_dateutil-2.9.0.20260518.tar.gz", hash = "sha256:51f02dc03b61c7f6a07df45797d4dfe8a1aa47f0b7db9ad89f6fd3a1a70e1b51"}, + {file = "types_python_dateutil-2.9.0.20260807-py3-none-any.whl", hash = "sha256:54aa3707350ed7a9cc0776fd2f6739679d6967d11b40150985e81edcb86df4db"}, + {file = "types_python_dateutil-2.9.0.20260807.tar.gz", hash = "sha256:e0b8a90d464c8684c66b7b8e4556d9074afdddcc56ca45323f0987134f9e7034"}, ] [[package]] @@ -1309,29 +1351,29 @@ files = [ [[package]] name = "typing-inspection" -version = "0.4.2" +version = "0.4.4" description = "Runtime typing introspection tools" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, - {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, + {file = "typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147"}, + {file = "typing_inspection-0.4.4.tar.gz", hash = "sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47"}, ] [package.dependencies] -typing-extensions = ">=4.12.0" +typing-extensions = ">=4.15.0" [[package]] name = "urllib3" -version = "2.7.0" +version = "2.8.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, - {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, + {file = "urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3"}, + {file = "urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63"}, ] [package.extras] @@ -1342,117 +1384,151 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "yarl" -version = "1.24.2" +version = "1.25.1" description = "Yet another URL library" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"aiohttp\"" files = [ - {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5249a113065c2b7a958bc699759e359cd61cfc81e3069662208f48f191b7ed12"}, - {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4425fa244fbf530b006d0c5f79ce920114cfff5b4f5f6056e669f8e160fdc0"}, - {file = "yarl-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15c0b5e49d3c44e2a0b93e6a49476c5edad0a7686b92c395765a7ea775572a75"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:246d32a53a947c8f0189f5d699cbd4c7036de45d9359e13ba238d1239678c727"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:64480fb3e4d4ed9ed71c48a91a477384fc342a50ca30071d2f8a88d51d9c9413"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:349de4701dc3760b6e876628423a8f147ef4f5599d10aba1e10702075d424ed9"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d162677af8d5d3d6ebab8394b021f4d041ac107a4b705873148a77a49dc9e1b2"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5f5c6ec23a9043f2d139cc072f53dd23168d202a334b9b2fda8de4c3e890d90"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:60de6742447fbbf697f16f070b8a443f1b5fe6ca3826fbef9fe70ecd5328e643"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acf93187c3710e422368eb768aee98db551ec7c85adc250207a95c16548ab7ac"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f4b0352fd41fd34b6651934606268816afd6914d09626f9bcbbf018edb0afb3f"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6b208bb939099b4b297438da4e9b25357f0b1c791888669b963e45b203ea9f36"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4b85b8825e631295ff4bc8943f7471d54c533a9360bbe15ebb38e018b555bb8a"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e26acf20c26cb4fefc631fdb75aca2a6b8fa8b7b5d7f204fb6a8f1e63c706f53"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:819ca24f8eafcfb683c1bd5f44f2f488cea1274eb8944731ffd2e1f10f619342"}, - {file = "yarl-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:5cb0f995a901c36be096ccbf4c673591c2faabbe96279598ffaec8c030f85bf4"}, - {file = "yarl-1.24.2-cp310-cp310-win_arm64.whl", hash = "sha256:f408eace7e22a68b467a0562e0d27d322f91fe3eaaa6f466b962c6cfaea9fa39"}, - {file = "yarl-1.24.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:36348bebb147b83818b9d7e673ea4debc75970afc6ffdc7e3975ad05ce5a58c1"}, - {file = "yarl-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a97e42c8a2233f2f279ecadd9e4a037bcb5d813b78435e8eedd4db5a9e9708c"}, - {file = "yarl-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8d027d56f1035e339d1001ac33eceab5b2ec8e42e449787bb75e289fb9a5cd1d"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a6377060e7927187a42b7eb202090cbe2b34933a4eeaf90e3bd9e33432e5cae"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:17076578bce0049a5ce57d14ad1bded391b68a3b213e9b81b0097b090244999a"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:50713f1d4d6be6375bb178bb43d140ee1acb8abe589cd723320b7925a275be1e"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:34263e2fa8fb5bb63a0d97706cda38edbad62fddb58c7f12d6acbc092812aa50"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49016d82f032b1bd1e10b01078a7d29ae71bf468eeae0ea22df8bab691e60003"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3f6d2c216318f8f32038ca3f72501ba08536f0fd18a36e858836b121b2deed9f"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:08d3a33218e0c64393e7610284e770409a9c31c429b078bcb24096ed0a783b8f"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5d699376c4ca3cba49bbfae3a05b5b70ded572937171ce1e0b8d87118e2ba294"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a1cab588b4fa14bea2e55ebea27478adfb05372f47573738e1acc4a36c0b05d2"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ec87ccc31bd21db7ad009d8572c127c1000f268517618a4cc09adba3c2a7f21c"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d1dd47a22843b212baa8d74f37796815d43bd046b42a0f41e9da433386c3136b"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7b54b9c67c2b06bd7b9a77253d242124b9c95d2c02def5a1144001ee547dd9d5"}, - {file = "yarl-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:f8fdbcff8b2c7c9284e60c196f693588598ddcee31e11c18e14949ce44519d45"}, - {file = "yarl-1.24.2-cp311-cp311-win_arm64.whl", hash = "sha256:b32c37a7a337e90822c45797bf3d79d60875cfcccd3ecc80e9f453d87026c122"}, - {file = "yarl-1.24.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b975866c184564c827e0877380f0dae57dcca7e52782128381b72feff6dfceb8"}, - {file = "yarl-1.24.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3b075301a2836a0e297b1b658cb6d6135df535d62efefdd60366bd589c2c82f2"}, - {file = "yarl-1.24.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ae44649b00947634ab0dab2a374a638f52923a6e67083f2c156cd5cbd1a881d"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:507cc19f0b45454e2d6dcd62ff7d062b9f77a2812404e62dbdaec05b50faa035"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4c17bad5a530912d2111825d3f05e89bab2dd376aaa8cbc77e449e6db63e576"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5f0cbb112838a4a293985b6ed73948a547dadcc1ba6d2089938e7abdedceef8"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ec8356b8a6afcf81fc7aeeef13b1ff7a49dec00f313394bbb9e83830d32ccd7"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e7ebcdef69dec6c6451e616f32b622a6d4a2e92b445c992f7c8e5274a6bbc4c"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:47a55d6cf6db2f401017a9e96e5288844e5051911fb4e0c8311a3980f5e59a7d"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3065657c80a2321225e804048597ad55658a7e76b32d6f5ee4074d04c50401db"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cb84b80d88e19ede158619b80813968713d8d008b0e2497a576e6a0557d50712"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:990de4f680b1c217e77ff0d6aa0029f9eb79889c11fb3e9a3942c7eba29c1996"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:abb8ec0323b80161e3802da3150ef660b41d0e9be2048b76a363d93eee992c2b"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e7977781f83638a4c73e0f88425563d70173e0dfd90ac006a45c65036293ee3c"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e30dd55825dc554ec5b66a94953b8eda8745926514c5089dfcacecb9c99b5bd1"}, - {file = "yarl-1.24.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dafe10c12ddd4d120d528c4b5599c953bd7b12845347d507b95451195bb6cad"}, - {file = "yarl-1.24.2-cp312-cp312-win_arm64.whl", hash = "sha256:044a09d8401fcf8681977faef6d286b8ade1e2d2e9dceda175d1cfa5ca496f30"}, - {file = "yarl-1.24.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:491ac9141decf49ee8030199e1ee251cdff0e131f25678817ff6aa5f837a3536"}, - {file = "yarl-1.24.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e89418f65eda18f99030386305bd44d7d504e328a7945db1ead514fbe03a0607"}, - {file = "yarl-1.24.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cdfcce633b4a4bb8281913c57fcafd4b5933fbc19111a5e3930bbd299d6102f1"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:863297ddede92ee49024e9a9b11ecb59f310ca85b60d8537f56bed9bbb5b1986"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:374423f70754a2c96942ede36a29d37dc6b0cb8f92f8d009ddf3ed78d3da5488"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33a29b5d00ccbf3219bb3e351d7875739c19481e030779f48cc46a7a71681a9b"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a9532c57211730c515341af11fef6e9b61d157487272a096d0c04da445642592"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91e72cf093fd833483a97ee648e0c053c7c629f51ff4a0e7edd84f806b0c5617"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b3177bc0a768ef3bacceb4f272632990b7bea352f1b2f1eee9d6d6ff16516f92"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e196952aacaf3b232e265ff02980b64d483dc0972bd49bcb061171ff22ac203a"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:204e7a61ce99919c0de1bf904ab5d7aa188a129ea8f690a8f76cfb6e2844dc44"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b156914620f0b9d78dc1adb3751141daee561cfec796088abb89ed49d220f1a"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8372a2b976cf70654b2be6619ab6068acabb35f724c0fda7b277fbf53d66a5cf"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f9a1e9b622ca284143aab5d885848686dcd85453bb1ca9abcdb7503e64dc0056"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:810e19b685c8c3c5862f6a38160a1f4e4c0916c9390024ec347b6157a45a0992"}, - {file = "yarl-1.24.2-cp313-cp313-win_amd64.whl", hash = "sha256:7d37fb7c38f2b6edab0f845c4f85148d4c44204f52bc127021bd2bc9fdbf1656"}, - {file = "yarl-1.24.2-cp313-cp313-win_arm64.whl", hash = "sha256:1e831894be7c2954240e49791fa4b50c05a0dc881de2552cfe3ffd8631c7f461"}, - {file = "yarl-1.24.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:f9312b3c02d9b3d23840f67952913c9c8721d7f1b7db305289faefa878f364c2"}, - {file = "yarl-1.24.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a4f4d6cd615823bfc7fb7e9b5987c3f41666371d870d51058f77e2680fbe9630"}, - {file = "yarl-1.24.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0c3063e5c0a8e8e62fae6c2596fa01da1561e4cd1da6fec5789f5cf99a8aefd8"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fecd17873a096036c1c87ab3486f1aef7f269ada7f23f7f856f93b1cc7744f14"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a46d1ab4ba4d32e6dc80daf8a28ce0bd83d08df52fbc32f3e288663427734535"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73e68edf6dfd5f73f9ca127d84e2a6f9213c65bdffb736bda19524c0564fcd14"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a296ca617f2d25fbceafb962b88750d627e5984e75732c712154d058ae8d79a3"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51b2cf5ec89a8b8470177641ed62a3ba22d74e1e898e06ad53aa77972487208"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:310fc687f7b2044ec54e372c8cbe923bb88f5c37bded0d3079e5791c2fc3cf50"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:297a2fe352ecf858b30a98f87948746ec16f001d279f84aebdbd3bd965e2f1bd"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2a263e76b97bc42bdcd7c5f4953dec1f7cd62a1112fa7f869e57255229390d67"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:822519b64cf0b474f1a0aaef1dc621438ea46bb77c94df97a5b4d213a7d8a8b1"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b6067060d9dc594899ba83e6db6c48c68d1e494a6dab158156ed86977ca7bcb1"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:0063adad533e57171b79db3943b229d40dfafeeee579767f96541f106bac5f1b"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ee8e3fb34513e8dc082b586ef4910c98335d43a6fab688cd44d4851bacfce3e8"}, - {file = "yarl-1.24.2-cp314-cp314-win_amd64.whl", hash = "sha256:afb00d7fd8e0f285ca29a44cc50df2d622ff2f7a6d933fa641577b5f9d5f3db0"}, - {file = "yarl-1.24.2-cp314-cp314-win_arm64.whl", hash = "sha256:68cf6eacd6028ef1142bc4b48376b81566385ca6f9e7dde3b0fa91be08ffcb57"}, - {file = "yarl-1.24.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:221ce1dd921ac4f603957f17d7c18c5cc0797fbb52f156941f92e04605d1d67b"}, - {file = "yarl-1.24.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5f3224db28173a00d7afacdee07045cc4673dfab2b15492c7ae10deddbece761"}, - {file = "yarl-1.24.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c557165320d6244ebe3a02431b2a201a20080e02f41f0cfa0ccc47a183765da8"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:904065e6e85b1fa54d0d87438bd58c14c0bad97aad654ad1077fd9d87e8478ed"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cec2a38d70edc10e0e856ceda886af5327a017ccbde8e1de1bd44d300357543"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e7484b9361ed222ee1ca5b4337aa4cbdcc4618ce5aff57d9ef1582fd95893fc0"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:84f9670b89f34db07f81e53aee83e0b938a3412329d51c8f922488be7fcc4024"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:abb2759733d63a28b4956500a5dd57140f26486c92b2caedfb964ab7d9b79dbf"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:081c2bf54efe03774d0311172bc04fedf9ca01e644d4cd8c805688e527209bdc"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:86746bef442aa479107fe28132e1277237f9c24c2f00b0b0cf22b3ee0904f2bb"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:2d07d21d0bc4b17558e8de0b02fbfdf1e347d3bb3699edd00bb92e7c57925420"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4fb1ac3fc5fecd8ae7453ea237e4d22b49befa70266dfe1629924245c21a0c7f"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4da31a5512ed1729ca8d8aacde3f7faeb8843cde3165d6bcf7f88f74f17bb8aa"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:533ded4dceb5f1f3da7906244f4e82cf46cfd40d84c69a1faf5ac506aa65ecbe"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7b3a85525f6e7eeabcfdd372862b21ee1915db1b498a04e8bf0e389b607ff0bd"}, - {file = "yarl-1.24.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a7624b1ca46ca5d7b864ef0d2f8efe3091454085ee1855b4e992314529972215"}, - {file = "yarl-1.24.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e434a45ce2e7a947f951fc5a8944c8cc080b7e59f9c50ae80fd39107cf88126d"}, - {file = "yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9"}, - {file = "yarl-1.24.2.tar.gz", hash = "sha256:9ac374123c6fd7abf64d1fec93962b0bd4ee2c19751755a762a72dd96c0378f8"}, + {file = "yarl-1.25.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:142c06c4d6a35ee3ec5da08499805e879cb3ca7c1fbfbecb0140fe72403818d6"}, + {file = "yarl-1.25.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:24ce942011a61953e7d313438038f4d32ff21387b775f58a957f7a07dd55ef95"}, + {file = "yarl-1.25.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e23c82b63cd7652fc24d33ed6cc17099d607aa3b4fc4ddc75e95062f3d82df4"}, + {file = "yarl-1.25.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ee202350cf57abf0e9502a41601841019c25d3db7ff52d980aaf31446254059"}, + {file = "yarl-1.25.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5df89f769cc8ff94c3d7e7603386fba309d25ce5240132d26c15baa8d0e96c4c"}, + {file = "yarl-1.25.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:83e9f4a25085bd4b7214701a0794ff1f50fc633ffb8bdfebf07abdd81c2db126"}, + {file = "yarl-1.25.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e636b64d24fd9c38053c5e389a1174c66361fa49dcfd220f4dd35b4abde7cb89"}, + {file = "yarl-1.25.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e5637ca8d0bd7fb72648a6c7934af4baaccb697657f7438c9d264fc2abb8b0b1"}, + {file = "yarl-1.25.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:683e362b8ba453080f7489c66f4ea794e751c35b72e7eab3575ef784c2fbc7fb"}, + {file = "yarl-1.25.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:df23df54b5114a17c2d0ef192433e2e5a9f0c5178c32375e90b7cfc965f349d0"}, + {file = "yarl-1.25.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f53dcd26694f148f738edc052b5a69234833e739f10f4c3287bdfd8ec0f7b326"}, + {file = "yarl-1.25.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:b8075fe90bc08e40b8b8a1874fab42ee4c7b56af05c5886e9cc841397f916908"}, + {file = "yarl-1.25.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:a8c2b841478068440d8b733005d13a5ef535b9928cbc05f17182d410f32ba449"}, + {file = "yarl-1.25.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ca32926d7d77bcc8838425c4c95e040a3ace1cb7dfdae599013458dcda2607ca"}, + {file = "yarl-1.25.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:192a866877a49993949ef1975864ad8728bea28ee810f6abe1a0729c2b500426"}, + {file = "yarl-1.25.1-cp310-cp310-win_amd64.whl", hash = "sha256:3f4d48a6112712973e676bd792121fee470e432d749177162d9949d5c9460a1b"}, + {file = "yarl-1.25.1-cp310-cp310-win_arm64.whl", hash = "sha256:48796ea00a303961507dc6c8437c4b325a6fc3f95f7c36c71b91ea9a8150963c"}, + {file = "yarl-1.25.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9d693bf4bf534e9ba3ae2780cfd577f5135629f7b5ac653490859d0b77864865"}, + {file = "yarl-1.25.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ab2054c5531af2a9ba7b69b8ec91e4f884420e83a8c5e579b013084cb57e5e5d"}, + {file = "yarl-1.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:564fdc7085d2245ab84f88882fdb1d6ac0723124bff6ded35bfb1c00f812630d"}, + {file = "yarl-1.25.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:acae6b45d1ace09b6ba3876da43b88366ef368f73b988c7f57e14231753d4420"}, + {file = "yarl-1.25.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1fb2a01ba8cd9c5d2c5dc1ec35e0fc951d04b4f037541d4ac090c993ce58b3d7"}, + {file = "yarl-1.25.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e92b6bcc741b86d67606c40d3cb9c7cc8e6c737f81e31f4a94efc204456c92e3"}, + {file = "yarl-1.25.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:72c34ac7ad4314c19362d5ce27626dcc8429bd30bbf8c179f4234078851f9492"}, + {file = "yarl-1.25.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5add7b4ca7afeea91d52e4d4e4db3b1fe9885b71f07054560d8c4296b7441a2"}, + {file = "yarl-1.25.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:def538065f9e4d4cf1ae164bd59aba00dfa84f03923e0de4c3788f252d6bcd17"}, + {file = "yarl-1.25.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a191bfdb30a79b98e5d175d75285f9fcb78bf0e46ba5efda042e1c72071a0de"}, + {file = "yarl-1.25.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:71f42c5b9a948c113bbdebfa544598321431d064ff959d32e99b1feb61d68345"}, + {file = "yarl-1.25.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:72849d892954be4d09e569b8b831ac39ce58417fedc767d4308a0fe542018a40"}, + {file = "yarl-1.25.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:efb01a106f971cb3752856bca2318bbdf7f01bd8823779c461586cbe5ffd5258"}, + {file = "yarl-1.25.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a1daf47cd95a7c3a63456336bc5aaa8c86dd3a47d07ed3d0e76132ae4666a5a1"}, + {file = "yarl-1.25.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9489e6abf47ba37f332075a91444c7cfedb03e6ce99fbb2f116bfe1ce810da3b"}, + {file = "yarl-1.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7306dee25b8a0e737363f347362b875094b4dc4e367311470656ae420fdbf8e"}, + {file = "yarl-1.25.1-cp311-cp311-win_arm64.whl", hash = "sha256:abb1384477f5901d436b5d2e5465954de46ea6098f59163d243660b5c4461d35"}, + {file = "yarl-1.25.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:94d7aa6debf92a1dd14cb5280b083a764169a13cfb23a452111160274ed989f4"}, + {file = "yarl-1.25.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:83d4a37e4b95da4d8bda930d6d35b75b4cdadbacbb4980cae290ea3100b5d51d"}, + {file = "yarl-1.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e029648f9c951db30e98a7d7ec90835db88ec4b32820efe2a9bdc2287e032eb6"}, + {file = "yarl-1.25.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d781294bb815ecb5ea57ff6bbf8038e0a31a95fdf3e1788f66e0dc100d64b58"}, + {file = "yarl-1.25.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e12c538e00e7c1b286a07061046b90e8124e6a9793efae2c70db6a4aad07faad"}, + {file = "yarl-1.25.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7e4de3ac4adbad3d0bc7c6f4360a7dbff5de2f15e3b723be3198074e17fd9c40"}, + {file = "yarl-1.25.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:419f392a1da624877975709e3864dfe833af6cc7671b39318086d456e288380c"}, + {file = "yarl-1.25.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6f117789d22dce188e5754e8bc65b7e6ebf8cb73963b9fa761f672a5883769d"}, + {file = "yarl-1.25.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:80e47012e730da131c9f059c80936783f9659aae22dc31c03c0595590d11ed54"}, + {file = "yarl-1.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e80f557716fd765439577131e526b8942ffc2c07bdbc5e39fa62f660ba1e963f"}, + {file = "yarl-1.25.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:f61964f235a43738bfac50da46fc4254943a7eea3051aeb0b6fc7c992c29fadc"}, + {file = "yarl-1.25.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e546fe1d4a93ebc2910f0d768baff19faa09843ab3f2036a67ed6e69fae4419d"}, + {file = "yarl-1.25.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cce0727fd5ac04d372fa9bbfde9febc2bcf209aadfcf0468e45dec72719895d1"}, + {file = "yarl-1.25.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af4ea5b37403ef4e30f3927eaed540db942bde01d8d3ff083527c0704d1c9c68"}, + {file = "yarl-1.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:68782fdb4027b8d1eee25ec35e9a6db05e863b899eb0310b3a33b6c3fef55707"}, + {file = "yarl-1.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:7d575b54cb3863ef9bc290ea4b009999d55dc237326131e4853cf33e888fee03"}, + {file = "yarl-1.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:bc3ac7bf569f6b64dad04dd7808c7872dae8a97df657856eac05e9b7e3614a85"}, + {file = "yarl-1.25.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:25868beca8b6765f8f7d0e11fe6dd7c66dd4b0793b9500286d20cc92352126a5"}, + {file = "yarl-1.25.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:10b2fd95332f0d716d5eee3c9fb2ce8eada19082de7fee83d32e37992fd75c26"}, + {file = "yarl-1.25.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f12afda4eea8c8994a76d4df1875c765194f5fbe8a9d197929ea303caee29ec"}, + {file = "yarl-1.25.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14b79a30a93a3ce2e8832603fd0ab780ada281b0ba5110b519a634f2d7d7d1fc"}, + {file = "yarl-1.25.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4bd6340d20ae2c7ca719b87b426e808e90743b676d05d4c26c4fb5ca71f41184"}, + {file = "yarl-1.25.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:126a2533570c554719ca40a1288fdee1700b6bc82e7131aa69fa85252d92e651"}, + {file = "yarl-1.25.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a3faadac7d812ddac258feb57b9846b60c1b437c4f4b9ad42595c6f6fe4390df"}, + {file = "yarl-1.25.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be80550d9bfe83d9b62398a37081a90434e6df2d978ec345c3d2820de6beddab"}, + {file = "yarl-1.25.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e07595c7d6f4db270ceede356a1bd1c07a34f1c26f958d1ed0cd7b48e0d2bba3"}, + {file = "yarl-1.25.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eb96ed1ae6c7d072d60840c0434aef07a2df611812810807fbc54263a6053e9a"}, + {file = "yarl-1.25.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3feb99222553a8cbedfa52c2f59dd84c3f50d5b582c728d522caf8d72769a54b"}, + {file = "yarl-1.25.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a2ed0ba415ccdf08f14bf544cb78346d0f76086707ffee24921a2c84dbf1305a"}, + {file = "yarl-1.25.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2b49375d22299b0a834c2bca72f39aaecc270d96fb24c30424899676f487b22a"}, + {file = "yarl-1.25.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ef74070ac553c59eb4f04258722066d6c6135b7baa03b2e9f2da65c096e96d98"}, + {file = "yarl-1.25.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0a66db89ea473abeac4b70523cafd94db3772380e565f9d28af7a179b7af71fa"}, + {file = "yarl-1.25.1-cp313-cp313-win_amd64.whl", hash = "sha256:1f51020b2eb8a003c84925638ec63c21a750a4bddd3a22ec8eac6a742dadf1b9"}, + {file = "yarl-1.25.1-cp313-cp313-win_arm64.whl", hash = "sha256:b10dd0557ba422715b5206b3743192135a6022acca8baec51aa127d0a75db8fe"}, + {file = "yarl-1.25.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:a9ca696eb02e5c02a8afd872ada510eba9b7fe6e68b9572c2e9a9b1941e31e2e"}, + {file = "yarl-1.25.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a5877f2255aab518ebe528289037699201d5dc5f045f2396cb30aa02db22f57f"}, + {file = "yarl-1.25.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7a5c3115595995779ee21f2567035793911c3802a43c74f3fbb0314929ec67ac"}, + {file = "yarl-1.25.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77e5099b99b37f3cf79c246998ca9f7313a78054cd1809ec46bc1afad47e1c4c"}, + {file = "yarl-1.25.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6efaf45df6a849cef613a03a94c845647456662f85438c886bb67a9c027c8c2c"}, + {file = "yarl-1.25.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5f90e44653c4e0f78501ed9bb7d3fce835a8d62b7c6ed0cb16557534087e743"}, + {file = "yarl-1.25.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:632da579b2d879f6bad20f2cfa35ded1efe2f4f77f8abb26a6234a5b236acd2f"}, + {file = "yarl-1.25.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:30eec96e8a91bd588ce897c9543f6d5d8d34b28fbcba28a4dedf20ebeae9fe57"}, + {file = "yarl-1.25.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:12b6bc4906e11f5e1a1cdcb12296e7afbd366c783cc8073403cd2fb74334e453"}, + {file = "yarl-1.25.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9d6ed3d17bccce4c05343e1ca8da13bc5c02c812a4e7282ddd05e8769322d3fc"}, + {file = "yarl-1.25.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:f38a70074041d3b7e138e452799f5174198bae5bd5ab2000917badf403908c5f"}, + {file = "yarl-1.25.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca89e4e21854ed27ec753297dde84b16c9f8e53b14a4866fb44457d643c19f8"}, + {file = "yarl-1.25.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:1ab7618921a93767387a4b83776f751588f5b5ae9bb5bc96620e2e2e00bca868"}, + {file = "yarl-1.25.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:0ae12ff2b805fa02c4dab838005caef735e39986322698c48588d3beacb65c62"}, + {file = "yarl-1.25.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:90c30ed53546da833c700115c0064c22120d1b1560f474699fd31f22dd668233"}, + {file = "yarl-1.25.1-cp314-cp314-win_amd64.whl", hash = "sha256:acfa7e22aa6c6e7a5996a41d275bfa01efa7ea56ab890590280e9063e2cf5c1b"}, + {file = "yarl-1.25.1-cp314-cp314-win_arm64.whl", hash = "sha256:8e7d98cdbb6d71e726f7d525952867096053d1f290dd4e3c50d7d313a136f414"}, + {file = "yarl-1.25.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d21f0fa80a02d05299207eeaafef345d812ace96d5306e4ef265e1d419a615fa"}, + {file = "yarl-1.25.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:17c9877a89fb6e2bca6f9087eb24cd7fb434653946ef5075e470d23d49b52287"}, + {file = "yarl-1.25.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:29273edf1530e397bd07cb784db1fbe0d2590b77569f2e24679a9c0a2d763b94"}, + {file = "yarl-1.25.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7abffdf37af1cec6a2ad69b827aa84320db5894791bc8ed932dc93fb274b7e9"}, + {file = "yarl-1.25.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2239a02249d9326655419e0168a28ca9008938eaab31dc29fc875c217927a6c0"}, + {file = "yarl-1.25.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:664ec6a520b74a1df2810666eb67695fcb77fa663e6ea0a25aaf2e529cb24dfa"}, + {file = "yarl-1.25.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4f1c91f5a5980a937ff8e238e98e6897e1ad74a4b1e2c0d68c73b5ffbb3f5c0b"}, + {file = "yarl-1.25.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c88edaec8c349ad4c5ad4c486a3defcc4b80ceb2f074436ffa0a87caf5e76a6"}, + {file = "yarl-1.25.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:35dcbea443fafb3eece757ad4e514560ddeb6c34cfae1582c620d7b293d7feee"}, + {file = "yarl-1.25.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:882569ff613758cac762a457a5d72d6e211b28d4bcfea89d1d71ea942b02eac0"}, + {file = "yarl-1.25.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d0f1489233a254bb3643d2f05de7d59019254d81daeca6b9162fe9edef57e0c7"}, + {file = "yarl-1.25.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f41753a76f4f63927d03a0d8ba8f5ce0f2083bec29a8cfaccc55371b1564b96b"}, + {file = "yarl-1.25.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8fb0eb4955adf0579001581f2f71a126e8781ba61bcd120f127b0401163c6c2d"}, + {file = "yarl-1.25.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a1e32763e641a1566507d90a8d3b19bfc3cc04a9d4e5ae3e32189874ed4b58a3"}, + {file = "yarl-1.25.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65b5b2066651b7432d389e9799d979c703bcc6ef44266bb8153ef54e91e4aab3"}, + {file = "yarl-1.25.1-cp314-cp314t-win_amd64.whl", hash = "sha256:734f6e5400352ac4254456003d462866c684703570929cff7a7bde015d0cb371"}, + {file = "yarl-1.25.1-cp314-cp314t-win_arm64.whl", hash = "sha256:287e99ff5aa4dc1c7630bfc683ded6f106d756c99dec432a2d7f197a784f51c6"}, + {file = "yarl-1.25.1-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:9b1bdaae98bc016825dd3c9d8ee1832f829b3341f9cc6ebd1a1b0a7fef7367cc"}, + {file = "yarl-1.25.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:e7011b8fb8c4054bf0c12e5edc6cd83778b0028e99ce59b18586ed036f92cfdc"}, + {file = "yarl-1.25.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:f074e8d4aa0a5798920ddb6de3d08b228c614ff3724c3e8bd7577f4bafea867b"}, + {file = "yarl-1.25.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d42e7e3ca399555578b4d617e3a6ecf13371b3743a115995fa010c7bf341459"}, + {file = "yarl-1.25.1-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:aa4ed3dd308548f9e707d9caaf005d2d7f8c1e7868f858dfeb47fe76e16b391d"}, + {file = "yarl-1.25.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42a66563d8cc056ee32e6191e05097a7b2b3bc302e0bc3133daf8710eb18bd26"}, + {file = "yarl-1.25.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:98d370568f393215d605304cdb77b3d5539bd192c75b623c7304c42c8d6d8273"}, + {file = "yarl-1.25.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23bf5b403c879a54964e0feac7285688e04bb220074878d737d331522da0a5bf"}, + {file = "yarl-1.25.1-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d45673badd08456d0340e9364eddafe1c53a9d2896424294de4d7dd71ad3ee57"}, + {file = "yarl-1.25.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:0136d640dfa9b0523853e411430a99f8a91eca85774c6420285a33b755bc6de3"}, + {file = "yarl-1.25.1-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:59ba3a6e1aa8cfe5adf4bd270fd965db21955401b7ca6f1696010c55ed4daec2"}, + {file = "yarl-1.25.1-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:87796fedc3ba97ec14fab55acb48584276e6c1e4c1e89c422bda62c838e754a9"}, + {file = "yarl-1.25.1-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:bd0912757081f89b107d6c00b2ff8a194401b0b87eadcf4481de2b865a8fd44f"}, + {file = "yarl-1.25.1-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:b51c159a9794633f5e0db7ecec7b2b6e3734eca1f5d17dc989ff3552a43ff78b"}, + {file = "yarl-1.25.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:319e070a01db9920fb63761843f96a104c8e2b9427266731810dc1e22595b17c"}, + {file = "yarl-1.25.1-cp315-cp315-win_amd64.whl", hash = "sha256:a2059a2d891bd156bc5184e7ab7a56e78a84dfcfdeac8c501b552533ad1c36ee"}, + {file = "yarl-1.25.1-cp315-cp315-win_arm64.whl", hash = "sha256:a78b50b4f7918a3de71105d5c0b93bbc57bb8339a4d03a9dfd449f9068e76f3d"}, + {file = "yarl-1.25.1-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:b5402a340723fa7da00b5cff987ddab61276be6d11251ea71ae02bcac54890d8"}, + {file = "yarl-1.25.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:eda19ea5ee88742f47a2340816e6f2d40b53bed3ab5b69794769f36af9f35bb4"}, + {file = "yarl-1.25.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:75baa6cf9b6d1c52f3e111a130e202fd8cf0a5b3a066c3f73d615e885092e4ec"}, + {file = "yarl-1.25.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dbcef5a9119ef653653132cccaf999b30a0af6f33bb0a4ba80bec30056868487"}, + {file = "yarl-1.25.1-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7efc9f082dfed77c316edffa9deb52888e1bc6789171887cc1f68e06d65465c8"}, + {file = "yarl-1.25.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fe01645169a2112aa1d4ebc3e4c5f029c5c8f97adfc32e5d37c993b39a994d75"}, + {file = "yarl-1.25.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1c557dfd5e3db046053a0bdc72261ade790ebe8e2c7a41b36b0ca1f14cb95f3"}, + {file = "yarl-1.25.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ce4d6ccafb33d39bd78444612d14938ead674c25702ded2ee9c54a47735d225"}, + {file = "yarl-1.25.1-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:80a063f8297fc796296f00f100be520f209b23dc98f93ce8eba6ee7122598209"}, + {file = "yarl-1.25.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:7cb414a73e21a7ab58254926073f2930cb22f5b4314ea4260a687e2b3fd4dce3"}, + {file = "yarl-1.25.1-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:85a18376073f8a39aa07be34f9fc77e2869aa72c55c441efdd2cf79a0407504d"}, + {file = "yarl-1.25.1-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:77716e245c90f058466a05e6a465bb8600f767a8f4b18b4d40f3aff958e5f73c"}, + {file = "yarl-1.25.1-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:1e80dcf1446e1b080b1932b0d103c464a04112f5bc31f0f983ad418172063cde"}, + {file = "yarl-1.25.1-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:bdc8d8b8c22e9e43ac68316b5e6cf083dec537f4ec213cb4aa967b583bc3fa64"}, + {file = "yarl-1.25.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:dfbf531053a0935f2e871bcd4753f90313688772ff8c017f5ea402e315a78c1f"}, + {file = "yarl-1.25.1-cp315-cp315t-win_amd64.whl", hash = "sha256:b13b88747769537f3d32e89e3a735da10c0a9e35d7322928c701b5f93d3afffd"}, + {file = "yarl-1.25.1-cp315-cp315t-win_arm64.whl", hash = "sha256:783dd1467083f4d3f7722ad6a313f24c173e7571372738fcb7a6e6d1ba48df25"}, + {file = "yarl-1.25.1-py3-none-any.whl", hash = "sha256:681c758b0490f9e96b78e5fa8e8dc6e648e9185bb6eaebe73183c33ea0c445f3"}, + {file = "yarl-1.25.1.tar.gz", hash = "sha256:03dd38de09bc213e9a8b29761eec33ee1d5318dac0e49d8af36e4d27830e23a7"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index 710e2c5..d38fd2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "wavix-python-sdk" -version = "1.0.0" +version = "1.1.1" description = "" readme = "README.md" authors = [] diff --git a/reference.md b/reference.md index b13d80f..b18e1c3 100644 --- a/reference.md +++ b/reference.md @@ -73,7 +73,7 @@ client.api_keys.list( -
client.api_keys.create(...) -> ApiKey +
client.api_keys.create(...) -> ApiKeyWithSecret
@@ -728,7 +728,6 @@ client.sip_trunks.create( ip_restrict=False, didinfo_enabled=True, call_restrict=True, - cost_limit=True, channels_restrict=False, rewrite_enabled=True, transcription_enabled=True, @@ -885,7 +884,6 @@ client.sip_trunks.update( ip_restrict=False, didinfo_enabled=True, call_restrict=True, - cost_limit=True, channels_restrict=False, rewrite_enabled=True, transcription_enabled=True, @@ -1008,7 +1006,7 @@ client.sip_trunks.delete(
## Cart -
client.cart.get() -> GetCartResponse +
client.cart.get() -> CartResponse
@@ -1071,7 +1069,7 @@ client.cart.get()
-
client.cart.add(...) -> typing.List[typing.Any] +
client.cart.add(...) -> typing.List[AvailableNumber]
@@ -1147,7 +1145,7 @@ client.cart.add(
-
client.cart.remove(...) -> RemoveCartResponse +
client.cart.remove(...) -> SuccessResponse
@@ -1223,7 +1221,7 @@ client.cart.remove(
-
client.cart.checkout(...) -> CheckoutCartResponse +
client.cart.checkout(...) -> SuccessResponse
@@ -1235,7 +1233,7 @@ client.cart.remove(
-Purchases the listed phone numbers from the cart. Activation and monthly fees are deducted from the account balance. +Purchases the listed phone numbers from the cart. Activation and monthly fees are debited from the account balance immediately, and the purchase cannot be reversed through this API.
@@ -1418,7 +1416,7 @@ client.numbers.list(
-
client.numbers.delete(...) -> DeleteNumbersResponse +
client.numbers.delete(...) -> SuccessResponse
@@ -1923,7 +1921,7 @@ client.cdrs.list(
-**disposition:** `typing.Optional[CallDisposition]` — Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). +**disposition:** `typing.Optional[CallDisposition]` — Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter).
@@ -2031,8 +2029,6 @@ client.cdrs.search( type="placed", from_=datetime.date.fromisoformat("2023-08-01"), to=datetime.date.fromisoformat("2023-08-31"), - page=1, - per_page=50, ) ``` @@ -2073,7 +2069,7 @@ client.cdrs.search(
-**page:** `int` — Page number to retrieve. +**from_search:** `typing.Optional[str]` — Originating phone number to filter results. Accepts full or partial number.
@@ -2081,7 +2077,7 @@ client.cdrs.search(
-**per_page:** `int` — Number of records per page. +**to_search:** `typing.Optional[str]` — Destination phone number to filter results. Accepts full or partial number.
@@ -2089,7 +2085,7 @@ client.cdrs.search(
-**from_search:** `typing.Optional[str]` — Originating phone number to filter results. Accepts full or partial number. +**sip_trunk:** `typing.Optional[str]` — SIP trunk login to filter outbound calls. Ignored for inbound calls.
@@ -2097,7 +2093,7 @@ client.cdrs.search(
-**to_search:** `typing.Optional[str]` — Destination phone number to filter results. Accepts full or partial number. +**min_duration:** `typing.Optional[int]` — Minimum call duration in seconds.
@@ -2105,7 +2101,7 @@ client.cdrs.search(
-**sip_trunk:** `typing.Optional[str]` — SIP trunk login to filter outbound calls. Ignored for inbound calls. +**transcription:** `typing.Optional[TranscriptionFilter]`
@@ -2113,7 +2109,7 @@ client.cdrs.search(
-**min_duration:** `typing.Optional[int]` — Minimum call duration in seconds. +**uuid:** `typing.Optional[str]` — Call ID.
@@ -2121,7 +2117,12 @@ client.cdrs.search(
-**transcription:** `typing.Optional[TranscriptionFilter]` +**disposition:** `typing.Optional[CallDisposition]` + +Call disposition to filter results. If omitted, returns only answered + calls. Allowed values: `answered`, `noanswer`, `busy`, + `failed`, `all`. Use `all` to return calls + regardless of their disposition.
@@ -2129,7 +2130,7 @@ client.cdrs.search(
-**uuid:** `typing.Optional[str]` — Call ID. +**page:** `typing.Optional[int]` — Page number to retrieve.
@@ -2137,12 +2138,7 @@ client.cdrs.search(
-**disposition:** `typing.Optional[CdrSearchRequestDisposition]` - -Call disposition to filter results. If omitted, returns only answered - calls. Allowed values: `answered`, `busy`, `rejected`, - `failed`, `all`. Use `all` to return calls - regardless of their disposition. +**per_page:** `typing.Optional[int]` — Number of records per page.
@@ -2174,7 +2170,7 @@ Call disposition to filter results. If omitted, returns only answered
-Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. +Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. Billed per minute at the account's call-transcription rate; fails with an insufficient-funds error when the balance cannot cover it.
@@ -2198,7 +2194,7 @@ client = Wavix( ) client.cdrs.retranscribe( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) ``` @@ -2287,7 +2283,7 @@ client = Wavix( ) client.cdrs.transcriptions( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) ``` @@ -2492,7 +2488,7 @@ client.cdrs.list_all(
-**disposition:** `typing.Optional[CallDisposition]` — Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). +**disposition:** `typing.Optional[CallDisposition]` — Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter).
@@ -2855,7 +2851,7 @@ client.call_recording.get(
-Deletes the call recording identified by `id`. Deletion is permanent and removes the recording file. +Deletes the call recording identified by `id`. Deletion is permanent — the audio file is unrecoverable.
@@ -2917,7 +2913,7 @@ client.call_recording.delete(
## Speech Analytics -
client.speech_analytics.create(...) -> CreateSpeechAnalyticsResponse +
client.speech_analytics.create(...) -> SubmitFileTranscriptionResponse
@@ -3020,7 +3016,7 @@ client.speech_analytics.create(
-
client.speech_analytics.get(...) -> GetSpeechAnalyticsResponse +
client.speech_analytics.get(...) -> FileTranscriptionResponse
@@ -3259,7 +3255,7 @@ client.call_webhooks.list()
-Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. +Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. Creates persistent configuration that forwards call metadata to the URL on every matching call until the webhook is deleted.
@@ -3485,7 +3481,7 @@ client.call_control.list()
-Places an outbound call. Returns the call with its `uuid` for tracking and control. +Places a real, billable outbound PSTN call. Returns the call with its `uuid` for tracking and control.
@@ -3681,7 +3677,7 @@ client.call_control.get(
-Ends the active call identified by `id` by hanging up. +Ends the active call identified by `id` by hanging up. Irreversible — the call cannot be resumed once ended.
@@ -3836,7 +3832,7 @@ client.call_control.update(
-Answers the inbound call identified by `id`. Optionally starts media streaming on answer. +Answers the inbound call identified by `id`. Optionally starts recording, post-call transcription, or live media streaming on answer.
@@ -4054,7 +4050,7 @@ Prompt to play before collecting digits.
## NumberValidator -
client.number_validator.get(...) -> GetNumberValidatorResponse +
client.number_validator.get(...) -> PhoneValidationResponse
@@ -4066,7 +4062,7 @@ Prompt to play before collecting digits.
-Validates a single phone number and returns line type, carrier, portability, and reachability details. +Validates a single phone number and returns line type, carrier, portability, and reachability details. The response's `error_code` is a per-number result code (`000` success; `013` internal error; `021` invalid format; `041` remote timeout; `042` remote query failed; `091` insufficient funds) — distinct from the HTTP status codes below.
@@ -4177,8 +4173,6 @@ client.number_validator.create_bulk( "971504359195" ], type="format", - async_=True, - force=True, ) ``` @@ -4195,7 +4189,7 @@ client.number_validator.create_bulk(
-**phone_numbers:** `typing.List[str]` — List of phone numbers to get detailed information about. +**phone_numbers:** `typing.List[str]` — List of phone numbers to get detailed information about. Maximum 1000 numbers per request.
@@ -4211,7 +4205,7 @@ client.number_validator.create_bulk(
-**async:** `bool` — Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false`, the response will include validation results directly. +**async:** `typing.Optional[bool]` — Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false` (default), the response will include validation results directly.
@@ -4219,7 +4213,7 @@ client.number_validator.create_bulk(
-**force:** `bool` — Indicates whether to force a fresh validation instead of returning a previously cached result. +**force:** `typing.Optional[bool]` — Indicates whether to force a fresh validation instead of returning a previously cached result. Defaults to `false`.
@@ -4252,7 +4246,7 @@ client.number_validator.create_bulk(
-Launches a voice campaign that places an outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. +Launches a voice campaign that places a real outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`.
@@ -4444,7 +4438,7 @@ client.link_shortener.create(
-**link:** `str` — Target URL to shorten. +**link:** `str` — Target URL to shorten. Must be `https://` — the short link is publicly resolvable and redirects any visitor here, so only pass URLs you trust; this endpoint is a common target for open-redirect and phishing abuse.
@@ -4460,7 +4454,7 @@ client.link_shortener.create(
-**fallback_url:** `typing.Optional[str]` — Fallback URL for expired or invalid links. +**fallback_url:** `typing.Optional[str]` — Fallback URL for expired or invalid links. Must be `https://` — same open-redirect/phishing considerations as `link` apply.
@@ -4468,7 +4462,7 @@ client.link_shortener.create(
-**phone:** `typing.Optional[str]` — Phone number for the short link. +**phone:** `typing.Optional[str]` — Phone number the short link is associated with, in E.164 format (without the leading `+`). Used to attribute click metrics returned by short link metrics list.
@@ -4771,6 +4765,22 @@ client.sub_accounts.list()
+**page:** `typing.Optional[int]` — Page number to retrieve. Default `1`. + +
+
+ +
+
+ +**per_page:** `typing.Optional[int]` — Number of records to return per page. Default `25`. + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -5010,7 +5020,7 @@ client.sub_accounts.update(
-**name:** `str` — Sub-account name. +**name:** `typing.Optional[str]` — Sub-account name.
@@ -5047,7 +5057,7 @@ client.sub_accounts.update(
## Billing Transactions -
client.billing.transactions.list(...) -> ListTransactionsResponse +
client.billing.transactions.list(...) -> BillingTransactionListResponse
@@ -5175,7 +5185,7 @@ client.billing.transactions.list(
## Billing Invoices -
client.billing.invoices.list(...) -> ListInvoicesResponse +
client.billing.invoices.list(...) -> InvoiceListResponse
@@ -5331,7 +5341,7 @@ client.billing.invoices.download(
## Buy Countries -
client.buy.countries.list(...) -> ListCountriesResponse +
client.buy.countries.list(...) -> CountryListResponse
@@ -5403,7 +5413,7 @@ client.buy.countries.list()
## Buy Regions -
client.buy.regions.list(...) -> ListRegionsResponse +
client.buy.regions.list(...) -> RegionListResponse
@@ -5485,7 +5495,7 @@ client.buy.regions.list(
## Buy Cities -
client.buy.cities.list(...) -> ListCitiesResponse +
client.buy.cities.list(...) -> CityListResponse
@@ -5568,7 +5578,7 @@ client.buy.cities.list(
## Buy RegionCities -
client.buy.region_cities.list(...) -> ListRegionCitiesResponse +
client.buy.region_cities.list(...) -> CityListResponse
@@ -5659,7 +5669,7 @@ client.buy.region_cities.list(
## Buy Numbers -
client.buy.numbers.list(...) -> ListNumbersResponse +
client.buy.numbers.list(...) -> AvailableNumberListResponse
@@ -5778,7 +5788,7 @@ client.buy.numbers.list(
-Starts streaming the media of the call identified by `call_id` to the configured destination. Returns the `stream_id`. +Starts streaming the audio of the call identified by `call_id` to a WebSocket destination you supply, in the direction (`stream_type`) and channel (`stream_channel`) you configure. The destination can be any URL you specify — Wavix does not restrict it. Returns the `stream_id`.
@@ -5961,7 +5971,7 @@ client.call_control.streams.delete(
-Plays an audio prompt into the active call identified by `id`. +Plays an audio prompt into the active call identified by `id`. The audio is audible to the remote party in real time.
@@ -6141,7 +6151,7 @@ client = Wavix( ) client.cdrs.transcription.get( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) ``` @@ -6416,7 +6426,7 @@ client = Wavix( client.numbers.papers.upload( doc_attachment="example_doc_attachment", did_ids="did_ids", - doc_id=1, + doc_id="id", ) ``` @@ -6449,7 +6459,7 @@ client.numbers.papers.upload(
-**doc_id:** `DocumentTypeId` +**doc_id:** `DocumentType`
@@ -6470,7 +6480,7 @@ client.numbers.papers.upload(
## Profile Config -
client.profile.config.get() -> GetConfigResponse +
client.profile.config.get() -> ProfileConfigResponse
@@ -6609,7 +6619,7 @@ client.sms_and_mms.sender_ids.list()
-Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. +Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. Registering a Sender ID incurs a recurring monthly fee, billed to the account balance.
@@ -6788,7 +6798,7 @@ client.sms_and_mms.sender_ids.get(
-
client.sms_and_mms.sender_ids.delete(...) -> DeleteSenderIdsResponse +
client.sms_and_mms.sender_ids.delete(...) -> SuccessResponse
@@ -6979,7 +6989,7 @@ client.sms_and_mms.opt_outs.list(
-
client.sms_and_mms.opt_outs.create(...) -> CreateOptOutsResponse +
client.sms_and_mms.opt_outs.create(...) -> SuccessResponse
@@ -7056,7 +7066,7 @@ client.sms_and_mms.opt_outs.create(
## SmsAndMms Messages -
client.sms_and_mms.messages.list(...) -> ListMessagesResponse +
client.sms_and_mms.messages.list(...) -> MessageListResponse
@@ -7085,6 +7095,7 @@ Returns a paginated list of SMS and MMS messages for the authenticated account, ```python from wavix import Wavix from wavix.environment import WavixEnvironment +import datetime client = Wavix( token="", @@ -7092,8 +7103,8 @@ client = Wavix( ) client.sms_and_mms.messages.list( - sent_after="2023-04-10", - sent_before="2023-04-13", + sent_after=datetime.date.fromisoformat("2023-04-10"), + sent_before=datetime.date.fromisoformat("2023-04-13"), type="outbound", from_="15072429497", to="16419252149", @@ -7124,7 +7135,7 @@ client.sms_and_mms.messages.list(
-**sent_after:** `typing.Optional[str]` — Returns messages sent on or after this date, in `YYYY-MM-DD` format. +**sent_after:** `typing.Optional[datetime.date]` — Returns messages sent on or after this date, in `YYYY-MM-DD` format.
@@ -7132,7 +7143,7 @@ client.sms_and_mms.messages.list(
-**sent_before:** `typing.Optional[str]` — Returns messages sent on or before this date, in `YYYY-MM-DD` format. +**sent_before:** `typing.Optional[datetime.date]` — Returns messages sent on or before this date, in `YYYY-MM-DD` format.
@@ -7220,8 +7231,7 @@ client.sms_and_mms.messages.list(
-Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. -**Rate limit**: 20 messages per phone number in 24 hours. +Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. The recipient must be opted in to receive messages from the account; sending to an opted-out number fails.
@@ -7249,7 +7259,6 @@ client.sms_and_mms.messages.send( to="+447537151866", message_body=MessageBody( text="Hi there, this is a message from Wavix", - media=None, ), callback_url="https://you-site.com/webhook", validity=3600, @@ -7330,7 +7339,7 @@ client.sms_and_mms.messages.send(
-
client.sms_and_mms.messages.get(...) -> GetMessagesResponse +
client.sms_and_mms.messages.get(...) -> MessageResponse
@@ -7734,7 +7743,7 @@ client.sub_accounts.transactions.list(
## TenDlc Brands -
client.ten_dlc.brands.list(...) -> ListBrandsResponse +
client.ten_dlc.brands.list(...) -> TenDlcBrandListResponse
@@ -7906,7 +7915,7 @@ client.ten_dlc.brands.list(
-
client.ten_dlc.brands.create(...) -> CreateBrandsResponse +
client.ten_dlc.brands.create(...) -> TenDlcBrand
@@ -7918,7 +7927,7 @@ client.ten_dlc.brands.list(
-Registers a 10DLC Brand. TCR automatically verifies the brand identity. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. +Registers a 10DLC Brand. Submits the company's legal identity data (EIN/Tax ID, legal company name, contact and address) to The Campaign Registry (TCR), which verifies the brand identity. Charges a 10DLC brand registration fee on successful submission; fails with an insufficient-funds error when the balance cannot cover it. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns.
@@ -7979,7 +7988,7 @@ client.ten_dlc.brands.create(
-
client.ten_dlc.brands.get(...) -> GetBrandsResponse +
client.ten_dlc.brands.get(...) -> TenDlcBrand
@@ -8052,7 +8061,7 @@ client.ten_dlc.brands.get(
-
client.ten_dlc.brands.update(...) -> UpdateBrandsResponse +
client.ten_dlc.brands.update(...) -> TenDlcBrand
@@ -8289,7 +8298,7 @@ Business segment the Brand operates in. One of:
-
client.ten_dlc.brands.delete(...) -> DeleteBrandsResponse +
client.ten_dlc.brands.delete(...) -> SuccessResponse
@@ -8362,7 +8371,7 @@ client.ten_dlc.brands.delete(
-
client.ten_dlc.brands.qualify_usecase(...) -> QualifyUsecaseBrandsResponse +
client.ten_dlc.brands.qualify_usecase(...) -> TenDlcBrandQualificationResult
@@ -8518,7 +8527,7 @@ client.ten_dlc.brand_appeals.list(
-
client.ten_dlc.brand_appeals.create(...) -> CreateBrandAppealsResponse +
client.ten_dlc.brand_appeals.create(...) -> SuccessResponse
@@ -8533,7 +8542,7 @@ client.ten_dlc.brand_appeals.list( Submits an appeal for 10DLC brand identity verification. Provide any additional documentation to support the appeal. Use `appeal_category` to specify the appeal type: - `VERIFY_TAX_ID` — Use if the brand is UNVERIFIED due to a tax ID mismatch. Applies to private companies, public companies, non-profits, and government entities. - `VERIFY_NON_PROFIT` — Use if a non-profit brand is UNVERIFIED or VERIFIED but missing tax-exempt status. -- `VERIFY_GOVERNMENT` — Use if a government brand is UNVERIFIED or VERIFIED but missing government entity status. +- `VERIFY_GOVERNMENT` — Use if a government brand is UNVERIFIED or VERIFIED but missing government entity status.
@@ -8588,7 +8597,7 @@ client.ten_dlc.brand_appeals.create(
-**appeal_categories:** `typing.List[str]` — List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT` +**appeal_categories:** `typing.List[CreateBrandAppealsRequestAppealCategoriesItem]` — List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`
@@ -8698,7 +8707,7 @@ client.ten_dlc.brand_evidence.list(
-
client.ten_dlc.brand_evidence.upload(...) -> UploadBrandEvidenceResponse +
client.ten_dlc.brand_evidence.upload(...) -> TenDlcBrandEvidence
@@ -8862,7 +8871,7 @@ client.ten_dlc.brand_evidence.get(
-
client.ten_dlc.brand_evidence.delete(...) -> DeleteBrandEvidenceResponse +
client.ten_dlc.brand_evidence.delete(...) -> SuccessResponse
@@ -9030,7 +9039,7 @@ client.ten_dlc.brand_vettings.list(
-Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. +Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. Charges a 10DLC brand vetting fee (Standard or Enhanced); fails with an insufficient-funds error when the balance cannot cover it.
@@ -9283,7 +9292,7 @@ client.ten_dlc.brand_vetting_appeals.list(
-
client.ten_dlc.brand_vetting_appeals.create(...) -> CreateBrandVettingAppealsResponse +
client.ten_dlc.brand_vetting_appeals.create(...) -> SuccessResponse
@@ -9350,7 +9359,7 @@ client.ten_dlc.brand_vetting_appeals.create(
-**appeal_categories:** `typing.List[str]` — List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. +**appeal_categories:** `typing.List[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem]` — List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. `LOW_SCORE` is only valid for vetting appeals — brand identity appeals (`ten_dlc_brand_appeals_create`) do not accept it.
@@ -9403,7 +9412,7 @@ client.ten_dlc.brand_vetting_appeals.create(
## TenDlc Campaigns -
client.ten_dlc.campaigns.list(...) -> ListCampaignsResponse +
client.ten_dlc.campaigns.list(...) -> TenDlcCampaignListResponse
@@ -9540,7 +9549,7 @@ client.ten_dlc.campaigns.list(
-
client.ten_dlc.campaigns.list_by_brand(...) -> ListByBrandCampaignsResponse +
client.ten_dlc.campaigns.list_by_brand(...) -> TenDlcCampaignListResponse
@@ -9686,7 +9695,7 @@ client.ten_dlc.campaigns.list_by_brand(
-
client.ten_dlc.campaigns.create(...) -> CreateCampaignsResponse +
client.ten_dlc.campaigns.create(...) -> TenDlcCampaign
@@ -10011,7 +10020,7 @@ client.ten_dlc.campaigns.create(
-
client.ten_dlc.campaigns.get(...) -> GetCampaignsResponse +
client.ten_dlc.campaigns.get(...) -> TenDlcCampaign
@@ -10093,7 +10102,7 @@ client.ten_dlc.campaigns.get(
-
client.ten_dlc.campaigns.update(...) -> UpdateCampaignsResponse +
client.ten_dlc.campaigns.update(...) -> TenDlcCampaign
@@ -10383,7 +10392,7 @@ client.ten_dlc.campaigns.update(
-
client.ten_dlc.campaigns.delete(...) -> DeleteCampaignsResponse +
client.ten_dlc.campaigns.delete(...) -> SuccessResponse
@@ -10636,7 +10645,7 @@ client.ten_dlc.subscriptions.list()
-
client.ten_dlc.subscriptions.create(...) -> CreateSubscriptionsResponse +
client.ten_dlc.subscriptions.create(...) -> TenDlcEventSubscription
@@ -10710,7 +10719,7 @@ client.ten_dlc.subscriptions.create(
-
client.ten_dlc.subscriptions.delete(...) -> DeleteSubscriptionsResponse +
client.ten_dlc.subscriptions.delete(...) -> SuccessResponse
@@ -10784,7 +10793,7 @@ client.ten_dlc.subscriptions.delete(
## TenDlc CampaignNumbers -
client.ten_dlc.campaign_numbers.link(...) -> LinkCampaignNumbersResponse +
client.ten_dlc.campaign_numbers.link(...) -> SuccessResponse
@@ -10875,7 +10884,7 @@ client.ten_dlc.campaign_numbers.link(
-
client.ten_dlc.campaign_numbers.unlink(...) -> UnlinkCampaignNumbersResponse +
client.ten_dlc.campaign_numbers.unlink(...) -> SuccessResponse
@@ -10966,7 +10975,7 @@ client.ten_dlc.campaign_numbers.unlink(
-
client.ten_dlc.campaign_numbers.list(...) -> ListCampaignNumbersResponse +
client.ten_dlc.campaign_numbers.list(...) -> TenDlcCampaignNumberListResponse
@@ -11049,7 +11058,7 @@ client.ten_dlc.campaign_numbers.list(
## TwoFa Verification -
client.two_fa.verification.create(...) -> CreateVerificationResponse +
client.two_fa.verification.create(...) -> TwoFactorVerificationResponse
@@ -11061,7 +11070,7 @@ client.ten_dlc.campaign_numbers.list(
-Creates a 2FA verification and sends a one-time password (OTP) to the destination phone number over the selected channel. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. +Creates a 2FA verification and sends a real one-time password (OTP) to the destination phone number over the selected channel; this bills the account per OTP sent. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. The verification proceeds through three steps: 1. Create a verification to generate and send an OTP. @@ -11145,7 +11154,7 @@ client.two_fa.verification.create(
-
client.two_fa.verification.resend(...) -> ResendVerificationResponse +
client.two_fa.verification.resend(...) -> TwoFactorVerificationResendResponse
@@ -11227,7 +11236,7 @@ client.two_fa.verification.resend(
-
client.two_fa.verification.check(...) -> CheckVerificationResponse +
client.two_fa.verification.check(...) -> TwoFactorVerificationCheckResponse
@@ -11239,7 +11248,7 @@ client.two_fa.verification.resend(
-Validates the OTP submitted by the end user against the verification identified by `session_id`. +Validates the OTP submitted by the end user against the verification identified by `session_id`. Non-idempotent — each call consumes one of a limited number of attempts tracked server-side; once exhausted, the verification returns `429` until a new verification is created.
@@ -11550,7 +11559,7 @@ client.two_fa.events.list(
## Webrtc Tokens -
client.webrtc.tokens.list() -> WebRtcTokensListResponse +
client.webrtc.tokens.list(...) -> WebRtcTokensListResponse
@@ -11562,7 +11571,7 @@ client.two_fa.events.list(
-Returns a paginated list of active Wavix Embeddable widget tokens for the authenticated account. +Returns a paginated list of Wavix Embeddable widget tokens for the authenticated account.
@@ -11601,6 +11610,22 @@ client.webrtc.tokens.list()
+**page:** `typing.Optional[int]` — Page number to retrieve. Default `1`. + +
+
+ +
+
+ +**per_page:** `typing.Optional[int]` — Number of records to return per page. Default `25`. + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -11686,7 +11711,7 @@ client.webrtc.tokens.create(
-**ttl:** `typing.Optional[int]` — Time to live in seconds. Pass `null` for no expiration. +**ttl:** `typing.Optional[int]` — Time to live in seconds. Default `3600`. Pass `null` for no expiration.
diff --git a/src/wavix/__init__.py b/src/wavix/__init__.py index 35147bb..a9b46c4 100644 --- a/src/wavix/__init__.py +++ b/src/wavix/__init__.py @@ -16,9 +16,9 @@ ApiKeyCallsScopePermissionAllow, ApiKeyScopePermission, ApiKeyScopePermissionAllow, + ApiKeyWithSecret, AvailableNumber, AvailableNumberListResponse, - BadRequestErrorBody, BillingTransactionListResponse, BrandStatusUpdatedWebhook, BrandStatusUpdatedWebhookStatus, @@ -59,13 +59,11 @@ CountryHasNoRegionsErrorResponse, CountryListResponse, DocumentType, - DocumentTypeId, + DocumentTypeInfo, FileTranscriptResponse, FileTranscriptTurn, FileTranscriptionCompletedWebhook, FileTranscriptionResponse, - FileTranscriptionResponseLanguage, - FileTranscriptionResponseStatus, FinancialTransaction, ForbiddenErrorResponse, InboundCallDestination, @@ -83,7 +81,6 @@ MessageListResponse, MessageResponse, MessagesDeliveryReport, - NotFoundErrorBody, NotFoundErrorResponse, Number, NumberDestination, @@ -147,9 +144,9 @@ TenDlcBrand, TenDlcBrandAppeal, TenDlcBrandAppealCreateRequest, + TenDlcBrandAppealCreateRequestAppealCategoriesItem, TenDlcBrandAppealOutcome, TenDlcBrandAppealOutcomeFeedback, - TenDlcBrandAppealOutcomeVettingStatus, TenDlcBrandCreateRequest, TenDlcBrandCreateRequestEntityType, TenDlcBrandCreateRequestStockExchange, @@ -163,7 +160,6 @@ TenDlcBrandListResponse, TenDlcBrandListResponsePagination, TenDlcBrandQualificationResult, - TenDlcBrandStatus, TenDlcBrandVetting, TenDlcBrandVettingAppeal, TenDlcBrandVettingAppealAppealOutcome, @@ -179,6 +175,7 @@ TenDlcCampaignNumberListResponse, TenDlcEventSubscription, TenDlcmnoMetadata, + TooManyRequestsErrorResponse, TransactionStatus, TransactionType, TranscriptTurn, @@ -207,6 +204,38 @@ WebRtcToken, WebRtcTokenResponse, WebRtcTokensListResponse, + WhatsAppMessage, + WhatsAppMessageGetResponse, + WhatsAppMessageListItem, + WhatsAppMessageListItemDirection, + WhatsAppMessageListItemStatus, + WhatsAppMessageListResponse, + WhatsAppMessageSendRequest, + WhatsAppMessageSendRequestTemplate, + WhatsAppMessageSendRequestTemplateButtonsItem, + WhatsAppMessageSendRequestTemplateButtonsItemType, + WhatsAppMessageSendRequestTemplateHeader, + WhatsAppMessageSendRequestTemplateHeaderType, + WhatsAppMessageSendResponse, + WhatsAppMessageStatus, + WhatsAppMessageTemplate, + WhatsAppProblem, + WhatsAppProblemErrorClass, + WhatsAppSender, + WhatsAppSenderMessageTier, + WhatsAppSenderQualityRating, + WhatsAppSenderStatus, + WhatsAppTemplate, + WhatsAppTemplateCategory, + WhatsAppTemplateComponent, + WhatsAppTemplateComponentFormat, + WhatsAppTemplateComponentType, + WhatsAppTemplateCreateRequest, + WhatsAppTemplateCreateRequestCategory, + WhatsAppTemplateListResponse, + WhatsAppTemplateQualityRating, + WhatsAppTemplateResponse, + WhatsAppTemplateStatus, ) from .errors import ( BadRequestError, @@ -242,19 +271,11 @@ from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient from .call_control import CallDtmfCollectRequestPrompt, CallDtmfCollectRequestPromptSay from .call_webhooks import CallWebhooksCreateRequestEventType, DeleteCallWebhooksRequestEventType - from .cart import CheckoutCartResponse, GetCartResponse, RemoveCartResponse - from .cdrs import CdrSearchRequestDisposition, CdrSearchRequestType + from .cdrs import CdrSearchRequestType from .client import AsyncWavix, Wavix from .environment import WavixEnvironment - from .number_validator import GetNumberValidatorResponse - from .numbers import BulkUpdateNumbersResponse, DeleteNumbersResponse + from .numbers import BulkUpdateNumbersResponse from .profile import ProfileUpdateRequestCompanyInfo, ProfileUpdateRequestCompanyInfoIndustry - from .speech_analytics import ( - CreateSpeechAnalyticsResponse, - GetSpeechAnalyticsResponse, - GetSpeechAnalyticsResponseLanguage, - GetSpeechAnalyticsResponseStatus, - ) from .sub_accounts import ( ListSubAccountsRequestStatus, SubAccountsCreateRequestDefaultDestinations, @@ -272,11 +293,11 @@ "ApiKeyCallsScopePermissionAllow": ".types", "ApiKeyScopePermission": ".types", "ApiKeyScopePermissionAllow": ".types", + "ApiKeyWithSecret": ".types", "AsyncWavix": ".client", "AvailableNumber": ".types", "AvailableNumberListResponse": ".types", "BadRequestError": ".errors", - "BadRequestErrorBody": ".types", "BillingTransactionListResponse": ".types", "BrandStatusUpdatedWebhook": ".types", "BrandStatusUpdatedWebhookStatus": ".types", @@ -310,40 +331,29 @@ "Cdr": ".types", "CdrListResponse": ".types", "CdrResponse": ".types", - "CdrSearchRequestDisposition": ".cdrs", "CdrSearchRequestType": ".cdrs", "CdrTranscriptionCompletedWebhook": ".types", "CdrTranscriptionCompletedWebhookStatus": ".types", "CdrTranscriptionResponse": ".types", "CdrTranscriptionSearchResponse": ".types", "CdrWithTranscription": ".types", - "CheckoutCartResponse": ".cart", "City": ".types", "CityListResponse": ".types", "Country": ".types", "CountryHasNoRegionsErrorResponse": ".types", "CountryListResponse": ".types", - "CreateSpeechAnalyticsResponse": ".speech_analytics", "DefaultAioHttpClient": "._default_clients", "DefaultAsyncHttpxClient": "._default_clients", "DeleteCallWebhooksRequestEventType": ".call_webhooks", - "DeleteNumbersResponse": ".numbers", "DocumentType": ".types", - "DocumentTypeId": ".types", + "DocumentTypeInfo": ".types", "FileTranscriptResponse": ".types", "FileTranscriptTurn": ".types", "FileTranscriptionCompletedWebhook": ".types", "FileTranscriptionResponse": ".types", - "FileTranscriptionResponseLanguage": ".types", - "FileTranscriptionResponseStatus": ".types", "FinancialTransaction": ".types", "ForbiddenError": ".errors", "ForbiddenErrorResponse": ".types", - "GetCartResponse": ".cart", - "GetNumberValidatorResponse": ".number_validator", - "GetSpeechAnalyticsResponse": ".speech_analytics", - "GetSpeechAnalyticsResponseLanguage": ".speech_analytics", - "GetSpeechAnalyticsResponseStatus": ".speech_analytics", "InboundCallDestination": ".types", "InboundCallTransport": ".types", "InboundMessage": ".types", @@ -361,7 +371,6 @@ "MessageResponse": ".types", "MessagesDeliveryReport": ".types", "NotFoundError": ".errors", - "NotFoundErrorBody": ".types", "NotFoundErrorResponse": ".types", "Number": ".types", "NumberDestination": ".types", @@ -396,7 +405,6 @@ "RecordingDeletedErrorResponse": ".types", "Region": ".types", "RegionListResponse": ".types", - "RemoveCartResponse": ".cart", "SendMessagesResponse": ".types", "SenderId": ".types", "SenderIdDetails": ".types", @@ -432,9 +440,9 @@ "TenDlcBrand": ".types", "TenDlcBrandAppeal": ".types", "TenDlcBrandAppealCreateRequest": ".types", + "TenDlcBrandAppealCreateRequestAppealCategoriesItem": ".types", "TenDlcBrandAppealOutcome": ".types", "TenDlcBrandAppealOutcomeFeedback": ".types", - "TenDlcBrandAppealOutcomeVettingStatus": ".types", "TenDlcBrandCreateRequest": ".types", "TenDlcBrandCreateRequestEntityType": ".types", "TenDlcBrandCreateRequestStockExchange": ".types", @@ -448,7 +456,6 @@ "TenDlcBrandListResponse": ".types", "TenDlcBrandListResponsePagination": ".types", "TenDlcBrandQualificationResult": ".types", - "TenDlcBrandStatus": ".types", "TenDlcBrandVetting": ".types", "TenDlcBrandVettingAppeal": ".types", "TenDlcBrandVettingAppealAppealOutcome": ".types", @@ -465,6 +472,7 @@ "TenDlcEventSubscription": ".types", "TenDlcmnoMetadata": ".types", "TooManyRequestsError": ".errors", + "TooManyRequestsErrorResponse": ".types", "TransactionStatus": ".types", "TransactionType": ".types", "TranscriptTurn": ".types", @@ -497,6 +505,38 @@ "WebRtcToken": ".types", "WebRtcTokenResponse": ".types", "WebRtcTokensListResponse": ".types", + "WhatsAppMessage": ".types", + "WhatsAppMessageGetResponse": ".types", + "WhatsAppMessageListItem": ".types", + "WhatsAppMessageListItemDirection": ".types", + "WhatsAppMessageListItemStatus": ".types", + "WhatsAppMessageListResponse": ".types", + "WhatsAppMessageSendRequest": ".types", + "WhatsAppMessageSendRequestTemplate": ".types", + "WhatsAppMessageSendRequestTemplateButtonsItem": ".types", + "WhatsAppMessageSendRequestTemplateButtonsItemType": ".types", + "WhatsAppMessageSendRequestTemplateHeader": ".types", + "WhatsAppMessageSendRequestTemplateHeaderType": ".types", + "WhatsAppMessageSendResponse": ".types", + "WhatsAppMessageStatus": ".types", + "WhatsAppMessageTemplate": ".types", + "WhatsAppProblem": ".types", + "WhatsAppProblemErrorClass": ".types", + "WhatsAppSender": ".types", + "WhatsAppSenderMessageTier": ".types", + "WhatsAppSenderQualityRating": ".types", + "WhatsAppSenderStatus": ".types", + "WhatsAppTemplate": ".types", + "WhatsAppTemplateCategory": ".types", + "WhatsAppTemplateComponent": ".types", + "WhatsAppTemplateComponentFormat": ".types", + "WhatsAppTemplateComponentType": ".types", + "WhatsAppTemplateCreateRequest": ".types", + "WhatsAppTemplateCreateRequestCategory": ".types", + "WhatsAppTemplateListResponse": ".types", + "WhatsAppTemplateQualityRating": ".types", + "WhatsAppTemplateResponse": ".types", + "WhatsAppTemplateStatus": ".types", "__version__": ".version", "api_keys": ".api_keys", "billing": ".billing", @@ -552,11 +592,11 @@ def __dir__(): "ApiKeyCallsScopePermissionAllow", "ApiKeyScopePermission", "ApiKeyScopePermissionAllow", + "ApiKeyWithSecret", "AsyncWavix", "AvailableNumber", "AvailableNumberListResponse", "BadRequestError", - "BadRequestErrorBody", "BillingTransactionListResponse", "BrandStatusUpdatedWebhook", "BrandStatusUpdatedWebhookStatus", @@ -590,40 +630,29 @@ def __dir__(): "Cdr", "CdrListResponse", "CdrResponse", - "CdrSearchRequestDisposition", "CdrSearchRequestType", "CdrTranscriptionCompletedWebhook", "CdrTranscriptionCompletedWebhookStatus", "CdrTranscriptionResponse", "CdrTranscriptionSearchResponse", "CdrWithTranscription", - "CheckoutCartResponse", "City", "CityListResponse", "Country", "CountryHasNoRegionsErrorResponse", "CountryListResponse", - "CreateSpeechAnalyticsResponse", "DefaultAioHttpClient", "DefaultAsyncHttpxClient", "DeleteCallWebhooksRequestEventType", - "DeleteNumbersResponse", "DocumentType", - "DocumentTypeId", + "DocumentTypeInfo", "FileTranscriptResponse", "FileTranscriptTurn", "FileTranscriptionCompletedWebhook", "FileTranscriptionResponse", - "FileTranscriptionResponseLanguage", - "FileTranscriptionResponseStatus", "FinancialTransaction", "ForbiddenError", "ForbiddenErrorResponse", - "GetCartResponse", - "GetNumberValidatorResponse", - "GetSpeechAnalyticsResponse", - "GetSpeechAnalyticsResponseLanguage", - "GetSpeechAnalyticsResponseStatus", "InboundCallDestination", "InboundCallTransport", "InboundMessage", @@ -641,7 +670,6 @@ def __dir__(): "MessageResponse", "MessagesDeliveryReport", "NotFoundError", - "NotFoundErrorBody", "NotFoundErrorResponse", "Number", "NumberDestination", @@ -676,7 +704,6 @@ def __dir__(): "RecordingDeletedErrorResponse", "Region", "RegionListResponse", - "RemoveCartResponse", "SendMessagesResponse", "SenderId", "SenderIdDetails", @@ -712,9 +739,9 @@ def __dir__(): "TenDlcBrand", "TenDlcBrandAppeal", "TenDlcBrandAppealCreateRequest", + "TenDlcBrandAppealCreateRequestAppealCategoriesItem", "TenDlcBrandAppealOutcome", "TenDlcBrandAppealOutcomeFeedback", - "TenDlcBrandAppealOutcomeVettingStatus", "TenDlcBrandCreateRequest", "TenDlcBrandCreateRequestEntityType", "TenDlcBrandCreateRequestStockExchange", @@ -728,7 +755,6 @@ def __dir__(): "TenDlcBrandListResponse", "TenDlcBrandListResponsePagination", "TenDlcBrandQualificationResult", - "TenDlcBrandStatus", "TenDlcBrandVetting", "TenDlcBrandVettingAppeal", "TenDlcBrandVettingAppealAppealOutcome", @@ -745,6 +771,7 @@ def __dir__(): "TenDlcEventSubscription", "TenDlcmnoMetadata", "TooManyRequestsError", + "TooManyRequestsErrorResponse", "TransactionStatus", "TransactionType", "TranscriptTurn", @@ -777,6 +804,38 @@ def __dir__(): "WebRtcToken", "WebRtcTokenResponse", "WebRtcTokensListResponse", + "WhatsAppMessage", + "WhatsAppMessageGetResponse", + "WhatsAppMessageListItem", + "WhatsAppMessageListItemDirection", + "WhatsAppMessageListItemStatus", + "WhatsAppMessageListResponse", + "WhatsAppMessageSendRequest", + "WhatsAppMessageSendRequestTemplate", + "WhatsAppMessageSendRequestTemplateButtonsItem", + "WhatsAppMessageSendRequestTemplateButtonsItemType", + "WhatsAppMessageSendRequestTemplateHeader", + "WhatsAppMessageSendRequestTemplateHeaderType", + "WhatsAppMessageSendResponse", + "WhatsAppMessageStatus", + "WhatsAppMessageTemplate", + "WhatsAppProblem", + "WhatsAppProblemErrorClass", + "WhatsAppSender", + "WhatsAppSenderMessageTier", + "WhatsAppSenderQualityRating", + "WhatsAppSenderStatus", + "WhatsAppTemplate", + "WhatsAppTemplateCategory", + "WhatsAppTemplateComponent", + "WhatsAppTemplateComponentFormat", + "WhatsAppTemplateComponentType", + "WhatsAppTemplateCreateRequest", + "WhatsAppTemplateCreateRequestCategory", + "WhatsAppTemplateListResponse", + "WhatsAppTemplateQualityRating", + "WhatsAppTemplateResponse", + "WhatsAppTemplateStatus", "__version__", "api_keys", "billing", diff --git a/src/wavix/api_keys/client.py b/src/wavix/api_keys/client.py index 326d772..bc46e1e 100644 --- a/src/wavix/api_keys/client.py +++ b/src/wavix/api_keys/client.py @@ -7,6 +7,7 @@ from ..types.api_key import ApiKey from ..types.api_key_calls_scope_permission import ApiKeyCallsScopePermission from ..types.api_key_scope_permission import ApiKeyScopePermission +from ..types.api_key_with_secret import ApiKeyWithSecret from ..types.success_response import SuccessResponse from .raw_client import AsyncRawApiKeysClient, RawApiKeysClient @@ -84,7 +85,7 @@ def create( account: typing.Optional[ApiKeyScopePermission] = OMIT, subaccounts: typing.Optional[ApiKeyScopePermission] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> ApiKey: + ) -> ApiKeyWithSecret: """ Creates an API key for the authenticated account. Restrict access by listing permitted IP addresses in `permitted_ips`. @@ -151,8 +152,8 @@ def create( Returns ------- - ApiKey - Returns the created API key. + ApiKeyWithSecret + Returns the created API key, including the one-time `value` secret. Examples -------- @@ -451,7 +452,7 @@ async def create( account: typing.Optional[ApiKeyScopePermission] = OMIT, subaccounts: typing.Optional[ApiKeyScopePermission] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> ApiKey: + ) -> ApiKeyWithSecret: """ Creates an API key for the authenticated account. Restrict access by listing permitted IP addresses in `permitted_ips`. @@ -518,8 +519,8 @@ async def create( Returns ------- - ApiKey - Returns the created API key. + ApiKeyWithSecret + Returns the created API key, including the one-time `value` secret. Examples -------- diff --git a/src/wavix/api_keys/raw_client.py b/src/wavix/api_keys/raw_client.py index c85c418..d750bde 100644 --- a/src/wavix/api_keys/raw_client.py +++ b/src/wavix/api_keys/raw_client.py @@ -19,6 +19,7 @@ from ..types.api_key import ApiKey from ..types.api_key_calls_scope_permission import ApiKeyCallsScopePermission from ..types.api_key_scope_permission import ApiKeyScopePermission +from ..types.api_key_with_secret import ApiKeyWithSecret from ..types.success_response import SuccessResponse from ..types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -121,7 +122,7 @@ def create( account: typing.Optional[ApiKeyScopePermission] = OMIT, subaccounts: typing.Optional[ApiKeyScopePermission] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ApiKey]: + ) -> HttpResponse[ApiKeyWithSecret]: """ Creates an API key for the authenticated account. Restrict access by listing permitted IP addresses in `permitted_ips`. @@ -188,8 +189,8 @@ def create( Returns ------- - HttpResponse[ApiKey] - Returns the created API key. + HttpResponse[ApiKeyWithSecret] + Returns the created API key, including the one-time `value` secret. """ _response = self._client_wrapper.httpx_client.request( "v1/api-keys", @@ -249,9 +250,9 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ApiKey, + ApiKeyWithSecret, parse_obj_as( - type_=ApiKey, # type: ignore + type_=ApiKeyWithSecret, # type: ignore object_=_response.json(), ), ) @@ -343,6 +344,17 @@ def delete( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -703,7 +715,7 @@ async def create( account: typing.Optional[ApiKeyScopePermission] = OMIT, subaccounts: typing.Optional[ApiKeyScopePermission] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ApiKey]: + ) -> AsyncHttpResponse[ApiKeyWithSecret]: """ Creates an API key for the authenticated account. Restrict access by listing permitted IP addresses in `permitted_ips`. @@ -770,8 +782,8 @@ async def create( Returns ------- - AsyncHttpResponse[ApiKey] - Returns the created API key. + AsyncHttpResponse[ApiKeyWithSecret] + Returns the created API key, including the one-time `value` secret. """ _response = await self._client_wrapper.httpx_client.request( "v1/api-keys", @@ -831,9 +843,9 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ApiKey, + ApiKeyWithSecret, parse_obj_as( - type_=ApiKey, # type: ignore + type_=ApiKeyWithSecret, # type: ignore object_=_response.json(), ), ) @@ -925,6 +937,17 @@ async def delete( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), diff --git a/src/wavix/billing/__init__.py b/src/wavix/billing/__init__.py index fd7ced9..27b300a 100644 --- a/src/wavix/billing/__init__.py +++ b/src/wavix/billing/__init__.py @@ -7,14 +7,7 @@ if typing.TYPE_CHECKING: from . import invoices, transactions - from .invoices import ListInvoicesResponse - from .transactions import ListTransactionsResponse -_dynamic_imports: typing.Dict[str, str] = { - "ListInvoicesResponse": ".invoices", - "ListTransactionsResponse": ".transactions", - "invoices": ".invoices", - "transactions": ".transactions", -} +_dynamic_imports: typing.Dict[str, str] = {"invoices": ".invoices", "transactions": ".transactions"} def __getattr__(attr_name: str) -> typing.Any: @@ -38,4 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["ListInvoicesResponse", "ListTransactionsResponse", "invoices", "transactions"] +__all__ = ["invoices", "transactions"] diff --git a/src/wavix/billing/invoices/__init__.py b/src/wavix/billing/invoices/__init__.py index 7150d6b..5cde020 100644 --- a/src/wavix/billing/invoices/__init__.py +++ b/src/wavix/billing/invoices/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import ListInvoicesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListInvoicesResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListInvoicesResponse"] diff --git a/src/wavix/billing/invoices/client.py b/src/wavix/billing/invoices/client.py index 91ea347..ffe0ed4 100644 --- a/src/wavix/billing/invoices/client.py +++ b/src/wavix/billing/invoices/client.py @@ -4,8 +4,8 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.invoice_list_response import InvoiceListResponse from .raw_client import AsyncRawInvoicesClient, RawInvoicesClient -from .types.list_invoices_response import ListInvoicesResponse class InvoicesClient: @@ -29,7 +29,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListInvoicesResponse: + ) -> InvoiceListResponse: """ Returns the auto-generated financial statements for the authenticated account, paginated and ordered by billing period. @@ -46,7 +46,7 @@ def list( Returns ------- - ListInvoicesResponse + InvoiceListResponse Returns a paginated list of financial statements. Examples @@ -117,7 +117,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListInvoicesResponse: + ) -> InvoiceListResponse: """ Returns the auto-generated financial statements for the authenticated account, paginated and ordered by billing period. @@ -134,7 +134,7 @@ async def list( Returns ------- - ListInvoicesResponse + InvoiceListResponse Returns a paginated list of financial statements. Examples diff --git a/src/wavix/billing/invoices/raw_client.py b/src/wavix/billing/invoices/raw_client.py index cf0f3b2..acbc4c4 100644 --- a/src/wavix/billing/invoices/raw_client.py +++ b/src/wavix/billing/invoices/raw_client.py @@ -11,9 +11,12 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError -from .types.list_invoices_response import ListInvoicesResponse +from ...errors.unauthorized_error import UnauthorizedError +from ...types.invoice_list_response import InvoiceListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -27,7 +30,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListInvoicesResponse]: + ) -> HttpResponse[InvoiceListResponse]: """ Returns the auto-generated financial statements for the authenticated account, paginated and ordered by billing period. @@ -44,7 +47,7 @@ def list( Returns ------- - HttpResponse[ListInvoicesResponse] + HttpResponse[InvoiceListResponse] Returns a paginated list of financial statements. """ _response = self._client_wrapper.httpx_client.request( @@ -59,13 +62,35 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListInvoicesResponse, + InvoiceListResponse, parse_obj_as( - type_=ListInvoicesResponse, # type: ignore + type_=InvoiceListResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -120,6 +145,17 @@ def _stream() -> HttpResponse[typing.Iterator[bytes]]: response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) ) _response.read() + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -169,7 +205,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListInvoicesResponse]: + ) -> AsyncHttpResponse[InvoiceListResponse]: """ Returns the auto-generated financial statements for the authenticated account, paginated and ordered by billing period. @@ -186,7 +222,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListInvoicesResponse] + AsyncHttpResponse[InvoiceListResponse] Returns a paginated list of financial statements. """ _response = await self._client_wrapper.httpx_client.request( @@ -201,13 +237,35 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListInvoicesResponse, + InvoiceListResponse, parse_obj_as( - type_=ListInvoicesResponse, # type: ignore + type_=InvoiceListResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -263,6 +321,17 @@ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), ) await _response.aread() + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/billing/invoices/types/__init__.py b/src/wavix/billing/invoices/types/__init__.py deleted file mode 100644 index cc7d01d..0000000 --- a/src/wavix/billing/invoices/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .list_invoices_response import ListInvoicesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListInvoicesResponse": ".list_invoices_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListInvoicesResponse"] diff --git a/src/wavix/billing/invoices/types/list_invoices_response.py b/src/wavix/billing/invoices/types/list_invoices_response.py deleted file mode 100644 index 7ca2755..0000000 --- a/src/wavix/billing/invoices/types/list_invoices_response.py +++ /dev/null @@ -1,31 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.invoice import Invoice -from ....types.pagination import Pagination - - -class ListInvoicesResponse(UniversalBaseModel): - is_empty: bool = pydantic.Field() - """ - Indicates whether the statement list is empty. - """ - - invoices: typing.List[Invoice] = pydantic.Field() - """ - Auto-generated statements for the account. - """ - - pagination: Pagination - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/billing/transactions/__init__.py b/src/wavix/billing/transactions/__init__.py index 9bdc740..5cde020 100644 --- a/src/wavix/billing/transactions/__init__.py +++ b/src/wavix/billing/transactions/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import ListTransactionsResponse -_dynamic_imports: typing.Dict[str, str] = {"ListTransactionsResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListTransactionsResponse"] diff --git a/src/wavix/billing/transactions/client.py b/src/wavix/billing/transactions/client.py index d7f8161..b664e12 100644 --- a/src/wavix/billing/transactions/client.py +++ b/src/wavix/billing/transactions/client.py @@ -5,9 +5,9 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.billing_transaction_list_response import BillingTransactionListResponse from ...types.transaction_type import TransactionType from .raw_client import AsyncRawTransactionsClient, RawTransactionsClient -from .types.list_transactions_response import ListTransactionsResponse class TransactionsClient: @@ -36,7 +36,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListTransactionsResponse: + ) -> BillingTransactionListResponse: """ Returns a paginated list of billing transactions for the authenticated account within the requested date range. @@ -68,7 +68,7 @@ def list( Returns ------- - ListTransactionsResponse + BillingTransactionListResponse Returns a paginated list of billing transactions. Examples @@ -132,7 +132,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListTransactionsResponse: + ) -> BillingTransactionListResponse: """ Returns a paginated list of billing transactions for the authenticated account within the requested date range. @@ -164,7 +164,7 @@ async def list( Returns ------- - ListTransactionsResponse + BillingTransactionListResponse Returns a paginated list of billing transactions. Examples diff --git a/src/wavix/billing/transactions/raw_client.py b/src/wavix/billing/transactions/raw_client.py index a7459c5..4e06cf1 100644 --- a/src/wavix/billing/transactions/raw_client.py +++ b/src/wavix/billing/transactions/raw_client.py @@ -12,10 +12,13 @@ from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError +from ...errors.not_found_error import NotFoundError from ...errors.service_unavailable_error import ServiceUnavailableError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.billing_transaction_list_response import BillingTransactionListResponse from ...types.transaction_type import TransactionType +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from ...types.validation_error_response import ValidationErrorResponse -from .types.list_transactions_response import ListTransactionsResponse from pydantic import ValidationError @@ -34,7 +37,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListTransactionsResponse]: + ) -> HttpResponse[BillingTransactionListResponse]: """ Returns a paginated list of billing transactions for the authenticated account within the requested date range. @@ -66,7 +69,7 @@ def list( Returns ------- - HttpResponse[ListTransactionsResponse] + HttpResponse[BillingTransactionListResponse] Returns a paginated list of billing transactions. """ _response = self._client_wrapper.httpx_client.request( @@ -86,9 +89,9 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListTransactionsResponse, + BillingTransactionListResponse, parse_obj_as( - type_=ListTransactionsResponse, # type: ignore + type_=BillingTransactionListResponse, # type: ignore object_=_response.json(), ), ) @@ -104,6 +107,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -115,6 +129,17 @@ def list( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 503: raise ServiceUnavailableError( headers=dict(_response.headers), @@ -151,7 +176,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListTransactionsResponse]: + ) -> AsyncHttpResponse[BillingTransactionListResponse]: """ Returns a paginated list of billing transactions for the authenticated account within the requested date range. @@ -183,7 +208,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListTransactionsResponse] + AsyncHttpResponse[BillingTransactionListResponse] Returns a paginated list of billing transactions. """ _response = await self._client_wrapper.httpx_client.request( @@ -203,9 +228,9 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListTransactionsResponse, + BillingTransactionListResponse, parse_obj_as( - type_=ListTransactionsResponse, # type: ignore + type_=BillingTransactionListResponse, # type: ignore object_=_response.json(), ), ) @@ -221,6 +246,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -232,6 +268,17 @@ async def list( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 503: raise ServiceUnavailableError( headers=dict(_response.headers), diff --git a/src/wavix/billing/transactions/types/__init__.py b/src/wavix/billing/transactions/types/__init__.py deleted file mode 100644 index 9866956..0000000 --- a/src/wavix/billing/transactions/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .list_transactions_response import ListTransactionsResponse -_dynamic_imports: typing.Dict[str, str] = {"ListTransactionsResponse": ".list_transactions_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListTransactionsResponse"] diff --git a/src/wavix/billing/transactions/types/list_transactions_response.py b/src/wavix/billing/transactions/types/list_transactions_response.py deleted file mode 100644 index 5388010..0000000 --- a/src/wavix/billing/transactions/types/list_transactions_response.py +++ /dev/null @@ -1,31 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.financial_transaction import FinancialTransaction -from ....types.pagination import Pagination - - -class ListTransactionsResponse(UniversalBaseModel): - is_empty: bool = pydantic.Field() - """ - Indicates whether there are no transactions. - """ - - transactions: typing.List[FinancialTransaction] = pydantic.Field() - """ - List of transactions. - """ - - pagination: Pagination - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/buy/__init__.py b/src/wavix/buy/__init__.py index 0e17565..fee5b4a 100644 --- a/src/wavix/buy/__init__.py +++ b/src/wavix/buy/__init__.py @@ -7,17 +7,7 @@ if typing.TYPE_CHECKING: from . import cities, countries, numbers, region_cities, regions - from .cities import ListCitiesResponse - from .countries import ListCountriesResponse - from .numbers import ListNumbersResponse - from .region_cities import ListRegionCitiesResponse - from .regions import ListRegionsResponse _dynamic_imports: typing.Dict[str, str] = { - "ListCitiesResponse": ".cities", - "ListCountriesResponse": ".countries", - "ListNumbersResponse": ".numbers", - "ListRegionCitiesResponse": ".region_cities", - "ListRegionsResponse": ".regions", "cities": ".cities", "countries": ".countries", "numbers": ".numbers", @@ -47,15 +37,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "ListCitiesResponse", - "ListCountriesResponse", - "ListNumbersResponse", - "ListRegionCitiesResponse", - "ListRegionsResponse", - "cities", - "countries", - "numbers", - "region_cities", - "regions", -] +__all__ = ["cities", "countries", "numbers", "region_cities", "regions"] diff --git a/src/wavix/buy/cities/__init__.py b/src/wavix/buy/cities/__init__.py index b193890..5cde020 100644 --- a/src/wavix/buy/cities/__init__.py +++ b/src/wavix/buy/cities/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import ListCitiesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListCitiesResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListCitiesResponse"] diff --git a/src/wavix/buy/cities/client.py b/src/wavix/buy/cities/client.py index 673ac6d..7c0c68b 100644 --- a/src/wavix/buy/cities/client.py +++ b/src/wavix/buy/cities/client.py @@ -4,8 +4,8 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.city_list_response import CityListResponse from .raw_client import AsyncRawCitiesClient, RawCitiesClient -from .types.list_cities_response import ListCitiesResponse class CitiesClient: @@ -29,7 +29,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListCitiesResponse: + ) -> CityListResponse: """ Returns a list of cities for countries where `has_provinces_or_states` is `false`. @@ -47,7 +47,7 @@ def list( Returns ------- - ListCitiesResponse + CityListResponse Returns the list of cities. Examples @@ -88,7 +88,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListCitiesResponse: + ) -> CityListResponse: """ Returns a list of cities for countries where `has_provinces_or_states` is `false`. @@ -106,7 +106,7 @@ async def list( Returns ------- - ListCitiesResponse + CityListResponse Returns the list of cities. Examples diff --git a/src/wavix/buy/cities/raw_client.py b/src/wavix/buy/cities/raw_client.py index 6ce7b98..6b4d8a7 100644 --- a/src/wavix/buy/cities/raw_client.py +++ b/src/wavix/buy/cities/raw_client.py @@ -13,7 +13,9 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError -from .types.list_cities_response import ListCitiesResponse +from ...errors.unauthorized_error import UnauthorizedError +from ...types.city_list_response import CityListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -27,7 +29,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListCitiesResponse]: + ) -> HttpResponse[CityListResponse]: """ Returns a list of cities for countries where `has_provinces_or_states` is `false`. @@ -45,7 +47,7 @@ def list( Returns ------- - HttpResponse[ListCitiesResponse] + HttpResponse[CityListResponse] Returns the list of cities. """ _response = self._client_wrapper.httpx_client.request( @@ -59,9 +61,9 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCitiesResponse, + CityListResponse, parse_obj_as( - type_=ListCitiesResponse, # type: ignore + type_=CityListResponse, # type: ignore object_=_response.json(), ), ) @@ -77,6 +79,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -119,7 +132,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListCitiesResponse]: + ) -> AsyncHttpResponse[CityListResponse]: """ Returns a list of cities for countries where `has_provinces_or_states` is `false`. @@ -137,7 +150,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListCitiesResponse] + AsyncHttpResponse[CityListResponse] Returns the list of cities. """ _response = await self._client_wrapper.httpx_client.request( @@ -151,9 +164,9 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCitiesResponse, + CityListResponse, parse_obj_as( - type_=ListCitiesResponse, # type: ignore + type_=CityListResponse, # type: ignore object_=_response.json(), ), ) @@ -169,6 +182,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/buy/cities/types/__init__.py b/src/wavix/buy/cities/types/__init__.py deleted file mode 100644 index 3b68590..0000000 --- a/src/wavix/buy/cities/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .list_cities_response import ListCitiesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListCitiesResponse": ".list_cities_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListCitiesResponse"] diff --git a/src/wavix/buy/cities/types/list_cities_response.py b/src/wavix/buy/cities/types/list_cities_response.py deleted file mode 100644 index 5283589..0000000 --- a/src/wavix/buy/cities/types/list_cities_response.py +++ /dev/null @@ -1,23 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.city import City - - -class ListCitiesResponse(UniversalBaseModel): - cities: typing.List[City] = pydantic.Field() - """ - Cities available for the requested country or region. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/buy/countries/__init__.py b/src/wavix/buy/countries/__init__.py index 9551063..5cde020 100644 --- a/src/wavix/buy/countries/__init__.py +++ b/src/wavix/buy/countries/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import ListCountriesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListCountriesResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListCountriesResponse"] diff --git a/src/wavix/buy/countries/client.py b/src/wavix/buy/countries/client.py index 4afae52..669674d 100644 --- a/src/wavix/buy/countries/client.py +++ b/src/wavix/buy/countries/client.py @@ -4,8 +4,8 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.country_list_response import CountryListResponse from .raw_client import AsyncRawCountriesClient, RawCountriesClient -from .types.list_countries_response import ListCountriesResponse class CountriesClient: @@ -28,7 +28,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListCountriesResponse: + ) -> CountryListResponse: """ Returns a list of countries where phone numbers are available. @@ -42,7 +42,7 @@ def list( Returns ------- - ListCountriesResponse + CountryListResponse Returns the list of countries with available phone numbers. Examples @@ -78,7 +78,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListCountriesResponse: + ) -> CountryListResponse: """ Returns a list of countries where phone numbers are available. @@ -92,7 +92,7 @@ async def list( Returns ------- - ListCountriesResponse + CountryListResponse Returns the list of countries with available phone numbers. Examples diff --git a/src/wavix/buy/countries/raw_client.py b/src/wavix/buy/countries/raw_client.py index 3f5cb7f..c84d719 100644 --- a/src/wavix/buy/countries/raw_client.py +++ b/src/wavix/buy/countries/raw_client.py @@ -10,7 +10,9 @@ from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.forbidden_error import ForbiddenError -from .types.list_countries_response import ListCountriesResponse +from ...errors.unauthorized_error import UnauthorizedError +from ...types.country_list_response import CountryListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -23,7 +25,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListCountriesResponse]: + ) -> HttpResponse[CountryListResponse]: """ Returns a list of countries where phone numbers are available. @@ -37,7 +39,7 @@ def list( Returns ------- - HttpResponse[ListCountriesResponse] + HttpResponse[CountryListResponse] Returns the list of countries with available phone numbers. """ _response = self._client_wrapper.httpx_client.request( @@ -51,13 +53,24 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCountriesResponse, + CountryListResponse, parse_obj_as( - type_=ListCountriesResponse, # type: ignore + type_=CountryListResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -88,7 +101,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListCountriesResponse]: + ) -> AsyncHttpResponse[CountryListResponse]: """ Returns a list of countries where phone numbers are available. @@ -102,7 +115,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListCountriesResponse] + AsyncHttpResponse[CountryListResponse] Returns the list of countries with available phone numbers. """ _response = await self._client_wrapper.httpx_client.request( @@ -116,13 +129,24 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCountriesResponse, + CountryListResponse, parse_obj_as( - type_=ListCountriesResponse, # type: ignore + type_=CountryListResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/buy/countries/types/__init__.py b/src/wavix/buy/countries/types/__init__.py deleted file mode 100644 index 76df3a4..0000000 --- a/src/wavix/buy/countries/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .list_countries_response import ListCountriesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListCountriesResponse": ".list_countries_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListCountriesResponse"] diff --git a/src/wavix/buy/numbers/__init__.py b/src/wavix/buy/numbers/__init__.py index f898bb4..5cde020 100644 --- a/src/wavix/buy/numbers/__init__.py +++ b/src/wavix/buy/numbers/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import ListNumbersResponse -_dynamic_imports: typing.Dict[str, str] = {"ListNumbersResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListNumbersResponse"] diff --git a/src/wavix/buy/numbers/client.py b/src/wavix/buy/numbers/client.py index 075844d..c97b4c8 100644 --- a/src/wavix/buy/numbers/client.py +++ b/src/wavix/buy/numbers/client.py @@ -4,8 +4,8 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.available_number_list_response import AvailableNumberListResponse from .raw_client import AsyncRawNumbersClient, RawNumbersClient -from .types.list_numbers_response import ListNumbersResponse class NumbersClient: @@ -32,7 +32,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListNumbersResponse: + ) -> AvailableNumberListResponse: """ Returns a paginated list of phone numbers available for purchase in the specified city. @@ -58,7 +58,7 @@ def list( Returns ------- - ListNumbersResponse + AvailableNumberListResponse Returns a paginated list of available phone numbers. Examples @@ -108,7 +108,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListNumbersResponse: + ) -> AvailableNumberListResponse: """ Returns a paginated list of phone numbers available for purchase in the specified city. @@ -134,7 +134,7 @@ async def list( Returns ------- - ListNumbersResponse + AvailableNumberListResponse Returns a paginated list of available phone numbers. Examples diff --git a/src/wavix/buy/numbers/raw_client.py b/src/wavix/buy/numbers/raw_client.py index 360e2d9..ae7ea2f 100644 --- a/src/wavix/buy/numbers/raw_client.py +++ b/src/wavix/buy/numbers/raw_client.py @@ -13,7 +13,9 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError -from .types.list_numbers_response import ListNumbersResponse +from ...errors.unauthorized_error import UnauthorizedError +from ...types.available_number_list_response import AvailableNumberListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -30,7 +32,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListNumbersResponse]: + ) -> HttpResponse[AvailableNumberListResponse]: """ Returns a paginated list of phone numbers available for purchase in the specified city. @@ -56,7 +58,7 @@ def list( Returns ------- - HttpResponse[ListNumbersResponse] + HttpResponse[AvailableNumberListResponse] Returns a paginated list of available phone numbers. """ _response = self._client_wrapper.httpx_client.request( @@ -72,9 +74,9 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListNumbersResponse, + AvailableNumberListResponse, parse_obj_as( - type_=ListNumbersResponse, # type: ignore + type_=AvailableNumberListResponse, # type: ignore object_=_response.json(), ), ) @@ -90,6 +92,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -135,7 +148,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListNumbersResponse]: + ) -> AsyncHttpResponse[AvailableNumberListResponse]: """ Returns a paginated list of phone numbers available for purchase in the specified city. @@ -161,7 +174,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListNumbersResponse] + AsyncHttpResponse[AvailableNumberListResponse] Returns a paginated list of available phone numbers. """ _response = await self._client_wrapper.httpx_client.request( @@ -177,9 +190,9 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListNumbersResponse, + AvailableNumberListResponse, parse_obj_as( - type_=ListNumbersResponse, # type: ignore + type_=AvailableNumberListResponse, # type: ignore object_=_response.json(), ), ) @@ -195,6 +208,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/buy/numbers/types/__init__.py b/src/wavix/buy/numbers/types/__init__.py deleted file mode 100644 index d94134b..0000000 --- a/src/wavix/buy/numbers/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .list_numbers_response import ListNumbersResponse -_dynamic_imports: typing.Dict[str, str] = {"ListNumbersResponse": ".list_numbers_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListNumbersResponse"] diff --git a/src/wavix/buy/region_cities/__init__.py b/src/wavix/buy/region_cities/__init__.py index 264a60f..5cde020 100644 --- a/src/wavix/buy/region_cities/__init__.py +++ b/src/wavix/buy/region_cities/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import ListRegionCitiesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListRegionCitiesResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListRegionCitiesResponse"] diff --git a/src/wavix/buy/region_cities/client.py b/src/wavix/buy/region_cities/client.py index 30c2aff..becd745 100644 --- a/src/wavix/buy/region_cities/client.py +++ b/src/wavix/buy/region_cities/client.py @@ -4,8 +4,8 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.city_list_response import CityListResponse from .raw_client import AsyncRawRegionCitiesClient, RawRegionCitiesClient -from .types.list_region_cities_response import ListRegionCitiesResponse class RegionCitiesClient: @@ -30,7 +30,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListRegionCitiesResponse: + ) -> CityListResponse: """ Returns a list of cities in the specified region for countries where `has_provinces_or_states` is `true`. @@ -50,7 +50,7 @@ def list( Returns ------- - ListRegionCitiesResponse + CityListResponse Returns the list of cities. Examples @@ -93,7 +93,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListRegionCitiesResponse: + ) -> CityListResponse: """ Returns a list of cities in the specified region for countries where `has_provinces_or_states` is `true`. @@ -113,7 +113,7 @@ async def list( Returns ------- - ListRegionCitiesResponse + CityListResponse Returns the list of cities. Examples diff --git a/src/wavix/buy/region_cities/raw_client.py b/src/wavix/buy/region_cities/raw_client.py index f468090..279ffcc 100644 --- a/src/wavix/buy/region_cities/raw_client.py +++ b/src/wavix/buy/region_cities/raw_client.py @@ -13,7 +13,9 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError -from .types.list_region_cities_response import ListRegionCitiesResponse +from ...errors.unauthorized_error import UnauthorizedError +from ...types.city_list_response import CityListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -28,7 +30,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListRegionCitiesResponse]: + ) -> HttpResponse[CityListResponse]: """ Returns a list of cities in the specified region for countries where `has_provinces_or_states` is `true`. @@ -48,7 +50,7 @@ def list( Returns ------- - HttpResponse[ListRegionCitiesResponse] + HttpResponse[CityListResponse] Returns the list of cities. """ _response = self._client_wrapper.httpx_client.request( @@ -62,9 +64,9 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListRegionCitiesResponse, + CityListResponse, parse_obj_as( - type_=ListRegionCitiesResponse, # type: ignore + type_=CityListResponse, # type: ignore object_=_response.json(), ), ) @@ -80,6 +82,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -123,7 +136,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListRegionCitiesResponse]: + ) -> AsyncHttpResponse[CityListResponse]: """ Returns a list of cities in the specified region for countries where `has_provinces_or_states` is `true`. @@ -143,7 +156,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListRegionCitiesResponse] + AsyncHttpResponse[CityListResponse] Returns the list of cities. """ _response = await self._client_wrapper.httpx_client.request( @@ -157,9 +170,9 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListRegionCitiesResponse, + CityListResponse, parse_obj_as( - type_=ListRegionCitiesResponse, # type: ignore + type_=CityListResponse, # type: ignore object_=_response.json(), ), ) @@ -175,6 +188,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/buy/region_cities/types/__init__.py b/src/wavix/buy/region_cities/types/__init__.py deleted file mode 100644 index e4584ed..0000000 --- a/src/wavix/buy/region_cities/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .list_region_cities_response import ListRegionCitiesResponse -_dynamic_imports: typing.Dict[str, str] = {"ListRegionCitiesResponse": ".list_region_cities_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListRegionCitiesResponse"] diff --git a/src/wavix/buy/region_cities/types/list_region_cities_response.py b/src/wavix/buy/region_cities/types/list_region_cities_response.py deleted file mode 100644 index b9584fa..0000000 --- a/src/wavix/buy/region_cities/types/list_region_cities_response.py +++ /dev/null @@ -1,23 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.city import City - - -class ListRegionCitiesResponse(UniversalBaseModel): - cities: typing.List[City] = pydantic.Field() - """ - Cities available for the requested country or region. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/buy/regions/__init__.py b/src/wavix/buy/regions/__init__.py index 1de7747..5cde020 100644 --- a/src/wavix/buy/regions/__init__.py +++ b/src/wavix/buy/regions/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import ListRegionsResponse -_dynamic_imports: typing.Dict[str, str] = {"ListRegionsResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListRegionsResponse"] diff --git a/src/wavix/buy/regions/client.py b/src/wavix/buy/regions/client.py index cd84188..522f50e 100644 --- a/src/wavix/buy/regions/client.py +++ b/src/wavix/buy/regions/client.py @@ -4,8 +4,8 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.region_list_response import RegionListResponse from .raw_client import AsyncRawRegionsClient, RawRegionsClient -from .types.list_regions_response import ListRegionsResponse class RegionsClient: @@ -29,7 +29,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListRegionsResponse: + ) -> RegionListResponse: """ Returns a list of regions (states or provinces) for countries where `has_provinces_or_states` is `true`. @@ -46,7 +46,7 @@ def list( Returns ------- - ListRegionsResponse + RegionListResponse Returns the list of regions. Examples @@ -87,7 +87,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListRegionsResponse: + ) -> RegionListResponse: """ Returns a list of regions (states or provinces) for countries where `has_provinces_or_states` is `true`. @@ -104,7 +104,7 @@ async def list( Returns ------- - ListRegionsResponse + RegionListResponse Returns the list of regions. Examples diff --git a/src/wavix/buy/regions/raw_client.py b/src/wavix/buy/regions/raw_client.py index b8533e2..01c6098 100644 --- a/src/wavix/buy/regions/raw_client.py +++ b/src/wavix/buy/regions/raw_client.py @@ -13,8 +13,10 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError -from .types.list_regions_response import ListRegionsResponse +from ...types.region_list_response import RegionListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -28,7 +30,7 @@ def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListRegionsResponse]: + ) -> HttpResponse[RegionListResponse]: """ Returns a list of regions (states or provinces) for countries where `has_provinces_or_states` is `true`. @@ -45,7 +47,7 @@ def list( Returns ------- - HttpResponse[ListRegionsResponse] + HttpResponse[RegionListResponse] Returns the list of regions. """ _response = self._client_wrapper.httpx_client.request( @@ -59,9 +61,9 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListRegionsResponse, + RegionListResponse, parse_obj_as( - type_=ListRegionsResponse, # type: ignore + type_=RegionListResponse, # type: ignore object_=_response.json(), ), ) @@ -77,6 +79,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -130,7 +143,7 @@ async def list( *, text_enabled_only: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListRegionsResponse]: + ) -> AsyncHttpResponse[RegionListResponse]: """ Returns a list of regions (states or provinces) for countries where `has_provinces_or_states` is `true`. @@ -147,7 +160,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListRegionsResponse] + AsyncHttpResponse[RegionListResponse] Returns the list of regions. """ _response = await self._client_wrapper.httpx_client.request( @@ -161,9 +174,9 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListRegionsResponse, + RegionListResponse, parse_obj_as( - type_=ListRegionsResponse, # type: ignore + type_=RegionListResponse, # type: ignore object_=_response.json(), ), ) @@ -179,6 +192,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/buy/regions/types/__init__.py b/src/wavix/buy/regions/types/__init__.py deleted file mode 100644 index 835a2e8..0000000 --- a/src/wavix/buy/regions/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .list_regions_response import ListRegionsResponse -_dynamic_imports: typing.Dict[str, str] = {"ListRegionsResponse": ".list_regions_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["ListRegionsResponse"] diff --git a/src/wavix/buy/regions/types/list_regions_response.py b/src/wavix/buy/regions/types/list_regions_response.py deleted file mode 100644 index cfc8be8..0000000 --- a/src/wavix/buy/regions/types/list_regions_response.py +++ /dev/null @@ -1,23 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.region import Region - - -class ListRegionsResponse(UniversalBaseModel): - regions: typing.List[Region] = pydantic.Field() - """ - States or provinces available for the requested country. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/call_control/audio/client.py b/src/wavix/call_control/audio/client.py index cef7966..2b9f896 100644 --- a/src/wavix/call_control/audio/client.py +++ b/src/wavix/call_control/audio/client.py @@ -30,7 +30,7 @@ def play( self, id: str, *, audio_file: str, request_options: typing.Optional[RequestOptions] = None ) -> SuccessResponse: """ - Plays an audio prompt into the active call identified by `id`. + Plays an audio prompt into the active call identified by `id`. The audio is audible to the remote party in real time. Parameters ---------- @@ -114,7 +114,7 @@ async def play( self, id: str, *, audio_file: str, request_options: typing.Optional[RequestOptions] = None ) -> SuccessResponse: """ - Plays an audio prompt into the active call identified by `id`. + Plays an audio prompt into the active call identified by `id`. The audio is audible to the remote party in real time. Parameters ---------- diff --git a/src/wavix/call_control/audio/raw_client.py b/src/wavix/call_control/audio/raw_client.py index d0727fc..3190006 100644 --- a/src/wavix/call_control/audio/raw_client.py +++ b/src/wavix/call_control/audio/raw_client.py @@ -11,6 +11,7 @@ from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError +from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError from ...errors.unauthorized_error import UnauthorizedError from ...types.success_response import SuccessResponse @@ -29,7 +30,7 @@ def play( self, id: str, *, audio_file: str, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[SuccessResponse]: """ - Plays an audio prompt into the active call identified by `id`. + Plays an audio prompt into the active call identified by `id`. The audio is audible to the remote party in real time. Parameters ---------- @@ -91,6 +92,17 @@ def play( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -145,6 +157,17 @@ def stop( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -156,6 +179,17 @@ def stop( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -185,7 +219,7 @@ async def play( self, id: str, *, audio_file: str, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[SuccessResponse]: """ - Plays an audio prompt into the active call identified by `id`. + Plays an audio prompt into the active call identified by `id`. The audio is audible to the remote party in real time. Parameters ---------- @@ -247,6 +281,17 @@ async def play( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -301,6 +346,17 @@ async def stop( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -312,6 +368,17 @@ async def stop( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), diff --git a/src/wavix/call_control/client.py b/src/wavix/call_control/client.py index bdf4640..7f3fe01 100644 --- a/src/wavix/call_control/client.py +++ b/src/wavix/call_control/client.py @@ -79,7 +79,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> CallCreateResponse: """ - Places an outbound call. Returns the call with its `uuid` for tracking and control. + Places a real, billable outbound PSTN call. Returns the call with its `uuid` for tracking and control. Parameters ---------- @@ -170,7 +170,7 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ - Ends the active call identified by `id` by hanging up. + Ends the active call identified by `id` by hanging up. Irreversible — the call cannot be resumed once ended. Parameters ---------- @@ -246,7 +246,7 @@ def answer( request_options: typing.Optional[RequestOptions] = None, ) -> SuccessResponse: """ - Answers the inbound call identified by `id`. Optionally starts media streaming on answer. + Answers the inbound call identified by `id`. Optionally starts recording, post-call transcription, or live media streaming on answer. Parameters ---------- @@ -445,7 +445,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> CallCreateResponse: """ - Places an outbound call. Returns the call with its `uuid` for tracking and control. + Places a real, billable outbound PSTN call. Returns the call with its `uuid` for tracking and control. Parameters ---------- @@ -552,7 +552,7 @@ async def main() -> None: async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ - Ends the active call identified by `id` by hanging up. + Ends the active call identified by `id` by hanging up. Irreversible — the call cannot be resumed once ended. Parameters ---------- @@ -646,7 +646,7 @@ async def answer( request_options: typing.Optional[RequestOptions] = None, ) -> SuccessResponse: """ - Answers the inbound call identified by `id`. Optionally starts media streaming on answer. + Answers the inbound call identified by `id`. Optionally starts recording, post-call transcription, or live media streaming on answer. Parameters ---------- diff --git a/src/wavix/call_control/raw_client.py b/src/wavix/call_control/raw_client.py index 1acc4f0..2eb4d09 100644 --- a/src/wavix/call_control/raw_client.py +++ b/src/wavix/call_control/raw_client.py @@ -12,6 +12,7 @@ from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata from ..errors.bad_request_error import BadRequestError +from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError from ..errors.unauthorized_error import UnauthorizedError from ..types.call_create_response import CallCreateResponse @@ -61,6 +62,17 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Ht ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -72,6 +84,28 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Ht ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -94,7 +128,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[CallCreateResponse]: """ - Places an outbound call. Returns the call with its `uuid` for tracking and control. + Places a real, billable outbound PSTN call. Returns the call with its `uuid` for tracking and control. Parameters ---------- @@ -177,6 +211,28 @@ def create( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -218,6 +274,17 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -229,6 +296,17 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -253,7 +331,7 @@ def delete( self, id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[SuccessResponse]: """ - Ends the active call identified by `id` by hanging up. + Ends the active call identified by `id` by hanging up. Irreversible — the call cannot be resumed once ended. Parameters ---------- @@ -283,6 +361,17 @@ def delete( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -294,6 +383,17 @@ def delete( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -380,6 +480,17 @@ def update( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -412,7 +523,7 @@ def answer( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[SuccessResponse]: """ - Answers the inbound call identified by `id`. Optionally starts media streaming on answer. + Answers the inbound call identified by `id`. Optionally starts recording, post-call transcription, or live media streaming on answer. Parameters ---------- @@ -490,6 +601,17 @@ def answer( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -603,6 +725,17 @@ def collect( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -659,6 +792,17 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -670,6 +814,28 @@ async def list( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -692,7 +858,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[CallCreateResponse]: """ - Places an outbound call. Returns the call with its `uuid` for tracking and control. + Places a real, billable outbound PSTN call. Returns the call with its `uuid` for tracking and control. Parameters ---------- @@ -775,6 +941,28 @@ async def create( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -818,6 +1006,17 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -829,6 +1028,17 @@ async def get( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -853,7 +1063,7 @@ async def delete( self, id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[SuccessResponse]: """ - Ends the active call identified by `id` by hanging up. + Ends the active call identified by `id` by hanging up. Irreversible — the call cannot be resumed once ended. Parameters ---------- @@ -883,6 +1093,17 @@ async def delete( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -894,6 +1115,17 @@ async def delete( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -980,6 +1212,17 @@ async def update( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -1012,7 +1255,7 @@ async def answer( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[SuccessResponse]: """ - Answers the inbound call identified by `id`. Optionally starts media streaming on answer. + Answers the inbound call identified by `id`. Optionally starts recording, post-call transcription, or live media streaming on answer. Parameters ---------- @@ -1090,6 +1333,17 @@ async def answer( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -1203,6 +1457,17 @@ async def collect( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), diff --git a/src/wavix/call_control/streams/client.py b/src/wavix/call_control/streams/client.py index a46cfd3..a9d66c7 100644 --- a/src/wavix/call_control/streams/client.py +++ b/src/wavix/call_control/streams/client.py @@ -39,7 +39,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> CallStreamResponse: """ - Starts streaming the media of the call identified by `call_id` to the configured destination. Returns the `stream_id`. + Starts streaming the audio of the call identified by `call_id` to a WebSocket destination you supply, in the direction (`stream_type`) and channel (`stream_channel`) you configure. The destination can be any URL you specify — Wavix does not restrict it. Returns the `stream_id`. Parameters ---------- @@ -149,7 +149,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> CallStreamResponse: """ - Starts streaming the media of the call identified by `call_id` to the configured destination. Returns the `stream_id`. + Starts streaming the audio of the call identified by `call_id` to a WebSocket destination you supply, in the direction (`stream_type`) and channel (`stream_channel`) you configure. The destination can be any URL you specify — Wavix does not restrict it. Returns the `stream_id`. Parameters ---------- diff --git a/src/wavix/call_control/streams/raw_client.py b/src/wavix/call_control/streams/raw_client.py index cca3498..39f38e1 100644 --- a/src/wavix/call_control/streams/raw_client.py +++ b/src/wavix/call_control/streams/raw_client.py @@ -11,7 +11,10 @@ from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError +from ...errors.forbidden_error import ForbiddenError +from ...errors.not_found_error import NotFoundError from ...errors.unauthorized_error import UnauthorizedError +from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.call_stream_channel import CallStreamChannel from ...types.call_stream_response import CallStreamResponse from ...types.call_stream_type import CallStreamType @@ -37,7 +40,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[CallStreamResponse]: """ - Starts streaming the media of the call identified by `call_id` to the configured destination. Returns the `stream_id`. + Starts streaming the audio of the call identified by `call_id` to a WebSocket destination you supply, in the direction (`stream_type`) and channel (`stream_channel`) you configure. The destination can be any URL you specify — Wavix does not restrict it. Returns the `stream_id`. Parameters ---------- @@ -107,6 +110,39 @@ def create( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -153,6 +189,17 @@ def delete( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -164,6 +211,28 @@ def delete( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -188,7 +257,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[CallStreamResponse]: """ - Starts streaming the media of the call identified by `call_id` to the configured destination. Returns the `stream_id`. + Starts streaming the audio of the call identified by `call_id` to a WebSocket destination you supply, in the direction (`stream_type`) and channel (`stream_channel`) you configure. The destination can be any URL you specify — Wavix does not restrict it. Returns the `stream_id`. Parameters ---------- @@ -258,6 +327,39 @@ async def create( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -304,6 +406,17 @@ async def delete( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -315,6 +428,28 @@ async def delete( ), ), ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) diff --git a/src/wavix/call_control/types/call_dtmf_collect_request_prompt.py b/src/wavix/call_control/types/call_dtmf_collect_request_prompt.py index c9131a2..c4ac5f6 100644 --- a/src/wavix/call_control/types/call_dtmf_collect_request_prompt.py +++ b/src/wavix/call_control/types/call_dtmf_collect_request_prompt.py @@ -20,7 +20,7 @@ class CallDtmfCollectRequestPrompt(UniversalBaseModel): say: typing.Optional[CallDtmfCollectRequestPromptSay] = pydantic.Field(default=None) """ - Text to speak and voice to use. + Text to speak and voice to use. Pick `voice` from the language family matching `language` (for example, a German voice such as `Hans` for `ge`, a Spanish voice such as `Conchita` for `sp`) — Wavix does not validate the pairing itself. """ if IS_PYDANTIC_V2: diff --git a/src/wavix/call_control/types/call_dtmf_collect_request_prompt_say.py b/src/wavix/call_control/types/call_dtmf_collect_request_prompt_say.py index ed353d6..521975a 100644 --- a/src/wavix/call_control/types/call_dtmf_collect_request_prompt_say.py +++ b/src/wavix/call_control/types/call_dtmf_collect_request_prompt_say.py @@ -10,7 +10,7 @@ class CallDtmfCollectRequestPromptSay(UniversalBaseModel): """ - Text to speak and voice to use. + Text to speak and voice to use. Pick `voice` from the language family matching `language` (for example, a German voice such as `Hans` for `ge`, a Spanish voice such as `Conchita` for `sp`) — Wavix does not validate the pairing itself. """ text: str = pydantic.Field() diff --git a/src/wavix/call_recording/client.py b/src/wavix/call_recording/client.py index 0099737..d47273a 100644 --- a/src/wavix/call_recording/client.py +++ b/src/wavix/call_recording/client.py @@ -175,7 +175,7 @@ def get(self, id: int, *, request_options: typing.Optional[RequestOptions] = Non def delete(self, id: int, *, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ - Deletes the call recording identified by `id`. Deletion is permanent and removes the recording file. + Deletes the call recording identified by `id`. Deletion is permanent — the audio file is unrecoverable. Parameters ---------- @@ -392,7 +392,7 @@ async def main() -> None: async def delete(self, id: int, *, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ - Deletes the call recording identified by `id`. Deletion is permanent and removes the recording file. + Deletes the call recording identified by `id`. Deletion is permanent — the audio file is unrecoverable. Parameters ---------- diff --git a/src/wavix/call_recording/raw_client.py b/src/wavix/call_recording/raw_client.py index 3b4c591..366e9be 100644 --- a/src/wavix/call_recording/raw_client.py +++ b/src/wavix/call_recording/raw_client.py @@ -101,6 +101,17 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -289,7 +300,7 @@ def delete( self, id: int, *, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[SuccessResponse]: """ - Deletes the call recording identified by `id`. Deletion is permanent and removes the recording file. + Deletes the call recording identified by `id`. Deletion is permanent — the audio file is unrecoverable. Parameters ---------- @@ -452,6 +463,17 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -642,7 +664,7 @@ async def delete( self, id: int, *, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[SuccessResponse]: """ - Deletes the call recording identified by `id`. Deletion is permanent and removes the recording file. + Deletes the call recording identified by `id`. Deletion is permanent — the audio file is unrecoverable. Parameters ---------- diff --git a/src/wavix/call_webhooks/client.py b/src/wavix/call_webhooks/client.py index 7f04bef..1a09f23 100644 --- a/src/wavix/call_webhooks/client.py +++ b/src/wavix/call_webhooks/client.py @@ -64,7 +64,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> CallWebhook: """ - Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. + Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. Creates persistent configuration that forwards call metadata to the URL on every matching call until the webhook is deleted. Parameters ---------- @@ -193,7 +193,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> CallWebhook: """ - Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. + Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. Creates persistent configuration that forwards call metadata to the URL on every matching call until the webhook is deleted. Parameters ---------- diff --git a/src/wavix/call_webhooks/raw_client.py b/src/wavix/call_webhooks/raw_client.py index 6a211a9..09a9471 100644 --- a/src/wavix/call_webhooks/raw_client.py +++ b/src/wavix/call_webhooks/raw_client.py @@ -58,6 +58,17 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Ht ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -97,7 +108,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[CallWebhook]: """ - Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. + Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. Creates persistent configuration that forwards call metadata to the URL on every matching call until the webhook is deleted. Parameters ---------- @@ -176,6 +187,17 @@ def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -311,6 +333,17 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -350,7 +383,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[CallWebhook]: """ - Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. + Registers a callback URL for the `on-call` or `post-call` event. Wavix sends a POST callback to the URL when the event occurs. Creates persistent configuration that forwards call metadata to the URL on every matching call until the webhook is deleted. Parameters ---------- @@ -429,6 +462,17 @@ async def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) diff --git a/src/wavix/cart/__init__.py b/src/wavix/cart/__init__.py index eaebc73..5cde020 100644 --- a/src/wavix/cart/__init__.py +++ b/src/wavix/cart/__init__.py @@ -2,37 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import CheckoutCartResponse, GetCartResponse, RemoveCartResponse -_dynamic_imports: typing.Dict[str, str] = { - "CheckoutCartResponse": ".types", - "GetCartResponse": ".types", - "RemoveCartResponse": ".types", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["CheckoutCartResponse", "GetCartResponse", "RemoveCartResponse"] diff --git a/src/wavix/cart/client.py b/src/wavix/cart/client.py index d35cdef..e633b5b 100644 --- a/src/wavix/cart/client.py +++ b/src/wavix/cart/client.py @@ -4,10 +4,10 @@ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.request_options import RequestOptions +from ..types.available_number import AvailableNumber +from ..types.cart_response import CartResponse +from ..types.success_response import SuccessResponse from .raw_client import AsyncRawCartClient, RawCartClient -from .types.checkout_cart_response import CheckoutCartResponse -from .types.get_cart_response import GetCartResponse -from .types.remove_cart_response import RemoveCartResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -28,7 +28,7 @@ def with_raw_response(self) -> RawCartClient: """ return self._raw_client - def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> GetCartResponse: + def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> CartResponse: """ Returns the current purchase cart, including the phone numbers it contains and the documents each requires. @@ -39,7 +39,7 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Get Returns ------- - GetCartResponse + CartResponse Returns the cart. Examples @@ -56,7 +56,7 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Get def add( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> typing.List[typing.Any]: + ) -> typing.List[AvailableNumber]: """ Adds the listed phone numbers to the purchase cart. @@ -70,7 +70,7 @@ def add( Returns ------- - typing.List[typing.Any] + typing.List[AvailableNumber] Returns the phone numbers now in the cart. Examples @@ -89,7 +89,7 @@ def add( def remove( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> RemoveCartResponse: + ) -> SuccessResponse: """ Removes the listed phone numbers from the purchase cart. @@ -103,7 +103,7 @@ def remove( Returns ------- - RemoveCartResponse + SuccessResponse Returns a success confirmation. The numbers are removed from the cart. Examples @@ -122,9 +122,9 @@ def remove( def checkout( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> CheckoutCartResponse: + ) -> SuccessResponse: """ - Purchases the listed phone numbers from the cart. Activation and monthly fees are deducted from the account balance. + Purchases the listed phone numbers from the cart. Activation and monthly fees are debited from the account balance immediately, and the purchase cannot be reversed through this API. Parameters ---------- @@ -136,7 +136,7 @@ def checkout( Returns ------- - CheckoutCartResponse + SuccessResponse Returns a success confirmation. The phone numbers are purchased. Examples @@ -169,7 +169,7 @@ def with_raw_response(self) -> AsyncRawCartClient: """ return self._raw_client - async def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> GetCartResponse: + async def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> CartResponse: """ Returns the current purchase cart, including the phone numbers it contains and the documents each requires. @@ -180,7 +180,7 @@ async def get(self, *, request_options: typing.Optional[RequestOptions] = None) Returns ------- - GetCartResponse + CartResponse Returns the cart. Examples @@ -205,7 +205,7 @@ async def main() -> None: async def add( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> typing.List[typing.Any]: + ) -> typing.List[AvailableNumber]: """ Adds the listed phone numbers to the purchase cart. @@ -219,7 +219,7 @@ async def add( Returns ------- - typing.List[typing.Any] + typing.List[AvailableNumber] Returns the phone numbers now in the cart. Examples @@ -246,7 +246,7 @@ async def main() -> None: async def remove( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> RemoveCartResponse: + ) -> SuccessResponse: """ Removes the listed phone numbers from the purchase cart. @@ -260,7 +260,7 @@ async def remove( Returns ------- - RemoveCartResponse + SuccessResponse Returns a success confirmation. The numbers are removed from the cart. Examples @@ -287,9 +287,9 @@ async def main() -> None: async def checkout( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> CheckoutCartResponse: + ) -> SuccessResponse: """ - Purchases the listed phone numbers from the cart. Activation and monthly fees are deducted from the account balance. + Purchases the listed phone numbers from the cart. Activation and monthly fees are debited from the account balance immediately, and the purchase cannot be reversed through this API. Parameters ---------- @@ -301,7 +301,7 @@ async def checkout( Returns ------- - CheckoutCartResponse + SuccessResponse Returns a success confirmation. The phone numbers are purchased. Examples diff --git a/src/wavix/cart/raw_client.py b/src/wavix/cart/raw_client.py index f844a7c..79ff566 100644 --- a/src/wavix/cart/raw_client.py +++ b/src/wavix/cart/raw_client.py @@ -12,9 +12,12 @@ from ..errors.bad_request_error import BadRequestError from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError -from .types.checkout_cart_response import CheckoutCartResponse -from .types.get_cart_response import GetCartResponse -from .types.remove_cart_response import RemoveCartResponse +from ..errors.unauthorized_error import UnauthorizedError +from ..errors.unprocessable_entity_error import UnprocessableEntityError +from ..types.available_number import AvailableNumber +from ..types.cart_response import CartResponse +from ..types.success_response import SuccessResponse +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -25,7 +28,7 @@ class RawCartClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper - def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[GetCartResponse]: + def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[CartResponse]: """ Returns the current purchase cart, including the phone numbers it contains and the documents each requires. @@ -36,7 +39,7 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Htt Returns ------- - HttpResponse[GetCartResponse] + HttpResponse[CartResponse] Returns the cart. """ _response = self._client_wrapper.httpx_client.request( @@ -47,20 +50,20 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Htt try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetCartResponse, + CartResponse, parse_obj_as( - type_=GetCartResponse, # type: ignore + type_=CartResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) - if _response.status_code == 400: - raise BadRequestError( + if _response.status_code == 401: + raise UnauthorizedError( headers=dict(_response.headers), body=typing.cast( - typing.Any, + UnauthorizedErrorResponse, parse_obj_as( - type_=typing.Any, # type: ignore + type_=UnauthorizedErrorResponse, # type: ignore object_=_response.json(), ), ), @@ -87,7 +90,7 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Htt def add( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[typing.List[typing.Any]]: + ) -> HttpResponse[typing.List[AvailableNumber]]: """ Adds the listed phone numbers to the purchase cart. @@ -101,7 +104,7 @@ def add( Returns ------- - HttpResponse[typing.List[typing.Any]] + HttpResponse[typing.List[AvailableNumber]] Returns the phone numbers now in the cart. """ _response = self._client_wrapper.httpx_client.request( @@ -119,9 +122,9 @@ def add( try: if 200 <= _response.status_code < 300: _data = typing.cast( - typing.List[typing.Any], + typing.List[AvailableNumber], parse_obj_as( - type_=typing.List[typing.Any], # type: ignore + type_=typing.List[AvailableNumber], # type: ignore object_=_response.json(), ), ) @@ -137,6 +140,17 @@ def add( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -170,7 +184,7 @@ def add( def remove( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[RemoveCartResponse]: + ) -> HttpResponse[SuccessResponse]: """ Removes the listed phone numbers from the purchase cart. @@ -184,7 +198,7 @@ def remove( Returns ------- - HttpResponse[RemoveCartResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The numbers are removed from the cart. """ _response = self._client_wrapper.httpx_client.request( @@ -202,9 +216,9 @@ def remove( try: if 200 <= _response.status_code < 300: _data = typing.cast( - RemoveCartResponse, + SuccessResponse, parse_obj_as( - type_=RemoveCartResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -220,6 +234,17 @@ def remove( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -253,9 +278,9 @@ def remove( def checkout( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[CheckoutCartResponse]: + ) -> HttpResponse[SuccessResponse]: """ - Purchases the listed phone numbers from the cart. Activation and monthly fees are deducted from the account balance. + Purchases the listed phone numbers from the cart. Activation and monthly fees are debited from the account balance immediately, and the purchase cannot be reversed through this API. Parameters ---------- @@ -267,7 +292,7 @@ def checkout( Returns ------- - HttpResponse[CheckoutCartResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The phone numbers are purchased. """ _response = self._client_wrapper.httpx_client.request( @@ -285,13 +310,35 @@ def checkout( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CheckoutCartResponse, + SuccessResponse, parse_obj_as( - type_=CheckoutCartResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -314,6 +361,17 @@ def checkout( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -328,9 +386,7 @@ class AsyncRawCartClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper - async def get( - self, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[GetCartResponse]: + async def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> AsyncHttpResponse[CartResponse]: """ Returns the current purchase cart, including the phone numbers it contains and the documents each requires. @@ -341,7 +397,7 @@ async def get( Returns ------- - AsyncHttpResponse[GetCartResponse] + AsyncHttpResponse[CartResponse] Returns the cart. """ _response = await self._client_wrapper.httpx_client.request( @@ -352,20 +408,20 @@ async def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetCartResponse, + CartResponse, parse_obj_as( - type_=GetCartResponse, # type: ignore + type_=CartResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) - if _response.status_code == 400: - raise BadRequestError( + if _response.status_code == 401: + raise UnauthorizedError( headers=dict(_response.headers), body=typing.cast( - typing.Any, + UnauthorizedErrorResponse, parse_obj_as( - type_=typing.Any, # type: ignore + type_=UnauthorizedErrorResponse, # type: ignore object_=_response.json(), ), ), @@ -392,7 +448,7 @@ async def get( async def add( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[typing.List[typing.Any]]: + ) -> AsyncHttpResponse[typing.List[AvailableNumber]]: """ Adds the listed phone numbers to the purchase cart. @@ -406,7 +462,7 @@ async def add( Returns ------- - AsyncHttpResponse[typing.List[typing.Any]] + AsyncHttpResponse[typing.List[AvailableNumber]] Returns the phone numbers now in the cart. """ _response = await self._client_wrapper.httpx_client.request( @@ -424,9 +480,9 @@ async def add( try: if 200 <= _response.status_code < 300: _data = typing.cast( - typing.List[typing.Any], + typing.List[AvailableNumber], parse_obj_as( - type_=typing.List[typing.Any], # type: ignore + type_=typing.List[AvailableNumber], # type: ignore object_=_response.json(), ), ) @@ -442,6 +498,17 @@ async def add( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -475,7 +542,7 @@ async def add( async def remove( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[RemoveCartResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Removes the listed phone numbers from the purchase cart. @@ -489,7 +556,7 @@ async def remove( Returns ------- - AsyncHttpResponse[RemoveCartResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The numbers are removed from the cart. """ _response = await self._client_wrapper.httpx_client.request( @@ -507,9 +574,9 @@ async def remove( try: if 200 <= _response.status_code < 300: _data = typing.cast( - RemoveCartResponse, + SuccessResponse, parse_obj_as( - type_=RemoveCartResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -525,6 +592,17 @@ async def remove( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -558,9 +636,9 @@ async def remove( async def checkout( self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[CheckoutCartResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ - Purchases the listed phone numbers from the cart. Activation and monthly fees are deducted from the account balance. + Purchases the listed phone numbers from the cart. Activation and monthly fees are debited from the account balance immediately, and the purchase cannot be reversed through this API. Parameters ---------- @@ -572,7 +650,7 @@ async def checkout( Returns ------- - AsyncHttpResponse[CheckoutCartResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The phone numbers are purchased. """ _response = await self._client_wrapper.httpx_client.request( @@ -590,13 +668,35 @@ async def checkout( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CheckoutCartResponse, + SuccessResponse, parse_obj_as( - type_=CheckoutCartResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -619,6 +719,17 @@ async def checkout( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) diff --git a/src/wavix/cart/types/__init__.py b/src/wavix/cart/types/__init__.py deleted file mode 100644 index f9a9d94..0000000 --- a/src/wavix/cart/types/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .checkout_cart_response import CheckoutCartResponse - from .get_cart_response import GetCartResponse - from .remove_cart_response import RemoveCartResponse -_dynamic_imports: typing.Dict[str, str] = { - "CheckoutCartResponse": ".checkout_cart_response", - "GetCartResponse": ".get_cart_response", - "RemoveCartResponse": ".remove_cart_response", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["CheckoutCartResponse", "GetCartResponse", "RemoveCartResponse"] diff --git a/src/wavix/cart/types/get_cart_response.py b/src/wavix/cart/types/get_cart_response.py deleted file mode 100644 index 619c62b..0000000 --- a/src/wavix/cart/types/get_cart_response.py +++ /dev/null @@ -1,29 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ...types.available_number import AvailableNumber -from ...types.document_type import DocumentType - - -class GetCartResponse(UniversalBaseModel): - dids: typing.List[AvailableNumber] = pydantic.Field() - """ - List of phone numbers in the cart. - """ - - doc_types: typing.List[DocumentType] = pydantic.Field() - """ - Document types required to activate phone numbers. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/cdrs/__init__.py b/src/wavix/cdrs/__init__.py index adfd295..09cda14 100644 --- a/src/wavix/cdrs/__init__.py +++ b/src/wavix/cdrs/__init__.py @@ -6,13 +6,9 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import CdrSearchRequestDisposition, CdrSearchRequestType + from .types import CdrSearchRequestType from . import transcription -_dynamic_imports: typing.Dict[str, str] = { - "CdrSearchRequestDisposition": ".types", - "CdrSearchRequestType": ".types", - "transcription": ".transcription", -} +_dynamic_imports: typing.Dict[str, str] = {"CdrSearchRequestType": ".types", "transcription": ".transcription"} def __getattr__(attr_name: str) -> typing.Any: @@ -36,4 +32,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["CdrSearchRequestDisposition", "CdrSearchRequestType", "transcription"] +__all__ = ["CdrSearchRequestType", "transcription"] diff --git a/src/wavix/cdrs/client.py b/src/wavix/cdrs/client.py index 77175d0..ba2a1df 100644 --- a/src/wavix/cdrs/client.py +++ b/src/wavix/cdrs/client.py @@ -16,7 +16,6 @@ from ..types.transcription_filter import TranscriptionFilter from ..types.transcription_language import TranscriptionLanguage from .raw_client import AsyncRawCdrsClient, RawCdrsClient -from .types.cdr_search_request_disposition import CdrSearchRequestDisposition from .types.cdr_search_request_type import CdrSearchRequestType if typing.TYPE_CHECKING: @@ -72,7 +71,7 @@ def list( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. @@ -146,15 +145,15 @@ def search( type: CdrSearchRequestType, from_: dt.date, to: dt.date, - page: int, - per_page: int, from_search: typing.Optional[str] = OMIT, to_search: typing.Optional[str] = OMIT, sip_trunk: typing.Optional[str] = OMIT, min_duration: typing.Optional[int] = OMIT, transcription: typing.Optional[TranscriptionFilter] = OMIT, uuid_: typing.Optional[str] = OMIT, - disposition: typing.Optional[CdrSearchRequestDisposition] = OMIT, + disposition: typing.Optional[CallDisposition] = OMIT, + page: typing.Optional[int] = OMIT, + per_page: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CdrTranscriptionSearchResponse: """ @@ -171,12 +170,6 @@ def search( to : dt.date End date for call search in `YYYY-MM-DD` format. - page : int - Page number to retrieve. - - per_page : int - Number of records per page. - from_search : typing.Optional[str] Originating phone number to filter results. Accepts full or partial number. @@ -194,12 +187,18 @@ def search( uuid_ : typing.Optional[str] Call ID. - disposition : typing.Optional[CdrSearchRequestDisposition] + disposition : typing.Optional[CallDisposition] Call disposition to filter results. If omitted, returns only answered - calls. Allowed values: `answered`, `busy`, `rejected`, + calls. Allowed values: `answered`, `noanswer`, `busy`, `failed`, `all`. Use `all` to return calls regardless of their disposition. + page : typing.Optional[int] + Page number to retrieve. + + per_page : typing.Optional[int] + Number of records per page. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -225,16 +224,12 @@ def search( to=datetime.date.fromisoformat( "2023-08-31", ), - page=1, - per_page=50, ) """ _response = self._raw_client.search( type=type, from_=from_, to=to, - page=page, - per_page=per_page, from_search=from_search, to_search=to_search, sip_trunk=sip_trunk, @@ -242,6 +237,8 @@ def search( transcription=transcription, uuid_=uuid_, disposition=disposition, + page=page, + per_page=per_page, request_options=request_options, ) return _response.data @@ -255,7 +252,7 @@ def retranscribe( request_options: typing.Optional[RequestOptions] = None, ) -> SuccessResponse: """ - Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. + Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. Billed per minute at the account's call-transcription rate; fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- @@ -283,7 +280,7 @@ def retranscribe( token="YOUR_TOKEN", ) client.cdrs.retranscribe( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) """ _response = self._raw_client.retranscribe( @@ -318,7 +315,7 @@ def transcriptions( token="YOUR_TOKEN", ) client.cdrs.transcriptions( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) """ _response = self._raw_client.transcriptions(call_id, request_options=request_options) @@ -397,7 +394,7 @@ def list_all( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. @@ -521,7 +518,7 @@ async def list( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. @@ -602,15 +599,15 @@ async def search( type: CdrSearchRequestType, from_: dt.date, to: dt.date, - page: int, - per_page: int, from_search: typing.Optional[str] = OMIT, to_search: typing.Optional[str] = OMIT, sip_trunk: typing.Optional[str] = OMIT, min_duration: typing.Optional[int] = OMIT, transcription: typing.Optional[TranscriptionFilter] = OMIT, uuid_: typing.Optional[str] = OMIT, - disposition: typing.Optional[CdrSearchRequestDisposition] = OMIT, + disposition: typing.Optional[CallDisposition] = OMIT, + page: typing.Optional[int] = OMIT, + per_page: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CdrTranscriptionSearchResponse: """ @@ -627,12 +624,6 @@ async def search( to : dt.date End date for call search in `YYYY-MM-DD` format. - page : int - Page number to retrieve. - - per_page : int - Number of records per page. - from_search : typing.Optional[str] Originating phone number to filter results. Accepts full or partial number. @@ -650,12 +641,18 @@ async def search( uuid_ : typing.Optional[str] Call ID. - disposition : typing.Optional[CdrSearchRequestDisposition] + disposition : typing.Optional[CallDisposition] Call disposition to filter results. If omitted, returns only answered - calls. Allowed values: `answered`, `busy`, `rejected`, + calls. Allowed values: `answered`, `noanswer`, `busy`, `failed`, `all`. Use `all` to return calls regardless of their disposition. + page : typing.Optional[int] + Page number to retrieve. + + per_page : typing.Optional[int] + Number of records per page. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -685,8 +682,6 @@ async def main() -> None: to=datetime.date.fromisoformat( "2023-08-31", ), - page=1, - per_page=50, ) @@ -696,8 +691,6 @@ async def main() -> None: type=type, from_=from_, to=to, - page=page, - per_page=per_page, from_search=from_search, to_search=to_search, sip_trunk=sip_trunk, @@ -705,6 +698,8 @@ async def main() -> None: transcription=transcription, uuid_=uuid_, disposition=disposition, + page=page, + per_page=per_page, request_options=request_options, ) return _response.data @@ -718,7 +713,7 @@ async def retranscribe( request_options: typing.Optional[RequestOptions] = None, ) -> SuccessResponse: """ - Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. + Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. Billed per minute at the account's call-transcription rate; fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- @@ -751,7 +746,7 @@ async def retranscribe( async def main() -> None: await client.cdrs.retranscribe( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) @@ -794,7 +789,7 @@ async def transcriptions( async def main() -> None: await client.cdrs.transcriptions( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) @@ -884,7 +879,7 @@ async def list_all( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. diff --git a/src/wavix/cdrs/raw_client.py b/src/wavix/cdrs/raw_client.py index bbbec06..1d6d4d2 100644 --- a/src/wavix/cdrs/raw_client.py +++ b/src/wavix/cdrs/raw_client.py @@ -15,6 +15,7 @@ from ..errors.bad_request_error import BadRequestError from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError from ..errors.unprocessable_entity_error import UnprocessableEntityError from ..types.call_disposition import CallDisposition from ..types.cdr_list_response import CdrListResponse @@ -24,7 +25,7 @@ from ..types.success_response import SuccessResponse from ..types.transcription_filter import TranscriptionFilter from ..types.transcription_language import TranscriptionLanguage -from .types.cdr_search_request_disposition import CdrSearchRequestDisposition +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from .types.cdr_search_request_type import CdrSearchRequestType from pydantic import ValidationError @@ -66,7 +67,7 @@ def list( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. @@ -132,6 +133,39 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -147,15 +181,15 @@ def search( type: CdrSearchRequestType, from_: dt.date, to: dt.date, - page: int, - per_page: int, from_search: typing.Optional[str] = OMIT, to_search: typing.Optional[str] = OMIT, sip_trunk: typing.Optional[str] = OMIT, min_duration: typing.Optional[int] = OMIT, transcription: typing.Optional[TranscriptionFilter] = OMIT, uuid_: typing.Optional[str] = OMIT, - disposition: typing.Optional[CdrSearchRequestDisposition] = OMIT, + disposition: typing.Optional[CallDisposition] = OMIT, + page: typing.Optional[int] = OMIT, + per_page: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[CdrTranscriptionSearchResponse]: """ @@ -172,12 +206,6 @@ def search( to : dt.date End date for call search in `YYYY-MM-DD` format. - page : int - Page number to retrieve. - - per_page : int - Number of records per page. - from_search : typing.Optional[str] Originating phone number to filter results. Accepts full or partial number. @@ -195,12 +223,18 @@ def search( uuid_ : typing.Optional[str] Call ID. - disposition : typing.Optional[CdrSearchRequestDisposition] + disposition : typing.Optional[CallDisposition] Call disposition to filter results. If omitted, returns only answered - calls. Allowed values: `answered`, `busy`, `rejected`, + calls. Allowed values: `answered`, `noanswer`, `busy`, `failed`, `all`. Use `all` to return calls regardless of their disposition. + page : typing.Optional[int] + Page number to retrieve. + + per_page : typing.Optional[int] + Number of records per page. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -244,6 +278,17 @@ def search( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -284,7 +329,7 @@ def retranscribe( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[SuccessResponse]: """ - Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. + Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. Billed per minute at the account's call-transcription rate; fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- @@ -327,6 +372,28 @@ def retranscribe( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -403,6 +470,17 @@ def transcriptions( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -478,6 +556,39 @@ def get( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -528,7 +639,7 @@ def list_all( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. @@ -583,6 +694,17 @@ def list_all( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -638,7 +760,7 @@ async def list( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. @@ -704,6 +826,39 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -719,15 +874,15 @@ async def search( type: CdrSearchRequestType, from_: dt.date, to: dt.date, - page: int, - per_page: int, from_search: typing.Optional[str] = OMIT, to_search: typing.Optional[str] = OMIT, sip_trunk: typing.Optional[str] = OMIT, min_duration: typing.Optional[int] = OMIT, transcription: typing.Optional[TranscriptionFilter] = OMIT, uuid_: typing.Optional[str] = OMIT, - disposition: typing.Optional[CdrSearchRequestDisposition] = OMIT, + disposition: typing.Optional[CallDisposition] = OMIT, + page: typing.Optional[int] = OMIT, + per_page: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[CdrTranscriptionSearchResponse]: """ @@ -744,12 +899,6 @@ async def search( to : dt.date End date for call search in `YYYY-MM-DD` format. - page : int - Page number to retrieve. - - per_page : int - Number of records per page. - from_search : typing.Optional[str] Originating phone number to filter results. Accepts full or partial number. @@ -767,12 +916,18 @@ async def search( uuid_ : typing.Optional[str] Call ID. - disposition : typing.Optional[CdrSearchRequestDisposition] + disposition : typing.Optional[CallDisposition] Call disposition to filter results. If omitted, returns only answered - calls. Allowed values: `answered`, `busy`, `rejected`, + calls. Allowed values: `answered`, `noanswer`, `busy`, `failed`, `all`. Use `all` to return calls regardless of their disposition. + page : typing.Optional[int] + Page number to retrieve. + + per_page : typing.Optional[int] + Number of records per page. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -816,6 +971,17 @@ async def search( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -856,7 +1022,7 @@ async def retranscribe( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[SuccessResponse]: """ - Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. + Transcribes the recording of the call identified by `call_id`. Transcription is asynchronous; poll the transcription endpoint for the result. Billed per minute at the account's call-transcription rate; fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- @@ -899,6 +1065,28 @@ async def retranscribe( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -975,6 +1163,17 @@ async def transcriptions( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1050,6 +1249,39 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -1100,7 +1332,7 @@ async def list_all( Filters CDRs by call direction. One of `placed` (outbound calls dialed by the account) or `received` (inbound calls answered by the account). disposition : typing.Optional[CallDisposition] - Filters CDRs by call disposition. One of `answered` (the called party answered), `busy` (the called party was busy), `rejected` (the call was declined), `failed` (the call could not be routed), or `all` (no disposition filter). + Filters CDRs by call disposition. One of `answered` (the called party answered), `noanswer` (no answer within the ring timeout), `busy` (the called party was busy), `failed` (the call could not be routed), or `all` (no disposition filter). from_search : typing.Optional[str] Filters CDRs by originating phone number. Accepts a full or partial number. @@ -1155,6 +1387,17 @@ async def list_all( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/cdrs/transcription/client.py b/src/wavix/cdrs/transcription/client.py index 36f5295..9995568 100644 --- a/src/wavix/cdrs/transcription/client.py +++ b/src/wavix/cdrs/transcription/client.py @@ -48,7 +48,7 @@ def get(self, call_id: str, *, request_options: typing.Optional[RequestOptions] token="YOUR_TOKEN", ) client.cdrs.transcription.get( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) """ _response = self._raw_client.get(call_id, request_options=request_options) @@ -102,7 +102,7 @@ async def get( async def main() -> None: await client.cdrs.transcription.get( - call_id="bbaa37bf-430a-46da-ade3-c248e407016", + call_id="bbaa37bf-430a-46da-ade3-c248e4070160", ) diff --git a/src/wavix/cdrs/transcription/raw_client.py b/src/wavix/cdrs/transcription/raw_client.py index c11e05c..c2a9b83 100644 --- a/src/wavix/cdrs/transcription/raw_client.py +++ b/src/wavix/cdrs/transcription/raw_client.py @@ -10,9 +10,12 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...types.cdr_transcription_response import CdrTranscriptionResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -54,6 +57,28 @@ def get( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -124,6 +149,28 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/cdrs/types/__init__.py b/src/wavix/cdrs/types/__init__.py index e2ad5ff..855c094 100644 --- a/src/wavix/cdrs/types/__init__.py +++ b/src/wavix/cdrs/types/__init__.py @@ -6,12 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .cdr_search_request_disposition import CdrSearchRequestDisposition from .cdr_search_request_type import CdrSearchRequestType -_dynamic_imports: typing.Dict[str, str] = { - "CdrSearchRequestDisposition": ".cdr_search_request_disposition", - "CdrSearchRequestType": ".cdr_search_request_type", -} +_dynamic_imports: typing.Dict[str, str] = {"CdrSearchRequestType": ".cdr_search_request_type"} def __getattr__(attr_name: str) -> typing.Any: @@ -35,4 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["CdrSearchRequestDisposition", "CdrSearchRequestType"] +__all__ = ["CdrSearchRequestType"] diff --git a/src/wavix/cdrs/types/cdr_search_request_disposition.py b/src/wavix/cdrs/types/cdr_search_request_disposition.py deleted file mode 100644 index d82988a..0000000 --- a/src/wavix/cdrs/types/cdr_search_request_disposition.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -CdrSearchRequestDisposition = typing.Union[typing.Literal["answered", "noanswer", "busy", "failed", "all"], typing.Any] diff --git a/src/wavix/core/client_wrapper.py b/src/wavix/core/client_wrapper.py index d08f70d..2c10e90 100644 --- a/src/wavix/core/client_wrapper.py +++ b/src/wavix/core/client_wrapper.py @@ -29,12 +29,12 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { - "User-Agent": "wavix-python-sdk/1.0.0", + "User-Agent": "wavix-python-sdk/1.1.1", "X-Fern-Language": "Python", "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "wavix-python-sdk", - "X-Fern-SDK-Version": "1.0.0", + "X-Fern-SDK-Version": "1.1.1", **(self.get_custom_headers() or {}), } headers["Authorization"] = f"Bearer {self._get_token()}" diff --git a/src/wavix/errors/too_many_requests_error.py b/src/wavix/errors/too_many_requests_error.py index 4a4055c..705d6f1 100644 --- a/src/wavix/errors/too_many_requests_error.py +++ b/src/wavix/errors/too_many_requests_error.py @@ -3,9 +3,8 @@ import typing from ..core.api_error import ApiError -from ..types.validation_error_response import ValidationErrorResponse class TooManyRequestsError(ApiError): - def __init__(self, body: ValidationErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None): + def __init__(self, body: typing.Any, headers: typing.Optional[typing.Dict[str, str]] = None): super().__init__(status_code=429, headers=headers, body=body) diff --git a/src/wavix/link_shortener/client.py b/src/wavix/link_shortener/client.py index 20df966..dc12238 100644 --- a/src/wavix/link_shortener/client.py +++ b/src/wavix/link_shortener/client.py @@ -49,16 +49,16 @@ def create( Parameters ---------- link : str - Target URL to shorten. + Target URL to shorten. Must be `https://` — the short link is publicly resolvable and redirects any visitor here, so only pass URLs you trust; this endpoint is a common target for open-redirect and phishing abuse. expiration_time : typing.Optional[dt.datetime] Expiration date and time in ISO 8601 format. fallback_url : typing.Optional[str] - Fallback URL for expired or invalid links. + Fallback URL for expired or invalid links. Must be `https://` — same open-redirect/phishing considerations as `link` apply. phone : typing.Optional[str] - Phone number for the short link. + Phone number the short link is associated with, in E.164 format (without the leading `+`). Used to attribute click metrics returned by short link metrics list. utm_campaign : typing.Optional[str] UTM campaign name for tracking insights. @@ -134,16 +134,16 @@ async def create( Parameters ---------- link : str - Target URL to shorten. + Target URL to shorten. Must be `https://` — the short link is publicly resolvable and redirects any visitor here, so only pass URLs you trust; this endpoint is a common target for open-redirect and phishing abuse. expiration_time : typing.Optional[dt.datetime] Expiration date and time in ISO 8601 format. fallback_url : typing.Optional[str] - Fallback URL for expired or invalid links. + Fallback URL for expired or invalid links. Must be `https://` — same open-redirect/phishing considerations as `link` apply. phone : typing.Optional[str] - Phone number for the short link. + Phone number the short link is associated with, in E.164 format (without the leading `+`). Used to attribute click metrics returned by short link metrics list. utm_campaign : typing.Optional[str] UTM campaign name for tracking insights. diff --git a/src/wavix/link_shortener/metrics/raw_client.py b/src/wavix/link_shortener/metrics/raw_client.py index 52c9154..e004c5c 100644 --- a/src/wavix/link_shortener/metrics/raw_client.py +++ b/src/wavix/link_shortener/metrics/raw_client.py @@ -12,7 +12,10 @@ from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError +from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...types.short_link_metrics_response import ShortLinkMetricsResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -96,6 +99,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -107,6 +121,17 @@ def list( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -197,6 +222,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -208,6 +244,17 @@ async def list( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) diff --git a/src/wavix/link_shortener/raw_client.py b/src/wavix/link_shortener/raw_client.py index 1cd2728..bb41c15 100644 --- a/src/wavix/link_shortener/raw_client.py +++ b/src/wavix/link_shortener/raw_client.py @@ -13,8 +13,10 @@ from ..errors.bad_request_error import BadRequestError from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError from ..errors.unprocessable_entity_error import UnprocessableEntityError from ..types.short_link_response import ShortLinkResponse +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -41,16 +43,16 @@ def create( Parameters ---------- link : str - Target URL to shorten. + Target URL to shorten. Must be `https://` — the short link is publicly resolvable and redirects any visitor here, so only pass URLs you trust; this endpoint is a common target for open-redirect and phishing abuse. expiration_time : typing.Optional[dt.datetime] Expiration date and time in ISO 8601 format. fallback_url : typing.Optional[str] - Fallback URL for expired or invalid links. + Fallback URL for expired or invalid links. Must be `https://` — same open-redirect/phishing considerations as `link` apply. phone : typing.Optional[str] - Phone number for the short link. + Phone number the short link is associated with, in E.164 format (without the leading `+`). Used to attribute click metrics returned by short link metrics list. utm_campaign : typing.Optional[str] UTM campaign name for tracking insights. @@ -100,6 +102,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -163,16 +176,16 @@ async def create( Parameters ---------- link : str - Target URL to shorten. + Target URL to shorten. Must be `https://` — the short link is publicly resolvable and redirects any visitor here, so only pass URLs you trust; this endpoint is a common target for open-redirect and phishing abuse. expiration_time : typing.Optional[dt.datetime] Expiration date and time in ISO 8601 format. fallback_url : typing.Optional[str] - Fallback URL for expired or invalid links. + Fallback URL for expired or invalid links. Must be `https://` — same open-redirect/phishing considerations as `link` apply. phone : typing.Optional[str] - Phone number for the short link. + Phone number the short link is associated with, in E.164 format (without the leading `+`). Used to attribute click metrics returned by short link metrics list. utm_campaign : typing.Optional[str] UTM campaign name for tracking insights. @@ -222,6 +235,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/number_validator/__init__.py b/src/wavix/number_validator/__init__.py index da27b6f..73d4ff0 100644 --- a/src/wavix/number_validator/__init__.py +++ b/src/wavix/number_validator/__init__.py @@ -6,9 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import GetNumberValidatorResponse from . import results -_dynamic_imports: typing.Dict[str, str] = {"GetNumberValidatorResponse": ".types", "results": ".results"} +_dynamic_imports: typing.Dict[str, str] = {"results": ".results"} def __getattr__(attr_name: str) -> typing.Any: @@ -32,4 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["GetNumberValidatorResponse", "results"] +__all__ = ["results"] diff --git a/src/wavix/number_validator/client.py b/src/wavix/number_validator/client.py index 258df00..329a0e0 100644 --- a/src/wavix/number_validator/client.py +++ b/src/wavix/number_validator/client.py @@ -8,8 +8,8 @@ from ..core.request_options import RequestOptions from ..types.number_validator_create_bulk_response import NumberValidatorCreateBulkResponse from ..types.phone_number_validation_type import PhoneNumberValidationType +from ..types.phone_validation_response import PhoneValidationResponse from .raw_client import AsyncRawNumberValidatorClient, RawNumberValidatorClient -from .types.get_number_validator_response import GetNumberValidatorResponse if typing.TYPE_CHECKING: from .results.client import AsyncResultsClient, ResultsClient @@ -40,9 +40,9 @@ def get( phone_number: str, type: PhoneNumberValidationType, request_options: typing.Optional[RequestOptions] = None, - ) -> GetNumberValidatorResponse: + ) -> PhoneValidationResponse: """ - Validates a single phone number and returns line type, carrier, portability, and reachability details. + Validates a single phone number and returns line type, carrier, portability, and reachability details. The response's `error_code` is a per-number result code (`000` success; `013` internal error; `021` invalid format; `041` remote timeout; `042` remote query failed; `091` insufficient funds) — distinct from the HTTP status codes below. Parameters ---------- @@ -57,7 +57,7 @@ def get( Returns ------- - GetNumberValidatorResponse + PhoneValidationResponse Returns the phone number validation details. Examples @@ -80,8 +80,8 @@ def create_bulk( *, phone_numbers: typing.Sequence[str], type: PhoneNumberValidationType, - async_: bool, - force: bool, + async_: typing.Optional[bool] = OMIT, + force: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> NumberValidatorCreateBulkResponse: """ @@ -90,15 +90,15 @@ def create_bulk( Parameters ---------- phone_numbers : typing.Sequence[str] - List of phone numbers to get detailed information about. + List of phone numbers to get detailed information about. Maximum 1000 numbers per request. type : PhoneNumberValidationType - async_ : bool - Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false`, the response will include validation results directly. + async_ : typing.Optional[bool] + Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false` (default), the response will include validation results directly. - force : bool - Indicates whether to force a fresh validation instead of returning a previously cached result. + force : typing.Optional[bool] + Indicates whether to force a fresh validation instead of returning a previously cached result. Defaults to `false`. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -118,8 +118,6 @@ def create_bulk( client.number_validator.create_bulk( phone_numbers=["971501390098", "971504359195"], type="format", - async_=True, - force=True, ) """ _response = self._raw_client.create_bulk( @@ -159,9 +157,9 @@ async def get( phone_number: str, type: PhoneNumberValidationType, request_options: typing.Optional[RequestOptions] = None, - ) -> GetNumberValidatorResponse: + ) -> PhoneValidationResponse: """ - Validates a single phone number and returns line type, carrier, portability, and reachability details. + Validates a single phone number and returns line type, carrier, portability, and reachability details. The response's `error_code` is a per-number result code (`000` success; `013` internal error; `021` invalid format; `041` remote timeout; `042` remote query failed; `091` insufficient funds) — distinct from the HTTP status codes below. Parameters ---------- @@ -176,7 +174,7 @@ async def get( Returns ------- - GetNumberValidatorResponse + PhoneValidationResponse Returns the phone number validation details. Examples @@ -207,8 +205,8 @@ async def create_bulk( *, phone_numbers: typing.Sequence[str], type: PhoneNumberValidationType, - async_: bool, - force: bool, + async_: typing.Optional[bool] = OMIT, + force: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> NumberValidatorCreateBulkResponse: """ @@ -217,15 +215,15 @@ async def create_bulk( Parameters ---------- phone_numbers : typing.Sequence[str] - List of phone numbers to get detailed information about. + List of phone numbers to get detailed information about. Maximum 1000 numbers per request. type : PhoneNumberValidationType - async_ : bool - Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false`, the response will include validation results directly. + async_ : typing.Optional[bool] + Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false` (default), the response will include validation results directly. - force : bool - Indicates whether to force a fresh validation instead of returning a previously cached result. + force : typing.Optional[bool] + Indicates whether to force a fresh validation instead of returning a previously cached result. Defaults to `false`. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -250,8 +248,6 @@ async def main() -> None: await client.number_validator.create_bulk( phone_numbers=["971501390098", "971504359195"], type="format", - async_=True, - force=True, ) diff --git a/src/wavix/number_validator/raw_client.py b/src/wavix/number_validator/raw_client.py index a756f49..3bf0daa 100644 --- a/src/wavix/number_validator/raw_client.py +++ b/src/wavix/number_validator/raw_client.py @@ -12,9 +12,12 @@ from ..errors.bad_request_error import BadRequestError from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError +from ..errors.unprocessable_entity_error import UnprocessableEntityError from ..types.number_validator_create_bulk_response import NumberValidatorCreateBulkResponse from ..types.phone_number_validation_type import PhoneNumberValidationType -from .types.get_number_validator_response import GetNumberValidatorResponse +from ..types.phone_validation_response import PhoneValidationResponse +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -31,9 +34,9 @@ def get( phone_number: str, type: PhoneNumberValidationType, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[GetNumberValidatorResponse]: + ) -> HttpResponse[PhoneValidationResponse]: """ - Validates a single phone number and returns line type, carrier, portability, and reachability details. + Validates a single phone number and returns line type, carrier, portability, and reachability details. The response's `error_code` is a per-number result code (`000` success; `013` internal error; `021` invalid format; `041` remote timeout; `042` remote query failed; `091` insufficient funds) — distinct from the HTTP status codes below. Parameters ---------- @@ -48,7 +51,7 @@ def get( Returns ------- - HttpResponse[GetNumberValidatorResponse] + HttpResponse[PhoneValidationResponse] Returns the phone number validation details. """ _response = self._client_wrapper.httpx_client.request( @@ -63,9 +66,9 @@ def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetNumberValidatorResponse, + PhoneValidationResponse, parse_obj_as( - type_=GetNumberValidatorResponse, # type: ignore + type_=PhoneValidationResponse, # type: ignore object_=_response.json(), ), ) @@ -81,6 +84,17 @@ def get( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -92,6 +106,17 @@ def get( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -106,8 +131,8 @@ def create_bulk( *, phone_numbers: typing.Sequence[str], type: PhoneNumberValidationType, - async_: bool, - force: bool, + async_: typing.Optional[bool] = OMIT, + force: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[NumberValidatorCreateBulkResponse]: """ @@ -116,15 +141,15 @@ def create_bulk( Parameters ---------- phone_numbers : typing.Sequence[str] - List of phone numbers to get detailed information about. + List of phone numbers to get detailed information about. Maximum 1000 numbers per request. type : PhoneNumberValidationType - async_ : bool - Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false`, the response will include validation results directly. + async_ : typing.Optional[bool] + Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false` (default), the response will include validation results directly. - force : bool - Indicates whether to force a fresh validation instead of returning a previously cached result. + force : typing.Optional[bool] + Indicates whether to force a fresh validation instead of returning a previously cached result. Defaults to `false`. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -170,6 +195,17 @@ def create_bulk( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -192,6 +228,17 @@ def create_bulk( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -212,9 +259,9 @@ async def get( phone_number: str, type: PhoneNumberValidationType, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[GetNumberValidatorResponse]: + ) -> AsyncHttpResponse[PhoneValidationResponse]: """ - Validates a single phone number and returns line type, carrier, portability, and reachability details. + Validates a single phone number and returns line type, carrier, portability, and reachability details. The response's `error_code` is a per-number result code (`000` success; `013` internal error; `021` invalid format; `041` remote timeout; `042` remote query failed; `091` insufficient funds) — distinct from the HTTP status codes below. Parameters ---------- @@ -229,7 +276,7 @@ async def get( Returns ------- - AsyncHttpResponse[GetNumberValidatorResponse] + AsyncHttpResponse[PhoneValidationResponse] Returns the phone number validation details. """ _response = await self._client_wrapper.httpx_client.request( @@ -244,9 +291,9 @@ async def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetNumberValidatorResponse, + PhoneValidationResponse, parse_obj_as( - type_=GetNumberValidatorResponse, # type: ignore + type_=PhoneValidationResponse, # type: ignore object_=_response.json(), ), ) @@ -262,6 +309,17 @@ async def get( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -273,6 +331,17 @@ async def get( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -287,8 +356,8 @@ async def create_bulk( *, phone_numbers: typing.Sequence[str], type: PhoneNumberValidationType, - async_: bool, - force: bool, + async_: typing.Optional[bool] = OMIT, + force: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[NumberValidatorCreateBulkResponse]: """ @@ -297,15 +366,15 @@ async def create_bulk( Parameters ---------- phone_numbers : typing.Sequence[str] - List of phone numbers to get detailed information about. + List of phone numbers to get detailed information about. Maximum 1000 numbers per request. type : PhoneNumberValidationType - async_ : bool - Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false`, the response will include validation results directly. + async_ : typing.Optional[bool] + Indicates whether the request should be executed asynchronously. If `true`, the response will include a `request_uuid` that can be used to poll for results. If `false` (default), the response will include validation results directly. - force : bool - Indicates whether to force a fresh validation instead of returning a previously cached result. + force : typing.Optional[bool] + Indicates whether to force a fresh validation instead of returning a previously cached result. Defaults to `false`. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -351,6 +420,17 @@ async def create_bulk( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -373,6 +453,17 @@ async def create_bulk( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) diff --git a/src/wavix/number_validator/results/raw_client.py b/src/wavix/number_validator/results/raw_client.py index a97da94..8ec0cf8 100644 --- a/src/wavix/number_validator/results/raw_client.py +++ b/src/wavix/number_validator/results/raw_client.py @@ -10,9 +10,12 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...types.phone_validation_batch_result_response import PhoneValidationBatchResultResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -54,6 +57,28 @@ def get( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -124,6 +149,28 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/number_validator/types/__init__.py b/src/wavix/number_validator/types/__init__.py deleted file mode 100644 index aab5846..0000000 --- a/src/wavix/number_validator/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .get_number_validator_response import GetNumberValidatorResponse -_dynamic_imports: typing.Dict[str, str] = {"GetNumberValidatorResponse": ".get_number_validator_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["GetNumberValidatorResponse"] diff --git a/src/wavix/number_validator/types/get_number_validator_response.py b/src/wavix/number_validator/types/get_number_validator_response.py deleted file mode 100644 index 769428d..0000000 --- a/src/wavix/number_validator/types/get_number_validator_response.py +++ /dev/null @@ -1,112 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -import typing_extensions -from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ...core.serialization import FieldMetadata - - -class GetNumberValidatorResponse(UniversalBaseModel): - phone_number: str = pydantic.Field() - """ - Phone number. - """ - - valid: bool = pydantic.Field() - """ - Indicates whether the phone number is valid. - """ - - country_code: typing.Optional[str] = pydantic.Field(default=None) - """ - ISO 3166-1 alpha-2 country code of the phone number. - `null` if the number is invalid. - """ - - e164format: typing_extensions.Annotated[ - str, - FieldMetadata(alias="e164_format"), - pydantic.Field(alias="e164_format", description="Phone number in international E.164 format."), - ] - national_format: str = pydantic.Field() - """ - Phone number in the national format of the identified country. - """ - - ported: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the phone number was ported or not. `null` if the phone number is invalid. - """ - - mcc: typing.Optional[str] = pydantic.Field(default=None) - """ - Mobile Country Code of the phone number carrier. For mobile phone numbers only. `null` if the phone number is invalid. - """ - - mnc: typing.Optional[str] = pydantic.Field(default=None) - """ - Mobile Network Code of the phone number carrier. For mobile phone numbers only. `null` if the phone number is invalid - """ - - number_type: typing.Optional[str] = pydantic.Field(default=None) - """ - Number type. Possible values are `mobile`, `landline`, or `toll-free`. `null` if the phone number is invalid. - """ - - carrier_name: typing.Optional[str] = pydantic.Field(default=None) - """ - Name of the phone number carrier. `null` if the phone number is invalid. - """ - - risky_destination: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the phone number belongs to a number range associated with traffic pumping. `null` if the number is invalid. - """ - - unallocated_range: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the phone number belongs to an unallocated number range. `null` if the number is invalid - """ - - reachable: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the number is registered in a mobile network. For mobile phone numbers only. `null` if the number is invalid - """ - - roaming: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the number is roaming. For mobile phone numbers only. `null` if the number is invalid - """ - - timezone: typing.Optional[str] = pydantic.Field(default=None) - """ - Time zone based on the phone number's country and area code. - `null` if the number is invalid. - """ - - charge: str = pydantic.Field() - """ - Charge for the validation. - """ - - error_code: str = pydantic.Field() - """ - Error code for the request. `000` indicates success. - Possible values: - - `013`: — Internal service error - - `021`: — Invalid phone number length or format - - `041`: — Request timeout - - `042`: — Request failed - - `091`: — Insufficient funds - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/numbers/__init__.py b/src/wavix/numbers/__init__.py index 4b55697..cb41f99 100644 --- a/src/wavix/numbers/__init__.py +++ b/src/wavix/numbers/__init__.py @@ -6,13 +6,9 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import BulkUpdateNumbersResponse, DeleteNumbersResponse + from .types import BulkUpdateNumbersResponse from . import papers -_dynamic_imports: typing.Dict[str, str] = { - "BulkUpdateNumbersResponse": ".types", - "DeleteNumbersResponse": ".types", - "papers": ".papers", -} +_dynamic_imports: typing.Dict[str, str] = {"BulkUpdateNumbersResponse": ".types", "papers": ".papers"} def __getattr__(attr_name: str) -> typing.Any: @@ -36,4 +32,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["BulkUpdateNumbersResponse", "DeleteNumbersResponse", "papers"] +__all__ = ["BulkUpdateNumbersResponse", "papers"] diff --git a/src/wavix/numbers/client.py b/src/wavix/numbers/client.py index b09e992..4dc1085 100644 --- a/src/wavix/numbers/client.py +++ b/src/wavix/numbers/client.py @@ -9,9 +9,9 @@ from ..types.number import Number from ..types.number_destination import NumberDestination from ..types.number_list_response import NumberListResponse +from ..types.success_response import SuccessResponse from .raw_client import AsyncRawNumbersClient, RawNumbersClient from .types.bulk_update_numbers_response import BulkUpdateNumbersResponse -from .types.delete_numbers_response import DeleteNumbersResponse if typing.TYPE_CHECKING: from .papers.client import AsyncPapersClient, PapersClient @@ -111,7 +111,7 @@ def delete( ids: typing.Optional[typing.Union[int, typing.Sequence[int]]] = None, dids: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> DeleteNumbersResponse: + ) -> SuccessResponse: """ Releases the listed phone numbers back to stock. Selection accepts either `ids` (record IDs) or `dids` (phone numbers), but not both. @@ -128,7 +128,7 @@ def delete( Returns ------- - DeleteNumbersResponse + SuccessResponse Returns a success confirmation. The numbers are released back to stock. Examples @@ -434,7 +434,7 @@ async def delete( ids: typing.Optional[typing.Union[int, typing.Sequence[int]]] = None, dids: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> DeleteNumbersResponse: + ) -> SuccessResponse: """ Releases the listed phone numbers back to stock. Selection accepts either `ids` (record IDs) or `dids` (phone numbers), but not both. @@ -451,7 +451,7 @@ async def delete( Returns ------- - DeleteNumbersResponse + SuccessResponse Returns a success confirmation. The numbers are released back to stock. Examples diff --git a/src/wavix/numbers/papers/client.py b/src/wavix/numbers/papers/client.py index 38b98d2..ae626e9 100644 --- a/src/wavix/numbers/papers/client.py +++ b/src/wavix/numbers/papers/client.py @@ -5,7 +5,7 @@ from ... import core from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.document_type_id import DocumentTypeId +from ...types.document_type import DocumentType from ...types.number_document import NumberDocument from .raw_client import AsyncRawPapersClient, RawPapersClient @@ -33,7 +33,7 @@ def upload( *, did_ids: str, doc_attachment: core.File, - doc_id: DocumentTypeId, + doc_id: DocumentType, request_options: typing.Optional[RequestOptions] = None, ) -> typing.List[NumberDocument]: """ @@ -52,7 +52,7 @@ def upload( doc_attachment : core.File See core.File for more documentation - doc_id : DocumentTypeId + doc_id : DocumentType request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -71,7 +71,7 @@ def upload( ) client.numbers.papers.upload( did_ids="did_ids", - doc_id=1, + doc_id="id", ) """ _response = self._raw_client.upload( @@ -100,7 +100,7 @@ async def upload( *, did_ids: str, doc_attachment: core.File, - doc_id: DocumentTypeId, + doc_id: DocumentType, request_options: typing.Optional[RequestOptions] = None, ) -> typing.List[NumberDocument]: """ @@ -119,7 +119,7 @@ async def upload( doc_attachment : core.File See core.File for more documentation - doc_id : DocumentTypeId + doc_id : DocumentType request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -143,7 +143,7 @@ async def upload( async def main() -> None: await client.numbers.papers.upload( did_ids="did_ids", - doc_id=1, + doc_id="id", ) diff --git a/src/wavix/numbers/papers/raw_client.py b/src/wavix/numbers/papers/raw_client.py index 070ac63..ccb9d0f 100644 --- a/src/wavix/numbers/papers/raw_client.py +++ b/src/wavix/numbers/papers/raw_client.py @@ -12,8 +12,10 @@ from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError -from ...types.document_type_id import DocumentTypeId +from ...errors.unauthorized_error import UnauthorizedError +from ...types.document_type import DocumentType from ...types.number_document import NumberDocument +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -29,7 +31,7 @@ def upload( *, did_ids: str, doc_attachment: core.File, - doc_id: DocumentTypeId, + doc_id: DocumentType, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[typing.List[NumberDocument]]: """ @@ -48,7 +50,7 @@ def upload( doc_attachment : core.File See core.File for more documentation - doc_id : DocumentTypeId + doc_id : DocumentType request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -93,6 +95,17 @@ def upload( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -123,7 +136,7 @@ async def upload( *, did_ids: str, doc_attachment: core.File, - doc_id: DocumentTypeId, + doc_id: DocumentType, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[typing.List[NumberDocument]]: """ @@ -142,7 +155,7 @@ async def upload( doc_attachment : core.File See core.File for more documentation - doc_id : DocumentTypeId + doc_id : DocumentType request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -187,6 +200,17 @@ async def upload( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/numbers/raw_client.py b/src/wavix/numbers/raw_client.py index 0fcbf04..2d34d50 100644 --- a/src/wavix/numbers/raw_client.py +++ b/src/wavix/numbers/raw_client.py @@ -14,12 +14,14 @@ from ..errors.bad_request_error import BadRequestError from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError from ..errors.unprocessable_entity_error import UnprocessableEntityError from ..types.number import Number from ..types.number_destination import NumberDestination from ..types.number_list_response import NumberListResponse +from ..types.success_response import SuccessResponse +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from .types.bulk_update_numbers_response import BulkUpdateNumbersResponse -from .types.delete_numbers_response import DeleteNumbersResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -95,6 +97,28 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -121,7 +145,7 @@ def delete( ids: typing.Optional[typing.Union[int, typing.Sequence[int]]] = None, dids: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[DeleteNumbersResponse]: + ) -> HttpResponse[SuccessResponse]: """ Releases the listed phone numbers back to stock. Selection accepts either `ids` (record IDs) or `dids` (phone numbers), but not both. @@ -138,7 +162,7 @@ def delete( Returns ------- - HttpResponse[DeleteNumbersResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The numbers are released back to stock. """ _response = self._client_wrapper.httpx_client.request( @@ -153,13 +177,24 @@ def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteNumbersResponse, + SuccessResponse, parse_obj_as( - type_=DeleteNumbersResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -295,6 +330,17 @@ def bulk_update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -358,6 +404,28 @@ def get(self, id: int, *, request_options: typing.Optional[RequestOptions] = Non ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -480,6 +548,17 @@ def update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -581,6 +660,28 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -607,7 +708,7 @@ async def delete( ids: typing.Optional[typing.Union[int, typing.Sequence[int]]] = None, dids: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[DeleteNumbersResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Releases the listed phone numbers back to stock. Selection accepts either `ids` (record IDs) or `dids` (phone numbers), but not both. @@ -624,7 +725,7 @@ async def delete( Returns ------- - AsyncHttpResponse[DeleteNumbersResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The numbers are released back to stock. """ _response = await self._client_wrapper.httpx_client.request( @@ -639,13 +740,24 @@ async def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteNumbersResponse, + SuccessResponse, parse_obj_as( - type_=DeleteNumbersResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -781,6 +893,17 @@ async def bulk_update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -846,6 +969,28 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -968,6 +1113,17 @@ async def update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/numbers/types/__init__.py b/src/wavix/numbers/types/__init__.py index 545ff00..ea4c1a7 100644 --- a/src/wavix/numbers/types/__init__.py +++ b/src/wavix/numbers/types/__init__.py @@ -7,11 +7,7 @@ if typing.TYPE_CHECKING: from .bulk_update_numbers_response import BulkUpdateNumbersResponse - from .delete_numbers_response import DeleteNumbersResponse -_dynamic_imports: typing.Dict[str, str] = { - "BulkUpdateNumbersResponse": ".bulk_update_numbers_response", - "DeleteNumbersResponse": ".delete_numbers_response", -} +_dynamic_imports: typing.Dict[str, str] = {"BulkUpdateNumbersResponse": ".bulk_update_numbers_response"} def __getattr__(attr_name: str) -> typing.Any: @@ -35,4 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["BulkUpdateNumbersResponse", "DeleteNumbersResponse"] +__all__ = ["BulkUpdateNumbersResponse"] diff --git a/src/wavix/profile/__init__.py b/src/wavix/profile/__init__.py index edea256..ebfc7f3 100644 --- a/src/wavix/profile/__init__.py +++ b/src/wavix/profile/__init__.py @@ -8,9 +8,7 @@ if typing.TYPE_CHECKING: from .types import ProfileUpdateRequestCompanyInfo, ProfileUpdateRequestCompanyInfoIndustry from . import config - from .config import GetConfigResponse _dynamic_imports: typing.Dict[str, str] = { - "GetConfigResponse": ".config", "ProfileUpdateRequestCompanyInfo": ".types", "ProfileUpdateRequestCompanyInfoIndustry": ".types", "config": ".config", @@ -38,4 +36,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["GetConfigResponse", "ProfileUpdateRequestCompanyInfo", "ProfileUpdateRequestCompanyInfoIndustry", "config"] +__all__ = ["ProfileUpdateRequestCompanyInfo", "ProfileUpdateRequestCompanyInfoIndustry", "config"] diff --git a/src/wavix/profile/config/__init__.py b/src/wavix/profile/config/__init__.py index f19b786..5cde020 100644 --- a/src/wavix/profile/config/__init__.py +++ b/src/wavix/profile/config/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import GetConfigResponse -_dynamic_imports: typing.Dict[str, str] = {"GetConfigResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["GetConfigResponse"] diff --git a/src/wavix/profile/config/client.py b/src/wavix/profile/config/client.py index 8446cdd..7ca584f 100644 --- a/src/wavix/profile/config/client.py +++ b/src/wavix/profile/config/client.py @@ -4,8 +4,8 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.profile_config_response import ProfileConfigResponse from .raw_client import AsyncRawConfigClient, RawConfigClient -from .types.get_config_response import GetConfigResponse class ConfigClient: @@ -23,7 +23,7 @@ def with_raw_response(self) -> RawConfigClient: """ return self._raw_client - def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> GetConfigResponse: + def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> ProfileConfigResponse: """ Returns the balance and global limits configured for the authenticated account. @@ -34,7 +34,7 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Get Returns ------- - GetConfigResponse + ProfileConfigResponse Returns the account settings. Examples @@ -65,7 +65,7 @@ def with_raw_response(self) -> AsyncRawConfigClient: """ return self._raw_client - async def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> GetConfigResponse: + async def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> ProfileConfigResponse: """ Returns the balance and global limits configured for the authenticated account. @@ -76,7 +76,7 @@ async def get(self, *, request_options: typing.Optional[RequestOptions] = None) Returns ------- - GetConfigResponse + ProfileConfigResponse Returns the account settings. Examples diff --git a/src/wavix/profile/config/raw_client.py b/src/wavix/profile/config/raw_client.py index 389f50b..4feb497 100644 --- a/src/wavix/profile/config/raw_client.py +++ b/src/wavix/profile/config/raw_client.py @@ -9,8 +9,11 @@ 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.forbidden_error import ForbiddenError -from .types.get_config_response import GetConfigResponse +from ...errors.unauthorized_error import UnauthorizedError +from ...types.profile_config_response import ProfileConfigResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -18,7 +21,7 @@ class RawConfigClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper - def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[GetConfigResponse]: + def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[ProfileConfigResponse]: """ Returns the balance and global limits configured for the authenticated account. @@ -29,7 +32,7 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Htt Returns ------- - HttpResponse[GetConfigResponse] + HttpResponse[ProfileConfigResponse] Returns the account settings. """ _response = self._client_wrapper.httpx_client.request( @@ -40,13 +43,35 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Htt try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetConfigResponse, + ProfileConfigResponse, parse_obj_as( - type_=GetConfigResponse, # type: ignore + type_=ProfileConfigResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -74,7 +99,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def get( self, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[GetConfigResponse]: + ) -> AsyncHttpResponse[ProfileConfigResponse]: """ Returns the balance and global limits configured for the authenticated account. @@ -85,7 +110,7 @@ async def get( Returns ------- - AsyncHttpResponse[GetConfigResponse] + AsyncHttpResponse[ProfileConfigResponse] Returns the account settings. """ _response = await self._client_wrapper.httpx_client.request( @@ -96,13 +121,35 @@ async def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetConfigResponse, + ProfileConfigResponse, parse_obj_as( - type_=GetConfigResponse, # type: ignore + type_=ProfileConfigResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/profile/config/types/__init__.py b/src/wavix/profile/config/types/__init__.py deleted file mode 100644 index 12d6e40..0000000 --- a/src/wavix/profile/config/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .get_config_response import GetConfigResponse -_dynamic_imports: typing.Dict[str, str] = {"GetConfigResponse": ".get_config_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["GetConfigResponse"] diff --git a/src/wavix/profile/config/types/get_config_response.py b/src/wavix/profile/config/types/get_config_response.py deleted file mode 100644 index e54c07f..0000000 --- a/src/wavix/profile/config/types/get_config_response.py +++ /dev/null @@ -1,25 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.account_limits import AccountLimits - - -class GetConfigResponse(UniversalBaseModel): - balance: str = pydantic.Field() - """ - Funds available on the account balance, in USD - """ - - global_limits: AccountLimits - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/profile/raw_client.py b/src/wavix/profile/raw_client.py index 2c96af0..d535868 100644 --- a/src/wavix/profile/raw_client.py +++ b/src/wavix/profile/raw_client.py @@ -10,9 +10,13 @@ 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 ..errors.forbidden_error import ForbiddenError +from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError from ..errors.unprocessable_entity_error import UnprocessableEntityError from ..types.profile_response import ProfileResponse +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from .types.profile_update_request_company_info import ProfileUpdateRequestCompanyInfo from pydantic import ValidationError @@ -53,6 +57,28 @@ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> Htt ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -168,6 +194,50 @@ def update( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), @@ -224,6 +294,28 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -339,6 +431,50 @@ async def update( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), diff --git a/src/wavix/sip_trunks/client.py b/src/wavix/sip_trunks/client.py index d59e488..76133d2 100644 --- a/src/wavix/sip_trunks/client.py +++ b/src/wavix/sip_trunks/client.py @@ -77,7 +77,6 @@ def create( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -86,6 +85,7 @@ def create( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -118,9 +118,6 @@ def create( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -147,6 +144,9 @@ def create( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -191,7 +191,6 @@ def create( ip_restrict=False, didinfo_enabled=True, call_restrict=True, - cost_limit=True, channels_restrict=False, rewrite_enabled=True, transcription_enabled=True, @@ -205,7 +204,6 @@ def create( ip_restrict=ip_restrict, didinfo_enabled=didinfo_enabled, call_restrict=call_restrict, - cost_limit=cost_limit, channels_restrict=channels_restrict, rewrite_enabled=rewrite_enabled, transcription_enabled=transcription_enabled, @@ -214,6 +212,7 @@ def create( multiple_numbers=multiple_numbers, allowed_ips=allowed_ips, call_limit=call_limit, + cost_limit=cost_limit, max_call_cost=max_call_cost, max_channels=max_channels, rewrite_prefix=rewrite_prefix, @@ -266,7 +265,6 @@ def update( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -275,6 +273,7 @@ def update( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -310,9 +309,6 @@ def update( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -339,6 +335,9 @@ def update( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -384,7 +383,6 @@ def update( ip_restrict=False, didinfo_enabled=True, call_restrict=True, - cost_limit=True, channels_restrict=False, rewrite_enabled=True, transcription_enabled=True, @@ -399,7 +397,6 @@ def update( ip_restrict=ip_restrict, didinfo_enabled=didinfo_enabled, call_restrict=call_restrict, - cost_limit=cost_limit, channels_restrict=channels_restrict, rewrite_enabled=rewrite_enabled, transcription_enabled=transcription_enabled, @@ -408,6 +405,7 @@ def update( multiple_numbers=multiple_numbers, allowed_ips=allowed_ips, call_limit=call_limit, + cost_limit=cost_limit, max_call_cost=max_call_cost, max_channels=max_channels, rewrite_prefix=rewrite_prefix, @@ -521,7 +519,6 @@ async def create( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -530,6 +527,7 @@ async def create( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -562,9 +560,6 @@ async def create( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -591,6 +586,9 @@ async def create( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -640,7 +638,6 @@ async def main() -> None: ip_restrict=False, didinfo_enabled=True, call_restrict=True, - cost_limit=True, channels_restrict=False, rewrite_enabled=True, transcription_enabled=True, @@ -657,7 +654,6 @@ async def main() -> None: ip_restrict=ip_restrict, didinfo_enabled=didinfo_enabled, call_restrict=call_restrict, - cost_limit=cost_limit, channels_restrict=channels_restrict, rewrite_enabled=rewrite_enabled, transcription_enabled=transcription_enabled, @@ -666,6 +662,7 @@ async def main() -> None: multiple_numbers=multiple_numbers, allowed_ips=allowed_ips, call_limit=call_limit, + cost_limit=cost_limit, max_call_cost=max_call_cost, max_channels=max_channels, rewrite_prefix=rewrite_prefix, @@ -726,7 +723,6 @@ async def update( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -735,6 +731,7 @@ async def update( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -770,9 +767,6 @@ async def update( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -799,6 +793,9 @@ async def update( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -849,7 +846,6 @@ async def main() -> None: ip_restrict=False, didinfo_enabled=True, call_restrict=True, - cost_limit=True, channels_restrict=False, rewrite_enabled=True, transcription_enabled=True, @@ -867,7 +863,6 @@ async def main() -> None: ip_restrict=ip_restrict, didinfo_enabled=didinfo_enabled, call_restrict=call_restrict, - cost_limit=cost_limit, channels_restrict=channels_restrict, rewrite_enabled=rewrite_enabled, transcription_enabled=transcription_enabled, @@ -876,6 +871,7 @@ async def main() -> None: multiple_numbers=multiple_numbers, allowed_ips=allowed_ips, call_limit=call_limit, + cost_limit=cost_limit, max_call_cost=max_call_cost, max_channels=max_channels, rewrite_prefix=rewrite_prefix, diff --git a/src/wavix/sip_trunks/raw_client.py b/src/wavix/sip_trunks/raw_client.py index b8b2b37..5dd4e8a 100644 --- a/src/wavix/sip_trunks/raw_client.py +++ b/src/wavix/sip_trunks/raw_client.py @@ -117,7 +117,6 @@ def create( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -126,6 +125,7 @@ def create( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -158,9 +158,6 @@ def create( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -187,6 +184,9 @@ def create( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -353,6 +353,28 @@ def get( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -394,7 +416,6 @@ def update( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -403,6 +424,7 @@ def update( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -438,9 +460,6 @@ def update( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -467,6 +486,9 @@ def update( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -633,6 +655,17 @@ def delete( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -765,7 +798,6 @@ async def create( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -774,6 +806,7 @@ async def create( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -806,9 +839,6 @@ async def create( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -835,6 +865,9 @@ async def create( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -1001,6 +1034,28 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1042,7 +1097,6 @@ async def update( ip_restrict: bool, didinfo_enabled: bool, call_restrict: bool, - cost_limit: bool, channels_restrict: bool, rewrite_enabled: bool, transcription_enabled: bool, @@ -1051,6 +1105,7 @@ async def update( multiple_numbers: typing.Optional[bool] = OMIT, allowed_ips: typing.Optional[typing.Sequence[SipTrunkCreateRequestAllowedIpsItem]] = OMIT, call_limit: typing.Optional[int] = OMIT, + cost_limit: typing.Optional[bool] = OMIT, max_call_cost: typing.Optional[float] = OMIT, max_channels: typing.Optional[int] = OMIT, rewrite_prefix: typing.Optional[str] = OMIT, @@ -1086,9 +1141,6 @@ async def update( call_restrict : bool Indicates whether a maximum call duration limit is enforced for the SIP trunk - cost_limit : bool - Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. - channels_restrict : bool Indicates whether a limit on the number of concurrent outbound calls is enforced for the SIP trunk @@ -1115,6 +1167,9 @@ async def update( call_limit : typing.Optional[int] Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. + cost_limit : typing.Optional[bool] + Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. + max_call_cost : typing.Optional[float] Maximum cost for an outbound call, in USD @@ -1281,6 +1336,17 @@ async def delete( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), diff --git a/src/wavix/sms_and_mms/__init__.py b/src/wavix/sms_and_mms/__init__.py index 1910a96..9d00711 100644 --- a/src/wavix/sms_and_mms/__init__.py +++ b/src/wavix/sms_and_mms/__init__.py @@ -7,21 +7,11 @@ if typing.TYPE_CHECKING: from . import messages, opt_outs, sender_ids - from .messages import ( - GetMessagesResponse, - ListAllMessagesRequestMessageType, - ListMessagesRequestMessageType, - ListMessagesResponse, - ) - from .opt_outs import CreateOptOutsResponse - from .sender_ids import DeleteSenderIdsResponse, SenderIdCreateRequestMonthlyVolume, SenderIdCreateRequestUsecase + from .messages import ListAllMessagesRequestMessageType, ListMessagesRequestMessageType + from .sender_ids import SenderIdCreateRequestMonthlyVolume, SenderIdCreateRequestUsecase _dynamic_imports: typing.Dict[str, str] = { - "CreateOptOutsResponse": ".opt_outs", - "DeleteSenderIdsResponse": ".sender_ids", - "GetMessagesResponse": ".messages", "ListAllMessagesRequestMessageType": ".messages", "ListMessagesRequestMessageType": ".messages", - "ListMessagesResponse": ".messages", "SenderIdCreateRequestMonthlyVolume": ".sender_ids", "SenderIdCreateRequestUsecase": ".sender_ids", "messages": ".messages", @@ -52,12 +42,8 @@ def __dir__(): __all__ = [ - "CreateOptOutsResponse", - "DeleteSenderIdsResponse", - "GetMessagesResponse", "ListAllMessagesRequestMessageType", "ListMessagesRequestMessageType", - "ListMessagesResponse", "SenderIdCreateRequestMonthlyVolume", "SenderIdCreateRequestUsecase", "messages", diff --git a/src/wavix/sms_and_mms/messages/__init__.py b/src/wavix/sms_and_mms/messages/__init__.py index 999b097..74d4d97 100644 --- a/src/wavix/sms_and_mms/messages/__init__.py +++ b/src/wavix/sms_and_mms/messages/__init__.py @@ -6,17 +6,10 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import ( - GetMessagesResponse, - ListAllMessagesRequestMessageType, - ListMessagesRequestMessageType, - ListMessagesResponse, - ) + from .types import ListAllMessagesRequestMessageType, ListMessagesRequestMessageType _dynamic_imports: typing.Dict[str, str] = { - "GetMessagesResponse": ".types", "ListAllMessagesRequestMessageType": ".types", "ListMessagesRequestMessageType": ".types", - "ListMessagesResponse": ".types", } @@ -41,9 +34,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "GetMessagesResponse", - "ListAllMessagesRequestMessageType", - "ListMessagesRequestMessageType", - "ListMessagesResponse", -] +__all__ = ["ListAllMessagesRequestMessageType", "ListMessagesRequestMessageType"] diff --git a/src/wavix/sms_and_mms/messages/client.py b/src/wavix/sms_and_mms/messages/client.py index d68e0dc..ad7fffe 100644 --- a/src/wavix/sms_and_mms/messages/client.py +++ b/src/wavix/sms_and_mms/messages/client.py @@ -1,17 +1,18 @@ # This file was auto-generated by Fern from our API Definition. +import datetime as dt import typing from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions from ...types.message_body import MessageBody from ...types.message_delivery_status import MessageDeliveryStatus +from ...types.message_list_response import MessageListResponse +from ...types.message_response import MessageResponse from ...types.send_messages_response import SendMessagesResponse from .raw_client import AsyncRawMessagesClient, RawMessagesClient -from .types.get_messages_response import GetMessagesResponse from .types.list_all_messages_request_message_type import ListAllMessagesRequestMessageType from .types.list_messages_request_message_type import ListMessagesRequestMessageType -from .types.list_messages_response import ListMessagesResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -36,8 +37,8 @@ def list( self, *, type: str, - sent_after: typing.Optional[str] = None, - sent_before: typing.Optional[str] = None, + sent_after: typing.Optional[dt.date] = None, + sent_before: typing.Optional[dt.date] = None, from_: typing.Optional[str] = None, to: typing.Optional[str] = None, status: typing.Optional[MessageDeliveryStatus] = None, @@ -46,7 +47,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListMessagesResponse: + ) -> MessageListResponse: """ Returns a paginated list of SMS and MMS messages for the authenticated account, filtered by direction, date, and other criteria. @@ -55,10 +56,10 @@ def list( type : str Filters messages by direction. One of `inbound` (messages received by the account) or `outbound` (messages sent by the account). - sent_after : typing.Optional[str] + sent_after : typing.Optional[dt.date] Returns messages sent on or after this date, in `YYYY-MM-DD` format. - sent_before : typing.Optional[str] + sent_before : typing.Optional[dt.date] Returns messages sent on or before this date, in `YYYY-MM-DD` format. from_ : typing.Optional[str] @@ -87,19 +88,25 @@ def list( Returns ------- - ListMessagesResponse + MessageListResponse Returns a paginated list of messages. Examples -------- + import datetime + from wavix import Wavix client = Wavix( token="YOUR_TOKEN", ) client.sms_and_mms.messages.list( - sent_after="2023-04-10", - sent_before="2023-04-13", + sent_after=datetime.date.fromisoformat( + "2023-04-10", + ), + sent_before=datetime.date.fromisoformat( + "2023-04-13", + ), type="outbound", from_="15072429497", to="16419252149", @@ -135,8 +142,7 @@ def send( request_options: typing.Optional[RequestOptions] = None, ) -> SendMessagesResponse: """ - Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. - **Rate limit**: 20 messages per phone number in 24 hours. + Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. The recipient must be opted in to receive messages from the account; sending to an opted-out number fails. Parameters ---------- @@ -194,7 +200,7 @@ def send( ) return _response.data - def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetMessagesResponse: + def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> MessageResponse: """ Returns the SMS or MMS message identified by `id`, including its delivery status and content. @@ -208,7 +214,7 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non Returns ------- - GetMessagesResponse + MessageResponse Returns the message. Examples @@ -324,8 +330,8 @@ async def list( self, *, type: str, - sent_after: typing.Optional[str] = None, - sent_before: typing.Optional[str] = None, + sent_after: typing.Optional[dt.date] = None, + sent_before: typing.Optional[dt.date] = None, from_: typing.Optional[str] = None, to: typing.Optional[str] = None, status: typing.Optional[MessageDeliveryStatus] = None, @@ -334,7 +340,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListMessagesResponse: + ) -> MessageListResponse: """ Returns a paginated list of SMS and MMS messages for the authenticated account, filtered by direction, date, and other criteria. @@ -343,10 +349,10 @@ async def list( type : str Filters messages by direction. One of `inbound` (messages received by the account) or `outbound` (messages sent by the account). - sent_after : typing.Optional[str] + sent_after : typing.Optional[dt.date] Returns messages sent on or after this date, in `YYYY-MM-DD` format. - sent_before : typing.Optional[str] + sent_before : typing.Optional[dt.date] Returns messages sent on or before this date, in `YYYY-MM-DD` format. from_ : typing.Optional[str] @@ -375,12 +381,13 @@ async def list( Returns ------- - ListMessagesResponse + MessageListResponse Returns a paginated list of messages. Examples -------- import asyncio + import datetime from wavix import AsyncWavix @@ -391,8 +398,12 @@ async def list( async def main() -> None: await client.sms_and_mms.messages.list( - sent_after="2023-04-10", - sent_before="2023-04-13", + sent_after=datetime.date.fromisoformat( + "2023-04-10", + ), + sent_before=datetime.date.fromisoformat( + "2023-04-13", + ), type="outbound", from_="15072429497", to="16419252149", @@ -431,8 +442,7 @@ async def send( request_options: typing.Optional[RequestOptions] = None, ) -> SendMessagesResponse: """ - Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. - **Rate limit**: 20 messages per phone number in 24 hours. + Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. The recipient must be opted in to receive messages from the account; sending to an opted-out number fails. Parameters ---------- @@ -498,7 +508,7 @@ async def main() -> None: ) return _response.data - async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetMessagesResponse: + async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> MessageResponse: """ Returns the SMS or MMS message identified by `id`, including its delivery status and content. @@ -512,7 +522,7 @@ async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] Returns ------- - GetMessagesResponse + MessageResponse Returns the message. Examples diff --git a/src/wavix/sms_and_mms/messages/raw_client.py b/src/wavix/sms_and_mms/messages/raw_client.py index 2b73f29..963a128 100644 --- a/src/wavix/sms_and_mms/messages/raw_client.py +++ b/src/wavix/sms_and_mms/messages/raw_client.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. +import datetime as dt import typing from json.decoder import JSONDecodeError @@ -14,13 +15,17 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.message_body import MessageBody from ...types.message_delivery_status import MessageDeliveryStatus +from ...types.message_list_response import MessageListResponse +from ...types.message_response import MessageResponse from ...types.send_messages_response import SendMessagesResponse -from .types.get_messages_response import GetMessagesResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from .types.list_all_messages_request_message_type import ListAllMessagesRequestMessageType from .types.list_messages_request_message_type import ListMessagesRequestMessageType -from .types.list_messages_response import ListMessagesResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -35,8 +40,8 @@ def list( self, *, type: str, - sent_after: typing.Optional[str] = None, - sent_before: typing.Optional[str] = None, + sent_after: typing.Optional[dt.date] = None, + sent_before: typing.Optional[dt.date] = None, from_: typing.Optional[str] = None, to: typing.Optional[str] = None, status: typing.Optional[MessageDeliveryStatus] = None, @@ -45,7 +50,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListMessagesResponse]: + ) -> HttpResponse[MessageListResponse]: """ Returns a paginated list of SMS and MMS messages for the authenticated account, filtered by direction, date, and other criteria. @@ -54,10 +59,10 @@ def list( type : str Filters messages by direction. One of `inbound` (messages received by the account) or `outbound` (messages sent by the account). - sent_after : typing.Optional[str] + sent_after : typing.Optional[dt.date] Returns messages sent on or after this date, in `YYYY-MM-DD` format. - sent_before : typing.Optional[str] + sent_before : typing.Optional[dt.date] Returns messages sent on or before this date, in `YYYY-MM-DD` format. from_ : typing.Optional[str] @@ -86,15 +91,15 @@ def list( Returns ------- - HttpResponse[ListMessagesResponse] + HttpResponse[MessageListResponse] Returns a paginated list of messages. """ _response = self._client_wrapper.httpx_client.request( "v3/messages", method="GET", params={ - "sent_after": sent_after, - "sent_before": sent_before, + "sent_after": str(sent_after) if sent_after is not None else None, + "sent_before": str(sent_before) if sent_before is not None else None, "type": type, "from": from_, "to": to, @@ -109,9 +114,9 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListMessagesResponse, + MessageListResponse, parse_obj_as( - type_=ListMessagesResponse, # type: ignore + type_=MessageListResponse, # type: ignore object_=_response.json(), ), ) @@ -127,6 +132,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -159,8 +175,7 @@ def send( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[SendMessagesResponse]: """ - Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. - **Rate limit**: 20 messages per phone number in 24 hours. + Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. The recipient must be opted in to receive messages from the account; sending to an opted-out number fails. Parameters ---------- @@ -229,6 +244,17 @@ def send( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -240,6 +266,39 @@ def send( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -249,9 +308,7 @@ def send( ) 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[GetMessagesResponse]: + def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[MessageResponse]: """ Returns the SMS or MMS message identified by `id`, including its delivery status and content. @@ -265,7 +322,7 @@ def get( Returns ------- - HttpResponse[GetMessagesResponse] + HttpResponse[MessageResponse] Returns the message. """ _response = self._client_wrapper.httpx_client.request( @@ -276,13 +333,35 @@ def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetMessagesResponse, + MessageResponse, parse_obj_as( - type_=GetMessagesResponse, # type: ignore + type_=MessageResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -389,6 +468,17 @@ def list_all( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -418,8 +508,8 @@ async def list( self, *, type: str, - sent_after: typing.Optional[str] = None, - sent_before: typing.Optional[str] = None, + sent_after: typing.Optional[dt.date] = None, + sent_before: typing.Optional[dt.date] = None, from_: typing.Optional[str] = None, to: typing.Optional[str] = None, status: typing.Optional[MessageDeliveryStatus] = None, @@ -428,7 +518,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListMessagesResponse]: + ) -> AsyncHttpResponse[MessageListResponse]: """ Returns a paginated list of SMS and MMS messages for the authenticated account, filtered by direction, date, and other criteria. @@ -437,10 +527,10 @@ async def list( type : str Filters messages by direction. One of `inbound` (messages received by the account) or `outbound` (messages sent by the account). - sent_after : typing.Optional[str] + sent_after : typing.Optional[dt.date] Returns messages sent on or after this date, in `YYYY-MM-DD` format. - sent_before : typing.Optional[str] + sent_before : typing.Optional[dt.date] Returns messages sent on or before this date, in `YYYY-MM-DD` format. from_ : typing.Optional[str] @@ -469,15 +559,15 @@ async def list( Returns ------- - AsyncHttpResponse[ListMessagesResponse] + AsyncHttpResponse[MessageListResponse] Returns a paginated list of messages. """ _response = await self._client_wrapper.httpx_client.request( "v3/messages", method="GET", params={ - "sent_after": sent_after, - "sent_before": sent_before, + "sent_after": str(sent_after) if sent_after is not None else None, + "sent_before": str(sent_before) if sent_before is not None else None, "type": type, "from": from_, "to": to, @@ -492,9 +582,9 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListMessagesResponse, + MessageListResponse, parse_obj_as( - type_=ListMessagesResponse, # type: ignore + type_=MessageListResponse, # type: ignore object_=_response.json(), ), ) @@ -510,6 +600,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -542,8 +643,7 @@ async def send( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[SendMessagesResponse]: """ - Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. - **Rate limit**: 20 messages per phone number in 24 hours. + Sends an SMS or MMS message. MMS is supported for U.S. numbers only. Track delivery using the returned `message_id` and the message status callback. The recipient must be opted in to receive messages from the account; sending to an opted-out number fails. Parameters ---------- @@ -612,6 +712,17 @@ async def send( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -623,6 +734,39 @@ async def send( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -634,7 +778,7 @@ async def send( async def get( self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[GetMessagesResponse]: + ) -> AsyncHttpResponse[MessageResponse]: """ Returns the SMS or MMS message identified by `id`, including its delivery status and content. @@ -648,7 +792,7 @@ async def get( Returns ------- - AsyncHttpResponse[GetMessagesResponse] + AsyncHttpResponse[MessageResponse] Returns the message. """ _response = await self._client_wrapper.httpx_client.request( @@ -659,13 +803,35 @@ async def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetMessagesResponse, + MessageResponse, parse_obj_as( - type_=GetMessagesResponse, # type: ignore + type_=MessageResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -772,6 +938,17 @@ async def list_all( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/sms_and_mms/messages/types/__init__.py b/src/wavix/sms_and_mms/messages/types/__init__.py index 0ca11f7..cfc3a37 100644 --- a/src/wavix/sms_and_mms/messages/types/__init__.py +++ b/src/wavix/sms_and_mms/messages/types/__init__.py @@ -6,15 +6,11 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .get_messages_response import GetMessagesResponse from .list_all_messages_request_message_type import ListAllMessagesRequestMessageType from .list_messages_request_message_type import ListMessagesRequestMessageType - from .list_messages_response import ListMessagesResponse _dynamic_imports: typing.Dict[str, str] = { - "GetMessagesResponse": ".get_messages_response", "ListAllMessagesRequestMessageType": ".list_all_messages_request_message_type", "ListMessagesRequestMessageType": ".list_messages_request_message_type", - "ListMessagesResponse": ".list_messages_response", } @@ -39,9 +35,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "GetMessagesResponse", - "ListAllMessagesRequestMessageType", - "ListMessagesRequestMessageType", - "ListMessagesResponse", -] +__all__ = ["ListAllMessagesRequestMessageType", "ListMessagesRequestMessageType"] diff --git a/src/wavix/sms_and_mms/messages/types/get_messages_response.py b/src/wavix/sms_and_mms/messages/types/get_messages_response.py deleted file mode 100644 index 6651bbe..0000000 --- a/src/wavix/sms_and_mms/messages/types/get_messages_response.py +++ /dev/null @@ -1,97 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -import typing_extensions -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....core.serialization import FieldMetadata -from ....types.message_body import MessageBody -from ....types.message_delivery_status import MessageDeliveryStatus - - -class GetMessagesResponse(UniversalBaseModel): - message_id: str = pydantic.Field() - """ - Message ID. - """ - - message_type: str = pydantic.Field() - """ - Message type. Possible values are `sms`, `mms`. - """ - - from_: typing_extensions.Annotated[ - str, FieldMetadata(alias="from"), pydantic.Field(alias="from", description="Sender ID.") - ] - to: str = pydantic.Field() - """ - Recipient phone number. - """ - - direction: str = pydantic.Field() - """ - Message direction. Possible values are `outbound`, `inbound`. - """ - - mcc: typing.Optional[str] = pydantic.Field(default=None) - """ - Mobile country code. - """ - - mnc: typing.Optional[str] = pydantic.Field(default=None) - """ - Mobile network code. - """ - - message_body: MessageBody - tag: typing.Optional[str] = pydantic.Field(default=None) - """ - Tag to group messages, such as for a specific campaign. - """ - - status: MessageDeliveryStatus - segments: int = pydantic.Field() - """ - Number of SMS segments. Always 1 for MMS. - """ - - charge: str = pydantic.Field() - """ - Total charge for the message in USD. - """ - - submitted_at: str = pydantic.Field() - """ - Date and time the message was accepted in ISO 8601 format. - """ - - sent_at: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the message was sent in ISO 8601 format. For mobile-terminated messages only. - """ - - delivered_at: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the message was delivered in ISO 8601 format. Refers to DLR reception for mobile-terminated messages - or webhook relay for mobile-originated messages. - """ - - error_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Human-readable error message. - """ - - carrier_fees: typing.Optional[str] = pydantic.Field(default=None) - """ - Mobile carrier fees in USD. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/sms_and_mms/opt_outs/__init__.py b/src/wavix/sms_and_mms/opt_outs/__init__.py index 403e602..5cde020 100644 --- a/src/wavix/sms_and_mms/opt_outs/__init__.py +++ b/src/wavix/sms_and_mms/opt_outs/__init__.py @@ -2,33 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import CreateOptOutsResponse -_dynamic_imports: typing.Dict[str, str] = {"CreateOptOutsResponse": ".types"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["CreateOptOutsResponse"] diff --git a/src/wavix/sms_and_mms/opt_outs/client.py b/src/wavix/sms_and_mms/opt_outs/client.py index ae60a5a..8c87e96 100644 --- a/src/wavix/sms_and_mms/opt_outs/client.py +++ b/src/wavix/sms_and_mms/opt_outs/client.py @@ -7,8 +7,8 @@ from ...core.request_options import RequestOptions from ...types.opt_out import OptOut from ...types.opt_outs_list_response import OptOutsListResponse +from ...types.success_response import SuccessResponse from .raw_client import AsyncRawOptOutsClient, RawOptOutsClient -from .types.create_opt_outs_response import CreateOptOutsResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -102,9 +102,7 @@ def list( ) return _response.data - def create( - self, *, opt_out: OptOut, request_options: typing.Optional[RequestOptions] = None - ) -> CreateOptOutsResponse: + def create(self, *, opt_out: OptOut, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ Opts a phone number out of receiving messages from a Sender ID, a 10DLC campaign, or all outbound messages. @@ -117,7 +115,7 @@ def create( Returns ------- - CreateOptOutsResponse + SuccessResponse Returns a success confirmation. The opt-out is created. Examples @@ -235,7 +233,7 @@ async def main() -> None: async def create( self, *, opt_out: OptOut, request_options: typing.Optional[RequestOptions] = None - ) -> CreateOptOutsResponse: + ) -> SuccessResponse: """ Opts a phone number out of receiving messages from a Sender ID, a 10DLC campaign, or all outbound messages. @@ -248,7 +246,7 @@ async def create( Returns ------- - CreateOptOutsResponse + SuccessResponse Returns a success confirmation. The opt-out is created. Examples diff --git a/src/wavix/sms_and_mms/opt_outs/raw_client.py b/src/wavix/sms_and_mms/opt_outs/raw_client.py index 7fcd538..4b99c3f 100644 --- a/src/wavix/sms_and_mms/opt_outs/raw_client.py +++ b/src/wavix/sms_and_mms/opt_outs/raw_client.py @@ -14,10 +14,12 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.opt_out import OptOut from ...types.opt_outs_list_response import OptOutsListResponse -from .types.create_opt_outs_response import CreateOptOutsResponse +from ...types.success_response import SuccessResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -104,6 +106,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -137,7 +150,7 @@ def list( def create( self, *, opt_out: OptOut, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[CreateOptOutsResponse]: + ) -> HttpResponse[SuccessResponse]: """ Opts a phone number out of receiving messages from a Sender ID, a 10DLC campaign, or all outbound messages. @@ -150,7 +163,7 @@ def create( Returns ------- - HttpResponse[CreateOptOutsResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The opt-out is created. """ _response = self._client_wrapper.httpx_client.request( @@ -170,9 +183,9 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateOptOutsResponse, + SuccessResponse, parse_obj_as( - type_=CreateOptOutsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -188,6 +201,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -311,6 +335,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -344,7 +379,7 @@ async def list( async def create( self, *, opt_out: OptOut, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[CreateOptOutsResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Opts a phone number out of receiving messages from a Sender ID, a 10DLC campaign, or all outbound messages. @@ -357,7 +392,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateOptOutsResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The opt-out is created. """ _response = await self._client_wrapper.httpx_client.request( @@ -377,9 +412,9 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateOptOutsResponse, + SuccessResponse, parse_obj_as( - type_=CreateOptOutsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -395,6 +430,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/sms_and_mms/opt_outs/types/__init__.py b/src/wavix/sms_and_mms/opt_outs/types/__init__.py deleted file mode 100644 index b744285..0000000 --- a/src/wavix/sms_and_mms/opt_outs/types/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .create_opt_outs_response import CreateOptOutsResponse -_dynamic_imports: typing.Dict[str, str] = {"CreateOptOutsResponse": ".create_opt_outs_response"} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["CreateOptOutsResponse"] diff --git a/src/wavix/sms_and_mms/opt_outs/types/create_opt_outs_response.py b/src/wavix/sms_and_mms/opt_outs/types/create_opt_outs_response.py deleted file mode 100644 index 08da10a..0000000 --- a/src/wavix/sms_and_mms/opt_outs/types/create_opt_outs_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class CreateOptOutsResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/sms_and_mms/sender_ids/__init__.py b/src/wavix/sms_and_mms/sender_ids/__init__.py index e8e21be..f8c9795 100644 --- a/src/wavix/sms_and_mms/sender_ids/__init__.py +++ b/src/wavix/sms_and_mms/sender_ids/__init__.py @@ -6,9 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import DeleteSenderIdsResponse, SenderIdCreateRequestMonthlyVolume, SenderIdCreateRequestUsecase + from .types import SenderIdCreateRequestMonthlyVolume, SenderIdCreateRequestUsecase _dynamic_imports: typing.Dict[str, str] = { - "DeleteSenderIdsResponse": ".types", "SenderIdCreateRequestMonthlyVolume": ".types", "SenderIdCreateRequestUsecase": ".types", } @@ -35,4 +34,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["DeleteSenderIdsResponse", "SenderIdCreateRequestMonthlyVolume", "SenderIdCreateRequestUsecase"] +__all__ = ["SenderIdCreateRequestMonthlyVolume", "SenderIdCreateRequestUsecase"] diff --git a/src/wavix/sms_and_mms/sender_ids/client.py b/src/wavix/sms_and_mms/sender_ids/client.py index 7a102fb..b63cbae 100644 --- a/src/wavix/sms_and_mms/sender_ids/client.py +++ b/src/wavix/sms_and_mms/sender_ids/client.py @@ -8,8 +8,8 @@ from ...types.sender_id_list_response import SenderIdListResponse from ...types.sender_id_response import SenderIdResponse from ...types.sender_id_type import SenderIdType +from ...types.success_response import SuccessResponse from .raw_client import AsyncRawSenderIdsClient, RawSenderIdsClient -from .types.delete_sender_ids_response import DeleteSenderIdsResponse from .types.sender_id_create_request_monthly_volume import SenderIdCreateRequestMonthlyVolume from .types.sender_id_create_request_usecase import SenderIdCreateRequestUsecase @@ -70,7 +70,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> SenderIdDetails: """ - Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. + Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. Registering a Sender ID incurs a recurring monthly fee, billed to the account balance. Parameters ---------- @@ -155,7 +155,7 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non _response = self._raw_client.get(id, request_options=request_options) return _response.data - def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> DeleteSenderIdsResponse: + def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ Deletes the Sender ID identified by `id`. Deletion is permanent. @@ -169,7 +169,7 @@ def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = Returns ------- - DeleteSenderIdsResponse + SuccessResponse Returns a success confirmation. The Sender ID is deleted. Examples @@ -248,7 +248,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> SenderIdDetails: """ - Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. + Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. Registering a Sender ID incurs a recurring monthly fee, billed to the account balance. Parameters ---------- @@ -349,9 +349,7 @@ async def main() -> None: _response = await self._raw_client.get(id, request_options=request_options) return _response.data - async def delete( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteSenderIdsResponse: + async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ Deletes the Sender ID identified by `id`. Deletion is permanent. @@ -365,7 +363,7 @@ async def delete( Returns ------- - DeleteSenderIdsResponse + SuccessResponse Returns a success confirmation. The Sender ID is deleted. Examples diff --git a/src/wavix/sms_and_mms/sender_ids/raw_client.py b/src/wavix/sms_and_mms/sender_ids/raw_client.py index c338aa7..3b1ef35 100644 --- a/src/wavix/sms_and_mms/sender_ids/raw_client.py +++ b/src/wavix/sms_and_mms/sender_ids/raw_client.py @@ -13,12 +13,14 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.sender_id_details import SenderIdDetails from ...types.sender_id_list_response import SenderIdListResponse from ...types.sender_id_response import SenderIdResponse from ...types.sender_id_type import SenderIdType -from .types.delete_sender_ids_response import DeleteSenderIdsResponse +from ...types.success_response import SuccessResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from .types.sender_id_create_request_monthly_volume import SenderIdCreateRequestMonthlyVolume from .types.sender_id_create_request_usecase import SenderIdCreateRequestUsecase from pydantic import ValidationError @@ -60,6 +62,28 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Ht ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -92,7 +116,7 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[SenderIdDetails]: """ - Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. + Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. Registering a Sender ID incurs a recurring monthly fee, billed to the account balance. Parameters ---------- @@ -159,6 +183,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -170,6 +205,28 @@ def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -213,6 +270,28 @@ def get( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -246,7 +325,7 @@ def get( def delete( self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[DeleteSenderIdsResponse]: + ) -> HttpResponse[SuccessResponse]: """ Deletes the Sender ID identified by `id`. Deletion is permanent. @@ -260,7 +339,7 @@ def delete( Returns ------- - HttpResponse[DeleteSenderIdsResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The Sender ID is deleted. """ _response = self._client_wrapper.httpx_client.request( @@ -271,13 +350,35 @@ def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteSenderIdsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteSenderIdsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -356,6 +457,28 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -388,7 +511,7 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[SenderIdDetails]: """ - Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. + Creates a Sender ID. Use the 10DLC API to create Sender IDs in the US. Registering a Sender ID incurs a recurring monthly fee, billed to the account balance. Parameters ---------- @@ -455,6 +578,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -466,6 +600,28 @@ async def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -509,6 +665,28 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -542,7 +720,7 @@ async def get( async def delete( self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[DeleteSenderIdsResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Deletes the Sender ID identified by `id`. Deletion is permanent. @@ -556,7 +734,7 @@ async def delete( Returns ------- - AsyncHttpResponse[DeleteSenderIdsResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The Sender ID is deleted. """ _response = await self._client_wrapper.httpx_client.request( @@ -567,13 +745,35 @@ async def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteSenderIdsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteSenderIdsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/sms_and_mms/sender_ids/types/__init__.py b/src/wavix/sms_and_mms/sender_ids/types/__init__.py index cb12fd2..1c8e6ad 100644 --- a/src/wavix/sms_and_mms/sender_ids/types/__init__.py +++ b/src/wavix/sms_and_mms/sender_ids/types/__init__.py @@ -6,11 +6,9 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .delete_sender_ids_response import DeleteSenderIdsResponse from .sender_id_create_request_monthly_volume import SenderIdCreateRequestMonthlyVolume from .sender_id_create_request_usecase import SenderIdCreateRequestUsecase _dynamic_imports: typing.Dict[str, str] = { - "DeleteSenderIdsResponse": ".delete_sender_ids_response", "SenderIdCreateRequestMonthlyVolume": ".sender_id_create_request_monthly_volume", "SenderIdCreateRequestUsecase": ".sender_id_create_request_usecase", } @@ -37,4 +35,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["DeleteSenderIdsResponse", "SenderIdCreateRequestMonthlyVolume", "SenderIdCreateRequestUsecase"] +__all__ = ["SenderIdCreateRequestMonthlyVolume", "SenderIdCreateRequestUsecase"] diff --git a/src/wavix/sms_and_mms/sender_ids/types/delete_sender_ids_response.py b/src/wavix/sms_and_mms/sender_ids/types/delete_sender_ids_response.py deleted file mode 100644 index 365c8fb..0000000 --- a/src/wavix/sms_and_mms/sender_ids/types/delete_sender_ids_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class DeleteSenderIdsResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/speech_analytics/__init__.py b/src/wavix/speech_analytics/__init__.py index 1a4f19a..13f075c 100644 --- a/src/wavix/speech_analytics/__init__.py +++ b/src/wavix/speech_analytics/__init__.py @@ -6,20 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import ( - CreateSpeechAnalyticsResponse, - GetSpeechAnalyticsResponse, - GetSpeechAnalyticsResponseLanguage, - GetSpeechAnalyticsResponseStatus, - ) from . import file -_dynamic_imports: typing.Dict[str, str] = { - "CreateSpeechAnalyticsResponse": ".types", - "GetSpeechAnalyticsResponse": ".types", - "GetSpeechAnalyticsResponseLanguage": ".types", - "GetSpeechAnalyticsResponseStatus": ".types", - "file": ".file", -} +_dynamic_imports: typing.Dict[str, str] = {"file": ".file"} def __getattr__(attr_name: str) -> typing.Any: @@ -43,10 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "CreateSpeechAnalyticsResponse", - "GetSpeechAnalyticsResponse", - "GetSpeechAnalyticsResponseLanguage", - "GetSpeechAnalyticsResponseStatus", - "file", -] +__all__ = ["file"] diff --git a/src/wavix/speech_analytics/client.py b/src/wavix/speech_analytics/client.py index 2f55c65..b629c0f 100644 --- a/src/wavix/speech_analytics/client.py +++ b/src/wavix/speech_analytics/client.py @@ -7,10 +7,10 @@ from .. import core from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.request_options import RequestOptions +from ..types.file_transcription_response import FileTranscriptionResponse +from ..types.submit_file_transcription_response import SubmitFileTranscriptionResponse from ..types.success_response import SuccessResponse from .raw_client import AsyncRawSpeechAnalyticsClient, RawSpeechAnalyticsClient -from .types.create_speech_analytics_response import CreateSpeechAnalyticsResponse -from .types.get_speech_analytics_response import GetSpeechAnalyticsResponse if typing.TYPE_CHECKING: from .file.client import AsyncFileClient, FileClient @@ -42,7 +42,7 @@ def create( callback_url: str, insights: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateSpeechAnalyticsResponse: + ) -> SubmitFileTranscriptionResponse: """ Uploads an audio file for transcription. Transcription is asynchronous; Wavix sends a POST callback to `callback_url` when it completes, including the `request_id` returned by this request. @@ -75,7 +75,7 @@ def create( Returns ------- - CreateSpeechAnalyticsResponse + SubmitFileTranscriptionResponse Returns the transcription `request_id` for the uploaded file. Examples @@ -96,7 +96,7 @@ def create( def get( self, request_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> GetSpeechAnalyticsResponse: + ) -> FileTranscriptionResponse: """ Returns the transcription for the request identified by `request_id`, including transcript, speaker turns, and insights when available. @@ -110,7 +110,7 @@ def get( Returns ------- - GetSpeechAnalyticsResponse + FileTranscriptionResponse Returns the completed transcription. Examples @@ -207,7 +207,7 @@ async def create( callback_url: str, insights: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateSpeechAnalyticsResponse: + ) -> SubmitFileTranscriptionResponse: """ Uploads an audio file for transcription. Transcription is asynchronous; Wavix sends a POST callback to `callback_url` when it completes, including the `request_id` returned by this request. @@ -240,7 +240,7 @@ async def create( Returns ------- - CreateSpeechAnalyticsResponse + SubmitFileTranscriptionResponse Returns the transcription `request_id` for the uploaded file. Examples @@ -269,7 +269,7 @@ async def main() -> None: async def get( self, request_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> GetSpeechAnalyticsResponse: + ) -> FileTranscriptionResponse: """ Returns the transcription for the request identified by `request_id`, including transcript, speaker turns, and insights when available. @@ -283,7 +283,7 @@ async def get( Returns ------- - GetSpeechAnalyticsResponse + FileTranscriptionResponse Returns the completed transcription. Examples diff --git a/src/wavix/speech_analytics/file/raw_client.py b/src/wavix/speech_analytics/file/raw_client.py index 7bb4a50..d540a62 100644 --- a/src/wavix/speech_analytics/file/raw_client.py +++ b/src/wavix/speech_analytics/file/raw_client.py @@ -11,7 +11,11 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -53,6 +57,39 @@ def _stream() -> HttpResponse[typing.Iterator[bytes]]: response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) ) _response.read() + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -120,6 +157,39 @@ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), ) await _response.aread() + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), diff --git a/src/wavix/speech_analytics/raw_client.py b/src/wavix/speech_analytics/raw_client.py index 82147b4..63b8023 100644 --- a/src/wavix/speech_analytics/raw_client.py +++ b/src/wavix/speech_analytics/raw_client.py @@ -12,11 +12,14 @@ from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.bad_request_error import BadRequestError +from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError from ..errors.unprocessable_entity_error import UnprocessableEntityError +from ..types.file_transcription_response import FileTranscriptionResponse +from ..types.submit_file_transcription_response import SubmitFileTranscriptionResponse from ..types.success_response import SuccessResponse -from .types.create_speech_analytics_response import CreateSpeechAnalyticsResponse -from .types.get_speech_analytics_response import GetSpeechAnalyticsResponse +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -34,7 +37,7 @@ def create( callback_url: str, insights: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[CreateSpeechAnalyticsResponse]: + ) -> HttpResponse[SubmitFileTranscriptionResponse]: """ Uploads an audio file for transcription. Transcription is asynchronous; Wavix sends a POST callback to `callback_url` when it completes, including the `request_id` returned by this request. @@ -67,7 +70,7 @@ def create( Returns ------- - HttpResponse[CreateSpeechAnalyticsResponse] + HttpResponse[SubmitFileTranscriptionResponse] Returns the transcription `request_id` for the uploaded file. """ _response = self._client_wrapper.httpx_client.request( @@ -87,9 +90,9 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateSpeechAnalyticsResponse, + SubmitFileTranscriptionResponse, parse_obj_as( - type_=CreateSpeechAnalyticsResponse, # type: ignore + type_=SubmitFileTranscriptionResponse, # type: ignore object_=_response.json(), ), ) @@ -105,6 +108,28 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), @@ -127,7 +152,7 @@ def create( def get( self, request_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[GetSpeechAnalyticsResponse]: + ) -> HttpResponse[FileTranscriptionResponse]: """ Returns the transcription for the request identified by `request_id`, including transcript, speaker turns, and insights when available. @@ -141,7 +166,7 @@ def get( Returns ------- - HttpResponse[GetSpeechAnalyticsResponse] + HttpResponse[FileTranscriptionResponse] Returns the completed transcription. """ _response = self._client_wrapper.httpx_client.request( @@ -152,13 +177,46 @@ def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetSpeechAnalyticsResponse, + FileTranscriptionResponse, parse_obj_as( - type_=GetSpeechAnalyticsResponse, # type: ignore + type_=FileTranscriptionResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -243,6 +301,28 @@ def retranscribe( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -286,7 +366,7 @@ async def create( callback_url: str, insights: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[CreateSpeechAnalyticsResponse]: + ) -> AsyncHttpResponse[SubmitFileTranscriptionResponse]: """ Uploads an audio file for transcription. Transcription is asynchronous; Wavix sends a POST callback to `callback_url` when it completes, including the `request_id` returned by this request. @@ -319,7 +399,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateSpeechAnalyticsResponse] + AsyncHttpResponse[SubmitFileTranscriptionResponse] Returns the transcription `request_id` for the uploaded file. """ _response = await self._client_wrapper.httpx_client.request( @@ -339,9 +419,9 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateSpeechAnalyticsResponse, + SubmitFileTranscriptionResponse, parse_obj_as( - type_=CreateSpeechAnalyticsResponse, # type: ignore + type_=SubmitFileTranscriptionResponse, # type: ignore object_=_response.json(), ), ) @@ -357,6 +437,28 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), @@ -379,7 +481,7 @@ async def create( async def get( self, request_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[GetSpeechAnalyticsResponse]: + ) -> AsyncHttpResponse[FileTranscriptionResponse]: """ Returns the transcription for the request identified by `request_id`, including transcript, speaker turns, and insights when available. @@ -393,7 +495,7 @@ async def get( Returns ------- - AsyncHttpResponse[GetSpeechAnalyticsResponse] + AsyncHttpResponse[FileTranscriptionResponse] Returns the completed transcription. """ _response = await self._client_wrapper.httpx_client.request( @@ -404,13 +506,46 @@ async def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetSpeechAnalyticsResponse, + FileTranscriptionResponse, parse_obj_as( - type_=GetSpeechAnalyticsResponse, # type: ignore + type_=FileTranscriptionResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -495,6 +630,28 @@ async def retranscribe( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), diff --git a/src/wavix/speech_analytics/types/__init__.py b/src/wavix/speech_analytics/types/__init__.py deleted file mode 100644 index 5a1f760..0000000 --- a/src/wavix/speech_analytics/types/__init__.py +++ /dev/null @@ -1,47 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .create_speech_analytics_response import CreateSpeechAnalyticsResponse - from .get_speech_analytics_response import GetSpeechAnalyticsResponse - from .get_speech_analytics_response_language import GetSpeechAnalyticsResponseLanguage - from .get_speech_analytics_response_status import GetSpeechAnalyticsResponseStatus -_dynamic_imports: typing.Dict[str, str] = { - "CreateSpeechAnalyticsResponse": ".create_speech_analytics_response", - "GetSpeechAnalyticsResponse": ".get_speech_analytics_response", - "GetSpeechAnalyticsResponseLanguage": ".get_speech_analytics_response_language", - "GetSpeechAnalyticsResponseStatus": ".get_speech_analytics_response_status", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = [ - "CreateSpeechAnalyticsResponse", - "GetSpeechAnalyticsResponse", - "GetSpeechAnalyticsResponseLanguage", - "GetSpeechAnalyticsResponseStatus", -] diff --git a/src/wavix/speech_analytics/types/get_speech_analytics_response.py b/src/wavix/speech_analytics/types/get_speech_analytics_response.py deleted file mode 100644 index 4565da2..0000000 --- a/src/wavix/speech_analytics/types/get_speech_analytics_response.py +++ /dev/null @@ -1,77 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ...types.file_transcript_response import FileTranscriptResponse -from ...types.file_transcript_turn import FileTranscriptTurn -from .get_speech_analytics_response_language import GetSpeechAnalyticsResponseLanguage -from .get_speech_analytics_response_status import GetSpeechAnalyticsResponseStatus - - -class GetSpeechAnalyticsResponse(UniversalBaseModel): - transcript: typing.Optional[FileTranscriptResponse] = pydantic.Field(default=None) - """ - Complete transcription text attributed to each channel. - """ - - turns: typing.Optional[typing.List[FileTranscriptTurn]] = pydantic.Field(default=None) - """ - List of transcription turns, including speaker attribution, timestamps, and sentiment. - """ - - request_id: str = pydantic.Field() - """ - Transcription request ID. - """ - - language: typing.Optional[GetSpeechAnalyticsResponseLanguage] = pydantic.Field(default=None) - """ - Transcription language. - """ - - duration: typing.Optional[int] = pydantic.Field(default=None) - """ - File duration in seconds. - """ - - charge: str = pydantic.Field() - """ - Total transcription charge in USD. - """ - - status: GetSpeechAnalyticsResponseStatus = pydantic.Field() - """ - Transcription status. Possible values are `completed`, `failed`. - """ - - transcription_date: dt.datetime = pydantic.Field() - """ - Date and time of the transcription in ISO 8601 format. - """ - - transcription_score: typing.Optional[str] = pydantic.Field(default=None) - """ - Conversation sentiment score. Scores from 1.0 to 3.0 are negative; scores from 4.0 to 5.0 are positive. - """ - - transcription_summary: typing.Optional[str] = pydantic.Field(default=None) - """ - Transcription summary. - """ - - original_file: str = pydantic.Field() - """ - Uploaded file URL. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/speech_analytics/types/get_speech_analytics_response_language.py b/src/wavix/speech_analytics/types/get_speech_analytics_response_language.py deleted file mode 100644 index 41bbedf..0000000 --- a/src/wavix/speech_analytics/types/get_speech_analytics_response_language.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -GetSpeechAnalyticsResponseLanguage = typing.Union[typing.Literal["en", "de", "es", "fr", "it"], typing.Any] diff --git a/src/wavix/speech_analytics/types/get_speech_analytics_response_status.py b/src/wavix/speech_analytics/types/get_speech_analytics_response_status.py deleted file mode 100644 index 49a3509..0000000 --- a/src/wavix/speech_analytics/types/get_speech_analytics_response_status.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -GetSpeechAnalyticsResponseStatus = typing.Union[typing.Literal["completed", "failed"], typing.Any] diff --git a/src/wavix/sub_accounts/client.py b/src/wavix/sub_accounts/client.py index 3fdbdc5..bb80b37 100644 --- a/src/wavix/sub_accounts/client.py +++ b/src/wavix/sub_accounts/client.py @@ -41,6 +41,8 @@ def list( self, *, status: typing.Optional[ListSubAccountsRequestStatus] = None, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SubAccountsListResponse: """ @@ -51,6 +53,12 @@ def list( status : typing.Optional[ListSubAccountsRequestStatus] Filters sub-accounts by status. One of `enabled` (the sub-account is active) or `disabled` (the sub-account is suspended). + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -68,7 +76,7 @@ def list( ) client.sub_accounts.list() """ - _response = self._raw_client.list(status=status, request_options=request_options) + _response = self._raw_client.list(status=status, page=page, per_page=per_page, request_options=request_options) return _response.data def create( @@ -153,7 +161,7 @@ def update( self, id: int, *, - name: str, + name: typing.Optional[str] = OMIT, status: typing.Optional[SubAccountsUpdateRequestStatus] = OMIT, default_destinations: typing.Optional[SubAccountsUpdateRequestDefaultDestinations] = OMIT, request_options: typing.Optional[RequestOptions] = None, @@ -166,7 +174,7 @@ def update( id : int The unique ID of the sub-account. - name : str + name : typing.Optional[str] Sub-account name. status : typing.Optional[SubAccountsUpdateRequestStatus] @@ -236,6 +244,8 @@ async def list( self, *, status: typing.Optional[ListSubAccountsRequestStatus] = None, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SubAccountsListResponse: """ @@ -246,6 +256,12 @@ async def list( status : typing.Optional[ListSubAccountsRequestStatus] Filters sub-accounts by status. One of `enabled` (the sub-account is active) or `disabled` (the sub-account is suspended). + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -271,7 +287,9 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._raw_client.list(status=status, request_options=request_options) + _response = await self._raw_client.list( + status=status, page=page, per_page=per_page, request_options=request_options + ) return _response.data async def create( @@ -372,7 +390,7 @@ async def update( self, id: int, *, - name: str, + name: typing.Optional[str] = OMIT, status: typing.Optional[SubAccountsUpdateRequestStatus] = OMIT, default_destinations: typing.Optional[SubAccountsUpdateRequestDefaultDestinations] = OMIT, request_options: typing.Optional[RequestOptions] = None, @@ -385,7 +403,7 @@ async def update( id : int The unique ID of the sub-account. - name : str + name : typing.Optional[str] Sub-account name. status : typing.Optional[SubAccountsUpdateRequestStatus] diff --git a/src/wavix/sub_accounts/raw_client.py b/src/wavix/sub_accounts/raw_client.py index e7389dc..f1a34b7 100644 --- a/src/wavix/sub_accounts/raw_client.py +++ b/src/wavix/sub_accounts/raw_client.py @@ -37,6 +37,8 @@ def list( self, *, status: typing.Optional[ListSubAccountsRequestStatus] = None, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[SubAccountsListResponse]: """ @@ -47,6 +49,12 @@ def list( status : typing.Optional[ListSubAccountsRequestStatus] Filters sub-accounts by status. One of `enabled` (the sub-account is active) or `disabled` (the sub-account is suspended). + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -60,6 +68,8 @@ def list( method="GET", params={ "status": status, + "page": page, + "per_page": per_page, }, request_options=request_options, ) @@ -168,6 +178,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -233,6 +254,17 @@ def get( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -279,7 +311,7 @@ def update( self, id: int, *, - name: str, + name: typing.Optional[str] = OMIT, status: typing.Optional[SubAccountsUpdateRequestStatus] = OMIT, default_destinations: typing.Optional[SubAccountsUpdateRequestDefaultDestinations] = OMIT, request_options: typing.Optional[RequestOptions] = None, @@ -292,7 +324,7 @@ def update( id : int The unique ID of the sub-account. - name : str + name : typing.Optional[str] Sub-account name. status : typing.Optional[SubAccountsUpdateRequestStatus] @@ -410,6 +442,8 @@ async def list( self, *, status: typing.Optional[ListSubAccountsRequestStatus] = None, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[SubAccountsListResponse]: """ @@ -420,6 +454,12 @@ async def list( status : typing.Optional[ListSubAccountsRequestStatus] Filters sub-accounts by status. One of `enabled` (the sub-account is active) or `disabled` (the sub-account is suspended). + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -433,6 +473,8 @@ async def list( method="GET", params={ "status": status, + "page": page, + "per_page": per_page, }, request_options=request_options, ) @@ -541,6 +583,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -606,6 +659,17 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -652,7 +716,7 @@ async def update( self, id: int, *, - name: str, + name: typing.Optional[str] = OMIT, status: typing.Optional[SubAccountsUpdateRequestStatus] = OMIT, default_destinations: typing.Optional[SubAccountsUpdateRequestDefaultDestinations] = OMIT, request_options: typing.Optional[RequestOptions] = None, @@ -665,7 +729,7 @@ async def update( id : int The unique ID of the sub-account. - name : str + name : typing.Optional[str] Sub-account name. status : typing.Optional[SubAccountsUpdateRequestStatus] diff --git a/src/wavix/sub_accounts/transactions/raw_client.py b/src/wavix/sub_accounts/transactions/raw_client.py index f266c65..1f8078a 100644 --- a/src/wavix/sub_accounts/transactions/raw_client.py +++ b/src/wavix/sub_accounts/transactions/raw_client.py @@ -11,6 +11,7 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError from ...errors.service_unavailable_error import ServiceUnavailableError @@ -89,6 +90,17 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -211,6 +223,17 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), diff --git a/src/wavix/ten_dlc/__init__.py b/src/wavix/ten_dlc/__init__.py index 1c6b556..8e5e9e6 100644 --- a/src/wavix/ten_dlc/__init__.py +++ b/src/wavix/ten_dlc/__init__.py @@ -16,79 +16,21 @@ campaigns, subscriptions, ) - from .brand_appeals import CreateBrandAppealsResponse - from .brand_evidence import DeleteBrandEvidenceResponse, UploadBrandEvidenceResponse - from .brand_vetting_appeals import CreateBrandVettingAppealsResponse + from .brand_appeals import CreateBrandAppealsRequestAppealCategoriesItem + from .brand_vetting_appeals import TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem from .brands import ( - CreateBrandsResponse, - CreateBrandsResponseEntityType, - CreateBrandsResponseStatus, - DeleteBrandsResponse, - GetBrandsResponse, - GetBrandsResponseEntityType, - GetBrandsResponseStatus, - ListBrandsResponse, - ListBrandsResponsePagination, QualifyUsecaseBrandsRequestUseCase, - QualifyUsecaseBrandsResponse, TenDlcBrandUpdateRequestEntityType, TenDlcBrandUpdateRequestVertical, - UpdateBrandsResponse, - UpdateBrandsResponseEntityType, - UpdateBrandsResponseStatus, ) - from .campaign_numbers import ( - LinkCampaignNumbersResponse, - ListCampaignNumbersResponse, - UnlinkCampaignNumbersResponse, - ) - from .campaigns import ( - CreateCampaignsResponse, - DeleteCampaignsResponse, - GetCampaignsResponse, - ListByBrandCampaignsResponse, - ListByBrandCampaignsResponsePagination, - ListCampaignsResponse, - ListCampaignsResponsePagination, - TenDlcCampaignUpdateRequestUsecase, - UpdateCampaignsResponse, - ) - from .subscriptions import CreateSubscriptionsResponse, DeleteSubscriptionsResponse + from .campaigns import TenDlcCampaignUpdateRequestUsecase _dynamic_imports: typing.Dict[str, str] = { - "CreateBrandAppealsResponse": ".brand_appeals", - "CreateBrandVettingAppealsResponse": ".brand_vetting_appeals", - "CreateBrandsResponse": ".brands", - "CreateBrandsResponseEntityType": ".brands", - "CreateBrandsResponseStatus": ".brands", - "CreateCampaignsResponse": ".campaigns", - "CreateSubscriptionsResponse": ".subscriptions", - "DeleteBrandEvidenceResponse": ".brand_evidence", - "DeleteBrandsResponse": ".brands", - "DeleteCampaignsResponse": ".campaigns", - "DeleteSubscriptionsResponse": ".subscriptions", - "GetBrandsResponse": ".brands", - "GetBrandsResponseEntityType": ".brands", - "GetBrandsResponseStatus": ".brands", - "GetCampaignsResponse": ".campaigns", - "LinkCampaignNumbersResponse": ".campaign_numbers", - "ListBrandsResponse": ".brands", - "ListBrandsResponsePagination": ".brands", - "ListByBrandCampaignsResponse": ".campaigns", - "ListByBrandCampaignsResponsePagination": ".campaigns", - "ListCampaignNumbersResponse": ".campaign_numbers", - "ListCampaignsResponse": ".campaigns", - "ListCampaignsResponsePagination": ".campaigns", + "CreateBrandAppealsRequestAppealCategoriesItem": ".brand_appeals", "QualifyUsecaseBrandsRequestUseCase": ".brands", - "QualifyUsecaseBrandsResponse": ".brands", "TenDlcBrandUpdateRequestEntityType": ".brands", "TenDlcBrandUpdateRequestVertical": ".brands", + "TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem": ".brand_vetting_appeals", "TenDlcCampaignUpdateRequestUsecase": ".campaigns", - "UnlinkCampaignNumbersResponse": ".campaign_numbers", - "UpdateBrandsResponse": ".brands", - "UpdateBrandsResponseEntityType": ".brands", - "UpdateBrandsResponseStatus": ".brands", - "UpdateCampaignsResponse": ".campaigns", - "UploadBrandEvidenceResponse": ".brand_evidence", "brand_appeals": ".brand_appeals", "brand_evidence": ".brand_evidence", "brand_vetting_appeals": ".brand_vetting_appeals", @@ -122,40 +64,12 @@ def __dir__(): __all__ = [ - "CreateBrandAppealsResponse", - "CreateBrandVettingAppealsResponse", - "CreateBrandsResponse", - "CreateBrandsResponseEntityType", - "CreateBrandsResponseStatus", - "CreateCampaignsResponse", - "CreateSubscriptionsResponse", - "DeleteBrandEvidenceResponse", - "DeleteBrandsResponse", - "DeleteCampaignsResponse", - "DeleteSubscriptionsResponse", - "GetBrandsResponse", - "GetBrandsResponseEntityType", - "GetBrandsResponseStatus", - "GetCampaignsResponse", - "LinkCampaignNumbersResponse", - "ListBrandsResponse", - "ListBrandsResponsePagination", - "ListByBrandCampaignsResponse", - "ListByBrandCampaignsResponsePagination", - "ListCampaignNumbersResponse", - "ListCampaignsResponse", - "ListCampaignsResponsePagination", + "CreateBrandAppealsRequestAppealCategoriesItem", "QualifyUsecaseBrandsRequestUseCase", - "QualifyUsecaseBrandsResponse", "TenDlcBrandUpdateRequestEntityType", "TenDlcBrandUpdateRequestVertical", + "TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem", "TenDlcCampaignUpdateRequestUsecase", - "UnlinkCampaignNumbersResponse", - "UpdateBrandsResponse", - "UpdateBrandsResponseEntityType", - "UpdateBrandsResponseStatus", - "UpdateCampaignsResponse", - "UploadBrandEvidenceResponse", "brand_appeals", "brand_evidence", "brand_vetting_appeals", diff --git a/src/wavix/ten_dlc/brand_appeals/__init__.py b/src/wavix/ten_dlc/brand_appeals/__init__.py index dd0b21c..7503c0f 100644 --- a/src/wavix/ten_dlc/brand_appeals/__init__.py +++ b/src/wavix/ten_dlc/brand_appeals/__init__.py @@ -6,8 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import CreateBrandAppealsResponse -_dynamic_imports: typing.Dict[str, str] = {"CreateBrandAppealsResponse": ".types"} + from .types import CreateBrandAppealsRequestAppealCategoriesItem +_dynamic_imports: typing.Dict[str, str] = {"CreateBrandAppealsRequestAppealCategoriesItem": ".types"} def __getattr__(attr_name: str) -> typing.Any: @@ -31,4 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["CreateBrandAppealsResponse"] +__all__ = ["CreateBrandAppealsRequestAppealCategoriesItem"] diff --git a/src/wavix/ten_dlc/brand_appeals/client.py b/src/wavix/ten_dlc/brand_appeals/client.py index fbdb34d..925cdc2 100644 --- a/src/wavix/ten_dlc/brand_appeals/client.py +++ b/src/wavix/ten_dlc/brand_appeals/client.py @@ -4,9 +4,10 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.success_response import SuccessResponse from ...types.ten_dlc_brand_appeal import TenDlcBrandAppeal from .raw_client import AsyncRawBrandAppealsClient, RawBrandAppealsClient -from .types.create_brand_appeals_response import CreateBrandAppealsResponse +from .types.create_brand_appeals_request_appeal_categories_item import CreateBrandAppealsRequestAppealCategoriesItem # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -64,11 +65,11 @@ def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateBrandAppealsResponse: + ) -> SuccessResponse: """ Submits an appeal for 10DLC brand identity verification. Provide any additional documentation to support the appeal. Use `appeal_category` to specify the appeal type: - `VERIFY_TAX_ID` — Use if the brand is UNVERIFIED due to a tax ID mismatch. Applies to private companies, public companies, non-profits, and government entities. @@ -80,7 +81,7 @@ def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] + appeal_categories : typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem] List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT` evidence : typing.Sequence[str] @@ -94,7 +95,7 @@ def create( Returns ------- - CreateBrandAppealsResponse + SuccessResponse Returns the submitted appeal. Examples @@ -180,11 +181,11 @@ async def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateBrandAppealsResponse: + ) -> SuccessResponse: """ Submits an appeal for 10DLC brand identity verification. Provide any additional documentation to support the appeal. Use `appeal_category` to specify the appeal type: - `VERIFY_TAX_ID` — Use if the brand is UNVERIFIED due to a tax ID mismatch. Applies to private companies, public companies, non-profits, and government entities. @@ -196,7 +197,7 @@ async def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] + appeal_categories : typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem] List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT` evidence : typing.Sequence[str] @@ -210,7 +211,7 @@ async def create( Returns ------- - CreateBrandAppealsResponse + SuccessResponse Returns the submitted appeal. Examples diff --git a/src/wavix/ten_dlc/brand_appeals/raw_client.py b/src/wavix/ten_dlc/brand_appeals/raw_client.py index d2fc6b9..7d7d93d 100644 --- a/src/wavix/ten_dlc/brand_appeals/raw_client.py +++ b/src/wavix/ten_dlc/brand_appeals/raw_client.py @@ -13,9 +13,12 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError +from ...types.success_response import SuccessResponse from ...types.ten_dlc_brand_appeal import TenDlcBrandAppeal -from .types.create_brand_appeals_response import CreateBrandAppealsResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse +from .types.create_brand_appeals_request_appeal_categories_item import CreateBrandAppealsRequestAppealCategoriesItem from pydantic import ValidationError # this is used as the default value for optional parameters @@ -71,6 +74,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -106,11 +120,11 @@ def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[CreateBrandAppealsResponse]: + ) -> HttpResponse[SuccessResponse]: """ Submits an appeal for 10DLC brand identity verification. Provide any additional documentation to support the appeal. Use `appeal_category` to specify the appeal type: - `VERIFY_TAX_ID` — Use if the brand is UNVERIFIED due to a tax ID mismatch. Applies to private companies, public companies, non-profits, and government entities. @@ -122,7 +136,7 @@ def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] + appeal_categories : typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem] List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT` evidence : typing.Sequence[str] @@ -136,7 +150,7 @@ def create( Returns ------- - HttpResponse[CreateBrandAppealsResponse] + HttpResponse[SuccessResponse] Returns the submitted appeal. """ _response = self._client_wrapper.httpx_client.request( @@ -156,9 +170,9 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateBrandAppealsResponse, + SuccessResponse, parse_obj_as( - type_=CreateBrandAppealsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -174,6 +188,28 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -255,6 +291,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -290,11 +337,11 @@ async def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[CreateBrandAppealsResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Submits an appeal for 10DLC brand identity verification. Provide any additional documentation to support the appeal. Use `appeal_category` to specify the appeal type: - `VERIFY_TAX_ID` — Use if the brand is UNVERIFIED due to a tax ID mismatch. Applies to private companies, public companies, non-profits, and government entities. @@ -306,7 +353,7 @@ async def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] + appeal_categories : typing.Sequence[CreateBrandAppealsRequestAppealCategoriesItem] List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT` evidence : typing.Sequence[str] @@ -320,7 +367,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateBrandAppealsResponse] + AsyncHttpResponse[SuccessResponse] Returns the submitted appeal. """ _response = await self._client_wrapper.httpx_client.request( @@ -340,9 +387,9 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateBrandAppealsResponse, + SuccessResponse, parse_obj_as( - type_=CreateBrandAppealsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -358,6 +405,28 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), diff --git a/src/wavix/ten_dlc/brand_appeals/types/__init__.py b/src/wavix/ten_dlc/brand_appeals/types/__init__.py index 78dbbfb..fea2a21 100644 --- a/src/wavix/ten_dlc/brand_appeals/types/__init__.py +++ b/src/wavix/ten_dlc/brand_appeals/types/__init__.py @@ -6,8 +6,10 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .create_brand_appeals_response import CreateBrandAppealsResponse -_dynamic_imports: typing.Dict[str, str] = {"CreateBrandAppealsResponse": ".create_brand_appeals_response"} + from .create_brand_appeals_request_appeal_categories_item import CreateBrandAppealsRequestAppealCategoriesItem +_dynamic_imports: typing.Dict[str, str] = { + "CreateBrandAppealsRequestAppealCategoriesItem": ".create_brand_appeals_request_appeal_categories_item" +} def __getattr__(attr_name: str) -> typing.Any: @@ -31,4 +33,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["CreateBrandAppealsResponse"] +__all__ = ["CreateBrandAppealsRequestAppealCategoriesItem"] diff --git a/src/wavix/ten_dlc/brand_appeals/types/create_brand_appeals_request_appeal_categories_item.py b/src/wavix/ten_dlc/brand_appeals/types/create_brand_appeals_request_appeal_categories_item.py new file mode 100644 index 0000000..8945e8b --- /dev/null +++ b/src/wavix/ten_dlc/brand_appeals/types/create_brand_appeals_request_appeal_categories_item.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CreateBrandAppealsRequestAppealCategoriesItem = typing.Union[ + typing.Literal["VERIFY_TAX_ID", "VERIFY_NON_PROFIT", "VERIFY_GOVERNMENT"], typing.Any +] diff --git a/src/wavix/ten_dlc/brand_appeals/types/create_brand_appeals_response.py b/src/wavix/ten_dlc/brand_appeals/types/create_brand_appeals_response.py deleted file mode 100644 index 2d157d0..0000000 --- a/src/wavix/ten_dlc/brand_appeals/types/create_brand_appeals_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class CreateBrandAppealsResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brand_evidence/__init__.py b/src/wavix/ten_dlc/brand_evidence/__init__.py index bf7e85c..5cde020 100644 --- a/src/wavix/ten_dlc/brand_evidence/__init__.py +++ b/src/wavix/ten_dlc/brand_evidence/__init__.py @@ -2,36 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import DeleteBrandEvidenceResponse, UploadBrandEvidenceResponse -_dynamic_imports: typing.Dict[str, str] = { - "DeleteBrandEvidenceResponse": ".types", - "UploadBrandEvidenceResponse": ".types", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["DeleteBrandEvidenceResponse", "UploadBrandEvidenceResponse"] diff --git a/src/wavix/ten_dlc/brand_evidence/client.py b/src/wavix/ten_dlc/brand_evidence/client.py index c99db97..f45b66a 100644 --- a/src/wavix/ten_dlc/brand_evidence/client.py +++ b/src/wavix/ten_dlc/brand_evidence/client.py @@ -6,9 +6,9 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions from ...types.list_brand_evidence_response import ListBrandEvidenceResponse +from ...types.success_response import SuccessResponse +from ...types.ten_dlc_brand_evidence import TenDlcBrandEvidence from .raw_client import AsyncRawBrandEvidenceClient, RawBrandEvidenceClient -from .types.delete_brand_evidence_response import DeleteBrandEvidenceResponse -from .types.upload_brand_evidence_response import UploadBrandEvidenceResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -64,7 +64,7 @@ def list( def upload( self, brand_id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None - ) -> UploadBrandEvidenceResponse: + ) -> TenDlcBrandEvidence: """ Uploads a supporting evidence file for the 10DLC Brand identified by `brand_id`. Supported formats include `.jpg`, `.png`, and `.pdf`. Maximum size is 10 MB. @@ -81,7 +81,7 @@ def upload( Returns ------- - UploadBrandEvidenceResponse + TenDlcBrandEvidence Returns the uploaded evidence file. Examples @@ -137,7 +137,7 @@ def get( def delete( self, brand_id: str, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteBrandEvidenceResponse: + ) -> SuccessResponse: """ Deletes the Brand evidence file identified by the evidence ID. Deletion is permanent. @@ -154,7 +154,7 @@ def delete( Returns ------- - DeleteBrandEvidenceResponse + SuccessResponse Returns a success confirmation. The evidence file is deleted. Examples @@ -231,7 +231,7 @@ async def main() -> None: async def upload( self, brand_id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None - ) -> UploadBrandEvidenceResponse: + ) -> TenDlcBrandEvidence: """ Uploads a supporting evidence file for the 10DLC Brand identified by `brand_id`. Supported formats include `.jpg`, `.png`, and `.pdf`. Maximum size is 10 MB. @@ -248,7 +248,7 @@ async def upload( Returns ------- - UploadBrandEvidenceResponse + TenDlcBrandEvidence Returns the uploaded evidence file. Examples @@ -321,7 +321,7 @@ async def main() -> None: async def delete( self, brand_id: str, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteBrandEvidenceResponse: + ) -> SuccessResponse: """ Deletes the Brand evidence file identified by the evidence ID. Deletion is permanent. @@ -338,7 +338,7 @@ async def delete( Returns ------- - DeleteBrandEvidenceResponse + SuccessResponse Returns a success confirmation. The evidence file is deleted. Examples diff --git a/src/wavix/ten_dlc/brand_evidence/raw_client.py b/src/wavix/ten_dlc/brand_evidence/raw_client.py index 24b1e9c..1e2ea73 100644 --- a/src/wavix/ten_dlc/brand_evidence/raw_client.py +++ b/src/wavix/ten_dlc/brand_evidence/raw_client.py @@ -12,12 +12,15 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.list_brand_evidence_response import ListBrandEvidenceResponse -from .types.delete_brand_evidence_response import DeleteBrandEvidenceResponse -from .types.upload_brand_evidence_response import UploadBrandEvidenceResponse +from ...types.success_response import SuccessResponse +from ...types.ten_dlc_brand_evidence import TenDlcBrandEvidence +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -62,6 +65,28 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -95,7 +120,7 @@ def list( def upload( self, brand_id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[UploadBrandEvidenceResponse]: + ) -> HttpResponse[TenDlcBrandEvidence]: """ Uploads a supporting evidence file for the 10DLC Brand identified by `brand_id`. Supported formats include `.jpg`, `.png`, and `.pdf`. Maximum size is 10 MB. @@ -112,7 +137,7 @@ def upload( Returns ------- - HttpResponse[UploadBrandEvidenceResponse] + HttpResponse[TenDlcBrandEvidence] Returns the uploaded evidence file. """ _response = self._client_wrapper.httpx_client.request( @@ -129,13 +154,24 @@ def upload( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UploadBrandEvidenceResponse, + TenDlcBrandEvidence, parse_obj_as( - type_=UploadBrandEvidenceResponse, # type: ignore + type_=TenDlcBrandEvidence, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -215,6 +251,39 @@ def _stream() -> HttpResponse[typing.Iterator[bytes]]: response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) ) _response.read() + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -244,7 +313,7 @@ def _stream() -> HttpResponse[typing.Iterator[bytes]]: def delete( self, brand_id: str, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[DeleteBrandEvidenceResponse]: + ) -> HttpResponse[SuccessResponse]: """ Deletes the Brand evidence file identified by the evidence ID. Deletion is permanent. @@ -261,7 +330,7 @@ def delete( Returns ------- - HttpResponse[DeleteBrandEvidenceResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The evidence file is deleted. """ _response = self._client_wrapper.httpx_client.request( @@ -272,13 +341,35 @@ def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteBrandEvidenceResponse, + SuccessResponse, parse_obj_as( - type_=DeleteBrandEvidenceResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -349,6 +440,28 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -382,7 +495,7 @@ async def list( async def upload( self, brand_id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[UploadBrandEvidenceResponse]: + ) -> AsyncHttpResponse[TenDlcBrandEvidence]: """ Uploads a supporting evidence file for the 10DLC Brand identified by `brand_id`. Supported formats include `.jpg`, `.png`, and `.pdf`. Maximum size is 10 MB. @@ -399,7 +512,7 @@ async def upload( Returns ------- - AsyncHttpResponse[UploadBrandEvidenceResponse] + AsyncHttpResponse[TenDlcBrandEvidence] Returns the uploaded evidence file. """ _response = await self._client_wrapper.httpx_client.request( @@ -416,13 +529,24 @@ async def upload( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UploadBrandEvidenceResponse, + TenDlcBrandEvidence, parse_obj_as( - type_=UploadBrandEvidenceResponse, # type: ignore + type_=TenDlcBrandEvidence, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -503,6 +627,39 @@ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), ) await _response.aread() + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 404: raise NotFoundError( headers=dict(_response.headers), @@ -532,7 +689,7 @@ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: async def delete( self, brand_id: str, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[DeleteBrandEvidenceResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Deletes the Brand evidence file identified by the evidence ID. Deletion is permanent. @@ -549,7 +706,7 @@ async def delete( Returns ------- - AsyncHttpResponse[DeleteBrandEvidenceResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The evidence file is deleted. """ _response = await self._client_wrapper.httpx_client.request( @@ -560,13 +717,35 @@ async def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteBrandEvidenceResponse, + SuccessResponse, parse_obj_as( - type_=DeleteBrandEvidenceResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/ten_dlc/brand_evidence/types/__init__.py b/src/wavix/ten_dlc/brand_evidence/types/__init__.py deleted file mode 100644 index 464bd76..0000000 --- a/src/wavix/ten_dlc/brand_evidence/types/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .delete_brand_evidence_response import DeleteBrandEvidenceResponse - from .upload_brand_evidence_response import UploadBrandEvidenceResponse -_dynamic_imports: typing.Dict[str, str] = { - "DeleteBrandEvidenceResponse": ".delete_brand_evidence_response", - "UploadBrandEvidenceResponse": ".upload_brand_evidence_response", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["DeleteBrandEvidenceResponse", "UploadBrandEvidenceResponse"] diff --git a/src/wavix/ten_dlc/brand_evidence/types/delete_brand_evidence_response.py b/src/wavix/ten_dlc/brand_evidence/types/delete_brand_evidence_response.py deleted file mode 100644 index e76071c..0000000 --- a/src/wavix/ten_dlc/brand_evidence/types/delete_brand_evidence_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class DeleteBrandEvidenceResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brand_evidence/types/upload_brand_evidence_response.py b/src/wavix/ten_dlc/brand_evidence/types/upload_brand_evidence_response.py deleted file mode 100644 index dda8332..0000000 --- a/src/wavix/ten_dlc/brand_evidence/types/upload_brand_evidence_response.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -import typing_extensions -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....core.serialization import FieldMetadata - - -class UploadBrandEvidenceResponse(UniversalBaseModel): - file_name: str = pydantic.Field() - """ - The uploaded file name - """ - - mime_type: str = pydantic.Field() - """ - The uploaded file media type - """ - - url: str = pydantic.Field() - """ - An URL to the uploaded file - """ - - uuid_: typing_extensions.Annotated[ - str, FieldMetadata(alias="uuid"), pydantic.Field(alias="uuid", description="The evidence UUID") - ] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brand_vetting_appeals/__init__.py b/src/wavix/ten_dlc/brand_vetting_appeals/__init__.py index be9f0c5..415608a 100644 --- a/src/wavix/ten_dlc/brand_vetting_appeals/__init__.py +++ b/src/wavix/ten_dlc/brand_vetting_appeals/__init__.py @@ -6,8 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import CreateBrandVettingAppealsResponse -_dynamic_imports: typing.Dict[str, str] = {"CreateBrandVettingAppealsResponse": ".types"} + from .types import TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem +_dynamic_imports: typing.Dict[str, str] = {"TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem": ".types"} def __getattr__(attr_name: str) -> typing.Any: @@ -31,4 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["CreateBrandVettingAppealsResponse"] +__all__ = ["TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem"] diff --git a/src/wavix/ten_dlc/brand_vetting_appeals/client.py b/src/wavix/ten_dlc/brand_vetting_appeals/client.py index e723499..782ca84 100644 --- a/src/wavix/ten_dlc/brand_vetting_appeals/client.py +++ b/src/wavix/ten_dlc/brand_vetting_appeals/client.py @@ -4,9 +4,12 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.success_response import SuccessResponse from ...types.ten_dlc_brand_vetting_appeal import TenDlcBrandVettingAppeal from .raw_client import AsyncRawBrandVettingAppealsClient, RawBrandVettingAppealsClient -from .types.create_brand_vetting_appeals_response import CreateBrandVettingAppealsResponse +from .types.ten_dlc_brand_vetting_appeal_create_request_appeal_categories_item import ( + TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem, +) # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -64,13 +67,13 @@ def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, evp_id: typing.Optional[str] = OMIT, vetting_id: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateBrandVettingAppealsResponse: + ) -> SuccessResponse: """ Submits an appeal for an external vetting of the 10DLC Brand identified by `brand_id`. @@ -79,8 +82,8 @@ def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] - List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. + appeal_categories : typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem] + List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. `LOW_SCORE` is only valid for vetting appeals — brand identity appeals (`ten_dlc_brand_appeals_create`) do not accept it. evidence : typing.Sequence[str] List of evidence IDs associated with the appeal. @@ -99,7 +102,7 @@ def create( Returns ------- - CreateBrandVettingAppealsResponse + SuccessResponse Returns the submitted appeal. Examples @@ -187,13 +190,13 @@ async def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, evp_id: typing.Optional[str] = OMIT, vetting_id: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateBrandVettingAppealsResponse: + ) -> SuccessResponse: """ Submits an appeal for an external vetting of the 10DLC Brand identified by `brand_id`. @@ -202,8 +205,8 @@ async def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] - List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. + appeal_categories : typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem] + List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. `LOW_SCORE` is only valid for vetting appeals — brand identity appeals (`ten_dlc_brand_appeals_create`) do not accept it. evidence : typing.Sequence[str] List of evidence IDs associated with the appeal. @@ -222,7 +225,7 @@ async def create( Returns ------- - CreateBrandVettingAppealsResponse + SuccessResponse Returns the submitted appeal. Examples diff --git a/src/wavix/ten_dlc/brand_vetting_appeals/raw_client.py b/src/wavix/ten_dlc/brand_vetting_appeals/raw_client.py index d1fbe48..f8db283 100644 --- a/src/wavix/ten_dlc/brand_vetting_appeals/raw_client.py +++ b/src/wavix/ten_dlc/brand_vetting_appeals/raw_client.py @@ -10,11 +10,17 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError +from ...types.success_response import SuccessResponse from ...types.ten_dlc_brand_vetting_appeal import TenDlcBrandVettingAppeal -from .types.create_brand_vetting_appeals_response import CreateBrandVettingAppealsResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse +from .types.ten_dlc_brand_vetting_appeal_create_request_appeal_categories_item import ( + TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem, +) from pydantic import ValidationError # this is used as the default value for optional parameters @@ -59,6 +65,28 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -94,13 +122,13 @@ def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, evp_id: typing.Optional[str] = OMIT, vetting_id: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[CreateBrandVettingAppealsResponse]: + ) -> HttpResponse[SuccessResponse]: """ Submits an appeal for an external vetting of the 10DLC Brand identified by `brand_id`. @@ -109,8 +137,8 @@ def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] - List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. + appeal_categories : typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem] + List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. `LOW_SCORE` is only valid for vetting appeals — brand identity appeals (`ten_dlc_brand_appeals_create`) do not accept it. evidence : typing.Sequence[str] List of evidence IDs associated with the appeal. @@ -129,7 +157,7 @@ def create( Returns ------- - HttpResponse[CreateBrandVettingAppealsResponse] + HttpResponse[SuccessResponse] Returns the submitted appeal. """ _response = self._client_wrapper.httpx_client.request( @@ -151,13 +179,35 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateBrandVettingAppealsResponse, + SuccessResponse, parse_obj_as( - type_=CreateBrandVettingAppealsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -239,6 +289,28 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -274,13 +346,13 @@ async def create( self, brand_id: str, *, - appeal_categories: typing.Sequence[str], + appeal_categories: typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem], evidence: typing.Sequence[str], explanation: typing.Optional[str] = OMIT, evp_id: typing.Optional[str] = OMIT, vetting_id: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[CreateBrandVettingAppealsResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Submits an appeal for an external vetting of the 10DLC Brand identified by `brand_id`. @@ -289,8 +361,8 @@ async def create( brand_id : str The unique ID of the 10DLC Brand. - appeal_categories : typing.Sequence[str] - List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. + appeal_categories : typing.Sequence[TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem] + List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT`, `LOW_SCORE`. `LOW_SCORE` is only valid for vetting appeals — brand identity appeals (`ten_dlc_brand_appeals_create`) do not accept it. evidence : typing.Sequence[str] List of evidence IDs associated with the appeal. @@ -309,7 +381,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateBrandVettingAppealsResponse] + AsyncHttpResponse[SuccessResponse] Returns the submitted appeal. """ _response = await self._client_wrapper.httpx_client.request( @@ -331,13 +403,35 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateBrandVettingAppealsResponse, + SuccessResponse, parse_obj_as( - type_=CreateBrandVettingAppealsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/ten_dlc/brand_vetting_appeals/types/__init__.py b/src/wavix/ten_dlc/brand_vetting_appeals/types/__init__.py index cf6edab..a12927c 100644 --- a/src/wavix/ten_dlc/brand_vetting_appeals/types/__init__.py +++ b/src/wavix/ten_dlc/brand_vetting_appeals/types/__init__.py @@ -6,9 +6,11 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .create_brand_vetting_appeals_response import CreateBrandVettingAppealsResponse + from .ten_dlc_brand_vetting_appeal_create_request_appeal_categories_item import ( + TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem, + ) _dynamic_imports: typing.Dict[str, str] = { - "CreateBrandVettingAppealsResponse": ".create_brand_vetting_appeals_response" + "TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem": ".ten_dlc_brand_vetting_appeal_create_request_appeal_categories_item" } @@ -33,4 +35,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["CreateBrandVettingAppealsResponse"] +__all__ = ["TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem"] diff --git a/src/wavix/ten_dlc/brand_vetting_appeals/types/create_brand_vetting_appeals_response.py b/src/wavix/ten_dlc/brand_vetting_appeals/types/create_brand_vetting_appeals_response.py deleted file mode 100644 index 0897e20..0000000 --- a/src/wavix/ten_dlc/brand_vetting_appeals/types/create_brand_vetting_appeals_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class CreateBrandVettingAppealsResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brand_vetting_appeals/types/ten_dlc_brand_vetting_appeal_create_request_appeal_categories_item.py b/src/wavix/ten_dlc/brand_vetting_appeals/types/ten_dlc_brand_vetting_appeal_create_request_appeal_categories_item.py new file mode 100644 index 0000000..fcc82ed --- /dev/null +++ b/src/wavix/ten_dlc/brand_vetting_appeals/types/ten_dlc_brand_vetting_appeal_create_request_appeal_categories_item.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +TenDlcBrandVettingAppealCreateRequestAppealCategoriesItem = typing.Union[ + typing.Literal["VERIFY_TAX_ID", "VERIFY_NON_PROFIT", "VERIFY_GOVERNMENT", "LOW_SCORE"], typing.Any +] diff --git a/src/wavix/ten_dlc/brand_vettings/client.py b/src/wavix/ten_dlc/brand_vettings/client.py index e1d81c7..5ab1c81 100644 --- a/src/wavix/ten_dlc/brand_vettings/client.py +++ b/src/wavix/ten_dlc/brand_vettings/client.py @@ -63,7 +63,7 @@ def create( self, brand_id: str, *, evp_id: str, vetting_class: str, request_options: typing.Optional[RequestOptions] = None ) -> TenDlcBrandVetting: """ - Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. + Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. Charges a 10DLC brand vetting fee (Standard or Enhanced); fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- @@ -216,7 +216,7 @@ async def create( self, brand_id: str, *, evp_id: str, vetting_class: str, request_options: typing.Optional[RequestOptions] = None ) -> TenDlcBrandVetting: """ - Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. + Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. Charges a 10DLC brand vetting fee (Standard or Enhanced); fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- diff --git a/src/wavix/ten_dlc/brand_vettings/raw_client.py b/src/wavix/ten_dlc/brand_vettings/raw_client.py index c8c7512..9bbe43d 100644 --- a/src/wavix/ten_dlc/brand_vettings/raw_client.py +++ b/src/wavix/ten_dlc/brand_vettings/raw_client.py @@ -10,10 +10,13 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.ten_dlc_brand_vetting import TenDlcBrandVetting +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -58,6 +61,28 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -93,7 +118,7 @@ def create( self, brand_id: str, *, evp_id: str, vetting_class: str, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[TenDlcBrandVetting]: """ - Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. + Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. Charges a 10DLC brand vetting fee (Standard or Enhanced); fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- @@ -137,6 +162,28 @@ def create( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -159,6 +206,17 @@ def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -226,6 +284,28 @@ def import_( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -307,6 +387,28 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -342,7 +444,7 @@ async def create( self, brand_id: str, *, evp_id: str, vetting_class: str, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[TenDlcBrandVetting]: """ - Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. + Requests external vetting for a 10DLC Brand. Supported providers: `AEGIS`, `CV`, `WMC`. Supported classes: `STANDARD`, `ENHANCED`. Charges a 10DLC brand vetting fee (Standard or Enhanced); fails with an insufficient-funds error when the balance cannot cover it. Parameters ---------- @@ -386,6 +488,28 @@ async def create( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -408,6 +532,17 @@ async def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -475,6 +610,28 @@ async def import_( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/ten_dlc/brands/__init__.py b/src/wavix/ten_dlc/brands/__init__.py index 86bb5a4..4d01777 100644 --- a/src/wavix/ten_dlc/brands/__init__.py +++ b/src/wavix/ten_dlc/brands/__init__.py @@ -7,40 +7,14 @@ if typing.TYPE_CHECKING: from .types import ( - CreateBrandsResponse, - CreateBrandsResponseEntityType, - CreateBrandsResponseStatus, - DeleteBrandsResponse, - GetBrandsResponse, - GetBrandsResponseEntityType, - GetBrandsResponseStatus, - ListBrandsResponse, - ListBrandsResponsePagination, QualifyUsecaseBrandsRequestUseCase, - QualifyUsecaseBrandsResponse, TenDlcBrandUpdateRequestEntityType, TenDlcBrandUpdateRequestVertical, - UpdateBrandsResponse, - UpdateBrandsResponseEntityType, - UpdateBrandsResponseStatus, ) _dynamic_imports: typing.Dict[str, str] = { - "CreateBrandsResponse": ".types", - "CreateBrandsResponseEntityType": ".types", - "CreateBrandsResponseStatus": ".types", - "DeleteBrandsResponse": ".types", - "GetBrandsResponse": ".types", - "GetBrandsResponseEntityType": ".types", - "GetBrandsResponseStatus": ".types", - "ListBrandsResponse": ".types", - "ListBrandsResponsePagination": ".types", "QualifyUsecaseBrandsRequestUseCase": ".types", - "QualifyUsecaseBrandsResponse": ".types", "TenDlcBrandUpdateRequestEntityType": ".types", "TenDlcBrandUpdateRequestVertical": ".types", - "UpdateBrandsResponse": ".types", - "UpdateBrandsResponseEntityType": ".types", - "UpdateBrandsResponseStatus": ".types", } @@ -66,20 +40,7 @@ def __dir__(): __all__ = [ - "CreateBrandsResponse", - "CreateBrandsResponseEntityType", - "CreateBrandsResponseStatus", - "DeleteBrandsResponse", - "GetBrandsResponse", - "GetBrandsResponseEntityType", - "GetBrandsResponseStatus", - "ListBrandsResponse", - "ListBrandsResponsePagination", "QualifyUsecaseBrandsRequestUseCase", - "QualifyUsecaseBrandsResponse", "TenDlcBrandUpdateRequestEntityType", "TenDlcBrandUpdateRequestVertical", - "UpdateBrandsResponse", - "UpdateBrandsResponseEntityType", - "UpdateBrandsResponseStatus", ] diff --git a/src/wavix/ten_dlc/brands/client.py b/src/wavix/ten_dlc/brands/client.py index f9d22d1..1b0515e 100644 --- a/src/wavix/ten_dlc/brands/client.py +++ b/src/wavix/ten_dlc/brands/client.py @@ -4,17 +4,15 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.success_response import SuccessResponse +from ...types.ten_dlc_brand import TenDlcBrand from ...types.ten_dlc_brand_create_request import TenDlcBrandCreateRequest +from ...types.ten_dlc_brand_list_response import TenDlcBrandListResponse +from ...types.ten_dlc_brand_qualification_result import TenDlcBrandQualificationResult from .raw_client import AsyncRawBrandsClient, RawBrandsClient -from .types.create_brands_response import CreateBrandsResponse -from .types.delete_brands_response import DeleteBrandsResponse -from .types.get_brands_response import GetBrandsResponse -from .types.list_brands_response import ListBrandsResponse from .types.qualify_usecase_brands_request_use_case import QualifyUsecaseBrandsRequestUseCase -from .types.qualify_usecase_brands_response import QualifyUsecaseBrandsResponse from .types.ten_dlc_brand_update_request_entity_type import TenDlcBrandUpdateRequestEntityType from .types.ten_dlc_brand_update_request_vertical import TenDlcBrandUpdateRequestVertical -from .types.update_brands_response import UpdateBrandsResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -51,7 +49,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListBrandsResponse: + ) -> TenDlcBrandListResponse: """ Returns a paginated list of 10DLC Brands for the authenticated account, filtered by date, name, legal name, and status. @@ -98,7 +96,7 @@ def list( Returns ------- - ListBrandsResponse + TenDlcBrandListResponse Returns a paginated list of 10DLC Brands. Examples @@ -142,9 +140,9 @@ def list( def create( self, *, request: TenDlcBrandCreateRequest, request_options: typing.Optional[RequestOptions] = None - ) -> CreateBrandsResponse: + ) -> TenDlcBrand: """ - Registers a 10DLC Brand. TCR automatically verifies the brand identity. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. + Registers a 10DLC Brand. Submits the company's legal identity data (EIN/Tax ID, legal company name, contact and address) to The Campaign Registry (TCR), which verifies the brand identity. Charges a 10DLC brand registration fee on successful submission; fails with an insufficient-funds error when the balance cannot cover it. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. Parameters ---------- @@ -155,7 +153,7 @@ def create( Returns ------- - CreateBrandsResponse + TenDlcBrand Returns the registered 10DLC Brand. Examples @@ -172,7 +170,7 @@ def create( _response = self._raw_client.create(request=request, request_options=request_options) return _response.data - def get(self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetBrandsResponse: + def get(self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> TenDlcBrand: """ Returns the 10DLC Brand identified by `brand_id`. @@ -186,7 +184,7 @@ def get(self, brand_id: str, *, request_options: typing.Optional[RequestOptions] Returns ------- - GetBrandsResponse + TenDlcBrand Returns the 10DLC Brand. Examples @@ -227,7 +225,7 @@ def update( country: typing.Optional[str] = OMIT, mock: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> UpdateBrandsResponse: + ) -> TenDlcBrand: """ Updates the 10DLC Brand identified by `brand_id`. Changing identity fields, including `ein_taxid`, `ein_taxid_country`, and `entity_type`, resets the Brand status to `UNVERIFIED` and triggers automatic re-submission. Brands in `VETTED_VERIFIED` status or with active Campaigns cannot be updated. @@ -308,7 +306,7 @@ def update( Returns ------- - UpdateBrandsResponse + TenDlcBrand Returns the updated 10DLC Brand. Examples @@ -347,7 +345,7 @@ def update( ) return _response.data - def delete(self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> DeleteBrandsResponse: + def delete(self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SuccessResponse: """ Deletes a 10DLC Brand. Brands with active campaigns cannot be deleted. @@ -361,7 +359,7 @@ def delete(self, brand_id: str, *, request_options: typing.Optional[RequestOptio Returns ------- - DeleteBrandsResponse + SuccessResponse Returns a success confirmation. The 10DLC Brand is deleted. Examples @@ -384,7 +382,7 @@ def qualify_usecase( use_case: QualifyUsecaseBrandsRequestUseCase, *, request_options: typing.Optional[RequestOptions] = None, - ) -> QualifyUsecaseBrandsResponse: + ) -> TenDlcBrandQualificationResult: """ Returns the qualification results for a 10DLC Brand use case. Includes MNO-specific attributes, restrictions, and fees. @@ -401,7 +399,7 @@ def qualify_usecase( Returns ------- - QualifyUsecaseBrandsResponse + TenDlcBrandQualificationResult Returns the use case qualification results for the Brand. Examples @@ -451,7 +449,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListBrandsResponse: + ) -> TenDlcBrandListResponse: """ Returns a paginated list of 10DLC Brands for the authenticated account, filtered by date, name, legal name, and status. @@ -498,7 +496,7 @@ async def list( Returns ------- - ListBrandsResponse + TenDlcBrandListResponse Returns a paginated list of 10DLC Brands. Examples @@ -550,9 +548,9 @@ async def main() -> None: async def create( self, *, request: TenDlcBrandCreateRequest, request_options: typing.Optional[RequestOptions] = None - ) -> CreateBrandsResponse: + ) -> TenDlcBrand: """ - Registers a 10DLC Brand. TCR automatically verifies the brand identity. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. + Registers a 10DLC Brand. Submits the company's legal identity data (EIN/Tax ID, legal company name, contact and address) to The Campaign Registry (TCR), which verifies the brand identity. Charges a 10DLC brand registration fee on successful submission; fails with an insufficient-funds error when the balance cannot cover it. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. Parameters ---------- @@ -563,7 +561,7 @@ async def create( Returns ------- - CreateBrandsResponse + TenDlcBrand Returns the registered 10DLC Brand. Examples @@ -588,7 +586,7 @@ async def main() -> None: _response = await self._raw_client.create(request=request, request_options=request_options) return _response.data - async def get(self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetBrandsResponse: + async def get(self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> TenDlcBrand: """ Returns the 10DLC Brand identified by `brand_id`. @@ -602,7 +600,7 @@ async def get(self, brand_id: str, *, request_options: typing.Optional[RequestOp Returns ------- - GetBrandsResponse + TenDlcBrand Returns the 10DLC Brand. Examples @@ -651,7 +649,7 @@ async def update( country: typing.Optional[str] = OMIT, mock: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> UpdateBrandsResponse: + ) -> TenDlcBrand: """ Updates the 10DLC Brand identified by `brand_id`. Changing identity fields, including `ein_taxid`, `ein_taxid_country`, and `entity_type`, resets the Brand status to `UNVERIFIED` and triggers automatic re-submission. Brands in `VETTED_VERIFIED` status or with active Campaigns cannot be updated. @@ -732,7 +730,7 @@ async def update( Returns ------- - UpdateBrandsResponse + TenDlcBrand Returns the updated 10DLC Brand. Examples @@ -781,7 +779,7 @@ async def main() -> None: async def delete( self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteBrandsResponse: + ) -> SuccessResponse: """ Deletes a 10DLC Brand. Brands with active campaigns cannot be deleted. @@ -795,7 +793,7 @@ async def delete( Returns ------- - DeleteBrandsResponse + SuccessResponse Returns a success confirmation. The 10DLC Brand is deleted. Examples @@ -826,7 +824,7 @@ async def qualify_usecase( use_case: QualifyUsecaseBrandsRequestUseCase, *, request_options: typing.Optional[RequestOptions] = None, - ) -> QualifyUsecaseBrandsResponse: + ) -> TenDlcBrandQualificationResult: """ Returns the qualification results for a 10DLC Brand use case. Includes MNO-specific attributes, restrictions, and fees. @@ -843,7 +841,7 @@ async def qualify_usecase( Returns ------- - QualifyUsecaseBrandsResponse + TenDlcBrandQualificationResult Returns the use case qualification results for the Brand. Examples diff --git a/src/wavix/ten_dlc/brands/raw_client.py b/src/wavix/ten_dlc/brands/raw_client.py index 6ed0068..43aa6fd 100644 --- a/src/wavix/ten_dlc/brands/raw_client.py +++ b/src/wavix/ten_dlc/brands/raw_client.py @@ -14,17 +14,17 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...errors.unprocessable_entity_error import UnprocessableEntityError +from ...types.success_response import SuccessResponse +from ...types.ten_dlc_brand import TenDlcBrand from ...types.ten_dlc_brand_create_request import TenDlcBrandCreateRequest -from .types.create_brands_response import CreateBrandsResponse -from .types.delete_brands_response import DeleteBrandsResponse -from .types.get_brands_response import GetBrandsResponse -from .types.list_brands_response import ListBrandsResponse +from ...types.ten_dlc_brand_list_response import TenDlcBrandListResponse +from ...types.ten_dlc_brand_qualification_result import TenDlcBrandQualificationResult +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from .types.qualify_usecase_brands_request_use_case import QualifyUsecaseBrandsRequestUseCase -from .types.qualify_usecase_brands_response import QualifyUsecaseBrandsResponse from .types.ten_dlc_brand_update_request_entity_type import TenDlcBrandUpdateRequestEntityType from .types.ten_dlc_brand_update_request_vertical import TenDlcBrandUpdateRequestVertical -from .types.update_brands_response import UpdateBrandsResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -51,7 +51,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListBrandsResponse]: + ) -> HttpResponse[TenDlcBrandListResponse]: """ Returns a paginated list of 10DLC Brands for the authenticated account, filtered by date, name, legal name, and status. @@ -98,7 +98,7 @@ def list( Returns ------- - HttpResponse[ListBrandsResponse] + HttpResponse[TenDlcBrandListResponse] Returns a paginated list of 10DLC Brands. """ _response = self._client_wrapper.httpx_client.request( @@ -123,9 +123,9 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListBrandsResponse, + TenDlcBrandListResponse, parse_obj_as( - type_=ListBrandsResponse, # type: ignore + type_=TenDlcBrandListResponse, # type: ignore object_=_response.json(), ), ) @@ -141,6 +141,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -163,9 +174,9 @@ def list( def create( self, *, request: TenDlcBrandCreateRequest, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[CreateBrandsResponse]: + ) -> HttpResponse[TenDlcBrand]: """ - Registers a 10DLC Brand. TCR automatically verifies the brand identity. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. + Registers a 10DLC Brand. Submits the company's legal identity data (EIN/Tax ID, legal company name, contact and address) to The Campaign Registry (TCR), which verifies the brand identity. Charges a 10DLC brand registration fee on successful submission; fails with an insufficient-funds error when the balance cannot cover it. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. Parameters ---------- @@ -176,7 +187,7 @@ def create( Returns ------- - HttpResponse[CreateBrandsResponse] + HttpResponse[TenDlcBrand] Returns the registered 10DLC Brand. """ _response = self._client_wrapper.httpx_client.request( @@ -194,9 +205,9 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateBrandsResponse, + TenDlcBrand, parse_obj_as( - type_=CreateBrandsResponse, # type: ignore + type_=TenDlcBrand, # type: ignore object_=_response.json(), ), ) @@ -212,6 +223,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -223,6 +245,28 @@ def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -234,7 +278,7 @@ def create( def get( self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[GetBrandsResponse]: + ) -> HttpResponse[TenDlcBrand]: """ Returns the 10DLC Brand identified by `brand_id`. @@ -248,7 +292,7 @@ def get( Returns ------- - HttpResponse[GetBrandsResponse] + HttpResponse[TenDlcBrand] Returns the 10DLC Brand. """ _response = self._client_wrapper.httpx_client.request( @@ -259,13 +303,35 @@ def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetBrandsResponse, + TenDlcBrand, parse_obj_as( - type_=GetBrandsResponse, # type: ignore + type_=TenDlcBrand, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -321,7 +387,7 @@ def update( country: typing.Optional[str] = OMIT, mock: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[UpdateBrandsResponse]: + ) -> HttpResponse[TenDlcBrand]: """ Updates the 10DLC Brand identified by `brand_id`. Changing identity fields, including `ein_taxid`, `ein_taxid_country`, and `entity_type`, resets the Brand status to `UNVERIFIED` and triggers automatic re-submission. Brands in `VETTED_VERIFIED` status or with active Campaigns cannot be updated. @@ -402,7 +468,7 @@ def update( Returns ------- - HttpResponse[UpdateBrandsResponse] + HttpResponse[TenDlcBrand] Returns the updated 10DLC Brand. """ _response = self._client_wrapper.httpx_client.request( @@ -438,9 +504,9 @@ def update( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UpdateBrandsResponse, + TenDlcBrand, parse_obj_as( - type_=UpdateBrandsResponse, # type: ignore + type_=TenDlcBrand, # type: ignore object_=_response.json(), ), ) @@ -456,6 +522,17 @@ def update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -500,7 +577,7 @@ def update( def delete( self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[DeleteBrandsResponse]: + ) -> HttpResponse[SuccessResponse]: """ Deletes a 10DLC Brand. Brands with active campaigns cannot be deleted. @@ -514,7 +591,7 @@ def delete( Returns ------- - HttpResponse[DeleteBrandsResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The 10DLC Brand is deleted. """ _response = self._client_wrapper.httpx_client.request( @@ -525,13 +602,35 @@ def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteBrandsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteBrandsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -569,7 +668,7 @@ def qualify_usecase( use_case: QualifyUsecaseBrandsRequestUseCase, *, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[QualifyUsecaseBrandsResponse]: + ) -> HttpResponse[TenDlcBrandQualificationResult]: """ Returns the qualification results for a 10DLC Brand use case. Includes MNO-specific attributes, restrictions, and fees. @@ -586,7 +685,7 @@ def qualify_usecase( Returns ------- - HttpResponse[QualifyUsecaseBrandsResponse] + HttpResponse[TenDlcBrandQualificationResult] Returns the use case qualification results for the Brand. """ _response = self._client_wrapper.httpx_client.request( @@ -597,13 +696,35 @@ def qualify_usecase( try: if 200 <= _response.status_code < 300: _data = typing.cast( - QualifyUsecaseBrandsResponse, + TenDlcBrandQualificationResult, parse_obj_as( - type_=QualifyUsecaseBrandsResponse, # type: ignore + type_=TenDlcBrandQualificationResult, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -667,7 +788,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListBrandsResponse]: + ) -> AsyncHttpResponse[TenDlcBrandListResponse]: """ Returns a paginated list of 10DLC Brands for the authenticated account, filtered by date, name, legal name, and status. @@ -714,7 +835,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListBrandsResponse] + AsyncHttpResponse[TenDlcBrandListResponse] Returns a paginated list of 10DLC Brands. """ _response = await self._client_wrapper.httpx_client.request( @@ -739,9 +860,9 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListBrandsResponse, + TenDlcBrandListResponse, parse_obj_as( - type_=ListBrandsResponse, # type: ignore + type_=TenDlcBrandListResponse, # type: ignore object_=_response.json(), ), ) @@ -757,6 +878,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -779,9 +911,9 @@ async def list( async def create( self, *, request: TenDlcBrandCreateRequest, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[CreateBrandsResponse]: + ) -> AsyncHttpResponse[TenDlcBrand]: """ - Registers a 10DLC Brand. TCR automatically verifies the brand identity. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. + Registers a 10DLC Brand. Submits the company's legal identity data (EIN/Tax ID, legal company name, contact and address) to The Campaign Registry (TCR), which verifies the brand identity. Charges a 10DLC brand registration fee on successful submission; fails with an insufficient-funds error when the balance cannot cover it. Only brands with `VERIFIED` or `VETTED_VERIFIED` identity status can register 10DLC Campaigns. Parameters ---------- @@ -792,7 +924,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateBrandsResponse] + AsyncHttpResponse[TenDlcBrand] Returns the registered 10DLC Brand. """ _response = await self._client_wrapper.httpx_client.request( @@ -810,9 +942,9 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateBrandsResponse, + TenDlcBrand, parse_obj_as( - type_=CreateBrandsResponse, # type: ignore + type_=TenDlcBrand, # type: ignore object_=_response.json(), ), ) @@ -828,6 +960,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -839,6 +982,28 @@ async def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -850,7 +1015,7 @@ async def create( async def get( self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[GetBrandsResponse]: + ) -> AsyncHttpResponse[TenDlcBrand]: """ Returns the 10DLC Brand identified by `brand_id`. @@ -864,7 +1029,7 @@ async def get( Returns ------- - AsyncHttpResponse[GetBrandsResponse] + AsyncHttpResponse[TenDlcBrand] Returns the 10DLC Brand. """ _response = await self._client_wrapper.httpx_client.request( @@ -875,13 +1040,35 @@ async def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetBrandsResponse, + TenDlcBrand, parse_obj_as( - type_=GetBrandsResponse, # type: ignore + type_=TenDlcBrand, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -937,7 +1124,7 @@ async def update( country: typing.Optional[str] = OMIT, mock: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[UpdateBrandsResponse]: + ) -> AsyncHttpResponse[TenDlcBrand]: """ Updates the 10DLC Brand identified by `brand_id`. Changing identity fields, including `ein_taxid`, `ein_taxid_country`, and `entity_type`, resets the Brand status to `UNVERIFIED` and triggers automatic re-submission. Brands in `VETTED_VERIFIED` status or with active Campaigns cannot be updated. @@ -1018,7 +1205,7 @@ async def update( Returns ------- - AsyncHttpResponse[UpdateBrandsResponse] + AsyncHttpResponse[TenDlcBrand] Returns the updated 10DLC Brand. """ _response = await self._client_wrapper.httpx_client.request( @@ -1054,9 +1241,9 @@ async def update( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UpdateBrandsResponse, + TenDlcBrand, parse_obj_as( - type_=UpdateBrandsResponse, # type: ignore + type_=TenDlcBrand, # type: ignore object_=_response.json(), ), ) @@ -1072,6 +1259,17 @@ async def update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1116,7 +1314,7 @@ async def update( async def delete( self, brand_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[DeleteBrandsResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Deletes a 10DLC Brand. Brands with active campaigns cannot be deleted. @@ -1130,7 +1328,7 @@ async def delete( Returns ------- - AsyncHttpResponse[DeleteBrandsResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The 10DLC Brand is deleted. """ _response = await self._client_wrapper.httpx_client.request( @@ -1141,13 +1339,35 @@ async def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteBrandsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteBrandsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1185,7 +1405,7 @@ async def qualify_usecase( use_case: QualifyUsecaseBrandsRequestUseCase, *, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[QualifyUsecaseBrandsResponse]: + ) -> AsyncHttpResponse[TenDlcBrandQualificationResult]: """ Returns the qualification results for a 10DLC Brand use case. Includes MNO-specific attributes, restrictions, and fees. @@ -1202,7 +1422,7 @@ async def qualify_usecase( Returns ------- - AsyncHttpResponse[QualifyUsecaseBrandsResponse] + AsyncHttpResponse[TenDlcBrandQualificationResult] Returns the use case qualification results for the Brand. """ _response = await self._client_wrapper.httpx_client.request( @@ -1213,13 +1433,35 @@ async def qualify_usecase( try: if 200 <= _response.status_code < 300: _data = typing.cast( - QualifyUsecaseBrandsResponse, + TenDlcBrandQualificationResult, parse_obj_as( - type_=QualifyUsecaseBrandsResponse, # type: ignore + type_=TenDlcBrandQualificationResult, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/ten_dlc/brands/types/__init__.py b/src/wavix/ten_dlc/brands/types/__init__.py index e598915..8cff02e 100644 --- a/src/wavix/ten_dlc/brands/types/__init__.py +++ b/src/wavix/ten_dlc/brands/types/__init__.py @@ -6,39 +6,13 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .create_brands_response import CreateBrandsResponse - from .create_brands_response_entity_type import CreateBrandsResponseEntityType - from .create_brands_response_status import CreateBrandsResponseStatus - from .delete_brands_response import DeleteBrandsResponse - from .get_brands_response import GetBrandsResponse - from .get_brands_response_entity_type import GetBrandsResponseEntityType - from .get_brands_response_status import GetBrandsResponseStatus - from .list_brands_response import ListBrandsResponse - from .list_brands_response_pagination import ListBrandsResponsePagination from .qualify_usecase_brands_request_use_case import QualifyUsecaseBrandsRequestUseCase - from .qualify_usecase_brands_response import QualifyUsecaseBrandsResponse from .ten_dlc_brand_update_request_entity_type import TenDlcBrandUpdateRequestEntityType from .ten_dlc_brand_update_request_vertical import TenDlcBrandUpdateRequestVertical - from .update_brands_response import UpdateBrandsResponse - from .update_brands_response_entity_type import UpdateBrandsResponseEntityType - from .update_brands_response_status import UpdateBrandsResponseStatus _dynamic_imports: typing.Dict[str, str] = { - "CreateBrandsResponse": ".create_brands_response", - "CreateBrandsResponseEntityType": ".create_brands_response_entity_type", - "CreateBrandsResponseStatus": ".create_brands_response_status", - "DeleteBrandsResponse": ".delete_brands_response", - "GetBrandsResponse": ".get_brands_response", - "GetBrandsResponseEntityType": ".get_brands_response_entity_type", - "GetBrandsResponseStatus": ".get_brands_response_status", - "ListBrandsResponse": ".list_brands_response", - "ListBrandsResponsePagination": ".list_brands_response_pagination", "QualifyUsecaseBrandsRequestUseCase": ".qualify_usecase_brands_request_use_case", - "QualifyUsecaseBrandsResponse": ".qualify_usecase_brands_response", "TenDlcBrandUpdateRequestEntityType": ".ten_dlc_brand_update_request_entity_type", "TenDlcBrandUpdateRequestVertical": ".ten_dlc_brand_update_request_vertical", - "UpdateBrandsResponse": ".update_brands_response", - "UpdateBrandsResponseEntityType": ".update_brands_response_entity_type", - "UpdateBrandsResponseStatus": ".update_brands_response_status", } @@ -64,20 +38,7 @@ def __dir__(): __all__ = [ - "CreateBrandsResponse", - "CreateBrandsResponseEntityType", - "CreateBrandsResponseStatus", - "DeleteBrandsResponse", - "GetBrandsResponse", - "GetBrandsResponseEntityType", - "GetBrandsResponseStatus", - "ListBrandsResponse", - "ListBrandsResponsePagination", "QualifyUsecaseBrandsRequestUseCase", - "QualifyUsecaseBrandsResponse", "TenDlcBrandUpdateRequestEntityType", "TenDlcBrandUpdateRequestVertical", - "UpdateBrandsResponse", - "UpdateBrandsResponseEntityType", - "UpdateBrandsResponseStatus", ] diff --git a/src/wavix/ten_dlc/brands/types/create_brands_response.py b/src/wavix/ten_dlc/brands/types/create_brands_response.py deleted file mode 100644 index ac7177a..0000000 --- a/src/wavix/ten_dlc/brands/types/create_brands_response.py +++ /dev/null @@ -1,143 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from .create_brands_response_entity_type import CreateBrandsResponseEntityType -from .create_brands_response_status import CreateBrandsResponseStatus - - -class CreateBrandsResponse(UniversalBaseModel): - """ - Represents a 10DLC brand registered for application-to-person messaging. A Brand identifies the business behind one or more messaging campaigns. - """ - - brand_id: str = pydantic.Field() - """ - Unique identifier of the Brand assigned by the registry. - """ - - dba_name: str = pydantic.Field() - """ - Doing-business-as name, or the public-facing brand name. - """ - - company_name: str = pydantic.Field() - """ - Registered legal name of the company that owns the Brand. - """ - - entity_type: CreateBrandsResponseEntityType = pydantic.Field() - """ - Company entity type. - """ - - vertical: str = pydantic.Field() - """ - Industry vertical the Brand operates in. - """ - - ein_taxid: str = pydantic.Field() - """ - IRS Employer Identification Number (EIN) or other tax ID of the company. - """ - - ein_taxid_country: str = pydantic.Field() - """ - ISO 3166-1 alpha-2 country code where the Tax ID was issued. - """ - - status: CreateBrandsResponseStatus = pydantic.Field() - """ - Brand identity verification status. - """ - - website: typing.Optional[str] = pydantic.Field(default=None) - """ - Business website URL. - """ - - stock_symbol: typing.Optional[str] = pydantic.Field(default=None) - """ - Stock ticker symbol of the company. Required for publicly traded companies. - """ - - stock_exchange: typing.Optional[str] = pydantic.Field(default=None) - """ - Code of the stock exchange the company is listed on. Required for publicly traded companies. - """ - - first_name: str = pydantic.Field() - """ - Business contact first name. - """ - - last_name: str = pydantic.Field() - """ - Business contact last name. - """ - - phone_number: str = pydantic.Field() - """ - Support contact phone number in E.164 format. - """ - - email: str = pydantic.Field() - """ - Support contact email address. - """ - - street_address: str = pydantic.Field() - """ - Street address of the business. - """ - - city: str = pydantic.Field() - """ - City of the business address. - """ - - state_or_province: typing.Optional[str] = pydantic.Field(default=None) - """ - State or province of the business address. - """ - - country: str = pydantic.Field() - """ - ISO 3166-1 alpha-2 country code of the business address. - """ - - zip: str = pydantic.Field() - """ - ZIP or postal code of the business address. - """ - - feedback: typing.Optional[str] = pydantic.Field(default=None) - """ - Feedback from the identity verification process explaining the current `status`. - """ - - mock: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the Brand is a mock brand for testing. - """ - - created_at: str = pydantic.Field() - """ - Timestamp when the Brand was created, in ISO 8601 format. - """ - - updated_at: str = pydantic.Field() - """ - Timestamp when the Brand was last updated, in ISO 8601 format. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brands/types/create_brands_response_entity_type.py b/src/wavix/ten_dlc/brands/types/create_brands_response_entity_type.py deleted file mode 100644 index 07824b0..0000000 --- a/src/wavix/ten_dlc/brands/types/create_brands_response_entity_type.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -CreateBrandsResponseEntityType = typing.Union[ - typing.Literal["PRIVATE_PROFIT", "PUBLIC_PROFIT", "NON_PROFIT", "GOVERNMENT"], typing.Any -] diff --git a/src/wavix/ten_dlc/brands/types/create_brands_response_status.py b/src/wavix/ten_dlc/brands/types/create_brands_response_status.py deleted file mode 100644 index 99faa0b..0000000 --- a/src/wavix/ten_dlc/brands/types/create_brands_response_status.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -CreateBrandsResponseStatus = typing.Union[ - typing.Literal["REVIEW", "VERIFIED", "UNVERIFIED", "VETTED_VERIFIED", "SUSPENDED"], typing.Any -] diff --git a/src/wavix/ten_dlc/brands/types/delete_brands_response.py b/src/wavix/ten_dlc/brands/types/delete_brands_response.py deleted file mode 100644 index 4d5ccc5..0000000 --- a/src/wavix/ten_dlc/brands/types/delete_brands_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class DeleteBrandsResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brands/types/get_brands_response.py b/src/wavix/ten_dlc/brands/types/get_brands_response.py deleted file mode 100644 index c5c818b..0000000 --- a/src/wavix/ten_dlc/brands/types/get_brands_response.py +++ /dev/null @@ -1,143 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from .get_brands_response_entity_type import GetBrandsResponseEntityType -from .get_brands_response_status import GetBrandsResponseStatus - - -class GetBrandsResponse(UniversalBaseModel): - """ - Represents a 10DLC brand registered for application-to-person messaging. A Brand identifies the business behind one or more messaging campaigns. - """ - - brand_id: str = pydantic.Field() - """ - Unique identifier of the Brand assigned by the registry. - """ - - dba_name: str = pydantic.Field() - """ - Doing-business-as name, or the public-facing brand name. - """ - - company_name: str = pydantic.Field() - """ - Registered legal name of the company that owns the Brand. - """ - - entity_type: GetBrandsResponseEntityType = pydantic.Field() - """ - Company entity type. - """ - - vertical: str = pydantic.Field() - """ - Industry vertical the Brand operates in. - """ - - ein_taxid: str = pydantic.Field() - """ - IRS Employer Identification Number (EIN) or other tax ID of the company. - """ - - ein_taxid_country: str = pydantic.Field() - """ - ISO 3166-1 alpha-2 country code where the Tax ID was issued. - """ - - status: GetBrandsResponseStatus = pydantic.Field() - """ - Brand identity verification status. - """ - - website: typing.Optional[str] = pydantic.Field(default=None) - """ - Business website URL. - """ - - stock_symbol: typing.Optional[str] = pydantic.Field(default=None) - """ - Stock ticker symbol of the company. Required for publicly traded companies. - """ - - stock_exchange: typing.Optional[str] = pydantic.Field(default=None) - """ - Code of the stock exchange the company is listed on. Required for publicly traded companies. - """ - - first_name: str = pydantic.Field() - """ - Business contact first name. - """ - - last_name: str = pydantic.Field() - """ - Business contact last name. - """ - - phone_number: str = pydantic.Field() - """ - Support contact phone number in E.164 format. - """ - - email: str = pydantic.Field() - """ - Support contact email address. - """ - - street_address: str = pydantic.Field() - """ - Street address of the business. - """ - - city: str = pydantic.Field() - """ - City of the business address. - """ - - state_or_province: typing.Optional[str] = pydantic.Field(default=None) - """ - State or province of the business address. - """ - - country: str = pydantic.Field() - """ - ISO 3166-1 alpha-2 country code of the business address. - """ - - zip: str = pydantic.Field() - """ - ZIP or postal code of the business address. - """ - - feedback: typing.Optional[str] = pydantic.Field(default=None) - """ - Feedback from the identity verification process explaining the current `status`. - """ - - mock: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the Brand is a mock brand for testing. - """ - - created_at: str = pydantic.Field() - """ - Timestamp when the Brand was created, in ISO 8601 format. - """ - - updated_at: str = pydantic.Field() - """ - Timestamp when the Brand was last updated, in ISO 8601 format. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brands/types/get_brands_response_entity_type.py b/src/wavix/ten_dlc/brands/types/get_brands_response_entity_type.py deleted file mode 100644 index 8a664a5..0000000 --- a/src/wavix/ten_dlc/brands/types/get_brands_response_entity_type.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -GetBrandsResponseEntityType = typing.Union[ - typing.Literal["PRIVATE_PROFIT", "PUBLIC_PROFIT", "NON_PROFIT", "GOVERNMENT"], typing.Any -] diff --git a/src/wavix/ten_dlc/brands/types/get_brands_response_status.py b/src/wavix/ten_dlc/brands/types/get_brands_response_status.py deleted file mode 100644 index 7bacc7e..0000000 --- a/src/wavix/ten_dlc/brands/types/get_brands_response_status.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -GetBrandsResponseStatus = typing.Union[ - typing.Literal["REVIEW", "VERIFIED", "UNVERIFIED", "VETTED_VERIFIED", "SUSPENDED"], typing.Any -] diff --git a/src/wavix/ten_dlc/brands/types/list_brands_response.py b/src/wavix/ten_dlc/brands/types/list_brands_response.py deleted file mode 100644 index 41a3f2f..0000000 --- a/src/wavix/ten_dlc/brands/types/list_brands_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.ten_dlc_brand import TenDlcBrand -from .list_brands_response_pagination import ListBrandsResponsePagination - - -class ListBrandsResponse(UniversalBaseModel): - """ - A list of 10DLC Brands - """ - - items: typing.List[TenDlcBrand] = pydantic.Field() - """ - A paginated list of 10DLC Brands matching the filter criteria - """ - - pagination: ListBrandsResponsePagination = pydantic.Field() - """ - Pagination details - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brands/types/list_brands_response_pagination.py b/src/wavix/ten_dlc/brands/types/list_brands_response_pagination.py deleted file mode 100644 index 9f84f5d..0000000 --- a/src/wavix/ten_dlc/brands/types/list_brands_response_pagination.py +++ /dev/null @@ -1,41 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class ListBrandsResponsePagination(UniversalBaseModel): - """ - Pagination details - """ - - current_page: int = pydantic.Field() - """ - Current page number. - """ - - per_page: int = pydantic.Field() - """ - Number of records per page. - """ - - total: int = pydantic.Field() - """ - Total number of records. - """ - - total_pages: int = pydantic.Field() - """ - Total number of pages. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brands/types/qualify_usecase_brands_response.py b/src/wavix/ten_dlc/brands/types/qualify_usecase_brands_response.py deleted file mode 100644 index 06e8776..0000000 --- a/src/wavix/ten_dlc/brands/types/qualify_usecase_brands_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.ten_dlcmno_metadata import TenDlcmnoMetadata - - -class QualifyUsecaseBrandsResponse(UniversalBaseModel): - mno_metadata: typing.List[TenDlcmnoMetadata] = pydantic.Field() - """ - An array MNO-specific attributes (e.g. AT&T message class) for every MNO the Brand is qualified to run a Campaign with the specified use case. - """ - - monthly_fee: float = pydantic.Field() - """ - Monthly fee associated with any Campaign with this use case - """ - - usecase: str = pydantic.Field() - """ - The use case name - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brands/types/update_brands_response.py b/src/wavix/ten_dlc/brands/types/update_brands_response.py deleted file mode 100644 index a0406c5..0000000 --- a/src/wavix/ten_dlc/brands/types/update_brands_response.py +++ /dev/null @@ -1,143 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from .update_brands_response_entity_type import UpdateBrandsResponseEntityType -from .update_brands_response_status import UpdateBrandsResponseStatus - - -class UpdateBrandsResponse(UniversalBaseModel): - """ - Represents a 10DLC brand registered for application-to-person messaging. A Brand identifies the business behind one or more messaging campaigns. - """ - - brand_id: str = pydantic.Field() - """ - Unique identifier of the Brand assigned by the registry. - """ - - dba_name: str = pydantic.Field() - """ - Doing-business-as name, or the public-facing brand name. - """ - - company_name: str = pydantic.Field() - """ - Registered legal name of the company that owns the Brand. - """ - - entity_type: UpdateBrandsResponseEntityType = pydantic.Field() - """ - Company entity type. - """ - - vertical: str = pydantic.Field() - """ - Industry vertical the Brand operates in. - """ - - ein_taxid: str = pydantic.Field() - """ - IRS Employer Identification Number (EIN) or other tax ID of the company. - """ - - ein_taxid_country: str = pydantic.Field() - """ - ISO 3166-1 alpha-2 country code where the Tax ID was issued. - """ - - status: UpdateBrandsResponseStatus = pydantic.Field() - """ - Brand identity verification status. - """ - - website: typing.Optional[str] = pydantic.Field(default=None) - """ - Business website URL. - """ - - stock_symbol: typing.Optional[str] = pydantic.Field(default=None) - """ - Stock ticker symbol of the company. Required for publicly traded companies. - """ - - stock_exchange: typing.Optional[str] = pydantic.Field(default=None) - """ - Code of the stock exchange the company is listed on. Required for publicly traded companies. - """ - - first_name: str = pydantic.Field() - """ - Business contact first name. - """ - - last_name: str = pydantic.Field() - """ - Business contact last name. - """ - - phone_number: str = pydantic.Field() - """ - Support contact phone number in E.164 format. - """ - - email: str = pydantic.Field() - """ - Support contact email address. - """ - - street_address: str = pydantic.Field() - """ - Street address of the business. - """ - - city: str = pydantic.Field() - """ - City of the business address. - """ - - state_or_province: typing.Optional[str] = pydantic.Field(default=None) - """ - State or province of the business address. - """ - - country: str = pydantic.Field() - """ - ISO 3166-1 alpha-2 country code of the business address. - """ - - zip: str = pydantic.Field() - """ - ZIP or postal code of the business address. - """ - - feedback: typing.Optional[str] = pydantic.Field(default=None) - """ - Feedback from the identity verification process explaining the current `status`. - """ - - mock: typing.Optional[bool] = pydantic.Field(default=None) - """ - Indicates whether the Brand is a mock brand for testing. - """ - - created_at: str = pydantic.Field() - """ - Timestamp when the Brand was created, in ISO 8601 format. - """ - - updated_at: str = pydantic.Field() - """ - Timestamp when the Brand was last updated, in ISO 8601 format. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/brands/types/update_brands_response_entity_type.py b/src/wavix/ten_dlc/brands/types/update_brands_response_entity_type.py deleted file mode 100644 index 6b944d9..0000000 --- a/src/wavix/ten_dlc/brands/types/update_brands_response_entity_type.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -UpdateBrandsResponseEntityType = typing.Union[ - typing.Literal["PRIVATE_PROFIT", "PUBLIC_PROFIT", "NON_PROFIT", "GOVERNMENT"], typing.Any -] diff --git a/src/wavix/ten_dlc/brands/types/update_brands_response_status.py b/src/wavix/ten_dlc/brands/types/update_brands_response_status.py deleted file mode 100644 index 7f490a9..0000000 --- a/src/wavix/ten_dlc/brands/types/update_brands_response_status.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -UpdateBrandsResponseStatus = typing.Union[ - typing.Literal["REVIEW", "VERIFIED", "UNVERIFIED", "VETTED_VERIFIED", "SUSPENDED"], typing.Any -] diff --git a/src/wavix/ten_dlc/campaign_numbers/__init__.py b/src/wavix/ten_dlc/campaign_numbers/__init__.py index adb823a..5cde020 100644 --- a/src/wavix/ten_dlc/campaign_numbers/__init__.py +++ b/src/wavix/ten_dlc/campaign_numbers/__init__.py @@ -2,37 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import LinkCampaignNumbersResponse, ListCampaignNumbersResponse, UnlinkCampaignNumbersResponse -_dynamic_imports: typing.Dict[str, str] = { - "LinkCampaignNumbersResponse": ".types", - "ListCampaignNumbersResponse": ".types", - "UnlinkCampaignNumbersResponse": ".types", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["LinkCampaignNumbersResponse", "ListCampaignNumbersResponse", "UnlinkCampaignNumbersResponse"] diff --git a/src/wavix/ten_dlc/campaign_numbers/client.py b/src/wavix/ten_dlc/campaign_numbers/client.py index ad454ed..ae48769 100644 --- a/src/wavix/ten_dlc/campaign_numbers/client.py +++ b/src/wavix/ten_dlc/campaign_numbers/client.py @@ -4,10 +4,9 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.success_response import SuccessResponse +from ...types.ten_dlc_campaign_number_list_response import TenDlcCampaignNumberListResponse from .raw_client import AsyncRawCampaignNumbersClient, RawCampaignNumbersClient -from .types.link_campaign_numbers_response import LinkCampaignNumbersResponse -from .types.list_campaign_numbers_response import ListCampaignNumbersResponse -from .types.unlink_campaign_numbers_response import UnlinkCampaignNumbersResponse class CampaignNumbersClient: @@ -27,7 +26,7 @@ def with_raw_response(self) -> RawCampaignNumbersClient: def link( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> LinkCampaignNumbersResponse: + ) -> SuccessResponse: """ Links a phone number to a 10DLC Campaign. Wavix automatically creates a Sender ID once the number is approved. @@ -47,7 +46,7 @@ def link( Returns ------- - LinkCampaignNumbersResponse + SuccessResponse Returns a success confirmation. The phone number is linked to the Campaign. Examples @@ -68,7 +67,7 @@ def link( def unlink( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> UnlinkCampaignNumbersResponse: + ) -> SuccessResponse: """ Unlinks a phone number from a 10DLC Campaign. The associated Sender ID is also deleted. @@ -88,7 +87,7 @@ def unlink( Returns ------- - UnlinkCampaignNumbersResponse + SuccessResponse Returns a success confirmation. The phone number is unlinked from the Campaign. Examples @@ -109,7 +108,7 @@ def unlink( def list( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListCampaignNumbersResponse: + ) -> TenDlcCampaignNumberListResponse: """ Returns the phone numbers linked to the 10DLC Campaign identified by `campaign_id`. @@ -126,7 +125,7 @@ def list( Returns ------- - ListCampaignNumbersResponse + TenDlcCampaignNumberListResponse Returns the phone numbers linked to the Campaign. Examples @@ -162,7 +161,7 @@ def with_raw_response(self) -> AsyncRawCampaignNumbersClient: async def link( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> LinkCampaignNumbersResponse: + ) -> SuccessResponse: """ Links a phone number to a 10DLC Campaign. Wavix automatically creates a Sender ID once the number is approved. @@ -182,7 +181,7 @@ async def link( Returns ------- - LinkCampaignNumbersResponse + SuccessResponse Returns a success confirmation. The phone number is linked to the Campaign. Examples @@ -211,7 +210,7 @@ async def main() -> None: async def unlink( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> UnlinkCampaignNumbersResponse: + ) -> SuccessResponse: """ Unlinks a phone number from a 10DLC Campaign. The associated Sender ID is also deleted. @@ -231,7 +230,7 @@ async def unlink( Returns ------- - UnlinkCampaignNumbersResponse + SuccessResponse Returns a success confirmation. The phone number is unlinked from the Campaign. Examples @@ -260,7 +259,7 @@ async def main() -> None: async def list( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListCampaignNumbersResponse: + ) -> TenDlcCampaignNumberListResponse: """ Returns the phone numbers linked to the 10DLC Campaign identified by `campaign_id`. @@ -277,7 +276,7 @@ async def list( Returns ------- - ListCampaignNumbersResponse + TenDlcCampaignNumberListResponse Returns the phone numbers linked to the Campaign. Examples diff --git a/src/wavix/ten_dlc/campaign_numbers/raw_client.py b/src/wavix/ten_dlc/campaign_numbers/raw_client.py index e43c73d..258ab8a 100644 --- a/src/wavix/ten_dlc/campaign_numbers/raw_client.py +++ b/src/wavix/ten_dlc/campaign_numbers/raw_client.py @@ -10,11 +10,14 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError -from .types.link_campaign_numbers_response import LinkCampaignNumbersResponse -from .types.list_campaign_numbers_response import ListCampaignNumbersResponse -from .types.unlink_campaign_numbers_response import UnlinkCampaignNumbersResponse +from ...errors.unauthorized_error import UnauthorizedError +from ...errors.unprocessable_entity_error import UnprocessableEntityError +from ...types.success_response import SuccessResponse +from ...types.ten_dlc_campaign_number_list_response import TenDlcCampaignNumberListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -24,7 +27,7 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def link( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[LinkCampaignNumbersResponse]: + ) -> HttpResponse[SuccessResponse]: """ Links a phone number to a 10DLC Campaign. Wavix automatically creates a Sender ID once the number is approved. @@ -44,7 +47,7 @@ def link( Returns ------- - HttpResponse[LinkCampaignNumbersResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The phone number is linked to the Campaign. """ _response = self._client_wrapper.httpx_client.request( @@ -55,13 +58,35 @@ def link( try: if 200 <= _response.status_code < 300: _data = typing.cast( - LinkCampaignNumbersResponse, + SuccessResponse, parse_obj_as( - type_=LinkCampaignNumbersResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -84,6 +109,17 @@ def link( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -95,7 +131,7 @@ def link( def unlink( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[UnlinkCampaignNumbersResponse]: + ) -> HttpResponse[SuccessResponse]: """ Unlinks a phone number from a 10DLC Campaign. The associated Sender ID is also deleted. @@ -115,7 +151,7 @@ def unlink( Returns ------- - HttpResponse[UnlinkCampaignNumbersResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The phone number is unlinked from the Campaign. """ _response = self._client_wrapper.httpx_client.request( @@ -126,13 +162,35 @@ def unlink( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UnlinkCampaignNumbersResponse, + SuccessResponse, parse_obj_as( - type_=UnlinkCampaignNumbersResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -166,7 +224,7 @@ def unlink( def list( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[ListCampaignNumbersResponse]: + ) -> HttpResponse[TenDlcCampaignNumberListResponse]: """ Returns the phone numbers linked to the 10DLC Campaign identified by `campaign_id`. @@ -183,7 +241,7 @@ def list( Returns ------- - HttpResponse[ListCampaignNumbersResponse] + HttpResponse[TenDlcCampaignNumberListResponse] Returns the phone numbers linked to the Campaign. """ _response = self._client_wrapper.httpx_client.request( @@ -194,13 +252,35 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCampaignNumbersResponse, + TenDlcCampaignNumberListResponse, parse_obj_as( - type_=ListCampaignNumbersResponse, # type: ignore + type_=TenDlcCampaignNumberListResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -239,7 +319,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def link( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[LinkCampaignNumbersResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Links a phone number to a 10DLC Campaign. Wavix automatically creates a Sender ID once the number is approved. @@ -259,7 +339,7 @@ async def link( Returns ------- - AsyncHttpResponse[LinkCampaignNumbersResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The phone number is linked to the Campaign. """ _response = await self._client_wrapper.httpx_client.request( @@ -270,13 +350,35 @@ async def link( try: if 200 <= _response.status_code < 300: _data = typing.cast( - LinkCampaignNumbersResponse, + SuccessResponse, parse_obj_as( - type_=LinkCampaignNumbersResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -299,6 +401,17 @@ async def link( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -310,7 +423,7 @@ async def link( async def unlink( self, brand_id: str, campaign_id: str, number: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[UnlinkCampaignNumbersResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Unlinks a phone number from a 10DLC Campaign. The associated Sender ID is also deleted. @@ -330,7 +443,7 @@ async def unlink( Returns ------- - AsyncHttpResponse[UnlinkCampaignNumbersResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The phone number is unlinked from the Campaign. """ _response = await self._client_wrapper.httpx_client.request( @@ -341,13 +454,35 @@ async def unlink( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UnlinkCampaignNumbersResponse, + SuccessResponse, parse_obj_as( - type_=UnlinkCampaignNumbersResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -381,7 +516,7 @@ async def unlink( async def list( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[ListCampaignNumbersResponse]: + ) -> AsyncHttpResponse[TenDlcCampaignNumberListResponse]: """ Returns the phone numbers linked to the 10DLC Campaign identified by `campaign_id`. @@ -398,7 +533,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListCampaignNumbersResponse] + AsyncHttpResponse[TenDlcCampaignNumberListResponse] Returns the phone numbers linked to the Campaign. """ _response = await self._client_wrapper.httpx_client.request( @@ -409,13 +544,35 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCampaignNumbersResponse, + TenDlcCampaignNumberListResponse, parse_obj_as( - type_=ListCampaignNumbersResponse, # type: ignore + type_=TenDlcCampaignNumberListResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/ten_dlc/campaign_numbers/types/__init__.py b/src/wavix/ten_dlc/campaign_numbers/types/__init__.py deleted file mode 100644 index f9e5326..0000000 --- a/src/wavix/ten_dlc/campaign_numbers/types/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .link_campaign_numbers_response import LinkCampaignNumbersResponse - from .list_campaign_numbers_response import ListCampaignNumbersResponse - from .unlink_campaign_numbers_response import UnlinkCampaignNumbersResponse -_dynamic_imports: typing.Dict[str, str] = { - "LinkCampaignNumbersResponse": ".link_campaign_numbers_response", - "ListCampaignNumbersResponse": ".list_campaign_numbers_response", - "UnlinkCampaignNumbersResponse": ".unlink_campaign_numbers_response", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["LinkCampaignNumbersResponse", "ListCampaignNumbersResponse", "UnlinkCampaignNumbersResponse"] diff --git a/src/wavix/ten_dlc/campaign_numbers/types/link_campaign_numbers_response.py b/src/wavix/ten_dlc/campaign_numbers/types/link_campaign_numbers_response.py deleted file mode 100644 index 688e653..0000000 --- a/src/wavix/ten_dlc/campaign_numbers/types/link_campaign_numbers_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class LinkCampaignNumbersResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaign_numbers/types/list_campaign_numbers_response.py b/src/wavix/ten_dlc/campaign_numbers/types/list_campaign_numbers_response.py deleted file mode 100644 index 801b4d6..0000000 --- a/src/wavix/ten_dlc/campaign_numbers/types/list_campaign_numbers_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.ten_dlc_campaign_number import TenDlcCampaignNumber - - -class ListCampaignNumbersResponse(UniversalBaseModel): - brand_id: str = pydantic.Field() - """ - Unique identifier of the 10DLC Brand that owns the Campaign. - """ - - campaign_id: str = pydantic.Field() - """ - Unique identifier of the 10DLC Campaign the numbers belong to. - """ - - numbers: typing.List[TenDlcCampaignNumber] = pydantic.Field() - """ - Phone numbers assigned to the Campaign, with their provisioning status. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaign_numbers/types/unlink_campaign_numbers_response.py b/src/wavix/ten_dlc/campaign_numbers/types/unlink_campaign_numbers_response.py deleted file mode 100644 index c3acc23..0000000 --- a/src/wavix/ten_dlc/campaign_numbers/types/unlink_campaign_numbers_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class UnlinkCampaignNumbersResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/__init__.py b/src/wavix/ten_dlc/campaigns/__init__.py index 45daec6..e77a685 100644 --- a/src/wavix/ten_dlc/campaigns/__init__.py +++ b/src/wavix/ten_dlc/campaigns/__init__.py @@ -6,28 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import ( - CreateCampaignsResponse, - DeleteCampaignsResponse, - GetCampaignsResponse, - ListByBrandCampaignsResponse, - ListByBrandCampaignsResponsePagination, - ListCampaignsResponse, - ListCampaignsResponsePagination, - TenDlcCampaignUpdateRequestUsecase, - UpdateCampaignsResponse, - ) -_dynamic_imports: typing.Dict[str, str] = { - "CreateCampaignsResponse": ".types", - "DeleteCampaignsResponse": ".types", - "GetCampaignsResponse": ".types", - "ListByBrandCampaignsResponse": ".types", - "ListByBrandCampaignsResponsePagination": ".types", - "ListCampaignsResponse": ".types", - "ListCampaignsResponsePagination": ".types", - "TenDlcCampaignUpdateRequestUsecase": ".types", - "UpdateCampaignsResponse": ".types", -} + from .types import TenDlcCampaignUpdateRequestUsecase +_dynamic_imports: typing.Dict[str, str] = {"TenDlcCampaignUpdateRequestUsecase": ".types"} def __getattr__(attr_name: str) -> typing.Any: @@ -51,14 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "CreateCampaignsResponse", - "DeleteCampaignsResponse", - "GetCampaignsResponse", - "ListByBrandCampaignsResponse", - "ListByBrandCampaignsResponsePagination", - "ListCampaignsResponse", - "ListCampaignsResponsePagination", - "TenDlcCampaignUpdateRequestUsecase", - "UpdateCampaignsResponse", -] +__all__ = ["TenDlcCampaignUpdateRequestUsecase"] diff --git a/src/wavix/ten_dlc/campaigns/client.py b/src/wavix/ten_dlc/campaigns/client.py index bd3e159..60373ed 100644 --- a/src/wavix/ten_dlc/campaigns/client.py +++ b/src/wavix/ten_dlc/campaigns/client.py @@ -6,14 +6,10 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions from ...types.success_response import SuccessResponse +from ...types.ten_dlc_campaign import TenDlcCampaign +from ...types.ten_dlc_campaign_list_response import TenDlcCampaignListResponse from .raw_client import AsyncRawCampaignsClient, RawCampaignsClient -from .types.create_campaigns_response import CreateCampaignsResponse -from .types.delete_campaigns_response import DeleteCampaignsResponse -from .types.get_campaigns_response import GetCampaignsResponse -from .types.list_by_brand_campaigns_response import ListByBrandCampaignsResponse -from .types.list_campaigns_response import ListCampaignsResponse from .types.ten_dlc_campaign_update_request_usecase import TenDlcCampaignUpdateRequestUsecase -from .types.update_campaigns_response import UpdateCampaignsResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -46,7 +42,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListCampaignsResponse: + ) -> TenDlcCampaignListResponse: """ Returns a paginated list of 10DLC Campaigns for the authenticated account, filtered by date, status, and use case. @@ -81,7 +77,7 @@ def list( Returns ------- - ListCampaignsResponse + TenDlcCampaignListResponse Returns a paginated list of 10DLC Campaigns. Examples @@ -134,7 +130,7 @@ def list_by_brand( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListByBrandCampaignsResponse: + ) -> TenDlcCampaignListResponse: """ Returns a paginated list of 10DLC Campaigns associated with the 10DLC Brand identified by `brand_id`. @@ -172,7 +168,7 @@ def list_by_brand( Returns ------- - ListByBrandCampaignsResponse + TenDlcCampaignListResponse Returns a paginated list of 10DLC Campaigns. Examples @@ -247,7 +243,7 @@ def create( sample5: typing.Optional[str] = OMIT, privacy_policy: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateCampaignsResponse: + ) -> TenDlcCampaign: """ Registers a 10DLC Campaign under the 10DLC Brand identified by `brand_id`. The Brand must have a verified identity status. @@ -345,7 +341,7 @@ def create( Returns ------- - CreateCampaignsResponse + TenDlcCampaign Returns the registered 10DLC Campaign. Examples @@ -423,7 +419,7 @@ def create( def get( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> GetCampaignsResponse: + ) -> TenDlcCampaign: """ Returns the 10DLC Campaign identified by `campaign_id` under the Brand identified by `brand_id`. @@ -440,7 +436,7 @@ def get( Returns ------- - GetCampaignsResponse + TenDlcCampaign Returns the 10DLC Campaign. Examples @@ -490,7 +486,7 @@ def update( privacy_policy: typing.Optional[str] = OMIT, embedded_link_sample: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> UpdateCampaignsResponse: + ) -> TenDlcCampaign: """ Updates the 10DLC Campaign identified by `campaign_id`. Only the provided fields are changed. @@ -585,7 +581,7 @@ def update( Returns ------- - UpdateCampaignsResponse + TenDlcCampaign Returns the updated 10DLC Campaign. Examples @@ -635,7 +631,7 @@ def update( def delete( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteCampaignsResponse: + ) -> SuccessResponse: """ Deletes a 10DLC Campaign. Associated phone numbers cannot be used as Sender IDs once the Campaign is deleted. @@ -652,7 +648,7 @@ def delete( Returns ------- - DeleteCampaignsResponse + SuccessResponse Returns a success confirmation. The 10DLC Campaign is deleted. Examples @@ -756,7 +752,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListCampaignsResponse: + ) -> TenDlcCampaignListResponse: """ Returns a paginated list of 10DLC Campaigns for the authenticated account, filtered by date, status, and use case. @@ -791,7 +787,7 @@ async def list( Returns ------- - ListCampaignsResponse + TenDlcCampaignListResponse Returns a paginated list of 10DLC Campaigns. Examples @@ -851,7 +847,7 @@ async def list_by_brand( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> ListByBrandCampaignsResponse: + ) -> TenDlcCampaignListResponse: """ Returns a paginated list of 10DLC Campaigns associated with the 10DLC Brand identified by `brand_id`. @@ -889,7 +885,7 @@ async def list_by_brand( Returns ------- - ListByBrandCampaignsResponse + TenDlcCampaignListResponse Returns a paginated list of 10DLC Campaigns. Examples @@ -971,7 +967,7 @@ async def create( sample5: typing.Optional[str] = OMIT, privacy_policy: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CreateCampaignsResponse: + ) -> TenDlcCampaign: """ Registers a 10DLC Campaign under the 10DLC Brand identified by `brand_id`. The Brand must have a verified identity status. @@ -1069,7 +1065,7 @@ async def create( Returns ------- - CreateCampaignsResponse + TenDlcCampaign Returns the registered 10DLC Campaign. Examples @@ -1155,7 +1151,7 @@ async def main() -> None: async def get( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> GetCampaignsResponse: + ) -> TenDlcCampaign: """ Returns the 10DLC Campaign identified by `campaign_id` under the Brand identified by `brand_id`. @@ -1172,7 +1168,7 @@ async def get( Returns ------- - GetCampaignsResponse + TenDlcCampaign Returns the 10DLC Campaign. Examples @@ -1230,7 +1226,7 @@ async def update( privacy_policy: typing.Optional[str] = OMIT, embedded_link_sample: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> UpdateCampaignsResponse: + ) -> TenDlcCampaign: """ Updates the 10DLC Campaign identified by `campaign_id`. Only the provided fields are changed. @@ -1325,7 +1321,7 @@ async def update( Returns ------- - UpdateCampaignsResponse + TenDlcCampaign Returns the updated 10DLC Campaign. Examples @@ -1383,7 +1379,7 @@ async def main() -> None: async def delete( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteCampaignsResponse: + ) -> SuccessResponse: """ Deletes a 10DLC Campaign. Associated phone numbers cannot be used as Sender IDs once the Campaign is deleted. @@ -1400,7 +1396,7 @@ async def delete( Returns ------- - DeleteCampaignsResponse + SuccessResponse Returns a success confirmation. The 10DLC Campaign is deleted. Examples diff --git a/src/wavix/ten_dlc/campaigns/raw_client.py b/src/wavix/ten_dlc/campaigns/raw_client.py index d422de6..3f6978b 100644 --- a/src/wavix/ten_dlc/campaigns/raw_client.py +++ b/src/wavix/ten_dlc/campaigns/raw_client.py @@ -15,15 +15,13 @@ from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.success_response import SuccessResponse -from ...types.validation_error_response import ValidationErrorResponse -from .types.create_campaigns_response import CreateCampaignsResponse -from .types.delete_campaigns_response import DeleteCampaignsResponse -from .types.get_campaigns_response import GetCampaignsResponse -from .types.list_by_brand_campaigns_response import ListByBrandCampaignsResponse -from .types.list_campaigns_response import ListCampaignsResponse +from ...types.ten_dlc_campaign import TenDlcCampaign +from ...types.ten_dlc_campaign_list_response import TenDlcCampaignListResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from .types.ten_dlc_campaign_update_request_usecase import TenDlcCampaignUpdateRequestUsecase -from .types.update_campaigns_response import UpdateCampaignsResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -46,7 +44,7 @@ def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListCampaignsResponse]: + ) -> HttpResponse[TenDlcCampaignListResponse]: """ Returns a paginated list of 10DLC Campaigns for the authenticated account, filtered by date, status, and use case. @@ -81,7 +79,7 @@ def list( Returns ------- - HttpResponse[ListCampaignsResponse] + HttpResponse[TenDlcCampaignListResponse] Returns a paginated list of 10DLC Campaigns. """ _response = self._client_wrapper.httpx_client.request( @@ -102,13 +100,35 @@ def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCampaignsResponse, + TenDlcCampaignListResponse, parse_obj_as( - type_=ListCampaignsResponse, # type: ignore + type_=TenDlcCampaignListResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -120,6 +140,17 @@ def list( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -142,7 +173,7 @@ def list_by_brand( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ListByBrandCampaignsResponse]: + ) -> HttpResponse[TenDlcCampaignListResponse]: """ Returns a paginated list of 10DLC Campaigns associated with the 10DLC Brand identified by `brand_id`. @@ -180,7 +211,7 @@ def list_by_brand( Returns ------- - HttpResponse[ListByBrandCampaignsResponse] + HttpResponse[TenDlcCampaignListResponse] Returns a paginated list of 10DLC Campaigns. """ _response = self._client_wrapper.httpx_client.request( @@ -201,13 +232,35 @@ def list_by_brand( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListByBrandCampaignsResponse, + TenDlcCampaignListResponse, parse_obj_as( - type_=ListByBrandCampaignsResponse, # type: ignore + type_=TenDlcCampaignListResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -272,7 +325,7 @@ def create( sample5: typing.Optional[str] = OMIT, privacy_policy: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[CreateCampaignsResponse]: + ) -> HttpResponse[TenDlcCampaign]: """ Registers a 10DLC Campaign under the 10DLC Brand identified by `brand_id`. The Brand must have a verified identity status. @@ -370,7 +423,7 @@ def create( Returns ------- - HttpResponse[CreateCampaignsResponse] + HttpResponse[TenDlcCampaign] Returns the registered 10DLC Campaign. """ _response = self._client_wrapper.httpx_client.request( @@ -415,9 +468,9 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateCampaignsResponse, + TenDlcCampaign, parse_obj_as( - type_=CreateCampaignsResponse, # type: ignore + type_=TenDlcCampaign, # type: ignore object_=_response.json(), ), ) @@ -433,6 +486,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -455,6 +519,17 @@ def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -466,7 +541,7 @@ def create( def get( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[GetCampaignsResponse]: + ) -> HttpResponse[TenDlcCampaign]: """ Returns the 10DLC Campaign identified by `campaign_id` under the Brand identified by `brand_id`. @@ -483,7 +558,7 @@ def get( Returns ------- - HttpResponse[GetCampaignsResponse] + HttpResponse[TenDlcCampaign] Returns the 10DLC Campaign. """ _response = self._client_wrapper.httpx_client.request( @@ -494,13 +569,35 @@ def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetCampaignsResponse, + TenDlcCampaign, parse_obj_as( - type_=GetCampaignsResponse, # type: ignore + type_=TenDlcCampaign, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -564,7 +661,7 @@ def update( privacy_policy: typing.Optional[str] = OMIT, embedded_link_sample: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[UpdateCampaignsResponse]: + ) -> HttpResponse[TenDlcCampaign]: """ Updates the 10DLC Campaign identified by `campaign_id`. Only the provided fields are changed. @@ -659,7 +756,7 @@ def update( Returns ------- - HttpResponse[UpdateCampaignsResponse] + HttpResponse[TenDlcCampaign] Returns the updated 10DLC Campaign. """ _response = self._client_wrapper.httpx_client.request( @@ -702,9 +799,9 @@ def update( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UpdateCampaignsResponse, + TenDlcCampaign, parse_obj_as( - type_=UpdateCampaignsResponse, # type: ignore + type_=TenDlcCampaign, # type: ignore object_=_response.json(), ), ) @@ -720,6 +817,17 @@ def update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -742,6 +850,17 @@ def update( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -753,7 +872,7 @@ def update( def delete( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[DeleteCampaignsResponse]: + ) -> HttpResponse[SuccessResponse]: """ Deletes a 10DLC Campaign. Associated phone numbers cannot be used as Sender IDs once the Campaign is deleted. @@ -770,7 +889,7 @@ def delete( Returns ------- - HttpResponse[DeleteCampaignsResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The 10DLC Campaign is deleted. """ _response = self._client_wrapper.httpx_client.request( @@ -781,13 +900,35 @@ def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteCampaignsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteCampaignsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -892,6 +1033,17 @@ def nudge( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -918,9 +1070,9 @@ def nudge( raise TooManyRequestsError( headers=dict(_response.headers), body=typing.cast( - ValidationErrorResponse, + typing.Any, parse_obj_as( - type_=ValidationErrorResponse, # type: ignore + type_=typing.Any, # type: ignore object_=_response.json(), ), ), @@ -951,7 +1103,7 @@ async def list( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListCampaignsResponse]: + ) -> AsyncHttpResponse[TenDlcCampaignListResponse]: """ Returns a paginated list of 10DLC Campaigns for the authenticated account, filtered by date, status, and use case. @@ -986,7 +1138,7 @@ async def list( Returns ------- - AsyncHttpResponse[ListCampaignsResponse] + AsyncHttpResponse[TenDlcCampaignListResponse] Returns a paginated list of 10DLC Campaigns. """ _response = await self._client_wrapper.httpx_client.request( @@ -1007,13 +1159,35 @@ async def list( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListCampaignsResponse, + TenDlcCampaignListResponse, parse_obj_as( - type_=ListCampaignsResponse, # type: ignore + type_=TenDlcCampaignListResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1025,6 +1199,17 @@ async def list( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -1047,7 +1232,7 @@ async def list_by_brand( page: typing.Optional[int] = None, per_page: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ListByBrandCampaignsResponse]: + ) -> AsyncHttpResponse[TenDlcCampaignListResponse]: """ Returns a paginated list of 10DLC Campaigns associated with the 10DLC Brand identified by `brand_id`. @@ -1085,7 +1270,7 @@ async def list_by_brand( Returns ------- - AsyncHttpResponse[ListByBrandCampaignsResponse] + AsyncHttpResponse[TenDlcCampaignListResponse] Returns a paginated list of 10DLC Campaigns. """ _response = await self._client_wrapper.httpx_client.request( @@ -1106,13 +1291,35 @@ async def list_by_brand( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ListByBrandCampaignsResponse, + TenDlcCampaignListResponse, parse_obj_as( - type_=ListByBrandCampaignsResponse, # type: ignore + type_=TenDlcCampaignListResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1177,7 +1384,7 @@ async def create( sample5: typing.Optional[str] = OMIT, privacy_policy: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[CreateCampaignsResponse]: + ) -> AsyncHttpResponse[TenDlcCampaign]: """ Registers a 10DLC Campaign under the 10DLC Brand identified by `brand_id`. The Brand must have a verified identity status. @@ -1275,7 +1482,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateCampaignsResponse] + AsyncHttpResponse[TenDlcCampaign] Returns the registered 10DLC Campaign. """ _response = await self._client_wrapper.httpx_client.request( @@ -1320,9 +1527,9 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateCampaignsResponse, + TenDlcCampaign, parse_obj_as( - type_=CreateCampaignsResponse, # type: ignore + type_=TenDlcCampaign, # type: ignore object_=_response.json(), ), ) @@ -1338,6 +1545,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1360,6 +1578,17 @@ async def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -1371,7 +1600,7 @@ async def create( async def get( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[GetCampaignsResponse]: + ) -> AsyncHttpResponse[TenDlcCampaign]: """ Returns the 10DLC Campaign identified by `campaign_id` under the Brand identified by `brand_id`. @@ -1388,7 +1617,7 @@ async def get( Returns ------- - AsyncHttpResponse[GetCampaignsResponse] + AsyncHttpResponse[TenDlcCampaign] Returns the 10DLC Campaign. """ _response = await self._client_wrapper.httpx_client.request( @@ -1399,13 +1628,35 @@ async def get( try: if 200 <= _response.status_code < 300: _data = typing.cast( - GetCampaignsResponse, + TenDlcCampaign, parse_obj_as( - type_=GetCampaignsResponse, # type: ignore + type_=TenDlcCampaign, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1469,7 +1720,7 @@ async def update( privacy_policy: typing.Optional[str] = OMIT, embedded_link_sample: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[UpdateCampaignsResponse]: + ) -> AsyncHttpResponse[TenDlcCampaign]: """ Updates the 10DLC Campaign identified by `campaign_id`. Only the provided fields are changed. @@ -1564,7 +1815,7 @@ async def update( Returns ------- - AsyncHttpResponse[UpdateCampaignsResponse] + AsyncHttpResponse[TenDlcCampaign] Returns the updated 10DLC Campaign. """ _response = await self._client_wrapper.httpx_client.request( @@ -1607,9 +1858,9 @@ async def update( try: if 200 <= _response.status_code < 300: _data = typing.cast( - UpdateCampaignsResponse, + TenDlcCampaign, parse_obj_as( - type_=UpdateCampaignsResponse, # type: ignore + type_=TenDlcCampaign, # type: ignore object_=_response.json(), ), ) @@ -1625,6 +1876,17 @@ async def update( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1647,6 +1909,17 @@ async def update( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -1658,7 +1931,7 @@ async def update( async def delete( self, brand_id: str, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[DeleteCampaignsResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Deletes a 10DLC Campaign. Associated phone numbers cannot be used as Sender IDs once the Campaign is deleted. @@ -1675,7 +1948,7 @@ async def delete( Returns ------- - AsyncHttpResponse[DeleteCampaignsResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The 10DLC Campaign is deleted. """ _response = await self._client_wrapper.httpx_client.request( @@ -1686,13 +1959,35 @@ async def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteCampaignsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteCampaignsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1797,6 +2092,17 @@ async def nudge( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -1823,9 +2129,9 @@ async def nudge( raise TooManyRequestsError( headers=dict(_response.headers), body=typing.cast( - ValidationErrorResponse, + typing.Any, parse_obj_as( - type_=ValidationErrorResponse, # type: ignore + type_=typing.Any, # type: ignore object_=_response.json(), ), ), diff --git a/src/wavix/ten_dlc/campaigns/types/__init__.py b/src/wavix/ten_dlc/campaigns/types/__init__.py index af8fae8..0515073 100644 --- a/src/wavix/ten_dlc/campaigns/types/__init__.py +++ b/src/wavix/ten_dlc/campaigns/types/__init__.py @@ -6,25 +6,9 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .create_campaigns_response import CreateCampaignsResponse - from .delete_campaigns_response import DeleteCampaignsResponse - from .get_campaigns_response import GetCampaignsResponse - from .list_by_brand_campaigns_response import ListByBrandCampaignsResponse - from .list_by_brand_campaigns_response_pagination import ListByBrandCampaignsResponsePagination - from .list_campaigns_response import ListCampaignsResponse - from .list_campaigns_response_pagination import ListCampaignsResponsePagination from .ten_dlc_campaign_update_request_usecase import TenDlcCampaignUpdateRequestUsecase - from .update_campaigns_response import UpdateCampaignsResponse _dynamic_imports: typing.Dict[str, str] = { - "CreateCampaignsResponse": ".create_campaigns_response", - "DeleteCampaignsResponse": ".delete_campaigns_response", - "GetCampaignsResponse": ".get_campaigns_response", - "ListByBrandCampaignsResponse": ".list_by_brand_campaigns_response", - "ListByBrandCampaignsResponsePagination": ".list_by_brand_campaigns_response_pagination", - "ListCampaignsResponse": ".list_campaigns_response", - "ListCampaignsResponsePagination": ".list_campaigns_response_pagination", - "TenDlcCampaignUpdateRequestUsecase": ".ten_dlc_campaign_update_request_usecase", - "UpdateCampaignsResponse": ".update_campaigns_response", + "TenDlcCampaignUpdateRequestUsecase": ".ten_dlc_campaign_update_request_usecase" } @@ -49,14 +33,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "CreateCampaignsResponse", - "DeleteCampaignsResponse", - "GetCampaignsResponse", - "ListByBrandCampaignsResponse", - "ListByBrandCampaignsResponsePagination", - "ListCampaignsResponse", - "ListCampaignsResponsePagination", - "TenDlcCampaignUpdateRequestUsecase", - "UpdateCampaignsResponse", -] +__all__ = ["TenDlcCampaignUpdateRequestUsecase"] diff --git a/src/wavix/ten_dlc/campaigns/types/create_campaigns_response.py b/src/wavix/ten_dlc/campaigns/types/create_campaigns_response.py deleted file mode 100644 index 8229008..0000000 --- a/src/wavix/ten_dlc/campaigns/types/create_campaigns_response.py +++ /dev/null @@ -1,211 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class CreateCampaignsResponse(UniversalBaseModel): - """ - Represents a 10DLC campaign registered under a Brand. A Campaign defines the messaging use case, opt-in and opt-out flows, and the phone numbers permitted to send its traffic. - """ - - affiliate_marketing: bool = pydantic.Field() - """ - Indicates whether the Campaign is used for affiliate marketing. - """ - - age_gated: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain age-gated content. - """ - - auto_renewal: bool = pydantic.Field() - """ - Indicates whether the Campaign should be automatically renewed. - """ - - last_bill_date: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the Campaign was last billed in ISO 8601 format. `null` if the Campaign has never been billed. - """ - - next_bill_date: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the Campaign will be billed next in ISO 8601 format. `null` if the next billing date is not scheduled. - """ - - direct_lending: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain direct lending content. - """ - - embedded_links: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain embedded links. - """ - - embedded_phones: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain embedded phone numbers. - """ - - embedded_link_sample: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample of an embedded link used in Campaign messages. - """ - - brand_id: str = pydantic.Field() - """ - Unique identifier of the Brand that owns the Campaign. - """ - - campaign_id: str = pydantic.Field() - """ - Unique identifier of the Campaign assigned by the registry. - """ - - description: typing.Optional[str] = pydantic.Field(default=None) - """ - Description of the Campaign and its messaging purpose. - """ - - optin_workflow: typing.Optional[str] = pydantic.Field(default=None) - """ - Description of the workflow through which subscribers opt in to the Campaign. - """ - - feedback: typing.Optional[str] = pydantic.Field(default=None) - """ - Feedback from the registry explaining the current `status`. - """ - - help: bool = pydantic.Field() - """ - Indicates whether the campaign includes a help system (for example, keyword: HELP, INFO). - """ - - help_keywords: str = pydantic.Field() - """ - Comma-separated list of help keywords. Keywords are case-insensitive. - """ - - help_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Help message sent upon receiving a help keyword. - """ - - optin: bool = pydantic.Field() - """ - Indicates whether the Campaign requires subscriber opt-in. - """ - - optin_keywords: str = pydantic.Field() - """ - Comma-separated list of opt-in keywords. Keywords are case-insensitive. - """ - - optin_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Opt-in message sent upon receiving an opt-in keyword. - """ - - optout: bool = pydantic.Field() - """ - Indicates whether the campaign includes an opt-out system (for example, keyword: STOP, QUIT). - """ - - optout_keywords: str = pydantic.Field() - """ - Comma-separated list of opt-out keywords. Keywords are case-insensitive. - """ - - optout_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Opt-out message sent upon receiving an opt-out keyword. - """ - - name: str = pydantic.Field() - """ - Display name of the Campaign. - """ - - created_at: str = pydantic.Field() - """ - Timestamp when the Campaign was created, in ISO 8601 format. - """ - - sample1: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample2: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample3: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample4: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample5: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - updated_at: str = pydantic.Field() - """ - Timestamp when the Campaign was last updated, in ISO 8601 format. - """ - - mock: bool = pydantic.Field() - """ - Indicates whether the Campaign is a mock campaign used for testing. Mock campaigns cannot send production traffic. - """ - - usecase: str = pydantic.Field() - """ - Registered use case for the Campaign, such as `2FA` or `MARKETING`. - """ - - monthly_fee: str = pydantic.Field() - """ - Recurring monthly fee charged for the Campaign, as a decimal string. - """ - - privacy_policy: typing.Optional[str] = pydantic.Field(default=None) - """ - Privacy policy URL. - """ - - terms_conditions: typing.Optional[str] = pydantic.Field(default=None) - """ - Terms and conditions URL. - """ - - status: str = pydantic.Field() - """ - Current registration status of the Campaign, such as `APPROVED` or `PENDING`. - """ - - phone_numbers: typing.List[str] = pydantic.Field() - """ - Phone numbers assigned to the Campaign, in E.164 format. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/types/delete_campaigns_response.py b/src/wavix/ten_dlc/campaigns/types/delete_campaigns_response.py deleted file mode 100644 index 9b721cf..0000000 --- a/src/wavix/ten_dlc/campaigns/types/delete_campaigns_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class DeleteCampaignsResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/types/get_campaigns_response.py b/src/wavix/ten_dlc/campaigns/types/get_campaigns_response.py deleted file mode 100644 index b3a63e9..0000000 --- a/src/wavix/ten_dlc/campaigns/types/get_campaigns_response.py +++ /dev/null @@ -1,211 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class GetCampaignsResponse(UniversalBaseModel): - """ - Represents a 10DLC campaign registered under a Brand. A Campaign defines the messaging use case, opt-in and opt-out flows, and the phone numbers permitted to send its traffic. - """ - - affiliate_marketing: bool = pydantic.Field() - """ - Indicates whether the Campaign is used for affiliate marketing. - """ - - age_gated: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain age-gated content. - """ - - auto_renewal: bool = pydantic.Field() - """ - Indicates whether the Campaign should be automatically renewed. - """ - - last_bill_date: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the Campaign was last billed in ISO 8601 format. `null` if the Campaign has never been billed. - """ - - next_bill_date: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the Campaign will be billed next in ISO 8601 format. `null` if the next billing date is not scheduled. - """ - - direct_lending: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain direct lending content. - """ - - embedded_links: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain embedded links. - """ - - embedded_phones: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain embedded phone numbers. - """ - - embedded_link_sample: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample of an embedded link used in Campaign messages. - """ - - brand_id: str = pydantic.Field() - """ - Unique identifier of the Brand that owns the Campaign. - """ - - campaign_id: str = pydantic.Field() - """ - Unique identifier of the Campaign assigned by the registry. - """ - - description: typing.Optional[str] = pydantic.Field(default=None) - """ - Description of the Campaign and its messaging purpose. - """ - - optin_workflow: typing.Optional[str] = pydantic.Field(default=None) - """ - Description of the workflow through which subscribers opt in to the Campaign. - """ - - feedback: typing.Optional[str] = pydantic.Field(default=None) - """ - Feedback from the registry explaining the current `status`. - """ - - help: bool = pydantic.Field() - """ - Indicates whether the campaign includes a help system (for example, keyword: HELP, INFO). - """ - - help_keywords: str = pydantic.Field() - """ - Comma-separated list of help keywords. Keywords are case-insensitive. - """ - - help_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Help message sent upon receiving a help keyword. - """ - - optin: bool = pydantic.Field() - """ - Indicates whether the Campaign requires subscriber opt-in. - """ - - optin_keywords: str = pydantic.Field() - """ - Comma-separated list of opt-in keywords. Keywords are case-insensitive. - """ - - optin_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Opt-in message sent upon receiving an opt-in keyword. - """ - - optout: bool = pydantic.Field() - """ - Indicates whether the campaign includes an opt-out system (for example, keyword: STOP, QUIT). - """ - - optout_keywords: str = pydantic.Field() - """ - Comma-separated list of opt-out keywords. Keywords are case-insensitive. - """ - - optout_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Opt-out message sent upon receiving an opt-out keyword. - """ - - name: str = pydantic.Field() - """ - Display name of the Campaign. - """ - - created_at: str = pydantic.Field() - """ - Timestamp when the Campaign was created, in ISO 8601 format. - """ - - sample1: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample2: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample3: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample4: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample5: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - updated_at: str = pydantic.Field() - """ - Timestamp when the Campaign was last updated, in ISO 8601 format. - """ - - mock: bool = pydantic.Field() - """ - Indicates whether the Campaign is a mock campaign used for testing. Mock campaigns cannot send production traffic. - """ - - usecase: str = pydantic.Field() - """ - Registered use case for the Campaign, such as `2FA` or `MARKETING`. - """ - - monthly_fee: str = pydantic.Field() - """ - Recurring monthly fee charged for the Campaign, as a decimal string. - """ - - privacy_policy: typing.Optional[str] = pydantic.Field(default=None) - """ - Privacy policy URL. - """ - - terms_conditions: typing.Optional[str] = pydantic.Field(default=None) - """ - Terms and conditions URL. - """ - - status: str = pydantic.Field() - """ - Current registration status of the Campaign, such as `APPROVED` or `PENDING`. - """ - - phone_numbers: typing.List[str] = pydantic.Field() - """ - Phone numbers assigned to the Campaign, in E.164 format. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/types/list_by_brand_campaigns_response.py b/src/wavix/ten_dlc/campaigns/types/list_by_brand_campaigns_response.py deleted file mode 100644 index beedf3a..0000000 --- a/src/wavix/ten_dlc/campaigns/types/list_by_brand_campaigns_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.ten_dlc_campaign import TenDlcCampaign -from .list_by_brand_campaigns_response_pagination import ListByBrandCampaignsResponsePagination - - -class ListByBrandCampaignsResponse(UniversalBaseModel): - """ - Paginated list of 10DLC Campaigns. - """ - - items: typing.List[TenDlcCampaign] = pydantic.Field() - """ - 10DLC Campaigns on the current page that match the filter criteria. - """ - - pagination: ListByBrandCampaignsResponsePagination = pydantic.Field() - """ - Pagination metadata for the result set. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/types/list_by_brand_campaigns_response_pagination.py b/src/wavix/ten_dlc/campaigns/types/list_by_brand_campaigns_response_pagination.py deleted file mode 100644 index dcf6661..0000000 --- a/src/wavix/ten_dlc/campaigns/types/list_by_brand_campaigns_response_pagination.py +++ /dev/null @@ -1,41 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class ListByBrandCampaignsResponsePagination(UniversalBaseModel): - """ - Pagination metadata for the result set. - """ - - current_page: int = pydantic.Field() - """ - Current page number. - """ - - per_page: int = pydantic.Field() - """ - Number of records per page. - """ - - total: int = pydantic.Field() - """ - Total number of records. - """ - - total_pages: int = pydantic.Field() - """ - Total number of pages. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/types/list_campaigns_response.py b/src/wavix/ten_dlc/campaigns/types/list_campaigns_response.py deleted file mode 100644 index defe2f7..0000000 --- a/src/wavix/ten_dlc/campaigns/types/list_campaigns_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.ten_dlc_campaign import TenDlcCampaign -from .list_campaigns_response_pagination import ListCampaignsResponsePagination - - -class ListCampaignsResponse(UniversalBaseModel): - """ - Paginated list of 10DLC Campaigns. - """ - - items: typing.List[TenDlcCampaign] = pydantic.Field() - """ - 10DLC Campaigns on the current page that match the filter criteria. - """ - - pagination: ListCampaignsResponsePagination = pydantic.Field() - """ - Pagination metadata for the result set. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/types/list_campaigns_response_pagination.py b/src/wavix/ten_dlc/campaigns/types/list_campaigns_response_pagination.py deleted file mode 100644 index 53261c1..0000000 --- a/src/wavix/ten_dlc/campaigns/types/list_campaigns_response_pagination.py +++ /dev/null @@ -1,41 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class ListCampaignsResponsePagination(UniversalBaseModel): - """ - Pagination metadata for the result set. - """ - - current_page: int = pydantic.Field() - """ - Current page number. - """ - - per_page: int = pydantic.Field() - """ - Number of records per page. - """ - - total: int = pydantic.Field() - """ - Total number of records. - """ - - total_pages: int = pydantic.Field() - """ - Total number of pages. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/campaigns/types/update_campaigns_response.py b/src/wavix/ten_dlc/campaigns/types/update_campaigns_response.py deleted file mode 100644 index 7367d72..0000000 --- a/src/wavix/ten_dlc/campaigns/types/update_campaigns_response.py +++ /dev/null @@ -1,211 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class UpdateCampaignsResponse(UniversalBaseModel): - """ - Represents a 10DLC campaign registered under a Brand. A Campaign defines the messaging use case, opt-in and opt-out flows, and the phone numbers permitted to send its traffic. - """ - - affiliate_marketing: bool = pydantic.Field() - """ - Indicates whether the Campaign is used for affiliate marketing. - """ - - age_gated: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain age-gated content. - """ - - auto_renewal: bool = pydantic.Field() - """ - Indicates whether the Campaign should be automatically renewed. - """ - - last_bill_date: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the Campaign was last billed in ISO 8601 format. `null` if the Campaign has never been billed. - """ - - next_bill_date: typing.Optional[str] = pydantic.Field(default=None) - """ - Date and time the Campaign will be billed next in ISO 8601 format. `null` if the next billing date is not scheduled. - """ - - direct_lending: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain direct lending content. - """ - - embedded_links: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain embedded links. - """ - - embedded_phones: bool = pydantic.Field() - """ - Indicates whether the Campaign messages contain embedded phone numbers. - """ - - embedded_link_sample: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample of an embedded link used in Campaign messages. - """ - - brand_id: str = pydantic.Field() - """ - Unique identifier of the Brand that owns the Campaign. - """ - - campaign_id: str = pydantic.Field() - """ - Unique identifier of the Campaign assigned by the registry. - """ - - description: typing.Optional[str] = pydantic.Field(default=None) - """ - Description of the Campaign and its messaging purpose. - """ - - optin_workflow: typing.Optional[str] = pydantic.Field(default=None) - """ - Description of the workflow through which subscribers opt in to the Campaign. - """ - - feedback: typing.Optional[str] = pydantic.Field(default=None) - """ - Feedback from the registry explaining the current `status`. - """ - - help: bool = pydantic.Field() - """ - Indicates whether the campaign includes a help system (for example, keyword: HELP, INFO). - """ - - help_keywords: str = pydantic.Field() - """ - Comma-separated list of help keywords. Keywords are case-insensitive. - """ - - help_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Help message sent upon receiving a help keyword. - """ - - optin: bool = pydantic.Field() - """ - Indicates whether the Campaign requires subscriber opt-in. - """ - - optin_keywords: str = pydantic.Field() - """ - Comma-separated list of opt-in keywords. Keywords are case-insensitive. - """ - - optin_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Opt-in message sent upon receiving an opt-in keyword. - """ - - optout: bool = pydantic.Field() - """ - Indicates whether the campaign includes an opt-out system (for example, keyword: STOP, QUIT). - """ - - optout_keywords: str = pydantic.Field() - """ - Comma-separated list of opt-out keywords. Keywords are case-insensitive. - """ - - optout_message: typing.Optional[str] = pydantic.Field(default=None) - """ - Opt-out message sent upon receiving an opt-out keyword. - """ - - name: str = pydantic.Field() - """ - Display name of the Campaign. - """ - - created_at: str = pydantic.Field() - """ - Timestamp when the Campaign was created, in ISO 8601 format. - """ - - sample1: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample2: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample3: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample4: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - sample5: typing.Optional[str] = pydantic.Field(default=None) - """ - Sample message demonstrating the content sent through the Campaign. - """ - - updated_at: str = pydantic.Field() - """ - Timestamp when the Campaign was last updated, in ISO 8601 format. - """ - - mock: bool = pydantic.Field() - """ - Indicates whether the Campaign is a mock campaign used for testing. Mock campaigns cannot send production traffic. - """ - - usecase: str = pydantic.Field() - """ - Registered use case for the Campaign, such as `2FA` or `MARKETING`. - """ - - monthly_fee: str = pydantic.Field() - """ - Recurring monthly fee charged for the Campaign, as a decimal string. - """ - - privacy_policy: typing.Optional[str] = pydantic.Field(default=None) - """ - Privacy policy URL. - """ - - terms_conditions: typing.Optional[str] = pydantic.Field(default=None) - """ - Terms and conditions URL. - """ - - status: str = pydantic.Field() - """ - Current registration status of the Campaign, such as `APPROVED` or `PENDING`. - """ - - phone_numbers: typing.List[str] = pydantic.Field() - """ - Phone numbers assigned to the Campaign, in E.164 format. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/subscriptions/__init__.py b/src/wavix/ten_dlc/subscriptions/__init__.py index fce3a1f..5cde020 100644 --- a/src/wavix/ten_dlc/subscriptions/__init__.py +++ b/src/wavix/ten_dlc/subscriptions/__init__.py @@ -2,36 +2,3 @@ # isort: skip_file -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .types import CreateSubscriptionsResponse, DeleteSubscriptionsResponse -_dynamic_imports: typing.Dict[str, str] = { - "CreateSubscriptionsResponse": ".types", - "DeleteSubscriptionsResponse": ".types", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["CreateSubscriptionsResponse", "DeleteSubscriptionsResponse"] diff --git a/src/wavix/ten_dlc/subscriptions/client.py b/src/wavix/ten_dlc/subscriptions/client.py index c089df1..30e2076 100644 --- a/src/wavix/ten_dlc/subscriptions/client.py +++ b/src/wavix/ten_dlc/subscriptions/client.py @@ -4,10 +4,9 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.success_response import SuccessResponse from ...types.ten_dlc_event_subscription import TenDlcEventSubscription from .raw_client import AsyncRawSubscriptionsClient, RawSubscriptionsClient -from .types.create_subscriptions_response import CreateSubscriptionsResponse -from .types.delete_subscriptions_response import DeleteSubscriptionsResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -56,7 +55,7 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ty def create( self, *, subscription_category: str, url: str, request_options: typing.Optional[RequestOptions] = None - ) -> CreateSubscriptionsResponse: + ) -> TenDlcEventSubscription: """ Registers a callback URL to receive Wavix 10DLC event notifications. @@ -73,7 +72,7 @@ def create( Returns ------- - CreateSubscriptionsResponse + TenDlcEventSubscription Returns the created 10DLC event subscription. Examples @@ -95,7 +94,7 @@ def create( def delete( self, *, subscription_category: str, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteSubscriptionsResponse: + ) -> SuccessResponse: """ Removes the 10DLC event subscription for the specified event category. @@ -109,7 +108,7 @@ def delete( Returns ------- - DeleteSubscriptionsResponse + SuccessResponse Returns a success confirmation. The event subscription is removed. Examples @@ -182,7 +181,7 @@ async def main() -> None: async def create( self, *, subscription_category: str, url: str, request_options: typing.Optional[RequestOptions] = None - ) -> CreateSubscriptionsResponse: + ) -> TenDlcEventSubscription: """ Registers a callback URL to receive Wavix 10DLC event notifications. @@ -199,7 +198,7 @@ async def create( Returns ------- - CreateSubscriptionsResponse + TenDlcEventSubscription Returns the created 10DLC event subscription. Examples @@ -229,7 +228,7 @@ async def main() -> None: async def delete( self, *, subscription_category: str, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteSubscriptionsResponse: + ) -> SuccessResponse: """ Removes the 10DLC event subscription for the specified event category. @@ -243,7 +242,7 @@ async def delete( Returns ------- - DeleteSubscriptionsResponse + SuccessResponse Returns a success confirmation. The event subscription is removed. Examples diff --git a/src/wavix/ten_dlc/subscriptions/raw_client.py b/src/wavix/ten_dlc/subscriptions/raw_client.py index dea33fa..5de65a9 100644 --- a/src/wavix/ten_dlc/subscriptions/raw_client.py +++ b/src/wavix/ten_dlc/subscriptions/raw_client.py @@ -11,9 +11,12 @@ from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError +from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError +from ...errors.unprocessable_entity_error import UnprocessableEntityError +from ...types.success_response import SuccessResponse from ...types.ten_dlc_event_subscription import TenDlcEventSubscription -from .types.create_subscriptions_response import CreateSubscriptionsResponse -from .types.delete_subscriptions_response import DeleteSubscriptionsResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError # this is used as the default value for optional parameters @@ -55,6 +58,28 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -77,7 +102,7 @@ def list( def create( self, *, subscription_category: str, url: str, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[CreateSubscriptionsResponse]: + ) -> HttpResponse[TenDlcEventSubscription]: """ Registers a callback URL to receive Wavix 10DLC event notifications. @@ -94,7 +119,7 @@ def create( Returns ------- - HttpResponse[CreateSubscriptionsResponse] + HttpResponse[TenDlcEventSubscription] Returns the created 10DLC event subscription. """ _response = self._client_wrapper.httpx_client.request( @@ -113,13 +138,35 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateSubscriptionsResponse, + TenDlcEventSubscription, parse_obj_as( - type_=CreateSubscriptionsResponse, # type: ignore + type_=TenDlcEventSubscription, # type: ignore object_=_response.json(), ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -131,6 +178,17 @@ def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -142,7 +200,7 @@ def create( def delete( self, *, subscription_category: str, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[DeleteSubscriptionsResponse]: + ) -> HttpResponse[SuccessResponse]: """ Removes the 10DLC event subscription for the specified event category. @@ -156,7 +214,7 @@ def delete( Returns ------- - HttpResponse[DeleteSubscriptionsResponse] + HttpResponse[SuccessResponse] Returns a success confirmation. The event subscription is removed. """ _response = self._client_wrapper.httpx_client.request( @@ -170,9 +228,9 @@ def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteSubscriptionsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteSubscriptionsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -188,6 +246,17 @@ def delete( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -199,6 +268,17 @@ def delete( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -244,6 +324,28 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -266,7 +368,7 @@ async def list( async def create( self, *, subscription_category: str, url: str, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[CreateSubscriptionsResponse]: + ) -> AsyncHttpResponse[TenDlcEventSubscription]: """ Registers a callback URL to receive Wavix 10DLC event notifications. @@ -283,7 +385,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateSubscriptionsResponse] + AsyncHttpResponse[TenDlcEventSubscription] Returns the created 10DLC event subscription. """ _response = await self._client_wrapper.httpx_client.request( @@ -302,13 +404,35 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateSubscriptionsResponse, + TenDlcEventSubscription, parse_obj_as( - type_=CreateSubscriptionsResponse, # type: ignore + type_=TenDlcEventSubscription, # type: ignore object_=_response.json(), ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -320,6 +444,17 @@ async def create( ), ), ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -331,7 +466,7 @@ async def create( async def delete( self, *, subscription_category: str, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[DeleteSubscriptionsResponse]: + ) -> AsyncHttpResponse[SuccessResponse]: """ Removes the 10DLC event subscription for the specified event category. @@ -345,7 +480,7 @@ async def delete( Returns ------- - AsyncHttpResponse[DeleteSubscriptionsResponse] + AsyncHttpResponse[SuccessResponse] Returns a success confirmation. The event subscription is removed. """ _response = await self._client_wrapper.httpx_client.request( @@ -359,9 +494,9 @@ async def delete( try: if 200 <= _response.status_code < 300: _data = typing.cast( - DeleteSubscriptionsResponse, + SuccessResponse, parse_obj_as( - type_=DeleteSubscriptionsResponse, # type: ignore + type_=SuccessResponse, # type: ignore object_=_response.json(), ), ) @@ -377,6 +512,17 @@ async def delete( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -388,6 +534,17 @@ async def delete( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) diff --git a/src/wavix/ten_dlc/subscriptions/types/__init__.py b/src/wavix/ten_dlc/subscriptions/types/__init__.py deleted file mode 100644 index 5fc752a..0000000 --- a/src/wavix/ten_dlc/subscriptions/types/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -# isort: skip_file - -import typing -from importlib import import_module - -if typing.TYPE_CHECKING: - from .create_subscriptions_response import CreateSubscriptionsResponse - from .delete_subscriptions_response import DeleteSubscriptionsResponse -_dynamic_imports: typing.Dict[str, str] = { - "CreateSubscriptionsResponse": ".create_subscriptions_response", - "DeleteSubscriptionsResponse": ".delete_subscriptions_response", -} - - -def __getattr__(attr_name: str) -> typing.Any: - module_name = _dynamic_imports.get(attr_name) - if module_name is None: - raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") - try: - module = import_module(module_name, __package__) - if module_name == f".{attr_name}": - return module - else: - return getattr(module, attr_name) - except ImportError as e: - raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e - except AttributeError as e: - raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e - - -def __dir__(): - lazy_attrs = list(_dynamic_imports.keys()) - return sorted(lazy_attrs) - - -__all__ = ["CreateSubscriptionsResponse", "DeleteSubscriptionsResponse"] diff --git a/src/wavix/ten_dlc/subscriptions/types/create_subscriptions_response.py b/src/wavix/ten_dlc/subscriptions/types/create_subscriptions_response.py deleted file mode 100644 index a477b00..0000000 --- a/src/wavix/ten_dlc/subscriptions/types/create_subscriptions_response.py +++ /dev/null @@ -1,31 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class CreateSubscriptionsResponse(UniversalBaseModel): - """ - Represents a subscription that delivers 10DLC lifecycle events to a webhook URL. - """ - - subscription_category: str = pydantic.Field() - """ - Category of 10DLC events to subscribe to. One of `brand` (brand status changes), `campaign` (campaign status changes), or `number` (number provisioning changes). - """ - - url: str = pydantic.Field() - """ - Webhook URL that events in this category are delivered to. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/ten_dlc/subscriptions/types/delete_subscriptions_response.py b/src/wavix/ten_dlc/subscriptions/types/delete_subscriptions_response.py deleted file mode 100644 index fb1d9c6..0000000 --- a/src/wavix/ten_dlc/subscriptions/types/delete_subscriptions_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class DeleteSubscriptionsResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/two_fa/__init__.py b/src/wavix/two_fa/__init__.py index 8b0948a..500a8f9 100644 --- a/src/wavix/two_fa/__init__.py +++ b/src/wavix/two_fa/__init__.py @@ -7,16 +7,8 @@ if typing.TYPE_CHECKING: from . import events, sessions, verification - from .verification import ( - CheckVerificationResponse, - CreateVerificationResponse, - ResendVerificationResponse, - TwoFactorVerificationResendRequestChannel, - ) + from .verification import TwoFactorVerificationResendRequestChannel _dynamic_imports: typing.Dict[str, str] = { - "CheckVerificationResponse": ".verification", - "CreateVerificationResponse": ".verification", - "ResendVerificationResponse": ".verification", "TwoFactorVerificationResendRequestChannel": ".verification", "events": ".events", "sessions": ".sessions", @@ -45,12 +37,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "CheckVerificationResponse", - "CreateVerificationResponse", - "ResendVerificationResponse", - "TwoFactorVerificationResendRequestChannel", - "events", - "sessions", - "verification", -] +__all__ = ["TwoFactorVerificationResendRequestChannel", "events", "sessions", "verification"] diff --git a/src/wavix/two_fa/events/raw_client.py b/src/wavix/two_fa/events/raw_client.py index 5ccfc19..c50d692 100644 --- a/src/wavix/two_fa/events/raw_client.py +++ b/src/wavix/two_fa/events/raw_client.py @@ -10,9 +10,12 @@ 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.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...types.two_factor_verification_event import TwoFactorVerificationEvent +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -54,6 +57,28 @@ def list( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -124,6 +149,28 @@ async def list( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/two_fa/sessions/raw_client.py b/src/wavix/two_fa/sessions/raw_client.py index eaccd62..599563d 100644 --- a/src/wavix/two_fa/sessions/raw_client.py +++ b/src/wavix/two_fa/sessions/raw_client.py @@ -14,7 +14,9 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.unauthorized_error import UnauthorizedError from ...types.list_sessions_response_item import ListSessionsResponseItem +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from pydantic import ValidationError @@ -77,6 +79,17 @@ def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -168,6 +181,17 @@ async def list( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/two_fa/verification/__init__.py b/src/wavix/two_fa/verification/__init__.py index 8988388..9fff4b6 100644 --- a/src/wavix/two_fa/verification/__init__.py +++ b/src/wavix/two_fa/verification/__init__.py @@ -6,18 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import ( - CheckVerificationResponse, - CreateVerificationResponse, - ResendVerificationResponse, - TwoFactorVerificationResendRequestChannel, - ) -_dynamic_imports: typing.Dict[str, str] = { - "CheckVerificationResponse": ".types", - "CreateVerificationResponse": ".types", - "ResendVerificationResponse": ".types", - "TwoFactorVerificationResendRequestChannel": ".types", -} + from .types import TwoFactorVerificationResendRequestChannel +_dynamic_imports: typing.Dict[str, str] = {"TwoFactorVerificationResendRequestChannel": ".types"} def __getattr__(attr_name: str) -> typing.Any: @@ -41,9 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "CheckVerificationResponse", - "CreateVerificationResponse", - "ResendVerificationResponse", - "TwoFactorVerificationResendRequestChannel", -] +__all__ = ["TwoFactorVerificationResendRequestChannel"] diff --git a/src/wavix/two_fa/verification/client.py b/src/wavix/two_fa/verification/client.py index dddc593..dad8ba9 100644 --- a/src/wavix/two_fa/verification/client.py +++ b/src/wavix/two_fa/verification/client.py @@ -5,10 +5,10 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions from ...types.success_response import SuccessResponse +from ...types.two_factor_verification_check_response import TwoFactorVerificationCheckResponse +from ...types.two_factor_verification_resend_response import TwoFactorVerificationResendResponse +from ...types.two_factor_verification_response import TwoFactorVerificationResponse from .raw_client import AsyncRawVerificationClient, RawVerificationClient -from .types.check_verification_response import CheckVerificationResponse -from .types.create_verification_response import CreateVerificationResponse -from .types.resend_verification_response import ResendVerificationResponse from .types.two_factor_verification_resend_request_channel import TwoFactorVerificationResendRequestChannel # this is used as the default value for optional parameters @@ -32,9 +32,9 @@ def with_raw_response(self) -> RawVerificationClient: def create( self, *, service_id: str, to: str, channel: str, request_options: typing.Optional[RequestOptions] = None - ) -> CreateVerificationResponse: + ) -> TwoFactorVerificationResponse: """ - Creates a 2FA verification and sends a one-time password (OTP) to the destination phone number over the selected channel. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. + Creates a 2FA verification and sends a real one-time password (OTP) to the destination phone number over the selected channel; this bills the account per OTP sent. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. The verification proceeds through three steps: 1. Create a verification to generate and send an OTP. @@ -57,7 +57,7 @@ def create( Returns ------- - CreateVerificationResponse + TwoFactorVerificationResponse Returns the created 2FA verification. Examples @@ -84,7 +84,7 @@ def resend( *, channel: TwoFactorVerificationResendRequestChannel, request_options: typing.Optional[RequestOptions] = None, - ) -> ResendVerificationResponse: + ) -> TwoFactorVerificationResendResponse: """ Resends the OTP for the verification identified by `session_id` over the specified channel. Previously sent codes are invalidated. @@ -101,7 +101,7 @@ def resend( Returns ------- - ResendVerificationResponse + TwoFactorVerificationResendResponse Returns the resend result, including the channel used. Examples @@ -121,9 +121,9 @@ def resend( def check( self, session_id: str, *, code: str, request_options: typing.Optional[RequestOptions] = None - ) -> CheckVerificationResponse: + ) -> TwoFactorVerificationCheckResponse: """ - Validates the OTP submitted by the end user against the verification identified by `session_id`. + Validates the OTP submitted by the end user against the verification identified by `session_id`. Non-idempotent — each call consumes one of a limited number of attempts tracked server-side; once exhausted, the verification returns `429` until a new verification is created. Parameters ---------- @@ -138,7 +138,7 @@ def check( Returns ------- - CheckVerificationResponse + TwoFactorVerificationCheckResponse Returns the validation result in `is_valid`. Examples @@ -205,9 +205,9 @@ def with_raw_response(self) -> AsyncRawVerificationClient: async def create( self, *, service_id: str, to: str, channel: str, request_options: typing.Optional[RequestOptions] = None - ) -> CreateVerificationResponse: + ) -> TwoFactorVerificationResponse: """ - Creates a 2FA verification and sends a one-time password (OTP) to the destination phone number over the selected channel. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. + Creates a 2FA verification and sends a real one-time password (OTP) to the destination phone number over the selected channel; this bills the account per OTP sent. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. The verification proceeds through three steps: 1. Create a verification to generate and send an OTP. @@ -230,7 +230,7 @@ async def create( Returns ------- - CreateVerificationResponse + TwoFactorVerificationResponse Returns the created 2FA verification. Examples @@ -265,7 +265,7 @@ async def resend( *, channel: TwoFactorVerificationResendRequestChannel, request_options: typing.Optional[RequestOptions] = None, - ) -> ResendVerificationResponse: + ) -> TwoFactorVerificationResendResponse: """ Resends the OTP for the verification identified by `session_id` over the specified channel. Previously sent codes are invalidated. @@ -282,7 +282,7 @@ async def resend( Returns ------- - ResendVerificationResponse + TwoFactorVerificationResendResponse Returns the resend result, including the channel used. Examples @@ -310,9 +310,9 @@ async def main() -> None: async def check( self, session_id: str, *, code: str, request_options: typing.Optional[RequestOptions] = None - ) -> CheckVerificationResponse: + ) -> TwoFactorVerificationCheckResponse: """ - Validates the OTP submitted by the end user against the verification identified by `session_id`. + Validates the OTP submitted by the end user against the verification identified by `session_id`. Non-idempotent — each call consumes one of a limited number of attempts tracked server-side; once exhausted, the verification returns `429` until a new verification is created. Parameters ---------- @@ -327,7 +327,7 @@ async def check( Returns ------- - CheckVerificationResponse + TwoFactorVerificationCheckResponse Returns the validation result in `is_valid`. Examples diff --git a/src/wavix/two_fa/verification/raw_client.py b/src/wavix/two_fa/verification/raw_client.py index a30c1d7..05495fe 100644 --- a/src/wavix/two_fa/verification/raw_client.py +++ b/src/wavix/two_fa/verification/raw_client.py @@ -13,10 +13,14 @@ from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.success_response import SuccessResponse -from .types.check_verification_response import CheckVerificationResponse -from .types.create_verification_response import CreateVerificationResponse -from .types.resend_verification_response import ResendVerificationResponse +from ...types.two_factor_verification_check_response import TwoFactorVerificationCheckResponse +from ...types.two_factor_verification_resend_response import TwoFactorVerificationResendResponse +from ...types.two_factor_verification_response import TwoFactorVerificationResponse +from ...types.unauthorized_error_response import UnauthorizedErrorResponse from .types.two_factor_verification_resend_request_channel import TwoFactorVerificationResendRequestChannel from pydantic import ValidationError @@ -30,9 +34,9 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def create( self, *, service_id: str, to: str, channel: str, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[CreateVerificationResponse]: + ) -> HttpResponse[TwoFactorVerificationResponse]: """ - Creates a 2FA verification and sends a one-time password (OTP) to the destination phone number over the selected channel. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. + Creates a 2FA verification and sends a real one-time password (OTP) to the destination phone number over the selected channel; this bills the account per OTP sent. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. The verification proceeds through three steps: 1. Create a verification to generate and send an OTP. @@ -55,7 +59,7 @@ def create( Returns ------- - HttpResponse[CreateVerificationResponse] + HttpResponse[TwoFactorVerificationResponse] Returns the created 2FA verification. """ _response = self._client_wrapper.httpx_client.request( @@ -75,9 +79,9 @@ def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateVerificationResponse, + TwoFactorVerificationResponse, parse_obj_as( - type_=CreateVerificationResponse, # type: ignore + type_=TwoFactorVerificationResponse, # type: ignore object_=_response.json(), ), ) @@ -93,6 +97,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -104,6 +119,28 @@ def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -119,7 +156,7 @@ def resend( *, channel: TwoFactorVerificationResendRequestChannel, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ResendVerificationResponse]: + ) -> HttpResponse[TwoFactorVerificationResendResponse]: """ Resends the OTP for the verification identified by `session_id` over the specified channel. Previously sent codes are invalidated. @@ -136,7 +173,7 @@ def resend( Returns ------- - HttpResponse[ResendVerificationResponse] + HttpResponse[TwoFactorVerificationResendResponse] Returns the resend result, including the channel used. """ _response = self._client_wrapper.httpx_client.request( @@ -154,9 +191,9 @@ def resend( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ResendVerificationResponse, + TwoFactorVerificationResendResponse, parse_obj_as( - type_=ResendVerificationResponse, # type: ignore + type_=TwoFactorVerificationResendResponse, # type: ignore object_=_response.json(), ), ) @@ -172,6 +209,17 @@ def resend( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -183,6 +231,28 @@ def resend( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -194,9 +264,9 @@ def resend( def check( self, session_id: str, *, code: str, request_options: typing.Optional[RequestOptions] = None - ) -> HttpResponse[CheckVerificationResponse]: + ) -> HttpResponse[TwoFactorVerificationCheckResponse]: """ - Validates the OTP submitted by the end user against the verification identified by `session_id`. + Validates the OTP submitted by the end user against the verification identified by `session_id`. Non-idempotent — each call consumes one of a limited number of attempts tracked server-side; once exhausted, the verification returns `429` until a new verification is created. Parameters ---------- @@ -211,7 +281,7 @@ def check( Returns ------- - HttpResponse[CheckVerificationResponse] + HttpResponse[TwoFactorVerificationCheckResponse] Returns the validation result in `is_valid`. """ _response = self._client_wrapper.httpx_client.request( @@ -229,9 +299,9 @@ def check( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CheckVerificationResponse, + TwoFactorVerificationCheckResponse, parse_obj_as( - type_=CheckVerificationResponse, # type: ignore + type_=TwoFactorVerificationCheckResponse, # type: ignore object_=_response.json(), ), ) @@ -247,6 +317,17 @@ def check( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -258,6 +339,28 @@ def check( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -312,6 +415,17 @@ def cancel( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -350,9 +464,9 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def create( self, *, service_id: str, to: str, channel: str, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[CreateVerificationResponse]: + ) -> AsyncHttpResponse[TwoFactorVerificationResponse]: """ - Creates a 2FA verification and sends a one-time password (OTP) to the destination phone number over the selected channel. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. + Creates a 2FA verification and sends a real one-time password (OTP) to the destination phone number over the selected channel; this bills the account per OTP sent. Requires a 2FA service configured in the Wavix portal; the service is reused to generate and validate OTPs. The verification proceeds through three steps: 1. Create a verification to generate and send an OTP. @@ -375,7 +489,7 @@ async def create( Returns ------- - AsyncHttpResponse[CreateVerificationResponse] + AsyncHttpResponse[TwoFactorVerificationResponse] Returns the created 2FA verification. """ _response = await self._client_wrapper.httpx_client.request( @@ -395,9 +509,9 @@ async def create( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CreateVerificationResponse, + TwoFactorVerificationResponse, parse_obj_as( - type_=CreateVerificationResponse, # type: ignore + type_=TwoFactorVerificationResponse, # type: ignore object_=_response.json(), ), ) @@ -413,6 +527,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -424,6 +549,28 @@ async def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -439,7 +586,7 @@ async def resend( *, channel: TwoFactorVerificationResendRequestChannel, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ResendVerificationResponse]: + ) -> AsyncHttpResponse[TwoFactorVerificationResendResponse]: """ Resends the OTP for the verification identified by `session_id` over the specified channel. Previously sent codes are invalidated. @@ -456,7 +603,7 @@ async def resend( Returns ------- - AsyncHttpResponse[ResendVerificationResponse] + AsyncHttpResponse[TwoFactorVerificationResendResponse] Returns the resend result, including the channel used. """ _response = await self._client_wrapper.httpx_client.request( @@ -474,9 +621,9 @@ async def resend( try: if 200 <= _response.status_code < 300: _data = typing.cast( - ResendVerificationResponse, + TwoFactorVerificationResendResponse, parse_obj_as( - type_=ResendVerificationResponse, # type: ignore + type_=TwoFactorVerificationResendResponse, # type: ignore object_=_response.json(), ), ) @@ -492,6 +639,17 @@ async def resend( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -503,6 +661,28 @@ async def resend( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -514,9 +694,9 @@ async def resend( async def check( self, session_id: str, *, code: str, request_options: typing.Optional[RequestOptions] = None - ) -> AsyncHttpResponse[CheckVerificationResponse]: + ) -> AsyncHttpResponse[TwoFactorVerificationCheckResponse]: """ - Validates the OTP submitted by the end user against the verification identified by `session_id`. + Validates the OTP submitted by the end user against the verification identified by `session_id`. Non-idempotent — each call consumes one of a limited number of attempts tracked server-side; once exhausted, the verification returns `429` until a new verification is created. Parameters ---------- @@ -531,7 +711,7 @@ async def check( Returns ------- - AsyncHttpResponse[CheckVerificationResponse] + AsyncHttpResponse[TwoFactorVerificationCheckResponse] Returns the validation result in `is_valid`. """ _response = await self._client_wrapper.httpx_client.request( @@ -549,9 +729,9 @@ async def check( try: if 200 <= _response.status_code < 300: _data = typing.cast( - CheckVerificationResponse, + TwoFactorVerificationCheckResponse, parse_obj_as( - type_=CheckVerificationResponse, # type: ignore + type_=TwoFactorVerificationCheckResponse, # type: ignore object_=_response.json(), ), ) @@ -567,6 +747,17 @@ async def check( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -578,6 +769,28 @@ async def check( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) @@ -632,6 +845,17 @@ async def cancel( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/two_fa/verification/types/__init__.py b/src/wavix/two_fa/verification/types/__init__.py index 8f28453..fdd8d83 100644 --- a/src/wavix/two_fa/verification/types/__init__.py +++ b/src/wavix/two_fa/verification/types/__init__.py @@ -6,15 +6,9 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .check_verification_response import CheckVerificationResponse - from .create_verification_response import CreateVerificationResponse - from .resend_verification_response import ResendVerificationResponse from .two_factor_verification_resend_request_channel import TwoFactorVerificationResendRequestChannel _dynamic_imports: typing.Dict[str, str] = { - "CheckVerificationResponse": ".check_verification_response", - "CreateVerificationResponse": ".create_verification_response", - "ResendVerificationResponse": ".resend_verification_response", - "TwoFactorVerificationResendRequestChannel": ".two_factor_verification_resend_request_channel", + "TwoFactorVerificationResendRequestChannel": ".two_factor_verification_resend_request_channel" } @@ -39,9 +33,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = [ - "CheckVerificationResponse", - "CreateVerificationResponse", - "ResendVerificationResponse", - "TwoFactorVerificationResendRequestChannel", -] +__all__ = ["TwoFactorVerificationResendRequestChannel"] diff --git a/src/wavix/two_fa/verification/types/check_verification_response.py b/src/wavix/two_fa/verification/types/check_verification_response.py deleted file mode 100644 index 50e198e..0000000 --- a/src/wavix/two_fa/verification/types/check_verification_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class CheckVerificationResponse(UniversalBaseModel): - is_valid: bool = pydantic.Field() - """ - Indicates whether the entered code is valid - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/two_fa/verification/types/create_verification_response.py b/src/wavix/two_fa/verification/types/create_verification_response.py deleted file mode 100644 index 9b688c6..0000000 --- a/src/wavix/two_fa/verification/types/create_verification_response.py +++ /dev/null @@ -1,51 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.phone_lookup_details import PhoneLookupDetails - - -class CreateVerificationResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the 2FA Verification was successfully created - """ - - service_id: str = pydantic.Field() - """ - Unique identifier of the Wavix 2FA Service - """ - - session_url: str = pydantic.Field() - """ - Automatically generated 2FA Verification URL. The URL can be used to resend or validate the OTP. - """ - - session_id: str = pydantic.Field() - """ - Unique identifier of the Wavix 2FA Verification - """ - - destination: str = pydantic.Field() - """ - The end user's phone number. - """ - - created_at: dt.datetime = pydantic.Field() - """ - Date and time the 2FA Verification is created - """ - - number_lookup: PhoneLookupDetails - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/two_fa/verification/types/resend_verification_response.py b/src/wavix/two_fa/verification/types/resend_verification_response.py deleted file mode 100644 index d01b43c..0000000 --- a/src/wavix/two_fa/verification/types/resend_verification_response.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class ResendVerificationResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the verification code was successfully sent - """ - - channel: str = pydantic.Field() - """ - Indicates whether the code was sent via an SMS or a voice call - """ - - destination: str = pydantic.Field() - """ - The destination phone number the code was sent to - """ - - created_at: dt.datetime = pydantic.Field() - """ - Date and time the code was sent - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/wavix/types/__init__.py b/src/wavix/types/__init__.py index 0e83249..35c7aea 100644 --- a/src/wavix/types/__init__.py +++ b/src/wavix/types/__init__.py @@ -15,9 +15,9 @@ from .api_key_calls_scope_permission_allow import ApiKeyCallsScopePermissionAllow from .api_key_scope_permission import ApiKeyScopePermission from .api_key_scope_permission_allow import ApiKeyScopePermissionAllow + from .api_key_with_secret import ApiKeyWithSecret from .available_number import AvailableNumber from .available_number_list_response import AvailableNumberListResponse - from .bad_request_error_body import BadRequestErrorBody from .billing_transaction_list_response import BillingTransactionListResponse from .brand_status_updated_webhook import BrandStatusUpdatedWebhook from .brand_status_updated_webhook_status import BrandStatusUpdatedWebhookStatus @@ -58,13 +58,11 @@ from .country_has_no_regions_error_response import CountryHasNoRegionsErrorResponse from .country_list_response import CountryListResponse from .document_type import DocumentType - from .document_type_id import DocumentTypeId + from .document_type_info import DocumentTypeInfo from .file_transcript_response import FileTranscriptResponse from .file_transcript_turn import FileTranscriptTurn from .file_transcription_completed_webhook import FileTranscriptionCompletedWebhook from .file_transcription_response import FileTranscriptionResponse - from .file_transcription_response_language import FileTranscriptionResponseLanguage - from .file_transcription_response_status import FileTranscriptionResponseStatus from .financial_transaction import FinancialTransaction from .forbidden_error_response import ForbiddenErrorResponse from .inbound_call_destination import InboundCallDestination @@ -82,7 +80,6 @@ from .message_list_response import MessageListResponse from .message_response import MessageResponse from .messages_delivery_report import MessagesDeliveryReport - from .not_found_error_body import NotFoundErrorBody from .not_found_error_response import NotFoundErrorResponse from .number import Number from .number_destination import NumberDestination @@ -148,9 +145,11 @@ from .ten_dlc_brand import TenDlcBrand from .ten_dlc_brand_appeal import TenDlcBrandAppeal from .ten_dlc_brand_appeal_create_request import TenDlcBrandAppealCreateRequest + from .ten_dlc_brand_appeal_create_request_appeal_categories_item import ( + TenDlcBrandAppealCreateRequestAppealCategoriesItem, + ) from .ten_dlc_brand_appeal_outcome import TenDlcBrandAppealOutcome from .ten_dlc_brand_appeal_outcome_feedback import TenDlcBrandAppealOutcomeFeedback - from .ten_dlc_brand_appeal_outcome_vetting_status import TenDlcBrandAppealOutcomeVettingStatus from .ten_dlc_brand_create_request import TenDlcBrandCreateRequest from .ten_dlc_brand_create_request_entity_type import TenDlcBrandCreateRequestEntityType from .ten_dlc_brand_create_request_stock_exchange import TenDlcBrandCreateRequestStockExchange @@ -164,7 +163,6 @@ from .ten_dlc_brand_list_response import TenDlcBrandListResponse from .ten_dlc_brand_list_response_pagination import TenDlcBrandListResponsePagination from .ten_dlc_brand_qualification_result import TenDlcBrandQualificationResult - from .ten_dlc_brand_status import TenDlcBrandStatus from .ten_dlc_brand_vetting import TenDlcBrandVetting from .ten_dlc_brand_vetting_appeal import TenDlcBrandVettingAppeal from .ten_dlc_brand_vetting_appeal_appeal_outcome import TenDlcBrandVettingAppealAppealOutcome @@ -180,6 +178,7 @@ from .ten_dlc_campaign_number_list_response import TenDlcCampaignNumberListResponse from .ten_dlc_event_subscription import TenDlcEventSubscription from .ten_dlcmno_metadata import TenDlcmnoMetadata + from .too_many_requests_error_response import TooManyRequestsErrorResponse from .transaction_status import TransactionStatus from .transaction_type import TransactionType from .transcript_turn import TranscriptTurn @@ -208,6 +207,40 @@ from .web_rtc_token import WebRtcToken from .web_rtc_token_response import WebRtcTokenResponse from .web_rtc_tokens_list_response import WebRtcTokensListResponse + from .whats_app_message import WhatsAppMessage + from .whats_app_message_get_response import WhatsAppMessageGetResponse + from .whats_app_message_list_item import WhatsAppMessageListItem + from .whats_app_message_list_item_direction import WhatsAppMessageListItemDirection + from .whats_app_message_list_item_status import WhatsAppMessageListItemStatus + from .whats_app_message_list_response import WhatsAppMessageListResponse + from .whats_app_message_send_request import WhatsAppMessageSendRequest + from .whats_app_message_send_request_template import WhatsAppMessageSendRequestTemplate + from .whats_app_message_send_request_template_buttons_item import WhatsAppMessageSendRequestTemplateButtonsItem + from .whats_app_message_send_request_template_buttons_item_type import ( + WhatsAppMessageSendRequestTemplateButtonsItemType, + ) + from .whats_app_message_send_request_template_header import WhatsAppMessageSendRequestTemplateHeader + from .whats_app_message_send_request_template_header_type import WhatsAppMessageSendRequestTemplateHeaderType + from .whats_app_message_send_response import WhatsAppMessageSendResponse + from .whats_app_message_status import WhatsAppMessageStatus + from .whats_app_message_template import WhatsAppMessageTemplate + from .whats_app_problem import WhatsAppProblem + from .whats_app_problem_error_class import WhatsAppProblemErrorClass + from .whats_app_sender import WhatsAppSender + from .whats_app_sender_message_tier import WhatsAppSenderMessageTier + from .whats_app_sender_quality_rating import WhatsAppSenderQualityRating + from .whats_app_sender_status import WhatsAppSenderStatus + from .whats_app_template import WhatsAppTemplate + from .whats_app_template_category import WhatsAppTemplateCategory + from .whats_app_template_component import WhatsAppTemplateComponent + from .whats_app_template_component_format import WhatsAppTemplateComponentFormat + from .whats_app_template_component_type import WhatsAppTemplateComponentType + from .whats_app_template_create_request import WhatsAppTemplateCreateRequest + from .whats_app_template_create_request_category import WhatsAppTemplateCreateRequestCategory + from .whats_app_template_list_response import WhatsAppTemplateListResponse + from .whats_app_template_quality_rating import WhatsAppTemplateQualityRating + from .whats_app_template_response import WhatsAppTemplateResponse + from .whats_app_template_status import WhatsAppTemplateStatus _dynamic_imports: typing.Dict[str, str] = { "AccountErrorResponse": ".account_error_response", "AccountLimits": ".account_limits", @@ -218,9 +251,9 @@ "ApiKeyCallsScopePermissionAllow": ".api_key_calls_scope_permission_allow", "ApiKeyScopePermission": ".api_key_scope_permission", "ApiKeyScopePermissionAllow": ".api_key_scope_permission_allow", + "ApiKeyWithSecret": ".api_key_with_secret", "AvailableNumber": ".available_number", "AvailableNumberListResponse": ".available_number_list_response", - "BadRequestErrorBody": ".bad_request_error_body", "BillingTransactionListResponse": ".billing_transaction_list_response", "BrandStatusUpdatedWebhook": ".brand_status_updated_webhook", "BrandStatusUpdatedWebhookStatus": ".brand_status_updated_webhook_status", @@ -261,13 +294,11 @@ "CountryHasNoRegionsErrorResponse": ".country_has_no_regions_error_response", "CountryListResponse": ".country_list_response", "DocumentType": ".document_type", - "DocumentTypeId": ".document_type_id", + "DocumentTypeInfo": ".document_type_info", "FileTranscriptResponse": ".file_transcript_response", "FileTranscriptTurn": ".file_transcript_turn", "FileTranscriptionCompletedWebhook": ".file_transcription_completed_webhook", "FileTranscriptionResponse": ".file_transcription_response", - "FileTranscriptionResponseLanguage": ".file_transcription_response_language", - "FileTranscriptionResponseStatus": ".file_transcription_response_status", "FinancialTransaction": ".financial_transaction", "ForbiddenErrorResponse": ".forbidden_error_response", "InboundCallDestination": ".inbound_call_destination", @@ -285,7 +316,6 @@ "MessageListResponse": ".message_list_response", "MessageResponse": ".message_response", "MessagesDeliveryReport": ".messages_delivery_report", - "NotFoundErrorBody": ".not_found_error_body", "NotFoundErrorResponse": ".not_found_error_response", "Number": ".number", "NumberDestination": ".number_destination", @@ -349,9 +379,9 @@ "TenDlcBrand": ".ten_dlc_brand", "TenDlcBrandAppeal": ".ten_dlc_brand_appeal", "TenDlcBrandAppealCreateRequest": ".ten_dlc_brand_appeal_create_request", + "TenDlcBrandAppealCreateRequestAppealCategoriesItem": ".ten_dlc_brand_appeal_create_request_appeal_categories_item", "TenDlcBrandAppealOutcome": ".ten_dlc_brand_appeal_outcome", "TenDlcBrandAppealOutcomeFeedback": ".ten_dlc_brand_appeal_outcome_feedback", - "TenDlcBrandAppealOutcomeVettingStatus": ".ten_dlc_brand_appeal_outcome_vetting_status", "TenDlcBrandCreateRequest": ".ten_dlc_brand_create_request", "TenDlcBrandCreateRequestEntityType": ".ten_dlc_brand_create_request_entity_type", "TenDlcBrandCreateRequestStockExchange": ".ten_dlc_brand_create_request_stock_exchange", @@ -365,7 +395,6 @@ "TenDlcBrandListResponse": ".ten_dlc_brand_list_response", "TenDlcBrandListResponsePagination": ".ten_dlc_brand_list_response_pagination", "TenDlcBrandQualificationResult": ".ten_dlc_brand_qualification_result", - "TenDlcBrandStatus": ".ten_dlc_brand_status", "TenDlcBrandVetting": ".ten_dlc_brand_vetting", "TenDlcBrandVettingAppeal": ".ten_dlc_brand_vetting_appeal", "TenDlcBrandVettingAppealAppealOutcome": ".ten_dlc_brand_vetting_appeal_appeal_outcome", @@ -381,6 +410,7 @@ "TenDlcCampaignNumberListResponse": ".ten_dlc_campaign_number_list_response", "TenDlcEventSubscription": ".ten_dlc_event_subscription", "TenDlcmnoMetadata": ".ten_dlcmno_metadata", + "TooManyRequestsErrorResponse": ".too_many_requests_error_response", "TransactionStatus": ".transaction_status", "TransactionType": ".transaction_type", "TranscriptTurn": ".transcript_turn", @@ -409,6 +439,38 @@ "WebRtcToken": ".web_rtc_token", "WebRtcTokenResponse": ".web_rtc_token_response", "WebRtcTokensListResponse": ".web_rtc_tokens_list_response", + "WhatsAppMessage": ".whats_app_message", + "WhatsAppMessageGetResponse": ".whats_app_message_get_response", + "WhatsAppMessageListItem": ".whats_app_message_list_item", + "WhatsAppMessageListItemDirection": ".whats_app_message_list_item_direction", + "WhatsAppMessageListItemStatus": ".whats_app_message_list_item_status", + "WhatsAppMessageListResponse": ".whats_app_message_list_response", + "WhatsAppMessageSendRequest": ".whats_app_message_send_request", + "WhatsAppMessageSendRequestTemplate": ".whats_app_message_send_request_template", + "WhatsAppMessageSendRequestTemplateButtonsItem": ".whats_app_message_send_request_template_buttons_item", + "WhatsAppMessageSendRequestTemplateButtonsItemType": ".whats_app_message_send_request_template_buttons_item_type", + "WhatsAppMessageSendRequestTemplateHeader": ".whats_app_message_send_request_template_header", + "WhatsAppMessageSendRequestTemplateHeaderType": ".whats_app_message_send_request_template_header_type", + "WhatsAppMessageSendResponse": ".whats_app_message_send_response", + "WhatsAppMessageStatus": ".whats_app_message_status", + "WhatsAppMessageTemplate": ".whats_app_message_template", + "WhatsAppProblem": ".whats_app_problem", + "WhatsAppProblemErrorClass": ".whats_app_problem_error_class", + "WhatsAppSender": ".whats_app_sender", + "WhatsAppSenderMessageTier": ".whats_app_sender_message_tier", + "WhatsAppSenderQualityRating": ".whats_app_sender_quality_rating", + "WhatsAppSenderStatus": ".whats_app_sender_status", + "WhatsAppTemplate": ".whats_app_template", + "WhatsAppTemplateCategory": ".whats_app_template_category", + "WhatsAppTemplateComponent": ".whats_app_template_component", + "WhatsAppTemplateComponentFormat": ".whats_app_template_component_format", + "WhatsAppTemplateComponentType": ".whats_app_template_component_type", + "WhatsAppTemplateCreateRequest": ".whats_app_template_create_request", + "WhatsAppTemplateCreateRequestCategory": ".whats_app_template_create_request_category", + "WhatsAppTemplateListResponse": ".whats_app_template_list_response", + "WhatsAppTemplateQualityRating": ".whats_app_template_quality_rating", + "WhatsAppTemplateResponse": ".whats_app_template_response", + "WhatsAppTemplateStatus": ".whats_app_template_status", } @@ -443,9 +505,9 @@ def __dir__(): "ApiKeyCallsScopePermissionAllow", "ApiKeyScopePermission", "ApiKeyScopePermissionAllow", + "ApiKeyWithSecret", "AvailableNumber", "AvailableNumberListResponse", - "BadRequestErrorBody", "BillingTransactionListResponse", "BrandStatusUpdatedWebhook", "BrandStatusUpdatedWebhookStatus", @@ -486,13 +548,11 @@ def __dir__(): "CountryHasNoRegionsErrorResponse", "CountryListResponse", "DocumentType", - "DocumentTypeId", + "DocumentTypeInfo", "FileTranscriptResponse", "FileTranscriptTurn", "FileTranscriptionCompletedWebhook", "FileTranscriptionResponse", - "FileTranscriptionResponseLanguage", - "FileTranscriptionResponseStatus", "FinancialTransaction", "ForbiddenErrorResponse", "InboundCallDestination", @@ -510,7 +570,6 @@ def __dir__(): "MessageListResponse", "MessageResponse", "MessagesDeliveryReport", - "NotFoundErrorBody", "NotFoundErrorResponse", "Number", "NumberDestination", @@ -574,9 +633,9 @@ def __dir__(): "TenDlcBrand", "TenDlcBrandAppeal", "TenDlcBrandAppealCreateRequest", + "TenDlcBrandAppealCreateRequestAppealCategoriesItem", "TenDlcBrandAppealOutcome", "TenDlcBrandAppealOutcomeFeedback", - "TenDlcBrandAppealOutcomeVettingStatus", "TenDlcBrandCreateRequest", "TenDlcBrandCreateRequestEntityType", "TenDlcBrandCreateRequestStockExchange", @@ -590,7 +649,6 @@ def __dir__(): "TenDlcBrandListResponse", "TenDlcBrandListResponsePagination", "TenDlcBrandQualificationResult", - "TenDlcBrandStatus", "TenDlcBrandVetting", "TenDlcBrandVettingAppeal", "TenDlcBrandVettingAppealAppealOutcome", @@ -606,6 +664,7 @@ def __dir__(): "TenDlcCampaignNumberListResponse", "TenDlcEventSubscription", "TenDlcmnoMetadata", + "TooManyRequestsErrorResponse", "TransactionStatus", "TransactionType", "TranscriptTurn", @@ -634,4 +693,36 @@ def __dir__(): "WebRtcToken", "WebRtcTokenResponse", "WebRtcTokensListResponse", + "WhatsAppMessage", + "WhatsAppMessageGetResponse", + "WhatsAppMessageListItem", + "WhatsAppMessageListItemDirection", + "WhatsAppMessageListItemStatus", + "WhatsAppMessageListResponse", + "WhatsAppMessageSendRequest", + "WhatsAppMessageSendRequestTemplate", + "WhatsAppMessageSendRequestTemplateButtonsItem", + "WhatsAppMessageSendRequestTemplateButtonsItemType", + "WhatsAppMessageSendRequestTemplateHeader", + "WhatsAppMessageSendRequestTemplateHeaderType", + "WhatsAppMessageSendResponse", + "WhatsAppMessageStatus", + "WhatsAppMessageTemplate", + "WhatsAppProblem", + "WhatsAppProblemErrorClass", + "WhatsAppSender", + "WhatsAppSenderMessageTier", + "WhatsAppSenderQualityRating", + "WhatsAppSenderStatus", + "WhatsAppTemplate", + "WhatsAppTemplateCategory", + "WhatsAppTemplateComponent", + "WhatsAppTemplateComponentFormat", + "WhatsAppTemplateComponentType", + "WhatsAppTemplateCreateRequest", + "WhatsAppTemplateCreateRequestCategory", + "WhatsAppTemplateListResponse", + "WhatsAppTemplateQualityRating", + "WhatsAppTemplateResponse", + "WhatsAppTemplateStatus", ] diff --git a/src/wavix/types/api_key_with_secret.py b/src/wavix/types/api_key_with_secret.py new file mode 100644 index 0000000..9d40e32 --- /dev/null +++ b/src/wavix/types/api_key_with_secret.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from .api_key import ApiKey + +ApiKeyWithSecret = ApiKey +""" +API key details, including the secret `value`. Returned only at creation time — +store it securely, it cannot be retrieved again. +""" diff --git a/src/wavix/types/available_number.py b/src/wavix/types/available_number.py index 3002d9d..8341a31 100644 --- a/src/wavix/types/available_number.py +++ b/src/wavix/types/available_number.py @@ -4,6 +4,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .document_type import DocumentType class AvailableNumber(UniversalBaseModel): @@ -66,9 +67,9 @@ class AvailableNumber(UniversalBaseModel): Phone number in E.164 format. """ - require_docs: typing.List[int] = pydantic.Field() + require_docs: typing.List[DocumentType] = pydantic.Field() """ - Documents required to activate the phone number. + Documents to activate the number. """ sms_enabled: bool = pydantic.Field() diff --git a/src/wavix/types/cart_response.py b/src/wavix/types/cart_response.py index 49ddc26..53c30fe 100644 --- a/src/wavix/types/cart_response.py +++ b/src/wavix/types/cart_response.py @@ -5,7 +5,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .available_number import AvailableNumber -from .document_type import DocumentType +from .document_type_info import DocumentTypeInfo class CartResponse(UniversalBaseModel): @@ -14,7 +14,7 @@ class CartResponse(UniversalBaseModel): List of phone numbers in the cart. """ - doc_types: typing.List[DocumentType] = pydantic.Field() + doc_types: typing.List[DocumentTypeInfo] = pydantic.Field() """ Document types required to activate phone numbers. """ diff --git a/src/wavix/types/cdr_transcription_response.py b/src/wavix/types/cdr_transcription_response.py index f72ff8a..98ef6a8 100644 --- a/src/wavix/types/cdr_transcription_response.py +++ b/src/wavix/types/cdr_transcription_response.py @@ -26,7 +26,7 @@ class CdrTranscriptionResponse(UniversalBaseModel): uuid_: typing_extensions.Annotated[ str, FieldMetadata(alias="uuid"), pydantic.Field(alias="uuid", description="Transcription ID.") ] - language: TranscriptionLanguage + language: typing.Optional[TranscriptionLanguage] = None duration: int = pydantic.Field() """ Call duration in seconds. diff --git a/src/wavix/types/document_type.py b/src/wavix/types/document_type.py index 98e9cdd..032daca 100644 --- a/src/wavix/types/document_type.py +++ b/src/wavix/types/document_type.py @@ -2,31 +2,4 @@ import typing -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel - - -class DocumentType(UniversalBaseModel): - id: int = pydantic.Field() - """ - Document type ID. - """ - - name: str = pydantic.Field() - """ - Document type name. - """ - - title: str = pydantic.Field() - """ - Human-readable document type name. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow +DocumentType = typing.Union[typing.Literal["id", "address", "localaddress"], typing.Any] diff --git a/src/wavix/types/document_type_id.py b/src/wavix/types/document_type_id.py deleted file mode 100644 index 72a3282..0000000 --- a/src/wavix/types/document_type_id.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -DocumentTypeId = int -""" -Specifies the type of document required to activate the phone number. -Possible values are: `1` - Proof of identity, `2` - Proof of address, `3` - Proof of business registration. -""" diff --git a/src/wavix/buy/numbers/types/list_numbers_response.py b/src/wavix/types/document_type_info.py similarity index 51% rename from src/wavix/buy/numbers/types/list_numbers_response.py rename to src/wavix/types/document_type_info.py index 4122a84..b3f3a89 100644 --- a/src/wavix/buy/numbers/types/list_numbers_response.py +++ b/src/wavix/types/document_type_info.py @@ -3,18 +3,25 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.available_number import AvailableNumber -from ....types.pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .document_type import DocumentType -class ListNumbersResponse(UniversalBaseModel): - dids: typing.List[AvailableNumber] = pydantic.Field() +class DocumentTypeInfo(UniversalBaseModel): """ - Phone numbers available for purchase that match the search criteria. + Document type required to activate a phone number. """ - pagination: Pagination + id: int = pydantic.Field() + """ + Document type ID. + """ + + name: DocumentType + title: str = pydantic.Field() + """ + Document type name. + """ if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/wavix/types/file_transcription_response.py b/src/wavix/types/file_transcription_response.py index db74443..cf685ac 100644 --- a/src/wavix/types/file_transcription_response.py +++ b/src/wavix/types/file_transcription_response.py @@ -7,8 +7,8 @@ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .file_transcript_response import FileTranscriptResponse from .file_transcript_turn import FileTranscriptTurn -from .file_transcription_response_language import FileTranscriptionResponseLanguage -from .file_transcription_response_status import FileTranscriptionResponseStatus +from .transcription_language import TranscriptionLanguage +from .transcription_status import TranscriptionStatus class FileTranscriptionResponse(UniversalBaseModel): @@ -27,7 +27,7 @@ class FileTranscriptionResponse(UniversalBaseModel): Transcription request ID. """ - language: FileTranscriptionResponseLanguage = pydantic.Field() + language: typing.Optional[TranscriptionLanguage] = pydantic.Field(default=None) """ Transcription language. """ @@ -42,7 +42,7 @@ class FileTranscriptionResponse(UniversalBaseModel): Total transcription charge in USD. """ - status: FileTranscriptionResponseStatus = pydantic.Field() + status: TranscriptionStatus = pydantic.Field() """ Transcription status. Possible values are `completed`, `failed`. """ diff --git a/src/wavix/types/file_transcription_response_language.py b/src/wavix/types/file_transcription_response_language.py deleted file mode 100644 index c0b790b..0000000 --- a/src/wavix/types/file_transcription_response_language.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -FileTranscriptionResponseLanguage = typing.Union[typing.Literal["en", "de", "es", "fr", "it"], typing.Any] diff --git a/src/wavix/types/file_transcription_response_status.py b/src/wavix/types/file_transcription_response_status.py deleted file mode 100644 index 004f0ce..0000000 --- a/src/wavix/types/file_transcription_response_status.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -FileTranscriptionResponseStatus = typing.Union[typing.Literal["completed", "failed"], typing.Any] diff --git a/src/wavix/types/number.py b/src/wavix/types/number.py index bdffd45..6d345e2 100644 --- a/src/wavix/types/number.py +++ b/src/wavix/types/number.py @@ -5,6 +5,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .document_type import DocumentType from .inbound_call_destination import InboundCallDestination from .number_document import NumberDocument @@ -65,14 +66,14 @@ class Number(UniversalBaseModel): Maximum number of concurrent inbound calls. """ - require_docs: typing.List[str] = pydantic.Field() + require_docs: typing.List[DocumentType] = pydantic.Field() """ - Documents required to activate the phone number. + Documents to activate the number. """ documents: typing.List[NumberDocument] = pydantic.Field() """ - Uploaded documents for the phone number. + Uploaded documents. """ domestic_cli: bool = pydantic.Field() diff --git a/src/wavix/types/number_document.py b/src/wavix/types/number_document.py index 1b92572..7407bf9 100644 --- a/src/wavix/types/number_document.py +++ b/src/wavix/types/number_document.py @@ -4,7 +4,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from .document_type_id import DocumentTypeId +from .document_type import DocumentType class NumberDocument(UniversalBaseModel): @@ -37,7 +37,11 @@ class NumberDocument(UniversalBaseModel): The uploaded document name """ - doc_type_id: DocumentTypeId + doc_type: typing.Optional[DocumentType] = pydantic.Field(default=None) + """ + Document type. + """ + status: str = pydantic.Field() """ Status of the uploaded document. Can be either `approved`, `pending`, or `rejected` diff --git a/src/wavix/types/number_list_response.py b/src/wavix/types/number_list_response.py index e996fca..f19b3ab 100644 --- a/src/wavix/types/number_list_response.py +++ b/src/wavix/types/number_list_response.py @@ -4,7 +4,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from .document_type import DocumentType +from .document_type_info import DocumentTypeInfo from .number import Number from .pagination import Pagination @@ -15,7 +15,7 @@ class NumberListResponse(UniversalBaseModel): List of phone numbers on the account. """ - doc_types: typing.List[DocumentType] = pydantic.Field() + doc_types: typing.List[DocumentTypeInfo] = pydantic.Field() """ Documents required to activate phone numbers. """ diff --git a/src/wavix/types/sip_trunk_create_request.py b/src/wavix/types/sip_trunk_create_request.py index 66a270e..3a7ec78 100644 --- a/src/wavix/types/sip_trunk_create_request.py +++ b/src/wavix/types/sip_trunk_create_request.py @@ -59,7 +59,7 @@ class SipTrunkCreateRequest(UniversalBaseModel): Maximum call duration for the SIP trunk, in seconds. Must not exceed the maximum duration set for the account. Ignored when `call_restrict` is `false`. """ - cost_limit: bool = pydantic.Field() + cost_limit: typing.Optional[bool] = pydantic.Field(default=None) """ Indicates if the max cost limit for an outbound call limit is activated for the SIP trunk. """ diff --git a/src/wavix/types/ten_dlc_brand.py b/src/wavix/types/ten_dlc_brand.py index 2fd9e08..de89fe4 100644 --- a/src/wavix/types/ten_dlc_brand.py +++ b/src/wavix/types/ten_dlc_brand.py @@ -5,7 +5,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .ten_dlc_brand_entity_type import TenDlcBrandEntityType -from .ten_dlc_brand_status import TenDlcBrandStatus +from .ten_dlc_brand_identity_verification_status import TenDlcBrandIdentityVerificationStatus class TenDlcBrand(UniversalBaseModel): @@ -48,7 +48,7 @@ class TenDlcBrand(UniversalBaseModel): ISO 3166-1 alpha-2 country code where the Tax ID was issued. """ - status: TenDlcBrandStatus = pydantic.Field() + status: TenDlcBrandIdentityVerificationStatus = pydantic.Field() """ Brand identity verification status. """ diff --git a/src/wavix/types/ten_dlc_brand_appeal.py b/src/wavix/types/ten_dlc_brand_appeal.py index 3b06f55..67ca2b2 100644 --- a/src/wavix/types/ten_dlc_brand_appeal.py +++ b/src/wavix/types/ten_dlc_brand_appeal.py @@ -1,6 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt import typing import pydantic @@ -14,7 +13,7 @@ class TenDlcBrandAppeal(UniversalBaseModel): A list of Brand Identity status appeal categories associated with the original request """ - created_at: dt.datetime = pydantic.Field() + created_at: str = pydantic.Field() """ The date and time the appeal request is created """ @@ -34,7 +33,7 @@ class TenDlcBrandAppeal(UniversalBaseModel): The appeal status """ - updated_at: dt.datetime = pydantic.Field() + updated_at: str = pydantic.Field() """ The date and time the appeal request is updated """ diff --git a/src/wavix/types/ten_dlc_brand_appeal_create_request.py b/src/wavix/types/ten_dlc_brand_appeal_create_request.py index 475985d..a3a0126 100644 --- a/src/wavix/types/ten_dlc_brand_appeal_create_request.py +++ b/src/wavix/types/ten_dlc_brand_appeal_create_request.py @@ -4,6 +4,9 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .ten_dlc_brand_appeal_create_request_appeal_categories_item import ( + TenDlcBrandAppealCreateRequestAppealCategoriesItem, +) class TenDlcBrandAppealCreateRequest(UniversalBaseModel): @@ -11,7 +14,7 @@ class TenDlcBrandAppealCreateRequest(UniversalBaseModel): Brand identity verification appeal details. """ - appeal_categories: typing.List[str] = pydantic.Field() + appeal_categories: typing.List[TenDlcBrandAppealCreateRequestAppealCategoriesItem] = pydantic.Field() """ List of appeal categories. Allowed values: `VERIFY_TAX_ID`, `VERIFY_NON_PROFIT`, `VERIFY_GOVERNMENT` """ diff --git a/src/wavix/types/ten_dlc_brand_appeal_create_request_appeal_categories_item.py b/src/wavix/types/ten_dlc_brand_appeal_create_request_appeal_categories_item.py new file mode 100644 index 0000000..21bd7cc --- /dev/null +++ b/src/wavix/types/ten_dlc_brand_appeal_create_request_appeal_categories_item.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +TenDlcBrandAppealCreateRequestAppealCategoriesItem = typing.Union[ + typing.Literal["VERIFY_TAX_ID", "VERIFY_NON_PROFIT", "VERIFY_GOVERNMENT"], typing.Any +] diff --git a/src/wavix/types/ten_dlc_brand_appeal_outcome.py b/src/wavix/types/ten_dlc_brand_appeal_outcome.py index c2cc4ec..0b83932 100644 --- a/src/wavix/types/ten_dlc_brand_appeal_outcome.py +++ b/src/wavix/types/ten_dlc_brand_appeal_outcome.py @@ -5,7 +5,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .ten_dlc_brand_appeal_outcome_feedback import TenDlcBrandAppealOutcomeFeedback -from .ten_dlc_brand_appeal_outcome_vetting_status import TenDlcBrandAppealOutcomeVettingStatus +from .ten_dlc_brand_identity_verification_status import TenDlcBrandIdentityVerificationStatus class TenDlcBrandAppealOutcome(UniversalBaseModel): @@ -18,7 +18,7 @@ class TenDlcBrandAppealOutcome(UniversalBaseModel): An optional attributes that might be returned from TCR """ - vetting_status: TenDlcBrandAppealOutcomeVettingStatus = pydantic.Field() + vetting_status: TenDlcBrandIdentityVerificationStatus = pydantic.Field() """ Brand Identity Verification appeal outcome """ diff --git a/src/wavix/types/ten_dlc_brand_appeal_outcome_vetting_status.py b/src/wavix/types/ten_dlc_brand_appeal_outcome_vetting_status.py deleted file mode 100644 index 094f262..0000000 --- a/src/wavix/types/ten_dlc_brand_appeal_outcome_vetting_status.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -TenDlcBrandAppealOutcomeVettingStatus = typing.Union[ - typing.Literal["REVIEW", "VERIFIED", "UNVERIFIED", "VETTED_VERIFIED", "SUSPENDED"], typing.Any -] diff --git a/src/wavix/types/ten_dlc_brand_status.py b/src/wavix/types/ten_dlc_brand_status.py deleted file mode 100644 index daea288..0000000 --- a/src/wavix/types/ten_dlc_brand_status.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -TenDlcBrandStatus = typing.Union[ - typing.Literal["REVIEW", "VERIFIED", "UNVERIFIED", "VETTED_VERIFIED", "SUSPENDED"], typing.Any -] diff --git a/src/wavix/types/ten_dlc_brand_vetting_appeal.py b/src/wavix/types/ten_dlc_brand_vetting_appeal.py index f9c5f35..1ed16ad 100644 --- a/src/wavix/types/ten_dlc_brand_vetting_appeal.py +++ b/src/wavix/types/ten_dlc_brand_vetting_appeal.py @@ -1,6 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt import typing import pydantic @@ -23,7 +22,7 @@ class TenDlcBrandVettingAppeal(UniversalBaseModel): Current status of the appeal, such as `PENDING` or `COMPLETE`. """ - appeal_status_update_date: dt.datetime = pydantic.Field() + appeal_status_update_date: str = pydantic.Field() """ Timestamp when the appeal status was last updated, in ISO 8601 format. """ diff --git a/src/wavix/types/bad_request_error_body.py b/src/wavix/types/too_many_requests_error_response.py similarity index 83% rename from src/wavix/types/bad_request_error_body.py rename to src/wavix/types/too_many_requests_error_response.py index dab5e5b..0e3de4e 100644 --- a/src/wavix/types/bad_request_error_body.py +++ b/src/wavix/types/too_many_requests_error_response.py @@ -6,7 +6,7 @@ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -class BadRequestErrorBody(UniversalBaseModel): +class TooManyRequestsErrorResponse(UniversalBaseModel): success: bool = pydantic.Field() """ Indicates whether the request was successful. Always `false` for this error. @@ -14,7 +14,7 @@ class BadRequestErrorBody(UniversalBaseModel): message: str = pydantic.Field() """ - Human-readable error description + Human-readable description stating that the rate limit was exceeded. """ if IS_PYDANTIC_V2: diff --git a/src/wavix/types/transaction_type.py b/src/wavix/types/transaction_type.py index d9058d0..d9007c0 100644 --- a/src/wavix/types/transaction_type.py +++ b/src/wavix/types/transaction_type.py @@ -43,6 +43,7 @@ * 53 - Inbound SMS carrier fee * 54 - Outbound MMS carrier fee * 55 - Inbound MMS carrier fee + * 56 - 10DLC Campaign vetting fee * 57 - Outbound SMS segment * 58 - Inbound SMS segment * 59 - Outbound MMS segment diff --git a/src/wavix/types/transcription_filter.py b/src/wavix/types/transcription_filter.py index 92c8560..31469ae 100644 --- a/src/wavix/types/transcription_filter.py +++ b/src/wavix/types/transcription_filter.py @@ -10,17 +10,17 @@ class TranscriptionFilter(UniversalBaseModel): - agent: TranscriptionFilterAgent = pydantic.Field() + agent: typing.Optional[TranscriptionFilterAgent] = pydantic.Field(default=None) """ Search in an agent's spoken words and phrases """ - client: TranscriptionFilterClient = pydantic.Field() + client: typing.Optional[TranscriptionFilterClient] = pydantic.Field(default=None) """ Search in an customer's spoken words and phrases """ - any: TranscriptionFilterAny = pydantic.Field() + any: typing.Optional[TranscriptionFilterAny] = pydantic.Field(default=None) """ Search in both speakers' spoken words and phrases """ diff --git a/src/wavix/types/unprocessable_entity_error_body.py b/src/wavix/types/unprocessable_entity_error_body.py index f61c539..6b31a0d 100644 --- a/src/wavix/types/unprocessable_entity_error_body.py +++ b/src/wavix/types/unprocessable_entity_error_body.py @@ -7,14 +7,14 @@ class UnprocessableEntityErrorBody(UniversalBaseModel): - success: bool = pydantic.Field() + error: typing.Optional[str] = pydantic.Field(default=None) """ - Indicates whether the request was successful. Always `false` for this error. + Human-readable error description. """ - message: str = pydantic.Field() + error_dids: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ - Human-readable error description + Numbers from the cart that could not be purchased. """ if IS_PYDANTIC_V2: diff --git a/src/wavix/types/whats_app_message.py b/src/wavix/types/whats_app_message.py new file mode 100644 index 0000000..60e1f0e --- /dev/null +++ b/src/wavix/types/whats_app_message.py @@ -0,0 +1,49 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .whats_app_message_status import WhatsAppMessageStatus +from .whats_app_message_template import WhatsAppMessageTemplate + + +class WhatsAppMessage(UniversalBaseModel): + uuid_: typing_extensions.Annotated[ + str, FieldMetadata(alias="uuid"), pydantic.Field(alias="uuid", description="Message ID.") + ] + from_: typing_extensions.Annotated[ + str, + FieldMetadata(alias="from"), + pydantic.Field(alias="from", description="Sender's phone number in E.164 digits."), + ] + to: str = pydantic.Field() + """ + Recipient's phone number in E.164 digits. + """ + + status: WhatsAppMessageStatus = pydantic.Field() + """ + Message delivery status. + """ + + template: typing.Optional[WhatsAppMessageTemplate] = pydantic.Field(default=None) + """ + Template used to send the message. + """ + + created_at: str = pydantic.Field() + """ + Date and time the message was created, in ISO 8601 format. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/numbers/types/delete_numbers_response.py b/src/wavix/types/whats_app_message_get_response.py similarity index 63% rename from src/wavix/numbers/types/delete_numbers_response.py rename to src/wavix/types/whats_app_message_get_response.py index 88a5912..e4f5f37 100644 --- a/src/wavix/numbers/types/delete_numbers_response.py +++ b/src/wavix/types/whats_app_message_get_response.py @@ -3,14 +3,12 @@ import typing import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_message_list_item import WhatsAppMessageListItem -class DeleteNumbersResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ +class WhatsAppMessageGetResponse(UniversalBaseModel): + message: WhatsAppMessageListItem if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/wavix/types/whats_app_message_list_item.py b/src/wavix/types/whats_app_message_list_item.py new file mode 100644 index 0000000..179a6aa --- /dev/null +++ b/src/wavix/types/whats_app_message_list_item.py @@ -0,0 +1,57 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .whats_app_message_list_item_direction import WhatsAppMessageListItemDirection +from .whats_app_message_list_item_status import WhatsAppMessageListItemStatus + + +class WhatsAppMessageListItem(UniversalBaseModel): + uuid_: typing_extensions.Annotated[ + str, FieldMetadata(alias="uuid"), pydantic.Field(alias="uuid", description="Message ID.") + ] + direction: WhatsAppMessageListItemDirection = pydantic.Field() + """ + Message direction. + """ + + status: WhatsAppMessageListItemStatus = pydantic.Field() + """ + Message delivery status. + """ + + from_: typing_extensions.Annotated[ + str, + FieldMetadata(alias="from"), + pydantic.Field( + alias="from", + description="For `outbound` messages, the sender's phone number. For `inbound`, the originating phone number.", + ), + ] + to: str = pydantic.Field() + """ + For `outbound` messages, the recipient's phone number. For `inbound`, the sender's phone number. + """ + + country: typing.Optional[str] = pydantic.Field(default=None) + """ + Recipient's country, derived from the phone number. + """ + + created_at: str = pydantic.Field() + """ + Date and time the message was created, in ISO 8601 format. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_message_list_item_direction.py b/src/wavix/types/whats_app_message_list_item_direction.py new file mode 100644 index 0000000..a524a55 --- /dev/null +++ b/src/wavix/types/whats_app_message_list_item_direction.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppMessageListItemDirection = typing.Union[typing.Literal["outbound", "inbound"], typing.Any] diff --git a/src/wavix/types/whats_app_message_list_item_status.py b/src/wavix/types/whats_app_message_list_item_status.py new file mode 100644 index 0000000..f75b083 --- /dev/null +++ b/src/wavix/types/whats_app_message_list_item_status.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppMessageListItemStatus = typing.Union[ + typing.Literal["failed", "sent", "delivered", "undelivered", "expired", "rejected", "unknown"], typing.Any +] diff --git a/src/wavix/sms_and_mms/messages/types/list_messages_response.py b/src/wavix/types/whats_app_message_list_response.py similarity index 61% rename from src/wavix/sms_and_mms/messages/types/list_messages_response.py rename to src/wavix/types/whats_app_message_list_response.py index 5da8279..fb609c0 100644 --- a/src/wavix/sms_and_mms/messages/types/list_messages_response.py +++ b/src/wavix/types/whats_app_message_list_response.py @@ -3,13 +3,13 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.message import Message -from ....types.pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .pagination import Pagination +from .whats_app_message_list_item import WhatsAppMessageListItem -class ListMessagesResponse(UniversalBaseModel): - items: typing.List[Message] = pydantic.Field() +class WhatsAppMessageListResponse(UniversalBaseModel): + messages: typing.List[WhatsAppMessageListItem] = pydantic.Field() """ Messages that match the request. """ diff --git a/src/wavix/types/whats_app_message_send_request.py b/src/wavix/types/whats_app_message_send_request.py new file mode 100644 index 0000000..f9bc34e --- /dev/null +++ b/src/wavix/types/whats_app_message_send_request.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .whats_app_message_send_request_template import WhatsAppMessageSendRequestTemplate + + +class WhatsAppMessageSendRequest(UniversalBaseModel): + from_: typing_extensions.Annotated[ + str, + FieldMetadata(alias="from"), + pydantic.Field(alias="from", description="Sender's phone number, 6-20 digits."), + ] + to: str = pydantic.Field() + """ + Recipient's phone number, 6-20 digits. + """ + + template: WhatsAppMessageSendRequestTemplate + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_message_send_request_template.py b/src/wavix/types/whats_app_message_send_request_template.py new file mode 100644 index 0000000..e4adcb5 --- /dev/null +++ b/src/wavix/types/whats_app_message_send_request_template.py @@ -0,0 +1,44 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_message_send_request_template_buttons_item import WhatsAppMessageSendRequestTemplateButtonsItem +from .whats_app_message_send_request_template_header import WhatsAppMessageSendRequestTemplateHeader + + +class WhatsAppMessageSendRequestTemplate(UniversalBaseModel): + name: str = pydantic.Field() + """ + Approved template name. + """ + + language: str = pydantic.Field() + """ + Template language code. + """ + + placeholders: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + Values substituted into the template body's `{{n}}` placeholders, in order. + """ + + header: typing.Optional[WhatsAppMessageSendRequestTemplateHeader] = pydantic.Field(default=None) + """ + Header content, required only when the template's `HEADER` component needs one. + """ + + buttons: typing.Optional[typing.List[WhatsAppMessageSendRequestTemplateButtonsItem]] = pydantic.Field(default=None) + """ + Dynamic values for the template's `BUTTONS` component, one entry per button, matching the template's button order. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/buy/countries/types/list_countries_response.py b/src/wavix/types/whats_app_message_send_request_template_buttons_item.py similarity index 54% rename from src/wavix/buy/countries/types/list_countries_response.py rename to src/wavix/types/whats_app_message_send_request_template_buttons_item.py index d00a933..2789919 100644 --- a/src/wavix/buy/countries/types/list_countries_response.py +++ b/src/wavix/types/whats_app_message_send_request_template_buttons_item.py @@ -3,15 +3,12 @@ import typing import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from ....types.country import Country +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_message_send_request_template_buttons_item_type import WhatsAppMessageSendRequestTemplateButtonsItemType -class ListCountriesResponse(UniversalBaseModel): - countries: typing.List[Country] = pydantic.Field() - """ - Countries where phone numbers are available. - """ +class WhatsAppMessageSendRequestTemplateButtonsItem(UniversalBaseModel): + type: WhatsAppMessageSendRequestTemplateButtonsItemType if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/wavix/types/whats_app_message_send_request_template_buttons_item_type.py b/src/wavix/types/whats_app_message_send_request_template_buttons_item_type.py new file mode 100644 index 0000000..a1111fe --- /dev/null +++ b/src/wavix/types/whats_app_message_send_request_template_buttons_item_type.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppMessageSendRequestTemplateButtonsItemType = typing.Union[ + typing.Literal[ + "QUICK_REPLY", "URL", "COPY_CODE", "FLOW", "CATALOG", "MULTI_PRODUCT", "ORDER_DETAILS", "VOICE_CALL" + ], + typing.Any, +] diff --git a/src/wavix/types/whats_app_message_send_request_template_header.py b/src/wavix/types/whats_app_message_send_request_template_header.py new file mode 100644 index 0000000..fe8f1a3 --- /dev/null +++ b/src/wavix/types/whats_app_message_send_request_template_header.py @@ -0,0 +1,60 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .whats_app_message_send_request_template_header_type import WhatsAppMessageSendRequestTemplateHeaderType + + +class WhatsAppMessageSendRequestTemplateHeader(UniversalBaseModel): + """ + Header content, required only when the template's `HEADER` component needs one. + """ + + type: typing.Optional[WhatsAppMessageSendRequestTemplateHeaderType] = None + placeholder: typing.Optional[str] = pydantic.Field(default=None) + """ + Value for a `TEXT` header's `{{1}}` placeholder. + """ + + media_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="mediaUrl"), + pydantic.Field(alias="mediaUrl", description="Media URL for an `IMAGE`/`VIDEO`/`DOCUMENT` header."), + ] = None + filename: typing.Optional[str] = pydantic.Field(default=None) + """ + Filename for a `DOCUMENT` header. + """ + + latitude: typing.Optional[float] = pydantic.Field(default=None) + """ + Latitude for a `LOCATION` header. + """ + + longitude: typing.Optional[float] = pydantic.Field(default=None) + """ + Longitude for a `LOCATION` header. + """ + + parameter_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="parameterName"), + pydantic.Field(alias="parameterName", description="Placeholder name for a named-parameter `TEXT` header."), + ] = None + text: typing.Optional[str] = pydantic.Field(default=None) + """ + Value for a named-parameter `TEXT` header. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_message_send_request_template_header_type.py b/src/wavix/types/whats_app_message_send_request_template_header_type.py new file mode 100644 index 0000000..6f246a3 --- /dev/null +++ b/src/wavix/types/whats_app_message_send_request_template_header_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppMessageSendRequestTemplateHeaderType = typing.Union[ + typing.Literal["TEXT", "TEXT_NAMED_PARAMETERS", "IMAGE", "VIDEO", "DOCUMENT", "LOCATION"], typing.Any +] diff --git a/src/wavix/cart/types/remove_cart_response.py b/src/wavix/types/whats_app_message_send_response.py similarity index 63% rename from src/wavix/cart/types/remove_cart_response.py rename to src/wavix/types/whats_app_message_send_response.py index 87cc0de..8cd434b 100644 --- a/src/wavix/cart/types/remove_cart_response.py +++ b/src/wavix/types/whats_app_message_send_response.py @@ -3,14 +3,12 @@ import typing import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_message import WhatsAppMessage -class RemoveCartResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ +class WhatsAppMessageSendResponse(UniversalBaseModel): + message: WhatsAppMessage if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/wavix/types/whats_app_message_status.py b/src/wavix/types/whats_app_message_status.py new file mode 100644 index 0000000..6bcd36b --- /dev/null +++ b/src/wavix/types/whats_app_message_status.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppMessageStatus = typing.Union[ + typing.Literal["failed", "sent", "delivered", "undelivered", "expired", "rejected", "unknown"], typing.Any +] diff --git a/src/wavix/speech_analytics/types/create_speech_analytics_response.py b/src/wavix/types/whats_app_message_template.py similarity index 56% rename from src/wavix/speech_analytics/types/create_speech_analytics_response.py rename to src/wavix/types/whats_app_message_template.py index e36a017..4fa03ca 100644 --- a/src/wavix/speech_analytics/types/create_speech_analytics_response.py +++ b/src/wavix/types/whats_app_message_template.py @@ -3,23 +3,22 @@ import typing import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -class CreateSpeechAnalyticsResponse(UniversalBaseModel): - file: str = pydantic.Field() +class WhatsAppMessageTemplate(UniversalBaseModel): """ - Uploaded file name. + Template used to send the message. """ - request_id: str = pydantic.Field() + name: typing.Optional[str] = pydantic.Field(default=None) """ - Transcription request ID. + Template name. """ - success: bool = pydantic.Field() + language: typing.Optional[str] = pydantic.Field(default=None) """ - Indicates whether the request was successful. + Template language code. """ if IS_PYDANTIC_V2: diff --git a/src/wavix/types/whats_app_problem.py b/src/wavix/types/whats_app_problem.py new file mode 100644 index 0000000..625989f --- /dev/null +++ b/src/wavix/types/whats_app_problem.py @@ -0,0 +1,57 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_problem_error_class import WhatsAppProblemErrorClass + + +class WhatsAppProblem(UniversalBaseModel): + """ + RFC 9457 problem document returned by WhatsApp endpoints as `application/problem+json`. + """ + + type: str = pydantic.Field() + """ + URI identifying the problem type. + """ + + title: str = pydantic.Field() + """ + Short, human-readable summary of the problem type. + """ + + status: int = pydantic.Field() + """ + HTTP status code. + """ + + detail: str = pydantic.Field() + """ + Human-readable explanation specific to this occurrence of the problem. + """ + + instance: str = pydantic.Field() + """ + URI identifying this specific occurrence of the problem, such as the request ID. + """ + + error_class: typing.Optional[WhatsAppProblemErrorClass] = pydantic.Field(default=None) + """ + Machine-readable classification of the error. + """ + + error_code: typing.Optional[str] = pydantic.Field(default=None) + """ + Stable machine-readable error code, derived from the problem slug. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_problem_error_class.py b/src/wavix/types/whats_app_problem_error_class.py new file mode 100644 index 0000000..63c1c30 --- /dev/null +++ b/src/wavix/types/whats_app_problem_error_class.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppProblemErrorClass = typing.Union[ + typing.Literal["permanent", "retriable", "rate_limited", "invalid_template"], typing.Any +] diff --git a/src/wavix/types/whats_app_sender.py b/src/wavix/types/whats_app_sender.py new file mode 100644 index 0000000..4461e2a --- /dev/null +++ b/src/wavix/types/whats_app_sender.py @@ -0,0 +1,45 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_sender_message_tier import WhatsAppSenderMessageTier +from .whats_app_sender_quality_rating import WhatsAppSenderQualityRating +from .whats_app_sender_status import WhatsAppSenderStatus + + +class WhatsAppSender(UniversalBaseModel): + phone_number: str = pydantic.Field() + """ + Sender's phone number in E.164 format. + """ + + display_name: typing.Optional[str] = pydantic.Field(default=None) + """ + Sender's WhatsApp display name. + """ + + status: WhatsAppSenderStatus = pydantic.Field() + """ + Sender registration status with the provider. + """ + + quality_rating: typing.Optional[WhatsAppSenderQualityRating] = pydantic.Field(default=None) + """ + Sender's messaging quality rating. + """ + + message_tier: typing.Optional[WhatsAppSenderMessageTier] = pydantic.Field(default=None) + """ + Sender's 24-hour outbound messaging limit tier. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_sender_message_tier.py b/src/wavix/types/whats_app_sender_message_tier.py new file mode 100644 index 0000000..bb08661 --- /dev/null +++ b/src/wavix/types/whats_app_sender_message_tier.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppSenderMessageTier = typing.Union[ + typing.Literal["limit_na", "limit_250", "limit_2k", "limit_10k", "limit_100k", "unlimited"], typing.Any +] diff --git a/src/wavix/types/whats_app_sender_quality_rating.py b/src/wavix/types/whats_app_sender_quality_rating.py new file mode 100644 index 0000000..04c285f --- /dev/null +++ b/src/wavix/types/whats_app_sender_quality_rating.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppSenderQualityRating = typing.Union[typing.Literal["high", "medium", "low", "unknown"], typing.Any] diff --git a/src/wavix/types/whats_app_sender_status.py b/src/wavix/types/whats_app_sender_status.py new file mode 100644 index 0000000..e437c10 --- /dev/null +++ b/src/wavix/types/whats_app_sender_status.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppSenderStatus = typing.Union[ + typing.Literal[ + "banned", + "connected", + "deleted", + "disconnected", + "flagged", + "migrated", + "pending", + "rate_limited", + "restricted", + "unknown", + "unverified", + ], + typing.Any, +] diff --git a/src/wavix/types/whats_app_template.py b/src/wavix/types/whats_app_template.py new file mode 100644 index 0000000..f05cde1 --- /dev/null +++ b/src/wavix/types/whats_app_template.py @@ -0,0 +1,66 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .whats_app_template_category import WhatsAppTemplateCategory +from .whats_app_template_component import WhatsAppTemplateComponent +from .whats_app_template_quality_rating import WhatsAppTemplateQualityRating +from .whats_app_template_status import WhatsAppTemplateStatus + + +class WhatsAppTemplate(UniversalBaseModel): + uuid_: typing_extensions.Annotated[ + str, FieldMetadata(alias="uuid"), pydantic.Field(alias="uuid", description="Template ID.") + ] + name: str = pydantic.Field() + """ + Template name. + """ + + language: str = pydantic.Field() + """ + Template language code. + """ + + category: WhatsAppTemplateCategory = pydantic.Field() + """ + Template category. + """ + + status: WhatsAppTemplateStatus = pydantic.Field() + """ + Template review/approval status. + """ + + quality_rating: typing.Optional[WhatsAppTemplateQualityRating] = pydantic.Field(default=None) + """ + Template's messaging quality rating. + """ + + submitted_at: typing.Optional[str] = pydantic.Field(default=None) + """ + Date and time the template was submitted for review, in ISO 8601 format. + """ + + components: typing.List[WhatsAppTemplateComponent] = pydantic.Field() + """ + Structural components of the template. + """ + + created_at: str = pydantic.Field() + """ + Date and time the template was created, in ISO 8601 format. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_template_category.py b/src/wavix/types/whats_app_template_category.py new file mode 100644 index 0000000..d1311a9 --- /dev/null +++ b/src/wavix/types/whats_app_template_category.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppTemplateCategory = typing.Union[typing.Literal["marketing", "authentication", "utility"], typing.Any] diff --git a/src/wavix/types/whats_app_template_component.py b/src/wavix/types/whats_app_template_component.py new file mode 100644 index 0000000..210234f --- /dev/null +++ b/src/wavix/types/whats_app_template_component.py @@ -0,0 +1,48 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_template_component_format import WhatsAppTemplateComponentFormat +from .whats_app_template_component_type import WhatsAppTemplateComponentType + + +class WhatsAppTemplateComponent(UniversalBaseModel): + """ + One structural component (header, body, footer, or buttons) of a WhatsApp message template. + """ + + type: WhatsAppTemplateComponentType = pydantic.Field() + """ + Component type. + """ + + format: typing.Optional[WhatsAppTemplateComponentFormat] = pydantic.Field(default=None) + """ + Header content format. Present on `HEADER` components only. + """ + + text: typing.Optional[str] = pydantic.Field(default=None) + """ + Component text, with `{{n}}` placeholders where applicable. + """ + + example: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None) + """ + Sample values for the component's placeholders, in the shape the provider expects. + """ + + buttons: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = pydantic.Field(default=None) + """ + Button definitions. Present on `BUTTONS` components only. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_template_component_format.py b/src/wavix/types/whats_app_template_component_format.py new file mode 100644 index 0000000..933fe7b --- /dev/null +++ b/src/wavix/types/whats_app_template_component_format.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppTemplateComponentFormat = typing.Union[ + typing.Literal["TEXT", "IMAGE", "VIDEO", "DOCUMENT", "LOCATION"], typing.Any +] diff --git a/src/wavix/types/whats_app_template_component_type.py b/src/wavix/types/whats_app_template_component_type.py new file mode 100644 index 0000000..f2bc9f1 --- /dev/null +++ b/src/wavix/types/whats_app_template_component_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppTemplateComponentType = typing.Union[typing.Literal["HEADER", "BODY", "FOOTER", "BUTTONS"], typing.Any] diff --git a/src/wavix/types/whats_app_template_create_request.py b/src/wavix/types/whats_app_template_create_request.py new file mode 100644 index 0000000..c3b5733 --- /dev/null +++ b/src/wavix/types/whats_app_template_create_request.py @@ -0,0 +1,39 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_template_component import WhatsAppTemplateComponent +from .whats_app_template_create_request_category import WhatsAppTemplateCreateRequestCategory + + +class WhatsAppTemplateCreateRequest(UniversalBaseModel): + name: str = pydantic.Field() + """ + Template name. + """ + + language: str = pydantic.Field() + """ + Template language code. + """ + + category: WhatsAppTemplateCreateRequestCategory = pydantic.Field() + """ + Template category. + """ + + components: typing.List[WhatsAppTemplateComponent] = pydantic.Field() + """ + Structural components of the template. Must include a `BODY` component. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/wavix/types/whats_app_template_create_request_category.py b/src/wavix/types/whats_app_template_create_request_category.py new file mode 100644 index 0000000..d88cc1a --- /dev/null +++ b/src/wavix/types/whats_app_template_create_request_category.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppTemplateCreateRequestCategory = typing.Union[ + typing.Literal["marketing", "authentication", "utility"], typing.Any +] diff --git a/src/wavix/types/not_found_error_body.py b/src/wavix/types/whats_app_template_list_response.py similarity index 65% rename from src/wavix/types/not_found_error_body.py rename to src/wavix/types/whats_app_template_list_response.py index 2bc0506..832cb80 100644 --- a/src/wavix/types/not_found_error_body.py +++ b/src/wavix/types/whats_app_template_list_response.py @@ -4,17 +4,13 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_template import WhatsAppTemplate -class NotFoundErrorBody(UniversalBaseModel): - success: bool = pydantic.Field() +class WhatsAppTemplateListResponse(UniversalBaseModel): + templates: typing.List[WhatsAppTemplate] = pydantic.Field() """ - Indicates whether the request was successful. Always `false` for this error. - """ - - message: str = pydantic.Field() - """ - Human-readable error description + Templates registered for the sender. """ if IS_PYDANTIC_V2: diff --git a/src/wavix/types/whats_app_template_quality_rating.py b/src/wavix/types/whats_app_template_quality_rating.py new file mode 100644 index 0000000..5277231 --- /dev/null +++ b/src/wavix/types/whats_app_template_quality_rating.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppTemplateQualityRating = typing.Union[typing.Literal["high", "medium", "low", "unknown"], typing.Any] diff --git a/src/wavix/cart/types/checkout_cart_response.py b/src/wavix/types/whats_app_template_response.py similarity index 63% rename from src/wavix/cart/types/checkout_cart_response.py rename to src/wavix/types/whats_app_template_response.py index 2a41773..a645e47 100644 --- a/src/wavix/cart/types/checkout_cart_response.py +++ b/src/wavix/types/whats_app_template_response.py @@ -3,14 +3,12 @@ import typing import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .whats_app_template import WhatsAppTemplate -class CheckoutCartResponse(UniversalBaseModel): - success: bool = pydantic.Field() - """ - Indicates whether the request was successful. - """ +class WhatsAppTemplateResponse(UniversalBaseModel): + template: WhatsAppTemplate if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/wavix/types/whats_app_template_status.py b/src/wavix/types/whats_app_template_status.py new file mode 100644 index 0000000..c8a2465 --- /dev/null +++ b/src/wavix/types/whats_app_template_status.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WhatsAppTemplateStatus = typing.Union[ + typing.Literal[ + "draft", + "pending", + "approved", + "rejected", + "paused", + "flagged", + "disabled", + "in_appeal", + "pending_deletion", + "deleted", + "unknown", + ], + typing.Any, +] diff --git a/src/wavix/voice_campaigns/client.py b/src/wavix/voice_campaigns/client.py index e896ca3..705a4ba 100644 --- a/src/wavix/voice_campaigns/client.py +++ b/src/wavix/voice_campaigns/client.py @@ -32,7 +32,7 @@ def create( self, *, voice_campaign: VoiceCampaignResponse, request_options: typing.Optional[RequestOptions] = None ) -> VoiceCampaignsCreateResponse: """ - Launches a voice campaign that places an outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. + Launches a voice campaign that places a real outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. Parameters ---------- @@ -115,7 +115,7 @@ async def create( self, *, voice_campaign: VoiceCampaignResponse, request_options: typing.Optional[RequestOptions] = None ) -> VoiceCampaignsCreateResponse: """ - Launches a voice campaign that places an outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. + Launches a voice campaign that places a real outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. Parameters ---------- diff --git a/src/wavix/voice_campaigns/raw_client.py b/src/wavix/voice_campaigns/raw_client.py index 45a73a7..b375c69 100644 --- a/src/wavix/voice_campaigns/raw_client.py +++ b/src/wavix/voice_campaigns/raw_client.py @@ -14,7 +14,9 @@ from ..errors.bad_request_error import BadRequestError from ..errors.forbidden_error import ForbiddenError from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError from ..errors.unprocessable_entity_error import UnprocessableEntityError +from ..types.unauthorized_error_response import UnauthorizedErrorResponse from ..types.voice_campaign_response import VoiceCampaignResponse from ..types.voice_campaigns_create_response import VoiceCampaignsCreateResponse from ..types.voice_campaigns_get_response import VoiceCampaignsGetResponse @@ -32,7 +34,7 @@ def create( self, *, voice_campaign: VoiceCampaignResponse, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[VoiceCampaignsCreateResponse]: """ - Launches a voice campaign that places an outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. + Launches a voice campaign that places a real outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. Parameters ---------- @@ -81,6 +83,17 @@ def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -92,6 +105,17 @@ def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), @@ -146,6 +170,28 @@ def get( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -186,7 +232,7 @@ async def create( self, *, voice_campaign: VoiceCampaignResponse, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[VoiceCampaignsCreateResponse]: """ - Launches a voice campaign that places an outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. + Launches a voice campaign that places a real outbound call using a pre-configured scenario. Track progress with the returned voice campaign `id`. Parameters ---------- @@ -235,6 +281,17 @@ async def create( ), ), ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), @@ -246,6 +303,17 @@ async def create( ), ), ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), @@ -300,6 +368,28 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + UnauthorizedErrorResponse, + parse_obj_as( + type_=UnauthorizedErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 403: raise ForbiddenError( headers=dict(_response.headers), diff --git a/src/wavix/webrtc/tokens/client.py b/src/wavix/webrtc/tokens/client.py index f78747e..5b689e7 100644 --- a/src/wavix/webrtc/tokens/client.py +++ b/src/wavix/webrtc/tokens/client.py @@ -29,19 +29,31 @@ def with_raw_response(self) -> RawTokensClient: """ return self._raw_client - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> WebRtcTokensListResponse: + def list( + self, + *, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> WebRtcTokensListResponse: """ - Returns a paginated list of active Wavix Embeddable widget tokens for the authenticated account. + Returns a paginated list of Wavix Embeddable widget tokens for the authenticated account. Parameters ---------- + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- WebRtcTokensListResponse - Returns a paginated list of active widget tokens. + Returns a paginated list of widget tokens. Examples -------- @@ -52,7 +64,7 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> We ) client.webrtc.tokens.list() """ - _response = self._raw_client.list(request_options=request_options) + _response = self._raw_client.list(page=page, per_page=per_page, request_options=request_options) return _response.data def create( @@ -75,7 +87,7 @@ def create( Arbitrary client-defined data to associate with the token. ttl : typing.Optional[int] - Time to live in seconds. Pass `null` for no expiration. + Time to live in seconds. Default `3600`. Pass `null` for no expiration. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -218,19 +230,31 @@ def with_raw_response(self) -> AsyncRawTokensClient: """ return self._raw_client - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> WebRtcTokensListResponse: + async def list( + self, + *, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> WebRtcTokensListResponse: """ - Returns a paginated list of active Wavix Embeddable widget tokens for the authenticated account. + Returns a paginated list of Wavix Embeddable widget tokens for the authenticated account. Parameters ---------- + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- WebRtcTokensListResponse - Returns a paginated list of active widget tokens. + Returns a paginated list of widget tokens. Examples -------- @@ -249,7 +273,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._raw_client.list(request_options=request_options) + _response = await self._raw_client.list(page=page, per_page=per_page, request_options=request_options) return _response.data async def create( @@ -272,7 +296,7 @@ async def create( Arbitrary client-defined data to associate with the token. ttl : typing.Optional[int] - Time to live in seconds. Pass `null` for no expiration. + Time to live in seconds. Default `3600`. Pass `null` for no expiration. request_options : typing.Optional[RequestOptions] Request-specific configuration. diff --git a/src/wavix/webrtc/tokens/raw_client.py b/src/wavix/webrtc/tokens/raw_client.py index d5169eb..743e1ad 100644 --- a/src/wavix/webrtc/tokens/raw_client.py +++ b/src/wavix/webrtc/tokens/raw_client.py @@ -30,24 +30,38 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper def list( - self, *, request_options: typing.Optional[RequestOptions] = None + self, + *, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[WebRtcTokensListResponse]: """ - Returns a paginated list of active Wavix Embeddable widget tokens for the authenticated account. + Returns a paginated list of Wavix Embeddable widget tokens for the authenticated account. Parameters ---------- + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- HttpResponse[WebRtcTokensListResponse] - Returns a paginated list of active widget tokens. + Returns a paginated list of widget tokens. """ _response = self._client_wrapper.httpx_client.request( "v2/webrtc/tokens", method="GET", + params={ + "page": page, + "per_page": per_page, + }, request_options=request_options, ) try: @@ -111,7 +125,7 @@ def create( Arbitrary client-defined data to associate with the token. ttl : typing.Optional[int] - Time to live in seconds. Pass `null` for no expiration. + Time to live in seconds. Default `3600`. Pass `null` for no expiration. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -230,6 +244,17 @@ def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = Non ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -403,6 +428,17 @@ def delete( ), ) return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -451,24 +487,38 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper async def list( - self, *, request_options: typing.Optional[RequestOptions] = None + self, + *, + page: typing.Optional[int] = None, + per_page: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[WebRtcTokensListResponse]: """ - Returns a paginated list of active Wavix Embeddable widget tokens for the authenticated account. + Returns a paginated list of Wavix Embeddable widget tokens for the authenticated account. Parameters ---------- + page : typing.Optional[int] + Page number to retrieve. Default `1`. + + per_page : typing.Optional[int] + Number of records to return per page. Default `25`. + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- AsyncHttpResponse[WebRtcTokensListResponse] - Returns a paginated list of active widget tokens. + Returns a paginated list of widget tokens. """ _response = await self._client_wrapper.httpx_client.request( "v2/webrtc/tokens", method="GET", + params={ + "page": page, + "per_page": per_page, + }, request_options=request_options, ) try: @@ -532,7 +582,7 @@ async def create( Arbitrary client-defined data to associate with the token. ttl : typing.Optional[int] - Time to live in seconds. Pass `null` for no expiration. + Time to live in seconds. Default `3600`. Pass `null` for no expiration. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -653,6 +703,17 @@ async def get( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers), @@ -826,6 +887,17 @@ async def delete( ), ) return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 401: raise UnauthorizedError( headers=dict(_response.headers),