diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e96646d..b66ed19 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,8 +17,8 @@ on: env: VAULT_ADDR: https://vault.eng.aserto.com/ PYTHON_VERSION: "3.9" - POETRY_VERSION: "1.8.3" - TOPAZ_VERSION: "0.32.38" + POETRY_VERSION: "2.1.1" + TOPAZ_VERSION: "0.32.56" jobs: test: @@ -119,10 +119,7 @@ jobs: poetry publish - name: Bump version - id: bump - uses: callowayproject/bump-my-version@master - with: - args: patch + run: poetry version patch - name: Commit changes uses: EndBug/add-and-commit@v9 diff --git a/.gitignore b/.gitignore index 1a6ad5d..63814e9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,11 @@ dist __pycache__ .DS_Store .env +.envrc .mypy_cache .pytest_cache .vscode .coverage .python-version .ext +.dmypy.json diff --git a/poetry.lock b/poetry.lock index cf31d1d..aec18d6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,93 +14,93 @@ files = [ [[package]] name = "aiohttp" -version = "3.11.13" +version = "3.11.14" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4fe27dbbeec445e6e1291e61d61eb212ee9fed6e47998b27de71d70d3e8777d"}, - {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e64ca2dbea28807f8484c13f684a2f761e69ba2640ec49dacd342763cc265ef"}, - {file = "aiohttp-3.11.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9840be675de208d1f68f84d578eaa4d1a36eee70b16ae31ab933520c49ba1325"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28a772757c9067e2aee8a6b2b425d0efaa628c264d6416d283694c3d86da7689"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b88aca5adbf4625e11118df45acac29616b425833c3be7a05ef63a6a4017bfdb"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce10ddfbe26ed5856d6902162f71b8fe08545380570a885b4ab56aecfdcb07f4"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa48dac27f41b36735c807d1ab093a8386701bbf00eb6b89a0f69d9fa26b3671"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89ce611b1eac93ce2ade68f1470889e0173d606de20c85a012bfa24be96cf867"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78e4dd9c34ec7b8b121854eb5342bac8b02aa03075ae8618b6210a06bbb8a115"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:66047eacbc73e6fe2462b77ce39fc170ab51235caf331e735eae91c95e6a11e4"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ad8f1c19fe277eeb8bc45741c6d60ddd11d705c12a4d8ee17546acff98e0802"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64815c6f02e8506b10113ddbc6b196f58dbef135751cc7c32136df27b736db09"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:967b93f21b426f23ca37329230d5bd122f25516ae2f24a9cea95a30023ff8283"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf1f31f83d16ec344136359001c5e871915c6ab685a3d8dee38e2961b4c81730"}, - {file = "aiohttp-3.11.13-cp310-cp310-win32.whl", hash = "sha256:00c8ac69e259c60976aa2edae3f13d9991cf079aaa4d3cd5a49168ae3748dee3"}, - {file = "aiohttp-3.11.13-cp310-cp310-win_amd64.whl", hash = "sha256:90d571c98d19a8b6e793b34aa4df4cee1e8fe2862d65cc49185a3a3d0a1a3996"}, - {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b35aab22419ba45f8fc290d0010898de7a6ad131e468ffa3922b1b0b24e9d2e"}, - {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81cba651db8795f688c589dd11a4fbb834f2e59bbf9bb50908be36e416dc760"}, - {file = "aiohttp-3.11.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f55d0f242c2d1fcdf802c8fabcff25a9d85550a4cf3a9cf5f2a6b5742c992839"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4bea08a6aad9195ac9b1be6b0c7e8a702a9cec57ce6b713698b4a5afa9c2e33"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6070bcf2173a7146bb9e4735b3c62b2accba459a6eae44deea0eb23e0035a23"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:718d5deb678bc4b9d575bfe83a59270861417da071ab44542d0fcb6faa686636"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f6b2c5b4a4d22b8fb2c92ac98e0747f5f195e8e9448bfb7404cd77e7bfa243f"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747ec46290107a490d21fe1ff4183bef8022b848cf9516970cb31de6d9460088"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:01816f07c9cc9d80f858615b1365f8319d6a5fd079cd668cc58e15aafbc76a54"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a08ad95fcbd595803e0c4280671d808eb170a64ca3f2980dd38e7a72ed8d1fea"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c97be90d70f7db3aa041d720bfb95f4869d6063fcdf2bb8333764d97e319b7d0"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ab915a57c65f7a29353c8014ac4be685c8e4a19e792a79fe133a8e101111438e"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:35cda4e07f5e058a723436c4d2b7ba2124ab4e0aa49e6325aed5896507a8a42e"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:af55314407714fe77a68a9ccaab90fdb5deb57342585fd4a3a8102b6d4370080"}, - {file = "aiohttp-3.11.13-cp311-cp311-win32.whl", hash = "sha256:42d689a5c0a0c357018993e471893e939f555e302313d5c61dfc566c2cad6185"}, - {file = "aiohttp-3.11.13-cp311-cp311-win_amd64.whl", hash = "sha256:b73a2b139782a07658fbf170fe4bcdf70fc597fae5ffe75e5b67674c27434a9f"}, - {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2eabb269dc3852537d57589b36d7f7362e57d1ece308842ef44d9830d2dc3c90"}, - {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b77ee42addbb1c36d35aca55e8cc6d0958f8419e458bb70888d8c69a4ca833d"}, - {file = "aiohttp-3.11.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55789e93c5ed71832e7fac868167276beadf9877b85697020c46e9a75471f55f"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c929f9a7249a11e4aa5c157091cfad7f49cc6b13f4eecf9b747104befd9f56f2"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d33851d85537bbf0f6291ddc97926a754c8f041af759e0aa0230fe939168852b"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9229d8613bd8401182868fe95688f7581673e1c18ff78855671a4b8284f47bcb"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669dd33f028e54fe4c96576f406ebb242ba534dd3a981ce009961bf49960f117"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1b20a1ace54af7db1f95af85da530fe97407d9063b7aaf9ce6a32f44730778"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5724cc77f4e648362ebbb49bdecb9e2b86d9b172c68a295263fa072e679ee69d"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:aa36c35e94ecdb478246dd60db12aba57cfcd0abcad43c927a8876f25734d496"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9b5b37c863ad5b0892cc7a4ceb1e435e5e6acd3f2f8d3e11fa56f08d3c67b820"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e06cf4852ce8c4442a59bae5a3ea01162b8fcb49ab438d8548b8dc79375dad8a"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5194143927e494616e335d074e77a5dac7cd353a04755330c9adc984ac5a628e"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afcb6b275c2d2ba5d8418bf30a9654fa978b4f819c2e8db6311b3525c86fe637"}, - {file = "aiohttp-3.11.13-cp312-cp312-win32.whl", hash = "sha256:7104d5b3943c6351d1ad7027d90bdd0ea002903e9f610735ac99df3b81f102ee"}, - {file = "aiohttp-3.11.13-cp312-cp312-win_amd64.whl", hash = "sha256:47dc018b1b220c48089b5b9382fbab94db35bef2fa192995be22cbad3c5730c8"}, - {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9862d077b9ffa015dbe3ce6c081bdf35135948cb89116e26667dd183550833d1"}, - {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbfef0666ae9e07abfa2c54c212ac18a1f63e13e0760a769f70b5717742f3ece"}, - {file = "aiohttp-3.11.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a1f7d857c4fcf7cabb1178058182c789b30d85de379e04f64c15b7e88d66fb"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba40b7ae0f81c7029583a338853f6607b6d83a341a3dcde8bed1ea58a3af1df9"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5b95787335c483cd5f29577f42bbe027a412c5431f2f80a749c80d040f7ca9f"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7d474c5c1f0b9405c1565fafdc4429fa7d986ccbec7ce55bc6a330f36409cad"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e83fb1991e9d8982b3b36aea1e7ad27ea0ce18c14d054c7a404d68b0319eebb"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4586a68730bd2f2b04a83e83f79d271d8ed13763f64b75920f18a3a677b9a7f0"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fe4eb0e7f50cdb99b26250d9328faef30b1175a5dbcfd6d0578d18456bac567"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2a8a6bc19818ac3e5596310ace5aa50d918e1ebdcc204dc96e2f4d505d51740c"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f27eec42f6c3c1df09cfc1f6786308f8b525b8efaaf6d6bd76c1f52c6511f6a"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2a4a13dfbb23977a51853b419141cd0a9b9573ab8d3a1455c6e63561387b52ff"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:02876bf2f69b062584965507b07bc06903c2dc93c57a554b64e012d636952654"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b992778d95b60a21c4d8d4a5f15aaab2bd3c3e16466a72d7f9bfd86e8cea0d4b"}, - {file = "aiohttp-3.11.13-cp313-cp313-win32.whl", hash = "sha256:507ab05d90586dacb4f26a001c3abf912eb719d05635cbfad930bdbeb469b36c"}, - {file = "aiohttp-3.11.13-cp313-cp313-win_amd64.whl", hash = "sha256:5ceb81a4db2decdfa087381b5fc5847aa448244f973e5da232610304e199e7b2"}, - {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:51c3ff9c7a25f3cad5c09d9aacbc5aefb9267167c4652c1eb737989b554fe278"}, - {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e271beb2b1dabec5cd84eb488bdabf9758d22ad13471e9c356be07ad139b3012"}, - {file = "aiohttp-3.11.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e9eb7e5764abcb49f0e2bd8f5731849b8728efbf26d0cac8e81384c95acec3f"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baae005092e3f200de02699314ac8933ec20abf998ec0be39448f6605bce93df"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1982c98ac62c132d2b773d50e2fcc941eb0b8bad3ec078ce7e7877c4d5a2dce7"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2b25b2eeb35707113b2d570cadc7c612a57f1c5d3e7bb2b13870fe284e08fc0"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b27961d65639128336b7a7c3f0046dcc62a9443d5ef962e3c84170ac620cec47"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe9f1e05025eacdd97590895e2737b9f851d0eb2e017ae9574d9a4f0b6252"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa1fb1b61881c8405829c50e9cc5c875bfdbf685edf57a76817dfb50643e4a1a"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:25de43bb3cf83ad83efc8295af7310219af6dbe4c543c2e74988d8e9c8a2a917"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe7065e2215e4bba63dc00db9ae654c1ba3950a5fff691475a32f511142fcddb"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7836587eef675a17d835ec3d98a8c9acdbeb2c1d72b0556f0edf4e855a25e9c1"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:85fa0b18558eb1427090912bd456a01f71edab0872f4e0f9e4285571941e4090"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a86dc177eb4c286c19d1823ac296299f59ed8106c9536d2b559f65836e0fb2c6"}, - {file = "aiohttp-3.11.13-cp39-cp39-win32.whl", hash = "sha256:684eea71ab6e8ade86b9021bb62af4bf0881f6be4e926b6b5455de74e420783a"}, - {file = "aiohttp-3.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:82c249f2bfa5ecbe4a1a7902c81c0fba52ed9ebd0176ab3047395d02ad96cfcb"}, - {file = "aiohttp-3.11.13.tar.gz", hash = "sha256:8ce789231404ca8fff7f693cdce398abf6d90fd5dae2b1847477196c243b1fbb"}, + {file = "aiohttp-3.11.14-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e2bc827c01f75803de77b134afdbf74fa74b62970eafdf190f3244931d7a5c0d"}, + {file = "aiohttp-3.11.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e365034c5cf6cf74f57420b57682ea79e19eb29033399dd3f40de4d0171998fa"}, + {file = "aiohttp-3.11.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c32593ead1a8c6aabd58f9d7ee706e48beac796bb0cb71d6b60f2c1056f0a65f"}, + {file = "aiohttp-3.11.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4e7c7ec4146a94a307ca4f112802a8e26d969018fabed526efc340d21d3e7d0"}, + {file = "aiohttp-3.11.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8b2df9feac55043759aa89f722a967d977d80f8b5865a4153fc41c93b957efc"}, + {file = "aiohttp-3.11.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7571f99525c76a6280f5fe8e194eeb8cb4da55586c3c61c59c33a33f10cfce7"}, + {file = "aiohttp-3.11.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b59d096b5537ec7c85954cb97d821aae35cfccce3357a2cafe85660cc6295628"}, + {file = "aiohttp-3.11.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b42dbd097abb44b3f1156b4bf978ec5853840802d6eee2784857be11ee82c6a0"}, + {file = "aiohttp-3.11.14-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b05774864c87210c531b48dfeb2f7659407c2dda8643104fb4ae5e2c311d12d9"}, + {file = "aiohttp-3.11.14-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4e2e8ef37d4bc110917d038807ee3af82700a93ab2ba5687afae5271b8bc50ff"}, + {file = "aiohttp-3.11.14-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e9faafa74dbb906b2b6f3eb9942352e9e9db8d583ffed4be618a89bd71a4e914"}, + {file = "aiohttp-3.11.14-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7e7abe865504f41b10777ac162c727af14e9f4db9262e3ed8254179053f63e6d"}, + {file = "aiohttp-3.11.14-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4848ae31ad44330b30f16c71e4f586cd5402a846b11264c412de99fa768f00f3"}, + {file = "aiohttp-3.11.14-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2d0b46abee5b5737cb479cc9139b29f010a37b1875ee56d142aefc10686a390b"}, + {file = "aiohttp-3.11.14-cp310-cp310-win32.whl", hash = "sha256:a0d2c04a623ab83963576548ce098baf711a18e2c32c542b62322a0b4584b990"}, + {file = "aiohttp-3.11.14-cp310-cp310-win_amd64.whl", hash = "sha256:5409a59d5057f2386bb8b8f8bbcfb6e15505cedd8b2445db510563b5d7ea1186"}, + {file = "aiohttp-3.11.14-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f296d637a50bb15fb6a229fbb0eb053080e703b53dbfe55b1e4bb1c5ed25d325"}, + {file = "aiohttp-3.11.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ec6cd1954ca2bbf0970f531a628da1b1338f594bf5da7e361e19ba163ecc4f3b"}, + {file = "aiohttp-3.11.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:572def4aad0a4775af66d5a2b5923c7de0820ecaeeb7987dcbccda2a735a993f"}, + {file = "aiohttp-3.11.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c68e41c4d576cd6aa6c6d2eddfb32b2acfb07ebfbb4f9da991da26633a3db1a"}, + {file = "aiohttp-3.11.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b8bbfc8111826aa8363442c0fc1f5751456b008737ff053570f06a151650b3"}, + {file = "aiohttp-3.11.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b0a200e85da5c966277a402736a96457b882360aa15416bf104ca81e6f5807b"}, + {file = "aiohttp-3.11.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d173c0ac508a2175f7c9a115a50db5fd3e35190d96fdd1a17f9cb10a6ab09aa1"}, + {file = "aiohttp-3.11.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:413fe39fd929329f697f41ad67936f379cba06fcd4c462b62e5b0f8061ee4a77"}, + {file = "aiohttp-3.11.14-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:65c75b14ee74e8eeff2886321e76188cbe938d18c85cff349d948430179ad02c"}, + {file = "aiohttp-3.11.14-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:321238a42ed463848f06e291c4bbfb3d15ba5a79221a82c502da3e23d7525d06"}, + {file = "aiohttp-3.11.14-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59a05cdc636431f7ce843c7c2f04772437dd816a5289f16440b19441be6511f1"}, + {file = "aiohttp-3.11.14-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:daf20d9c3b12ae0fdf15ed92235e190f8284945563c4b8ad95b2d7a31f331cd3"}, + {file = "aiohttp-3.11.14-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:05582cb2d156ac7506e68b5eac83179faedad74522ed88f88e5861b78740dc0e"}, + {file = "aiohttp-3.11.14-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:12c5869e7ddf6b4b1f2109702b3cd7515667b437da90a5a4a50ba1354fe41881"}, + {file = "aiohttp-3.11.14-cp311-cp311-win32.whl", hash = "sha256:92868f6512714efd4a6d6cb2bfc4903b997b36b97baea85f744229f18d12755e"}, + {file = "aiohttp-3.11.14-cp311-cp311-win_amd64.whl", hash = "sha256:bccd2cb7aa5a3bfada72681bdb91637094d81639e116eac368f8b3874620a654"}, + {file = "aiohttp-3.11.14-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:70ab0f61c1a73d3e0342cedd9a7321425c27a7067bebeeacd509f96695b875fc"}, + {file = "aiohttp-3.11.14-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:602d4db80daf4497de93cb1ce00b8fc79969c0a7cf5b67bec96fa939268d806a"}, + {file = "aiohttp-3.11.14-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a8a0d127c10b8d89e69bbd3430da0f73946d839e65fec00ae48ca7916a31948"}, + {file = "aiohttp-3.11.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca9f835cdfedcb3f5947304e85b8ca3ace31eef6346d8027a97f4de5fb687534"}, + {file = "aiohttp-3.11.14-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8aa5c68e1e68fff7cd3142288101deb4316b51f03d50c92de6ea5ce646e6c71f"}, + {file = "aiohttp-3.11.14-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b512f1de1c688f88dbe1b8bb1283f7fbeb7a2b2b26e743bb2193cbadfa6f307"}, + {file = "aiohttp-3.11.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc9253069158d57e27d47a8453d8a2c5a370dc461374111b5184cf2f147a3cc3"}, + {file = "aiohttp-3.11.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b2501f1b981e70932b4a552fc9b3c942991c7ae429ea117e8fba57718cdeed0"}, + {file = "aiohttp-3.11.14-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:28a3d083819741592685762d51d789e6155411277050d08066537c5edc4066e6"}, + {file = "aiohttp-3.11.14-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0df3788187559c262922846087e36228b75987f3ae31dd0a1e5ee1034090d42f"}, + {file = "aiohttp-3.11.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e73fa341d8b308bb799cf0ab6f55fc0461d27a9fa3e4582755a3d81a6af8c09"}, + {file = "aiohttp-3.11.14-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:51ba80d473eb780a329d73ac8afa44aa71dfb521693ccea1dea8b9b5c4df45ce"}, + {file = "aiohttp-3.11.14-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8d1dd75aa4d855c7debaf1ef830ff2dfcc33f893c7db0af2423ee761ebffd22b"}, + {file = "aiohttp-3.11.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41cf0cefd9e7b5c646c2ef529c8335e7eafd326f444cc1cdb0c47b6bc836f9be"}, + {file = "aiohttp-3.11.14-cp312-cp312-win32.whl", hash = "sha256:948abc8952aff63de7b2c83bfe3f211c727da3a33c3a5866a0e2cf1ee1aa950f"}, + {file = "aiohttp-3.11.14-cp312-cp312-win_amd64.whl", hash = "sha256:3b420d076a46f41ea48e5fcccb996f517af0d406267e31e6716f480a3d50d65c"}, + {file = "aiohttp-3.11.14-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d14e274828561db91e4178f0057a915f3af1757b94c2ca283cb34cbb6e00b50"}, + {file = "aiohttp-3.11.14-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f30fc72daf85486cdcdfc3f5e0aea9255493ef499e31582b34abadbfaafb0965"}, + {file = "aiohttp-3.11.14-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4edcbe34e6dba0136e4cabf7568f5a434d89cc9de5d5155371acda275353d228"}, + {file = "aiohttp-3.11.14-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a7169ded15505f55a87f8f0812c94c9412623c744227b9e51083a72a48b68a5"}, + {file = "aiohttp-3.11.14-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad1f2fb9fe9b585ea4b436d6e998e71b50d2b087b694ab277b30e060c434e5db"}, + {file = "aiohttp-3.11.14-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20412c7cc3720e47a47e63c0005f78c0c2370020f9f4770d7fc0075f397a9fb0"}, + {file = "aiohttp-3.11.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dd9766da617855f7e85f27d2bf9a565ace04ba7c387323cd3e651ac4329db91"}, + {file = "aiohttp-3.11.14-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:599b66582f7276ebefbaa38adf37585e636b6a7a73382eb412f7bc0fc55fb73d"}, + {file = "aiohttp-3.11.14-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b41693b7388324b80f9acfabd479bd1c84f0bc7e8f17bab4ecd9675e9ff9c734"}, + {file = "aiohttp-3.11.14-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:86135c32d06927339c8c5e64f96e4eee8825d928374b9b71a3c42379d7437058"}, + {file = "aiohttp-3.11.14-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:04eb541ce1e03edc1e3be1917a0f45ac703e913c21a940111df73a2c2db11d73"}, + {file = "aiohttp-3.11.14-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dc311634f6f28661a76cbc1c28ecf3b3a70a8edd67b69288ab7ca91058eb5a33"}, + {file = "aiohttp-3.11.14-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:69bb252bfdca385ccabfd55f4cd740d421dd8c8ad438ded9637d81c228d0da49"}, + {file = "aiohttp-3.11.14-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2b86efe23684b58a88e530c4ab5b20145f102916bbb2d82942cafec7bd36a647"}, + {file = "aiohttp-3.11.14-cp313-cp313-win32.whl", hash = "sha256:b9c60d1de973ca94af02053d9b5111c4fbf97158e139b14f1be68337be267be6"}, + {file = "aiohttp-3.11.14-cp313-cp313-win_amd64.whl", hash = "sha256:0a29be28e60e5610d2437b5b2fed61d6f3dcde898b57fb048aa5079271e7f6f3"}, + {file = "aiohttp-3.11.14-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:14fc03508359334edc76d35b2821832f092c8f092e4b356e74e38419dfe7b6de"}, + {file = "aiohttp-3.11.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:92007c89a8cb7be35befa2732b0b32bf3a394c1b22ef2dff0ef12537d98a7bda"}, + {file = "aiohttp-3.11.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6d3986112e34eaa36e280dc8286b9dd4cc1a5bcf328a7f147453e188f6fe148f"}, + {file = "aiohttp-3.11.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:749f1eb10e51dbbcdba9df2ef457ec060554842eea4d23874a3e26495f9e87b1"}, + {file = "aiohttp-3.11.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:781c8bd423dcc4641298c8c5a2a125c8b1c31e11f828e8d35c1d3a722af4c15a"}, + {file = "aiohttp-3.11.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:997b57e38aa7dc6caab843c5e042ab557bc83a2f91b7bd302e3c3aebbb9042a1"}, + {file = "aiohttp-3.11.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a8b0321e40a833e381d127be993b7349d1564b756910b28b5f6588a159afef3"}, + {file = "aiohttp-3.11.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8778620396e554b758b59773ab29c03b55047841d8894c5e335f12bfc45ebd28"}, + {file = "aiohttp-3.11.14-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e906da0f2bcbf9b26cc2b144929e88cb3bf943dd1942b4e5af066056875c7618"}, + {file = "aiohttp-3.11.14-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:87f0e003fb4dd5810c7fbf47a1239eaa34cd929ef160e0a54c570883125c4831"}, + {file = "aiohttp-3.11.14-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7f2dadece8b85596ac3ab1ec04b00694bdd62abc31e5618f524648d18d9dd7fa"}, + {file = "aiohttp-3.11.14-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:fe846f0a98aa9913c2852b630cd39b4098f296e0907dd05f6c7b30d911afa4c3"}, + {file = "aiohttp-3.11.14-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ced66c5c6ad5bcaf9be54560398654779ec1c3695f1a9cf0ae5e3606694a000a"}, + {file = "aiohttp-3.11.14-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a40087b82f83bd671cbeb5f582c233d196e9653220404a798798bfc0ee189fff"}, + {file = "aiohttp-3.11.14-cp39-cp39-win32.whl", hash = "sha256:95d7787f2bcbf7cb46823036a8d64ccfbc2ffc7d52016b4044d901abceeba3db"}, + {file = "aiohttp-3.11.14-cp39-cp39-win_amd64.whl", hash = "sha256:22a8107896877212130c58f74e64b77f7007cb03cea8698be317272643602d45"}, + {file = "aiohttp-3.11.14.tar.gz", hash = "sha256:d6edc538c7480fa0a3b2bdd705f8010062d74700198da55d16498e1b49549b9c"}, ] [package.dependencies] @@ -133,35 +133,37 @@ frozenlist = ">=1.1.0" [[package]] name = "aserto-authorizer" -version = "0.20.4" +version = "0.20.7" description = "gRPC client for Aserto Authorizer service instances" optional = false -python-versions = "<4.0,>=3.8" +python-versions = "<4,>=3.9" groups = ["main"] files = [ - {file = "aserto_authorizer-0.20.4-py3-none-any.whl", hash = "sha256:38f6759f41dbd575bf9e2d036b56aed1fc7e3115bd7a2b0ce695441927d0c985"}, - {file = "aserto_authorizer-0.20.4.tar.gz", hash = "sha256:fe560cdafa51e5a44c2276cec18e389331b365e417d318c013d7b093ee64b605"}, + {file = "aserto_authorizer-0.20.7-py3-none-any.whl", hash = "sha256:daba6d3e4d8c77686dd2b02b4646407941d1482b83d956f70fa13fee80d64ad5"}, + {file = "aserto_authorizer-0.20.7.tar.gz", hash = "sha256:9e54fba9f30f64e129212734162d9f7e007b6fb5ef1ba32666a456ba5dd4438a"}, ] [package.dependencies] -grpcio = ">=1.70.0,<2.0.0" -protobuf = ">=5.27.2,<6.0.0" +grpcio = ">=1.71.0,<2.0.0" +protobuf = ">=6.30.1,<7.0.0" +types-protobuf = ">=5.29,<6.0" [[package]] name = "aserto-directory" -version = "0.33.5" +version = "0.33.8" description = "gRPC client for Aserto Directory service instances" optional = false -python-versions = "<4,>=3.8" +python-versions = "<4,>=3.9" groups = ["main"] files = [ - {file = "aserto_directory-0.33.5-py3-none-any.whl", hash = "sha256:9408474f144c17607b0d1bc8cbb0f47e86b6a087ae060a446a39b46933e16f95"}, - {file = "aserto_directory-0.33.5.tar.gz", hash = "sha256:e75d76c47bbd354b51bb77da3026fe1ee01d80d78c526d26f94ae9ffb6ee8123"}, + {file = "aserto_directory-0.33.8-py3-none-any.whl", hash = "sha256:db252ffbdd24ddf8ebed3755f649796d2497aee489a4c2d3396516d2a6c1785b"}, + {file = "aserto_directory-0.33.8.tar.gz", hash = "sha256:05c297cf528313100263f6bda047d5fbd21aa2d80fde0f0239dd1fbb7314f3cd"}, ] [package.dependencies] -grpcio = ">=1.70.0,<2.0.0" -protobuf = ">=5.27.2,<6.0.0" +grpcio = ">=1.71.0,<2.0.0" +protobuf = ">=6.30.1,<7.0.0" +types-protobuf = ">=5.29,<6.0" [[package]] name = "async-timeout" @@ -198,34 +200,34 @@ tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" a [[package]] name = "black" -version = "24.10.0" +version = "25.1.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, - {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, - {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, - {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, - {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, - {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, - {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, - {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, - {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, - {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, - {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, - {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, - {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, - {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, - {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, - {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, - {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, - {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, - {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, - {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, - {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, - {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, + {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, + {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, + {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, + {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, + {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, + {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, + {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, + {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, + {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, + {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, + {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, + {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, + {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, + {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, + {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, + {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, + {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, + {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, + {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, + {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, + {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, + {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, ] [package.dependencies] @@ -249,7 +251,7 @@ version = "2025.1.31" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main", "dev"] +groups = ["dev"] files = [ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, @@ -503,13 +505,28 @@ files = [ {file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"}, ] +[[package]] +name = "grpc-stubs" +version = "1.53.0.5" +description = "Mypy stubs for gRPC" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "grpc-stubs-1.53.0.5.tar.gz", hash = "sha256:3e1b642775cbc3e0c6332cfcedfccb022176db87e518757bef3a1241397be406"}, + {file = "grpc_stubs-1.53.0.5-py3-none-any.whl", hash = "sha256:04183fb65a1b166a1febb9627e3d9647d3926ccc2dfe049fe7b6af243428dbe1"}, +] + +[package.dependencies] +grpcio = "*" + [[package]] name = "grpcio" version = "1.71.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "grpcio-1.71.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:c200cb6f2393468142eb50ab19613229dcc7829b5ccee8b658a36005f6669fdd"}, {file = "grpcio-1.71.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b2266862c5ad664a380fbbcdbdb8289d71464c42a8c29053820ee78ba0119e5d"}, @@ -584,131 +601,132 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] name = "isort" -version = "5.13.2" +version = "6.0.1" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" groups = ["dev"] files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, + {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, + {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, ] [package.extras] -colors = ["colorama (>=0.4.6)"] +colors = ["colorama"] +plugins = ["setuptools"] [[package]] name = "multidict" -version = "6.1.0" +version = "6.2.0" description = "multidict implementation" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, - {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, - {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, - {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, - {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, - {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, - {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, - {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, - {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, - {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, - {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, - {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, - {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, - {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, - {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, + {file = "multidict-6.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b9f6392d98c0bd70676ae41474e2eecf4c7150cb419237a41f8f96043fcb81d1"}, + {file = "multidict-6.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3501621d5e86f1a88521ea65d5cad0a0834c77b26f193747615b7c911e5422d2"}, + {file = "multidict-6.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:32ed748ff9ac682eae7859790d3044b50e3076c7d80e17a44239683769ff485e"}, + {file = "multidict-6.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc826b9a8176e686b67aa60fd6c6a7047b0461cae5591ea1dc73d28f72332a8a"}, + {file = "multidict-6.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:214207dcc7a6221d9942f23797fe89144128a71c03632bf713d918db99bd36de"}, + {file = "multidict-6.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:05fefbc3cddc4e36da209a5e49f1094bbece9a581faa7f3589201fd95df40e5d"}, + {file = "multidict-6.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e851e6363d0dbe515d8de81fd544a2c956fdec6f8a049739562286727d4a00c3"}, + {file = "multidict-6.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32c9b4878f48be3e75808ea7e499d6223b1eea6d54c487a66bc10a1871e3dc6a"}, + {file = "multidict-6.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7243c5a6523c5cfeca76e063efa5f6a656d1d74c8b1fc64b2cd1e84e507f7e2a"}, + {file = "multidict-6.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0e5a644e50ef9fb87878d4d57907f03a12410d2aa3b93b3acdf90a741df52c49"}, + {file = "multidict-6.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0dc25a3293c50744796e87048de5e68996104d86d940bb24bc3ec31df281b191"}, + {file = "multidict-6.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a49994481b99cd7dedde07f2e7e93b1d86c01c0fca1c32aded18f10695ae17eb"}, + {file = "multidict-6.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:641cf2e3447c9ecff2f7aa6e9eee9eaa286ea65d57b014543a4911ff2799d08a"}, + {file = "multidict-6.2.0-cp310-cp310-win32.whl", hash = "sha256:0c383d28857f66f5aebe3e91d6cf498da73af75fbd51cedbe1adfb85e90c0460"}, + {file = "multidict-6.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:a33273a541f1e1a8219b2a4ed2de355848ecc0254264915b9290c8d2de1c74e1"}, + {file = "multidict-6.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:84e87a7d75fa36839a3a432286d719975362d230c70ebfa0948549cc38bd5b46"}, + {file = "multidict-6.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8de4d42dffd5ced9117af2ce66ba8722402541a3aa98ffdf78dde92badb68932"}, + {file = "multidict-6.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d91a230c7f8af86c904a5a992b8c064b66330544693fd6759c3d6162382ecf"}, + {file = "multidict-6.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f6cad071960ba1914fa231677d21b1b4a3acdcce463cee41ea30bc82e6040cf"}, + {file = "multidict-6.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f74f2fc51555f4b037ef278efc29a870d327053aba5cb7d86ae572426c7cccc"}, + {file = "multidict-6.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14ed9ed1bfedd72a877807c71113deac292bf485159a29025dfdc524c326f3e1"}, + {file = "multidict-6.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ac3fcf9a2d369bd075b2c2965544036a27ccd277fc3c04f708338cc57533081"}, + {file = "multidict-6.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fc6af8e39f7496047c7876314f4317736eac82bf85b54c7c76cf1a6f8e35d98"}, + {file = "multidict-6.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f8cb1329f42fadfb40d6211e5ff568d71ab49be36e759345f91c69d1033d633"}, + {file = "multidict-6.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5389445f0173c197f4a3613713b5fb3f3879df1ded2a1a2e4bc4b5b9c5441b7e"}, + {file = "multidict-6.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:94a7bb972178a8bfc4055db80c51efd24baefaced5e51c59b0d598a004e8305d"}, + {file = "multidict-6.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da51d8928ad8b4244926fe862ba1795f0b6e68ed8c42cd2f822d435db9c2a8f4"}, + {file = "multidict-6.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:063be88bd684782a0715641de853e1e58a2f25b76388538bd62d974777ce9bc2"}, + {file = "multidict-6.2.0-cp311-cp311-win32.whl", hash = "sha256:52b05e21ff05729fbea9bc20b3a791c3c11da61649ff64cce8257c82a020466d"}, + {file = "multidict-6.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1e2a2193d3aa5cbf5758f6d5680a52aa848e0cf611da324f71e5e48a9695cc86"}, + {file = "multidict-6.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b"}, + {file = "multidict-6.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4"}, + {file = "multidict-6.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44"}, + {file = "multidict-6.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd"}, + {file = "multidict-6.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e"}, + {file = "multidict-6.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c"}, + {file = "multidict-6.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87"}, + {file = "multidict-6.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29"}, + {file = "multidict-6.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd"}, + {file = "multidict-6.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8"}, + {file = "multidict-6.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df"}, + {file = "multidict-6.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d"}, + {file = "multidict-6.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b"}, + {file = "multidict-6.2.0-cp312-cp312-win32.whl", hash = "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626"}, + {file = "multidict-6.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c"}, + {file = "multidict-6.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80"}, + {file = "multidict-6.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16"}, + {file = "multidict-6.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e"}, + {file = "multidict-6.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef7d48207926edbf8b16b336f779c557dd8f5a33035a85db9c4b0febb0706817"}, + {file = "multidict-6.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c099d3899b14e1ce52262eb82a5f5cb92157bb5106bf627b618c090a0eadc"}, + {file = "multidict-6.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e16e7297f29a544f49340012d6fc08cf14de0ab361c9eb7529f6a57a30cbfda1"}, + {file = "multidict-6.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:042028348dc5a1f2be6c666437042a98a5d24cee50380f4c0902215e5ec41844"}, + {file = "multidict-6.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08549895e6a799bd551cf276f6e59820aa084f0f90665c0f03dd3a50db5d3c48"}, + {file = "multidict-6.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ccfd74957ef53fa7380aaa1c961f523d582cd5e85a620880ffabd407f8202c0"}, + {file = "multidict-6.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83b78c680d4b15d33042d330c2fa31813ca3974197bddb3836a5c635a5fd013f"}, + {file = "multidict-6.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b4c153863dd6569f6511845922c53e39c8d61f6e81f228ad5443e690fca403de"}, + {file = "multidict-6.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:98aa8325c7f47183b45588af9c434533196e241be0a4e4ae2190b06d17675c02"}, + {file = "multidict-6.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9e658d1373c424457ddf6d55ec1db93c280b8579276bebd1f72f113072df8a5d"}, + {file = "multidict-6.2.0-cp313-cp313-win32.whl", hash = "sha256:3157126b028c074951839233647bd0e30df77ef1fedd801b48bdcad242a60f4e"}, + {file = "multidict-6.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:2e87f1926e91855ae61769ba3e3f7315120788c099677e0842e697b0bfb659f2"}, + {file = "multidict-6.2.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:2529ddbdaa424b2c6c2eb668ea684dd6b75b839d0ad4b21aad60c168269478d7"}, + {file = "multidict-6.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:13551d0e2d7201f0959725a6a769b6f7b9019a168ed96006479c9ac33fe4096b"}, + {file = "multidict-6.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d1996ee1330e245cd3aeda0887b4409e3930524c27642b046e4fae88ffa66c5e"}, + {file = "multidict-6.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c537da54ce4ff7c15e78ab1292e5799d0d43a2108e006578a57f531866f64025"}, + {file = "multidict-6.2.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f249badb360b0b4d694307ad40f811f83df4da8cef7b68e429e4eea939e49dd"}, + {file = "multidict-6.2.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48d39b1824b8d6ea7de878ef6226efbe0773f9c64333e1125e0efcfdd18a24c7"}, + {file = "multidict-6.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b99aac6bb2c37db336fa03a39b40ed4ef2818bf2dfb9441458165ebe88b793af"}, + {file = "multidict-6.2.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07bfa8bc649783e703263f783f73e27fef8cd37baaad4389816cf6a133141331"}, + {file = "multidict-6.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2c00ad31fbc2cbac85d7d0fcf90853b2ca2e69d825a2d3f3edb842ef1544a2c"}, + {file = "multidict-6.2.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d57a01a2a9fa00234aace434d8c131f0ac6e0ac6ef131eda5962d7e79edfb5b"}, + {file = "multidict-6.2.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:abf5b17bc0cf626a8a497d89ac691308dbd825d2ac372aa990b1ca114e470151"}, + {file = "multidict-6.2.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:f7716f7e7138252d88607228ce40be22660d6608d20fd365d596e7ca0738e019"}, + {file = "multidict-6.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d5a36953389f35f0a4e88dc796048829a2f467c9197265504593f0e420571547"}, + {file = "multidict-6.2.0-cp313-cp313t-win32.whl", hash = "sha256:e653d36b1bf48fa78c7fcebb5fa679342e025121ace8c87ab05c1cefd33b34fc"}, + {file = "multidict-6.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ca23db5fb195b5ef4fd1f77ce26cadefdf13dba71dab14dadd29b34d457d7c44"}, + {file = "multidict-6.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b4f3d66dd0354b79761481fc15bdafaba0b9d9076f1f42cc9ce10d7fcbda205a"}, + {file = "multidict-6.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e2a2d6749e1ff2c9c76a72c6530d5baa601205b14e441e6d98011000f47a7ac"}, + {file = "multidict-6.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cca83a629f77402cfadd58352e394d79a61c8015f1694b83ab72237ec3941f88"}, + {file = "multidict-6.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:781b5dd1db18c9e9eacc419027b0acb5073bdec9de1675c0be25ceb10e2ad133"}, + {file = "multidict-6.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf8d370b2fea27fb300825ec3984334f7dd54a581bde6456799ba3776915a656"}, + {file = "multidict-6.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25bb96338512e2f46f615a2bb7c6012fe92a4a5ebd353e5020836a7e33120349"}, + {file = "multidict-6.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e2819b0b468174de25c0ceed766606a07cedeab132383f1e83b9a4e96ccb4f"}, + {file = "multidict-6.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6aed763b6a1b28c46c055692836879328f0b334a6d61572ee4113a5d0c859872"}, + {file = "multidict-6.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a1133414b771619aa3c3000701c11b2e4624a7f492f12f256aedde97c28331a2"}, + {file = "multidict-6.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:639556758c36093b35e2e368ca485dada6afc2bd6a1b1207d85ea6dfc3deab27"}, + {file = "multidict-6.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:163f4604e76639f728d127293d24c3e208b445b463168af3d031b92b0998bb90"}, + {file = "multidict-6.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2325105e16d434749e1be8022f942876a936f9bece4ec41ae244e3d7fae42aaf"}, + {file = "multidict-6.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e4371591e621579cb6da8401e4ea405b33ff25a755874a3567c4075ca63d56e2"}, + {file = "multidict-6.2.0-cp39-cp39-win32.whl", hash = "sha256:d1175b0e0d6037fab207f05774a176d71210ebd40b1c51f480a04b65ec5c786d"}, + {file = "multidict-6.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad81012b24b88aad4c70b2cbc2dad84018783221b7f923e926f4690ff8569da3"}, + {file = "multidict-6.2.0-py3-none-any.whl", hash = "sha256:5d26547423e5e71dcc562c4acdc134b900640a39abd9066d7326a7cc2324c530"}, + {file = "multidict-6.2.0.tar.gz", hash = "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8"}, ] [package.dependencies] @@ -764,20 +782,20 @@ files = [ [[package]] name = "platformdirs" -version = "4.3.6" +version = "4.3.7" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, + {file = "platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94"}, + {file = "platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] [[package]] name = "pluggy" @@ -905,35 +923,33 @@ files = [ [[package]] name = "protobuf" -version = "5.29.3" +version = "6.30.1" description = "" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "protobuf-5.29.3-cp310-abi3-win32.whl", hash = "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888"}, - {file = "protobuf-5.29.3-cp310-abi3-win_amd64.whl", hash = "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a"}, - {file = "protobuf-5.29.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8434404bbf139aa9e1300dbf989667a83d42ddda9153d8ab76e0d5dcaca484e"}, - {file = "protobuf-5.29.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:daaf63f70f25e8689c072cfad4334ca0ac1d1e05a92fc15c54eb9cf23c3efd84"}, - {file = "protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:c027e08a08be10b67c06bf2370b99c811c466398c357e615ca88c91c07f0910f"}, - {file = "protobuf-5.29.3-cp38-cp38-win32.whl", hash = "sha256:84a57163a0ccef3f96e4b6a20516cedcf5bb3a95a657131c5c3ac62200d23252"}, - {file = "protobuf-5.29.3-cp38-cp38-win_amd64.whl", hash = "sha256:b89c115d877892a512f79a8114564fb435943b59067615894c3b13cd3e1fa107"}, - {file = "protobuf-5.29.3-cp39-cp39-win32.whl", hash = "sha256:0eb32bfa5219fc8d4111803e9a690658aa2e6366384fd0851064b963b6d1f2a7"}, - {file = "protobuf-5.29.3-cp39-cp39-win_amd64.whl", hash = "sha256:6ce8cc3389a20693bfde6c6562e03474c40851b44975c9b2bf6df7d8c4f864da"}, - {file = "protobuf-5.29.3-py3-none-any.whl", hash = "sha256:0a18ed4a24198528f2333802eb075e59dea9d679ab7a6c5efb017a59004d849f"}, - {file = "protobuf-5.29.3.tar.gz", hash = "sha256:5da0f41edaf117bde316404bad1a486cb4ededf8e4a54891296f648e8e076620"}, + {file = "protobuf-6.30.1-cp310-abi3-win32.whl", hash = "sha256:ba0706f948d0195f5cac504da156d88174e03218d9364ab40d903788c1903d7e"}, + {file = "protobuf-6.30.1-cp310-abi3-win_amd64.whl", hash = "sha256:ed484f9ddd47f0f1bf0648806cccdb4fe2fb6b19820f9b79a5adf5dcfd1b8c5f"}, + {file = "protobuf-6.30.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aa4f7dfaed0d840b03d08d14bfdb41348feaee06a828a8c455698234135b4075"}, + {file = "protobuf-6.30.1-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:47cd320b7db63e8c9ac35f5596ea1c1e61491d8a8eb6d8b45edc44760b53a4f6"}, + {file = "protobuf-6.30.1-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:e3083660225fa94748ac2e407f09a899e6a28bf9c0e70c75def8d15706bf85fc"}, + {file = "protobuf-6.30.1-cp39-cp39-win32.whl", hash = "sha256:554d7e61cce2aa4c63ca27328f757a9f3867bce8ec213bf09096a8d16bcdcb6a"}, + {file = "protobuf-6.30.1-cp39-cp39-win_amd64.whl", hash = "sha256:b510f55ce60f84dc7febc619b47215b900466e3555ab8cb1ba42deb4496d6cc0"}, + {file = "protobuf-6.30.1-py3-none-any.whl", hash = "sha256:3c25e51e1359f1f5fa3b298faa6016e650d148f214db2e47671131b9063c53be"}, + {file = "protobuf-6.30.1.tar.gz", hash = "sha256:535fb4e44d0236893d5cf1263a0f706f1160b689a7ab962e9da8a9ce4050b780"}, ] [[package]] name = "pyright" -version = "1.1.396" +version = "1.1.397" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "pyright-1.1.396-py3-none-any.whl", hash = "sha256:c635e473095b9138c471abccca22b9fedbe63858e0b40d4fc4b67da041891844"}, - {file = "pyright-1.1.396.tar.gz", hash = "sha256:142901f5908f5a0895be3d3befcc18bedcdb8cc1798deecaec86ef7233a29b03"}, + {file = "pyright-1.1.397-py3-none-any.whl", hash = "sha256:2e93fba776e714a82b085d68f8345b01f91ba43e1ab9d513e79b70fc85906257"}, + {file = "pyright-1.1.397.tar.gz", hash = "sha256:07530fd65a449e4b0b28dceef14be0d8e0995a7a5b1bb2f3f897c3e548451ce3"}, ] [package.dependencies] @@ -1052,6 +1068,18 @@ files = [ {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] +[[package]] +name = "types-protobuf" +version = "5.29.1.20250315" +description = "Typing stubs for protobuf" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "types_protobuf-5.29.1.20250315-py3-none-any.whl", hash = "sha256:57efd51fd0979d1f5e1d94053d1e7cfff9c028e8d05b17e341b91a1c7fce37c4"}, + {file = "types_protobuf-5.29.1.20250315.tar.gz", hash = "sha256:0b05bc34621d046de54b94fddd5f4eb3bf849fe2e13a50f8fb8e89f35045ff49"}, +] + [[package]] name = "typing-extensions" version = "4.12.2" @@ -1183,4 +1211,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.1" python-versions = "^3.9" -content-hash = "5b405c38973d3e26eca64c00652be4703ff9c7eb72ae2383dc28ab34f1b7e918" +content-hash = "865b8ca3361b653d33e664e909fc2e8713ab34ed038a30359e960396b7ccda96" diff --git a/pyproject.toml b/pyproject.toml index b8d9010..686a525 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aserto" -version = "0.32.1" +version = "0.32.2" description = "Aserto API client" readme = "README.md" authors = ["Aserto, Inc. "] @@ -31,18 +31,16 @@ packages = [ [tool.poetry.dependencies] python = "^3.9" aiohttp = "^3.10.2" -grpcio = "^1.64.1" -protobuf = "^5.27.2" -aserto-authorizer = "^0.20.3" -aserto-directory = "^0.33.5" -certifi = ">=2024.8.30" +aserto-directory = "^0.33.8" +aserto-authorizer = "^0.20.7" [tool.poetry.group.dev.dependencies] -black = "^24.0" -isort= "^5.9.0" +black = "^25.1.0" +isort = "^6.0.1" pytest-asyncio = "^0.23" pyright = "^1.1.0" requests = "^2.31.0" +grpc-stubs = ">=1.53.0.5" [tool.black] line-length = 100 @@ -51,6 +49,16 @@ target-version = ["py38"] [tool.isort] profile = "black" +[tool.pylint] +max-line-length = 100 +disable = [ + "missing-module-docstring", + "missing-class-docstring", + "missing-function-docstring", + "too-many-arguments", + "too-many-positional-arguments", + "too-many-public-methods", +] [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/src/aserto/client/_typing.py b/src/aserto/client/_typing.py deleted file mode 100644 index 38680e8..0000000 --- a/src/aserto/client/_typing.py +++ /dev/null @@ -1,5 +0,0 @@ -from typing import NoReturn as Nothing - - -def assert_unreachable(value: Nothing) -> Nothing: - raise AssertionError(f"Unexpectedly reached code with unhandled value: {value}") diff --git a/src/aserto/client/authorizer/__init__.py b/src/aserto/client/authorizer/__init__.py index 06a3d08..611da59 100644 --- a/src/aserto/client/authorizer/__init__.py +++ b/src/aserto/client/authorizer/__init__.py @@ -1,10 +1,9 @@ import datetime import typing -import aserto.authorizer.v2 as authorizer -import aserto.authorizer.v2.api as api import grpc -import grpc.aio as grpcaio + +import aserto.authorizer.v2 as authorizer from aserto.authorizer.v2 import ( CompileResponse, GetPolicyResponse, @@ -12,16 +11,23 @@ QueryOptions, QueryResponse, ) + +from aserto.authorizer.v2 import api from aserto.authorizer.v2.api import IdentityContext, IdentityType import aserto.client._deadline as timeout -import aserto.client.authorizer.helpers as helpers import aserto.client.resource_context as res_ctx +from aserto.client.authorizer import helpers from aserto.client.authorizer.helpers import DecisionTree from aserto.client.identity import Identity from aserto.client.options import AuthorizerOptions from aserto.client.resource_context import ResourceContext +if typing.TYPE_CHECKING: + Metadata = grpc.Metadata +else: + Metadata = typing.NewType("Metadata", typing.Tuple) + class AuthorizerClient: def __init__( @@ -48,16 +54,16 @@ def _headers(self) -> typing.Mapping[str, str]: return self._options.auth_headers @property - def _metadata(self) -> grpcaio.Metadata: - return grpcaio.Metadata(*tuple(self._headers.items())) + def _metadata(self) -> Metadata: + return tuple(self._headers.items()) def decision_tree( self, *, policy_path_root: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str] = None, - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, policy_path_separator: typing.Optional[typing.Literal["DOT", "SLASH"]] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, @@ -93,8 +99,8 @@ def decisions( *, policy_path: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, ) -> typing.Dict[str, bool]: @@ -129,8 +135,8 @@ def query( input: str, policy_path: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, options: typing.Optional[QueryOptions] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, @@ -168,8 +174,8 @@ def compile( disable_inlining: typing.Sequence[str], policy_path: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str, + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, options: typing.Optional[QueryOptions] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, @@ -203,8 +209,8 @@ def compile( def list_policies( self, *, - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str, + policy_instance_label: str = "", deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, ) -> ListPoliciesResponse: response = self.client.ListPolicies( @@ -226,8 +232,8 @@ def get_policy( self, *, id: str, - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str, + policy_instance_label: str = "", deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, ) -> GetPolicyResponse: response = self.client.GetPolicy( diff --git a/src/aserto/client/authorizer/aio/__init__.py b/src/aserto/client/authorizer/aio/__init__.py index 1918529..178de3c 100644 --- a/src/aserto/client/authorizer/aio/__init__.py +++ b/src/aserto/client/authorizer/aio/__init__.py @@ -1,9 +1,10 @@ import datetime import typing -import aserto.authorizer.v2 as authorizer -import aserto.authorizer.v2.api as api import grpc.aio as grpc +from grpc import ssl_channel_credentials + +import aserto.authorizer.v2 as authorizer from aserto.authorizer.v2 import ( CompileResponse, GetPolicyResponse, @@ -11,17 +12,23 @@ QueryOptions, QueryResponse, ) + +import aserto.authorizer.v2.api as api from aserto.authorizer.v2.api import IdentityContext, IdentityType -from grpc import ssl_channel_credentials import aserto.client._deadline as timeout -import aserto.client.authorizer.helpers as helpers import aserto.client.resource_context as res_ctx +from aserto.client.authorizer import helpers from aserto.client.authorizer.helpers import DecisionTree from aserto.client.identity import Identity from aserto.client.options import AuthorizerOptions from aserto.client.resource_context import ResourceContext +if typing.TYPE_CHECKING: + AuthorizerAsyncStub = authorizer.AuthorizerAsyncStub +else: + AuthorizerAsyncStub = authorizer.AuthorizerStub + class AuthorizerClient: def __init__( @@ -41,7 +48,7 @@ def __init__( target=self._options.url, credentials=ssl_channel_credentials(self._options.cert), ) - self.client = authorizer.AuthorizerStub(self._channel) + self.client = typing.cast(AuthorizerAsyncStub, authorizer.AuthorizerStub(self._channel)) @property def _headers(self) -> typing.Mapping[str, str]: @@ -56,8 +63,8 @@ async def decision_tree( *, policy_path_root: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str] = None, - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, policy_path_separator: typing.Optional[typing.Literal["DOT", "SLASH"]] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, @@ -93,8 +100,8 @@ async def decisions( *, policy_path: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, ) -> typing.Dict[str, bool]: @@ -129,8 +136,8 @@ async def query( input: str, policy_path: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, options: typing.Optional[QueryOptions] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, @@ -168,8 +175,8 @@ async def compile( disable_inlining: typing.Sequence[str], policy_path: str, decisions: typing.Sequence[str], - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", resource_context: typing.Optional[ResourceContext] = None, options: typing.Optional[QueryOptions] = None, deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, @@ -203,8 +210,8 @@ async def compile( async def list_policies( self, *, - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, ) -> ListPoliciesResponse: response = await self.client.ListPolicies( @@ -226,8 +233,8 @@ async def get_policy( self, *, id: str, - policy_instance_name: typing.Optional[str], - policy_instance_label: typing.Optional[str] = None, + policy_instance_name: str = "", + policy_instance_label: str = "", deadline: typing.Optional[typing.Union[datetime.datetime, datetime.timedelta]] = None, ) -> GetPolicyResponse: return await self.client.GetPolicy( @@ -244,7 +251,13 @@ async def get_policy( ), ) - async def close(self) -> None: - """Closes the gRPC channel""" + async def close(self, grace: typing.Optional[float] = None) -> None: + """Closes the authorizer client's connection to the server. - await self._channel.close() + If a grace period is specified, this method waits until all active + requests are finished or until the grace period is reached. Requests that haven't + been terminated within the grace period are aborted. + If a grace period is not specified (by passing None for grace), + all existing requests are cancelled immediately. + """ + await self._channel.close(grace) diff --git a/src/aserto/client/authorizer/helpers.py b/src/aserto/client/authorizer/helpers.py index 0fd2dde..3014d3e 100644 --- a/src/aserto/client/authorizer/helpers.py +++ b/src/aserto/client/authorizer/helpers.py @@ -2,18 +2,18 @@ from aserto.authorizer.v2 import DecisionTreeResponse, PathSeparator -from aserto.client._typing import assert_unreachable - DecisionTree = Dict[str, Dict[str, bool]] -def policy_path_separator_field(policy_path_separator: Literal["DOT", "SLASH"]) -> PathSeparator: +def policy_path_separator_field( + policy_path_separator: Literal["DOT", "SLASH"], +) -> PathSeparator.ValueType: if policy_path_separator == "DOT": return PathSeparator.PATH_SEPARATOR_DOT - elif policy_path_separator == "SLASH": + if policy_path_separator == "SLASH": return PathSeparator.PATH_SEPARATOR_SLASH - else: - assert_unreachable(policy_path_separator) + + raise ValueError(f"Invalid PathSeparator: {policy_path_separator}") def validate_decision_tree(response: DecisionTreeResponse) -> DecisionTree: diff --git a/src/aserto/client/directory/__init__.py b/src/aserto/client/directory/__init__.py index 7e9f3ef..3d83c39 100644 --- a/src/aserto/client/directory/__init__.py +++ b/src/aserto/client/directory/__init__.py @@ -1,5 +1,7 @@ from typing import Literal, Tuple +from grpc import RpcError, StatusCode + from aserto.client.directory.channels import Channels __all__ = ["Channels"] @@ -9,6 +11,10 @@ class NotFoundError(Exception): pass +class InvalidArgumentError(Exception): + pass + + class ConfigError(Exception): pass @@ -20,3 +26,10 @@ def get_metadata(api_key, tenant_id) -> Tuple[Tuple[str, str], ...]: if tenant_id: md += (("aserto-tenant-id", tenant_id),) return md + + +def translate_rpc_error(err: RpcError) -> None: + if err.code() == StatusCode.NOT_FOUND: + raise NotFoundError(err.details()) from err + if err.code() == StatusCode.INVALID_ARGUMENT: + raise InvalidArgumentError(err.details()) from err diff --git a/src/aserto/client/directory/aio/__init__.py b/src/aserto/client/directory/aio/__init__.py index 4662db2..da55b18 100644 --- a/src/aserto/client/directory/aio/__init__.py +++ b/src/aserto/client/directory/aio/__init__.py @@ -1,33 +1,49 @@ -import grpc.aio as grpc_aio from typing import Optional + +import grpc.aio as grpc_aio + from aserto.client.directory.channels import channel_credentials, validate_addresses def build_grpc_channel(address: str, ca_cert_path: str) -> Optional[grpc_aio.Channel]: if address == "": return None - + return grpc_aio.secure_channel( - target=address, + target=address, credentials=channel_credentials(cert=ca_cert_path), ) + class Channels: def __init__( - self, - ca_cert_path: str, - default_address: str = "", - reader_address: str = "", - writer_address: str = "", - importer_address: str = "", - exporter_address: str = "", - model_address: str = "", - ) -> None: - validate_addresses(address=default_address, reader_address=reader_address, writer_address=writer_address, - importer_address=importer_address, exporter_address=exporter_address, model_address=model_address) - - self._addresses = [default_address, reader_address, writer_address, importer_address, exporter_address, model_address] - self._channels = dict() + self, + ca_cert_path: str, + default_address: str = "", + reader_address: str = "", + writer_address: str = "", + importer_address: str = "", + exporter_address: str = "", + model_address: str = "", + ) -> None: + validate_addresses( + address=default_address, + reader_address=reader_address, + writer_address=writer_address, + importer_address=importer_address, + exporter_address=exporter_address, + model_address=model_address, + ) + + self._addresses = [ + default_address, + reader_address, + writer_address, + importer_address, + exporter_address, + model_address, + ] + self._channels = {} for x in self._addresses: if x and x not in self._channels: self._channels[x] = build_grpc_channel(x, ca_cert_path=ca_cert_path) @@ -37,13 +53,13 @@ def get(self, address: str, default_address: str) -> Optional[grpc_aio.Channel]: return self._channels[address] if default_address != "": return self._channels[default_address] - - return None + return None async def close(self) -> None: for x in self._addresses: if x != "" and self._channels[x] is not None: - await self._channels[x].close() + await self._channels[x].close() + -__all__ = ["Channels"] \ No newline at end of file +__all__ = ["Channels"] diff --git a/src/aserto/client/directory/channels.py b/src/aserto/client/directory/channels.py index 2b50575..d18cff4 100644 --- a/src/aserto/client/directory/channels.py +++ b/src/aserto/client/directory/channels.py @@ -1,6 +1,7 @@ -from grpc import secure_channel, Channel, ChannelCredentials, ssl_channel_credentials from typing import Optional +from grpc import secure_channel, Channel, ChannelCredentials, ssl_channel_credentials + def validate_addresses( address: str, @@ -8,42 +9,68 @@ def validate_addresses( writer_address: str, importer_address: str, exporter_address: str, - model_address: str) -> None: - if address == "" and reader_address == "" and writer_address == "" and importer_address == "" and exporter_address == "" and model_address == "": + model_address: str, +) -> None: + if not any( + ( + address, + reader_address, + writer_address, + importer_address, + exporter_address, + model_address, + ), + ): raise ValueError("at least one directory service address must be specified") + def channel_credentials(cert) -> ChannelCredentials: if cert: with open(cert, "rb") as f: return ssl_channel_credentials(f.read()) else: return ssl_channel_credentials() - + + def build_grpc_channel(address: str, ca_cert_path: str) -> Optional[Channel]: if address == "": return None - + return secure_channel( - target=address, + target=address, credentials=channel_credentials(cert=ca_cert_path), ) + class Channels: def __init__( - self, - ca_cert_path: str, - default_address: str = "", - reader_address: str = "", - writer_address: str = "", - importer_address: str = "", - exporter_address: str = "", - model_address: str = "", - ) -> None: - validate_addresses(address=default_address, reader_address=reader_address, writer_address=writer_address, - importer_address=importer_address, exporter_address=exporter_address, model_address=model_address) - - self._addresses = [default_address, reader_address, writer_address, importer_address, exporter_address, model_address] - self._channels = dict() + self, + ca_cert_path: str, + default_address: str = "", + reader_address: str = "", + writer_address: str = "", + importer_address: str = "", + exporter_address: str = "", + model_address: str = "", + ) -> None: + validate_addresses( + address=default_address, + reader_address=reader_address, + writer_address=writer_address, + importer_address=importer_address, + exporter_address=exporter_address, + model_address=model_address, + ) + + self._addresses = [ + default_address, + reader_address, + writer_address, + importer_address, + exporter_address, + model_address, + ] + self._channels = {} for x in self._addresses: if x and x not in self._channels: self._channels[x] = build_grpc_channel(x, ca_cert_path=ca_cert_path) @@ -53,11 +80,10 @@ def get(self, address: str, default_address: str) -> Optional[Channel]: return self._channels[address] if default_address != "": return self._channels[default_address] - - return None + return None def close(self) -> None: for x in self._addresses: if x != "" and self._channels[x] is not None: - self._channels[x].close() \ No newline at end of file + self._channels[x].close() diff --git a/src/aserto/client/directory/v3/__init__.py b/src/aserto/client/directory/v3/__init__.py index b9352d7..f88aa26 100644 --- a/src/aserto/client/directory/v3/__init__.py +++ b/src/aserto/client/directory/v3/__init__.py @@ -1,20 +1,30 @@ import datetime import typing -from aserto.directory.common.v3 import Object, PaginationRequest, Relation +import grpc + +from google.protobuf import json_format +from google.protobuf.struct_pb2 import Struct + import aserto.directory.exporter.v3 as exporter import aserto.directory.importer.v3 as importer import aserto.directory.model.v3 as model import aserto.directory.reader.v3 as reader -from aserto.directory.reader.v3 import GetObjectResponse, GetObjectsResponse import aserto.directory.writer.v3 as writer -import google.protobuf.json_format as json_format -from google.protobuf.struct_pb2 import Struct -import grpc -import aserto.client.directory as directory -from aserto.client.directory import NotFoundError -import aserto.client.directory.v3.helpers as helpers +from aserto.directory.common.v3 import Object, PaginationRequest, Relation +from aserto.directory.reader.v3 import GetObjectResponse, GetObjectsResponse + +from aserto.client.directory.v3 import helpers + +from aserto.client.directory import ( + Channels, + ConfigError, + get_metadata, + InvalidArgumentError, + NotFoundError, + translate_rpc_error, +) from aserto.client.directory.v3.helpers import ( ETagMismatchError, ExportOption, @@ -41,7 +51,7 @@ def __init__( exporter_address: str = "", model_address: str = "", ) -> None: - self._channels = directory.Channels( + self._channels = Channels( default_address=address, reader_address=reader_address, writer_address=writer_address, @@ -51,7 +61,7 @@ def __init__( ca_cert_path=ca_cert_path, ) - self._metadata = directory.get_metadata(api_key=api_key, tenant_id=tenant_id) + self._metadata = get_metadata(api_key=api_key, tenant_id=tenant_id) reader_channel = self._channels.get(reader_address, address) self._reader = reader.ReaderStub(reader_channel) if reader_channel is not None else None @@ -74,31 +84,31 @@ def __init__( def reader(self) -> reader.ReaderStub: if self._reader is None: - raise directory.ConfigError("reader service address not specified") + raise ConfigError("reader service address not specified") return self._reader def writer(self) -> writer.WriterStub: if self._writer is None: - raise directory.ConfigError("writer service address not specified") + raise ConfigError("writer service address not specified") return self._writer def importer(self) -> importer.ImporterStub: if self._importer is None: - raise directory.ConfigError("importer service address not specified") + raise ConfigError("importer service address not specified") return self._importer def exporter(self) -> exporter.ExporterStub: if self._exporter is None: - raise directory.ConfigError("expoerter service address not specified") + raise ConfigError("expoerter service address not specified") return self._exporter def model(self) -> model.ModelStub: if self._model is None: - raise directory.ConfigError("model service address not specified") + raise ConfigError("model service address not specified") return self._model @@ -109,8 +119,7 @@ def get_object( object_id: str, with_relations: typing.Literal[False] = False, page: typing.Optional[PaginationRequest] = None, - ) -> Object: - ... + ) -> Object: ... @typing.overload def get_object( @@ -119,8 +128,7 @@ def get_object( object_id: str, with_relations: typing.Literal[True], page: typing.Optional[PaginationRequest] = None, - ) -> GetObjectResponse: - ... + ) -> GetObjectResponse: ... def get_object( self, @@ -131,6 +139,7 @@ def get_object( ) -> typing.Union[Object, GetObjectResponse]: """Retrieve a directory object by its type and id, optionally with the object's relations. Raises a NotFoundError if an object with the specified type and id doesn't exist. + Raises an InvalidArgumentError if the object type or id is invalid. Parameters ---- @@ -141,7 +150,8 @@ def get_object( with_relations: bool if True, the response includes all relations for the object. Default: False. page: typing.Optional[PaginationRequest] - paging information - used to iterate over all relations for an object when with_relations is True. + paging information - used to iterate over all relations for an object when + with_relations is True. Returns ---- @@ -164,17 +174,18 @@ def get_object( return response.result except grpc.RpcError as err: - if err.code() == grpc.StatusCode.NOT_FOUND: # type: ignore - raise NotFoundError from err + translate_rpc_error(err) raise def get_object_many( self, identifiers: typing.Sequence[ObjectIdentifier], - ) -> typing.List[Object]: + ) -> typing.Sequence[Object]: """Retrieve a list of directory object using a list of object key and type pairs. Returns a list of the requested objects. Raises a NotFoundError if any of the objects don't exist. + Raises an InvalidArgumentError if the object or subject type or id is invalid or + if the relation isn't defined on the object type or isn't assignable to the subject type. Parameters ---- @@ -194,8 +205,7 @@ def get_object_many( ) return response.results except grpc.RpcError as err: - if err.code() == grpc.StatusCode.NOT_FOUND: # type: ignore - raise NotFoundError from err + translate_rpc_error(err) raise def get_objects( @@ -227,19 +237,20 @@ def get_objects( @typing.overload def set_object(self, *, object: Object) -> Object: - """Create a new directory object or updates an existing object if an object with the same type and id already exists. - To update an existing object, the etag field must be set to the value of the current object's etag. + """Create a new directory object or updates an existing object if an object with the same + type and id already exists. + To update an existing object, the etag field must be set to the value of the current + object's etag. Returns the created/updated object. Parameters ---- - object : Object + obj : Object Returns ---- The created/updated object. """ - ... @typing.overload def set_object( @@ -251,8 +262,10 @@ def set_object( properties: typing.Optional[typing.Union[typing.Mapping[str, typing.Any], Struct]] = None, etag: str = "", ) -> Object: - """Create a new directory object or updates an existing object if an object with the same type and id already exists. - To update an existing object, the etag argument must be set to the value of the current object's etag. + """Create a new directory object or updates an existing object if an object with the same + type and id already exists. + To update an existing object, the etag argument must be set to the value of the current + object's etag. Returns the created/updated object. Parameters @@ -264,16 +277,16 @@ def set_object( display_name: str, optional display name for the object. properties: typing.Optional[typing.Union[typing.Mapping[str, typing.Any], Struct]], - optional JSON properties to set on the object. This can be passed in as a dict with string keys and - JSON-serializable values, or as a Struct. + optional JSON properties to set on the object. This can be passed in as a dict with + string keys and JSON-serializable values, or as a Struct. etag: str - optional etag. If set and the current object's etag doesn't match, the call raises an EtagMismatchError. + optional etag. If set and the current object's etag doesn't match, the call raises + an EtagMismatchError. Returns ---- The created/updated object. """ - ... def set_object( self, @@ -347,8 +360,7 @@ def get_relation( subject_type: str = "", subject_id: str = "", subject_relation: str = "", - ) -> Relation: - ... + ) -> Relation: ... @typing.overload def get_relation( @@ -361,8 +373,7 @@ def get_relation( subject_type: str = "", subject_id: str = "", subject_relation: str = "", - ) -> RelationResponse: - ... + ) -> RelationResponse: ... def get_relation( self, @@ -377,6 +388,8 @@ def get_relation( ) -> typing.Union[Relation, RelationResponse]: """Retrieve a directory relation that matches the specified filters. Raises a NotFoundError no matching relation is found. + Raises an InvalidArgumentError if the object or subject type or id is invalid or + if the relation isn't defined on the object type or isn't assignable to the subject type. Also returns the relation's object and subject if with_objects is set to True. Parameters @@ -429,8 +442,7 @@ def get_relation( ) except grpc.RpcError as err: - if err.code() == grpc.StatusCode.NOT_FOUND: # type: ignore - raise NotFoundError from err + translate_rpc_error(err) raise def get_relations( @@ -451,13 +463,15 @@ def get_relations( object_type : str include relations where the object is of this type. object_id: str - include relations where the object has this id. If specified, object_type must also be specified. + include relations where the object has this id. If specified, object_type must also be + specified. relation: str include relations of this type. subject_type : str include relations where the subject is of this type. subject_id: str - include relations where the subject has this id. If specified, subject_type must also be specified. + include relations where the subject has this id. If specified, subject_type must also be + specified. subject_relation: str include relations the specified subject relation. with_objects: bool @@ -549,7 +563,7 @@ def delete_relation( relation: str, subject_type: str, subject_id: str, - subject_relation: typing.Optional[str] = None, + subject_relation: str = "", ) -> None: """Deletes a relation. @@ -608,10 +622,11 @@ def find_subjects( subject_type : str the type of subject to search for. subject_relation: str - optional subject relation. This is useful when searching for intermediate subjects like groups. + optional subject relation. This is useful when searching for intermediate subjects like + groups. explain: bool - if True, the response includes, for each match, the set of relations that grant the specified relation or - permission . + if True, the response includes, for each match, the set of relations that grant the + specified relation or permission. trace: bool if True, the response includes the trace of the search process. @@ -661,10 +676,11 @@ def find_objects( subject_id: str the id of the subject to search from. subject_relation: str - optional subject relation. This is useful when searching for intermediate subjects like groups. + optional subject relation. This is useful when searching for intermediate subjects like + groups. explain: bool - if True, the response includes, for each match, the set of relations that grant the specified relation or - permission . + if True, the response includes, for each match, the set of relations that grant the + specified relation or permission. trace: bool if True, the response includes the trace of the search process. @@ -700,7 +716,8 @@ def check( subject_id: str, ) -> bool: """Checks if a subject has a given permissions or relation to an object. - Returns True if the subject has the specified permission/relation to the object. False, otherwise. + Returns True if the subject has the specified permission/relation to the object. + False, otherwise. Parameters ---- @@ -814,12 +831,10 @@ def check_permission( return response.check @typing.overload - def get_manifest(self) -> Manifest: - ... + def get_manifest(self) -> Manifest: ... @typing.overload - def get_manifest(self, etag: str) -> typing.Optional[Manifest]: - ... + def get_manifest(self, etag: str) -> typing.Optional[Manifest]: ... def get_manifest(self, etag: str = "") -> typing.Optional[Manifest]: """Returns the current manifest. @@ -926,7 +941,7 @@ def _import_iter() -> typing.Iterator[importer.ImportRequest]: return ImportResponse(obj_counter, rel_counter) def export_data( - self, options: ExportOption, start_from: typing.Optional[datetime.datetime] = None + self, options: ExportOption.ValueType, start_from: typing.Optional[datetime.datetime] = None ) -> typing.Iterator[typing.Union[Object, Relation]]: """Exports data from the directory. @@ -938,7 +953,8 @@ def export_data( OPTION_DATA - export both objects and relations start_from: typing.Optional[datetime.datetime] - if provided, only objects and relations that have been modified after this date are exported. + if provided, only objects and relations that have been modified after this date are + exported. """ req = exporter.ExportRequest(options=options) @@ -959,25 +975,27 @@ def close(self) -> None: def __enter__(self): return self - def __exit__(self, type, value, traceback) -> None: + def __exit__(self, typ, value, traceback) -> None: self.close() __all__ = [ + "ConfigError", "Directory", - "GetObjectResponse", - "GetObjectsResponse", - "Object", - "NotFoundError", - "PaginationRequest", - "Relation", - "Struct", "ETagMismatchError", "ExportOption", + "GetObjectResponse", + "GetObjectsResponse", "ImportCounter", "ImportResponse", + "InvalidArgumentError", "Manifest", + "NotFoundError", + "Object", "ObjectIdentifier", + "PaginationRequest", + "Relation", "RelationResponse", "RelationsResponse", + "Struct", ] diff --git a/src/aserto/client/directory/v3/aio/__init__.py b/src/aserto/client/directory/v3/aio/__init__.py index 90c76fd..4759475 100644 --- a/src/aserto/client/directory/v3/aio/__init__.py +++ b/src/aserto/client/directory/v3/aio/__init__.py @@ -1,22 +1,32 @@ import datetime import typing -from aserto.directory.common.v3 import Object, PaginationRequest, Relation +import grpc.aio as grpc + +from google.protobuf import json_format +from google.protobuf.struct_pb2 import Struct +from grpc import RpcError, StatusCode + import aserto.directory.exporter.v3 as exporter import aserto.directory.importer.v3 as importer import aserto.directory.model.v3 as model import aserto.directory.reader.v3 as reader -from aserto.directory.reader.v3 import GetObjectResponse, GetObjectsResponse import aserto.directory.writer.v3 as writer -import google.protobuf.json_format as json_format -from google.protobuf.struct_pb2 import Struct -from grpc import RpcError, StatusCode -import grpc.aio as grpc -import aserto.client.directory as directory -from aserto.client.directory import NotFoundError -import aserto.client.directory.aio as aio -import aserto.client.directory.v3.helpers as helpers +from aserto.directory.common.v3 import Object, PaginationRequest, Relation +from aserto.directory.reader.v3 import GetObjectResponse, GetObjectsResponse + +from aserto.client.directory import aio +from aserto.client.directory.v3 import helpers + +from aserto.client.directory import ( + ConfigError, + get_metadata, + InvalidArgumentError, + NotFoundError, + translate_rpc_error, +) + from aserto.client.directory.v3.helpers import ( ETagMismatchError, ExportOption, @@ -29,6 +39,19 @@ RelationsResponse, ) +if typing.TYPE_CHECKING: + ExporterAsyncStub = exporter.ExporterAsyncStub + ImporterAsyncStub = importer.ImporterAsyncStub + ModelAsyncStub = model.ModelAsyncStub + ReaderAsyncStub = reader.ReaderAsyncStub + WriterAsyncStub = writer.WriterAsyncStub +else: + ExporterAsyncStub = exporter.ExporterStub + ImporterAsyncStub = importer.ImporterStub + ModelAsyncStub = model.ModelStub + ReaderAsyncStub = reader.ReaderStub + WriterAsyncStub = writer.WriterStub + class Directory: def __init__( @@ -53,54 +76,70 @@ def __init__( ca_cert_path=ca_cert_path, ) - self._metadata = directory.get_metadata(api_key=api_key, tenant_id=tenant_id) + self._metadata = get_metadata(api_key=api_key, tenant_id=tenant_id) reader_channel = self._channels.get(reader_address, address) - self._reader = reader.ReaderStub(reader_channel) if reader_channel is not None else None + self._reader = ( + typing.cast(ReaderAsyncStub, reader.ReaderStub(reader_channel)) + if reader_channel is not None + else None + ) writer_channel = self._channels.get(writer_address, address) - self._writer = writer.WriterStub(writer_channel) if writer_channel is not None else None + self._writer = ( + typing.cast(WriterAsyncStub, writer.WriterStub(writer_channel)) + if writer_channel is not None + else None + ) model_channel = self._channels.get(model_address, address) - self._model = model.ModelStub(model_channel) if model_channel is not None else None + self._model = ( + typing.cast(ModelAsyncStub, model.ModelStub(model_channel)) + if model_channel is not None + else None + ) importer_channel = self._channels.get(importer_address, address) self._importer = ( - importer.ImporterStub(importer_channel) if importer_channel is not None else None + typing.cast(ImporterAsyncStub, importer.ImporterStub(importer_channel)) + if importer_channel is not None + else None ) exporter_channel = self._channels.get(exporter_address, address) self._exporter = ( - exporter.ExporterStub(exporter_channel) if exporter_channel is not None else None + typing.cast(ExporterAsyncStub, exporter.ExporterStub(exporter_channel)) + if exporter_channel is not None + else None ) - def reader(self) -> reader.ReaderStub: + def reader(self) -> ReaderAsyncStub: if self._reader is None: - raise directory.ConfigError("reader service address not specified") + raise ConfigError("reader service address not specified") return self._reader - def writer(self) -> writer.WriterStub: + def writer(self) -> WriterAsyncStub: if self._writer is None: - raise directory.ConfigError("writer service address not specified") + raise ConfigError("writer service address not specified") return self._writer - def importer(self) -> importer.ImporterStub: + def importer(self) -> ImporterAsyncStub: if self._importer is None: - raise directory.ConfigError("importer service address not specified") + raise ConfigError("importer service address not specified") return self._importer - def exporter(self) -> exporter.ExporterStub: + def exporter(self) -> ExporterAsyncStub: if self._exporter is None: - raise directory.ConfigError("expoerter service address not specified") + raise ConfigError("expoerter service address not specified") return self._exporter - def model(self) -> model.ModelStub: + def model(self) -> ModelAsyncStub: if self._model is None: - raise directory.ConfigError("model service address not specified") + raise ConfigError("model service address not specified") return self._model @@ -134,7 +173,7 @@ async def get_objects( async def get_object_many( self, identifiers: typing.Sequence[ObjectIdentifier], - ) -> typing.List[Object]: + ) -> typing.Sequence[Object]: """Retrieve a set of directory objects. Returns a list of all objects that were found. @@ -145,8 +184,8 @@ async def get_object_many( Returns ---- - list - list of directory objects + Sequence[Object] + sequence of directory objects """ try: @@ -156,8 +195,7 @@ async def get_object_many( ) return response.results except RpcError as err: - if err.code() == StatusCode.NOT_FOUND: # type: ignore - raise NotFoundError from err + translate_rpc_error(err) raise @typing.overload @@ -167,8 +205,7 @@ async def get_object( object_id: str, with_relations: typing.Literal[False] = False, page: typing.Optional[PaginationRequest] = None, - ) -> Object: - ... + ) -> Object: ... @typing.overload async def get_object( @@ -177,8 +214,7 @@ async def get_object( object_id: str, with_relations: typing.Literal[True], page: typing.Optional[PaginationRequest] = None, - ) -> GetObjectResponse: - ... + ) -> GetObjectResponse: ... async def get_object( self, @@ -189,6 +225,7 @@ async def get_object( ) -> typing.Union[Object, GetObjectResponse]: """Retrieve a directory object by its type and id, optionally with the object's relations. Raises a NotFoundError if an object with the specified type and id doesn't exist. + Raises an InvalidArgumentError if the object type or id is invalid. Parameters ---- @@ -199,7 +236,8 @@ async def get_object( with_relations: bool if True, the response includes all relations for the object. Default: False. page: typing.Optional[PaginationRequest] - paging information - used to iterate over all relations for an object when with_relations is True. + paging information - used to iterate over all relations for an object when + with_relations is True. Returns ---- @@ -222,25 +260,25 @@ async def get_object( return response.result except RpcError as err: - if err.code() == StatusCode.NOT_FOUND: # type: ignore - raise NotFoundError from err + translate_rpc_error(err) raise @typing.overload async def set_object(self, *, object: Object) -> Object: - """Create a new directory object or updates an existing object if an object with the same type and id already exists. - To update an existing object, the etag field must be set to the value of the current object's etag. + """Create a new directory object or updates an existing object if an object with the same + type and id already exists. + To update an existing object, the etag field must be set to the value of the current + object's etag. Returns the created/updated object. Parameters ---- - object : Object + obj : Object Returns ---- The created/updated object. """ - ... @typing.overload async def set_object( @@ -252,8 +290,10 @@ async def set_object( properties: typing.Optional[typing.Union[typing.Mapping[str, typing.Any], Struct]] = None, etag: str = "", ) -> Object: - """Create a new directory object or updates an existing object if an object with the same type and id already exists. - To update an existing object, the etag argument must be set to the value of the current object's etag. + """Create a new directory object or updates an existing object if an object with the same + type and id already exists. + To update an existing object, the etag argument must be set to the value of the current + object's etag. Returns the created/updated object. Parameters @@ -265,16 +305,16 @@ async def set_object( display_name: str, optional display name for the object. properties: typing.Optional[typing.Union[typing.Mapping[str, typing.Any], Struct]], - optional JSON properties to set on the object. This can be passed in as a dict with string keys and - JSON-serializable values, or as a Struct. + optional JSON properties to set on the object. This can be passed in as a dict with + string keys and JSON-serializable values, or as a Struct. etag: str - optional etag. If set and the current object's etag doesn't match, the call raises an EtagMismatchError. + optional etag. If set and the current object's etag doesn't match, the call raises + an EtagMismatchError. Returns ---- The created/updated object. """ - ... async def set_object( self, @@ -357,13 +397,15 @@ async def get_relations( object_type : str include relations where the object is of this type. object_id: str - include relations where the object has this id. If specified, object_type must also be specified. + include relations where the object has this id. If specified, object_type must also be + specified. relation: str include relations of this type. subject_type : str include relations where the subject is of this type. subject_id: str - include relations where the subject has this id. If specified, subject_type must also be specified. + include relations where the subject has this id. If specified, subject_type must also be + specified. subject_relation: str include relations the specified subject relation. with_objects: bool @@ -413,8 +455,7 @@ async def get_relation( subject_type: str = "", subject_id: str = "", subject_relation: str = "", - ) -> Relation: - ... + ) -> Relation: ... @typing.overload async def get_relation( @@ -427,8 +468,7 @@ async def get_relation( subject_type: str = "", subject_id: str = "", subject_relation: str = "", - ) -> RelationResponse: - ... + ) -> RelationResponse: ... async def get_relation( self, @@ -443,6 +483,8 @@ async def get_relation( ) -> typing.Union[Relation, RelationResponse]: """Retrieve a directory relation that matches the specified filters. Raises a NotFoundError no matching relation is found. + Raises an InvalidArgumentError if the object or subject type or id is invalid or + if the relation isn't defined on the object type or isn't assignable to the subject type. Also returns the relation's object and subject if with_objects is set to True. Parameters @@ -495,8 +537,7 @@ async def get_relation( ) except RpcError as err: - if err.code() == StatusCode.NOT_FOUND: # type: ignore - raise NotFoundError from err + translate_rpc_error(err) raise async def set_relation( @@ -552,7 +593,7 @@ async def delete_relation( relation: str, subject_type: str, subject_id: str, - subject_relation: typing.Optional[str] = None, + subject_relation: str = "", ) -> None: """Deletes a relation. @@ -611,10 +652,11 @@ async def find_subjects( subject_type : str the type of subject to search for. subject_relation: str - optional subject relation. This is useful when searching for intermediate subjects like groups. + optional subject relation. This is useful when searching for intermediate subjects like + groups. explain: bool - if True, the response includes, for each match, the set of relations that grant the specified relation or - permission . + if True, the response includes, for each match, the set of relations that grant the + specified relation or permission. trace: bool if True, the response includes the trace of the search process. @@ -664,10 +706,11 @@ async def find_objects( subject_id: str the id of the subject to search from. subject_relation: str - optional subject relation. This is useful when searching for intermediate subjects like groups. + optional subject relation. This is useful when searching for intermediate subjects like + groups. explain: bool - if True, the response includes, for each match, the set of relations that grant the specified relation or - permission . + if True, the response includes, for each match, the set of relations that grant the + specified relation or permission. trace: bool if True, the response includes the trace of the search process. @@ -703,7 +746,8 @@ async def check( subject_id: str, ) -> bool: """Checks if a subject has a given permissions or relation to an object. - Returns True if the subject has the specified permission/relation to the object. False, otherwise. + Returns True if the subject has the specified permission/relation to the object. + False, otherwise. Parameters ---- @@ -816,12 +860,10 @@ async def check_permission( return response.check @typing.overload - async def get_manifest(self) -> Manifest: - ... + async def get_manifest(self) -> Manifest: ... @typing.overload - async def get_manifest(self, etag: str) -> typing.Optional[Manifest]: - ... + async def get_manifest(self, etag: str) -> typing.Optional[Manifest]: ... async def get_manifest(self, etag: str = "") -> typing.Optional[Manifest]: """Returns the current manifest. @@ -929,7 +971,7 @@ async def _import_iter() -> typing.AsyncIterator[importer.ImportRequest]: return ImportResponse(obj_counter, rel_counter) async def export_data( - self, options: ExportOption, start_from: typing.Optional[datetime.datetime] = None + self, options: ExportOption.ValueType, start_from: typing.Optional[datetime.datetime] = None ) -> typing.AsyncIterator[typing.Union[Object, Relation]]: """Exports data from the directory. @@ -941,7 +983,8 @@ async def export_data( OPTION_DATA - export both objects and relations start_from: typing.Optional[datetime.datetime] - if provided, only objects and relations that have been modified after this date are exported. + if provided, only objects and relations that have been modified after this + date are exported. """ req = exporter.ExportRequest(options=options) @@ -961,20 +1004,22 @@ async def close(self) -> None: __all__ = [ + "ConfigError", "Directory", - "GetObjectResponse", - "GetObjectsResponse", - "Object", - "NotFoundError", - "PaginationRequest", - "Relation", - "Struct", "ETagMismatchError", "ExportOption", + "GetObjectResponse", + "GetObjectsResponse", "ImportCounter", "ImportResponse", + "InvalidArgumentError", "Manifest", + "NotFoundError", + "Object", "ObjectIdentifier", + "PaginationRequest", + "Relation", "RelationResponse", "RelationsResponse", + "Struct", ] diff --git a/src/aserto/client/directory/v3/helpers.py b/src/aserto/client/directory/v3/helpers.py index babbabe..5cafb1e 100644 --- a/src/aserto/client/directory/v3/helpers.py +++ b/src/aserto/client/directory/v3/helpers.py @@ -1,12 +1,13 @@ from dataclasses import dataclass import datetime -from typing import List, Mapping, Optional +from typing import List, Mapping, Optional, Sequence + +from google.protobuf.struct_pb2 import Struct from aserto.directory.common.v3 import Object from aserto.directory.common.v3 import ObjectIdentifier as ObjectIdentifierProto from aserto.directory.common.v3 import PaginationResponse, Relation from aserto.directory.exporter.v3 import Option -from google.protobuf.struct_pb2 import Struct MAX_CHUNK_BYTES = 64 * 1024 @@ -50,12 +51,12 @@ class RelationsResponse: Attributes ---- - relation The returned relation. + relation The returned relations. objects If with_relations is True, a mapping from "type:key" to the corresponding object. page The next page's token if there are more results. """ - relations: List[Relation] + relations: Sequence[Relation] objects: Optional[Mapping[ObjectIdentifier, Object]] page: PaginationResponse @@ -68,13 +69,14 @@ class FindResponse: Attributes ---- results The list of matching object identifiers. - explanation For each object in results, a list of paths that connect the result to the searched object. + explanation For each object in results, a list of paths that connect the result to the + searched object. trace The sequence of queries that were executed to find the results. """ results: List[ObjectIdentifier] explanation: Mapping[str, List[List[str]]] - trace: List[str] + trace: Sequence[str] @dataclass(frozen=True) @@ -116,4 +118,4 @@ def relation_objects(objects: Mapping[str, Object]) -> Mapping[ObjectIdentifier, def explanation_to_dict(explanation: Struct) -> Mapping[str, List[List[str]]]: - return {k: [[p for p in path] for path in v] for k, v in explanation.items()} # type: ignore + return {k: [list(path) for path in v] for k, v in explanation.items()} # type: ignore diff --git a/src/aserto/client/identity.py b/src/aserto/client/identity.py index 012e1a7..ae29e11 100644 --- a/src/aserto/client/identity.py +++ b/src/aserto/client/identity.py @@ -6,5 +6,5 @@ @dataclass class Identity: - type: IdentityType + type: IdentityType.ValueType value: Optional[str] = None diff --git a/test/test_directory_v3.py b/test/test_directory_v3.py index 999f433..1c47f1c 100644 --- a/test/test_directory_v3.py +++ b/test/test_directory_v3.py @@ -1,6 +1,5 @@ import datetime -import grpc import pytest from aserto.client.directory import ConfigError @@ -8,6 +7,7 @@ Directory, ETagMismatchError, ExportOption, + InvalidArgumentError, NotFoundError, Object, ObjectIdentifier, @@ -17,8 +17,8 @@ ) -@pytest.fixture(scope="module") -def directory(topaz): +@pytest.fixture(name="directory", scope="module") +def fixture_directory(topaz): client = Directory( address=topaz.directory_grpc.address, ca_cert_path=topaz.directory_grpc.ca_cert_path ) @@ -61,7 +61,7 @@ def test_object_not_found(directory: Directory): def test_object_invalid_arg(directory: Directory): - with pytest.raises(grpc.RpcError, match="object_type: value is required"): + with pytest.raises(InvalidArgumentError, match="invalid argument object identifier: type"): directory.get_object("", "morty@the-citadel") @@ -260,8 +260,8 @@ def test_check_relation(directory: Directory): subject_id="morty@the-citadel.com", ) - assert check_true == True - assert check_false == False + assert check_true is True + assert check_false is False def test_check_permission(directory: Directory): @@ -281,8 +281,8 @@ def test_check_permission(directory: Directory): subject_id="beth@the-smiths.com", ) - assert check_true == True - assert check_false == False + assert check_true is True + assert check_false is False def test_find_objects(directory: Directory): diff --git a/test/test_directory_v3_async.py b/test/test_directory_v3_async.py index eaccef3..5f332d6 100644 --- a/test/test_directory_v3_async.py +++ b/test/test_directory_v3_async.py @@ -9,6 +9,7 @@ Directory, ETagMismatchError, ExportOption, + InvalidArgumentError, NotFoundError, Object, ObjectIdentifier, @@ -18,8 +19,8 @@ ) -@pytest_asyncio.fixture(scope="module") -async def directory(topaz): +@pytest_asyncio.fixture(name="directory", scope="module") +async def fixture_directory(topaz): client = Directory( address=topaz.directory_grpc.address, ca_cert_path=topaz.directory_grpc.ca_cert_path ) @@ -66,7 +67,7 @@ async def test_object_not_found(directory: Directory): @pytest.mark.asyncio(scope="module") async def test_object_invalid_arg(directory: Directory): - with pytest.raises(RpcError, match="object_type: value is required"): + with pytest.raises(InvalidArgumentError, match="invalid argument object identifier: type"): await directory.get_object("", "morty@the-citadel") @@ -282,8 +283,8 @@ async def test_check_relation(directory: Directory): subject_id="morty@the-citadel.com", ) - assert check_true == True - assert check_false == False + assert check_true is True + assert check_false is False @pytest.mark.asyncio(scope="module") @@ -304,8 +305,8 @@ async def test_check_permission(directory: Directory): subject_id="beth@the-smiths.com", ) - assert check_true == True - assert check_false == False + assert check_true is True + assert check_false is False @pytest.mark.asyncio(scope="module")