diff --git a/.github/workflows/kubernetes-e2e-tests.yaml b/.github/workflows/kubernetes-e2e-tests.yaml new file mode 100644 index 00000000000..6937b76c79a --- /dev/null +++ b/.github/workflows/kubernetes-e2e-tests.yaml @@ -0,0 +1,42 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Run Kubernetes e2e tests +on: [pull_request] + +permissions: read-all + +jobs: + build: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v3 + - run: | # Needed for git diff to work. + git fetch origin master --depth 1 + git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master + + - name: Setup python environment + uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 + with: + python-version: 3.11 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'temurin' + + - name: Run Kubernetes e2e tests + run: ./local/tests/kubernetes_e2e_test.bash diff --git a/Pipfile b/Pipfile index 48fa5aac7fa..9e60944bc0b 100644 --- a/Pipfile +++ b/Pipfile @@ -10,6 +10,19 @@ future = "==0.17.1" protobuf = "==4.23.4" psutil = "==5.9.4" google-cloud-ndb = "==2.3.4" +kubernetes = "==34.1.0" +google-api-python-client = "==2.93.0" +aiohttp = "==3.10.5" +google-cloud-storage = "==2.10.0" +google-cloud-secret-manager = "==2.17.0" +google-cloud-logging = "==3.6.0" +google-cloud-monitoring = "==2.15.1" +google-cloud-datastore = "==2.16.1" +oauth2client = "==4.1.3" +requests = "==2.21.0" +PyYAML = "==6.0" +httplib2 = "==0.19.0" +google-auth-oauthlib = "==0.4.1" [dev-packages] Fabric = "==1.14.1" diff --git a/Pipfile.lock b/Pipfile.lock index e10f232ff68..ec94c4187c5 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "f8858cd09afd214bef4a14a6a3f0ad7046dcb715d65cb1a22ae92a62d1cc8c8f" + "sha256": "3da1762ff75a0047d113c0132cf839556d34483541e8a47a3b1461529cc52242" }, "pipfile-spec": 6, "requires": {}, @@ -14,21 +14,142 @@ ] }, "default": { + "aiohappyeyeballs": { + "hashes": [ + "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", + "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8" + ], + "markers": "python_version >= '3.9'", + "version": "==2.6.1" + }, + "aiohttp": { + "hashes": [ + "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277", + "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1", + "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe", + "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb", + "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca", + "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91", + "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972", + "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a", + "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3", + "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa", + "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77", + "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b", + "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8", + "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599", + "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc", + "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf", + "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511", + "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699", + "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487", + "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987", + "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff", + "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db", + "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022", + "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce", + "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a", + "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5", + "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7", + "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820", + "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf", + "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e", + "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf", + "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5", + "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6", + "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6", + "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91", + "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3", + "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a", + "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d", + "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088", + "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc", + "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f", + "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75", + "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471", + "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e", + "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697", + "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092", + "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69", + "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3", + "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32", + "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589", + "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178", + "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92", + "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2", + "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e", + "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058", + "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857", + "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1", + "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6", + "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22", + "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0", + "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b", + "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57", + "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f", + "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e", + "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16", + "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1", + "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f", + "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6", + "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04", + "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae", + "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d", + "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b", + "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f", + "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862", + "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689", + "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c", + "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683", + "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef", + "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f", + "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12", + "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73", + "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061", + "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072", + "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11", + "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691", + "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77", + "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385", + "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172", + "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569", + "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f", + "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5" + ], + "index": "pypi", + "version": "==3.10.5" + }, + "aiosignal": { + "hashes": [ + "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", + "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7" + ], + "markers": "python_version >= '3.9'", + "version": "==1.4.0" + }, + "attrs": { + "hashes": [ + "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", + "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373" + ], + "markers": "python_version >= '3.9'", + "version": "==25.4.0" + }, "cachetools": { "hashes": [ - "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", - "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a" + "sha256:69a7a52634fed8b8bf6e24a050fb60bff1c9bd8f6d24572b99c32d4e71e62a51", + "sha256:82c5c05585e70b6ba2d3ae09ea60b79548872185d2f24ae1f2709d37299fd607" ], - "markers": "python_version >= '3.7'", - "version": "==5.5.2" + "markers": "python_version >= '3.9'", + "version": "==6.2.4" }, "certifi": { "hashes": [ - "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", - "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5" + "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", + "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316" ], "markers": "python_version >= '3.7'", - "version": "==2025.8.3" + "version": "==2025.11.12" }, "cffi": { "hashes": [ @@ -120,90 +241,12 @@ "markers": "python_version >= '3.9'", "version": "==2.0.0" }, - "charset-normalizer": { + "chardet": { "hashes": [ - "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", - "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", - "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", - "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", - "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", - "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", - "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c", - "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", - "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", - "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", - "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432", - "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", - "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", - "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", - "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", - "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19", - "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", - "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", - "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4", - "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7", - "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312", - "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", - "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", - "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", - "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", - "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", - "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b", - "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", - "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", - "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", - "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", - "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", - "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", - "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc", - "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", - "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", - "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a", - "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40", - "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", - "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", - "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", - "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", - "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", - "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", - "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", - "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", - "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", - "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34", - "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9", - "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", - "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", - "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", - "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b", - "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", - "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942", - "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", - "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", - "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b", - "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", - "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", - "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", - "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", - "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", - "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", - "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", - "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", - "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", - "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", - "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca", - "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", - "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", - "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb", - "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", - "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557", - "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", - "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7", - "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", - "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", - "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9" + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" ], - "markers": "python_version >= '3.7'", - "version": "==3.4.3" + "version": "==3.0.4" }, "crcmod": { "hashes": [ @@ -241,15 +284,156 @@ "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==37.0.4" }, + "durationpy": { + "hashes": [ + "sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba", + "sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286" + ], + "version": "==0.10" + }, + "frozenlist": { + "hashes": [ + "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", + "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", + "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", + "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", + "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", + "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", + "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", + "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", + "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", + "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", + "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", + "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", + "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", + "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", + "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", + "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", + "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3", + "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", + "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087", + "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068", + "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", + "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", + "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", + "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", + "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", + "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", + "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", + "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", + "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", + "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", + "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", + "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", + "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675", + "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", + "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", + "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", + "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", + "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", + "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", + "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", + "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", + "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", + "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", + "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", + "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", + "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", + "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5", + "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", + "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", + "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", + "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", + "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", + "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", + "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", + "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", + "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95", + "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1", + "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", + "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", + "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", + "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", + "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459", + "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a", + "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", + "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", + "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", + "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", + "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", + "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6", + "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", + "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", + "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", + "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", + "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", + "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", + "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", + "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", + "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", + "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178", + "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", + "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", + "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", + "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", + "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", + "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61", + "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca", + "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", + "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", + "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", + "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", + "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", + "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", + "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", + "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103", + "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", + "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda", + "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", + "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", + "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", + "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", + "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", + "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", + "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", + "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", + "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", + "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", + "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", + "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", + "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", + "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", + "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", + "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47", + "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", + "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", + "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", + "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", + "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", + "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", + "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", + "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", + "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", + "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", + "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", + "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", + "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", + "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", + "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", + "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", + "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", + "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd" + ], + "markers": "python_version >= '3.9'", + "version": "==1.8.0" + }, "future": { "hashes": [ "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8" ], "index": "pypi", - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", "version": "==0.17.1" }, "google-api-core": { @@ -257,35 +441,91 @@ "grpc" ], "hashes": [ - "sha256:8a2a56c1fef82987a524371f99f3bd0143702fecc670c72e600c1cda6bf8dbb7", - "sha256:d2aaa0b13c78c61cb3f4282c464c046e45fbd75755683c9c525e6e8f7ed0a5e8" + "sha256:2b405df02d68e68ce0fbc138559e6036559e685159d148ae5861013dc201baf8", + "sha256:4021b0f8ceb77a6fb4de6fde4502cecab45062e66ff4f2895169e0b35bc9466c" ], "markers": "python_version >= '3.7'", - "version": "==2.25.1" + "version": "==2.28.1" + }, + "google-api-python-client": { + "hashes": [ + "sha256:62ee28e96031a10a1c341f226a75ac6a4f16bdb1d888dc8222b2cdca133d0031", + "sha256:f34abb671afd488bd19d30721ea20fb30d3796ddd825d6f91f26d8c718a9f07d" + ], + "index": "pypi", + "version": "==2.93.0" }, "google-auth": { "hashes": [ - "sha256:1370d4593e86213563547f97a92752fc658456fe4514c809544f330fed45a7ca", - "sha256:500c3a29adedeb36ea9cf24b8d10858e152f2412e3ca37829b3fa18e33d63b77" + "sha256:82344e86dc00410ef5382d99be677c6043d72e502b625aa4f4afa0bdacca0f36", + "sha256:90d3f41b6b72ea72dd9811e765699ee491ab24139f34ebf1ca2b9cc0c38708f3" + ], + "markers": "python_version >= '3.7'", + "version": "==2.45.0" + }, + "google-auth-httplib2": { + "hashes": [ + "sha256:177898a0175252480d5ed916aeea183c2df87c1f9c26705d74ae6b951c268b0b", + "sha256:426167e5df066e3f5a0fc7ea18768c08e7296046594ce4c8c409c2457dd1f776" ], "markers": "python_version >= '3.7'", - "version": "==2.40.3" + "version": "==0.3.0" + }, + "google-auth-oauthlib": { + "hashes": [ + "sha256:88d2cd115e3391eb85e1243ac6902e76e77c5fe438b7276b297fbe68015458dd", + "sha256:a92a0f6f41a0fb6138454fbc02674e64f89d82a244ea32f98471733c8ef0e0e1" + ], + "index": "pypi", + "version": "==0.4.1" + }, + "google-cloud-appengine-logging": { + "hashes": [ + "sha256:cfd28bc61a030008381a646d112ebe2734bf72abc8c12afc47d035a2c9b041fe", + "sha256:ea9ce73430cfc99f8957fd7df97733f9a759d4caab65e19d63a7474f012ffd94" + ], + "markers": "python_version >= '3.7'", + "version": "==1.7.0" + }, + "google-cloud-audit-log": { + "hashes": [ + "sha256:6b88e2349df45f8f4cc0993b687109b1388da1571c502dc1417efa4b66ec55e0", + "sha256:8467d4dcca9f3e6160520c24d71592e49e874838f174762272ec10e7950b6feb" + ], + "markers": "python_version >= '3.7'", + "version": "==0.4.0" }, "google-cloud-core": { "hashes": [ - "sha256:1fab62d7102844b278fe6dead3af32408b1df3eb06f5c7e8634cbd40edc4da53", - "sha256:5130f9f4c14b4fafdff75c79448f9495cfade0d8775facf1b09c3bf67e027f6e" + "sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc", + "sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963" ], "markers": "python_version >= '3.7'", - "version": "==2.4.3" + "version": "==2.5.0" }, "google-cloud-datastore": { "hashes": [ - "sha256:eee454dd4a55f5b327f9f344928ff1a09a6f77c23d5e3d908ad31a13cc2f4073", - "sha256:f303f27cd1983383f20bd227019cd8a7897419e0ec6b878367c58c66245f9d9b" + "sha256:153d8dac05f0248d7f7d6f0986a31f8fb22d3cdfb764718eac0f28e3cadc8144", + "sha256:710ef27ebdfb50340f4671c532ad4c1525665985e9421984ffcd6b96b57e34bb" ], - "markers": "python_version >= '3.7'", - "version": "==2.21.0" + "index": "pypi", + "version": "==2.16.1" + }, + "google-cloud-logging": { + "hashes": [ + "sha256:42134223956850ddd64877c88042d31f78658e7b067a5a8e3dd28236b71f3c32", + "sha256:6beb843cb88a9bc2f6df94ce69048243ebb360ee06979f5311ea7a0ec09bd097" + ], + "index": "pypi", + "version": "==3.6.0" + }, + "google-cloud-monitoring": { + "hashes": [ + "sha256:086a845a34a6e105ab8a3a4809392ea6367a65b28b7561c26101534a8705ed37", + "sha256:4394e5e031f30d622a24739678ec48a45400ead94af9a6032cbff7f66194dc12" + ], + "index": "pypi", + "version": "==2.15.1" }, "google-cloud-ndb": { "hashes": [ @@ -293,73 +533,153 @@ "sha256:c2cdc38b22fa2d3f6984db6368b9be11902235ef46e2252a17f8083fe3176160" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==2.3.4" }, + "google-cloud-secret-manager": { + "hashes": [ + "sha256:2bf58be569710773f0757d7a788e2860767aa1c148a5255e53b228da3fbcf446", + "sha256:8254e2960c06a8dc91aeac3c894afba0893a674582f0e0ecfc22f894e6173c2f" + ], + "index": "pypi", + "version": "==2.17.0" + }, + "google-cloud-storage": { + "hashes": [ + "sha256:934b31ead5f3994e5360f9ff5750982c5b6b11604dc072bc452c25965e076dc7", + "sha256:9433cf28801671de1c80434238fb1e7e4a1ba3087470e90f70c928ea77c2b9d7" + ], + "index": "pypi", + "version": "==2.10.0" + }, + "google-crc32c": { + "hashes": [ + "sha256:014a7e68d623e9a4222d663931febc3033c5c7c9730785727de2a81f87d5bab8", + "sha256:01f126a5cfddc378290de52095e2c7052be2ba7656a9f0caf4bcd1bfb1833f8a", + "sha256:0470b8c3d73b5f4e3300165498e4cf25221c7eb37f1159e221d1825b6df8a7ff", + "sha256:119fcd90c57c89f30040b47c211acee231b25a45d225e3225294386f5d258288", + "sha256:14f87e04d613dfa218d6135e81b78272c3b904e2a7053b841481b38a7d901411", + "sha256:17446feb05abddc187e5441a45971b8394ea4c1b6efd88ab0af393fd9e0a156a", + "sha256:19b40d637a54cb71e0829179f6cb41835f0fbd9e8eb60552152a8b52c36cbe15", + "sha256:2a3dc3318507de089c5384cc74d54318401410f82aa65b2d9cdde9d297aca7cb", + "sha256:3b9776774b24ba76831609ffbabce8cdf6fa2bd5e9df37b594221c7e333a81fa", + "sha256:3cc0c8912038065eafa603b238abf252e204accab2a704c63b9e14837a854962", + "sha256:3d488e98b18809f5e322978d4506373599c0c13e6c5ad13e53bb44758e18d215", + "sha256:3ebb04528e83b2634857f43f9bb8ef5b2bbe7f10f140daeb01b58f972d04736b", + "sha256:450dc98429d3e33ed2926fc99ee81001928d63460f8538f21a5d6060912a8e27", + "sha256:4b8286b659c1335172e39563ab0a768b8015e88e08329fa5321f774275fc3113", + "sha256:57a50a9035b75643996fbf224d6661e386c7162d1dfdab9bc4ca790947d1007f", + "sha256:61f58b28e0b21fcb249a8247ad0db2e64114e201e2e9b4200af020f3b6242c9f", + "sha256:6f35aaffc8ccd81ba3162443fabb920e65b1f20ab1952a31b13173a67811467d", + "sha256:71734788a88f551fbd6a97be9668a0020698e07b2bf5b3aa26a36c10cdfb27b2", + "sha256:864abafe7d6e2c4c66395c1eb0fe12dc891879769b52a3d56499612ca93b6092", + "sha256:86cfc00fe45a0ac7359e5214a1704e51a99e757d0272554874f419f79838c5f7", + "sha256:87b0072c4ecc9505cfa16ee734b00cd7721d20a0f595be4d40d3d21b41f65ae2", + "sha256:87fa445064e7db928226b2e6f0d5304ab4cd0339e664a4e9a25029f384d9bb93", + "sha256:89c17d53d75562edfff86679244830599ee0a48efc216200691de8b02ab6b2b8", + "sha256:8b3f68782f3cbd1bce027e48768293072813469af6a61a86f6bb4977a4380f21", + "sha256:a428e25fb7691024de47fecfbff7ff957214da51eddded0da0ae0e0f03a2cf79", + "sha256:b0d1a7afc6e8e4635564ba8aa5c0548e3173e41b6384d7711a9123165f582de2", + "sha256:ba6aba18daf4d36ad4412feede6221414692f44d17e5428bdd81ad3fc1eee5dc", + "sha256:cb5c869c2923d56cb0c8e6bcdd73c009c36ae39b652dbe46a05eb4ef0ad01454", + "sha256:d511b3153e7011a27ab6ee6bb3a5404a55b994dc1a7322c0b87b29606d9790e2", + "sha256:db3fe8eaf0612fc8b20fa21a5f25bd785bc3cd5be69f8f3412b0ac2ffd49e733", + "sha256:e6584b12cb06796d285d09e33f63309a09368b9d806a551d8036a4207ea43697", + "sha256:f4b51844ef67d6cf2e9425983274da75f18b1597bb2c998e1c0a0e8d46f8f651", + "sha256:f639065ea2042d5c034bf258a9f085eaa7af0cd250667c0635a3118e8f92c69c" + ], + "markers": "python_version >= '3.9'", + "version": "==1.8.0" + }, + "google-resumable-media": { + "hashes": [ + "sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582", + "sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae" + ], + "markers": "python_version >= '3.7'", + "version": "==2.8.0" + }, "googleapis-common-protos": { "hashes": [ - "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", - "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8" + "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", + "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5" + ], + "markers": "python_version >= '3.7'", + "version": "==1.72.0" + }, + "grpc-google-iam-v1": { + "hashes": [ + "sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6", + "sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389" ], "markers": "python_version >= '3.7'", - "version": "==1.70.0" + "version": "==0.14.3" }, "grpcio": { "hashes": [ - "sha256:0f87bddd6e27fc776aacf7ebfec367b6d49cad0455123951e4488ea99d9b9b8f", - "sha256:136b53c91ac1d02c8c24201bfdeb56f8b3ac3278668cbb8e0ba49c88069e1bdc", - "sha256:1733969040989f7acc3d94c22f55b4a9501a30f6aaacdbccfaba0a3ffb255ab7", - "sha256:176d60a5168d7948539def20b2a3adcce67d72454d9ae05969a2e73f3a0feee7", - "sha256:1a2b06afe2e50ebfd46247ac3ba60cac523f54ec7792ae9ba6073c12daf26f0a", - "sha256:1bf949792cee20d2078323a9b02bacbbae002b9e3b9e2433f2741c15bdeba1c4", - "sha256:22b834cef33429ca6cc28303c9c327ba9a3fafecbf62fae17e9a7b7163cc43ac", - "sha256:2918948864fec2a11721d91568effffbe0a02b23ecd57f281391d986847982f6", - "sha256:2bc2d7d8d184e2362b53905cb1708c84cb16354771c04b490485fa07ce3a1d89", - "sha256:2f609a39f62a6f6f05c7512746798282546358a37ea93c1fcbadf8b2fed162e3", - "sha256:3601274bc0523f6dc07666c0e01682c94472402ac2fd1226fd96e079863bfa49", - "sha256:3b03d8f2a07f0fea8c8f74deb59f8352b770e3900d143b3d1475effcb08eec20", - "sha256:3d14e3c4d65e19d8430a4e28ceb71ace4728776fd6c3ce34016947474479683f", - "sha256:42f8fee287427b94be63d916c90399ed310ed10aadbf9e2e5538b3e497d269bc", - "sha256:4bc5fca10aaf74779081e16c2bcc3d5ec643ffd528d9e7b1c9039000ead73bae", - "sha256:4e4181bfc24413d1e3a37a0b7889bea68d973d4b45dd2bc68bb766c140718f82", - "sha256:55b453812fa7c7ce2f5c88be3018fb4a490519b6ce80788d5913f3f9d7da8c7b", - "sha256:566b9395b90cc3d0d0c6404bc8572c7c18786ede549cdb540ae27b58afe0fb91", - "sha256:5f251c355167b2360537cf17bea2cf0197995e551ab9da6a0a59b3da5e8704f9", - "sha256:60d2d48b0580e70d2e1954d0d19fa3c2e60dd7cbed826aca104fff518310d1c5", - "sha256:64229c1e9cea079420527fa8ac45d80fc1e8d3f94deaa35643c381fa8d98f362", - "sha256:655726919b75ab3c34cdad39da5c530ac6fa32696fb23119e36b64adcfca174a", - "sha256:662456c4513e298db6d7bd9c3b8df6f75f8752f0ba01fb653e252ed4a59b5a5d", - "sha256:68c8ebcca945efff9d86d8d6d7bfb0841cf0071024417e2d7f45c5e46b5b08eb", - "sha256:69e1a8180868a2576f02356565f16635b99088da7df3d45aaa7e24e73a054e31", - "sha256:6bab67d15ad617aff094c382c882e0177637da73cbc5532d52c07b4ee887a87b", - "sha256:7d95d71ff35291bab3f1c52f52f474c632db26ea12700c2ff0ea0532cb0b5854", - "sha256:80d1f4fbb35b0742d3e3d3bb654b7381cd5f015f8497279a1e9c21ba623e01b1", - "sha256:834988b6c34515545b3edd13e902c1acdd9f2465d386ea5143fb558f153a7176", - "sha256:8533e6e9c5bd630ca98062e3a1326249e6ada07d05acf191a77bc33f8948f3d8", - "sha256:85bd5cdf4ed7b2d6438871adf6afff9af7096486fcf51818a81b77ef4dd30907", - "sha256:86ad489db097141a907c559988c29718719aa3e13370d40e20506f11b4de0d11", - "sha256:885912559974df35d92219e2dc98f51a16a48395f37b92865ad45186f294096c", - "sha256:8efe72fde5500f47aca1ef59495cb59c885afe04ac89dd11d810f2de87d935d4", - "sha256:8f7b5882fb50632ab1e48cb3122d6df55b9afabc265582808036b6e51b9fd6b7", - "sha256:9e7c4389771855a92934b2846bd807fc25a3dfa820fd912fe6bd8136026b2707", - "sha256:9e912d3c993a29df6c627459af58975b2e5c897d93287939b9d5065f000249b5", - "sha256:a8f0302f9ac4e9923f98d8e243939a6fb627cd048f5cd38595c97e38020dffce", - "sha256:b6a73b2ba83e663b2480a90b82fdae6a7aa6427f62bf43b29912c0cfd1aa2bfa", - "sha256:c14e803037e572c177ba54a3e090d6eb12efd795d49327c5ee2b3bddb836bf01", - "sha256:c3d7bd6e3929fd2ea7fbc3f562e4987229ead70c9ae5f01501a46701e08f1ad9", - "sha256:c98e0b7434a7fa4e3e63f250456eaef52499fba5ae661c58cc5b5477d11e7182", - "sha256:cce634b10aeab37010449124814b05a62fb5f18928ca878f1bf4750d1f0c815b", - "sha256:e154d230dc1bbbd78ad2fdc3039fa50ad7ffcf438e4eb2fa30bce223a70c7486", - "sha256:e1ea6176d7dfd5b941ea01c2ec34de9531ba494d541fe2057c904e601879f249", - "sha256:e759f9e8bc908aaae0412642afe5416c9f983a80499448fcc7fab8692ae044c3", - "sha256:e8978003816c7b9eabe217f88c78bc26adc8f9304bf6a594b02e5a49b2ef9c11", - "sha256:ecde9ab49f58433abe02f9ed076c7b5be839cf0153883a6d23995937a82392fa", - "sha256:f6ec94f0e50eb8fa1744a731088b966427575e40c2944a980049798b127a687e", - "sha256:fd3c71aeee838299c5887230b8a1822795325ddfea635edd82954c1eaa831e24", - "sha256:fe0f540750a13fd8e5da4b3eaba91a785eea8dca5ccd2bc2ffe978caa403090e" + "sha256:035d90bc79eaa4bed83f524331d55e35820725c9fbb00ffa1904d5550ed7ede3", + "sha256:04bbe1bfe3a68bbfd4e52402ab7d4eb59d72d02647ae2042204326cf4bbad280", + "sha256:063065249d9e7e0782d03d2bca50787f53bd0fb89a67de9a7b521c4a01f1989b", + "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd", + "sha256:08caea849a9d3c71a542827d6df9d5a69067b0a1efbea8a855633ff5d9571465", + "sha256:0aaa82d0813fd4c8e589fac9b65d7dd88702555f702fb10417f96e2a2a6d4c0f", + "sha256:0b7604868b38c1bfd5cf72d768aedd7db41d78cb6a4a18585e33fb0f9f2363fd", + "sha256:0c37db8606c258e2ee0c56b78c62fc9dee0e901b5dbdcf816c2dd4ad652b8b0c", + "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc", + "sha256:2107b0c024d1b35f4083f11245c0e23846ae64d02f40b2b226684840260ed054", + "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba", + "sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03", + "sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2", + "sha256:2e1743fbd7f5fa713a1b0a8ac8ebabf0ec980b5d8809ec358d488e273b9cf02a", + "sha256:32483fe2aab2c3794101c2a159070584e5db11d0aa091b2c0ea9c4fc43d0d749", + "sha256:3bf0f392c0b806905ed174dcd8bdd5e418a40d5567a05615a030a5aeddea692d", + "sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb", + "sha256:40ad3afe81676fd9ec6d9d406eda00933f218038433980aa19d401490e46ecde", + "sha256:4215d3a102bd95e2e11b5395c78562967959824156af11fa93d18fdd18050990", + "sha256:45d59a649a82df5718fd9527ce775fd66d1af35e6d31abdcdc906a49c6822958", + "sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468", + "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc", + "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09", + "sha256:49ce47231818806067aea3324d4bf13825b658ad662d3b25fada0bdad9b8a6af", + "sha256:4baf3cbe2f0be3289eb68ac8ae771156971848bb8aaff60bad42005539431980", + "sha256:522175aba7af9113c48ec10cc471b9b9bd4f6ceb36aeb4544a8e2c80ed9d252d", + "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f", + "sha256:615ba64c208aaceb5ec83bfdce7728b80bfeb8be97562944836a7a0a9647d882", + "sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae", + "sha256:65a20de41e85648e00305c1bb09a3598f840422e522277641145a32d42dcefcc", + "sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77", + "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e", + "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73", + "sha256:81fd9652b37b36f16138611c7e884eb82e0cec137c40d3ef7c3f9b3ed00f6ed8", + "sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3", + "sha256:8843114c0cfce61b40ad48df65abcfc00d4dba82eae8718fab5352390848c5da", + "sha256:8cc3309d8e08fd79089e13ed4819d0af72aa935dd8f435a195fd152796752ff2", + "sha256:8ebe63ee5f8fa4296b1b8cfc743f870d10e902ca18afc65c68cf46fd39bb0783", + "sha256:8eddfb4d203a237da6f3cc8a540dad0517d274b5a1e9e636fd8d2c79b5c1d397", + "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", + "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42", + "sha256:971fd5a1d6e62e00d945423a567e42eb1fa678ba89072832185ca836a94daaa6", + "sha256:980a846182ce88c4f2f7e2c22c56aefd515daeb36149d1c897f83cf57999e0b6", + "sha256:9d9adda641db7207e800a7f089068f6f645959f2df27e870ee81d44701dd9db3", + "sha256:9f8f757bebaaea112c00dba718fc0d3260052ce714e25804a03f93f5d1c6cc11", + "sha256:a6ae758eb08088d36812dd5d9af7a9859c05b1e0f714470ea243694b49278e7b", + "sha256:a8c2cf1209497cf659a667d7dea88985e834c24b7c3b605e6254cbb5076d985c", + "sha256:acab0277c40eff7143c2323190ea57b9ee5fd353d8190ee9652369fae735668a", + "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a", + "sha256:c088e7a90b6017307f423efbb9d1ba97a22aa2170876223f9709e9d1de0b5347", + "sha256:d099566accf23d21037f18a2a63d323075bebace807742e4b0ac210971d4dd70", + "sha256:d388087771c837cdb6515539f43b9d4bf0b0f23593a24054ac16f7a960be16f4", + "sha256:dcfe41187da8992c5f40aa8c5ec086fa3672834d2be57a32384c08d5a05b4c00", + "sha256:e6d1db20594d9daba22f90da738b1a0441a7427552cc6e2e3d1297aeddc00378", + "sha256:ebea5cc3aa8ea72e04df9913492f9a96d9348db876f9dda3ad729cfedf7ac416", + "sha256:ebebf83299b0cb1721a8859ea98f3a77811e35dce7609c5c963b9ad90728f886", + "sha256:f0e34c2079d47ae9f6188211db9e777c619a21d4faba6977774e8fa43b085e48", + "sha256:f92f88e6c033db65a5ae3d97905c8fea9c725b63e28d5a75cb73b49bda5024d8", + "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8", + "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc", + "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62" ], "markers": "python_version >= '3.9'", - "version": "==1.74.0" + "version": "==1.76.0" }, "grpcio-status": { "hashes": [ @@ -369,21 +689,333 @@ "markers": "python_version >= '3.6'", "version": "==1.62.3" }, + "httplib2": { + "hashes": [ + "sha256:749c32603f9bf16c1277f59531d502e8f1c2ca19901ae653b49c4ed698f0820e", + "sha256:e0d428dad43c72dbce7d163b7753ffc7a39c097e6788ef10f4198db69b92f08e" + ], + "index": "pypi", + "version": "==0.19.0" + }, "idna": { "hashes": [ - "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", - "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "markers": "python_version >= '3.6'", - "version": "==3.10" + "markers": "python_version >= '3.8'", + "version": "==2.8" + }, + "kubernetes": { + "hashes": [ + "sha256:8fe8edb0b5d290a2f3ac06596b23f87c658977d46b5f8df9d0f4ea83d0003912", + "sha256:bffba2272534e224e6a7a74d582deb0b545b7c9879d2cd9e4aae9481d1f2cc2a" + ], + "index": "pypi", + "version": "==34.1.0" + }, + "multidict": { + "hashes": [ + "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3", + "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", + "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", + "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", + "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", + "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32", + "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", + "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", + "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36", + "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", + "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff", + "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8", + "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", + "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721", + "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", + "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", + "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", + "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", + "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", + "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", + "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0", + "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", + "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", + "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6", + "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", + "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", + "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", + "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", + "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", + "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", + "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912", + "sha256:363eb68a0a59bd2303216d2346e6c441ba10d36d1f9969fcb6f1ba700de7bb5c", + "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", + "sha256:3996b50c3237c4aec17459217c1e7bbdead9a22a0fcd3c365564fbd16439dde6", + "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2", + "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", + "sha256:3ba3ef510467abb0667421a286dc906e30eb08569365f5cdb131d7aff7c2dd84", + "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", + "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", + "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", + "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd", + "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", + "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", + "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62", + "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", + "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", + "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0", + "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e", + "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6", + "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc", + "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc", + "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", + "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7", + "sha256:521f33e377ff64b96c4c556b81c55d0cfffb96a11c194fd0c3f1e56f3d8dd5a4", + "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", + "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", + "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", + "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111", + "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e", + "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84", + "sha256:68af405971779d8b37198726f2b6fe3955db846fee42db7a4286fc542203934c", + "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", + "sha256:6bdce131e14b04fd34a809b6380dbfd826065c3e2fe8a50dbae659fa0c390546", + "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", + "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", + "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", + "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", + "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", + "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", + "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", + "sha256:7e73299c99939f089dd9b2120a04a516b95cdf8c1cd2b18c53ebf0de80b1f18f", + "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", + "sha256:7f5170993a0dd3ab871c74f45c0a21a4e2c37a2f2b01b5f722a2ad9c6650469e", + "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", + "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", + "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", + "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", + "sha256:8b55d5497b51afdfde55925e04a022f1de14d4f4f25cdfd4f5d9b0aa96166851", + "sha256:8cfc12a8630a29d601f48d47787bd7eb730e475e83edb5d6c5084317463373eb", + "sha256:9281bf5b34f59afbc6b1e477a372e9526b66ca446f4bf62592839c195a718b32", + "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", + "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", + "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81", + "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", + "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", + "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", + "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", + "sha256:9cf41880c991716f3c7cec48e2f19ae4045fc9db5fc9cff27347ada24d710bb5", + "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb", + "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349", + "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", + "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", + "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", + "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", + "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34", + "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c", + "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", + "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", + "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", + "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", + "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff", + "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", + "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85", + "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7", + "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", + "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", + "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", + "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", + "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", + "sha256:b61189b29081a20c7e4e0b49b44d5d44bb0dc92be3c6d06a11cc043f81bf9329", + "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", + "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", + "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", + "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", + "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", + "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", + "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", + "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", + "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", + "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", + "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", + "sha256:ce8fdc2dca699f8dbf055a61d73eaa10482569ad20ee3c36ef9641f69afa8c91", + "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", + "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", + "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", + "sha256:d874eb056410ca05fed180b6642e680373688efafc7f077b2a2f61811e873a40", + "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7", + "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", + "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648", + "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", + "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73", + "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b", + "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", + "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", + "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4", + "sha256:ec81878ddf0e98817def1e77d4f50dae5ef5b0e4fe796fae3bd674304172416e", + "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", + "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046", + "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", + "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9", + "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", + "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", + "sha256:f8e5c0031b90ca9ce555e2e8fd5c3b02a25f14989cbc310701823832c99eb687", + "sha256:fb287618b9c7aa3bf8d825f02d9201b2f13078a5ed3b293c8f4d953917d84d5e", + "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", + "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7" + ], + "markers": "python_version >= '3.9'", + "version": "==6.7.0" + }, + "oauth2client": { + "hashes": [ + "sha256:b8a81cc5d60e2d364f0b1b98f958dbd472887acaf1a5b05e21c28c31a2d6d3ac", + "sha256:d486741e451287f69568a4d26d70d9acd73a2bbfa275746c535b4209891cccc6" + ], + "index": "pypi", + "version": "==4.1.3" + }, + "oauthlib": { + "hashes": [ + "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", + "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1" + ], + "markers": "python_version >= '3.8'", + "version": "==3.3.1" + }, + "propcache": { + "hashes": [ + "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e", + "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", + "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", + "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", + "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", + "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", + "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", + "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", + "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", + "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888", + "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", + "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", + "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", + "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", + "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", + "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", + "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", + "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", + "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", + "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb", + "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", + "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", + "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", + "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff", + "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", + "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", + "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", + "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", + "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", + "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", + "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", + "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc", + "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", + "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", + "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", + "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", + "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", + "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", + "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", + "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", + "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", + "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", + "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", + "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", + "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938", + "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", + "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", + "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", + "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", + "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", + "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", + "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", + "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", + "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0", + "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", + "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", + "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", + "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", + "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", + "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", + "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", + "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", + "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", + "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", + "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f", + "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", + "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", + "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183", + "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", + "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", + "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", + "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", + "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", + "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19", + "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", + "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", + "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", + "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", + "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", + "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", + "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", + "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", + "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", + "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", + "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", + "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", + "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", + "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", + "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", + "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", + "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", + "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac", + "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", + "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", + "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", + "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", + "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", + "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", + "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00", + "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a", + "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", + "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", + "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", + "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", + "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", + "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", + "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", + "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", + "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", + "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", + "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", + "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", + "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", + "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", + "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", + "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", + "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", + "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", + "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", + "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88", + "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", + "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.1" }, "proto-plus": { "hashes": [ - "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", - "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012" + "sha256:1baa7f81cf0f8acb8bc1f6d085008ba4171eaf669629d1b6d1673b21ed1c0a82", + "sha256:873af56dd0d7e91836aee871e5799e1c6f1bda86ac9a983e0bb9f0c266a568c4" ], "markers": "python_version >= '3.7'", - "version": "==1.26.1" + "version": "==1.27.0" }, "protobuf": { "hashes": [ @@ -402,7 +1034,6 @@ "sha256:fee88269a090ada09ca63551bf2f573eb2424035bcf2cb1b121895b01a46594a" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==4.23.4" }, "psutil": { @@ -423,7 +1054,6 @@ "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==5.9.4" }, "pyasn1": { @@ -447,7 +1077,7 @@ "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934" ], - "markers": "python_version >= '3.8'", + "markers": "implementation_name != 'PyPy'", "version": "==2.23" }, "pymemcache": { @@ -458,6 +1088,22 @@ "markers": "python_version >= '3.7'", "version": "==4.0.0" }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "python-dateutil": { + "hashes": [ + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.0.post0" + }, "pytz": { "hashes": [ "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", @@ -465,6 +1111,52 @@ ], "version": "==2025.2" }, + "pyyaml": { + "hashes": [ + "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", + "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", + "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", + "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", + "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", + "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", + "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", + "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", + "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", + "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", + "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", + "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", + "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", + "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", + "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", + "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", + "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", + "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", + "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", + "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", + "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", + "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", + "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", + "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", + "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", + "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", + "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", + "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", + "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", + "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", + "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", + "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", + "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", + "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + ], + "index": "pypi", + "version": "==6.0" + }, "redis": { "hashes": [ "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010", @@ -475,11 +1167,19 @@ }, "requests": { "hashes": [ - "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", - "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf" + "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", + "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" ], - "markers": "python_version >= '3.9'", - "version": "==2.32.5" + "index": "pypi", + "version": "==2.21.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", + "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9" + ], + "markers": "python_version >= '3.4'", + "version": "==2.0.0" }, "rsa": { "hashes": [ @@ -489,13 +1189,181 @@ "markers": "python_version >= '3.6' and python_version < '4'", "version": "==4.9.1" }, + "six": { + "hashes": [ + "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", + "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.17.0" + }, + "typing-extensions": { + "hashes": [ + "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", + "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" + ], + "markers": "python_version < '3.13'", + "version": "==4.15.0" + }, + "uritemplate": { + "hashes": [ + "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e", + "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686" + ], + "markers": "python_version >= '3.9'", + "version": "==4.2.0" + }, "urllib3": { "hashes": [ - "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", - "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" + "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4", + "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", + "version": "==1.24.3" + }, + "websocket-client": { + "hashes": [ + "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", + "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" ], "markers": "python_version >= '3.9'", - "version": "==2.5.0" + "version": "==1.9.0" + }, + "yarl": { + "hashes": [ + "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", + "sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8", + "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", + "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", + "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", + "sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890", + "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", + "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", + "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", + "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", + "sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed", + "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", + "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", + "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", + "sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b", + "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", + "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", + "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", + "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", + "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", + "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", + "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", + "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", + "sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba", + "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", + "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", + "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", + "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", + "sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748", + "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", + "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", + "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", + "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", + "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", + "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", + "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", + "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", + "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", + "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", + "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", + "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", + "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", + "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", + "sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b", + "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", + "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", + "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", + "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", + "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", + "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", + "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", + "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", + "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", + "sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba", + "sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9", + "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", + "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", + "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", + "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", + "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", + "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", + "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", + "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", + "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", + "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", + "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", + "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", + "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", + "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", + "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", + "sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca", + "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", + "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", + "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", + "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", + "sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60", + "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", + "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", + "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", + "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", + "sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e", + "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", + "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", + "sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859", + "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", + "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", + "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", + "sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054", + "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", + "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", + "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", + "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", + "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", + "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", + "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", + "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", + "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", + "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", + "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", + "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", + "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", + "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", + "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", + "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", + "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", + "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", + "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", + "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", + "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", + "sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2", + "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", + "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", + "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", + "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", + "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", + "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", + "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", + "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", + "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", + "sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b", + "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", + "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", + "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", + "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", + "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", + "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", + "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", + "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", + "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", + "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249" + ], + "markers": "python_version >= '3.9'", + "version": "==1.22.0" } }, "develop": { @@ -512,81 +1380,93 @@ "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991" ], - "markers": "python_version >= '3.8'", + "markers": "python_version < '3.12'", "version": "==1.2.0" }, "bcrypt": { "hashes": [ - "sha256:0042b2e342e9ae3d2ed22727c1262f76cc4f345683b5c1715f0250cf4277294f", - "sha256:0142b2cb84a009f8452c8c5a33ace5e3dfec4159e7735f5afe9a4d50a8ea722d", - "sha256:08bacc884fd302b611226c01014eca277d48f0a05187666bca23aac0dad6fe24", - "sha256:0d3efb1157edebfd9128e4e46e2ac1a64e0c1fe46fb023158a407c7892b0f8c3", - "sha256:0e30e5e67aed0187a1764911af023043b4542e70a7461ad20e837e94d23e1d6c", - "sha256:107d53b5c67e0bbc3f03ebf5b030e0403d24dda980f8e244795335ba7b4a027d", - "sha256:12fa6ce40cde3f0b899729dbd7d5e8811cb892d31b6f7d0334a1f37748b789fd", - "sha256:17a854d9a7a476a89dcef6c8bd119ad23e0f82557afbd2c442777a16408e614f", - "sha256:191354ebfe305e84f344c5964c7cd5f924a3bfc5d405c75ad07f232b6dffb49f", - "sha256:2ef6630e0ec01376f59a006dc72918b1bf436c3b571b80fa1968d775fa02fe7d", - "sha256:3004df1b323d10021fda07a813fd33e0fd57bef0e9a480bb143877f6cba996fe", - "sha256:335a420cfd63fc5bc27308e929bee231c15c85cc4c496610ffb17923abf7f231", - "sha256:33752b1ba962ee793fa2b6321404bf20011fe45b9afd2a842139de3011898fef", - "sha256:3a3fd2204178b6d2adcf09cb4f6426ffef54762577a7c9b54c159008cb288c18", - "sha256:3b8d62290ebefd49ee0b3ce7500f5dbdcf13b81402c05f6dafab9a1e1b27212f", - "sha256:3e36506d001e93bffe59754397572f21bb5dc7c83f54454c990c74a468cd589e", - "sha256:41261d64150858eeb5ff43c753c4b216991e0ae16614a308a15d909503617732", - "sha256:50e6e80a4bfd23a25f5c05b90167c19030cf9f87930f7cb2eacb99f45d1c3304", - "sha256:531457e5c839d8caea9b589a1bcfe3756b0547d7814e9ce3d437f17da75c32b0", - "sha256:55a935b8e9a1d2def0626c4269db3fcd26728cbff1e84f0341465c31c4ee56d8", - "sha256:57967b7a28d855313a963aaea51bf6df89f833db4320da458e5b3c5ab6d4c938", - "sha256:584027857bc2843772114717a7490a37f68da563b3620f78a849bcb54dc11e62", - "sha256:59e1aa0e2cd871b08ca146ed08445038f42ff75968c7ae50d2fdd7860ade2180", - "sha256:5bd3cca1f2aa5dbcf39e2aa13dd094ea181f48959e1071265de49cc2b82525af", - "sha256:5c1949bf259a388863ced887c7861da1df681cb2388645766c89fdfd9004c669", - "sha256:62f26585e8b219cdc909b6a0069efc5e4267e25d4a3770a364ac58024f62a761", - "sha256:67a561c4d9fb9465ec866177e7aebcad08fe23aaf6fbd692a6fab69088abfc51", - "sha256:6fb1fd3ab08c0cbc6826a2e0447610c6f09e983a281b919ed721ad32236b8b23", - "sha256:74a8d21a09f5e025a9a23e7c0fd2c7fe8e7503e4d356c0a2c1486ba010619f09", - "sha256:79e70b8342a33b52b55d93b3a59223a844962bef479f6a0ea318ebbcadf71505", - "sha256:7a4be4cbf241afee43f1c3969b9103a41b40bcb3a3f467ab19f891d9bc4642e4", - "sha256:7c03296b85cb87db865d91da79bf63d5609284fc0cab9472fdd8367bbd830753", - "sha256:842d08d75d9fe9fb94b18b071090220697f9f184d4547179b60734846461ed59", - "sha256:864f8f19adbe13b7de11ba15d85d4a428c7e2f344bac110f667676a0ff84924b", - "sha256:97eea7408db3a5bcce4a55d13245ab3fa566e23b4c67cd227062bb49e26c585d", - "sha256:a839320bf27d474e52ef8cb16449bb2ce0ba03ca9f44daba6d93fa1d8828e48a", - "sha256:afe327968aaf13fc143a56a3360cb27d4ad0345e34da12c7290f1b00b8fe9a8b", - "sha256:b4d4e57f0a63fd0b358eb765063ff661328f69a04494427265950c71b992a39a", - "sha256:b6354d3760fcd31994a14c89659dee887f1351a06e5dac3c1142307172a79f90", - "sha256:b693dbb82b3c27a1604a3dff5bfc5418a7e6a781bb795288141e5f80cf3a3492", - "sha256:bdc6a24e754a555d7316fa4774e64c6c3997d27ed2d1964d55920c7c227bc4ce", - "sha256:beeefe437218a65322fbd0069eb437e7c98137e08f22c4660ac2dc795c31f8bb", - "sha256:c5eeac541cefd0bb887a371ef73c62c3cd78535e4887b310626036a7c0a817bb", - "sha256:c950d682f0952bafcceaf709761da0a32a942272fad381081b51096ffa46cea1", - "sha256:d9af79d322e735b1fc33404b5765108ae0ff232d4b54666d46730f8ac1a43676", - "sha256:e53e074b120f2877a35cc6c736b8eb161377caae8925c17688bd46ba56daaa5b", - "sha256:e965a9c1e9a393b8005031ff52583cedc15b7884fce7deb8b0346388837d6cfe", - "sha256:f01e060f14b6b57bbb72fc5b4a83ac21c443c9a2ee708e04a10e9192f90a6281", - "sha256:f1e3ffa1365e8702dc48c8b360fef8d7afeca482809c5e45e653af82ccd088c1", - "sha256:f6746e6fec103fcd509b96bacdfdaa2fbde9a553245dbada284435173a6f1aef", - "sha256:f81b0ed2639568bf14749112298f9e4e2b28853dab50a8b357e31798686a036d" + "sha256:046ad6db88edb3c5ece4369af997938fb1c19d6a699b9c1b27b0db432faae4c4", + "sha256:0c418ca99fd47e9c59a301744d63328f17798b5947b0f791e9af3c1c499c2d0a", + "sha256:0c8e093ea2532601a6f686edbc2c6b2ec24131ff5c52f7610dd64fa4553b5464", + "sha256:0cae4cb350934dfd74c020525eeae0a5f79257e8a201c0c176f4b84fdbf2a4b4", + "sha256:137c5156524328a24b9fac1cb5db0ba618bc97d11970b39184c1d87dc4bf1746", + "sha256:200af71bc25f22006f4069060c88ed36f8aa4ff7f53e67ff04d2ab3f1e79a5b2", + "sha256:212139484ab3207b1f0c00633d3be92fef3c5f0af17cad155679d03ff2ee1e41", + "sha256:2b732e7d388fa22d48920baa267ba5d97cca38070b69c0e2d37087b381c681fd", + "sha256:35a77ec55b541e5e583eb3436ffbbf53b0ffa1fa16ca6782279daf95d146dcd9", + "sha256:38cac74101777a6a7d3b3e3cfefa57089b5ada650dce2baf0cbdd9d65db22a9e", + "sha256:3abeb543874b2c0524ff40c57a4e14e5d3a66ff33fb423529c88f180fd756538", + "sha256:3ca8a166b1140436e058298a34d88032ab62f15aae1c598580333dc21d27ef10", + "sha256:3cf67a804fc66fc217e6914a5635000259fbbbb12e78a99488e4d5ba445a71eb", + "sha256:4870a52610537037adb382444fefd3706d96d663ac44cbb2f37e3919dca3d7ef", + "sha256:48f753100931605686f74e27a7b49238122aa761a9aefe9373265b8b7aa43ea4", + "sha256:4bfd2a34de661f34d0bda43c3e4e79df586e4716ef401fe31ea39d69d581ef23", + "sha256:560ddb6ec730386e7b3b26b8b4c88197aaed924430e7b74666a586ac997249ef", + "sha256:5b1589f4839a0899c146e8892efe320c0fa096568abd9b95593efac50a87cb75", + "sha256:5feebf85a9cefda32966d8171f5db7e3ba964b77fdfe31919622256f80f9cf42", + "sha256:611f0a17aa4a25a69362dcc299fda5c8a3d4f160e2abb3831041feb77393a14a", + "sha256:61afc381250c3182d9078551e3ac3a41da14154fbff647ddf52a769f588c4172", + "sha256:64d7ce196203e468c457c37ec22390f1a61c85c6f0b8160fd752940ccfb3a683", + "sha256:64ee8434b0da054d830fa8e89e1c8bf30061d539044a39524ff7dec90481e5c2", + "sha256:6b8f520b61e8781efee73cba14e3e8c9556ccfb375623f4f97429544734545b4", + "sha256:741449132f64b3524e95cd30e5cd3343006ce146088f074f31ab26b94e6c75ba", + "sha256:744d3c6b164caa658adcb72cb8cc9ad9b4b75c7db507ab4bc2480474a51989da", + "sha256:79cfa161eda8d2ddf29acad370356b47f02387153b11d46042e93a0a95127493", + "sha256:7aeef54b60ceddb6f30ee3db090351ecf0d40ec6e2abf41430997407a46d2254", + "sha256:7edda91d5ab52b15636d9c30da87d2cc84f426c72b9dba7a9b4fe142ba11f534", + "sha256:7f277a4b3390ab4bebe597800a90da0edae882c6196d3038a73adf446c4f969f", + "sha256:7f4c94dec1b5ab5d522750cb059bb9409ea8872d4494fd152b53cca99f1ddd8c", + "sha256:801cad5ccb6b87d1b430f183269b94c24f248dddbbc5c1f78b6ed231743e001c", + "sha256:83e787d7a84dbbfba6f250dd7a5efd689e935f03dd83b0f919d39349e1f23f83", + "sha256:89042e61b5e808b67daf24a434d89bab164d4de1746b37a8d173b6b14f3db9ff", + "sha256:92864f54fb48b4c718fc92a32825d0e42265a627f956bc0361fe869f1adc3e7d", + "sha256:9d52ed507c2488eddd6a95bccee4e808d3234fa78dd370e24bac65a21212b861", + "sha256:9fffdb387abe6aa775af36ef16f55e318dcda4194ddbf82007a6f21da29de8f5", + "sha256:a28bc05039bdf3289d757f49d616ab3efe8cf40d8e8001ccdd621cd4f98f4fc9", + "sha256:a5393eae5722bcef046a990b84dff02b954904c36a194f6cfc817d7dca6c6f0b", + "sha256:a71f70ee269671460b37a449f5ff26982a6f2ba493b3eabdd687b4bf35f875ac", + "sha256:b17366316c654e1ad0306a6858e189fc835eca39f7eb2cafd6aaca8ce0c40a2e", + "sha256:baade0a5657654c2984468efb7d6c110db87ea63ef5a4b54732e7e337253e44f", + "sha256:c2388ca94ffee269b6038d48747f4ce8df0ffbea43f31abfa18ac72f0218effb", + "sha256:c58b56cdfb03202b3bcc9fd8daee8e8e9b6d7e3163aa97c631dfcfcc24d36c86", + "sha256:cde08734f12c6a4e28dc6755cd11d3bdfea608d93d958fffbe95a7026ebe4980", + "sha256:d79e5c65dcc9af213594d6f7f1fa2c98ad3fc10431e7aa53c176b441943efbdd", + "sha256:d8d65b564ec849643d9f7ea05c6d9f0cd7ca23bdd4ac0c2dbef1104ab504543d", + "sha256:db99dca3b1fdc3db87d7c57eac0c82281242d1eabf19dcb8a6b10eb29a2e72d1", + "sha256:dcd58e2b3a908b5ecc9b9df2f0085592506ac2d5110786018ee5e160f28e0911", + "sha256:dd19cf5184a90c873009244586396a6a884d591a5323f0e8a5922560718d4993", + "sha256:ddb4e1500f6efdd402218ffe34d040a1196c072e07929b9820f363a1fd1f4191", + "sha256:e3cf5b2560c7b5a142286f69bde914494b6d8f901aaa71e453078388a50881c4", + "sha256:ed2e1365e31fc73f1825fa830f1c8f8917ca1b3ca6185773b349c20fd606cec2", + "sha256:edfcdcedd0d0f05850c52ba3127b1fce70b9f89e0fe5ff16517df7e81fa3cbb8", + "sha256:f0ce778135f60799d89c9693b9b398819d15f1921ba15fe719acb3178215a7db", + "sha256:f2347d3534e76bf50bca5500989d6c1d05ed64b440408057a37673282c654927", + "sha256:f3c08197f3039bec79cee59a606d62b96b16669cff3949f21e74796b6e3cd2be", + "sha256:f632fd56fc4e61564f78b46a2269153122db34988e78b6be8b32d28507b7eaeb", + "sha256:f6984a24db30548fd39a44360532898c33528b74aedf81c26cf29c51ee47057e", + "sha256:f70aadb7a809305226daedf75d90379c397b094755a710d7014b8b117df1ebbf", + "sha256:f748f7c2d6fd375cc93d3fba7ef4a9e3a092421b8dbf34d8d4dc06be9492dfdd", + "sha256:f8429e1c410b4073944f03bd778a9e066e7fad723564a52ff91841d278dfc822", + "sha256:fc746432b951e92b58317af8e0ca746efe93e66555f1b40888865ef5bf56446b" ], "markers": "python_version >= '3.8'", - "version": "==4.3.0" + "version": "==5.0.0" }, "beautifulsoup4": { "hashes": [ - "sha256:5e70131382930e7c3de33450a2f54a63d5e4b19386eab43a5b34d594268f3695", - "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a" + "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", + "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86" ], - "markers": "python_full_version >= '3.7.0'", - "version": "==4.13.5" + "markers": "python_version >= '3.7'", + "version": "==4.14.3" }, "certifi": { "hashes": [ - "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", - "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5" + "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", + "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316" ], "markers": "python_version >= '3.7'", - "version": "==2025.8.3" + "version": "==2025.11.12" }, "cffi": { "hashes": [ @@ -680,88 +1560,122 @@ }, "charset-normalizer": { "hashes": [ - "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", - "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", - "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", - "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", - "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", - "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", - "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c", - "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", - "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", - "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", - "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432", - "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", - "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", - "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", - "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", - "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19", - "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", - "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", - "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4", - "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7", - "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312", - "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", - "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", - "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", - "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", - "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", - "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b", - "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", - "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", - "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", - "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", - "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", - "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", - "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc", - "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", - "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", - "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a", - "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40", - "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", - "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", - "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", - "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", - "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", - "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", - "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", - "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", - "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", - "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34", - "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9", - "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", - "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", - "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", - "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b", - "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", - "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942", - "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", - "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", - "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b", - "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", - "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", - "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", - "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", - "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", - "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", - "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", - "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", - "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", - "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", - "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca", - "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", - "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", - "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb", - "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", - "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557", - "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", - "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7", - "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", - "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", - "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9" + "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", + "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", + "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", + "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", + "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc", + "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", + "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63", + "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d", + "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", + "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", + "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", + "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505", + "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", + "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af", + "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", + "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318", + "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", + "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", + "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", + "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", + "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576", + "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", + "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1", + "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", + "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1", + "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", + "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", + "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", + "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88", + "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", + "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", + "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", + "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a", + "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", + "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", + "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", + "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", + "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", + "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7", + "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", + "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", + "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", + "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", + "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", + "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", + "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2", + "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", + "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", + "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", + "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", + "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf", + "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6", + "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", + "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", + "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa", + "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", + "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", + "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", + "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", + "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", + "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", + "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", + "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", + "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", + "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", + "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", + "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", + "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", + "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", + "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", + "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3", + "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9", + "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", + "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", + "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", + "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", + "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50", + "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf", + "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", + "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", + "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac", + "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", + "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", + "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c", + "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", + "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", + "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e", + "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4", + "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84", + "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", + "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", + "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", + "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", + "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", + "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", + "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", + "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", + "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", + "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074", + "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3", + "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", + "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", + "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", + "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d", + "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", + "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", + "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", + "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", + "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966", + "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", + "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3", + "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", + "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608" ], "markers": "python_version >= '3.7'", - "version": "==3.4.3" + "version": "==3.4.4" }, "cryptography": { "hashes": [ @@ -789,7 +1703,6 @@ "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==37.0.4" }, "dill": { @@ -797,7 +1710,7 @@ "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049" ], - "markers": "python_version >= '3.8'", + "markers": "python_version >= '3.11'", "version": "==0.4.0" }, "distlib": { @@ -809,11 +1722,11 @@ }, "docutils": { "hashes": [ - "sha256:4ed966a0e96a0477d852f7af31bdcb3adc049fbb35ccba358c2ea8a03287615e", - "sha256:ba9d57750e92331ebe7c08a1bbf7a7f8143b86c476acd51528b042216a6aad0f" + "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", + "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de" ], "markers": "python_version >= '3.9'", - "version": "==0.22" + "version": "==0.22.4" }, "fabric": { "hashes": [ @@ -825,68 +1738,78 @@ }, "filelock": { "hashes": [ - "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", - "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d" + "sha256:15d9e9a67306188a44baa72f569d2bfd803076269365fdea0934385da4dc361a", + "sha256:b8360948b351b80f420878d8516519a2204b07aefcdcfd24912a5d33127f188c" ], - "markers": "python_version >= '3.9'", - "version": "==3.19.1" + "markers": "python_version >= '3.10'", + "version": "==3.20.1" }, "grpcio": { "hashes": [ - "sha256:0f87bddd6e27fc776aacf7ebfec367b6d49cad0455123951e4488ea99d9b9b8f", - "sha256:136b53c91ac1d02c8c24201bfdeb56f8b3ac3278668cbb8e0ba49c88069e1bdc", - "sha256:1733969040989f7acc3d94c22f55b4a9501a30f6aaacdbccfaba0a3ffb255ab7", - "sha256:176d60a5168d7948539def20b2a3adcce67d72454d9ae05969a2e73f3a0feee7", - "sha256:1a2b06afe2e50ebfd46247ac3ba60cac523f54ec7792ae9ba6073c12daf26f0a", - "sha256:1bf949792cee20d2078323a9b02bacbbae002b9e3b9e2433f2741c15bdeba1c4", - "sha256:22b834cef33429ca6cc28303c9c327ba9a3fafecbf62fae17e9a7b7163cc43ac", - "sha256:2918948864fec2a11721d91568effffbe0a02b23ecd57f281391d986847982f6", - "sha256:2bc2d7d8d184e2362b53905cb1708c84cb16354771c04b490485fa07ce3a1d89", - "sha256:2f609a39f62a6f6f05c7512746798282546358a37ea93c1fcbadf8b2fed162e3", - "sha256:3601274bc0523f6dc07666c0e01682c94472402ac2fd1226fd96e079863bfa49", - "sha256:3b03d8f2a07f0fea8c8f74deb59f8352b770e3900d143b3d1475effcb08eec20", - "sha256:3d14e3c4d65e19d8430a4e28ceb71ace4728776fd6c3ce34016947474479683f", - "sha256:42f8fee287427b94be63d916c90399ed310ed10aadbf9e2e5538b3e497d269bc", - "sha256:4bc5fca10aaf74779081e16c2bcc3d5ec643ffd528d9e7b1c9039000ead73bae", - "sha256:4e4181bfc24413d1e3a37a0b7889bea68d973d4b45dd2bc68bb766c140718f82", - "sha256:55b453812fa7c7ce2f5c88be3018fb4a490519b6ce80788d5913f3f9d7da8c7b", - "sha256:566b9395b90cc3d0d0c6404bc8572c7c18786ede549cdb540ae27b58afe0fb91", - "sha256:5f251c355167b2360537cf17bea2cf0197995e551ab9da6a0a59b3da5e8704f9", - "sha256:60d2d48b0580e70d2e1954d0d19fa3c2e60dd7cbed826aca104fff518310d1c5", - "sha256:64229c1e9cea079420527fa8ac45d80fc1e8d3f94deaa35643c381fa8d98f362", - "sha256:655726919b75ab3c34cdad39da5c530ac6fa32696fb23119e36b64adcfca174a", - "sha256:662456c4513e298db6d7bd9c3b8df6f75f8752f0ba01fb653e252ed4a59b5a5d", - "sha256:68c8ebcca945efff9d86d8d6d7bfb0841cf0071024417e2d7f45c5e46b5b08eb", - "sha256:69e1a8180868a2576f02356565f16635b99088da7df3d45aaa7e24e73a054e31", - "sha256:6bab67d15ad617aff094c382c882e0177637da73cbc5532d52c07b4ee887a87b", - "sha256:7d95d71ff35291bab3f1c52f52f474c632db26ea12700c2ff0ea0532cb0b5854", - "sha256:80d1f4fbb35b0742d3e3d3bb654b7381cd5f015f8497279a1e9c21ba623e01b1", - "sha256:834988b6c34515545b3edd13e902c1acdd9f2465d386ea5143fb558f153a7176", - "sha256:8533e6e9c5bd630ca98062e3a1326249e6ada07d05acf191a77bc33f8948f3d8", - "sha256:85bd5cdf4ed7b2d6438871adf6afff9af7096486fcf51818a81b77ef4dd30907", - "sha256:86ad489db097141a907c559988c29718719aa3e13370d40e20506f11b4de0d11", - "sha256:885912559974df35d92219e2dc98f51a16a48395f37b92865ad45186f294096c", - "sha256:8efe72fde5500f47aca1ef59495cb59c885afe04ac89dd11d810f2de87d935d4", - "sha256:8f7b5882fb50632ab1e48cb3122d6df55b9afabc265582808036b6e51b9fd6b7", - "sha256:9e7c4389771855a92934b2846bd807fc25a3dfa820fd912fe6bd8136026b2707", - "sha256:9e912d3c993a29df6c627459af58975b2e5c897d93287939b9d5065f000249b5", - "sha256:a8f0302f9ac4e9923f98d8e243939a6fb627cd048f5cd38595c97e38020dffce", - "sha256:b6a73b2ba83e663b2480a90b82fdae6a7aa6427f62bf43b29912c0cfd1aa2bfa", - "sha256:c14e803037e572c177ba54a3e090d6eb12efd795d49327c5ee2b3bddb836bf01", - "sha256:c3d7bd6e3929fd2ea7fbc3f562e4987229ead70c9ae5f01501a46701e08f1ad9", - "sha256:c98e0b7434a7fa4e3e63f250456eaef52499fba5ae661c58cc5b5477d11e7182", - "sha256:cce634b10aeab37010449124814b05a62fb5f18928ca878f1bf4750d1f0c815b", - "sha256:e154d230dc1bbbd78ad2fdc3039fa50ad7ffcf438e4eb2fa30bce223a70c7486", - "sha256:e1ea6176d7dfd5b941ea01c2ec34de9531ba494d541fe2057c904e601879f249", - "sha256:e759f9e8bc908aaae0412642afe5416c9f983a80499448fcc7fab8692ae044c3", - "sha256:e8978003816c7b9eabe217f88c78bc26adc8f9304bf6a594b02e5a49b2ef9c11", - "sha256:ecde9ab49f58433abe02f9ed076c7b5be839cf0153883a6d23995937a82392fa", - "sha256:f6ec94f0e50eb8fa1744a731088b966427575e40c2944a980049798b127a687e", - "sha256:fd3c71aeee838299c5887230b8a1822795325ddfea635edd82954c1eaa831e24", - "sha256:fe0f540750a13fd8e5da4b3eaba91a785eea8dca5ccd2bc2ffe978caa403090e" + "sha256:035d90bc79eaa4bed83f524331d55e35820725c9fbb00ffa1904d5550ed7ede3", + "sha256:04bbe1bfe3a68bbfd4e52402ab7d4eb59d72d02647ae2042204326cf4bbad280", + "sha256:063065249d9e7e0782d03d2bca50787f53bd0fb89a67de9a7b521c4a01f1989b", + "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd", + "sha256:08caea849a9d3c71a542827d6df9d5a69067b0a1efbea8a855633ff5d9571465", + "sha256:0aaa82d0813fd4c8e589fac9b65d7dd88702555f702fb10417f96e2a2a6d4c0f", + "sha256:0b7604868b38c1bfd5cf72d768aedd7db41d78cb6a4a18585e33fb0f9f2363fd", + "sha256:0c37db8606c258e2ee0c56b78c62fc9dee0e901b5dbdcf816c2dd4ad652b8b0c", + "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc", + "sha256:2107b0c024d1b35f4083f11245c0e23846ae64d02f40b2b226684840260ed054", + "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba", + "sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03", + "sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2", + "sha256:2e1743fbd7f5fa713a1b0a8ac8ebabf0ec980b5d8809ec358d488e273b9cf02a", + "sha256:32483fe2aab2c3794101c2a159070584e5db11d0aa091b2c0ea9c4fc43d0d749", + "sha256:3bf0f392c0b806905ed174dcd8bdd5e418a40d5567a05615a030a5aeddea692d", + "sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb", + "sha256:40ad3afe81676fd9ec6d9d406eda00933f218038433980aa19d401490e46ecde", + "sha256:4215d3a102bd95e2e11b5395c78562967959824156af11fa93d18fdd18050990", + "sha256:45d59a649a82df5718fd9527ce775fd66d1af35e6d31abdcdc906a49c6822958", + "sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468", + "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc", + "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09", + "sha256:49ce47231818806067aea3324d4bf13825b658ad662d3b25fada0bdad9b8a6af", + "sha256:4baf3cbe2f0be3289eb68ac8ae771156971848bb8aaff60bad42005539431980", + "sha256:522175aba7af9113c48ec10cc471b9b9bd4f6ceb36aeb4544a8e2c80ed9d252d", + "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f", + "sha256:615ba64c208aaceb5ec83bfdce7728b80bfeb8be97562944836a7a0a9647d882", + "sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae", + "sha256:65a20de41e85648e00305c1bb09a3598f840422e522277641145a32d42dcefcc", + "sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77", + "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e", + "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73", + "sha256:81fd9652b37b36f16138611c7e884eb82e0cec137c40d3ef7c3f9b3ed00f6ed8", + "sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3", + "sha256:8843114c0cfce61b40ad48df65abcfc00d4dba82eae8718fab5352390848c5da", + "sha256:8cc3309d8e08fd79089e13ed4819d0af72aa935dd8f435a195fd152796752ff2", + "sha256:8ebe63ee5f8fa4296b1b8cfc743f870d10e902ca18afc65c68cf46fd39bb0783", + "sha256:8eddfb4d203a237da6f3cc8a540dad0517d274b5a1e9e636fd8d2c79b5c1d397", + "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", + "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42", + "sha256:971fd5a1d6e62e00d945423a567e42eb1fa678ba89072832185ca836a94daaa6", + "sha256:980a846182ce88c4f2f7e2c22c56aefd515daeb36149d1c897f83cf57999e0b6", + "sha256:9d9adda641db7207e800a7f089068f6f645959f2df27e870ee81d44701dd9db3", + "sha256:9f8f757bebaaea112c00dba718fc0d3260052ce714e25804a03f93f5d1c6cc11", + "sha256:a6ae758eb08088d36812dd5d9af7a9859c05b1e0f714470ea243694b49278e7b", + "sha256:a8c2cf1209497cf659a667d7dea88985e834c24b7c3b605e6254cbb5076d985c", + "sha256:acab0277c40eff7143c2323190ea57b9ee5fd353d8190ee9652369fae735668a", + "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a", + "sha256:c088e7a90b6017307f423efbb9d1ba97a22aa2170876223f9709e9d1de0b5347", + "sha256:d099566accf23d21037f18a2a63d323075bebace807742e4b0ac210971d4dd70", + "sha256:d388087771c837cdb6515539f43b9d4bf0b0f23593a24054ac16f7a960be16f4", + "sha256:dcfe41187da8992c5f40aa8c5ec086fa3672834d2be57a32384c08d5a05b4c00", + "sha256:e6d1db20594d9daba22f90da738b1a0441a7427552cc6e2e3d1297aeddc00378", + "sha256:ebea5cc3aa8ea72e04df9913492f9a96d9348db876f9dda3ad729cfedf7ac416", + "sha256:ebebf83299b0cb1721a8859ea98f3a77811e35dce7609c5c963b9ad90728f886", + "sha256:f0e34c2079d47ae9f6188211db9e777c619a21d4faba6977774e8fa43b085e48", + "sha256:f92f88e6c033db65a5ae3d97905c8fea9c725b63e28d5a75cb73b49bda5024d8", + "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8", + "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc", + "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62" ], "markers": "python_version >= '3.9'", - "version": "==1.74.0" + "version": "==1.76.0" }, "grpcio-tools": { "hashes": [ @@ -946,7 +1869,6 @@ "sha256:fa107460c842e4c1a6266150881694fefd4f33baa544ea9489601810c2210ef8" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==1.62.2" }, "gunicorn": { @@ -955,7 +1877,6 @@ "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==23.0.0" }, "id": { @@ -968,19 +1889,19 @@ }, "idna": { "hashes": [ - "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", - "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "markers": "python_version >= '3.6'", - "version": "==3.10" + "markers": "python_version >= '3.8'", + "version": "==2.8" }, "importlib-metadata": { "hashes": [ - "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", - "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd" + "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", + "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151" ], - "markers": "python_version >= '3.9'", - "version": "==8.7.0" + "markers": "python_version < '3.12'", + "version": "==8.7.1" }, "isort": { "hashes": [ @@ -988,7 +1909,6 @@ "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6" ], "index": "pypi", - "markers": "python_full_version >= '3.8.0'", "version": "==5.13.2" }, "jaraco.classes": { @@ -1009,27 +1929,27 @@ }, "jaraco.functools": { "hashes": [ - "sha256:227ff8ed6f7b8f62c56deff101545fa7543cf2c8e7b82a7c2116e672f29c26e8", - "sha256:cfd13ad0dd2c47a3600b439ef72d8615d482cedcff1632930d6f28924d92f294" + "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", + "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb" ], "markers": "python_version >= '3.9'", - "version": "==4.3.0" + "version": "==4.4.0" }, "jeepney": { "hashes": [ "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732" ], - "markers": "python_version >= '3.7'", + "markers": "sys_platform == 'linux'", "version": "==0.9.0" }, "keyring": { "hashes": [ - "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66", - "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd" + "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", + "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b" ], - "markers": "python_version >= '3.9'", - "version": "==25.6.0" + "markers": "platform_machine != 'ppc64le' and platform_machine != 's390x'", + "version": "==25.7.0" }, "lazy-object-proxy": { "hashes": [ @@ -1119,40 +2039,39 @@ "sha256:da33dfde7547ff57e5ba5564126cbfa114f14413b2fa50759b1fa5de1e4ab511" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==3.4.0" }, "nh3": { "hashes": [ - "sha256:0649464ac8eee018644aacbc103874ccbfac80e3035643c3acaab4287e36e7f5", - "sha256:16f8670201f7e8e0e05ed1a590eb84bfa51b01a69dd5caf1d3ea57733de6a52f", - "sha256:1adeb1062a1c2974bc75b8d1ecb014c5fd4daf2df646bbe2831f7c23659793f9", - "sha256:37d3003d98dedca6cd762bf88f2e70b67f05100f6b949ffe540e189cc06887f9", - "sha256:389d93d59b8214d51c400fb5b07866c2a4f79e4e14b071ad66c92184fec3a392", - "sha256:3f1b4f8a264a0c86ea01da0d0c390fe295ea0bcacc52c2103aca286f6884f518", - "sha256:423201bbdf3164a9e09aa01e540adbb94c9962cc177d5b1cbb385f5e1e79216e", - "sha256:634e34e6162e0408e14fb61d5e69dbaea32f59e847cfcfa41b66100a6b796f62", - "sha256:6d68fa277b4a3cf04e5c4b84dd0c6149ff7d56c12b3e3fab304c525b850f613d", - "sha256:7275fdffaab10cc5801bf026e3c089d8de40a997afc9e41b981f7ac48c5aa7d5", - "sha256:7852f038a054e0096dac12b8141191e02e93e0b4608c4b993ec7d4ffafea4e49", - "sha256:7c915060a2c8131bef6a29f78debc29ba40859b6dbe2362ef9e5fd44f11487c2", - "sha256:80fe20171c6da69c7978ecba33b638e951b85fb92059259edd285ff108b82a6d", - "sha256:a537ece1bf513e5a88d8cff8a872e12fe8d0f42ef71dd15a5e7520fecd191bbb", - "sha256:af5aa8127f62bbf03d68f67a956627b1bd0469703a35b3dad28d0c1195e6c7fb", - "sha256:b0612ccf5de8a480cf08f047b08f9d3fecc12e63d2ee91769cb19d7290614c23", - "sha256:ba0caa8aa184196daa6e574d997a33867d6d10234018012d35f86d46024a2a95", - "sha256:bae63772408fd63ad836ec569a7c8f444dd32863d0c67f6e0b25ebbd606afa95", - "sha256:c7a32a7f0d89f7d30cb8f4a84bdbd56d1eb88b78a2434534f62c71dac538c450", - "sha256:ce5e7185599f89b0e391e2f29cc12dc2e206167380cea49b33beda4891be2fe1", - "sha256:d8ba24cb31525492ea71b6aac11a4adac91d828aadeff7c4586541bf5dc34d2f", - "sha256:d97d3efd61404af7e5721a0e74d81cdbfc6e5f97e11e731bb6d090e30a7b62b2", - "sha256:e90883f9f85288f423c77b3f5a6f4486375636f25f793165112679a7b6363b35", - "sha256:e9e6a7e4d38f7e8dda9edd1433af5170c597336c1a74b4693c5cb75ab2b30f2a", - "sha256:ec6cfdd2e0399cb79ba4dcffb2332b94d9696c52272ff9d48a630c5dca5e325a", - "sha256:f416c35efee3e6a6c9ab7716d9e57aa0a49981be915963a82697952cba1353e1" + "sha256:019ecbd007536b67fdf76fab411b648fb64e2257ca3262ec80c3425c24028c80", + "sha256:03d617e5c8aa7331bd2659c654e021caf9bba704b109e7b2b28b039a00949fe5", + "sha256:0dca4365db62b2d71ff1620ee4f800c4729849906c5dd504ee1a7b2389558e31", + "sha256:0fe7ee035dd7b2290715baf29cb27167dddd2ff70ea7d052c958dbd80d323c99", + "sha256:13398e676a14d6233f372c75f52d5ae74f98210172991f7a3142a736bd92b131", + "sha256:169db03df90da63286e0560ea0efa9b6f3b59844a9735514a1d47e6bb2c8c61b", + "sha256:1710f3901cd6440ca92494ba2eb6dc260f829fa8d9196b659fa10de825610ce0", + "sha256:1f9ba555a797dbdcd844b89523f29cdc90973d8bd2e836ea6b962cf567cadd93", + "sha256:2ab70e8c6c7d2ce953d2a58102eefa90c2d0a5ed7aa40c7e29a487bc5e613131", + "sha256:2c9850041b77a9147d6bbd6dbbf13eeec7009eb60b44e83f07fcb2910075bf9b", + "sha256:403c11563e50b915d0efdb622866d1d9e4506bce590ef7da57789bf71dd148b5", + "sha256:45c953e57028c31d473d6b648552d9cab1efe20a42ad139d78e11d8f42a36130", + "sha256:562da3dca7a17f9077593214a9781a94b8d76de4f158f8c895e62f09573945fe", + "sha256:6d66f41672eb4060cf87c037f760bdbc6847852ca9ef8e9c5a5da18f090abf87", + "sha256:7064ccf5ace75825bd7bf57859daaaf16ed28660c1c6b306b649a9eda4b54b1e", + "sha256:72d67c25a84579f4a432c065e8b4274e53b7cf1df8f792cf846abfe2c3090866", + "sha256:7bb18403f02b655a1bbe4e3a4696c2ae1d6ae8f5991f7cacb684b1ae27e6c9f7", + "sha256:91e9b001101fb4500a2aafe3e7c92928d85242d38bf5ac0aba0b7480da0a4cd6", + "sha256:a40202fd58e49129764f025bbaae77028e420f1d5b3c8e6f6fd3a6490d513868", + "sha256:c8745454cdd28bbbc90861b80a0111a195b0e3961b9fa2e672be89eb199fa5d8", + "sha256:cf5964d54edd405e68583114a7cba929468bcd7db5e676ae38ee954de1cfc104", + "sha256:d18957a90806d943d141cc5e4a0fefa1d77cf0d7a156878bf9a66eed52c9cc7d", + "sha256:dce4248edc427c9b79261f3e6e2b3ecbdd9b88c267012168b4a7b3fc6fd41d13", + "sha256:f2f55c4d2d5a207e74eefe4d828067bbb01300e06e2a7436142f915c5928de07", + "sha256:f394759a06df8b685a4ebfb1874fb67a9cbfd58c64fc5ed587a663c0e63ec376", + "sha256:f97f8b25cb2681d25e2338148159447e4d689aafdccfcf19e61ff7db3905768a" ], "markers": "python_version >= '3.8'", - "version": "==0.3.0" + "version": "==0.3.2" }, "nodeenv": { "hashes": [ @@ -1160,7 +2079,6 @@ "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", "version": "==1.9.1" }, "packaging": { @@ -1177,7 +2095,6 @@ "sha256:7fc905272cefa4f364c1a3429cbbe9c0f98b793988efb5bf90aac80f08db09b1" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==0.9.0" }, "paramiko": { @@ -1194,16 +2111,15 @@ "sha256:e9333cdd365aeb9c3f9460ac2d84c4750e3ffa8e766fe3d5de03d4496b55d851" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==2022.8.5" }, "platformdirs": { "hashes": [ - "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", - "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf" + "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", + "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31" ], - "markers": "python_version >= '3.9'", - "version": "==4.4.0" + "markers": "python_version >= '3.10'", + "version": "==4.5.1" }, "protobuf": { "hashes": [ @@ -1222,7 +2138,6 @@ "sha256:fee88269a090ada09ca63551bf2f573eb2424035bcf2cb1b121895b01a46594a" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==4.23.4" }, "pycparser": { @@ -1230,7 +2145,7 @@ "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934" ], - "markers": "python_version >= '3.8'", + "markers": "implementation_name != 'PyPy'", "version": "==2.23" }, "pyfakefs": { @@ -1239,7 +2154,6 @@ "sha256:1ac3b2845dabe69af56c20691b9347914581195ccdde352535fb7d4ff0055c19" ], "index": "pypi", - "markers": "python_version >= '3.5'", "version": "==4.4.0" }, "pygments": { @@ -1256,7 +2170,6 @@ "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad" ], "index": "pypi", - "markers": "python_full_version >= '3.7.2'", "version": "==2.17.7" }, "pylint-protobuf": { @@ -1269,19 +2182,36 @@ }, "pynacl": { "hashes": [ - "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858", - "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d", - "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93", - "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1", - "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92", - "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff", - "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba", - "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394", - "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b", - "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543" + "sha256:262a8de6bba4aee8a66f5edf62c214b06647461c9b6b641f8cd0cb1e3b3196fe", + "sha256:2b12f1b97346f177affcdfdc78875ff42637cb40dcf79484a97dae3448083a78", + "sha256:319de653ef84c4f04e045eb250e6101d23132372b0a61a7acf91bac0fda8e58c", + "sha256:3206fa98737fdc66d59b8782cecc3d37d30aeec4593d1c8c145825a345bba0f0", + "sha256:3384a454adf5d716a9fadcb5eb2e3e72cd49302d1374a60edc531c9957a9b014", + "sha256:3cd787ec1f5c155dc8ecf39b1333cfef41415dc96d392f1ce288b4fe970df489", + "sha256:4ce50d19f1566c391fedc8dc2f2f5be265ae214112ebe55315e41d1f36a7f0a9", + "sha256:53543b4f3d8acb344f75fd4d49f75e6572fce139f4bfb4815a9282296ff9f4c0", + "sha256:543f869140f67d42b9b8d47f922552d7a967e6c116aad028c9bfc5f3f3b3a7b7", + "sha256:5953e8b8cfadb10889a6e7bd0f53041a745d1b3d30111386a1bb37af171e6daf", + "sha256:5a3becafc1ee2e5ea7f9abc642f56b82dcf5be69b961e782a96ea52b55d8a9fc", + "sha256:5f5b35c1a266f8a9ad22525049280a600b19edd1f785bccd01ae838437dcf935", + "sha256:6b35d93ab2df03ecb3aa506be0d3c73609a51449ae0855c2e89c7ed44abde40b", + "sha256:7713f8977b5d25f54a811ec9efa2738ac592e846dd6e8a4d3f7578346a841078", + "sha256:7d7c09749450c385301a3c20dca967a525152ae4608c0a096fe8464bfc3df93d", + "sha256:8d361dac0309f2b6ad33b349a56cd163c98430d409fa503b10b70b3ad66eaa1d", + "sha256:9fd1a4eb03caf8a2fe27b515a998d26923adb9ddb68db78e35ca2875a3830dde", + "sha256:a2bb472458c7ca959aeeff8401b8efef329b0fc44a89d3775cffe8fad3398ad8", + "sha256:a569a4069a7855f963940040f35e87d8bc084cb2d6347428d5ad20550a0a1a21", + "sha256:a6f9fd6d6639b1e81115c7f8ff16b8dedba1e8098d2756275d63d208b0e32021", + "sha256:c2228054f04bf32d558fb89bb99f163a8197d5a9bf4efa13069a7fa8d4b93fc3", + "sha256:d8615ee34d01c8e0ab3f302dcdd7b32e2bcf698ba5f4809e7cc407c8cdea7717", + "sha256:d984c91fe3494793b2a1fb1e91429539c6c28e9ec8209d26d25041ec599ccf63", + "sha256:dece79aecbb8f4640a1adbb81e4aa3bfb0e98e99834884a80eb3f33c7c30e708", + "sha256:e49a3f3d0da9f79c1bec2aa013261ab9fa651c7da045d376bd306cf7c1792993", + "sha256:e735c3a1bdfde3834503baf1a6d74d4a143920281cb724ba29fb84c9f49b9c48", + "sha256:fc734c1696ffd49b40f7c1779c89ba908157c57345cf626be2e0719488a076d3" ], - "markers": "python_version >= '3.6'", - "version": "==1.5.0" + "markers": "python_version >= '3.8'", + "version": "==1.6.1" }, "pyright": { "hashes": [ @@ -1289,68 +2219,53 @@ "sha256:aeeb7ff4e0364775ef416a80111613f91a05c8e01e58ecfefc370ca0db7aed9c" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==1.1.393" }, "pyyaml": { "hashes": [ - "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", - "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", - "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", - "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", - "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", - "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", - "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", - "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", - "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", - "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", - "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", - "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", - "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", - "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", - "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", - "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", - "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", - "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", - "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", - "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", - "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", - "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", - "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", - "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", - "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", - "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", - "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", - "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", - "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", - "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", - "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", - "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", - "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", - "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", - "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", - "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", - "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", - "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", - "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", - "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", - "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", - "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", - "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", - "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", - "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", - "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", - "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", - "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", - "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", - "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", - "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", - "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", - "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" + "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", + "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", + "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", + "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", + "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", + "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", + "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", + "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", + "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", + "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", + "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", + "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", + "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", + "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", + "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", + "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", + "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", + "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", + "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", + "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", + "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", + "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", + "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", + "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", + "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", + "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", + "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", + "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", + "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", + "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", + "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", + "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", + "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", + "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.0.2" + "version": "==6.0" }, "readme-renderer": { "hashes": [ @@ -1362,11 +2277,11 @@ }, "requests": { "hashes": [ - "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", - "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf" + "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", + "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" ], - "markers": "python_version >= '3.9'", - "version": "==2.32.5" + "index": "pypi", + "version": "==2.21.0" }, "requests-toolbelt": { "hashes": [ @@ -1386,19 +2301,19 @@ }, "rich": { "hashes": [ - "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", - "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8" + "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", + "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd" ], - "markers": "python_full_version >= '3.8.0'", - "version": "==14.1.0" + "markers": "python_version >= '3.8'", + "version": "==14.2.0" }, "secretstorage": { "hashes": [ - "sha256:0e3b6265c2c63509fb7415717607e4b2c9ab767b7f344a57473b779ca13bd02e", - "sha256:c46e216d6815aff8a8a18706a2fbfd8d53fcbb0dce99301881687a1b0289ef7c" + "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", + "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be" ], - "markers": "python_version >= '3.10'", - "version": "==3.4.0" + "markers": "sys_platform == 'linux'", + "version": "==3.5.0" }, "selenium": { "hashes": [ @@ -1418,11 +2333,11 @@ }, "soupsieve": { "hashes": [ - "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", - "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f" + "sha256:4cf733bc50fa805f5df4b8ef4740fc0e0fa6218cf3006269afd3f9d6d80fd350", + "sha256:a11fe2a6f3d76ab3cf2de04eb339c1be5b506a8a47f2ceb6d139803177f85434" ], "markers": "python_version >= '3.9'", - "version": "==2.8" + "version": "==2.8.1" }, "tomlkit": { "hashes": [ @@ -1438,40 +2353,39 @@ "sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf" ], "index": "pypi", - "markers": "python_version >= '3.9'", "version": "==6.2.0" }, "types-protobuf": { "hashes": [ - "sha256:5584c39f7e36104b5f8bdfd31815fa1d5b7b3455a79ddddc097b62320f4b1841", - "sha256:faacbbe87bd8cba4472361c0bd86f49296bd36f7761e25d8ada4f64767c1bde9" + "sha256:2641f78f3696822a048cfb8d0ff42ccd85c25f12f871fbebe86da63793692140", + "sha256:c698bb3f020274b1a2798ae09dc773728ce3f75209a35187bd11916ebfde6763" ], "markers": "python_version >= '3.9'", - "version": "==6.30.2.20250822" + "version": "==6.32.1.20251210" }, "typing-extensions": { "hashes": [ "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" ], - "markers": "python_version >= '3.9'", + "markers": "python_version < '3.13'", "version": "==4.15.0" }, "urllib3": { "hashes": [ - "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", - "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" + "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4", + "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb" ], - "markers": "python_version >= '3.9'", - "version": "==2.5.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", + "version": "==1.24.3" }, "virtualenv": { "hashes": [ - "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026", - "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a" + "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", + "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b" ], "markers": "python_version >= '3.8'", - "version": "==20.34.0" + "version": "==20.35.4" }, "virtualenv-clone": { "hashes": [ @@ -1486,7 +2400,7 @@ "sha256:682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f", "sha256:c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e" ], - "markers": "python_full_version >= '3.9.0'", + "markers": "python_version >= '3.9'", "version": "==3.0.2" }, "webob": { @@ -1494,7 +2408,7 @@ "sha256:45e34c58ed0c7e2ecd238ffd34432487ff13d9ad459ddfd77895e67abba7c1f9", "sha256:ad6078e2edb6766d1334ec3dee072ac6a7f95b1e32ce10def8ff7f0f02d56589" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.8.9" }, "webtest": { @@ -1503,7 +2417,6 @@ "sha256:54bd969725838d9861a9fa27f8d971f79d275d94ae255f5c501f53bb6d9929eb" ], "index": "pypi", - "markers": "python_version >= '3.6' and python_version < '4'", "version": "==3.0.0" }, "wrapt": { @@ -1590,7 +2503,7 @@ "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c" ], - "markers": "python_version >= '3.8'", + "markers": "python_version >= '3.11'", "version": "==1.17.3" }, "yapf": { diff --git a/butler.py b/butler.py index 15bc9f0ef8f..43b39f12eb9 100644 --- a/butler.py +++ b/butler.py @@ -436,6 +436,11 @@ def main(): parser_clean_indexes.add_argument( '-c', '--config-dir', required=True, help='Path to application config.') + parser_clean_jobs = subparsers.add_parser( + 'clean_jobs', help='Clean up pending kubernetes jobs.') + parser_clean_jobs.add_argument( + '-c', '--config-dir', required=True, help='Path to application config.') + parser_create_config = subparsers.add_parser( 'create_config', help='Create a new deployment config.') parser_create_config.add_argument( diff --git a/src/clusterfuzz/_internal/batch/kubernetes.py b/local/tests/kubernetes_e2e_test.bash old mode 100644 new mode 100755 similarity index 53% rename from src/clusterfuzz/_internal/batch/kubernetes.py rename to local/tests/kubernetes_e2e_test.bash index 69563d4101d..16a75bdc0a6 --- a/src/clusterfuzz/_internal/batch/kubernetes.py +++ b/local/tests/kubernetes_e2e_test.bash @@ -1,3 +1,5 @@ +#!/bin/bash -ex +# # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -11,17 +13,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Kubernetes batch client.""" -from clusterfuzz._internal.remote_task import RemoteTaskInterface +# This script is for running the Kubernetes end-to-end test in CI. + +pip install pipenv + +# Install dependencies. +pipenv --python 3.11 +pipenv install -class KubernetesJobClient(RemoteTaskInterface): - """A remote task execution client for Kubernetes. - - This class is a placeholder for a future implementation of a remote task - execution client that uses Kubernetes. It is not yet implemented. - """ +./local/install_deps.bash - def create_job(self, spec, input_urls): - """Creates a Kubernetes job.""" - raise NotImplementedError('Kubernetes batch client is not implemented yet.') +# Run the test. +export K8S_E2E=1 +pipenv run python butler.py py_unittest -t core -p k8s_service_e2e_test.py diff --git a/out.log b/out.log new file mode 100644 index 00000000000..eed0ee8a0d1 --- /dev/null +++ b/out.log @@ -0,0 +1,7 @@ +Running in dry-run mode, no datastore writes are committed. For permanent modifications, re-run with --non-dry-run. +Attempting to combine batch tasks. +Combining 2901 batch tasks. +K8s result: ['libfuzzer-chrome-asan-debug-7ca9c46f'] + +Please remember to run the migration individually on all projects. + diff --git a/src/Pipfile b/src/Pipfile index f462d19f732..588e21c2c43 100644 --- a/src/Pipfile +++ b/src/Pipfile @@ -27,6 +27,7 @@ google-crc32c = "==1.5.0" grpcio = "==1.62.2" httplib2 = "==0.19.0" jira = "==2.0.0" +kubernetes = "==34.1.0" mozprocess = "==1.3.1" oauth2client = "==4.1.3" psutil = "==5.9.4" @@ -34,7 +35,7 @@ protobuf = "==4.23.4" pygithub = "==1.55" pyOpenSSL = "==22.0.0" python-dateutil = "==2.8.1" -PyYAML = "==6.0" +PyYAML = "==6.0.1" pytz = "==2023.3" redis = "==4.6.0" requests = "==2.21.0" diff --git a/src/Pipfile.lock b/src/Pipfile.lock index 637b11c3d43..96887dd4e52 100644 --- a/src/Pipfile.lock +++ b/src/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "34863be9ebbc59b6df81493d51760b6aaf0648d8029638fd65cf0915139cb0dd" + "sha256": "9ba77bf5cea77347502d36f893a558c82a5a97de476fec986af0fa5c03f33c04" }, "pipfile-spec": 6, "requires": {}, @@ -117,15 +117,16 @@ "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5" ], "index": "pypi", + "markers": "python_version >= '3.8'", "version": "==3.10.5" }, "aiosignal": { "hashes": [ - "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", - "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54" + "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", + "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7" ], "markers": "python_version >= '3.9'", - "version": "==1.3.2" + "version": "==1.4.0" }, "antlr4-python3-runtime": { "hashes": [ @@ -136,11 +137,11 @@ }, "attrs": { "hashes": [ - "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", - "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" + "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", + "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373" ], - "markers": "python_version >= '3.8'", - "version": "==25.3.0" + "markers": "python_version >= '3.9'", + "version": "==25.4.0" }, "bcrypt": { "hashes": [ @@ -173,6 +174,7 @@ "sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==4.1.2" }, "cachetools": { @@ -189,6 +191,7 @@ "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==2024.2.2" }, "cffi": { @@ -294,6 +297,7 @@ "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==37.0.4" }, "defusedxml": { @@ -306,11 +310,11 @@ }, "deprecated": { "hashes": [ - "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d", - "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec" + "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f", + "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.2.18" + "version": "==1.3.1" }, "distro": { "hashes": [ @@ -320,129 +324,167 @@ "markers": "python_version >= '3.6'", "version": "==1.9.0" }, + "durationpy": { + "hashes": [ + "sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba", + "sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286" + ], + "version": "==0.10" + }, "frozenlist": { "hashes": [ - "sha256:01bcaa305a0fdad12745502bfd16a1c75b14558dabae226852f9159364573117", - "sha256:03572933a1969a6d6ab509d509e5af82ef80d4a5d4e1e9f2e1cdd22c77a3f4d2", - "sha256:0dbae96c225d584f834b8d3cc688825911960f003a85cb0fd20b6e5512468c42", - "sha256:0e6f8653acb82e15e5443dba415fb62a8732b68fe09936bb6d388c725b57f812", - "sha256:0f2ca7810b809ed0f1917293050163c7654cefc57a49f337d5cd9de717b8fad3", - "sha256:118e97556306402e2b010da1ef21ea70cb6d6122e580da64c056b96f524fbd6a", - "sha256:1255d5d64328c5a0d066ecb0f02034d086537925f1f04b50b1ae60d37afbf572", - "sha256:1330f0a4376587face7637dfd245380a57fe21ae8f9d360c1c2ef8746c4195fa", - "sha256:1b8e8cd8032ba266f91136d7105706ad57770f3522eac4a111d77ac126a25a9b", - "sha256:1c6eceb88aaf7221f75be6ab498dc622a151f5f88d536661af3ffc486245a626", - "sha256:1d7fb014fe0fbfee3efd6a94fc635aeaa68e5e1720fe9e57357f2e2c6e1a647e", - "sha256:1db8b2fc7ee8a940b547a14c10e56560ad3ea6499dc6875c354e2335812f739d", - "sha256:2187248203b59625566cac53572ec8c2647a140ee2738b4e36772930377a533c", - "sha256:2b8cf4cfea847d6c12af06091561a89740f1f67f331c3fa8623391905e878530", - "sha256:2bdfe2d7e6c9281c6e55523acd6c2bf77963cb422fdc7d142fb0cb6621b66878", - "sha256:2e8246877afa3f1ae5c979fe85f567d220f86a50dc6c493b9b7d8191181ae01e", - "sha256:36d2fc099229f1e4237f563b2a3e0ff7ccebc3999f729067ce4e64a97a7f2869", - "sha256:37a8a52c3dfff01515e9bbbee0e6063181362f9de3db2ccf9bc96189b557cbfd", - "sha256:3e911391bffdb806001002c1f860787542f45916c3baf764264a52765d5a5603", - "sha256:431ef6937ae0f853143e2ca67d6da76c083e8b1fe3df0e96f3802fd37626e606", - "sha256:437cfd39564744ae32ad5929e55b18ebd88817f9180e4cc05e7d53b75f79ce85", - "sha256:46138f5a0773d064ff663d273b309b696293d7a7c00a0994c5c13a5078134b64", - "sha256:482fe06e9a3fffbcd41950f9d890034b4a54395c60b5e61fae875d37a699813f", - "sha256:49ba23817781e22fcbd45fd9ff2b9b8cdb7b16a42a4851ab8025cae7b22e96d0", - "sha256:4da6fc43048b648275a220e3a61c33b7fff65d11bdd6dcb9d9c145ff708b804c", - "sha256:4def87ef6d90429f777c9d9de3961679abf938cb6b7b63d4a7eb8a268babfce4", - "sha256:4e1be9111cb6756868ac242b3c2bd1f09d9aea09846e4f5c23715e7afb647103", - "sha256:52021b528f1571f98a7d4258c58aa8d4b1a96d4f01d00d51f1089f2e0323cb02", - "sha256:535eec9987adb04701266b92745d6cdcef2e77669299359c3009c3404dd5d191", - "sha256:536a1236065c29980c15c7229fbb830dedf809708c10e159b8136534233545f0", - "sha256:54dece0d21dce4fdb188a1ffc555926adf1d1c516e493c2914d7c370e454bc9e", - "sha256:56a0b8dd6d0d3d971c91f1df75e824986667ccce91e20dca2023683814344791", - "sha256:5c9e89bf19ca148efcc9e3c44fd4c09d5af85c8a7dd3dbd0da1cb83425ef4983", - "sha256:625170a91dd7261a1d1c2a0c1a353c9e55d21cd67d0852185a5fef86587e6f5f", - "sha256:62c828a5b195570eb4b37369fcbbd58e96c905768d53a44d13044355647838ff", - "sha256:62dd7df78e74d924952e2feb7357d826af8d2f307557a779d14ddf94d7311be8", - "sha256:654e4ba1d0b2154ca2f096bed27461cf6160bc7f504a7f9a9ef447c293caf860", - "sha256:69bbd454f0fb23b51cadc9bdba616c9678e4114b6f9fa372d462ff2ed9323ec8", - "sha256:6ac40ec76041c67b928ca8aaffba15c2b2ee3f5ae8d0cb0617b5e63ec119ca25", - "sha256:6ef8e7e8f2f3820c5f175d70fdd199b79e417acf6c72c5d0aa8f63c9f721646f", - "sha256:716bbba09611b4663ecbb7cd022f640759af8259e12a6ca939c0a6acd49eedba", - "sha256:75ecee69073312951244f11b8627e3700ec2bfe07ed24e3a685a5979f0412d24", - "sha256:7613d9977d2ab4a9141dde4a149f4357e4065949674c5649f920fec86ecb393e", - "sha256:777704c1d7655b802c7850255639672e90e81ad6fa42b99ce5ed3fbf45e338dd", - "sha256:77effc978947548b676c54bbd6a08992759ea6f410d4987d69feea9cd0919911", - "sha256:7b0f6cce16306d2e117cf9db71ab3a9e8878a28176aeaf0dbe35248d97b28d0c", - "sha256:7b8c4dc422c1a3ffc550b465090e53b0bf4839047f3e436a34172ac67c45d595", - "sha256:7daa508e75613809c7a57136dec4871a21bca3080b3a8fc347c50b187df4f00c", - "sha256:853ac025092a24bb3bf09ae87f9127de9fe6e0c345614ac92536577cf956dfcc", - "sha256:85ef8d41764c7de0dcdaf64f733a27352248493a85a80661f3c678acd27e31f2", - "sha256:89ffdb799154fd4d7b85c56d5fa9d9ad48946619e0eb95755723fffa11022d75", - "sha256:8b314faa3051a6d45da196a2c495e922f987dc848e967d8cfeaee8a0328b1cd4", - "sha256:8c952f69dd524558694818a461855f35d36cc7f5c0adddce37e962c85d06eac0", - "sha256:8f5fef13136c4e2dee91bfb9a44e236fff78fc2cd9f838eddfc470c3d7d90afe", - "sha256:920b6bd77d209931e4c263223381d63f76828bec574440f29eb497cf3394c249", - "sha256:94bb451c664415f02f07eef4ece976a2c65dcbab9c2f1705b7031a3a75349d8c", - "sha256:95b7a8a3180dfb280eb044fdec562f9b461614c0ef21669aea6f1d3dac6ee576", - "sha256:9799257237d0479736e2b4c01ff26b5c7f7694ac9692a426cb717f3dc02fff9b", - "sha256:9a0318c2068e217a8f5e3b85e35899f5a19e97141a45bb925bb357cfe1daf770", - "sha256:9a79713adfe28830f27a3c62f6b5406c37376c892b05ae070906f07ae4487046", - "sha256:9d124b38b3c299ca68433597ee26b7819209cb8a3a9ea761dfe9db3a04bba584", - "sha256:a2bda8be77660ad4089caf2223fdbd6db1858462c4b85b67fbfa22102021e497", - "sha256:a4d96dc5bcdbd834ec6b0f91027817214216b5b30316494d2b1aebffb87c534f", - "sha256:a66781d7e4cddcbbcfd64de3d41a61d6bdde370fc2e38623f30b2bd539e84a9f", - "sha256:aa733d123cc78245e9bb15f29b44ed9e5780dc6867cfc4e544717b91f980af3b", - "sha256:abc4e880a9b920bc5020bf6a431a6bb40589d9bca3975c980495f63632e8382f", - "sha256:ae8337990e7a45683548ffb2fee1af2f1ed08169284cd829cdd9a7fa7470530d", - "sha256:b11534872256e1666116f6587a1592ef395a98b54476addb5e8d352925cb5d4a", - "sha256:b35298b2db9c2468106278537ee529719228950a5fdda686582f68f247d1dc6e", - "sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68", - "sha256:ba7f8d97152b61f22d7f59491a781ba9b177dd9f318486c5fbc52cde2db12189", - "sha256:bb52c8166499a8150bfd38478248572c924c003cbb45fe3bcd348e5ac7c000f9", - "sha256:c444d824e22da6c9291886d80c7d00c444981a72686e2b59d38b285617cb52c8", - "sha256:c5b9e42ace7d95bf41e19b87cec8f262c41d3510d8ad7514ab3862ea2197bfb1", - "sha256:c6154c3ba59cda3f954c6333025369e42c3acd0c6e8b6ce31eb5c5b8116c07e0", - "sha256:c7c608f833897501dac548585312d73a7dca028bf3b8688f0d712b7acfaf7fb3", - "sha256:ca9973735ce9f770d24d5484dcb42f68f135351c2fc81a7a9369e48cf2998a29", - "sha256:cbb56587a16cf0fb8acd19e90ff9924979ac1431baea8681712716a8337577b0", - "sha256:cdb2c7f071e4026c19a3e32b93a09e59b12000751fc9b0b7758da899e657d215", - "sha256:d108e2d070034f9d57210f22fefd22ea0d04609fc97c5f7f5a686b3471028590", - "sha256:d18689b40cb3936acd971f663ccb8e2589c45db5e2c5f07e0ec6207664029a9c", - "sha256:d1a686d0b0949182b8faddea596f3fc11f44768d1f74d4cad70213b2e139d821", - "sha256:d1eb89bf3454e2132e046f9599fbcf0a4483ed43b40f545551a39316d0201cd1", - "sha256:d3ceb265249fb401702fce3792e6b44c1166b9319737d21495d3611028d95769", - "sha256:da5cb36623f2b846fb25009d9d9215322318ff1c63403075f812b3b2876c8506", - "sha256:da62fecac21a3ee10463d153549d8db87549a5e77eefb8c91ac84bb42bb1e4e3", - "sha256:e18036cb4caa17ea151fd5f3d70be9d354c99eb8cf817a3ccde8a7873b074348", - "sha256:e19c0fc9f4f030fcae43b4cdec9e8ab83ffe30ec10c79a4a43a04d1af6c5e1ad", - "sha256:e1c6bd2c6399920c9622362ce95a7d74e7f9af9bfec05fff91b8ce4b9647845a", - "sha256:e2ada1d8515d3ea5378c018a5f6d14b4994d4036591a52ceaf1a1549dec8e1ad", - "sha256:e4f9373c500dfc02feea39f7a56e4f543e670212102cc2eeb51d3a99c7ffbde6", - "sha256:e67ddb0749ed066b1a03fba812e2dcae791dd50e5da03be50b6a14d0c1a9ee45", - "sha256:e69bb81de06827147b7bfbaeb284d85219fa92d9f097e32cc73675f279d70188", - "sha256:e6e558ea1e47fd6fa8ac9ccdad403e5dd5ecc6ed8dda94343056fa4277d5c65e", - "sha256:ea8e59105d802c5a38bdbe7362822c522230b3faba2aa35c0fa1765239b7dd70", - "sha256:ed5e3a4462ff25ca84fb09e0fada8ea267df98a450340ead4c91b44857267d70", - "sha256:f1a39819a5a3e84304cd286e3dc62a549fe60985415851b3337b6f5cc91907f1", - "sha256:f27a9f9a86dcf00708be82359db8de86b80d029814e6693259befe82bb58a106", - "sha256:f2c7d5aa19714b1b01a0f515d078a629e445e667b9da869a3cd0e6fe7dec78bd", - "sha256:f3a7bb0fe1f7a70fb5c6f497dc32619db7d2cdd53164af30ade2f34673f8b1fc", - "sha256:f4b3cd7334a4bbc0c472164f3744562cb72d05002cc6fcf58adb104630bbc352", - "sha256:f88bc0a2b9c2a835cb888b32246c27cdab5740059fb3688852bf91e915399b91", - "sha256:fb3b309f1d4086b5533cf7bbcf3f956f0ae6469664522f1bde4feed26fba60f1", - "sha256:fc5e64626e6682638d6e44398c9baf1d6ce6bc236d40b4b57255c9d3f9761f1f" + "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", + "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", + "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", + "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", + "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", + "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", + "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", + "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", + "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", + "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", + "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", + "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", + "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", + "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", + "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", + "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", + "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3", + "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", + "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087", + "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068", + "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", + "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", + "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", + "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", + "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", + "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", + "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", + "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", + "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", + "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", + "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", + "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", + "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675", + "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", + "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", + "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", + "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", + "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", + "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", + "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", + "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", + "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", + "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", + "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", + "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", + "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", + "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5", + "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", + "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", + "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", + "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", + "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", + "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", + "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", + "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", + "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95", + "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1", + "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", + "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", + "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", + "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", + "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459", + "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a", + "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", + "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", + "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", + "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", + "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", + "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6", + "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", + "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", + "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", + "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", + "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", + "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", + "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", + "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", + "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", + "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178", + "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", + "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", + "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", + "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", + "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", + "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61", + "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca", + "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", + "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", + "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", + "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", + "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", + "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", + "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", + "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103", + "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", + "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda", + "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", + "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", + "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", + "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", + "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", + "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", + "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", + "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", + "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", + "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", + "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", + "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", + "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", + "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", + "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", + "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47", + "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", + "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", + "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", + "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", + "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", + "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", + "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", + "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", + "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", + "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", + "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", + "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", + "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", + "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", + "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", + "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", + "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", + "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd" ], "markers": "python_version >= '3.9'", - "version": "==1.6.0" + "version": "==1.8.0" }, "future": { "hashes": [ "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8" ], "index": "pypi", + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.17.1" }, "google-api-core": { + "extras": [ + "grpc" + ], "hashes": [ "sha256:25d29e05a0058ed5f19c61c0a78b1b53adea4d9364b464d014fbda941f6d1c9a", "sha256:d92a5a92dc36dd4f4b9ee4e55528a90e432b059f93aee6ad857f9de8cc7ae94a" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.11.1" }, "google-api-python-client": { @@ -451,6 +493,7 @@ "sha256:f34abb671afd488bd19d30721ea20fb30d3796ddd825d6f91f26d8c718a9f07d" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.93.0" }, "google-auth": { @@ -459,14 +502,16 @@ "sha256:d61d1b40897407b574da67da1a833bdc10d5a11642566e506565d1b1a46ba873" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==2.22.0" }, "google-auth-httplib2": { "hashes": [ - "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05", - "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d" + "sha256:177898a0175252480d5ed916aeea183c2df87c1f9c26705d74ae6b951c268b0b", + "sha256:426167e5df066e3f5a0fc7ea18768c08e7296046594ce4c8c409c2457dd1f776" ], - "version": "==0.2.0" + "markers": "python_version >= '3.7'", + "version": "==0.3.0" }, "google-auth-oauthlib": { "hashes": [ @@ -478,19 +523,19 @@ }, "google-cloud-appengine-logging": { "hashes": [ - "sha256:48f4dcf43000899c7b411bc27181f70240e81a958a44e44ce800ba8e5d5184ac", - "sha256:f97bde36c7f7ff541123c2570813158bdda0c3f2385c8d32fdf1211c561ae56d" + "sha256:cfd28bc61a030008381a646d112ebe2734bf72abc8c12afc47d035a2c9b041fe", + "sha256:ea9ce73430cfc99f8957fd7df97733f9a759d4caab65e19d63a7474f012ffd94" ], "markers": "python_version >= '3.7'", - "version": "==1.6.1" + "version": "==1.7.0" }, "google-cloud-audit-log": { "hashes": [ - "sha256:2598f1533a7d7cdd6c7bf448c12e5519c1d53162d78784e10bcdd1df67791bc3", - "sha256:daaedfb947a0d77f524e1bd2b560242ab4836fe1afd6b06b92f152b9658554ed" + "sha256:6b88e2349df45f8f4cc0993b687109b1388da1571c502dc1417efa4b66ec55e0", + "sha256:8467d4dcca9f3e6160520c24d71592e49e874838f174762272ec10e7950b6feb" ], "markers": "python_version >= '3.7'", - "version": "==0.3.2" + "version": "==0.4.0" }, "google-cloud-batch": { "hashes": [ @@ -498,6 +543,7 @@ "sha256:f102a7230dd201236e1e2804d4ca025995bd2141887df8a95a64cc419b33b476" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==0.11.0" }, "google-cloud-core": { @@ -506,6 +552,7 @@ "sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.3.3" }, "google-cloud-datastore": { @@ -514,6 +561,7 @@ "sha256:710ef27ebdfb50340f4671c532ad4c1525665985e9421984ffcd6b96b57e34bb" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.16.1" }, "google-cloud-logging": { @@ -522,6 +570,7 @@ "sha256:6beb843cb88a9bc2f6df94ce69048243ebb360ee06979f5311ea7a0ec09bd097" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==3.6.0" }, "google-cloud-monitoring": { @@ -530,6 +579,7 @@ "sha256:4394e5e031f30d622a24739678ec48a45400ead94af9a6032cbff7f66194dc12" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.15.1" }, "google-cloud-ndb": { @@ -538,6 +588,7 @@ "sha256:e849b48c984f31616e99e1fcc797d1deb1d883a6f38f58f77768b814fb84b57e" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.2.1" }, "google-cloud-profiler": { @@ -553,6 +604,7 @@ "sha256:8254e2960c06a8dc91aeac3c894afba0893a674582f0e0ecfc22f894e6173c2f" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.17.0" }, "google-cloud-storage": { @@ -561,6 +613,7 @@ "sha256:9433cf28801671de1c80434238fb1e7e4a1ba3087470e90f70c928ea77c2b9d7" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.10.0" }, "google-crc32c": { @@ -635,31 +688,35 @@ "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==1.5.0" }, "google-resumable-media": { "hashes": [ - "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa", - "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0" + "sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582", + "sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae" ], "markers": "python_version >= '3.7'", - "version": "==2.7.2" + "version": "==2.8.0" }, "googleapis-common-protos": { + "extras": [ + "grpc" + ], "hashes": [ - "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", - "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8" + "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", + "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5" ], "markers": "python_version >= '3.7'", - "version": "==1.70.0" + "version": "==1.72.0" }, "grpc-google-iam-v1": { "hashes": [ - "sha256:a3171468459770907926d56a440b2bb643eec1d7ba215f48f3ecece42b4d8351", - "sha256:b3e1fc387a1a329e41672197d0ace9de22c78dd7d215048c4c78712073f7bd20" + "sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6", + "sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389" ], "markers": "python_version >= '3.7'", - "version": "==0.14.2" + "version": "==0.14.3" }, "grpcio": { "hashes": [ @@ -719,6 +776,7 @@ "sha256:fa63245271920786f4cb44dcada4983a3516be8f470924528cf658731864c14b" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==1.62.2" }, "grpcio-status": { @@ -751,6 +809,15 @@ "index": "pypi", "version": "==2.0.0" }, + "kubernetes": { + "hashes": [ + "sha256:8fe8edb0b5d290a2f3ac06596b23f87c658977d46b5f8df9d0f4ea83d0003912", + "sha256:bffba2272534e224e6a7a74d582deb0b545b7c9879d2cd9e4aae9481d1f2cc2a" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==34.1.0" + }, "mozfile": { "hashes": [ "sha256:3b0afcda2fa8b802ef657df80a56f21619008f61fcc14b756124028d7b7adf5c", @@ -775,113 +842,155 @@ }, "multidict": { "hashes": [ - "sha256:032efeab3049e37eef2ff91271884303becc9e54d740b492a93b7e7266e23756", - "sha256:062428944a8dc69df9fdc5d5fc6279421e5f9c75a9ee3f586f274ba7b05ab3c8", - "sha256:0bb8f8302fbc7122033df959e25777b0b7659b1fd6bcb9cb6bed76b5de67afef", - "sha256:0d4b31f8a68dccbcd2c0ea04f0e014f1defc6b78f0eb8b35f2265e8716a6df0c", - "sha256:0ecdc12ea44bab2807d6b4a7e5eef25109ab1c82a8240d86d3c1fc9f3b72efd5", - "sha256:0ee1bf613c448997f73fc4efb4ecebebb1c02268028dd4f11f011f02300cf1e8", - "sha256:11990b5c757d956cd1db7cb140be50a63216af32cd6506329c2c59d732d802db", - "sha256:1535cec6443bfd80d028052e9d17ba6ff8a5a3534c51d285ba56c18af97e9713", - "sha256:1748cb2743bedc339d63eb1bca314061568793acd603a6e37b09a326334c9f44", - "sha256:1b2019317726f41e81154df636a897de1bfe9228c3724a433894e44cd2512378", - "sha256:1c152c49e42277bc9a2f7b78bd5fa10b13e88d1b0328221e7aef89d5c60a99a5", - "sha256:1f1c2f58f08b36f8475f3ec6f5aeb95270921d418bf18f90dffd6be5c7b0e676", - "sha256:1f4e0334d7a555c63f5c8952c57ab6f1c7b4f8c7f3442df689fc9f03df315c08", - "sha256:1f6f90700881438953eae443a9c6f8a509808bc3b185246992c4233ccee37fea", - "sha256:224b79471b4f21169ea25ebc37ed6f058040c578e50ade532e2066562597b8a9", - "sha256:236966ca6c472ea4e2d3f02f6673ebfd36ba3f23159c323f5a496869bc8e47c9", - "sha256:2427370f4a255262928cd14533a70d9738dfacadb7563bc3b7f704cc2360fc4e", - "sha256:24a8caa26521b9ad09732972927d7b45b66453e6ebd91a3c6a46d811eeb7349b", - "sha256:255dac25134d2b141c944b59a0d2f7211ca12a6d4779f7586a98b4b03ea80508", - "sha256:26ae9ad364fc61b936fb7bf4c9d8bd53f3a5b4417142cd0be5c509d6f767e2f1", - "sha256:2e329114f82ad4b9dd291bef614ea8971ec119ecd0f54795109976de75c9a852", - "sha256:3002a856367c0b41cad6784f5b8d3ab008eda194ed7864aaa58f65312e2abcac", - "sha256:30a3ebdc068c27e9d6081fca0e2c33fdf132ecea703a72ea216b81a66860adde", - "sha256:30c433a33be000dd968f5750722eaa0991037be0be4a9d453eba121774985bc8", - "sha256:31469d5832b5885adeb70982e531ce86f8c992334edd2f2254a10fa3182ac504", - "sha256:32a998bd8a64ca48616eac5a8c1cc4fa38fb244a3facf2eeb14abe186e0f6cc5", - "sha256:3307b48cd156153b117c0ea54890a3bdbf858a5b296ddd40dc3852e5f16e9b02", - "sha256:389cfefb599edf3fcfd5f64c0410da686f90f5f5e2c4d84e14f6797a5a337af4", - "sha256:3ada0b058c9f213c5f95ba301f922d402ac234f1111a7d8fd70f1b99f3c281ec", - "sha256:3b73e7227681f85d19dec46e5b881827cd354aabe46049e1a61d2f9aaa4e285a", - "sha256:3ccdde001578347e877ca4f629450973c510e88e8865d5aefbcb89b852ccc666", - "sha256:3cd06d88cb7398252284ee75c8db8e680aa0d321451132d0dba12bc995f0adcc", - "sha256:3cf62f8e447ea2c1395afa289b332e49e13d07435369b6f4e41f887db65b40bf", - "sha256:3d75e621e7d887d539d6e1d789f0c64271c250276c333480a9e1de089611f790", - "sha256:422a5ec315018e606473ba1f5431e064cf8b2a7468019233dcf8082fabad64c8", - "sha256:43173924fa93c7486402217fab99b60baf78d33806af299c56133a3755f69589", - "sha256:43fe10524fb0a0514be3954be53258e61d87341008ce4914f8e8b92bee6f875d", - "sha256:4543d8dc6470a82fde92b035a92529317191ce993533c3c0c68f56811164ed07", - "sha256:4eb33b0bdc50acd538f45041f5f19945a1f32b909b76d7b117c0c25d8063df56", - "sha256:5427a2679e95a642b7f8b0f761e660c845c8e6fe3141cddd6b62005bd133fc21", - "sha256:578568c4ba5f2b8abd956baf8b23790dbfdc953e87d5b110bce343b4a54fc9e7", - "sha256:59fe01ee8e2a1e8ceb3f6dbb216b09c8d9f4ef1c22c4fc825d045a147fa2ebc9", - "sha256:5e3929269e9d7eff905d6971d8b8c85e7dbc72c18fb99c8eae6fe0a152f2e343", - "sha256:61ed4d82f8a1e67eb9eb04f8587970d78fe7cddb4e4d6230b77eda23d27938f9", - "sha256:64bc2bbc5fba7b9db5c2c8d750824f41c6994e3882e6d73c903c2afa78d091e4", - "sha256:659318c6c8a85f6ecfc06b4e57529e5a78dfdd697260cc81f683492ad7e9435a", - "sha256:66eb80dd0ab36dbd559635e62fba3083a48a252633164857a1d1684f14326427", - "sha256:6b5a272bc7c36a2cd1b56ddc6bff02e9ce499f9f14ee4a45c45434ef083f2459", - "sha256:6d79cf5c0c6284e90f72123f4a3e4add52d6c6ebb4a9054e88df15b8d08444c6", - "sha256:7146a8742ea71b5d7d955bffcef58a9e6e04efba704b52a460134fefd10a8208", - "sha256:740915eb776617b57142ce0bb13b7596933496e2f798d3d15a20614adf30d229", - "sha256:75482f43465edefd8a5d72724887ccdcd0c83778ded8f0cb1e0594bf71736cc0", - "sha256:7a76534263d03ae0cfa721fea40fd2b5b9d17a6f85e98025931d41dc49504474", - "sha256:7d50d4abf6729921e9613d98344b74241572b751c6b37feed75fb0c37bd5a817", - "sha256:805031c2f599eee62ac579843555ed1ce389ae00c7e9f74c2a1b45e0564a88dd", - "sha256:8aac2eeff69b71f229a405c0a4b61b54bade8e10163bc7b44fcd257949620618", - "sha256:8b6fcf6054fc4114a27aa865f8840ef3d675f9316e81868e0ad5866184a6cba5", - "sha256:8bd2b875f4ca2bb527fe23e318ddd509b7df163407b0fb717df229041c6df5d3", - "sha256:8eac0c49df91b88bf91f818e0a24c1c46f3622978e2c27035bfdca98e0e18124", - "sha256:909f7d43ff8f13d1adccb6a397094adc369d4da794407f8dd592c51cf0eae4b1", - "sha256:995015cf4a3c0d72cbf453b10a999b92c5629eaf3a0c3e1efb4b5c1f602253bb", - "sha256:99592bd3162e9c664671fd14e578a33bfdba487ea64bcb41d281286d3c870ad7", - "sha256:9c64f4ddb3886dd8ab71b68a7431ad4aa01a8fa5be5b11543b29674f29ca0ba3", - "sha256:9e78006af1a7c8a8007e4f56629d7252668344442f66982368ac06522445e375", - "sha256:9f35de41aec4b323c71f54b0ca461ebf694fb48bec62f65221f52e0017955b39", - "sha256:a059ad6b80de5b84b9fa02a39400319e62edd39d210b4e4f8c4f1243bdac4752", - "sha256:a2b0fabae7939d09d7d16a711468c385272fa1b9b7fb0d37e51143585d8e72e0", - "sha256:a54ec568f1fc7f3c313c2f3b16e5db346bf3660e1309746e7fccbbfded856188", - "sha256:a62d78a1c9072949018cdb05d3c533924ef8ac9bcb06cbf96f6d14772c5cd451", - "sha256:a7bd27f7ab3204f16967a6f899b3e8e9eb3362c0ab91f2ee659e0345445e0078", - "sha256:a7be07e5df178430621c716a63151165684d3e9958f2bbfcb644246162007ab7", - "sha256:ab583ac203af1d09034be41458feeab7863c0635c650a16f15771e1386abf2d7", - "sha256:abcfed2c4c139f25c2355e180bcc077a7cae91eefbb8b3927bb3f836c9586f1f", - "sha256:acc9fa606f76fc111b4569348cc23a771cb52c61516dcc6bcef46d612edb483b", - "sha256:ae93e0ff43b6f6892999af64097b18561691ffd835e21a8348a441e256592e1f", - "sha256:b038f10e23f277153f86f95c777ba1958bcd5993194fda26a1d06fae98b2f00c", - "sha256:b128dbf1c939674a50dd0b28f12c244d90e5015e751a4f339a96c54f7275e291", - "sha256:b1b389ae17296dd739015d5ddb222ee99fd66adeae910de21ac950e00979d897", - "sha256:b57e28dbc031d13916b946719f213c494a517b442d7b48b29443e79610acd887", - "sha256:b90e27b4674e6c405ad6c64e515a505c6d113b832df52fdacb6b1ffd1fa9a1d1", - "sha256:b9cb19dfd83d35b6ff24a4022376ea6e45a2beba8ef3f0836b8a4b288b6ad685", - "sha256:ba46b51b6e51b4ef7bfb84b82f5db0dc5e300fb222a8a13b8cd4111898a869cf", - "sha256:be8751869e28b9c0d368d94f5afcb4234db66fe8496144547b4b6d6a0645cfc6", - "sha256:c23831bdee0a2a3cf21be057b5e5326292f60472fb6c6f86392bbf0de70ba731", - "sha256:c2e98c840c9c8e65c0e04b40c6c5066c8632678cd50c8721fdbcd2e09f21a507", - "sha256:c56c179839d5dcf51d565132185409d1d5dd8e614ba501eb79023a6cab25576b", - "sha256:c605a2b2dc14282b580454b9b5d14ebe0668381a3a26d0ac39daa0ca115eb2ae", - "sha256:ce5b3082e86aee80b3925ab4928198450d8e5b6466e11501fe03ad2191c6d777", - "sha256:d4e8535bd4d741039b5aad4285ecd9b902ef9e224711f0b6afda6e38d7ac02c7", - "sha256:daeac9dd30cda8703c417e4fddccd7c4dc0c73421a0b54a7da2713be125846be", - "sha256:dd53893675b729a965088aaadd6a1f326a72b83742b056c1065bdd2e2a42b4df", - "sha256:e1eb72c741fd24d5a28242ce72bb61bc91f8451877131fa3fe930edb195f7054", - "sha256:e413152e3212c4d39f82cf83c6f91be44bec9ddea950ce17af87fbf4e32ca6b2", - "sha256:ead46b0fa1dcf5af503a46e9f1c2e80b5d95c6011526352fa5f42ea201526124", - "sha256:eccb67b0e78aa2e38a04c5ecc13bab325a43e5159a181a9d1a6723db913cbb3c", - "sha256:edf74dc5e212b8c75165b435c43eb0d5e81b6b300a938a4eb82827119115e840", - "sha256:f2882bf27037eb687e49591690e5d491e677272964f9ec7bc2abbe09108bdfb8", - "sha256:f6f19170197cc29baccd33ccc5b5d6a331058796485857cf34f7635aa25fb0cd", - "sha256:f84627997008390dd15762128dcf73c3365f4ec0106739cde6c20a07ed198ec8", - "sha256:f901a5aace8e8c25d78960dcc24c870c8d356660d3b49b93a78bf38eb682aac3", - "sha256:f92c7f62d59373cd93bc9969d2da9b4b21f78283b1379ba012f7ee8127b3152e", - "sha256:fb6214fe1750adc2a1b801a199d64b5a67671bf76ebf24c730b157846d0e90d2", - "sha256:fbd8d737867912b6c5f99f56782b8cb81f978a97b4437a1c476de90a3e41c9a1", - "sha256:fbf226ac85f7d6b6b9ba77db4ec0704fde88463dc17717aec78ec3c8546c70ad" + "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3", + "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", + "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", + "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", + "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", + "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32", + "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", + "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", + "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36", + "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", + "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff", + "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8", + "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", + "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721", + "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", + "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", + "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", + "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", + "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", + "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", + "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0", + "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", + "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", + "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6", + "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", + "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", + "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", + "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", + "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", + "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", + "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912", + "sha256:363eb68a0a59bd2303216d2346e6c441ba10d36d1f9969fcb6f1ba700de7bb5c", + "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", + "sha256:3996b50c3237c4aec17459217c1e7bbdead9a22a0fcd3c365564fbd16439dde6", + "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2", + "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", + "sha256:3ba3ef510467abb0667421a286dc906e30eb08569365f5cdb131d7aff7c2dd84", + "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", + "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", + "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", + "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd", + "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", + "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", + "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62", + "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", + "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", + "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0", + "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e", + "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6", + "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc", + "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc", + "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", + "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7", + "sha256:521f33e377ff64b96c4c556b81c55d0cfffb96a11c194fd0c3f1e56f3d8dd5a4", + "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", + "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", + "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", + "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111", + "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e", + "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84", + "sha256:68af405971779d8b37198726f2b6fe3955db846fee42db7a4286fc542203934c", + "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", + "sha256:6bdce131e14b04fd34a809b6380dbfd826065c3e2fe8a50dbae659fa0c390546", + "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", + "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", + "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", + "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", + "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", + "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", + "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", + "sha256:7e73299c99939f089dd9b2120a04a516b95cdf8c1cd2b18c53ebf0de80b1f18f", + "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", + "sha256:7f5170993a0dd3ab871c74f45c0a21a4e2c37a2f2b01b5f722a2ad9c6650469e", + "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", + "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", + "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", + "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", + "sha256:8b55d5497b51afdfde55925e04a022f1de14d4f4f25cdfd4f5d9b0aa96166851", + "sha256:8cfc12a8630a29d601f48d47787bd7eb730e475e83edb5d6c5084317463373eb", + "sha256:9281bf5b34f59afbc6b1e477a372e9526b66ca446f4bf62592839c195a718b32", + "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", + "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", + "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81", + "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", + "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", + "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", + "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", + "sha256:9cf41880c991716f3c7cec48e2f19ae4045fc9db5fc9cff27347ada24d710bb5", + "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb", + "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349", + "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", + "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", + "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", + "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", + "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34", + "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c", + "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", + "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", + "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", + "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", + "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff", + "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", + "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85", + "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7", + "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", + "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", + "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", + "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", + "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", + "sha256:b61189b29081a20c7e4e0b49b44d5d44bb0dc92be3c6d06a11cc043f81bf9329", + "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", + "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", + "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", + "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", + "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", + "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", + "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", + "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", + "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", + "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", + "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", + "sha256:ce8fdc2dca699f8dbf055a61d73eaa10482569ad20ee3c36ef9641f69afa8c91", + "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", + "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", + "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", + "sha256:d874eb056410ca05fed180b6642e680373688efafc7f077b2a2f61811e873a40", + "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7", + "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", + "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648", + "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", + "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73", + "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b", + "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", + "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", + "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4", + "sha256:ec81878ddf0e98817def1e77d4f50dae5ef5b0e4fe796fae3bd674304172416e", + "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", + "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046", + "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", + "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9", + "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", + "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", + "sha256:f8e5c0031b90ca9ce555e2e8fd5c3b02a25f14989cbc310701823832c99eb687", + "sha256:fb287618b9c7aa3bf8d825f02d9201b2f13078a5ed3b293c8f4d953917d84d5e", + "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", + "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7" ], "markers": "python_version >= '3.9'", - "version": "==6.4.3" + "version": "==6.7.0" }, "oauth2client": { "hashes": [ @@ -896,131 +1005,155 @@ "signedtoken" ], "hashes": [ - "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", - "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918" + "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", + "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1" ], - "markers": "python_version >= '3.6'", - "version": "==3.2.2" + "markers": "python_version >= '3.8'", + "version": "==3.3.1" }, "pbr": { "hashes": [ - "sha256:38d4daea5d9fa63b3f626131b9d34947fd0c8be9b05a29276870580050a25a76", - "sha256:93ea72ce6989eb2eed99d0f75721474f69ad88128afdef5ac377eb797c4bf76b" + "sha256:b46004ec30a5324672683ec848aed9e8fc500b0d261d40a3229c2d2bbfcedc29", + "sha256:ff223894eb1cd271a98076b13d3badff3bb36c424074d26334cd25aebeecea6b" ], "markers": "python_version >= '2.6'", - "version": "==6.1.1" + "version": "==7.0.3" }, "propcache": { "hashes": [ - "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", - "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", - "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf", - "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", - "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5", - "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c", - "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", - "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", - "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", - "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", - "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", - "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42", - "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035", - "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0", - "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e", - "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46", - "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", - "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", - "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", - "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", - "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", - "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", - "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", - "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833", - "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259", - "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136", - "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", - "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", - "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", - "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", - "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f", - "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", - "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", - "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", - "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566", - "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", - "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908", - "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf", - "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", - "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64", - "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", - "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71", - "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", - "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", - "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", - "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5", - "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894", - "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe", - "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", - "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", - "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", - "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", - "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641", - "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", - "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649", - "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", - "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd", - "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", - "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", - "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229", - "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", - "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", - "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", - "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", - "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", - "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294", - "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", - "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", - "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", - "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", - "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", - "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7", - "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", - "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", - "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", - "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", - "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7", - "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519", - "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", - "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180", - "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", - "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", - "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", - "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", - "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", - "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", - "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", - "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6", - "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c", - "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", - "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", - "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98", - "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", - "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", - "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", - "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", - "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", - "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5" + "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e", + "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", + "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", + "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", + "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", + "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", + "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", + "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", + "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", + "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888", + "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", + "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", + "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", + "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", + "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", + "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", + "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", + "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", + "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", + "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb", + "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", + "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", + "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", + "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff", + "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", + "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", + "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", + "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", + "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", + "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", + "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", + "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc", + "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", + "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", + "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", + "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", + "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", + "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", + "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", + "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", + "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", + "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", + "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", + "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", + "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938", + "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", + "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", + "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", + "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", + "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", + "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", + "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", + "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", + "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0", + "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", + "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", + "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", + "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", + "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", + "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", + "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", + "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", + "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", + "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", + "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f", + "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", + "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", + "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183", + "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", + "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", + "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", + "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", + "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", + "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19", + "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", + "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", + "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", + "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", + "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", + "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", + "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", + "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", + "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", + "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", + "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", + "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", + "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", + "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", + "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", + "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", + "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", + "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac", + "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", + "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", + "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", + "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", + "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", + "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", + "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00", + "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a", + "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", + "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", + "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", + "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", + "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", + "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", + "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", + "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", + "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", + "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", + "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", + "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", + "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", + "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", + "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", + "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", + "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", + "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", + "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", + "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88", + "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", + "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781" ], "markers": "python_version >= '3.9'", - "version": "==0.3.1" + "version": "==0.4.1" }, "proto-plus": { "hashes": [ - "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", - "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012" + "sha256:1baa7f81cf0f8acb8bc1f6d085008ba4171eaf669629d1b6d1673b21ed1c0a82", + "sha256:873af56dd0d7e91836aee871e5799e1c6f1bda86ac9a983e0bb9f0c266a568c4" ], "markers": "python_version >= '3.7'", - "version": "==1.26.1" + "version": "==1.27.0" }, "protobuf": { "hashes": [ @@ -1039,6 +1172,7 @@ "sha256:fee88269a090ada09ca63551bf2f573eb2424035bcf2cb1b121895b01a46594a" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==4.23.4" }, "psutil": { @@ -1059,6 +1193,7 @@ "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==5.9.4" }, "pyasn1": { @@ -1079,11 +1214,11 @@ }, "pycparser": { "hashes": [ - "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", - "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" + "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", + "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934" ], "markers": "python_version >= '3.8'", - "version": "==2.22" + "version": "==2.23" }, "pygithub": { "hashes": [ @@ -1091,6 +1226,7 @@ "sha256:2caf0054ea079b71e539741ae56c5a95e073b81fa472ce222e81667381b9601b" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==1.55" }, "pyjwt": { @@ -1111,19 +1247,36 @@ }, "pynacl": { "hashes": [ - "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858", - "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d", - "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93", - "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1", - "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92", - "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff", - "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba", - "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394", - "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b", - "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543" + "sha256:04f20784083014e265ad58c1b2dd562c3e35864b5394a14ab54f5d150ee9e53e", + "sha256:10d755cf2a455d8c0f8c767a43d68f24d163b8fe93ccfaabfa7bafd26be58d73", + "sha256:140373378e34a1f6977e573033d1dd1de88d2a5d90ec6958c9485b2fd9f3eb90", + "sha256:16c60daceee88d04f8d41d0a4004a7ed8d9a5126b997efd2933e08e93a3bd850", + "sha256:16dd347cdc8ae0b0f6187a2608c0af1c8b7ecbbe6b4a06bff8253c192f696990", + "sha256:25720bad35dfac34a2bcdd61d9e08d6bfc6041bebc7751d9c9f2446cf1e77d64", + "sha256:2d6cd56ce4998cb66a6c112fda7b1fdce5266c9f05044fa72972613bef376d15", + "sha256:347dcddce0b4d83ed3f32fd00379c83c425abee5a9d2cd0a2c84871334eaff64", + "sha256:4853c154dc16ea12f8f3ee4b7e763331876316cc3a9f06aeedf39bcdca8f9995", + "sha256:49c336dd80ea54780bcff6a03ee1a476be1612423010472e60af83452aa0f442", + "sha256:4a25cfede801f01e54179b8ff9514bd7b5944da560b7040939732d1804d25419", + "sha256:51fed9fe1bec9e7ff9af31cd0abba179d0e984a2960c77e8e5292c7e9b7f7b5d", + "sha256:536703b8f90e911294831a7fbcd0c062b837f3ccaa923d92a6254e11178aaf42", + "sha256:5789f016e08e5606803161ba24de01b5a345d24590a80323379fc4408832d290", + "sha256:6b08eab48c9669d515a344fb0ef27e2cbde847721e34bba94a343baa0f33f1f4", + "sha256:6b393bc5e5a0eb86bb85b533deb2d2c815666665f840a09e0aa3362bb6088736", + "sha256:84709cea8f888e618c21ed9a0efdb1a59cc63141c403db8bf56c469b71ad56f2", + "sha256:8bfaa0a28a1ab718bad6239979a5a57a8d1506d0caf2fba17e524dbb409441cf", + "sha256:bbcc4452a1eb10cd5217318c822fde4be279c9de8567f78bad24c773c21254f8", + "sha256:cb36deafe6e2bce3b286e5d1f3e1c246e0ccdb8808ddb4550bb2792f2df298f2", + "sha256:cf831615cc16ba324240de79d925eacae8265b7691412ac6b24221db157f6bd1", + "sha256:dcdeb41c22ff3c66eef5e63049abf7639e0db4edee57ba70531fc1b6b133185d", + "sha256:dea103a1afcbc333bc0e992e64233d360d393d1e63d0bc88554f572365664348", + "sha256:ef214b90556bb46a485b7da8258e59204c244b1b5b576fb71848819b468c44a7", + "sha256:f3482abf0f9815e7246d461fab597aa179b7524628a4bc36f86a7dc418d2608d", + "sha256:f46386c24a65383a9081d68e9c2de909b1834ec74ff3013271f1bca9c2d233eb", + "sha256:f4b3824920e206b4f52abd7de621ea7a44fd3cb5c8daceb7c3612345dfc54f2e" ], - "markers": "python_version >= '3.6'", - "version": "==1.5.0" + "markers": "python_version >= '3.8'", + "version": "==1.6.0" }, "pyopenssl": { "hashes": [ @@ -1131,6 +1284,7 @@ "sha256:ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==22.0.0" }, "pyparsing": { @@ -1147,6 +1301,7 @@ "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.1" }, "python-http-client": { @@ -1167,49 +1322,61 @@ }, "pyyaml": { "hashes": [ - "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", - "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", - "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", - "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", - "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", - "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", - "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", - "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", - "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", - "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", - "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", - "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", - "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", - "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", - "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", - "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", - "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", - "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", - "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", - "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", - "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", - "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", - "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", - "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", - "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", - "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", - "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", - "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", - "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", - "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", - "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", - "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", - "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", - "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", - "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", - "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", - "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", - "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", - "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", - "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", + "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", + "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", + "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", + "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", + "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", + "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", + "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", + "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", + "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", + "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", + "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", + "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", + "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", + "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", + "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", + "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", + "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", + "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", + "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", + "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", + "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", + "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", + "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", + "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", + "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", + "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", + "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", + "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", + "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", + "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", + "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", + "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", + "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", + "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", + "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", + "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", + "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", + "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", + "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" ], "index": "pypi", - "version": "==6.0" + "markers": "python_version >= '3.6'", + "version": "==6.0.1" }, "redis": { "hashes": [ @@ -1217,6 +1384,7 @@ "sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==4.6.0" }, "requests": { @@ -1225,6 +1393,7 @@ "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.21.0" }, "requests-oauthlib": { @@ -1261,11 +1430,11 @@ }, "setuptools": { "hashes": [ - "sha256:5a78f61820bc088c8e4add52932ae6b8cf423da2aff268c23f813cfbb13b4006", - "sha256:6cdc8cb9a7d590b237dbe4493614a9b75d0559b888047c1f67d49ba50fc3edb2" + "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", + "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c" ], "markers": "python_version >= '3.9'", - "version": "==80.4.0" + "version": "==80.9.0" }, "six": { "hashes": [ @@ -1277,11 +1446,11 @@ }, "uritemplate": { "hashes": [ - "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", - "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" + "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e", + "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686" ], - "markers": "python_version >= '3.6'", - "version": "==4.1.1" + "markers": "python_version >= '3.9'", + "version": "==4.2.0" }, "urllib3": { "hashes": [ @@ -1291,6 +1460,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", "version": "==1.24.3" }, + "websocket-client": { + "hashes": [ + "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", + "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, "wrapt": { "hashes": [ "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc", @@ -1365,127 +1542,154 @@ "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==1.16.0" }, "yarl": { "hashes": [ - "sha256:04d8cfb12714158abf2618f792c77bc5c3d8c5f37353e79509608be4f18705c9", - "sha256:04d9c7a1dc0a26efb33e1acb56c8849bd57a693b85f44774356c92d610369efa", - "sha256:06d06c9d5b5bc3eb56542ceeba6658d31f54cf401e8468512447834856fb0e61", - "sha256:077989b09ffd2f48fb2d8f6a86c5fef02f63ffe6b1dd4824c76de7bb01e4f2e2", - "sha256:083ce0393ea173cd37834eb84df15b6853b555d20c52703e21fbababa8c129d2", - "sha256:087e9731884621b162a3e06dc0d2d626e1542a617f65ba7cc7aeab279d55ad33", - "sha256:0a6a1e6ae21cdd84011c24c78d7a126425148b24d437b5702328e4ba640a8902", - "sha256:0acfaf1da020253f3533526e8b7dd212838fdc4109959a2c53cafc6db611bff2", - "sha256:119bca25e63a7725b0c9d20ac67ca6d98fa40e5a894bd5d4686010ff73397914", - "sha256:123393db7420e71d6ce40d24885a9e65eb1edefc7a5228db2d62bcab3386a5c0", - "sha256:18e321617de4ab170226cd15006a565d0fa0d908f11f724a2c9142d6b2812ab0", - "sha256:1a06701b647c9939d7019acdfa7ebbfbb78ba6aa05985bb195ad716ea759a569", - "sha256:2137810a20b933b1b1b7e5cf06a64c3ed3b4747b0e5d79c9447c00db0e2f752f", - "sha256:25b3bc0763a7aca16a0f1b5e8ef0f23829df11fb539a1b70476dcab28bd83da7", - "sha256:27359776bc359ee6eaefe40cb19060238f31228799e43ebd3884e9c589e63b20", - "sha256:2a8f64df8ed5d04c51260dbae3cc82e5649834eebea9eadfd829837b8093eb00", - "sha256:33bb660b390a0554d41f8ebec5cd4475502d84104b27e9b42f5321c5192bfcd1", - "sha256:35d20fb919546995f1d8c9e41f485febd266f60e55383090010f272aca93edcc", - "sha256:3b2992fe29002fd0d4cbaea9428b09af9b8686a9024c840b8a2b8f4ea4abc16f", - "sha256:3b4e88d6c3c8672f45a30867817e4537df1bbc6f882a91581faf1f6d9f0f1b5a", - "sha256:3b60a86551669c23dc5445010534d2c5d8a4e012163218fc9114e857c0586fdd", - "sha256:3d7dbbe44b443b0c4aa0971cb07dcb2c2060e4a9bf8d1301140a33a93c98e18c", - "sha256:3e429857e341d5e8e15806118e0294f8073ba9c4580637e59ab7b238afca836f", - "sha256:40ed574b4df723583a26c04b298b283ff171bcc387bc34c2683235e2487a65a5", - "sha256:42fbe577272c203528d402eec8bf4b2d14fd49ecfec92272334270b850e9cd7d", - "sha256:4345f58719825bba29895011e8e3b545e6e00257abb984f9f27fe923afca2501", - "sha256:447c5eadd750db8389804030d15f43d30435ed47af1313303ed82a62388176d3", - "sha256:44869ee8538208fe5d9342ed62c11cc6a7a1af1b3d0bb79bb795101b6e77f6e0", - "sha256:484e7a08f72683c0f160270566b4395ea5412b4359772b98659921411d32ad26", - "sha256:4a34c52ed158f89876cba9c600b2c964dfc1ca52ba7b3ab6deb722d1d8be6df2", - "sha256:4ba5e59f14bfe8d261a654278a0f6364feef64a794bd456a8c9e823071e5061c", - "sha256:4c43030e4b0af775a85be1fa0433119b1565673266a70bf87ef68a9d5ba3174c", - "sha256:4c903e0b42aab48abfbac668b5a9d7b6938e721a6341751331bcd7553de2dcae", - "sha256:4d9949eaf05b4d30e93e4034a7790634bbb41b8be2d07edd26754f2e38e491de", - "sha256:4f1a350a652bbbe12f666109fbddfdf049b3ff43696d18c9ab1531fbba1c977a", - "sha256:53b2da3a6ca0a541c1ae799c349788d480e5144cac47dba0266c7cb6c76151fe", - "sha256:54ac15a8b60382b2bcefd9a289ee26dc0920cf59b05368c9b2b72450751c6eb8", - "sha256:5d0fe6af927a47a230f31e6004621fd0959eaa915fc62acfafa67ff7229a3124", - "sha256:5d3d6d14754aefc7a458261027a562f024d4f6b8a798adb472277f675857b1eb", - "sha256:5d9b980d7234614bc4674468ab173ed77d678349c860c3af83b1fffb6a837ddc", - "sha256:634b7ba6b4a85cf67e9df7c13a7fb2e44fa37b5d34501038d174a63eaac25ee2", - "sha256:65a4053580fe88a63e8e4056b427224cd01edfb5f951498bfefca4052f0ce0ac", - "sha256:686d51e51ee5dfe62dec86e4866ee0e9ed66df700d55c828a615640adc885307", - "sha256:69df35468b66c1a6e6556248e6443ef0ec5f11a7a4428cf1f6281f1879220f58", - "sha256:6d12b8945250d80c67688602c891237994d203d42427cb14e36d1a732eda480e", - "sha256:6d409e321e4addf7d97ee84162538c7258e53792eb7c6defd0c33647d754172e", - "sha256:70e0c580a0292c7414a1cead1e076c9786f685c1fc4757573d2967689b370e62", - "sha256:737e9f171e5a07031cbee5e9180f6ce21a6c599b9d4b2c24d35df20a52fabf4b", - "sha256:7595498d085becc8fb9203aa314b136ab0516c7abd97e7d74f7bb4eb95042abe", - "sha256:798a5074e656f06b9fad1a162be5a32da45237ce19d07884d0b67a0aa9d5fdda", - "sha256:7dc63ad0d541c38b6ae2255aaa794434293964677d5c1ec5d0116b0e308031f5", - "sha256:839de4c574169b6598d47ad61534e6981979ca2c820ccb77bf70f4311dd2cc64", - "sha256:84aeb556cb06c00652dbf87c17838eb6d92cfd317799a8092cee0e570ee11229", - "sha256:85a231fa250dfa3308f3c7896cc007a47bc76e9e8e8595c20b7426cac4884c62", - "sha256:866349da9d8c5290cfefb7fcc47721e94de3f315433613e01b435473be63daa6", - "sha256:8681700f4e4df891eafa4f69a439a6e7d480d64e52bf460918f58e443bd3da7d", - "sha256:86de313371ec04dd2531f30bc41a5a1a96f25a02823558ee0f2af0beaa7ca791", - "sha256:8a7f62f5dc70a6c763bec9ebf922be52aa22863d9496a9a30124d65b489ea672", - "sha256:8c12cd754d9dbd14204c328915e23b0c361b88f3cffd124129955e60a4fbfcfb", - "sha256:8d8a3d54a090e0fff5837cd3cc305dd8a07d3435a088ddb1f65e33b322f66a94", - "sha256:91bc450c80a2e9685b10e34e41aef3d44ddf99b3a498717938926d05ca493f6a", - "sha256:95b50910e496567434cb77a577493c26bce0f31c8a305135f3bda6a2483b8e10", - "sha256:95fc9876f917cac7f757df80a5dda9de59d423568460fe75d128c813b9af558e", - "sha256:9c2aa4387de4bc3a5fe158080757748d16567119bef215bec643716b4fbf53f9", - "sha256:9c366b254082d21cc4f08f522ac201d0d83a8b8447ab562732931d31d80eb2a5", - "sha256:a0bc5e05f457b7c1994cc29e83b58f540b76234ba6b9648a4971ddc7f6aa52da", - "sha256:a884b8974729e3899d9287df46f015ce53f7282d8d3340fa0ed57536b440621c", - "sha256:ab47acc9332f3de1b39e9b702d9c916af7f02656b2a86a474d9db4e53ef8fd7a", - "sha256:af4baa8a445977831cbaa91a9a84cc09debb10bc8391f128da2f7bd070fc351d", - "sha256:af5607159085dcdb055d5678fc2d34949bd75ae6ea6b4381e784bbab1c3aa195", - "sha256:b2586e36dc070fc8fad6270f93242124df68b379c3a251af534030a4a33ef594", - "sha256:b4230ac0b97ec5eeb91d96b324d66060a43fd0d2a9b603e3327ed65f084e41f8", - "sha256:b594113a301ad537766b4e16a5a6750fcbb1497dcc1bc8a4daae889e6402a634", - "sha256:b6c4c3d0d6a0ae9b281e492b1465c72de433b782e6b5001c8e7249e085b69051", - "sha256:b7fa0cb9fd27ffb1211cde944b41f5c67ab1c13a13ebafe470b1e206b8459da8", - "sha256:b9ae2fbe54d859b3ade40290f60fe40e7f969d83d482e84d2c31b9bff03e359e", - "sha256:bb769ae5760cd1c6a712135ee7915f9d43f11d9ef769cb3f75a23e398a92d384", - "sha256:bc906b636239631d42eb8a07df8359905da02704a868983265603887ed68c076", - "sha256:bdb77efde644d6f1ad27be8a5d67c10b7f769804fff7a966ccb1da5a4de4b656", - "sha256:bf099e2432131093cc611623e0b0bcc399b8cddd9a91eded8bfb50402ec35018", - "sha256:c27d98f4e5c4060582f44e58309c1e55134880558f1add7a87c1bc36ecfade19", - "sha256:c8703517b924463994c344dcdf99a2d5ce9eca2b6882bb640aa555fb5efc706a", - "sha256:c9471ca18e6aeb0e03276b5e9b27b14a54c052d370a9c0c04a68cefbd1455eb4", - "sha256:ce360ae48a5e9961d0c730cf891d40698a82804e85f6e74658fb175207a77cb2", - "sha256:d0bf955b96ea44ad914bc792c26a0edcd71b4668b93cbcd60f5b0aeaaed06c64", - "sha256:d2cbca6760a541189cf87ee54ff891e1d9ea6406079c66341008f7ef6ab61145", - "sha256:d4fad6e5189c847820288286732075f213eabf81be4d08d6cc309912e62be5b7", - "sha256:d88cc43e923f324203f6ec14434fa33b85c06d18d59c167a0637164863b8e995", - "sha256:db243357c6c2bf3cd7e17080034ade668d54ce304d820c2a58514a4e51d0cfd6", - "sha256:dd59c9dd58ae16eaa0f48c3d0cbe6be8ab4dc7247c3ff7db678edecbaf59327f", - "sha256:e06b9f6cdd772f9b665e5ba8161968e11e403774114420737f7884b5bd7bdf6f", - "sha256:e52d6ed9ea8fd3abf4031325dc714aed5afcbfa19ee4a89898d663c9976eb487", - "sha256:ea52f7328a36960ba3231c6677380fa67811b414798a6e071c7085c57b6d20a9", - "sha256:eaddd7804d8e77d67c28d154ae5fab203163bd0998769569861258e525039d2a", - "sha256:f0cf05ae2d3d87a8c9022f3885ac6dea2b751aefd66a4f200e408a61ae9b7f0d", - "sha256:f106e75c454288472dbe615accef8248c686958c2e7dd3b8d8ee2669770d020f", - "sha256:f166eafa78810ddb383e930d62e623d288fb04ec566d1b4790099ae0f31485f1", - "sha256:f1f6670b9ae3daedb325fa55fbe31c22c8228f6e0b513772c2e1c623caa6ab22", - "sha256:f4d3fa9b9f013f7050326e165c3279e22850d02ae544ace285674cb6174b5d6d", - "sha256:f8d8aa8dd89ffb9a831fedbcb27d00ffd9f4842107d52dc9d57e64cb34073d5c", - "sha256:f9d02b591a64e4e6ca18c5e3d925f11b559c763b950184a64cf47d74d7e41877", - "sha256:faa709b66ae0e24c8e5134033187a972d849d87ed0a12a0366bedcc6b5dc14a5", - "sha256:fb0caeac4a164aadce342f1597297ec0ce261ec4532bbc5a9ca8da5622f53867", - "sha256:fdb5204d17cb32b2de2d1e21c7461cabfacf17f3645e4b9039f210c5d3378bf3" + "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", + "sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8", + "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", + "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", + "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", + "sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890", + "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", + "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", + "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", + "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", + "sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed", + "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", + "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", + "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", + "sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b", + "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", + "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", + "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", + "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", + "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", + "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", + "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", + "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", + "sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba", + "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", + "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", + "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", + "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", + "sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748", + "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", + "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", + "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", + "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", + "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", + "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", + "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", + "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", + "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", + "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", + "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", + "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", + "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", + "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", + "sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b", + "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", + "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", + "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", + "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", + "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", + "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", + "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", + "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", + "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", + "sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba", + "sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9", + "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", + "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", + "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", + "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", + "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", + "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", + "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", + "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", + "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", + "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", + "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", + "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", + "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", + "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", + "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", + "sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca", + "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", + "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", + "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", + "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", + "sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60", + "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", + "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", + "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", + "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", + "sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e", + "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", + "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", + "sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859", + "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", + "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", + "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", + "sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054", + "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", + "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", + "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", + "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", + "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", + "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", + "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", + "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", + "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", + "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", + "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", + "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", + "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", + "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", + "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", + "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", + "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", + "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", + "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", + "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", + "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", + "sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2", + "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", + "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", + "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", + "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", + "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", + "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", + "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", + "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", + "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", + "sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b", + "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", + "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", + "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", + "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", + "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", + "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", + "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", + "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", + "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", + "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249" ], "markers": "python_version >= '3.9'", - "version": "==1.20.0" + "version": "==1.22.0" } }, "develop": { "cachecontrol": { "hashes": [ - "sha256:73e7efec4b06b20d9267b441c1f733664f989fb8688391b670ca812d70795d11", - "sha256:b35e44a3113f17d2a31c1e6b27b9de6d4405f84ae51baa8c1d3cc5b633010cae" + "sha256:b7ac014ff72ee199b5f8af1de29d60239954f223e948196fa3d84adaffc71d2b", + "sha256:e6220afafa4c22a47dd0badb319f84475d79108100d04e26e8542ef7d3ab05a1" ], - "markers": "python_version >= '3.9'", - "version": "==0.14.3" + "markers": "python_version >= '3.10'", + "version": "==0.14.4" }, "cachetools": { "hashes": [ @@ -1501,6 +1705,7 @@ "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==2024.2.2" }, "cffi": { @@ -1573,6 +1778,13 @@ "index": "pypi", "version": "==1.15.1" }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, "charset-normalizer": { "hashes": [ "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", @@ -1667,15 +1879,16 @@ "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], "index": "pypi", + "markers": "python_full_version >= '3.7.0'", "version": "==3.3.2" }, "click": { "hashes": [ - "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c", - "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d" + "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", + "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" ], "markers": "python_version >= '3.10'", - "version": "==8.2.0" + "version": "==8.3.1" }, "cryptography": { "hashes": [ @@ -1703,6 +1916,7 @@ "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==37.0.4" }, "firebase-admin": { @@ -1711,6 +1925,7 @@ "sha256:e3c42351fb6194d7279a6fd9209a947005fb4ee7e9037d19762e6cb3da4a82e1" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==6.2.0" }, "flask": { @@ -1719,14 +1934,19 @@ "sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.2.2" }, "google-api-core": { + "extras": [ + "grpc" + ], "hashes": [ "sha256:25d29e05a0058ed5f19c61c0a78b1b53adea4d9364b464d014fbda941f6d1c9a", "sha256:d92a5a92dc36dd4f4b9ee4e55528a90e432b059f93aee6ad857f9de8cc7ae94a" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.11.1" }, "google-api-python-client": { @@ -1735,6 +1955,7 @@ "sha256:f34abb671afd488bd19d30721ea20fb30d3796ddd825d6f91f26d8c718a9f07d" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.93.0" }, "google-auth": { @@ -1743,14 +1964,16 @@ "sha256:d61d1b40897407b574da67da1a833bdc10d5a11642566e506565d1b1a46ba873" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==2.22.0" }, "google-auth-httplib2": { "hashes": [ - "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05", - "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d" + "sha256:177898a0175252480d5ed916aeea183c2df87c1f9c26705d74ae6b951c268b0b", + "sha256:426167e5df066e3f5a0fc7ea18768c08e7296046594ce4c8c409c2457dd1f776" ], - "version": "==0.2.0" + "markers": "python_version >= '3.7'", + "version": "==0.3.0" }, "google-cloud-core": { "hashes": [ @@ -1758,15 +1981,16 @@ "sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.3.3" }, "google-cloud-firestore": { "hashes": [ - "sha256:0ad2e33fa7da0ba8fb7ccc324f91d3f57866b770e24840bd62f6a272f747c5f9", - "sha256:0ff7b4c66e3ad2fe00f7d5d8c15127bf4ff8b316c6e4eb635ac51d9a9bcd828b" + "sha256:47652ca74a77903c192fe194f646871ca2f881e56c30e7f573a9782d3bdbb610", + "sha256:9d6a5bdefb30ed5ca94a7cb3560873352a3dbf868957ef789e6e74d086d52d82" ], "markers": "platform_python_implementation != 'PyPy'", - "version": "==2.20.2" + "version": "==2.22.0" }, "google-cloud-storage": { "hashes": [ @@ -1774,6 +1998,7 @@ "sha256:9433cf28801671de1c80434238fb1e7e4a1ba3087470e90f70c928ea77c2b9d7" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.10.0" }, "google-crc32c": { @@ -1848,23 +2073,27 @@ "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==1.5.0" }, "google-resumable-media": { "hashes": [ - "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa", - "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0" + "sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582", + "sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae" ], "markers": "python_version >= '3.7'", - "version": "==2.7.2" + "version": "==2.8.0" }, "googleapis-common-protos": { + "extras": [ + "grpc" + ], "hashes": [ - "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", - "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8" + "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", + "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5" ], "markers": "python_version >= '3.7'", - "version": "==1.70.0" + "version": "==1.72.0" }, "grpcio": { "hashes": [ @@ -1924,6 +2153,7 @@ "sha256:fa63245271920786f4cb44dcada4983a3516be8f470924528cf658731864c14b" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==1.62.2" }, "grpcio-status": { @@ -1954,6 +2184,7 @@ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0" ], "index": "pypi", + "markers": "python_version >= '3.6'", "version": "==2.0.1" }, "jinja2": { @@ -1962,152 +2193,188 @@ "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==3.1.4" }, "markupsafe": { "hashes": [ - "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", - "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", - "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", - "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", - "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", - "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", - "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", - "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", - "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", - "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", - "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", - "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", - "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", - "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", - "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", - "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", - "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", - "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", - "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", - "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", - "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", - "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", - "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", - "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", - "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", - "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", - "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", - "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", - "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", - "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", - "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", - "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", - "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", - "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", - "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", - "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", - "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", - "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", - "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", - "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", - "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", - "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", - "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", - "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", - "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", - "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", - "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", - "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", - "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", - "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", - "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", - "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", - "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", - "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", - "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", - "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", - "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", - "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", - "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", - "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", - "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50" + "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", + "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", + "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", + "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", + "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", + "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c", + "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", + "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", + "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", + "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", + "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", + "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26", + "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", + "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", + "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", + "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", + "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", + "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", + "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", + "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", + "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", + "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", + "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", + "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", + "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", + "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758", + "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", + "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8", + "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", + "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", + "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", + "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", + "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", + "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", + "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", + "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", + "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2", + "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", + "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", + "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", + "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", + "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", + "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", + "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", + "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", + "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e", + "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", + "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", + "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", + "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", + "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", + "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", + "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b", + "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", + "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", + "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", + "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d", + "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", + "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", + "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", + "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", + "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", + "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", + "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", + "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", + "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", + "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", + "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", + "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", + "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", + "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", + "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", + "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", + "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7", + "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", + "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", + "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", + "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", + "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", + "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42", + "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", + "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", + "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", + "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", + "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", + "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", + "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc", + "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", + "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50" ], "markers": "python_version >= '3.9'", - "version": "==3.0.2" + "version": "==3.0.3" }, "msgpack": { "hashes": [ - "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", - "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", - "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", - "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", - "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", - "sha256:13599f8829cfbe0158f6456374e9eea9f44eee08076291771d8ae93eda56607f", - "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", - "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", - "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b", - "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", - "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7", - "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044", - "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6", - "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b", - "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0", - "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", - "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468", - "sha256:471e27a5787a2e3f974ba023f9e265a8c7cfd373632247deb225617e3100a3c7", - "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", - "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", - "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325", - "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1", - "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846", - "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88", - "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", - "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", - "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", - "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59", - "sha256:646afc8102935a388ffc3914b336d22d1c2d6209c773f3eb5dd4d6d3b6f8c1cb", - "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68", - "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", - "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f", - "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701", - "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b", - "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d", - "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa", - "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", - "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd", - "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", - "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48", - "sha256:879a7b7b0ad82481c52d3c7eb99bf6f0645dbdec5134a4bddbd16f3506947feb", - "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74", - "sha256:8a84efb768fb968381e525eeeb3d92857e4985aacc39f3c47ffd00eb4509315b", - "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346", - "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e", - "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6", - "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5", - "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", - "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5", - "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", - "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", - "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", - "sha256:c40ffa9a15d74e05ba1fe2681ea33b9caffd886675412612d93ab17b58ea2fec", - "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8", - "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5", - "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", - "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e", - "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", - "sha256:e0856a2b7e8dcb874be44fea031d22e5b3a19121be92a1e098f46068a11b0870", - "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f", - "sha256:f1ba6136e650898082d9d5a5217d5906d1e138024f836ff48691784bbe1adf96", - "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c", - "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd", - "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788" + "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2", + "sha256:04fb995247a6e83830b62f0b07bf36540c213f6eac8e851166d8d86d83cbd014", + "sha256:180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931", + "sha256:1d1418482b1ee984625d88aa9585db570180c286d942da463533b238b98b812b", + "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b", + "sha256:1fdf7d83102bf09e7ce3357de96c59b627395352a4024f6e2458501f158bf999", + "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029", + "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0", + "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9", + "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c", + "sha256:350ad5353a467d9e3b126d8d1b90fe05ad081e2e1cef5753f8c345217c37e7b8", + "sha256:354e81bcdebaab427c3df4281187edc765d5d76bfb3a7c125af9da7a27e8458f", + "sha256:365c0bbe981a27d8932da71af63ef86acc59ed5c01ad929e09a0b88c6294e28a", + "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42", + "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", + "sha256:41d1a5d875680166d3ac5c38573896453bbbea7092936d2e107214daf43b1d4f", + "sha256:42eefe2c3e2af97ed470eec850facbe1b5ad1d6eacdbadc42ec98e7dcf68b4b7", + "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb", + "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef", + "sha256:4efd7b5979ccb539c221a4c4e16aac1a533efc97f3b759bb5a5ac9f6d10383bf", + "sha256:5559d03930d3aa0f3aacb4c42c776af1a2ace2611871c84a75afe436695e6245", + "sha256:5928604de9b032bc17f5099496417f113c45bc6bc21b5c6920caf34b3c428794", + "sha256:59415c6076b1e30e563eb732e23b994a61c159cec44deaf584e5cc1dd662f2af", + "sha256:5a46bf7e831d09470ad92dff02b8b1ac92175ca36b087f904a0519857c6be3ff", + "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e", + "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296", + "sha256:67016ae8c8965124fdede9d3769528ad8284f14d635337ffa6a713a580f6c030", + "sha256:6bde749afe671dc44893f8d08e83bf475a1a14570d67c4bb5cec5573463c8833", + "sha256:6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939", + "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa", + "sha256:70c5a7a9fea7f036b716191c29047374c10721c389c21e9ffafad04df8c52c90", + "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c", + "sha256:80a0ff7d4abf5fecb995fcf235d4064b9a9a8a40a3ab80999e6ac1e30b702717", + "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406", + "sha256:897c478140877e5307760b0ea66e0932738879e7aa68144d9b78ea4c8302a84a", + "sha256:8b696e83c9f1532b4af884045ba7f3aa741a63b2bc22617293a2c6a7c645f251", + "sha256:8e22ab046fa7ede9e36eeb4cfad44d46450f37bb05d5ec482b02868f451c95e2", + "sha256:94fd7dc7d8cb0a54432f296f2246bc39474e017204ca6f4ff345941d4ed285a7", + "sha256:99e2cb7b9031568a2a5c73aa077180f93dd2e95b4f8d3b8e14a73ae94a9e667e", + "sha256:9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b", + "sha256:9fba231af7a933400238cb357ecccf8ab5d51535ea95d94fc35b7806218ff844", + "sha256:a465f0dceb8e13a487e54c07d04ae3ba131c7c5b95e2612596eafde1dccf64a9", + "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87", + "sha256:a668204fa43e6d02f89dbe79a30b0d67238d9ec4c5bd8a940fc3a004a47b721b", + "sha256:a7787d353595c7c7e145e2331abf8b7ff1e6673a6b974ded96e6d4ec09f00c8c", + "sha256:a8f6e7d30253714751aa0b0c84ae28948e852ee7fb0524082e6716769124bc23", + "sha256:ad09b984828d6b7bb52d1d1d0c9be68ad781fa004ca39216c8a1e63c0f34ba3c", + "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e", + "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620", + "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69", + "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f", + "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68", + "sha256:d62ce1f483f355f61adb5433ebfd8868c5f078d1a52d042b0a998682b4fa8c27", + "sha256:d99ef64f349d5ec3293688e91486c5fdb925ed03807f64d98d205d2713c60b46", + "sha256:db6192777d943bdaaafb6ba66d44bf65aa0e9c5616fa1d2da9bb08828c6b39aa", + "sha256:e23ce8d5f7aa6ea6d2a2b326b4ba46c985dbb204523759984430db7114f8aa00", + "sha256:e64c8d2f5e5d5fda7b842f55dec6133260ea8f53c4257d64494c534f306bf7a9", + "sha256:e69b39f8c0aa5ec24b57737ebee40be647035158f14ed4b40e6f150077e21a84", + "sha256:ea5405c46e690122a76531ab97a079e184c0daf491e588592d6a23d3e32af99e", + "sha256:f2cb069d8b981abc72b41aea1c580ce92d57c673ec61af4c500153a626cb9e20", + "sha256:fac4be746328f90caa3cd4bc67e6fe36ca2bf61d5c6eb6d895b6527e3f05071e", + "sha256:fffee09044073e69f2bad787071aeec727183e7580443dfeb8556cbf1978d162" ], - "markers": "python_version >= '3.8'", - "version": "==1.1.0" + "markers": "python_version >= '3.9'", + "version": "==1.1.2" + }, + "parameterized": { + "hashes": [ + "sha256:4e0758e3d41bea3bbd05ec14fc2c24736723f243b28d702081aef438c9372b1b", + "sha256:7fc905272cefa4f364c1a3429cbbe9c0f98b793988efb5bf90aac80f08db09b1" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==0.9.0" }, "proto-plus": { "hashes": [ - "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", - "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012" + "sha256:1baa7f81cf0f8acb8bc1f6d085008ba4171eaf669629d1b6d1673b21ed1c0a82", + "sha256:873af56dd0d7e91836aee871e5799e1c6f1bda86ac9a983e0bb9f0c266a568c4" ], "markers": "python_version >= '3.7'", - "version": "==1.26.1" + "version": "==1.27.0" }, "protobuf": { "hashes": [ @@ -2126,6 +2393,7 @@ "sha256:fee88269a090ada09ca63551bf2f573eb2424035bcf2cb1b121895b01a46594a" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==4.23.4" }, "pyasn1": { @@ -2146,11 +2414,11 @@ }, "pycparser": { "hashes": [ - "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", - "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" + "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", + "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934" ], "markers": "python_version >= '3.8'", - "version": "==2.22" + "version": "==2.23" }, "pyjwt": { "hashes": [ @@ -2174,6 +2442,7 @@ "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.21.0" }, "requests-toolbelt": { @@ -2192,13 +2461,21 @@ "markers": "python_version >= '3.6' and python_version < '4'", "version": "==4.9.1" }, + "six": { + "hashes": [ + "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", + "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.17.0" + }, "uritemplate": { "hashes": [ - "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", - "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" + "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e", + "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686" ], - "markers": "python_version >= '3.6'", - "version": "==4.1.1" + "markers": "python_version >= '3.9'", + "version": "==4.2.0" }, "urllib3": { "hashes": [ @@ -2214,6 +2491,7 @@ "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.2.2" } } diff --git a/src/clusterfuzz/_internal/base/tasks/__init__.py b/src/clusterfuzz/_internal/base/tasks/__init__.py index eac1d204154..acb70f89ca1 100644 --- a/src/clusterfuzz/_internal/base/tasks/__init__.py +++ b/src/clusterfuzz/_internal/base/tasks/__init__.py @@ -64,6 +64,12 @@ 'regression': 24 * 60 * 60, } + +def get_task_duration(command): + """Gets the duration of a task.""" + return TASK_LEASE_SECONDS_BY_COMMAND.get(command, TASK_LEASE_SECONDS) + + TASK_QUEUE_DISPLAY_NAMES = { 'LINUX': 'Linux', 'LINUX_WITH_GPU': 'Linux (with GPU)', @@ -503,6 +509,7 @@ def __init__(self, pubsub_message): } self.eta = datetime.datetime.utcfromtimestamp(float(self.attribute('eta'))) + self.do_not_ack = False def attribute(self, key): """Return attribute value.""" @@ -550,7 +557,8 @@ def lease(self, _event=None): # pylint: disable=arguments-differ leaser_thread.join() # If we get here the task succeeded in running. Acknowledge the message. - self._pubsub_message.ack() + if not self.do_not_ack: + self._pubsub_message.ack() track_task_end() def dont_retry(self): @@ -587,7 +595,8 @@ def lease(self, _event=None): # pylint: disable=arguments-differ leaser_thread.join() # If we get here the task succeeded in running. Acknowledge the message. - self._pubsub_message.ack() + if not self.do_not_ack: + self._pubsub_message.ack() track_task_end() diff --git a/src/clusterfuzz/_internal/batch/data_structures.py b/src/clusterfuzz/_internal/batch/data_structures.py deleted file mode 100644 index 24e90670eb2..00000000000 --- a/src/clusterfuzz/_internal/batch/data_structures.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Batch module data structures.""" -import collections - -# A named tuple that defines the execution environment for a batch workload. -# This includes details about the machine, disk, network, and container image, -# as well as ClusterFuzz-specific settings. -BatchWorkloadSpec = collections.namedtuple('BatchWorkloadSpec', [ - 'clusterfuzz_release', - 'disk_size_gb', - 'disk_type', - 'docker_image', - 'user_data', - 'service_account_email', - 'subnetwork', - 'preemptible', - 'project', - 'machine_type', - 'network', - 'gce_region', - 'priority', - 'max_run_duration', - 'retry', -]) - - -class BatchTask: - """Represents a single ClusterFuzz task to be executed on a remote worker. - - This class holds the necessary information to execute a ClusterFuzz command, - such as 'fuzz' or 'progression', in a remote environment like GCP Batch. It - is used to enqueue tasks and track their state. - """ - - def __init__(self, command, job_type, input_download_url): - self.command = command - self.job_type = job_type - self.input_download_url = input_download_url diff --git a/src/clusterfuzz/_internal/batch/gcp.py b/src/clusterfuzz/_internal/batch/gcp.py deleted file mode 100644 index 9b155cce7b5..00000000000 --- a/src/clusterfuzz/_internal/batch/gcp.py +++ /dev/null @@ -1,200 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""GCP Cloud Batch helpers. - -This module provides a client for interacting with the GCP Batch service. It is -used to run granular tasks that require a high degree of isolation, such as -executing untrusted code from fuzzing jobs. Each task is run in its own VM, -ensuring that any potential security issues are contained. -""" -import threading -from typing import List -from typing import Tuple -import uuid - -from google.cloud import batch_v1 as batch - -from clusterfuzz._internal.base import retry -from clusterfuzz._internal.google_cloud_utils import credentials -from clusterfuzz._internal.metrics import logs -from clusterfuzz._internal.remote_task import RemoteTaskInterface - -_local = threading.local() - -DEFAULT_RETRY_COUNT = 0 - -# Controls how many containers (ClusterFuzz tasks) can run on a single VM. -# THIS SHOULD BE 1 OR THERE WILL BE SECURITY PROBLEMS. -TASK_COUNT_PER_NODE = 1 - -# See https://cloud.google.com/batch/quotas#job_limits -MAX_CONCURRENT_VMS_PER_JOB = 1000 - - -def _create_batch_client_new(): - """Creates a batch client.""" - creds, _ = credentials.get_default() - return batch.BatchServiceClient(credentials=creds) - - -def _batch_client(): - """Gets the batch client, creating it if it does not exist.""" - if hasattr(_local, 'client'): - return _local.client - - _local.client = _create_batch_client_new() - return _local.client - - -def get_job_name(): - return 'j-' + str(uuid.uuid4()).lower() - - -def _get_task_spec(batch_workload_spec): - """Gets the task spec based on the batch workload spec.""" - runnable = batch.Runnable() - runnable.container = batch.Runnable.Container() - runnable.container.image_uri = batch_workload_spec.docker_image - clusterfuzz_release = batch_workload_spec.clusterfuzz_release - runnable.container.options = ( - '--memory-swappiness=40 --shm-size=1.9g --rm --net=host ' - '-e HOST_UID=1337 -P --privileged --cap-add=all ' - f'-e CLUSTERFUZZ_RELEASE={clusterfuzz_release} ' - '--name=clusterfuzz -e UNTRUSTED_WORKER=False -e UWORKER=True ' - '-e USE_GCLOUD_STORAGE_RSYNC=1 ' - '-e UWORKER_INPUT_DOWNLOAD_URL') - runnable.container.volumes = ['/var/scratch0:/mnt/scratch0'] - task_spec = batch.TaskSpec() - task_spec.runnables = [runnable] - if batch_workload_spec.retry: - # Tasks in general have 6 hours to run (except pruning which has 24). - # Our signed URLs last 24 hours. Therefore, the maxiumum number of retries - # is 4. This is a temporary solution anyway. - task_spec.max_retry_count = 4 - else: - task_spec.max_retry_count = DEFAULT_RETRY_COUNT - task_spec.max_run_duration = batch_workload_spec.max_run_duration - return task_spec - - -def _set_preemptible(instance_policy, batch_workload_spec) -> None: - if batch_workload_spec.preemptible: - instance_policy.provisioning_model = ( - batch.AllocationPolicy.ProvisioningModel.PREEMPTIBLE) - else: - instance_policy.provisioning_model = ( - batch.AllocationPolicy.ProvisioningModel.STANDARD) - - -def _get_allocation_policy(spec): - """Returns the allocation policy for a BatchWorkloadSpec.""" - disk = batch.AllocationPolicy.Disk() - disk.image = 'batch-cos' - disk.size_gb = spec.disk_size_gb - disk.type = spec.disk_type - instance_policy = batch.AllocationPolicy.InstancePolicy() - instance_policy.boot_disk = disk - instance_policy.machine_type = spec.machine_type - _set_preemptible(instance_policy, spec) - instances = batch.AllocationPolicy.InstancePolicyOrTemplate() - instances.policy = instance_policy - - # Don't use external ip addresses which use quota, cost money, and are - # unnecessary. - network_interface = batch.AllocationPolicy.NetworkInterface() - network_interface.no_external_ip_address = True - network_interface.network = spec.network - network_interface.subnetwork = spec.subnetwork - network_interfaces = [network_interface] - network_policy = batch.AllocationPolicy.NetworkPolicy() - network_policy.network_interfaces = network_interfaces - - allocation_policy = batch.AllocationPolicy() - allocation_policy.instances = [instances] - allocation_policy.network = network_policy - service_account = batch.ServiceAccount(email=spec.service_account_email) # pylint: disable=no-member - allocation_policy.service_account = service_account - return allocation_policy - - -@retry.wrap( - retries=3, - delay=2, - function='google_cloud_utils.batch._send_create_job_request') -def _send_create_job_request(create_request): - return _batch_client().create_job(create_request) - - -def count_queued_or_scheduled_tasks(project: str, - region: str) -> Tuple[int, int]: - """Counts the number of queued and scheduled tasks.""" - region = f'projects/{project}/locations/{region}' - jobs_filter = 'Status.State="SCHEDULED" OR Status.State="QUEUED"' - req = batch.types.ListJobsRequest(parent=region, filter=jobs_filter) - queued = 0 - scheduled = 0 - for job in _batch_client().list_jobs(request=req): - if job.status.state == batch.JobStatus.State.SCHEDULED: - scheduled += job.task_groups[0].task_count - elif job.status.state == batch.JobStatus.State.QUEUED: - queued += job.task_groups[0].task_count - return (queued, scheduled) - - -class GcpBatchClient(RemoteTaskInterface): - """A client for creating and managing jobs on the GCP Batch service. - - This client is responsible for translating ClusterFuzz task specifications - into GCP Batch jobs. It handles the configuration of the job, including - the machine type, disk size, and network settings, as well as the task - specification, which defines the container image and command to run. - """ - - def create_job(self, spec, input_urls: List[str]): - """Creates and starts a batch job from |spec| that executes all tasks. - - This method creates a new GCP Batch job with a single task group. The - task group is configured to run a containerized task for each of the - input URLs. The tasks are run in parallel, with each task having its - own VM, as defined by the TASK_COUNT_PER_NODE setting. - """ - task_group = batch.TaskGroup() - task_group.task_count = len(input_urls) - assert task_group.task_count < MAX_CONCURRENT_VMS_PER_JOB - task_environments = [ - batch.Environment(variables={'UWORKER_INPUT_DOWNLOAD_URL': input_url}) - for input_url in input_urls - ] - task_group.task_environments = task_environments - task_group.task_spec = _get_task_spec(spec) - task_group.task_count_per_node = TASK_COUNT_PER_NODE - assert task_group.task_count_per_node == 1, 'This is a security issue' - - job = batch.Job() - job.task_groups = [task_group] - job.allocation_policy = _get_allocation_policy(spec) - job.logs_policy = batch.LogsPolicy() - job.logs_policy.destination = batch.LogsPolicy.Destination.CLOUD_LOGGING - job.priority = spec.priority - - create_request = batch.CreateJobRequest() - create_request.job = job - job_name = get_job_name() - create_request.job_id = job_name - # The job's parent is the region in which the job will run - project_id = spec.project - create_request.parent = f'projects/{project_id}/locations/{spec.gce_region}' - job_result = _send_create_job_request(create_request) - logs.info(f'Created batch job id={job_name}.', spec=spec) - return job_result diff --git a/src/clusterfuzz/_internal/batch/service.py b/src/clusterfuzz/_internal/batch/service.py index be16cb6da31..c11aea0a6da 100644 --- a/src/clusterfuzz/_internal/batch/service.py +++ b/src/clusterfuzz/_internal/batch/service.py @@ -18,24 +18,169 @@ and provides a simple interface for scheduling ClusterFuzz tasks. """ import collections +import threading from typing import Dict from typing import List +from typing import Tuple +import uuid +from google.cloud import batch_v1 as batch + +from clusterfuzz._internal.base import retry from clusterfuzz._internal.base import tasks from clusterfuzz._internal.base import utils from clusterfuzz._internal.base.tasks import task_utils -from clusterfuzz._internal.batch.data_structures import BatchTask -from clusterfuzz._internal.batch.data_structures import BatchWorkloadSpec -from clusterfuzz._internal.batch.gcp import GcpBatchClient from clusterfuzz._internal.config import local_config from clusterfuzz._internal.datastore import data_types from clusterfuzz._internal.datastore import ndb_utils +from clusterfuzz._internal.google_cloud_utils import credentials from clusterfuzz._internal.metrics import logs +from clusterfuzz._internal.remote_task import RemoteTask +from clusterfuzz._internal.remote_task import RemoteTaskInterface from clusterfuzz._internal.system import environment +# A named tuple that defines the execution environment for a batch workload. +# This includes details about the machine, disk, network, and container image, +# as well as ClusterFuzz-specific settings. +BatchWorkloadSpec = collections.namedtuple('BatchWorkloadSpec', [ + 'clusterfuzz_release', + 'disk_size_gb', + 'disk_type', + 'docker_image', + 'user_data', + 'service_account_email', + 'subnetwork', + 'preemptible', + 'project', + 'machine_type', + 'network', + 'gce_region', + 'priority', + 'max_run_duration', + 'retry', +]) + # See https://cloud.google.com/batch/quotas#job_limits MAX_CONCURRENT_VMS_PER_JOB = 1000 +_local = threading.local() + +DEFAULT_RETRY_COUNT = 0 + +# Controls how many containers (ClusterFuzz tasks) can run on a single VM. +# THIS SHOULD BE 1 OR THERE WILL BE SECURITY PROBLEMS. +TASK_COUNT_PER_NODE = 1 + + +def _create_batch_client_new(): + """Creates a batch client.""" + creds, _ = credentials.get_default() + return batch.BatchServiceClient(credentials=creds) + + +def _batch_client(): + """Gets the batch client, creating it if it does not exist.""" + if hasattr(_local, 'client'): + return _local.client + + _local.client = _create_batch_client_new() + return _local.client + + +def get_job_name(): + return 'j-' + str(uuid.uuid4()).lower() + + +def _get_task_spec(batch_workload_spec): + """Gets the task spec based on the batch workload spec.""" + runnable = batch.Runnable() + runnable.container = batch.Runnable.Container() + runnable.container.image_uri = batch_workload_spec.docker_image + clusterfuzz_release = batch_workload_spec.clusterfuzz_release + runnable.container.options = ( + '--memory-swappiness=40 --shm-size=1.9g --rm --net=host ' + '-e HOST_UID=1337 -P --privileged --cap-add=all ' + f'-e CLUSTERFUZZ_RELEASE={clusterfuzz_release} ' + '--name=clusterfuzz -e UNTRUSTED_WORKER=False -e UWORKER=True ' + '-e USE_GCLOUD_STORAGE_RSYNC=1 ' + '-e UWORKER_INPUT_DOWNLOAD_URL') + runnable.container.volumes = ['/var/scratch0:/mnt/scratch0'] + task_spec = batch.TaskSpec() + task_spec.runnables = [runnable] + if batch_workload_spec.retry: + # Tasks in general have 6 hours to run (except pruning which has 24). + # Our signed URLs last 24 hours. Therefore, the maxiumum number of retries + # is 4. This is a temporary solution anyway. + task_spec.max_retry_count = 4 + else: + task_spec.max_retry_count = DEFAULT_RETRY_COUNT + task_spec.max_run_duration = batch_workload_spec.max_run_duration + return task_spec + + +def _set_preemptible(instance_policy, batch_workload_spec) -> None: + if batch_workload_spec.preemptible: + instance_policy.provisioning_model = ( + batch.AllocationPolicy.ProvisioningModel.PREEMPTIBLE) + else: + instance_policy.provisioning_model = ( + batch.AllocationPolicy.ProvisioningModel.STANDARD) + + +def _get_allocation_policy(spec): + """Returns the allocation policy for a BatchWorkloadSpec.""" + disk = batch.AllocationPolicy.Disk() + disk.image = 'batch-cos' + disk.size_gb = spec.disk_size_gb + disk.type = spec.disk_type + instance_policy = batch.AllocationPolicy.InstancePolicy() + instance_policy.boot_disk = disk + instance_policy.machine_type = spec.machine_type + _set_preemptible(instance_policy, spec) + instances = batch.AllocationPolicy.InstancePolicyOrTemplate() + instances.policy = instance_policy + + # Don't use external ip addresses which use quota, cost money, and are + # unnecessary. + network_interface = batch.AllocationPolicy.NetworkInterface() + network_interface.no_external_ip_address = True + network_interface.network = spec.network + network_interface.subnetwork = spec.subnetwork + network_interfaces = [network_interface] + network_policy = batch.AllocationPolicy.NetworkPolicy() + network_policy.network_interfaces = network_interfaces + + allocation_policy = batch.AllocationPolicy() + allocation_policy.instances = [instances] + allocation_policy.network = network_policy + service_account = batch.ServiceAccount(email=spec.service_account_email) # pylint: disable=no-member + allocation_policy.service_account = service_account + return allocation_policy + + +@retry.wrap( + retries=3, + delay=2, + function='google_cloud_utils.batch._send_create_job_request') +def _send_create_job_request(create_request): + return _batch_client().create_job(create_request) + + +def count_queued_or_scheduled_tasks(project: str, + region: str) -> Tuple[int, int]: + """Counts the number of queued and scheduled tasks.""" + region = f'projects/{project}/locations/{region}' + jobs_filter = 'Status.State="SCHEDULED" OR Status.State="QUEUED"' + req = batch.types.ListJobsRequest(parent=region, filter=jobs_filter) + queued = 0 + scheduled = 0 + for job in _batch_client().list_jobs(request=req): + if job.status.state == batch.JobStatus.State.SCHEDULED: + scheduled += job.task_groups[0].task_count + elif job.status.state == batch.JobStatus.State.QUEUED: + queued += job.task_groups[0].task_count + return (queued, scheduled) + def _get_batch_config(): """Returns the batch config. This function was made to make mocking easier.""" @@ -49,13 +194,13 @@ def is_remote_task(command: str, job_name: str) -> bool: be found for the given command and job type. """ try: - _get_specs_from_config([BatchTask(command, job_name, None)]) + _get_specs_from_config([RemoteTask(command, job_name, None)]) return True except ValueError: return False -def _get_config_names(batch_tasks: List[BatchTask]): +def _get_config_names(batch_tasks: List[RemoteTask]): """"Gets the name of the configs for each batch_task. Returns a dict that is indexed by command and job_type for efficient lookup.""" job_names = {task.job_type for task in batch_tasks} @@ -93,11 +238,6 @@ def _get_config_names(batch_tasks: List[BatchTask]): return config_map -def _get_task_duration(command): - return tasks.TASK_LEASE_SECONDS_BY_COMMAND.get(command, - tasks.TASK_LEASE_SECONDS) - - WeightedSubconfig = collections.namedtuple('WeightedSubconfig', ['name', 'weight']) @@ -114,7 +254,7 @@ def _get_subconfig(batch_config, instance_spec): return all_subconfigs[weighted_subconfig.name] -def _get_specs_from_config(batch_tasks) -> Dict: +def _get_specs_from_config(batch_tasks: List[RemoteTask]) -> Dict: """Gets the configured specifications for a batch workload.""" if not batch_tasks: return {} @@ -148,7 +288,7 @@ def _get_specs_from_config(batch_tasks) -> Dict: # Lower numbers are a lower priority, meaning less likely to run From: # https://cloud.google.com/batch/docs/reference/rest/v1/projects.locations.jobs priority = 0 if task.command == 'fuzz' else 1 - max_run_duration = f'{_get_task_duration(task.command)}s' + max_run_duration = f'{tasks.get_task_duration(task.command)}s' # This saves us time and reduces fragementation, e.g. every linux fuzz task # run in this call will run in the same zone. if config_name not in subconfig_map: @@ -182,7 +322,7 @@ def _get_specs_from_config(batch_tasks) -> Dict: return specs -class BatchService: +class GcpBatchService(RemoteTaskInterface): """A high-level service for creating and managing remote tasks. This service provides a simple interface for scheduling ClusterFuzz tasks on @@ -190,20 +330,55 @@ class BatchService: provides a way to check if a task is configured to run remotely. """ - def __init__(self): - self._client = GcpBatchClient() + def create_job(self, spec: BatchWorkloadSpec, input_urls: List[str]): + """Creates and starts a batch job from |spec| that executes all tasks. + + This method creates a new GCP Batch job with a single task group. The + task group is configured to run a containerized task for each of the + input URLs. The tasks are run in parallel, with each task having its + own VM, as defined by the TASK_COUNT_PER_NODE setting. + """ + task_group = batch.TaskGroup() + task_group.task_count = len(input_urls) + assert task_group.task_count < MAX_CONCURRENT_VMS_PER_JOB + task_environments = [ + batch.Environment(variables={'UWORKER_INPUT_DOWNLOAD_URL': input_url}) + for input_url in input_urls + ] + task_group.task_environments = task_environments + task_group.task_spec = _get_task_spec(spec) + task_group.task_count_per_node = TASK_COUNT_PER_NODE + assert task_group.task_count_per_node == 1, 'This is a security issue' + + job = batch.Job() + job.task_groups = [task_group] + job.allocation_policy = _get_allocation_policy(spec) + job.logs_policy = batch.LogsPolicy() + job.logs_policy.destination = batch.LogsPolicy.Destination.CLOUD_LOGGING + job.priority = spec.priority + + create_request = batch.CreateJobRequest() + create_request.job = job + job_name = get_job_name() + create_request.job_id = job_name + # The job's parent is the region in which the job will run + project_id = spec.project + create_request.parent = f'projects/{project_id}/locations/{spec.gce_region}' + job_result = _send_create_job_request(create_request) + logs.info(f'Created batch job id={job_name}.', spec=spec) + return job_result def create_uworker_main_batch_job(self, module: str, job_type: str, input_download_url: str): """Creates a single batch job for a uworker main task.""" command = task_utils.get_command_from_module(module) - batch_tasks = [BatchTask(command, job_type, input_download_url)] + batch_tasks = [RemoteTask(command, job_type, input_download_url)] result = self.create_uworker_main_batch_jobs(batch_tasks) if result is None: return result return result[0] - def create_uworker_main_batch_jobs(self, batch_tasks: List[BatchTask]): + def create_uworker_main_batch_jobs(self, remote_tasks: List[RemoteTask]): """Creates a batch job for a list of uworker main tasks. This method groups the tasks by their workload specification and creates a @@ -211,11 +386,11 @@ def create_uworker_main_batch_jobs(self, batch_tasks: List[BatchTask]): requirements to be processed together, which can improve efficiency. """ job_specs = collections.defaultdict(list) - specs = _get_specs_from_config(batch_tasks) - for batch_task in batch_tasks: - logs.info(f'Scheduling {batch_task.command}, {batch_task.job_type}.') - spec = specs[(batch_task.command, batch_task.job_type)] - job_specs[spec].append(batch_task.input_download_url) + specs = _get_specs_from_config(remote_tasks) + for remote_task in remote_tasks: + logs.info(f'Scheduling {remote_task.command}, {remote_task.job_type}.') + spec = specs[(remote_task.command, remote_task.job_type)] + job_specs[spec].append(remote_task.input_download_url) logs.info('Creating batch jobs.') jobs = [] @@ -224,6 +399,6 @@ def create_uworker_main_batch_jobs(self, batch_tasks: List[BatchTask]): for spec, input_urls in job_specs.items(): for input_urls_portion in utils.batched(input_urls, MAX_CONCURRENT_VMS_PER_JOB - 1): - jobs.append(self._client.create_job(spec, input_urls_portion)) + jobs.append(self.create_job(spec, input_urls_portion).name) return jobs diff --git a/src/clusterfuzz/_internal/bot/tasks/task_types.py b/src/clusterfuzz/_internal/bot/tasks/task_types.py index de3e0d01364..7b3324f1cf6 100644 --- a/src/clusterfuzz/_internal/bot/tasks/task_types.py +++ b/src/clusterfuzz/_internal/bot/tasks/task_types.py @@ -225,7 +225,7 @@ def execute(self, task_argument, job_type, uworker_env): 'analyze': UTask, 'blame': TrustedTask, 'corpus_pruning': UTask, - 'fuzz': UTaskLocalExecutor, + 'fuzz': UTask, 'impact': TrustedTask, 'minimize': UTask, 'progression': UTask, diff --git a/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py b/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py index cbb6538a34b..6c1266a7ef9 100644 --- a/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py +++ b/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py @@ -461,6 +461,7 @@ def clamp(val, minimum, maximum): 'return_code': return_code, 'platform': environment.platform(), 'job': job_type, + 'runtime': environment.get_runtime().value }) @@ -480,20 +481,26 @@ def _track_testcase_run_result(fuzzer, job_type, new_crash_count, known_crash_count, { 'fuzzer': fuzzer, 'platform': environment.platform(), + 'runtime': environment.get_runtime().value }) monitoring_metrics.FUZZER_NEW_CRASH_COUNT.increment_by( new_crash_count, { 'fuzzer': fuzzer, 'platform': environment.platform(), + 'runtime': environment.get_runtime().value + }) + monitoring_metrics.JOB_KNOWN_CRASH_COUNT.increment_by( + known_crash_count, { + 'job': job_type, + 'platform': environment.platform(), + 'runtime': environment.get_runtime().value + }) + monitoring_metrics.JOB_NEW_CRASH_COUNT.increment_by( + new_crash_count, { + 'job': job_type, + 'platform': environment.platform(), + 'runtime': environment.get_runtime().value }) - monitoring_metrics.JOB_KNOWN_CRASH_COUNT.increment_by(known_crash_count, { - 'job': job_type, - 'platform': environment.platform(), - }) - monitoring_metrics.JOB_NEW_CRASH_COUNT.increment_by(new_crash_count, { - 'job': job_type, - 'platform': environment.platform() - }) def _last_sync_time(sync_file_path): @@ -2020,7 +2027,8 @@ def run(self): fuzzing_session_duration, { 'fuzzer': self.fuzzer_name, 'job': self.job_type, - 'platform': environment.platform() + 'platform': environment.platform(), + 'runtime': environment.get_runtime().value, }) return uworker_msg_pb2.Output(fuzz_task_output=self.fuzz_task_output) # pylint: disable=no-member diff --git a/src/clusterfuzz/_internal/cron/schedule_fuzz.py b/src/clusterfuzz/_internal/cron/schedule_fuzz.py index 0a296970727..d003b47ee6a 100644 --- a/src/clusterfuzz/_internal/cron/schedule_fuzz.py +++ b/src/clusterfuzz/_internal/cron/schedule_fuzz.py @@ -25,7 +25,7 @@ from clusterfuzz._internal.base import tasks from clusterfuzz._internal.base import utils -from clusterfuzz._internal.batch import gcp as batch +from clusterfuzz._internal.batch import service as batch from clusterfuzz._internal.config import local_config from clusterfuzz._internal.datastore import data_types from clusterfuzz._internal.datastore import ndb_utils diff --git a/src/clusterfuzz/_internal/datastore/data_types.py b/src/clusterfuzz/_internal/datastore/data_types.py index 4e5af47dc24..3008c21e8f5 100644 --- a/src/clusterfuzz/_internal/datastore/data_types.py +++ b/src/clusterfuzz/_internal/datastore/data_types.py @@ -1803,3 +1803,10 @@ class FuzzerTaskEvent(Model): def _pre_put_hook(self): self.ttl_expiry_timestamp = ( datetime.datetime.now() + self.FUZZER_EVENT_TTL) + + +class FeatureFlag(Model): + """Feature flag.""" + description = ndb.StringProperty(default='') + enabled = ndb.BooleanProperty(default=False) + value = ndb.FloatProperty() diff --git a/src/clusterfuzz/_internal/datastore/feature_flags.py b/src/clusterfuzz/_internal/datastore/feature_flags.py new file mode 100644 index 00000000000..5ab29075631 --- /dev/null +++ b/src/clusterfuzz/_internal/datastore/feature_flags.py @@ -0,0 +1,61 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""FeatureFlags.""" + +from enum import Enum + +from google.cloud import ndb + +from clusterfuzz._internal.datastore import data_types + + +class FeatureFlags(Enum): + """Feature flags""" + # Example flag. + TEST_FLAG = 'test_flag' + TEST_FLOAT_FLAG = 'test_float_flag' + + K8S_JOBS_FREQUENCY = 'k8s_jobs_frequency' + + @property + def flag(self): + """Get a feature flag.""" + flag = ndb.Key(data_types.FeatureFlag, self.value).get() + if not flag: + return None + return flag + + @property + def enabled(self): + """Check if a feature flag is enabled.""" + flag = self.flag + if not flag: + return False + return flag.enabled + + @property + def content(self): + """Get a feature flag value.""" + flag = self.flag + if not flag or flag.value is None: + return None + return flag.value + + @property + def description(self): + """Get a feature flag value.""" + flag = self.flag + if not flag or flag.description is None: + return "" + return flag.description diff --git a/src/clusterfuzz/_internal/datastore/ndb_init.py b/src/clusterfuzz/_internal/datastore/ndb_init.py index 30840c44362..c91e5c45bad 100644 --- a/src/clusterfuzz/_internal/datastore/ndb_init.py +++ b/src/clusterfuzz/_internal/datastore/ndb_init.py @@ -51,16 +51,21 @@ def context(): # multiprocessing.set_start_method to not fork. context_module._state.context = None # pylint: disable=protected-access - with _client().context() as ndb_context: - # Disable NDB caching, as NDB on GCE VMs do not use memcache and therefore - # can't invalidate the memcache cache. - ndb_context.set_memcache_policy(False) + current_context = context_module.get_context(False) + if current_context: + yield current_context - # Disable the in-context cache, as it can use up a lot of memory for - # longer running tasks such as cron jobs. - ndb_context.set_cache_policy(False) + else: + with _client().context() as ndb_context: + # Disable NDB caching, as NDB on GCE VMs do not use memcache and therefore + # can't invalidate the memcache cache. + ndb_context.set_memcache_policy(False) - yield ndb_context + # Disable the in-context cache, as it can use up a lot of memory for + # longer running tasks such as cron jobs. + ndb_context.set_cache_policy(False) + + yield ndb_context def thread_wrapper(func): diff --git a/src/clusterfuzz/_internal/google_cloud_utils/batch.py b/src/clusterfuzz/_internal/google_cloud_utils/batch.py deleted file mode 100644 index e804044cef8..00000000000 --- a/src/clusterfuzz/_internal/google_cloud_utils/batch.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Cloud Batch helpers.""" -from typing import List - -from clusterfuzz._internal.batch.data_structures import BatchTask -from clusterfuzz._internal.batch.service import BatchService - - -def create_uworker_main_batch_job(module, job_type, input_download_url): - """Creates a batch job.""" - service = BatchService() - return service.create_uworker_main_batch_job(module, job_type, - input_download_url) - - -def create_uworker_main_batch_jobs(batch_tasks: List[BatchTask]): - """Creates batch jobs.""" - service = BatchService() - return service.create_uworker_main_batch_jobs(batch_tasks) diff --git a/src/clusterfuzz/_internal/k8s/BUILD.bazel b/src/clusterfuzz/_internal/k8s/BUILD.bazel new file mode 100644 index 00000000000..966dd5249b2 --- /dev/null +++ b/src/clusterfuzz/_internal/k8s/BUILD.bazel @@ -0,0 +1,23 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package(default_visibility = ["//src:__subpackages__"]) + +py_library( + name = "service", + srcs = ["service.py"], + deps = [ + "//src/clusterfuzz/_internal/remote_task", + ], +) diff --git a/src/clusterfuzz/_internal/k8s/__init__.py b/src/clusterfuzz/_internal/k8s/__init__.py new file mode 100644 index 00000000000..605c2708985 --- /dev/null +++ b/src/clusterfuzz/_internal/k8s/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Kubernetes service.""" diff --git a/src/clusterfuzz/_internal/k8s/delete_pending_jobs.sh b/src/clusterfuzz/_internal/k8s/delete_pending_jobs.sh new file mode 100644 index 00000000000..05b93f60b02 --- /dev/null +++ b/src/clusterfuzz/_internal/k8s/delete_pending_jobs.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Script to delete pending Kubernetes jobs in batches. + +BATCH_SIZE=1000 +NAMESPACE="default" + +echo "Listing pending jobs in namespace '${NAMESPACE}'..." + +# Get list of pending jobs (completions usually 0/1) +# We assume pending jobs have '0/1' in the COMPLETIONS column (2nd column usually). +# Adjust awk if your kubectl output differs. +# Safer: check json output. But for a quick script: +# kubectl get jobs -o wide +# NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR +# job1 0/1 10s 10s ... ... ... + +# Using -o custom-columns to be sure about the column content +# We select jobs where status.succeeded is not equal to status.completions (or null) +# But filtering logic in bash is easier with just listing names of incomplete jobs. +# Pending jobs have .status.succeeded != 1 (assuming parallelism 1). + +# Let's get all jobs and filter those with 0 completions. +JOBS=$(kubectl get jobs -n "${NAMESPACE}" -o jsonpath='{range .items[?(@.status.succeeded!=1)]}{.metadata.name}{"\n"}{end}') + +if [ -z "$JOBS" ]; then + echo "No pending jobs found." + exit 0 +fi + +JOB_COUNT=$(echo "$JOBS" | wc -l) +echo "Found ${JOB_COUNT} pending jobs." + +# Process in batches +echo "$JOBS" | xargs -n "${BATCH_SIZE}" sh -c ' + echo "Deleting batch of jobs..." + kubectl delete jobs -n "'""${NAMESPACE}""'" --propagation=Background "$@" +' -- + +echo "Finished deleting pending jobs." diff --git a/src/clusterfuzz/_internal/k8s/service.py b/src/clusterfuzz/_internal/k8s/service.py new file mode 100644 index 00000000000..a2d22da9f7e --- /dev/null +++ b/src/clusterfuzz/_internal/k8s/service.py @@ -0,0 +1,505 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Kubernetes batch client.""" +import base64 +import collections +import os +import tempfile +from typing import Dict +from typing import List +import uuid + +import google.auth +from google.auth.transport import requests as google_requests +from googleapiclient import discovery +from kubernetes import client as k8s_client + +from clusterfuzz._internal.base import tasks +from clusterfuzz._internal.base import utils +from clusterfuzz._internal.base.tasks import task_utils +from clusterfuzz._internal.config import local_config +from clusterfuzz._internal.datastore import data_types +from clusterfuzz._internal.datastore import ndb_utils +from clusterfuzz._internal.metrics import logs +from clusterfuzz._internal.remote_task import RemoteTask +from clusterfuzz._internal.remote_task import RemoteTaskInterface +from clusterfuzz._internal.system import environment + +# See https://cloud.google.com/batch/quotas#job_limits +MAX_PENDING_JOBS = 1000 +CLUSTER_NAME = 'clusterfuzz-cronjobs-gke' + +KubernetesJobConfig = collections.namedtuple('KubernetesJobConfig', [ + 'job_type', + 'docker_image', + 'command', + 'disk_size_gb', + 'service_account_email', + 'clusterfuzz_release', + 'is_kata', +]) + + +def _get_config_names(remote_tasks: List[RemoteTask]): + """"Gets the name of the configs for each batch_task. Returns a dict + + that is indexed by command and job_type for efficient lookup.""" + + job_names = {task.job_type for task in remote_tasks} + query = data_types.Job.query(data_types.Job.name.IN(list(job_names))) + jobs = ndb_utils.get_all_from_query(query) + job_map = {job.name: job for job in jobs} + config_map = {} + for task in remote_tasks: + if task.job_type not in job_map: + logs.error(f"{task.job_type} doesn't exist.") + continue + if task.command == 'fuzz': + suffix = '-PREEMPTIBLE-UNPRIVILEGED' + else: + suffix = '-NONPREEMPTIBLE-UNPRIVILEGED' + job = job_map[task.job_type] + platform = job.platform if not utils.is_oss_fuzz() else 'LINUX' + disk_size_gb = environment.get_value( + 'DISK_SIZE_GB', env=job.get_environment()) + # Get the OS version from the job, this is the least specific version. + base_os_version = job.base_os_version + # If we are running in the oss-fuzz context, the project-specific config + # is more specific and overrides the job-level one. + if utils.is_oss_fuzz(): + oss_fuzz_project = data_types.OssFuzzProject.query( + data_types.OssFuzzProject.name == job.project).get() + if oss_fuzz_project and oss_fuzz_project.base_os_version: + base_os_version = oss_fuzz_project.base_os_version + config_map[(task.command, task.job_type)] = (f'{platform}{suffix}', + disk_size_gb, base_os_version) + + return config_map + + +def _get_k8s_job_configs(remote_tasks: List[RemoteTask]) -> Dict: + """Gets the configured specifications for a batch workload.""" + + if not remote_tasks: + return {} + #TODO(javanlacerda): Create remote task config + batch_config = local_config.BatchConfig() + config_map = _get_config_names(remote_tasks) + configs = {} + for task in remote_tasks: + if (task.command, task.job_type) in configs: + # Don't repeat work for no reason. + continue + config_name, disk_size_gb, base_os_version = config_map[(task.command, + task.job_type)] + instance_spec = batch_config.get('mapping').get(config_name) + if instance_spec is None: + raise ValueError(f'No mapping for {config_name}') + # Decide which docker image to use. + versioned_images_map = instance_spec.get('versioned_docker_images') + if (base_os_version and versioned_images_map and + base_os_version in versioned_images_map): + # New path: Use the versioned image if specified and available. + docker_image_uri = versioned_images_map[base_os_version] + else: + # Fallback/legacy path: Use the original docker_image key. + docker_image_uri = instance_spec['docker_image'] + disk_size_gb = (disk_size_gb or instance_spec['disk_size_gb']) + clusterfuzz_release = instance_spec.get('clusterfuzz_release', 'prod') + config = KubernetesJobConfig( + job_type=task.job_type, + docker_image=docker_image_uri, + command=task.command, + disk_size_gb=disk_size_gb, + service_account_email=instance_spec['service_account_email'], + clusterfuzz_release=clusterfuzz_release, + is_kata=instance_spec.get('is_kata', True), + ) + configs[(task.command, task.job_type)] = config + + return configs + + +def _create_job_body(config: KubernetesJobConfig, input_url: str, + service_account_name: str) -> dict: + """Creates the body of a Kubernetes job.""" + + job_name = config.job_type.replace('_', '-') + '-' + str(uuid.uuid4()).split( + '-', maxsplit=1)[0] + job_name = job_name.lower() + # Default job spec for non-kata containers (needs to be defined). + return { + 'apiVersion': 'batch/v1', + 'kind': 'Job', + 'metadata': { + 'name': job_name + }, + 'spec': { + 'activeDeadlineSeconds': tasks.get_task_duration(config.command), + 'template': { + 'spec': { + 'serviceAccountName': + service_account_name, + 'containers': [{ + 'name': + job_name, + 'image': + config.docker_image, + 'imagePullPolicy': + 'IfNotPresent', + 'env': [ + { + 'name': 'HOST_UID', + 'value': '1337' + }, + { + 'name': 'CLUSTERFUZZ_RELEASE', + 'value': config.clusterfuzz_release + }, + { + 'name': 'UNTRUSTED_WORKER', + 'value': 'False' + }, + { + 'name': 'UWORKER', + 'value': 'True' + }, + { + 'name': 'USE_GCLOUD_STORAGE_RSYNC', + 'value': '1' + }, + { + 'name': 'UWORKER_INPUT_DOWNLOAD_URL', + 'value': input_url + }, + { + 'name': 'IS_K8S_ENV', + 'value': 'true' + }, + { + 'name': 'DISABLE_MOUNTS', + 'value': 'true' + }, + { + 'name': 'UPDATE_WEB_TESTS', + 'value': 'False' + }, + ], + 'securityContext': { + 'privileged': True, + 'capabilities': { + 'add': ['ALL'] + } + }, + 'volumeMounts': [{ + 'mountPath': '/dev/shm', + 'name': 'dshm' + }] + }], + 'volumes': [{ + 'name': 'dshm', + 'emptyDir': { + 'medium': 'Memory', + 'sizeLimit': '1.9Gi' + } + }], + 'restartPolicy': + 'Never' + } + }, + 'backoffLimit': 0 + } + } + + +class KubernetesService(RemoteTaskInterface): + """A remote task execution client for Kubernetes.""" + + def __init__(self, k8s_config_loaded: bool = False): + # In e2e tests, the kubeconfig is already loaded by the test setup. + if not k8s_config_loaded: + self._load_gke_credentials() + + self._core_api = k8s_client.CoreV1Api() + self._batch_api = k8s_client.BatchV1Api() + + def _load_gke_credentials(self): + """Loads GKE credentials and configures the Kubernetes client.""" + credentials, _ = google.auth.default() + project = utils.get_application_id() + print(f"DEBUG: project from utils.get_application_id(): {project}") + service = discovery.build('container', 'v1', credentials=credentials) + parent = f"projects/{project}/locations/-" + + try: + response = service.projects().locations().clusters().list( + parent=parent).execute() + clusters = response.get('clusters', []) + cluster = next((c for c in clusters if c['name'] == CLUSTER_NAME), None) + + if not cluster: + logs.error(f"Cluster {CLUSTER_NAME} not found in project {project}.") + print(f"DEBUG: Cluster {CLUSTER_NAME} not found in project {project}.") + return + + except Exception as e: + logs.error(f"Failed to list clusters in {project}: {e}") + print(f"DEBUG: Failed to list clusters in {project}: {e}") + return + + endpoint = cluster['endpoint'] + # ca_cert is base64 encoded. + ca_cert = base64.b64decode(cluster['masterAuth']['clusterCaCertificate']) + + # Write CA cert to a temporary file. + fd, ca_cert_path = tempfile.mkstemp() + with os.fdopen(fd, 'wb') as f: + f.write(ca_cert) + + configuration = k8s_client.Configuration() + configuration.host = f'https://{endpoint}' + configuration.ssl_ca_cert = ca_cert_path + configuration.verify_ssl = True + + def get_token(creds): + request = google_requests.Request() + if not creds.valid or creds.expired: + creds.refresh(request) + return {"authorization": "Bearer " + creds.token} + + configuration.refresh_api_key_hook = lambda _: get_token(credentials) + configuration.api_key = get_token(credentials) + + k8s_client.Configuration.set_default(configuration) + logs.info("GKE credentials loaded successfully.") + + def _create_service_account_if_needed(self, + service_account_email: str) -> str: + """Creates a Kubernetes Service Account if it doesn't exist.""" + service_account_name = service_account_email.split('@')[0] + namespace = 'default' + try: + self._core_api.read_namespaced_service_account(service_account_name, + namespace) + return service_account_name + except k8s_client.rest.ApiException as e: + if e.status != 404: + raise + + logs.info(f'Creating Service Account {service_account_name} for ' + f'{service_account_email}.') + metadata = k8s_client.V1ObjectMeta( + name=service_account_name, + annotations={'iam.gke.io/gcp-service-account': service_account_email}) + body = k8s_client.V1ServiceAccount(metadata=metadata) + self._core_api.create_namespaced_service_account(namespace, body) + return service_account_name + + def create_job(self, config: KubernetesJobConfig, input_url: str) -> str: + """Creates a Kubernetes job. + Args: + config: The Kubernetes job configuration. + input_url: The URL to be passed as an environment variable to the + job's container. + Returns: + The name of the created Kubernetes job. + """ + service_account_name = self._create_service_account_if_needed( + config.service_account_email) + job_body = _create_job_body(config, input_url, service_account_name) + self._batch_api.create_namespaced_job(body=job_body, namespace='default') + return job_body['metadata']['name'] + + def _get_pending_jobs_count(self) -> int: + """Returns the number of pending jobs.""" + try: + pods = self._core_api.list_namespaced_pod( + namespace='default', + label_selector='app.kubernetes.io/name=clusterfuzz-kata-job', + field_selector='status.phase=Pending') + logs.info(f"Found {len(pods.items)} pending jobs.") + return len(pods.items) + except Exception as e: + logs.error(f"Failed to list pods: {e}") + return 0 + + def create_uworker_main_batch_job(self, module: str, job_type: str, + input_download_url: str): + """Creates a single batch job for a uworker main task.""" + + command = task_utils.get_command_from_module(module) + batch_tasks = [RemoteTask(command, job_type, input_download_url)] + result = self.create_uworker_main_batch_jobs(batch_tasks) + + if result is None: + return result + return result[0] + + def create_uworker_main_batch_jobs(self, remote_tasks: List[RemoteTask]): + """Creates a batch job for a list of uworker main tasks. + + This method groups the tasks by their workload specification and creates a + separate batch job for each group. This allows tasks with similar + requirements to be processed together, which can improve efficiency. + """ + if self._get_pending_jobs_count() >= MAX_PENDING_JOBS: + logs.warning( + f'Kubernetes job limit reached. Not acking {len(remote_tasks)} tasks.' + ) + for task in remote_tasks: + if task.pubsub_task: + task.pubsub_task.do_not_ack = True + return [] + + job_specs = collections.defaultdict(list) + configs = _get_k8s_job_configs(remote_tasks) + for remote_task in remote_tasks: + logs.info(f'Scheduling {remote_task.command}, {remote_task.job_type}.') + config = configs[(remote_task.command, remote_task.job_type)] + job_specs[config].append(remote_task.input_download_url) + logs.info('Creating batch jobs.') + jobs = [] + logs.info('Batching utask_mains.') + for config, input_urls in job_specs.items(): + # TODO(javanlacerda): Batch multiple tasks into a single job. + for input_url in input_urls: + if config.is_kata: + jobs.append(self.create_kata_container_job(config, input_url)) + else: + jobs.append(self.create_job(config, input_url)) + + return jobs + + def create_kata_container_job(self, config: KubernetesJobConfig, + input_url: str) -> str: + """Creates a Kubernetes job that runs in a Kata container.""" + service_account_name = self._create_service_account_if_needed( + config.service_account_email) + job_name = 'clusterfuzz-kata-job-' + str(uuid.uuid4()).split( + '-', maxsplit=1)[0] + + job_spec = { + 'apiVersion': 'batch/v1', + 'kind': 'Job', + 'metadata': { + 'name': job_name + }, + 'spec': { + 'activeDeadlineSeconds': tasks.get_task_duration(config.command), + 'template': { + 'metadata': { + 'labels': { + 'app.kubernetes.io/name': 'clusterfuzz-kata-job' + } + }, + 'spec': { + 'runtimeClassName': + 'kata', + 'serviceAccountName': + service_account_name, + 'dnsPolicy': + 'ClusterFirstWithHostNet', + 'containers': [{ + 'name': + job_name, + 'image': + config.docker_image, + 'imagePullPolicy': + 'IfNotPresent', + 'lifecycle': { + 'postStart': { + 'exec': { + 'command': [ + '/bin/sh', '-c', + 'mkdir -p /tmp/.X11-unix && ' + 'chmod 1777 /tmp/.X11-unix' + ] + } + } + }, + 'securityContext': { + 'privileged': True, + 'capabilities': { + 'add': ['ALL'] + } + }, + 'resources': { + 'requests': { + 'cpu': '2', + 'memory': '3.75Gi' + }, + 'limits': { + 'cpu': '2', + 'memory': '3.75Gi' + } + }, + 'env': [ + { + 'name': 'HOST_UID', + 'value': '1337' + }, + { + 'name': 'CLUSTERFUZZ_RELEASE', + 'value': config.clusterfuzz_release + }, + { + 'name': 'UNTRUSTED_WORKER', + 'value': 'False' + }, + { + 'name': 'UWORKER', + 'value': 'True' + }, + { + 'name': 'USE_GCLOUD_STORAGE_RSYNC', + 'value': '1' + }, + { + 'name': 'UWORKER_INPUT_DOWNLOAD_URL', + 'value': input_url + }, + { + 'name': 'IS_K8S_ENV', + 'value': 'true' + }, + { + 'name': 'DISABLE_MOUNTS', + 'value': 'true' + }, + { + 'name': 'UPDATE_WEB_TESTS', + 'value': 'False' + }, + ] + }], + 'restartPolicy': + 'Never', + 'volumes': [{ + 'name': 'dshm', + 'emptyDir': { + 'medium': 'Memory', + 'sizeLimit': '1.9Gi' + } + }], + 'nodeSelector': { + 'cloud.google.com/gke-nodepool': 'kata-enabled-pool' + } + } + }, + 'backoffLimit': 0 + } + } + + self._batch_api.create_namespaced_job(body=job_spec, namespace='default') + return job_name diff --git a/src/clusterfuzz/_internal/metrics/logs.py b/src/clusterfuzz/_internal/metrics/logs.py index cc77185abfa..bc25979e6c1 100644 --- a/src/clusterfuzz/_internal/metrics/logs.py +++ b/src/clusterfuzz/_internal/metrics/logs.py @@ -429,42 +429,60 @@ def configure_appengine(): def configure_k8s(): - """Configure logging for K8S and reporting errors.""" + """Configure logging for K8S.""" import google.cloud.logging + from google.cloud.logging.handlers import CloudLoggingHandler + from google.cloud.logging.handlers.transports import BackgroundThreadTransport + client = google.cloud.logging.Client() - client.setup_logging() - old_factory = logging.getLogRecordFactory() - - def record_factory(*args, **kwargs): - """Insert jsonPayload fields to all logs.""" - - record = old_factory(*args, **kwargs) - if not hasattr(record, 'json_fields'): - record.json_fields = {} - - # Add jsonPayload fields to logs that don't contain stack traces to enable - # capturing and grouping by error reporting. - # https://cloud.google.com/error-reporting/docs/formatting-error-messages#log-text - if record.levelno >= logging.ERROR and not record.exc_info: - record.json_fields.update({ - '@type': - 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent', # pylint: disable=line-too-long - 'serviceContext': { - 'service': 'k8s', - }, - 'context': { - 'reportLocation': { - 'filePath': record.pathname, - 'lineNumber': record.lineno, - 'functionName': record.funcName, - } - }, - }) - - return record - - logging.setLogRecordFactory(record_factory) - logging.getLogger().addFilter(json_fields_filter) + labels = { + 'k8s-pod/app': os.getenv('BOT_NAME', 'unknown'), + 'bot_name': os.getenv('BOT_NAME', 'unknown'), + } + + class FlushIntervalTransport(BackgroundThreadTransport): + + def __init__(self, client, name, **kwargs): + super().__init__( + client, + name, + grace_period=int(os.getenv('LOGGING_CLOUD_GRACE_PERIOD', '15')), + max_latency=int(os.getenv('LOGGING_CLOUD_MAX_LATENCY', '10')), + **kwargs) + + handler = CloudLoggingHandler( + client=client, + name='k8s-logs', + labels=labels, + transport=FlushIntervalTransport) + + def k8s_label_filter(record): + handler.labels.update({ + 'task_payload': + os.getenv('TASK_PAYLOAD', 'null'), + 'fuzz_target': + os.getenv('FUZZ_TARGET', 'null'), + 'worker_bot_name': + os.getenv('WORKER_BOT_NAME', 'null'), + 'extra': + truncate( + json.dumps( + getattr(record, 'extras', {}), + default=_handle_unserializable), + STACKDRIVER_LOG_MESSAGE_LIMIT), + 'location': + json.dumps( + getattr(record, 'location', {'Error': True}), + default=_handle_unserializable), + }) + return True + + handler.addFilter(k8s_label_filter) + handler.setLevel(logging.INFO) + formatter = JsonFormatter() + handler.setFormatter(formatter) + + logging.getLogger().addHandler(handler) logging.getLogger().setLevel(logging.INFO) diff --git a/src/clusterfuzz/_internal/metrics/monitoring_metrics.py b/src/clusterfuzz/_internal/metrics/monitoring_metrics.py index d28000378f4..d1272693734 100644 --- a/src/clusterfuzz/_internal/metrics/monitoring_metrics.py +++ b/src/clusterfuzz/_internal/metrics/monitoring_metrics.py @@ -97,6 +97,7 @@ field_spec=[ monitor.StringField('fuzzer'), monitor.StringField('platform'), + monitor.StringField('runtime') ]) FUZZER_NEW_CRASH_COUNT = monitor.CounterMetric( @@ -106,6 +107,7 @@ field_spec=[ monitor.StringField('fuzzer'), monitor.StringField('platform'), + monitor.StringField('runtime') ]) JOB_KNOWN_CRASH_COUNT = monitor.CounterMetric( @@ -115,6 +117,7 @@ field_spec=[ monitor.StringField('job'), monitor.StringField('platform'), + monitor.StringField('runtime') ]) JOB_NEW_CRASH_COUNT = monitor.CounterMetric( @@ -124,6 +127,7 @@ field_spec=[ monitor.StringField('job'), monitor.StringField('platform'), + monitor.StringField('runtime') ]) FUZZER_RETURN_CODE_COUNT = monitor.CounterMetric( @@ -135,6 +139,7 @@ monitor.IntegerField('return_code'), monitor.StringField('platform'), monitor.StringField('job'), + monitor.StringField('runtime') ], ) @@ -163,6 +168,7 @@ monitor.StringField('fuzzer'), monitor.StringField('job'), monitor.StringField('platform'), + monitor.StringField('runtime') ], ) diff --git a/src/clusterfuzz/_internal/platforms/kubernetes/BUILD.bazel b/src/clusterfuzz/_internal/platforms/kubernetes/BUILD.bazel new file mode 100644 index 00000000000..249dd0ec2dd --- /dev/null +++ b/src/clusterfuzz/_internal/platforms/kubernetes/BUILD.bazel @@ -0,0 +1,15 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package(default_visibility = ["//src:__subpackages__"]) diff --git a/src/clusterfuzz/_internal/platforms/kubernetes/__init__.py b/src/clusterfuzz/_internal/platforms/kubernetes/__init__.py new file mode 100644 index 00000000000..f74b38a1320 --- /dev/null +++ b/src/clusterfuzz/_internal/platforms/kubernetes/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Kubernetes platform specific code.""" diff --git a/src/clusterfuzz/_internal/remote_task/__init__.py b/src/clusterfuzz/_internal/remote_task/__init__.py index 25a47f021d2..a6bdfd20140 100644 --- a/src/clusterfuzz/_internal/remote_task/__init__.py +++ b/src/clusterfuzz/_internal/remote_task/__init__.py @@ -19,6 +19,27 @@ the task creation logic to a specific implementation. """ import abc +import collections +import random +from typing import List + +from clusterfuzz._internal.metrics import logs +from clusterfuzz._internal.remote_task import job_frequency + + +class RemoteTask: + """Represents a single ClusterFuzz task to be executed on a remote worker. + + This class holds the necessary information to execute a ClusterFuzz command, + such as 'fuzz' or 'progression', in a remote environment like GCP Batch. It + is used to enqueue tasks and track their state. + """ + + def __init__(self, command, job_type, input_download_url, pubsub_task=None): + self.command = command + self.job_type = job_type + self.input_download_url = input_download_url + self.pubsub_task = pubsub_task class RemoteTaskInterface(abc.ABC): @@ -30,11 +51,88 @@ class RemoteTaskInterface(abc.ABC): """ @abc.abstractmethod - def create_job(self, spec, input_urls): - """Creates a remote job. + def create_uworker_main_batch_job(self, module: str, job_type: str, + input_download_url: str): + """Creates a single remote task for a uworker main task.""" + raise NotImplementedError + + @abc.abstractmethod + def create_uworker_main_batch_jobs(self, remote_tasks: List[RemoteTask]): + """Creates a many remote tasks for uworker main tasks.""" + raise NotImplementedError + + +class RemoteTaskGate(RemoteTaskInterface): + """A gatekeeper for remote task execution. + + This class is responsible for choosing the remote execution backend (GCP Batch + or Kubernetes) for a given task, based on the configured frequencies in the + `job_frequency` module. + """ + + def __init__(self): + from clusterfuzz._internal.batch.service import GcpBatchService + from clusterfuzz._internal.k8s.service import KubernetesService + self._gcp_batch_service = GcpBatchService() + self._kubernetes_service = KubernetesService() + + def _should_use_kubernetes(self) -> bool: + """Determines whether to use the Kubernetes backend for a given job. - This method is responsible for creating a new job in the remote execution - environment. It takes a workload specification and a list of input URLs, - and returns a representation of the created job. + The decision is made based on a random roll and the configured frequency + for the given job type. """ - raise NotImplementedError + frequencies = job_frequency.get_job_frequency() + return random.random() < frequencies['kubernetes'] + + def create_uworker_main_batch_job(self, module: str, job_type: str, + input_download_url: str): + """Creates a batch job on either GCP Batch or Kubernetes. + + The choice of backend is determined by the `_should_use_kubernetes` method. + """ + if self._should_use_kubernetes(job_type): + return self._kubernetes_service.create_uworker_main_batch_job( + module, job_type, input_download_url) + return self._gcp_batch_service.create_uworker_main_batch_job( + module, job_type, input_download_url) + + def create_uworker_main_batch_jobs(self, remote_tasks: List[RemoteTask]): + """Creates batch jobs on either GCP Batch or Kubernetes. + + The tasks are grouped by their target backend (GCP Batch or Kubernetes) and + then created in separate batches. + """ + gcp_batch_tasks = [] + kubernetes_tasks = [] + + # Use random distribution if there is only one task + if len(remote_tasks) == 1: + if self._should_use_kubernetes(): + kubernetes_tasks.extend(remote_tasks) + else: + gcp_batch_tasks.extend(remote_tasks) + else: + # Use deterministic slicing for multiple tasks + frequencies = job_frequency.get_job_frequency() + k8s_ratio = frequencies['kubernetes'] + k8s_count = int(len(remote_tasks) * k8s_ratio) + + # We take the first chunk for Kubernetes + kubernetes_tasks.extend(remote_tasks[:k8s_count]) + gcp_batch_tasks.extend(remote_tasks[k8s_count:]) + + logs.info(f'Sending {len(gcp_batch_tasks)} tasks to GCP Batch.') + logs.info(f'Sending {len(kubernetes_tasks)} tasks to Kubernetes.') + + results = [] + if kubernetes_tasks: + results.extend( + self._kubernetes_service.create_uworker_main_batch_jobs( + kubernetes_tasks)) + + if gcp_batch_tasks: + results.extend( + self._gcp_batch_service.create_uworker_main_batch_jobs( + gcp_batch_tasks)) + return results diff --git a/src/clusterfuzz/_internal/remote_task/job_frequency.py b/src/clusterfuzz/_internal/remote_task/job_frequency.py new file mode 100644 index 00000000000..596145fdd9c --- /dev/null +++ b/src/clusterfuzz/_internal/remote_task/job_frequency.py @@ -0,0 +1,57 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Configurable job frequencies for remote task execution. + +This module provides a way to define how frequently certain jobs are executed +on different remote backends, such as GCP Batch and Kubernetes. This allows for +A/B testing and performance comparisons between the two platforms. +""" + +from clusterfuzz._internal.datastore import feature_flags +from clusterfuzz._internal.metrics import logs +from clusterfuzz._internal.system import environment + +# By default, all jobs are sent to the GCP Batch backend. This can be +# overridden on a per-job basis by setting the `K8S_JOBS_FREQUENCY` +# feature flag. +DEFAULT_FREQUENCY = {'gcp_batch': 1.0, 'kubernetes': 0.0} + + +def get_job_frequency(): + """Returns the frequency for a given job. + + If the frequency is not explicitly defined in the `K8S_JOBS_FREQUENCY` + environment variable, the default frequency is returned. + """ + frequency = DEFAULT_FREQUENCY + + kubernetes_frequency = feature_flags.FeatureFlags.K8S_JOBS_FREQUENCY.content + if not isinstance( + kubernetes_frequency, + float) or kubernetes_frequency < 0 or kubernetes_frequency > 1: + logs.warning( + "Kubernetes frequency inconsistent", + kubernetes_frequency=kubernetes_frequency) + kubernetes_frequency = None + + elif not feature_flags.FeatureFlags.K8S_JOBS_FREQUENCY.enabled: + kubernetes_frequency = None + + if kubernetes_frequency: + frequency = { + 'gcp_batch': 1.0 - kubernetes_frequency, + 'kubernetes': kubernetes_frequency + } + logs.info("Job frequency", frequency=frequency) + return frequency diff --git a/src/clusterfuzz/_internal/tests/core/batch/service_test.py b/src/clusterfuzz/_internal/tests/core/batch/batch_service_test.py similarity index 88% rename from src/clusterfuzz/_internal/tests/core/batch/service_test.py rename to src/clusterfuzz/_internal/tests/core/batch/batch_service_test.py index 613a32603e6..d386eafb61c 100644 --- a/src/clusterfuzz/_internal/tests/core/batch/service_test.py +++ b/src/clusterfuzz/_internal/tests/core/batch/batch_service_test.py @@ -11,17 +11,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Tests for the batch service.""" +"""Tests for the batch batch_service.""" import datetime import unittest from unittest import mock import uuid from google.cloud import batch_v1 as batch +from google.cloud.batch_v1.types import job as gcb_job -from clusterfuzz._internal.batch import data_structures -from clusterfuzz._internal.batch import gcp -from clusterfuzz._internal.batch import service +from clusterfuzz._internal.batch import service as batch_service from clusterfuzz._internal.datastore import data_types from clusterfuzz._internal.tests.test_libs import helpers from clusterfuzz._internal.tests.test_libs import test_utils @@ -50,7 +49,7 @@ def _get_expected_task_spec(batch_workload_spec): if batch_workload_spec.retry: task_spec.max_retry_count = 4 else: - task_spec.max_retry_count = gcp.DEFAULT_RETRY_COUNT + task_spec.max_retry_count = batch_service.DEFAULT_RETRY_COUNT task_spec.max_run_duration = datetime.timedelta( seconds=int(batch_workload_spec.max_run_duration[:-1])) @@ -126,7 +125,7 @@ def _get_expected_create_request(job_name_uuid, spec, input_urls): task_group.task_count = len(input_urls) task_group.task_environments = task_environments task_group.task_spec = task_spec - task_group.task_count_per_node = gcp.TASK_COUNT_PER_NODE + task_group.task_count_per_node = batch_service.TASK_COUNT_PER_NODE job = batch.Job() job.task_groups = [task_group] @@ -143,26 +142,24 @@ def _get_expected_create_request(job_name_uuid, spec, input_urls): @test_utils.with_cloud_emulators('datastore') -class BatchServiceTest(unittest.TestCase): - """Tests for BatchService.""" +class GcpBatchServiceTest(unittest.TestCase): + """Tests for GcpBatchService.""" def setUp(self): helpers.patch(self, [ - 'clusterfuzz._internal.batch.gcp._batch_client', + 'clusterfuzz._internal.batch.service._batch_client', 'clusterfuzz._internal.base.tasks.task_utils.get_command_from_module', 'uuid.uuid4', ]) - self.mock.GcpBatchClient = mock.Mock( - ) # Still need this for BatchService constructor self.mock_batch_client_instance = mock.Mock() self.mock._batch_client.return_value = self.mock_batch_client_instance - self.batch_service = service.BatchService() + self.batch_service = batch_service.GcpBatchService() self.mock.uuid4.side_effect = [uuid.UUID(u) for u in UUIDS] def test_create_uworker_main_batch_jobs(self): """Tests that create_uworker_main_batch_jobs works as expected.""" # Create mock data. - spec1 = service.BatchWorkloadSpec( + spec1 = batch_service.BatchWorkloadSpec( clusterfuzz_release='release1', disk_size_gb=10, disk_type='type1', @@ -178,7 +175,7 @@ def test_create_uworker_main_batch_jobs(self): priority=1, max_run_duration='1s', retry=False) - spec2 = service.BatchWorkloadSpec( + spec2 = batch_service.BatchWorkloadSpec( clusterfuzz_release='release2', disk_size_gb=20, disk_type='type2', @@ -201,9 +198,9 @@ def test_create_uworker_main_batch_jobs(self): ('command2', 'job2'): spec2, } tasks = [ - data_structures.BatchTask('command1', 'job1', 'url1'), - data_structures.BatchTask('command1', 'job1', 'url2'), - data_structures.BatchTask('command2', 'job2', 'url3'), + batch_service.RemoteTask('command1', 'job1', 'url1'), + batch_service.RemoteTask('command1', 'job1', 'url2'), + batch_service.RemoteTask('command2', 'job2', 'url3'), ] # Call the function. @@ -222,7 +219,7 @@ def test_create_uworker_main_batch_jobs(self): def test_create_uworker_main_batch_job(self): """Tests that create_uworker_main_batch_job works as expected.""" # Create mock data. - spec1 = service.BatchWorkloadSpec( + spec1 = batch_service.BatchWorkloadSpec( clusterfuzz_release='release1', disk_size_gb=10, disk_type='type1', @@ -243,7 +240,9 @@ def test_create_uworker_main_batch_job(self): mock_get_specs_from_config.return_value = { ('fuzz', 'job1'): spec1, } - self.mock_batch_client_instance.create_job.return_value = 'job' + + self.mock_batch_client_instance.create_job.return_value = gcb_job.Job( + name='job') self.mock.get_command_from_module.return_value = 'fuzz' # Call the function. @@ -272,11 +271,11 @@ def test_is_remote_task(self): """Tests that is_remote_task works as expected.""" # Test when it is a remote task. self.mock._get_specs_from_config.return_value = {('fuzz', 'job'): True} - self.assertTrue(service.is_remote_task('fuzz', 'job')) + self.assertTrue(batch_service.is_remote_task('fuzz', 'job')) # Test when it is not a remote task. self.mock._get_specs_from_config.side_effect = ValueError - self.assertFalse(service.is_remote_task('progression', 'job')) + self.assertFalse(batch_service.is_remote_task('progression', 'job')) if __name__ == '__main__': @@ -296,7 +295,7 @@ def setUp(self): helpers.patch(self, [ 'clusterfuzz._internal.base.utils.random_weighted_choice', ]) - self.mock.random_weighted_choice.return_value = service.WeightedSubconfig( + self.mock.random_weighted_choice.return_value = batch_service.WeightedSubconfig( name='east4-network2', weight=1, ) @@ -305,7 +304,7 @@ def test_nonpreemptible(self): """Tests that _get_specs_from_config works for non-preemptibles as expected.""" spec = _get_spec_from_config('analyze', self.job.name) - expected_spec = service.BatchWorkloadSpec( + expected_spec = batch_service.BatchWorkloadSpec( clusterfuzz_release='prod', docker_image='gcr.io/clusterfuzz-images/base:a2f4dd6-202202070654', user_data='file://linux-init.yaml', @@ -331,7 +330,7 @@ def test_fuzz_get_specs_from_config(self): job = data_types.Job(name='libfuzzer_chrome_asan', platform='LINUX') job.put() spec = _get_spec_from_config('fuzz', job.name) - expected_spec = service.BatchWorkloadSpec( + expected_spec = batch_service.BatchWorkloadSpec( clusterfuzz_release='prod', docker_image='gcr.io/clusterfuzz-images/base:a2f4dd6-202202070654', user_data='file://linux-init.yaml', @@ -374,16 +373,16 @@ def test_get_specs_from_config_disk_size(self): platform='LINUX', name='libfuzzer_asan_test').put() - spec = service._get_specs_from_config( - [service.BatchTask('fuzz', 'libfuzzer_asan_test', None)]) + spec = batch_service._get_specs_from_config( + [batch_service.RemoteTask('fuzz', 'libfuzzer_asan_test', None)]) self.assertEqual(spec['fuzz', 'libfuzzer_asan_test'].disk_size_gb, size) def test_get_specs_from_config_no_disk_size(self): """Test that disk_size_gb isn't mandatory.""" data_types.Job(platform='LINUX', name='libfuzzer_asan_test').put() - spec = service._get_specs_from_config( - [service.BatchTask('fuzz', 'libfuzzer_asan_test', None)]) - conf = service._get_batch_config() + spec = batch_service._get_specs_from_config( + [batch_service.RemoteTask('fuzz', 'libfuzzer_asan_test', None)]) + conf = batch_service._get_batch_config() expected_size = ( conf.get('mapping')['LINUX-PREEMPTIBLE-UNPRIVILEGED']['disk_size_gb']) self.assertEqual(spec['fuzz', 'libfuzzer_asan_test'].disk_size_gb, @@ -406,8 +405,8 @@ def test_get_specs_from_config_with_disk_size_override(self): platform='LINUX', name=job_name).put() - spec = service._get_specs_from_config( - [service.BatchTask('fuzz', job_name, None)]) + spec = batch_service._get_specs_from_config( + [batch_service.RemoteTask('fuzz', job_name, None)]) self.assertEqual(spec['fuzz', job_name].disk_size_gb, overridden_size) @mock.patch('clusterfuzz._internal.batch.service.utils.is_oss_fuzz') @@ -422,8 +421,8 @@ def test_get_config_names_os_version(self, mock_get_all_from_query, job1 = data_types.Job( name='job1', platform='LINUX', base_os_version='job-os-ubuntu-20') mock_get_all_from_query.return_value = [job1] - config_map = service._get_config_names( - [service.BatchTask('fuzz', 'job1', None)]) + config_map = batch_service._get_config_names( + [batch_service.RemoteTask('fuzz', 'job1', None)]) self.assertEqual(config_map[('fuzz', 'job1')][2], 'job-os-ubuntu-20') # Test Case 2: OSS-Fuzz project, project-level version overrides job-level. @@ -437,24 +436,24 @@ def test_get_config_names_os_version(self, mock_get_all_from_query, name='my-project', base_os_version='project-os-ubuntu-24') mock_get_all_from_query.return_value = [job2] mock_oss_fuzz_project_query.return_value.get.return_value = project - config_map = service._get_config_names( - [service.BatchTask('fuzz', 'job2', None)]) + config_map = batch_service._get_config_names( + [batch_service.RemoteTask('fuzz', 'job2', None)]) self.assertEqual(config_map[('fuzz', 'job2')][2], 'project-os-ubuntu-24') # Test Case 3: OSS-Fuzz project, only project-level version exists. job3 = data_types.Job(name='job3', project='my-project', platform='LINUX') mock_get_all_from_query.return_value = [job3] mock_oss_fuzz_project_query.return_value.get.return_value = project - config_map = service._get_config_names( - [service.BatchTask('fuzz', 'job3', None)]) + config_map = batch_service._get_config_names( + [batch_service.RemoteTask('fuzz', 'job3', None)]) self.assertEqual(config_map[('fuzz', 'job3')][2], 'project-os-ubuntu-24') # Test Case 4: Internal project, no version is set, should be None. mock_is_oss_fuzz.return_value = False job4 = data_types.Job(name='job4', platform='LINUX') mock_get_all_from_query.return_value = [job4] - config_map = service._get_config_names( - [service.BatchTask('fuzz', 'job4', None)]) + config_map = batch_service._get_config_names( + [batch_service.RemoteTask('fuzz', 'job4', None)]) self.assertIsNone(config_map[('fuzz', 'job4')][2]) # Test Case 5: OSS-Fuzz project, but no versions are set anywhere. @@ -464,12 +463,12 @@ def test_get_config_names_os_version(self, mock_get_all_from_query, project_no_version = data_types.OssFuzzProject(name='my-project-no-version') mock_get_all_from_query.return_value = [job5] mock_oss_fuzz_project_query.return_value.get.return_value = project_no_version - config_map = service._get_config_names( - [service.BatchTask('fuzz', 'job5', None)]) + config_map = batch_service._get_config_names( + [batch_service.RemoteTask('fuzz', 'job5', None)]) self.assertIsNone(config_map[('fuzz', 'job5')][2]) def _get_spec_from_config(command, job_name): return list( - service._get_specs_from_config( - [service.BatchTask(command, job_name, None)]).values())[0] + batch_service._get_specs_from_config( + [batch_service.RemoteTask(command, job_name, None)]).values())[0] diff --git a/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py b/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py index 9a3c5f50fae..eafbf5d85b5 100644 --- a/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py +++ b/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py @@ -60,6 +60,9 @@ def setUp(self): monitor.metrics_store().reset_for_testing() helpers.patch(self, ['clusterfuzz._internal.system.environment.platform']) self.mock.platform.return_value = 'some_platform' + helpers.patch(self, + ['clusterfuzz._internal.system.environment.get_runtime']) + self.mock.get_runtime.return_value = environment.UtaskMainRuntime.KATA_CONTAINER def test_fuzzer_run_result(self): """Ensure _track_fuzzer_run_result set the right metrics.""" @@ -77,6 +80,7 @@ def test_fuzzer_run_result(self): 'return_code': 2, 'platform': 'some_platform', 'job': 'job', + 'runtime': 'kata_container' })) self.assertEqual( 1, @@ -85,6 +89,7 @@ def test_fuzzer_run_result(self): 'return_code': 0, 'platform': 'some_platform', 'job': 'job', + 'runtime': 'kata_container' })) self.assertEqual( 1, @@ -93,6 +98,7 @@ def test_fuzzer_run_result(self): 'return_code': -1, 'platform': 'some_platform', 'job': 'job', + 'runtime': 'kata_container' })) testcase_count_ratio = ( @@ -143,6 +149,9 @@ def setUp(self): monitor.metrics_store().reset_for_testing() helpers.patch(self, ['clusterfuzz._internal.system.environment.platform']) self.mock.platform.return_value = 'some_platform' + helpers.patch(self, + ['clusterfuzz._internal.system.environment.get_runtime']) + self.mock.get_runtime.return_value = environment.UtaskMainRuntime.KATA_CONTAINER def test_testcase_run_result(self): """Ensure _track_testcase_run_result sets the right metrics.""" @@ -154,24 +163,28 @@ def test_testcase_run_result(self): monitoring_metrics.JOB_NEW_CRASH_COUNT.get({ 'job': 'job', 'platform': 'some_platform', + 'runtime': 'kata_container', })) self.assertEqual( 15, monitoring_metrics.JOB_KNOWN_CRASH_COUNT.get({ 'job': 'job', 'platform': 'some_platform', + 'runtime': 'kata_container', })) self.assertEqual( 7, monitoring_metrics.FUZZER_NEW_CRASH_COUNT.get({ 'fuzzer': 'fuzzer', 'platform': 'some_platform', + 'runtime': 'kata_container', })) self.assertEqual( 15, monitoring_metrics.FUZZER_KNOWN_CRASH_COUNT.get({ 'fuzzer': 'fuzzer', 'platform': 'some_platform', + 'runtime': 'kata_container', })) diff --git a/src/clusterfuzz/_internal/tests/core/datastore/feature_flag_test.py b/src/clusterfuzz/_internal/tests/core/datastore/feature_flag_test.py new file mode 100644 index 00000000000..972fe40a65b --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/datastore/feature_flag_test.py @@ -0,0 +1,54 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""FeatureFlag tests.""" +import unittest + +from google.cloud import ndb + +from clusterfuzz._internal.datastore import data_types +from clusterfuzz._internal.datastore import feature_flags +from clusterfuzz._internal.tests.test_libs import test_utils + + +@test_utils.with_cloud_emulators('datastore') +class FeatureFlagTest(unittest.TestCase): + """Test FeatureFlag.""" + + def test_get_and_set(self): + """Test getting and setting feature flags.""" + # Create a boolean feature flag. + flag = data_types.FeatureFlag(id=feature_flags.FeatureFlags.TEST_FLAG.value) + flag.description = 'A test boolean flag' + flag.enabled = True + flag.put() + + # Create a float feature flag. + flag_float = data_types.FeatureFlag( + id=feature_flags.FeatureFlags.TEST_FLOAT_FLAG.value) + flag_float.description = 'A test float flag' + flag_float.enabled = True + flag_float.value = 1.23 + flag_float.put() + + # Retrieve and verify. + self.assertIsNotNone(feature_flags.FeatureFlags.TEST_FLAG.flag) + self.assertTrue(feature_flags.FeatureFlags.TEST_FLAG.enabled) + self.assertEqual(feature_flags.FeatureFlags.TEST_FLAG.description, + 'A test boolean flag') + self.assertIsNone(feature_flags.FeatureFlags.TEST_FLAG.content) + + retrieved_flag_float = feature_flags.FeatureFlags.TEST_FLOAT_FLAG.flag + self.assertIsNotNone(retrieved_flag_float) + self.assertTrue(feature_flags.FeatureFlags.TEST_FLOAT_FLAG.enabled) + self.assertEqual(feature_flags.FeatureFlags.TEST_FLOAT_FLAG.content, 1.23) diff --git a/src/clusterfuzz/_internal/tests/core/google_cloud_utils/use_batch.py b/src/clusterfuzz/_internal/tests/core/google_cloud_utils/use_batch.py deleted file mode 100644 index 783f04a772b..00000000000 --- a/src/clusterfuzz/_internal/tests/core/google_cloud_utils/use_batch.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Cloud Batch helpers for local testing""" - -import multiprocessing.pool -import os -from unittest import mock - -from clusterfuzz._internal.google_cloud_utils import batch - - -def _create_many(): - """Creates many jobs.""" - many = [None for _ in range(2000)] - with multiprocessing.pool.Pool(120) as pool: - pool.map(_send_test_job, many) - - -@mock.patch( - 'clusterfuzz._internal.google_cloud_utils.batch._get_job', - return_value=mock.Mock(platform='LINUX')) -@mock.patch( - 'clusterfuzz._internal.system.environment.get_config_directory', - return_value=os.environ['BATCH_TEST_CONFIG_PATH']) -def _send_test_job(_=None, get_config_directory=None, get_job=None): - """Creates a test batch job for local manual testing to ensure job creation - actually works.""" - del _ - del get_config_directory - del get_job - tasks = [ - batch.BatchTask('variant', 'libfuzzer_chrome_asan', 'https://fake/') - for _ in range(10) - ] - batch.create_uworker_main_batch_jobs(tasks) diff --git a/src/clusterfuzz/_internal/tests/core/k8s/__init__.py b/src/clusterfuzz/_internal/tests/core/k8s/__init__.py new file mode 100644 index 00000000000..a705175a72d --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/k8s/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Kubernetes tests.""" diff --git a/src/clusterfuzz/_internal/tests/core/k8s/k8s_integration_test.py b/src/clusterfuzz/_internal/tests/core/k8s/k8s_integration_test.py new file mode 100644 index 00000000000..d3c9e024eb1 --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/k8s/k8s_integration_test.py @@ -0,0 +1,93 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Integration tests for KubernetesService.""" + +import base64 +import os +import unittest +from unittest import mock + +from kubernetes import client + +from clusterfuzz._internal.k8s import service + + +class KubernetesIntegrationTest(unittest.TestCase): + """Integration tests for KubernetesService.""" + + @mock.patch('googleapiclient.discovery.build') + def test_load_credentials(self, mock_discovery_build): + """Test that credentials can be loaded manually using the fallback logic.""" + # Ensure no kubeconfig interferes to force manual path (if local kubeconfig exists) + # Note: os.environ changes are process-local. + old_kubeconfig = os.environ.get('KUBECONFIG') + os.environ['KUBECONFIG'] = '/dev/null' + + # Mock GKE response + mock_service = mock.Mock() + mock_discovery_build.return_value = mock_service + + mock_clusters_list = mock_service.projects().locations().clusters().list( + ).execute + mock_clusters_list.return_value = { + 'clusters': [{ + 'name': 'clusterfuzz-cronjobs-gke', + 'endpoint': '1.2.3.4', + 'masterAuth': { + 'clusterCaCertificate': + base64.b64encode(b'fake-cert').decode('utf-8') + } + }] + } + + # Mock list_namespaced_job to avoid actual network call to 1.2.3.4 + with mock.patch('kubernetes.client.BatchV1Api.list_namespaced_job'): + try: + # This will trigger _load_gke_credentials + # It should try load_kube_config (fail), load_incluster (fail), then manual. + k8s_service = service.KubernetesService() + + # Verify api client is initialized + self.assertIsNotNone(k8s_service._batch_api) + self.assertIsInstance(k8s_service._batch_api, client.BatchV1Api) + + # Verify configuration + config = client.Configuration.get_default_copy() + print(f"Loaded Host: {config.host}") + + # Check that we got a valid https endpoint + self.assertTrue(config.host.startswith("https://")) + self.assertTrue(config.verify_ssl) + self.assertIsNotNone(config.ssl_ca_cert) + + # Verify API key fix is present (Crucial for manual path) + self.assertIn("authorization", config.api_key) + + # Verify hook is present + self.assertIsNotNone(config.refresh_api_key_hook) + + # Verify actual connectivity and auth + print("Attempting to list jobs to verify authentication...") + k8s_service._batch_api.list_namespaced_job(namespace='default', limit=1) + print("Successfully listed jobs.") + + finally: + if old_kubeconfig: + os.environ['KUBECONFIG'] = old_kubeconfig + else: + del os.environ['KUBECONFIG'] + + +if __name__ == '__main__': + unittest.main() diff --git a/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_e2e_test.py b/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_e2e_test.py new file mode 100644 index 00000000000..0bedbaaeb8d --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_e2e_test.py @@ -0,0 +1,371 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""End-to-end tests for the Kubernetes service.""" + +# pylint: disable=unused-argument + +import os +import shutil +import subprocess +import tempfile +import time +import unittest +from unittest import mock + +from kubernetes import client as k8s_client +from kubernetes import config as k8s_config + +from clusterfuzz._internal.datastore import data_types +from clusterfuzz._internal.k8s import service as kubernetes_service +from clusterfuzz._internal.k8s.service import KubernetesJobConfig +from clusterfuzz._internal.remote_task import RemoteTask +from clusterfuzz._internal.tests.test_libs import test_utils + + +@mock.patch( + 'clusterfuzz._internal.metrics.logs.get_logging_config_dict', + return_value={ + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'simpleFormatter': { + 'format': '%(levelname)s:%(module)s:%(lineno)d:%(message)s' + } + }, + 'handlers': { + 'consoleHandler': { + 'class': 'logging.StreamHandler', + 'formatter': 'simpleFormatter' + } + }, + 'loggers': { + 'root': { + 'handlers': ['consoleHandler'], + 'level': 'INFO' + } + } + }) +@test_utils.with_cloud_emulators('datastore') +class KubernetesServiceE2ETest(unittest.TestCase): + """End-to-end tests for the Kubernetes service.""" + + @classmethod + def setUpClass(cls): + """Set up the test environment.""" + if not os.getenv('K8S_E2E'): + raise unittest.SkipTest('K8S_E2E environment variable not set.') + + cls.mock_batch_config = mock.Mock() + cls.mock_batch_config.get.return_value = 'test-project' + + def get_batch_config(key): + return { + 'project': 'test-project', + 'mapping': { + 'LINUX-PREEMPTIBLE-UNPRIVILEGED': { + 'clusterfuzz_release': 'prod', + 'docker_image': cls.image, + 'user_data': 'file://linux-init.yaml', + 'disk_size_gb': 10, + 'disk_type': 'pd-standard', + 'service_account_email': 'test-email', + 'preemptible': True, + 'machine_type': 'machine-type', + 'subconfigs': [{ + 'name': 'subconfig1', + 'weight': 1 + }] + }, + 'LINUX-NONPREEMPTIBLE-UNPRIVILEGED': { + 'clusterfuzz_release': 'prod', + 'docker_image': cls.image, + 'user_data': 'file://linux-init.yaml', + 'disk_size_gb': 20, + 'disk_type': 'pd-standard', + 'service_account_email': 'test-email', + 'preemptible': False, + 'machine_type': 'machine-type', + 'subconfigs': [{ + 'name': 'subconfig1', + 'weight': 1 + }] + } + }, + 'subconfigs': { + 'subconfig1': { + 'region': 'region', + 'network': 'network', + 'subnetwork': 'subnetwork' + } + } + }.get(key) + + cls.mock_batch_config.get.side_effect = get_batch_config + + cls.mock_local_config = mock.Mock() + cls.mock_local_config.BatchConfig.return_value = cls.mock_batch_config + + with mock.patch( + 'clusterfuzz._internal.config.local_config', new=cls.mock_local_config): + cls.cluster_name = 'test-cluster-for-e2e-test' + cls.image = 'gcr.io/clusterfuzz-images/base:000dc1f-202511191429' + + # First, try to find `kind` in the user's local bin directory. + home_dir = os.path.expanduser('~') + local_kind_path = os.path.join(home_dir, '.local', 'bin', 'kind') + + if os.path.exists(local_kind_path): + cls.kind_path = local_kind_path + else: + # Fallback to searching the PATH. + cls.kind_path = shutil.which('kind') + + # Ensure no old cluster exists. + subprocess.run( + [cls.kind_path, 'delete', 'cluster', '--name', cls.cluster_name], + check=False) + + subprocess.run( + [cls.kind_path, 'create', 'cluster', '--name', cls.cluster_name], + check=True) + + # Explicitly get the kubeconfig from the kind cluster. + kubeconfig = subprocess.check_output( + [cls.kind_path, 'get', 'kubeconfig', '--name', + cls.cluster_name]).decode('utf-8') + + # Write the kubeconfig to a temporary file and load it. + with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + f.write(kubeconfig) + cls.kubeconfig_path = f.name + k8s_config.load_kube_config(config_file=cls.kubeconfig_path) + cls.api_client = k8s_client.BatchV1Api() + + cls.kubernetes_client = kubernetes_service.KubernetesService( + k8s_config_loaded=True) + data_types.Job(name='test-job', platform='LINUX').put() + data_types.Job(name='test-job1', platform='LINUX').put() + data_types.Job(name='test-job2', platform='LINUX').put() + + cls.mock_get_config_names = mock.Mock( + return_value={ + ('fuzz', 'test-job'): ('LINUX-PREEMPTIBLE-UNPRIVILEGED', 10, None), + ('fuzz', 'test-job1'): ('LINUX-PREEMPTIBLE-UNPRIVILEGED', 10, None), + ('fuzz', 'test-job2'): ('LINUX-NONPREEMPTIBLE-UNPRIVILEGED', 20, + None), + }) + cls.mock_get_config_names_patcher = mock.patch( + 'clusterfuzz._internal.batch.service._get_config_names', + new=cls.mock_get_config_names) + cls.mock_get_config_names_patcher.start() + + @classmethod + def tearDownClass(cls): + """Tear down the test environment.""" + os.remove(cls.kubeconfig_path) + subprocess.run( + [cls.kind_path, 'delete', 'cluster', '--name', cls.cluster_name], + check=True) + cls.mock_get_config_names_patcher.stop() + + def test_create_job(self, mock_get_logging_config_dict): + """Tests creating a job.""" + input_url = 'url' + remote_task = RemoteTask(None, 'test-job', None) + remote_task.docker_image = self.image + + config = KubernetesJobConfig( + job_type='test-job', + docker_image=self.image, + command=remote_task.command, + disk_size_gb=10, + service_account_email='test-email', + clusterfuzz_release='prod', + is_kata=False) + actual_job_name = self.kubernetes_client.create_job(config, input_url) + + # Wait for the job to be created. + time.sleep(5) + + job = self.api_client.read_namespaced_job(actual_job_name, 'default') + self.assertIsNotNone(job) + self.assertEqual(job.metadata.name, actual_job_name) + + # Wait for the job to start running. + job_running = False + for _ in range(180): + job = self.api_client.read_namespaced_job(actual_job_name, 'default') + if job.status.active or job.status.succeeded: + job_running = True + break + time.sleep(1) + + self.assertTrue( + job_running, + f"Job {actual_job_name} did not start running. Status: {job.status}") + + self.api_client.delete_namespaced_job( + name=actual_job_name, + namespace='default', + body=k8s_client.V1DeleteOptions(propagation_policy='Foreground')) + + @unittest.skip('Should be implemented against a cluster that supports kata') + def test_create_kata_container_job(self, mock_get_logging_config_dict): + """Tests creating a Kata container job.""" + input_urls = [] + actual_job_name = self.kubernetes_client.create_kata_container_job( + self.image, input_urls) + + # Wait for the job to be created. + time.sleep(5) + + job = self.api_client.read_namespaced_job(actual_job_name, 'default') + self.assertIsNotNone(job) + self.assertEqual(job.metadata.name, actual_job_name) + self.assertEqual(job.spec.template.spec.runtime_class_name, 'kata') + + # Wait for the job to start running. + job_running = False + for _ in range(180): + job = self.api_client.read_namespaced_job(actual_job_name, 'default') + if job.status.active or job.status.succeeded: + job_running = True + break + time.sleep(1) + + self.assertTrue( + job_running, + f"Kata Job {actual_job_name} did not start running. Status: {job.status}" + ) + + self.api_client.delete_namespaced_job( + name=actual_job_name, + namespace='default', + body=k8s_client.V1DeleteOptions(propagation_policy='Foreground')) + + @mock.patch('clusterfuzz._internal.k8s.service._get_k8s_job_configs') + @mock.patch( + 'clusterfuzz._internal.base.tasks.task_utils.get_command_from_module') + def test_create_uworker_main_batch_job(self, mock_get_command_from_module, + mock_get_k8s_job_configs, + mock_get_logging_config_dict): + """Tests creating a single uworker main batch job.""" + mock_get_command_from_module.return_value = 'fuzz' + config = KubernetesJobConfig( + job_type='test-job', + docker_image=self.image, + command='fuzz', + disk_size_gb=10, + service_account_email='test-email', + clusterfuzz_release='prod', + is_kata=False) + mock_get_k8s_job_configs.return_value = {('fuzz', 'test-job'): config} + + actual_job_name = \ + self.kubernetes_client.create_uworker_main_batch_job( + 'module', 'test-job', 'url1') + + # Wait for the job to be created. + time.sleep(5) + + job = self.api_client.read_namespaced_job(actual_job_name, 'default') + self.assertIsNotNone(job) + self.assertEqual(job.metadata.name, actual_job_name) + + # Wait for the job to start running. + job_running = False + for _ in range(180): + job = self.api_client.read_namespaced_job(actual_job_name, 'default') + if job.status.active or job.status.succeeded: + job_running = True + break + time.sleep(1) + + self.assertTrue( + job_running, + f"Job {actual_job_name} did not start running. Status: {job.status}") + + self.api_client.delete_namespaced_job( + name=actual_job_name, + namespace='default', + body=k8s_client.V1DeleteOptions(propagation_policy='Foreground')) + + @mock.patch('clusterfuzz._internal.k8s.service._get_k8s_job_configs') + @mock.patch( + 'clusterfuzz._internal.base.tasks.task_utils.get_command_from_module') + def test_create_uworker_main_batch_jobs(self, mock_get_command_from_module, + mock_get_k8s_job_configs, + mock_get_logging_config_dict): + """Tests creating multiple uworker main batch jobs.""" + mock_get_command_from_module.return_value = 'fuzz' + config1 = KubernetesJobConfig( + job_type='test-job1', + docker_image=self.image, + command='fuzz', + disk_size_gb=10, + service_account_email='test-email', + clusterfuzz_release='prod', + is_kata=False) + config2 = KubernetesJobConfig( + job_type='test-job2', + docker_image='different-image', + command='fuzz', + disk_size_gb=20, + service_account_email='test-email', + clusterfuzz_release='prod', + is_kata=False) + + mock_get_k8s_job_configs.return_value = { + ('fuzz', 'test-job1'): config1, + ('fuzz', 'test-job2'): config2 + } + + tasks = [ + RemoteTask('fuzz', 'test-job1', 'url1'), + RemoteTask('fuzz', 'test-job2', 'url2'), + ] + + actual_job_names = \ + self.kubernetes_client.create_uworker_main_batch_jobs(tasks) + self.assertEqual(len(actual_job_names), 2) + + for job_name in actual_job_names: + # Wait for the job to be created. + time.sleep(5) + + job = self.api_client.read_namespaced_job(job_name, 'default') + self.assertIsNotNone(job) + self.assertEqual(job.metadata.name, job_name) + + # Wait for the job to start running. + job_running = False + for _ in range(180): + job = self.api_client.read_namespaced_job(job_name, 'default') + if job.status.active or job.status.succeeded: + job_running = True + break + time.sleep(1) + + self.assertTrue( + job_running, + f"Job {job_name} did not start running. Status: {job.status}") + + self.api_client.delete_namespaced_job( + name=job_name, + namespace='default', + body=k8s_client.V1DeleteOptions(propagation_policy='Foreground')) + + +if __name__ == '__main__': + unittest.main() diff --git a/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_limit_test.py b/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_limit_test.py new file mode 100644 index 00000000000..0bf22a3bdf5 --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_limit_test.py @@ -0,0 +1,85 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for the Kubernetes batch client limit logic.""" + +import unittest +from unittest import mock + +from clusterfuzz._internal.k8s import service +from clusterfuzz._internal.tests.test_libs import test_utils + + +@test_utils.with_cloud_emulators('datastore') +@mock.patch('kubernetes.config.load_kube_config') +class KubernetesServiceLimitTest(unittest.TestCase): + """Tests for the KubernetesService limit logic.""" + + def setUp(self): + patcher = mock.patch( + 'clusterfuzz._internal.k8s.service.KubernetesService._load_gke_credentials' + ) + self.addCleanup(patcher.stop) + self.mock_load_gke = patcher.start() + + # Create a job to prevent KeyError in _get_k8s_job_configs + from clusterfuzz._internal.datastore import data_types + data_types.Job(name='job1', platform='LINUX').put() + + @mock.patch.object(service.KubernetesService, '_get_pending_jobs_count') + def test_create_uworker_main_batch_jobs_limit_not_reached( + self, mock_get_pending_count, _): + """Tests that create_uworker_main_batch_jobs proceeds when limit not reached.""" + mock_get_pending_count.return_value = 99 + kube_service = service.KubernetesService() + + # We expect this to proceed to job creation logic (which we mock to avoid actual creation) + with mock.patch.object(service.KubernetesService, + 'create_kata_container_job') as mock_create: + kube_service.create_uworker_main_batch_jobs( + [service.RemoteTask('fuzz', 'job1', 'url1')]) + self.assertTrue(mock_create.called) + + @mock.patch.object(service.KubernetesService, '_get_pending_jobs_count') + def test_create_uworker_main_batch_jobs_limit_reached( + self, mock_get_pending_count, _): + """Tests that create_uworker_main_batch_jobs nacks tasks when limit reached.""" + mock_get_pending_count.return_value = service.MAX_PENDING_JOBS + kube_service = service.KubernetesService() + + mock_pubsub_task = mock.Mock() + mock_pubsub_task.do_not_ack = False + task = service.RemoteTask( + 'fuzz', 'job1', 'url1', pubsub_task=mock_pubsub_task) + + result = kube_service.create_uworker_main_batch_jobs([task]) + + self.assertEqual(result, []) + self.assertTrue(mock_pubsub_task.do_not_ack) + + @mock.patch.object(service.KubernetesService, '_get_pending_jobs_count') + def test_create_uworker_main_batch_jobs_limit_exceeded( + self, mock_get_pending_count, _): + """Tests that create_uworker_main_batch_jobs nacks tasks when limit exceeded.""" + mock_get_pending_count.return_value = service.MAX_PENDING_JOBS + 1 + kube_service = service.KubernetesService() + + mock_pubsub_task = mock.Mock() + mock_pubsub_task.do_not_ack = False + task = service.RemoteTask( + 'fuzz', 'job1', 'url1', pubsub_task=mock_pubsub_task) + + result = kube_service.create_uworker_main_batch_jobs([task]) + + self.assertEqual(result, []) + self.assertTrue(mock_pubsub_task.do_not_ack) diff --git a/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_test.py b/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_test.py new file mode 100644 index 00000000000..ccc45aea9a4 --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/k8s/k8s_service_test.py @@ -0,0 +1,192 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for the Kubernetes batch client.""" + +import unittest +from unittest import mock + +from clusterfuzz._internal.datastore import data_types +from clusterfuzz._internal.k8s import service +from clusterfuzz._internal.tests.test_libs import test_utils + + +@test_utils.with_cloud_emulators('datastore') +@mock.patch('kubernetes.config.load_kube_config') +class KubernetesServiceTest(unittest.TestCase): + """Tests for the KubernetesService class.""" + + def setUp(self): + patcher = mock.patch( + 'clusterfuzz._internal.k8s.service.KubernetesService._load_gke_credentials' + ) + self.addCleanup(patcher.stop) + self.mock_load_gke = patcher.start() + + data_types.Job(name='job1', platform='LINUX').put() + data_types.Job( + name='job2', platform='LINUX', + environment_string='CUSTOM_VAR = value').put() + + @mock.patch.object(service.KubernetesService, '_get_pending_jobs_count') + @mock.patch.object(service.KubernetesService, 'create_kata_container_job') + @mock.patch.object(service.KubernetesService, 'create_job') + def test_create_uworker_main_batch_jobs( + self, mock_create_job, mock_create_kata_job, mock_get_pending_count, _): + """Tests the creation of uworker main batch jobs.""" + mock_get_pending_count.return_value = 0 + tasks = [ + service.RemoteTask('fuzz', 'job1', 'url1'), + service.RemoteTask('fuzz', 'job1', 'url2'), + service.RemoteTask('command2', 'job2', 'url3'), + ] + + kube_service = service.KubernetesService() + kube_service.create_uworker_main_batch_jobs(tasks) + + # Assuming default config implies Kata, and no batching of URLs. + # Total 3 tasks, so 3 calls. + self.assertEqual(3, mock_create_kata_job.call_count) + self.assertEqual(0, mock_create_job.call_count) + + urls = sorted( + [call.args[1] for call in mock_create_kata_job.call_args_list]) + self.assertEqual(urls, ['url1', 'url2', 'url3']) + + @mock.patch('kubernetes.client.CoreV1Api') + def test_get_pending_jobs_count(self, mock_core_api_cls, _): + """Tests _get_pending_jobs_count.""" + mock_core_api = mock_core_api_cls.return_value + kube_service = service.KubernetesService() + + # Mock pods + mock_core_api.list_namespaced_pod.return_value.items = [ + mock.Mock(), mock.Mock() + ] + + self.assertEqual(2, kube_service._get_pending_jobs_count()) + mock_core_api.list_namespaced_pod.assert_called_with( + namespace='default', + label_selector='app.kubernetes.io/name=clusterfuzz-kata-job', + field_selector='status.phase=Pending') + + @mock.patch.object(service.KubernetesService, '_get_pending_jobs_count') + def test_create_uworker_main_batch_jobs_limit_reached( + self, mock_get_pending_count, _): + """Tests that create_uworker_main_batch_jobs nacks when limit reached.""" + mock_get_pending_count.return_value = service.MAX_PENDING_JOBS + kube_service = service.KubernetesService() + + mock_pubsub_task = mock.Mock() + mock_pubsub_task.do_not_ack = False + task = service.RemoteTask( + 'fuzz', 'job1', 'url1', pubsub_task=mock_pubsub_task) + + result = kube_service.create_uworker_main_batch_jobs([task]) + self.assertEqual(result, []) + self.assertTrue(mock_pubsub_task.do_not_ack) + + @mock.patch('kubernetes.client.BatchV1Api') + def test_create_kata_container_job_spec(self, mock_batch_api_cls, _): + """Tests that create_kata_container_job generates the correct spec.""" + mock_batch_api = mock_batch_api_cls.return_value + kube_service = service.KubernetesService() + # Mock _create_service_account_if_needed + kube_service._create_service_account_if_needed = mock.Mock( + return_value='untrusted-worker') + + config = service.KubernetesJobConfig( + job_type='test-job', + docker_image='test-image', + command='fuzz', + disk_size_gb=10, + service_account_email= + 'untrusted-worker@clusterfuzz-development.iam.gserviceaccount.com', + clusterfuzz_release='prod', + is_kata=True) + + kube_service.create_kata_container_job(config, 'input_url') + + self.assertTrue(mock_batch_api.create_namespaced_job.called) + call_args = mock_batch_api.create_namespaced_job.call_args + job_body = call_args.kwargs['body'] + + # Check Spec + pod_spec = job_body['spec']['template']['spec'] + container = pod_spec['containers'][0] + self.assertEqual(21600, job_body['spec']['activeDeadlineSeconds']) + + # Check capabilities + self.assertEqual(['ALL'], + container['securityContext']['capabilities']['add']) + + # Check HOST_UID env var + env_names = {e['name']: e['value'] for e in container['env']} + self.assertEqual('1337', env_names['HOST_UID']) + + # Check shm size + volumes = {v['name']: v for v in pod_spec['volumes']} + self.assertEqual('1.9Gi', volumes['dshm']['emptyDir']['sizeLimit']) + + # Check Service Account + self.assertEqual('untrusted-worker', pod_spec['serviceAccountName']) + kube_service._create_service_account_if_needed.assert_called_with( + 'untrusted-worker@clusterfuzz-development.iam.gserviceaccount.com') + + @mock.patch('kubernetes.client.BatchV1Api') + def test_create_job(self, mock_batch_api_cls, _): + """Tests create_job.""" + mock_batch_api = mock_batch_api_cls.return_value + kube_service = service.KubernetesService() + kube_service._create_service_account_if_needed = mock.Mock( + return_value='test-sa') + + config = service.KubernetesJobConfig( + job_type='test-job', + docker_image='test-image', + command='fuzz', + disk_size_gb=10, + service_account_email='test-email', + clusterfuzz_release='prod', + is_kata=False) + + kube_service.create_job(config, 'input_url') + + self.assertTrue(mock_batch_api.create_namespaced_job.called) + call_args = mock_batch_api.create_namespaced_job.call_args + job_body = call_args.kwargs['body'] + self.assertEqual(21600, job_body['spec']['activeDeadlineSeconds']) + + # Check Service Account + self.assertEqual('test-sa', + job_body['spec']['template']['spec']['serviceAccountName']) + kube_service._create_service_account_if_needed.assert_called_with( + 'test-email') + + @mock.patch( + 'clusterfuzz._internal.base.tasks.task_utils.get_command_from_module') + @mock.patch.object(service.KubernetesService, + 'create_uworker_main_batch_jobs') + def test_create_uworker_main_batch_job(self, mock_create_batch_jobs, + mock_get_command, _): + """Tests the creation of a single uworker main batch job.""" + mock_get_command.return_value = 'command' + kube_service = service.KubernetesService() + kube_service.create_uworker_main_batch_job('module', 'job', 'url') + + self.assertEqual(1, mock_create_batch_jobs.call_count) + tasks = mock_create_batch_jobs.call_args[0][0] + self.assertEqual(1, len(tasks)) + self.assertEqual('command', tasks[0].command) + self.assertEqual('job', tasks[0].job_type) + self.assertEqual('url', tasks[0].input_download_url) diff --git a/src/clusterfuzz/_internal/tests/core/kubernetes/__init__.py b/src/clusterfuzz/_internal/tests/core/kubernetes/__init__.py new file mode 100644 index 00000000000..37b43b64d76 --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/kubernetes/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Kubernetes batch client tests.""" diff --git a/src/clusterfuzz/_internal/tests/core/kubernetes/kubernetes_test.py b/src/clusterfuzz/_internal/tests/core/kubernetes/kubernetes_test.py new file mode 100644 index 00000000000..12e4e6d8929 --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/kubernetes/kubernetes_test.py @@ -0,0 +1,91 @@ +# pylint: disable=protected-access +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for the Kubernetes batch client.""" +import unittest +import uuid + +from clusterfuzz._internal.k8s import service as kubernetes_service +from clusterfuzz._internal.tests.test_libs import helpers + + +class MockRemoteTask(): + """Mock RemoteTask for testing.""" + job_type = 'test-job' + docker_image = 'test-image' + command = 'fuzz' + + +class KubernetesJobClientTest(unittest.TestCase): + """Tests for KubernetesJobClient.""" + + def setUp(self): + helpers.patch(self, [ + 'clusterfuzz._internal.k8s.service.KubernetesService._load_gke_credentials', + 'kubernetes.config.load_kube_config', + 'kubernetes.client.CoreV1Api', + 'kubernetes.client.BatchV1Api', + 'uuid.uuid4', + ]) + self.mock.uuid4.return_value = uuid.UUID( + 'a0b1c2d3-e4f5-6789-0123-456789abcdef') + self.job_spec = { + 'metadata': { + 'name': 'test-job' + }, + 'spec': { + 'template': { + 'spec': { + 'containers': [{ + 'name': 'test-container', + 'image': 'test-image', + 'env': [] + }] + } + } + } + } + self.k8s_client = kubernetes_service.KubernetesService() + + def test_create_job(self): + """Tests that create_job works as expected.""" + input_url = 'url1' + remote_task = MockRemoteTask() + + config = kubernetes_service.KubernetesJobConfig( + job_type=remote_task.job_type, + docker_image=remote_task.docker_image, + command=remote_task.command, + disk_size_gb=10, + service_account_email='test-email', + clusterfuzz_release='prod', + is_kata=True) + + self.k8s_client.create_job(config, input_url) + self.k8s_client._batch_api.create_namespaced_job.assert_called_once() + called_args, called_kwargs = self.k8s_client._batch_api.create_namespaced_job.call_args + self.assertEqual(called_args, ()) + job_body = called_kwargs['body'] + self.assertEqual(job_body['metadata']['name'], 'test-job-a0b1c2d3') + self.assertEqual( + job_body['spec']['template']['spec']['containers'][0]['image'], + 'test-image') + self.assertIn({ + 'name': 'UWORKER_INPUT_DOWNLOAD_URL', + 'value': 'url1' + }, job_body['spec']['template']['spec']['containers'][0]['env']) + self.assertIn({ + 'name': 'CLUSTERFUZZ_RELEASE', + 'value': 'prod' + }, job_body['spec']['template']['spec']['containers'][0]['env']) diff --git a/src/clusterfuzz/_internal/tests/core/platforms/__init__.py b/src/clusterfuzz/_internal/tests/core/platforms/__init__.py index ddd71c00285..19f288442b2 100644 --- a/src/clusterfuzz/_internal/tests/core/platforms/__init__.py +++ b/src/clusterfuzz/_internal/tests/core/platforms/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,3 +11,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Platforms tests.""" diff --git a/src/clusterfuzz/_internal/tests/core/remote_task/__init__.py b/src/clusterfuzz/_internal/tests/core/remote_task/__init__.py new file mode 100644 index 00000000000..14cb13c5dbf --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/remote_task/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Remote task tests.""" diff --git a/src/clusterfuzz/_internal/tests/core/remote_task/remote_task_gate_test.py b/src/clusterfuzz/_internal/tests/core/remote_task/remote_task_gate_test.py new file mode 100644 index 00000000000..16058f13e0c --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/remote_task/remote_task_gate_test.py @@ -0,0 +1,168 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for the RemoteTaskGate class.""" + +# pylint: disable=protected-access, unused-argument + +import unittest +from unittest import mock + +from clusterfuzz._internal.remote_task import RemoteTask +from clusterfuzz._internal.remote_task import RemoteTaskGate + + +@mock.patch('clusterfuzz._internal.k8s.service.KubernetesService') +@mock.patch('clusterfuzz._internal.batch.service.GcpBatchService') +class RemoteTaskGateTest(unittest.TestCase): + """Tests for the RemoteTaskGate class.""" + + def test_init(self, mock_gcp_batch_service, mock_kubernetes_service): + """Tests that the RemoteTaskGate initializes correctly.""" + RemoteTaskGate() + mock_gcp_batch_service.assert_called_once() + mock_kubernetes_service.assert_called_once() + + @mock.patch.object(RemoteTaskGate, '_should_use_kubernetes') + def test_create_uworker_main_batch_job_kubernetes( + self, mock_should_use_kubernetes, mock_gcp_batch_service, + mock_kubernetes_service): + """ + Tests that create_uworker_main_batch_job calls the Kubernetes service + when _should_use_kubernetes returns True. + """ + mock_should_use_kubernetes.return_value = True + gate = RemoteTaskGate() + gate.create_uworker_main_batch_job('module', 'job', 'url') + mock_kubernetes_service.return_value.create_uworker_main_batch_job.assert_called_once_with( + 'module', 'job', 'url') + mock_gcp_batch_service.return_value.create_uworker_main_batch_job.assert_not_called( + ) + + @mock.patch.object(RemoteTaskGate, '_should_use_kubernetes') + def test_create_uworker_main_batch_job_gcp_batch( + self, mock_should_use_kubernetes, mock_gcp_batch_service, + mock_kubernetes_service): + """ + Tests that create_uworker_main_batch_job calls the GCP Batch service + when _should_use_kubernetes returns False. + """ + mock_should_use_kubernetes.return_value = False + gate = RemoteTaskGate() + gate.create_uworker_main_batch_job('module', 'job', 'url') + mock_gcp_batch_service.return_value.create_uworker_main_batch_job.assert_called_once_with( + 'module', 'job', 'url') + mock_kubernetes_service.return_value.create_uworker_main_batch_job.assert_not_called( + ) + + @mock.patch( + 'clusterfuzz._internal.remote_task.job_frequency.get_job_frequency') + @mock.patch('random.random') + def test_should_use_kubernetes(self, mock_random, mock_get_job_frequency, + mock_gcp_batch_service, + mock_kubernetes_service): + """ + Tests that _should_use_kubernetes returns the correct value based on + the configured frequency and a random roll. + """ + mock_get_job_frequency.return_value = {'kubernetes': 0.5} + gate = RemoteTaskGate() + + mock_random.return_value = 0.4 + self.assertTrue(gate._should_use_kubernetes('job')) + + mock_random.return_value = 0.6 + self.assertFalse(gate._should_use_kubernetes('job')) + + @mock.patch.object(RemoteTaskGate, '_should_use_kubernetes') + def test_create_uworker_main_batch_jobs(self, mock_should_use_kubernetes, + mock_gcp_batch_service, + mock_kubernetes_service): + """ + Tests that create_uworker_main_batch_jobs correctly routes tasks to + the appropriate service when they have different job types (random distribution). + """ + tasks = [ + RemoteTask('command1', 'job1', 'url1'), + RemoteTask('command2', 'job2', 'url2'), + RemoteTask('command3', 'job3', 'url3'), + ] + # different job types -> loop calls _should_use_kubernetes for each + mock_should_use_kubernetes.side_effect = [True, False, True] + gate = RemoteTaskGate() + gate.create_uworker_main_batch_jobs(tasks) + + # tasks[0] (job1) -> k8s + # tasks[1] (job2) -> batch + # tasks[2] (job3) -> k8s + + # K8s gets tasks[0] and tasks[2] + # Since call order depends on dict iteration order which is insertion ordered in Py3.7+, + # job1, job2, job3. + + # However, create_uworker_main_batch_jobs aggregates them into lists and calls service once. + + mock_kubernetes_service.return_value.create_uworker_main_batch_jobs.assert_called_once( + ) + k8s_call_args = mock_kubernetes_service.return_value.create_uworker_main_batch_jobs.call_args[ + 0][0] + self.assertEqual(len(k8s_call_args), 2) + self.assertIn(tasks[0], k8s_call_args) + self.assertIn(tasks[2], k8s_call_args) + + mock_gcp_batch_service.return_value.create_uworker_main_batch_jobs.assert_called_once( + ) + batch_call_args = mock_gcp_batch_service.return_value.create_uworker_main_batch_jobs.call_args[ + 0][0] + self.assertEqual(len(batch_call_args), 1) + self.assertIn(tasks[1], batch_call_args) + + @mock.patch( + 'clusterfuzz._internal.remote_task.job_frequency.get_job_frequency') + def test_create_uworker_main_batch_jobs_slicing(self, mock_get_job_frequency, + mock_gcp_batch_service, + mock_kubernetes_service): + """ + Tests that create_uworker_main_batch_jobs correctly routes tasks using + deterministic slicing when tasks share the same job type. + """ + # 4 tasks with same job type + tasks = [ + RemoteTask('command', 'job1', 'url1'), + RemoteTask('command', 'job1', 'url2'), + RemoteTask('command', 'job1', 'url3'), + RemoteTask('command', 'job1', 'url4'), + ] + + # 50% split + mock_get_job_frequency.return_value = {'kubernetes': 0.5, 'gcp_batch': 0.5} + + gate = RemoteTaskGate() + gate.create_uworker_main_batch_jobs(tasks) + + # 4 * 0.5 = 2 tasks for k8s. + # The code takes the first chunk for k8s. + + mock_kubernetes_service.return_value.create_uworker_main_batch_jobs.assert_called_once( + ) + k8s_call_args = mock_kubernetes_service.return_value.create_uworker_main_batch_jobs.call_args[ + 0][0] + self.assertEqual(len(k8s_call_args), 2) + self.assertEqual(k8s_call_args, tasks[:2]) + + mock_gcp_batch_service.return_value.create_uworker_main_batch_jobs.assert_called_once( + ) + batch_call_args = mock_gcp_batch_service.return_value.create_uworker_main_batch_jobs.call_args[ + 0][0] + self.assertEqual(len(batch_call_args), 2) + self.assertEqual(batch_call_args, tasks[2:]) diff --git a/src/clusterfuzz/_internal/tests/core/remote_task/remote_task_test.py b/src/clusterfuzz/_internal/tests/core/remote_task/remote_task_test.py new file mode 100644 index 00000000000..3e29ef2cb6e --- /dev/null +++ b/src/clusterfuzz/_internal/tests/core/remote_task/remote_task_test.py @@ -0,0 +1,79 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for remote_task.""" + +import unittest +from unittest import mock + +from clusterfuzz._internal.k8s import service as k8s_service +from clusterfuzz._internal.remote_task import RemoteTask +from clusterfuzz._internal.remote_task import RemoteTaskGate +from clusterfuzz._internal.tests.test_libs import test_utils + + +@test_utils.with_cloud_emulators('datastore') +class RemoteTaskGateTest(unittest.TestCase): + """Tests for RemoteTaskGate.""" + + def setUp(self): + self.gate = RemoteTaskGate() + + @mock.patch( + 'clusterfuzz._internal.remote_task.job_frequency.get_job_frequency') + @mock.patch.object(k8s_service.KubernetesService, + 'create_uworker_main_batch_jobs') + @mock.patch( + 'clusterfuzz._internal.batch.service.GcpBatchService.create_uworker_main_batch_jobs' + ) + def test_create_uworker_main_batch_jobs_k8s_limit_reached( + self, mock_gcp_create, mock_k8s_create, mock_get_frequency): + """Test delegation when K8s limit is reached (handled by service).""" + # Setup tasks to go to Kubernetes + mock_get_frequency.return_value = {'kubernetes': 1.0} + + task = RemoteTask('fuzz', 'job1', 'url1') + + # Simulate K8s service returning empty list (limit reached) + mock_k8s_create.return_value = [] + + result = self.gate.create_uworker_main_batch_jobs([task]) + + # Verify K8s was attempted + self.assertTrue(mock_k8s_create.called) + + # Verify GCP was NOT attempted + self.assertFalse(mock_gcp_create.called) + + # Verify result is empty list + self.assertEqual(result, []) + + @mock.patch( + 'clusterfuzz._internal.remote_task.job_frequency.get_job_frequency') + @mock.patch.object(k8s_service.KubernetesService, + 'create_uworker_main_batch_jobs') + @mock.patch( + 'clusterfuzz._internal.batch.service.GcpBatchService.create_uworker_main_batch_jobs' + ) + def test_create_uworker_main_batch_jobs_success( + self, mock_gcp_create, mock_k8s_create, mock_get_frequency): + """Test successful creation.""" + mock_get_frequency.return_value = {'kubernetes': 1.0} + mock_pubsub_task = mock.Mock() + mock_pubsub_task.do_not_ack = False + task = RemoteTask('fuzz', 'job1', 'url1', pubsub_task=mock_pubsub_task) + + self.gate.create_uworker_main_batch_jobs([task]) + + self.assertTrue(mock_k8s_create.called) + self.assertFalse(mock_pubsub_task.do_not_ack) diff --git a/src/local/butler/clean_jobs.py b/src/local/butler/clean_jobs.py new file mode 100644 index 00000000000..e5abc959ada --- /dev/null +++ b/src/local/butler/clean_jobs.py @@ -0,0 +1,118 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"clean_jobs.py cleans up pending kubernetes jobs." + +import datetime + +from local.butler import common + + +def execute(args): + """Run the clean_jobs command.""" + # Currently config_dir is unused but required by the argument parser for consistency. + del args + + namespace = 'default' + + while True: + print(f'Listing pending jobs in namespace \'{namespace}\'...') + + # Get list of pending jobs by checking for pending pods. + # We filter pods with status.phase=Pending and get their owner Job name. + pending_cmd = ( + "kubectl get pods -n {namespace} " + "--field-selector=status.phase=Pending " + "-o jsonpath='{{range .items[*]}}{{.metadata.ownerReferences[?(@.kind==\"Job\")].name}}{{\"\\n\"}}{{end}}'" + ).format(namespace=namespace) + + return_code, output = common.execute(pending_cmd, print_output=False) + if return_code != 0: + print('Failed to list pending pods. Ensure kubectl is configured.') + return return_code + + jobs = output.decode('utf-8').strip() + job_list = [] + if jobs: + # Filter empty strings and deduplicate + job_list = list(set([j.strip() for j in jobs.split('\n') if j.strip()])) + + # Get running pods older than 6 hours + print( + f'Listing running jobs older than 6 hours in namespace \'{namespace}\'...' + ) + running_cmd = ( + "kubectl get pods -n {namespace} " + "--field-selector=status.phase=Running " + "-o jsonpath='{{range .items[*]}}{{.metadata.creationTimestamp}},{{.metadata.ownerReferences[?(@.kind==\"Job\")].name}}{{\"\\n\"}}{{end}}'" + ).format(namespace=namespace) + + return_code, output = common.execute(running_cmd, print_output=False) + if return_code != 0: + print('Failed to list running pods. Ensure kubectl is configured.') + return return_code + + running_pods = output.decode('utf-8').strip() + if running_pods: + now = datetime.datetime.utcnow() + cutoff_time = now - datetime.timedelta(hours=6) + + for line in running_pods.split('\n'): + if not line.strip(): + continue + + parts = line.strip().split(',') + if len(parts) != 2: + continue + + creation_timestamp_str, job_name = parts + # Format from kubernetes: 2023-10-27T10:00:00Z + try: + creation_time = datetime.datetime.strptime(creation_timestamp_str, + "%Y-%m-%dT%H:%M:%SZ") + except ValueError: + print(f"Error parsing date: {creation_timestamp_str}") + continue + + if creation_time < cutoff_time: + if job_name: + job_list.append(job_name) + + # Deduplicate combined list + job_list = list(set(job_list)) + job_count = len(job_list) + print(f'Found {job_count} jobs to delete (pending + old running).') + + if job_count < 500: + print('Job count is under 500. Exiting.') + break + + # Process in batches + batch_size = 500 + for i in range(0, job_count, batch_size): + batch = job_list[i:i + batch_size] + print(f'Deleting batch of {len(batch)} jobs...') + + # We join with spaces for the command + delete_cmd = f'kubectl delete jobs -n {namespace} ' + ' '.join(batch) + + # Use execute but we need to handle potential line length issues. + # common.execute uses shell=True. + # If the command is too long, it will fail. + # 500 jobs * 50 chars avg = 25000 chars. + # Linux ARG_MAX is usually huge (2MB), so 25KB is fine. + + common.execute(delete_cmd) + + print('Finished deleting jobs.') + return 0 diff --git a/src/local/butler/scripts/run_remote_task.py b/src/local/butler/scripts/run_remote_task.py index ac0dbf49627..4b4ee08c690 100644 --- a/src/local/butler/scripts/run_remote_task.py +++ b/src/local/butler/scripts/run_remote_task.py @@ -17,6 +17,8 @@ from clusterfuzz._internal.base import tasks from clusterfuzz._internal.metrics import monitoring_metrics +from clusterfuzz._internal.remote_task import RemoteTask +from clusterfuzz._internal.remote_task import RemoteTaskGate from clusterfuzz._internal.system import environment @@ -35,22 +37,25 @@ def lease_all_tasks(task_list): def schedule_utask_mains(): """Schedules utask_mains from preprocessed utasks on Google Cloud Batch.""" - from clusterfuzz._internal.google_cloud_utils import batch print('Attempting to combine batch tasks.') utask_mains = tasks.get_utask_mains() if not utask_mains: print('No utask mains.') - return [] # Return an empty list for consistency. + return [] print(f'Combining {len(utask_mains)} batch tasks.') - + # utask_mains = utask_mains[:5] + results = [] with lease_all_tasks(utask_mains): batch_tasks = [ - batch.BatchTask(task.command, task.job, task.argument) + RemoteTask(task.command, task.job, task.argument) for task in utask_mains ] - return batch.create_uworker_main_batch_jobs(batch_tasks) + + results = RemoteTaskGate().create_uworker_main_batch_jobs(batch_tasks) + print('Created jobs:', results) + return results def execute(*args, **kwargs): # pylint: disable=unused-argument diff --git a/src/platform_requirements.txt b/src/platform_requirements.txt index 6732d4dd9ac..eeb19228808 100644 --- a/src/platform_requirements.txt +++ b/src/platform_requirements.txt @@ -1,3 +1,4 @@ grpcio==1.62.2 +kubernetes==34.1.0 protobuf==4.23.4 psutil==5.9.4 \ No newline at end of file diff --git a/src/python/bot/startup/run_bot.py b/src/python/bot/startup/run_bot.py index f36a5f7a8c0..849609736c8 100644 --- a/src/python/bot/startup/run_bot.py +++ b/src/python/bot/startup/run_bot.py @@ -17,6 +17,8 @@ # to be able to import dependencies directly, but we must store these in # subdirectories of common so that they are shared with App Engine. from clusterfuzz._internal.base import modules +from clusterfuzz._internal.remote_task import RemoteTask +from clusterfuzz._internal.remote_task import RemoteTaskGate modules.fix_module_search_paths() @@ -86,7 +88,6 @@ def lease_all_tasks(task_list): def schedule_utask_mains(): """Schedules utask_mains from preprocessed utasks on Google Cloud Batch.""" - from clusterfuzz._internal.google_cloud_utils import batch logs.info('Attempting to combine batch tasks.') utask_mains = tasks.get_utask_mains() @@ -98,10 +99,10 @@ def schedule_utask_mains(): with lease_all_tasks(utask_mains): batch_tasks = [ - batch.BatchTask(task.command, task.job, task.argument) + RemoteTask(task.command, task.job, task.argument, pubsub_task=task) for task in utask_mains ] - batch.create_uworker_main_batch_jobs(batch_tasks) + RemoteTaskGate().create_uworker_main_batch_jobs(batch_tasks) def task_loop(): diff --git a/src/setup.py b/src/setup.py index 65059382788..e9e7cba3257 100644 --- a/src/setup.py +++ b/src/setup.py @@ -45,6 +45,7 @@ 'google-cloud-storage', 'grpcio', 'httplib2', + 'kubernetes==34.1.0', 'mozprocess', 'oauth2client', 'protobuf',