diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff1bd50..92ce78e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,3 +51,4 @@ repos: - types-pyyaml - types-requests - google-api-python-client + - pytest diff --git a/poetry.lock b/poetry.lock index be63e82..289846f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,86 +1,101 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "cachetools" -version = "5.3.3" +version = "5.5.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, - {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, ] [[package]] name = "certifi" -version = "2024.7.4" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] name = "cffi" -version = "1.16.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -99,101 +114,116 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -209,38 +239,38 @@ files = [ [[package]] name = "cryptography" -version = "43.0.1" +version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"}, - {file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"}, - {file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"}, - {file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"}, - {file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"}, - {file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2"}, - {file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"}, + {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, + {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, + {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, + {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, + {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, + {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, + {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, ] [package.dependencies] @@ -253,29 +283,29 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] name = "distlib" -version = "0.3.8" +version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" files = [ - {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, - {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, ] [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -283,29 +313,29 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.14.0" +version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] -typing = ["typing-extensions (>=4.8)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "identify" -version = "2.5.36" +version = "2.6.3" description = "File identification library for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"}, - {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"}, + {file = "identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd"}, + {file = "identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02"}, ] [package.extras] @@ -313,15 +343,18 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.7" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -441,47 +474,53 @@ test = ["mypy (>=1.0)", "pytest (>=7.0.0)"] [[package]] name = "mypy" -version = "1.10.0" +version = "1.13.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, - {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, - {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, - {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, - {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, - {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, - {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, - {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, - {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, - {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, - {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, - {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, - {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, - {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, - {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, - {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, - {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, - {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, - {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, + {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, + {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, + {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, + {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, + {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, + {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, + {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, + {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, + {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, + {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, + {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, + {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, + {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, + {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, + {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, + {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, + {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, + {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, + {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, + {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] @@ -510,30 +549,30 @@ files = [ [[package]] name = "packaging" -version = "24.0" +version = "24.2" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "pluggy" @@ -552,13 +591,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.7.1" +version = "3.8.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"}, - {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"}, + {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, + {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, ] [package.dependencies] @@ -570,22 +609,22 @@ virtualenv = ">=20.10.0" [[package]] name = "protobuf" -version = "5.27.1" +version = "5.29.2" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-5.27.1-cp310-abi3-win32.whl", hash = "sha256:3adc15ec0ff35c5b2d0992f9345b04a540c1e73bfee3ff1643db43cc1d734333"}, - {file = "protobuf-5.27.1-cp310-abi3-win_amd64.whl", hash = "sha256:25236b69ab4ce1bec413fd4b68a15ef8141794427e0b4dc173e9d5d9dffc3bcd"}, - {file = "protobuf-5.27.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4e38fc29d7df32e01a41cf118b5a968b1efd46b9c41ff515234e794011c78b17"}, - {file = "protobuf-5.27.1-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:917ed03c3eb8a2d51c3496359f5b53b4e4b7e40edfbdd3d3f34336e0eef6825a"}, - {file = "protobuf-5.27.1-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:ee52874a9e69a30271649be88ecbe69d374232e8fd0b4e4b0aaaa87f429f1631"}, - {file = "protobuf-5.27.1-cp38-cp38-win32.whl", hash = "sha256:7a97b9c5aed86b9ca289eb5148df6c208ab5bb6906930590961e08f097258107"}, - {file = "protobuf-5.27.1-cp38-cp38-win_amd64.whl", hash = "sha256:f6abd0f69968792da7460d3c2cfa7d94fd74e1c21df321eb6345b963f9ec3d8d"}, - {file = "protobuf-5.27.1-cp39-cp39-win32.whl", hash = "sha256:dfddb7537f789002cc4eb00752c92e67885badcc7005566f2c5de9d969d3282d"}, - {file = "protobuf-5.27.1-cp39-cp39-win_amd64.whl", hash = "sha256:39309898b912ca6febb0084ea912e976482834f401be35840a008da12d189340"}, - {file = "protobuf-5.27.1-py3-none-any.whl", hash = "sha256:4ac7249a1530a2ed50e24201d6630125ced04b30619262f06224616e0030b6cf"}, - {file = "protobuf-5.27.1.tar.gz", hash = "sha256:df5e5b8e39b7d1c25b186ffdf9f44f40f810bbcc9d2b71d9d3156fee5a9adf15"}, + {file = "protobuf-5.29.2-cp310-abi3-win32.whl", hash = "sha256:c12ba8249f5624300cf51c3d0bfe5be71a60c63e4dcf51ffe9a68771d958c851"}, + {file = "protobuf-5.29.2-cp310-abi3-win_amd64.whl", hash = "sha256:842de6d9241134a973aab719ab42b008a18a90f9f07f06ba480df268f86432f9"}, + {file = "protobuf-5.29.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a0c53d78383c851bfa97eb42e3703aefdc96d2036a41482ffd55dc5f529466eb"}, + {file = "protobuf-5.29.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:494229ecd8c9009dd71eda5fd57528395d1eacdf307dbece6c12ad0dd09e912e"}, + {file = "protobuf-5.29.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:b6b0d416bbbb9d4fbf9d0561dbfc4e324fd522f61f7af0fe0f282ab67b22477e"}, + {file = "protobuf-5.29.2-cp38-cp38-win32.whl", hash = "sha256:e621a98c0201a7c8afe89d9646859859be97cb22b8bf1d8eacfd90d5bda2eb19"}, + {file = "protobuf-5.29.2-cp38-cp38-win_amd64.whl", hash = "sha256:13d6d617a2a9e0e82a88113d7191a1baa1e42c2cc6f5f1398d3b054c8e7e714a"}, + {file = "protobuf-5.29.2-cp39-cp39-win32.whl", hash = "sha256:36000f97ea1e76e8398a3f02936aac2a5d2b111aae9920ec1b769fc4a222c4d9"}, + {file = "protobuf-5.29.2-cp39-cp39-win_amd64.whl", hash = "sha256:2d2e674c58a06311c8e99e74be43e7f3a8d1e2b2fdf845eaa347fbd866f23355"}, + {file = "protobuf-5.29.2-py3-none-any.whl", hash = "sha256:fde4554c0e578a5a0bcc9a276339594848d1e89f9ea47b4427c80e5d72f90181"}, + {file = "protobuf-5.29.2.tar.gz", hash = "sha256:b2cc8e8bb7c9326996f0e160137b0861f1a82162502658df2951209d0cb0309e"}, ] [[package]] @@ -623,62 +662,64 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] @@ -723,13 +764,13 @@ tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asy [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] @@ -745,18 +786,18 @@ files = [ [[package]] name = "structlog" -version = "24.2.0" +version = "24.4.0" description = "Structured Logging for Python" optional = false python-versions = ">=3.8" files = [ - {file = "structlog-24.2.0-py3-none-any.whl", hash = "sha256:983bd49f70725c5e1e3867096c0c09665918936b3db27341b41d294283d7a48a"}, - {file = "structlog-24.2.0.tar.gz", hash = "sha256:0e3fe74924a6d8857d3f612739efb94c72a7417d7c7c008d12276bca3b5bf13b"}, + {file = "structlog-24.4.0-py3-none-any.whl", hash = "sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610"}, + {file = "structlog-24.4.0.tar.gz", hash = "sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4"}, ] [package.extras] dev = ["freezegun (>=0.2.8)", "mypy (>=1.4)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "rich", "simplejson", "twisted"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "sphinxext-opengraph", "twisted"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "sphinxext-opengraph", "twisted"] tests = ["freezegun (>=0.2.8)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "simplejson"] typing = ["mypy (>=1.4)", "rich", "twisted"] @@ -787,35 +828,65 @@ files = [ [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "typing-extensions" -version = "4.12.1" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"}, - {file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "2.2.2" +version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.extras] @@ -826,13 +897,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.26.2" +version = "20.28.0" description = "Virtual Python Environment builder" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"}, - {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"}, + {file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"}, + {file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"}, ] [package.dependencies] diff --git a/prefab.proto b/prefab.proto index 7af693f..9db3ad6 100644 --- a/prefab.proto +++ b/prefab.proto @@ -176,6 +176,11 @@ message Criterion { PROP_GREATER_THAN_OR_EQUAL = 19; PROP_BEFORE = 20; PROP_AFTER = 21; + PROP_MATCHES = 22; + PROP_DOES_NOT_MATCH = 23; + PROP_SEMVER_LESS_THAN = 24; + PROP_SEMVER_EQUAL = 25; + PROP_SEMVER_GREATER_THAN = 26; } string property_name = 1; CriterionOperator operator = 2; diff --git a/prefab_cloud_python/_requests.py b/prefab_cloud_python/_requests.py index 1146b04..e1e32f7 100644 --- a/prefab_cloud_python/_requests.py +++ b/prefab_cloud_python/_requests.py @@ -1,3 +1,4 @@ +import importlib from socket import socket from typing import Optional @@ -13,11 +14,16 @@ wait_exponential, retry_if_exception_type, ) -from importlib.metadata import version logger = InternalLogger(__name__) +try: + from importlib.metadata import version + + Version = version("prefab-cloud-python") +except importlib.metadata.PackageNotFoundError: + Version = "development" + -Version = version("prefab-cloud-python") VersionHeader = "X-PrefabCloud-Client-Version" DEFAULT_TIMEOUT = 5 # seconds diff --git a/prefab_cloud_python/config_resolver.py b/prefab_cloud_python/config_resolver.py index 2fa15d4..16ca786 100644 --- a/prefab_cloud_python/config_resolver.py +++ b/prefab_cloud_python/config_resolver.py @@ -5,6 +5,13 @@ from .config_value_unwrapper import ConfigValueUnwrapper from .context import Context from ._internal_logging import InternalLogger +from .simple_criterion_evaluators import ( + NumericOperators, + StringOperators, + DateOperators, + SemverOperators, + RegexMatchOperators, +) import prefab_pb2 as Prefab import google @@ -123,67 +130,42 @@ def all_criteria_match(self, conditional_value, props): def evaluate_criterion(self, criterion, properties): value_from_properties = properties.get(criterion.property_name) + deepest_value = ConfigValueUnwrapper.deepest_value( + criterion.value_to_match, self.config, properties + ) if criterion.operator in [OPS.LOOKUP_KEY_IN, OPS.PROP_IS_ONE_OF]: - return self.matches(criterion, value_from_properties, properties) + return self.one_of(criterion, value_from_properties, properties) if criterion.operator in [OPS.LOOKUP_KEY_NOT_IN, OPS.PROP_IS_NOT_ONE_OF]: - return not self.matches(criterion, value_from_properties, properties) + return not self.one_of(criterion, value_from_properties, properties) if criterion.operator == OPS.IN_SEG: return self.in_segment(criterion, properties) if criterion.operator == OPS.NOT_IN_SEG: return not self.in_segment(criterion, properties) - if criterion.operator in [ - OPS.PROP_ENDS_WITH_ONE_OF, - OPS.PROP_DOES_NOT_END_WITH_ONE_OF, - ]: - negative = criterion.operator == OPS.PROP_DOES_NOT_END_WITH_ONE_OF - if value_from_properties is None: - return self.negate(negative, False) - return self.negate( - negative, - any( - [ - str(value_from_properties).endswith(ending) - for ending in criterion.value_to_match.string_list.values - ] - ), - ) - if criterion.operator in [ - OPS.PROP_STARTS_WITH_ONE_OF, - OPS.PROP_DOES_NOT_START_WITH_ONE_OF, - ]: - negative = criterion.operator == OPS.PROP_DOES_NOT_START_WITH_ONE_OF - if value_from_properties is None: - return self.negate(negative, False) - return self.negate( - negative, - any( - [ - str(value_from_properties).startswith(beginning) - for beginning in criterion.value_to_match.string_list.values - ] - ), - ) - if criterion.operator in [ - OPS.PROP_CONTAINS_ONE_OF, - OPS.PROP_DOES_NOT_CONTAIN_ONE_OF, - ]: - negative = criterion.operator == OPS.PROP_DOES_NOT_CONTAIN_ONE_OF - if value_from_properties is None: - return self.negate(negative, False) - return self.negate( - negative, - any( - [ - string in str(value_from_properties) - for string in criterion.value_to_match.string_list.values - ] - ), + if criterion.operator in StringOperators.SUPPORTED_OPERATORS: + return StringOperators.evaluate( + value_from_properties, criterion.operator, deepest_value.unwrap() ) if criterion.operator == OPS.HIERARCHICAL_MATCH: return value_from_properties.startswith(criterion.value_to_match.string) if criterion.operator == OPS.ALWAYS_TRUE: return True + if criterion.operator in DateOperators.SUPPORTED_OPERATORS: + return DateOperators.evaluate( + value_from_properties, criterion.operator, deepest_value.unwrap() + ) + if criterion.operator in NumericOperators.SUPPORTED_OPERATORS: + return NumericOperators.evaluate( + value_from_properties, criterion.operator, deepest_value.unwrap() + ) + if criterion.operator in RegexMatchOperators.SUPPORTED_OPERATORS: + return RegexMatchOperators.evaluate( + value_from_properties, criterion.operator, deepest_value.unwrap() + ) + if criterion.operator in SemverOperators.SUPPORTED_OPERATORS: + return SemverOperators.evaluate( + value_from_properties, criterion.operator, deepest_value.unwrap() + ) logger.info(f"Unknown criterion operator {criterion.operator}") return False @@ -192,15 +174,23 @@ def evaluate_criterion(self, criterion, properties): def negate(negate, value): return not value if negate else value - def matches(self, criterion, value, properties): + @staticmethod + def _ensure_list(value): + return ( + value + if isinstance(value, (list, google._upb._message.RepeatedScalarContainer)) + else [value] + ) + + def one_of(self, criterion, value, properties): criterion_value_or_values = ConfigValueUnwrapper.deepest_value( - criterion.value_to_match, self.config.key, properties + criterion.value_to_match, self.config, properties ).unwrap() - if isinstance( - criterion_value_or_values, google._upb._message.RepeatedScalarContainer - ) or isinstance(criterion_value_or_values, list): - return str(value) in criterion_value_or_values - return value == criterion_value_or_values + + criterion_values = self._ensure_list(criterion_value_or_values) + values = self._ensure_list(value) + + return any(str(v1) == str(v2) for v1 in criterion_values for v2 in values) def in_segment(self, criterion, properties): return ( diff --git a/prefab_cloud_python/config_value_unwrapper.py b/prefab_cloud_python/config_value_unwrapper.py index 9f094d7..5ad01cf 100644 --- a/prefab_cloud_python/config_value_unwrapper.py +++ b/prefab_cloud_python/config_value_unwrapper.py @@ -1,5 +1,13 @@ import json + +from typing import TYPE_CHECKING, ForwardRef + +if TYPE_CHECKING: + from .config_resolver import ConfigResolver +else: + ConfigResolver = ForwardRef("ConfigResolver") + from .weighted_value_resolver import WeightedValueResolver from .config_value_wrapper import ConfigValueWrapper from .context import Context @@ -77,8 +85,8 @@ def reportable_value(self): @staticmethod def deepest_value( config_value: Prefab.ConfigValue, - config, - resolver, + config: Prefab.Config, + resolver: ConfigResolver, context=Context.get_current(), ): if config_value and config_value.WhichOneof("type") == "weighted_values": diff --git a/prefab_cloud_python/config_value_wrapper.py b/prefab_cloud_python/config_value_wrapper.py index 2f5f920..22d0524 100644 --- a/prefab_cloud_python/config_value_wrapper.py +++ b/prefab_cloud_python/config_value_wrapper.py @@ -1,19 +1,39 @@ +from datetime import date, datetime, timezone + import prefab_pb2 as Prefab class ConfigValueWrapper: @staticmethod def wrap(value, confidential=None): - if type(value) == int: + value_type = type(value) + + if value_type == int: return Prefab.ConfigValue(int=value, confidential=confidential) - elif type(value) == float: + elif value_type == float: return Prefab.ConfigValue(double=value, confidential=confidential) - elif type(value) == bool: + elif value_type == bool: return Prefab.ConfigValue(bool=value, confidential=confidential) - elif type(value) == list: + elif value_type == list: return Prefab.ConfigValue( string_list=Prefab.StringList(values=[str(x) for x in value]), confidential=confidential, ) + elif value_type == datetime: + return Prefab.ConfigValue( + string=ConfigValueWrapper._format_date_time(value), + confidential=confidential, + ) + elif value_type == date: + return Prefab.ConfigValue( + string=ConfigValueWrapper._format_date_time( + datetime.combine(value, datetime.min.time(), timezone.utc) + ), + confidential=confidential, + ) else: return Prefab.ConfigValue(string=value, confidential=confidential) + + @staticmethod + def _format_date_time(value: datetime): + return value.strftime("%Y-%m-%dT%H:%M:%SZ") diff --git a/prefab_cloud_python/context_shape.py b/prefab_cloud_python/context_shape.py index 55c2056..57c557f 100644 --- a/prefab_cloud_python/context_shape.py +++ b/prefab_cloud_python/context_shape.py @@ -1,8 +1,7 @@ -import json - -MAPPING = {int: 1, str: 2, float: 4, bool: 5, list: 10, json: 16} +MAPPING = {int: 1, str: 2, float: 4, bool: 5, list: 10, dict: 16} class ContextShape: + @staticmethod def field_type_number(value): - return MAPPING.setdefault(type(value), MAPPING[str]) + return MAPPING.get(type(value), 2) # default to string type diff --git a/prefab_cloud_python/semantic_version.py b/prefab_cloud_python/semantic_version.py new file mode 100644 index 0000000..b3468b2 --- /dev/null +++ b/prefab_cloud_python/semantic_version.py @@ -0,0 +1,164 @@ +from __future__ import annotations +import re +from typing import Optional + + +class SemanticVersion: + _SEMVER_PATTERN = re.compile( + r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)" + r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)" + r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?" + r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" + ) + + def __init__( + self, + major: int, + minor: int, + patch: int, + prerelease: str = "", + build_metadata: str = "", + ): + self._major = major + self._minor = minor + self._patch = patch + self._prerelease = prerelease + self._build_metadata = build_metadata + + @staticmethod + def parse_quietly(version: str) -> Optional[SemanticVersion]: + """Attempts to parse a version string, returning None if parsing fails.""" + try: + return SemanticVersion.parse(version) + except ValueError: + return None + + @staticmethod + def parse(version: str) -> SemanticVersion: + """Creates a new SemanticVersion from a version string.""" + if not version: + raise ValueError("version string cannot be empty") + + match = SemanticVersion._SEMVER_PATTERN.match(version) + if not match: + raise ValueError(f"invalid semantic version format: {version}") + + matches = match.groupdict() + try: + major = int(matches["major"]) + minor = int(matches["minor"]) + patch = int(matches["patch"]) + except ValueError as e: + raise ValueError(f"invalid version number format: {str(e)}") + + return SemanticVersion( + major=major, + minor=minor, + patch=patch, + prerelease=matches["prerelease"] or "", + build_metadata=matches["buildmetadata"] or "", + ) + + @property + def major(self) -> int: + return self._major + + @property + def minor(self) -> int: + return self._minor + + @property + def patch(self) -> int: + return self._patch + + @property + def prerelease(self) -> str: + return self._prerelease + + @property + def build_metadata(self) -> str: + return self._build_metadata + + def _compare_prerelease_identifiers(self, id1: str, id2: str) -> int: + """Compare two prerelease identifiers according to semver rules.""" + # If both are numeric + if id1.isdigit() and id2.isdigit(): + num1, num2 = int(id1), int(id2) + return 1 if num1 > num2 else (-1 if num1 < num2 else 0) + + # If one is numeric + if id1.isdigit(): + return -1 # Numeric identifiers have lower precedence + if id2.isdigit(): + return 1 + + # Neither is numeric, compare as strings + return 1 if id1 > id2 else (-1 if id1 < id2 else 0) + + def _compare_prerelease(self, other: SemanticVersion) -> int: + """Compare prerelease strings according to semver rules.""" + if not self.prerelease and not other.prerelease: + return 0 + if not self.prerelease: + return 1 + if not other.prerelease: + return -1 + + self_ids = self.prerelease.split(".") + other_ids = other.prerelease.split(".") + + for id1, id2 in zip(self_ids, other_ids): + result = self._compare_prerelease_identifiers(id1, id2) + if result != 0: + return result + + # If all identifiers match up to the length of the shorter one, + # the longer one is greater + return len(self_ids) - len(other_ids) + + def compare(self, other: SemanticVersion) -> int: + """ + Implements comparison between two semantic versions + Returns -1 if self < other, 0 if self == other, and 1 if self > other + """ + if self.major != other.major: + return 1 if self.major > other.major else -1 + + if self.minor != other.minor: + return 1 if self.minor > other.minor else -1 + + if self.patch != other.patch: + return 1 if self.patch > other.patch else -1 + + return self._compare_prerelease(other) + + def __str__(self) -> str: + result = f"{self.major}.{self.minor}.{self.patch}" + if self.prerelease: + result += f"-{self.prerelease}" + if self.build_metadata: + result += f"+{self.build_metadata}" + return result + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SemanticVersion): + return NotImplemented + return ( + self.major == other.major + and self.minor == other.minor + and self.patch == other.patch + and self.prerelease == other.prerelease + # Build metadata is ignored in equality checks + ) + + def __lt__(self, other: SemanticVersion) -> bool: + return self.compare(other) < 0 + + def __le__(self, other: SemanticVersion) -> bool: + return self.compare(other) <= 0 + + def __gt__(self, other: SemanticVersion) -> bool: + return self.compare(other) > 0 + + def __ge__(self, other: SemanticVersion) -> bool: + return self.compare(other) >= 0 diff --git a/prefab_cloud_python/simple_criterion_evaluators.py b/prefab_cloud_python/simple_criterion_evaluators.py new file mode 100644 index 0000000..146493a --- /dev/null +++ b/prefab_cloud_python/simple_criterion_evaluators.py @@ -0,0 +1,284 @@ +import re +from datetime import datetime, date, timezone +from typing import Callable, Mapping, FrozenSet, Union, Optional +import prefab_pb2 as Prefab +from types import MappingProxyType +from numbers import Real # includes both int and float + +from prefab_cloud_python.semantic_version import SemanticVersion + + +def negate(should_negate: bool, value: bool) -> bool: + return not value if should_negate else value + + +class NumericOperators: + """Handles numeric comparisons for criterion evaluation.""" + + _COMPARE_TO_EVAL: Mapping[ + Prefab.Criterion.CriterionOperator.ValueType, Callable[[int], bool] + ] = MappingProxyType( + { + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN: lambda v: v > 0, + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN_OR_EQUAL: lambda v: v + >= 0, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN: lambda v: v < 0, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN_OR_EQUAL: lambda v: v + <= 0, + } + ) + + SUPPORTED_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset(_COMPARE_TO_EVAL.keys()) + + @staticmethod + def evaluate( + context_value: Real, + operator: Prefab.Criterion.CriterionOperator.ValueType, + criterion_value: Real, + ) -> bool: + """ + Evaluates a numeric comparison between two values. + + Args: + context_value: The value from context + operator: The comparison operator to apply + criterion_value: The value from the criterion + + Returns: + True if the comparison succeeds, False otherwise + """ + if not (isinstance(criterion_value, Real) and isinstance(context_value, Real)): + return False + + comparison_result = NumericOperators._compare(context_value, criterion_value) + return NumericOperators._COMPARE_TO_EVAL[operator](comparison_result) + + @staticmethod + def _compare(a: Real, b: Real) -> int: + """Compare two numbers, returning -1, 0, or 1.""" + if a < b: + return -1 + elif a > b: + return 1 + return 0 + + +class StringOperators: + """Handles string comparisons for criterion evaluation.""" + + # Group operators by their base operation + _CONTAINS_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset( + { + Prefab.Criterion.CriterionOperator.PROP_CONTAINS_ONE_OF, + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_CONTAIN_ONE_OF, + } + ) + + _STARTS_WITH_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset( + { + Prefab.Criterion.CriterionOperator.PROP_STARTS_WITH_ONE_OF, + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_START_WITH_ONE_OF, + } + ) + + _ENDS_WITH_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset( + { + Prefab.Criterion.CriterionOperator.PROP_ENDS_WITH_ONE_OF, + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_END_WITH_ONE_OF, + } + ) + + SUPPORTED_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset(_CONTAINS_OPERATORS | _STARTS_WITH_OPERATORS | _ENDS_WITH_OPERATORS) + + _NEGATIVE_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset( + { + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_CONTAIN_ONE_OF, + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_START_WITH_ONE_OF, + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_END_WITH_ONE_OF, + } + ) + + _STRING_OPERATIONS: MappingProxyType[ + Prefab.Criterion.CriterionOperator.ValueType, Callable[[str, str], bool] + ] = MappingProxyType( + {op: lambda s, x: x in s for op in _CONTAINS_OPERATORS} + | {op: str.startswith for op in _STARTS_WITH_OPERATORS} + | {op: str.endswith for op in _ENDS_WITH_OPERATORS} + ) + + @staticmethod + def evaluate( + context_value: str, + operator: Prefab.Criterion.CriterionOperator.ValueType, + criterion_value: list[str], + ) -> bool: + if not (isinstance(context_value, str) and isinstance(criterion_value, list)): + return False + + operation = StringOperators._STRING_OPERATIONS[operator] + negative = operator in StringOperators._NEGATIVE_OPERATORS + + return negate( + negative, + any( + operation(str(context_value), test_value) + for test_value in criterion_value + ), + ) + + +class DateOperators: + """Handles date comparisons for criterion evaluation.""" + + SUPPORTED_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset( + { + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + Prefab.Criterion.CriterionOperator.PROP_AFTER, + } + ) + + @staticmethod + def evaluate( + context_value: Union[str, Real, datetime, date], + operator: Prefab.Criterion.CriterionOperator.ValueType, + criterion_value: int, + ) -> bool: + if not ( + isinstance(context_value, (str, Real, datetime, date)) + and isinstance(criterion_value, int) + ): + return False + + try: + # Convert context_value to milliseconds since epoch + if isinstance(context_value, str): + # Handle RFC3339 string + # Replace 'Z' with '+00:00' for compatibility with fromisoformat + if context_value.endswith("Z"): + context_value = context_value[:-1] + "+00:00" + dt = datetime.fromisoformat(context_value) + context_millis = int(dt.timestamp() * 1000) + elif isinstance(context_value, datetime): + context_millis = int(context_value.timestamp() * 1000) + elif isinstance(context_value, date): + context_millis = ( + int( + datetime.combine( + context_value, datetime.min.time(), timezone.utc + ).timestamp() + ) + * 1000 + ) + else: + context_millis = int(float(context_value)) + + # Perform comparison based on operator + if operator == Prefab.Criterion.CriterionOperator.PROP_BEFORE: + return context_millis < criterion_value + elif operator == Prefab.Criterion.CriterionOperator.PROP_AFTER: + return context_millis > criterion_value + else: + return False + + except (ValueError, TypeError): + return False + + +class SemverOperators: + """Handles semver comparisons for criterion evaluation.""" + + SUPPORTED_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset( + { + Prefab.Criterion.CriterionOperator.PROP_SEMVER_EQUAL, + Prefab.Criterion.CriterionOperator.PROP_SEMVER_GREATER_THAN, + Prefab.Criterion.CriterionOperator.PROP_SEMVER_LESS_THAN, + } + ) + + @staticmethod + def evaluate( + context_value: str, + operator: Prefab.Criterion.CriterionOperator.ValueType, + criterion_value: str, + ) -> bool: + # Parse both versions, return False if either parse fails + context_semver = SemanticVersion.parse_quietly(context_value) + criterion_semver = SemanticVersion.parse_quietly(criterion_value) + + if context_semver is None or criterion_semver is None: + return False + + if operator == Prefab.Criterion.CriterionOperator.PROP_SEMVER_EQUAL: + return context_semver == criterion_semver + + if operator == Prefab.Criterion.CriterionOperator.PROP_SEMVER_GREATER_THAN: + return context_semver > criterion_semver + + if operator == Prefab.Criterion.CriterionOperator.PROP_SEMVER_LESS_THAN: + return context_semver < criterion_semver + + return False # Unsupported operator + + +class RegexMatchOperators: + """Handles regex matching comparisons for criterion evaluation.""" + + SUPPORTED_OPERATORS: FrozenSet[ + Prefab.Criterion.CriterionOperator.ValueType + ] = frozenset( + { + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_MATCH, + } + ) + + @staticmethod + def _compile_pattern(pattern: str) -> Optional[re.Pattern]: + """ + Attempts to compile a regex pattern, returning None if compilation fails. + """ + try: + return re.compile(pattern) + except (re.error, TypeError): + return None + + @staticmethod + def evaluate( + context_value: str, + operator: Prefab.Criterion.CriterionOperator.ValueType, + criterion_value: str, + ) -> bool: + # Handle non-string inputs + if not isinstance(context_value, str) or not isinstance(criterion_value, str): + return False + + # Try to compile the pattern + pattern = RegexMatchOperators._compile_pattern(criterion_value) + if pattern is None: + return False + + # Perform the match + try: + matches = bool(pattern.search(context_value)) + return negate( + operator == Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_MATCH, + matches, + ) + except (re.error, TypeError): + return False diff --git a/prefab_pb2.py b/prefab_pb2.py index 6f3018d..6b4c4e0 100644 --- a/prefab_pb2.py +++ b/prefab_pb2.py @@ -13,7 +13,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cprefab.proto\x12\x06prefab\"{\n\x14\x43onfigServicePointer\x12\x1d\n\nproject_id\x18\x01 \x01(\x03R\tprojectId\x12\x1e\n\x0bstart_at_id\x18\x02 \x01(\x03R\tstartAtId\x12$\n\x0eproject_env_id\x18\x03 \x01(\x03R\x0cprojectEnvId\"\xa7\x05\n\x0b\x43onfigValue\x12\x12\n\x03int\x18\x01 \x01(\x03H\x00R\x03int\x12\x18\n\x06string\x18\x02 \x01(\tH\x00R\x06string\x12\x16\n\x05\x62ytes\x18\x03 \x01(\x0cH\x00R\x05\x62ytes\x12\x18\n\x06\x64ouble\x18\x04 \x01(\x01H\x00R\x06\x64ouble\x12\x14\n\x04\x62ool\x18\x05 \x01(\x08H\x00R\x04\x62ool\x12\x41\n\x0fweighted_values\x18\x06 \x01(\x0b\x32\x16.prefab.WeightedValuesH\x00R\x0eweightedValues\x12\x44\n\x10limit_definition\x18\x07 \x01(\x0b\x32\x17.prefab.LimitDefinitionH\x00R\x0flimitDefinition\x12/\n\tlog_level\x18\t \x01(\x0e\x32\x10.prefab.LogLevelH\x00R\x08logLevel\x12\x35\n\x0bstring_list\x18\n \x01(\x0b\x32\x12.prefab.StringListH\x00R\nstringList\x12/\n\tint_range\x18\x0b \x01(\x0b\x32\x10.prefab.IntRangeH\x00R\x08intRange\x12.\n\x08provided\x18\x0c \x01(\x0b\x32\x10.prefab.ProvidedH\x00R\x08provided\x12\x31\n\x08\x64uration\x18\x0f \x01(\x0b\x32\x13.prefab.IsoDurationH\x00R\x08\x64uration\x12\"\n\x04json\x18\x10 \x01(\x0b\x32\x0c.prefab.JsonH\x00R\x04json\x12\'\n\x0c\x63onfidential\x18\r \x01(\x08H\x01R\x0c\x63onfidential\x88\x01\x01\x12&\n\x0c\x64\x65\x63rypt_with\x18\x0e \x01(\tH\x02R\x0b\x64\x65\x63ryptWith\x88\x01\x01\x42\x06\n\x04typeB\x0f\n\r_confidentialB\x0f\n\r_decrypt_with\"\x1a\n\x04Json\x12\x12\n\x04json\x18\x01 \x01(\tR\x04json\"-\n\x0bIsoDuration\x12\x1e\n\ndefinition\x18\x01 \x01(\tR\ndefinition\"r\n\x08Provided\x12\x33\n\x06source\x18\x01 \x01(\x0e\x32\x16.prefab.ProvidedSourceH\x00R\x06source\x88\x01\x01\x12\x1b\n\x06lookup\x18\x02 \x01(\tH\x01R\x06lookup\x88\x01\x01\x42\t\n\x07_sourceB\t\n\x07_lookup\"N\n\x08IntRange\x12\x19\n\x05start\x18\x01 \x01(\x03H\x00R\x05start\x88\x01\x01\x12\x15\n\x03\x65nd\x18\x02 \x01(\x03H\x01R\x03\x65nd\x88\x01\x01\x42\x08\n\x06_startB\x06\n\x04_end\"$\n\nStringList\x12\x16\n\x06values\x18\x01 \x03(\tR\x06values\"R\n\rWeightedValue\x12\x16\n\x06weight\x18\x01 \x01(\x05R\x06weight\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value\"\xa2\x01\n\x0eWeightedValues\x12>\n\x0fweighted_values\x18\x01 \x03(\x0b\x32\x15.prefab.WeightedValueR\x0eweightedValues\x12\x36\n\x15hash_by_property_name\x18\x02 \x01(\tH\x00R\x12hashByPropertyName\x88\x01\x01\x42\x18\n\x16_hash_by_property_name\"g\n\x0e\x41piKeyMetadata\x12\x1a\n\x06key_id\x18\x01 \x01(\tH\x00R\x05keyId\x88\x01\x01\x12\x1c\n\x07user_id\x18\x03 \x01(\tH\x01R\x06userId\x88\x01\x01\x42\t\n\x07_key_idB\n\n\x08_user_idJ\x04\x08\x02\x10\x03\"\xea\x02\n\x07\x43onfigs\x12(\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x0e.prefab.ConfigR\x07\x63onfigs\x12R\n\x16\x63onfig_service_pointer\x18\x02 \x01(\x0b\x32\x1c.prefab.ConfigServicePointerR\x14\x63onfigServicePointer\x12\x44\n\x0f\x61pikey_metadata\x18\x03 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00R\x0e\x61pikeyMetadata\x88\x01\x01\x12@\n\x0f\x64\x65\x66\x61ult_context\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSetH\x01R\x0e\x64\x65\x66\x61ultContext\x88\x01\x01\x12\"\n\nkeep_alive\x18\x05 \x01(\x08H\x02R\tkeepAlive\x88\x01\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_contextB\r\n\x0b_keep_alive\"\xe3\x04\n\x06\x43onfig\x12\x0e\n\x02id\x18\x01 \x01(\x03R\x02id\x12\x1d\n\nproject_id\x18\x02 \x01(\x03R\tprojectId\x12\x10\n\x03key\x18\x03 \x01(\tR\x03key\x12\x30\n\nchanged_by\x18\x04 \x01(\x0b\x32\x11.prefab.ChangedByR\tchangedBy\x12%\n\x04rows\x18\x05 \x03(\x0b\x32\x11.prefab.ConfigRowR\x04rows\x12>\n\x10\x61llowable_values\x18\x06 \x03(\x0b\x32\x13.prefab.ConfigValueR\x0f\x61llowableValues\x12\x33\n\x0b\x63onfig_type\x18\x07 \x01(\x0e\x32\x12.prefab.ConfigTypeR\nconfigType\x12\x1e\n\x08\x64raft_id\x18\x08 \x01(\x03H\x00R\x07\x64raftId\x88\x01\x01\x12\x37\n\nvalue_type\x18\t \x01(\x0e\x32\x18.prefab.Config.ValueTypeR\tvalueType\x12+\n\x12send_to_client_sdk\x18\n \x01(\x08R\x0fsendToClientSdk\"\xb6\x01\n\tValueType\x12\x16\n\x12NOT_SET_VALUE_TYPE\x10\x00\x12\x07\n\x03INT\x10\x01\x12\n\n\x06STRING\x10\x02\x12\t\n\x05\x42YTES\x10\x03\x12\n\n\x06\x44OUBLE\x10\x04\x12\x08\n\x04\x42OOL\x10\x05\x12\x14\n\x10LIMIT_DEFINITION\x10\x07\x12\r\n\tLOG_LEVEL\x10\t\x12\x0f\n\x0bSTRING_LIST\x10\n\x12\r\n\tINT_RANGE\x10\x0b\x12\x0c\n\x08\x44URATION\x10\x0c\x12\x08\n\x04JSON\x10\rB\x0b\n\t_draft_id\"X\n\tChangedBy\x12\x17\n\x07user_id\x18\x01 \x01(\x03R\x06userId\x12\x14\n\x05\x65mail\x18\x02 \x01(\tR\x05\x65mail\x12\x1c\n\napi_key_id\x18\x03 \x01(\tR\x08\x61piKeyId\"\x92\x02\n\tConfigRow\x12)\n\x0eproject_env_id\x18\x01 \x01(\x03H\x00R\x0cprojectEnvId\x88\x01\x01\x12\x30\n\x06values\x18\x02 \x03(\x0b\x32\x18.prefab.ConditionalValueR\x06values\x12\x41\n\nproperties\x18\x03 \x03(\x0b\x32!.prefab.ConfigRow.PropertiesEntryR\nproperties\x1aR\n\x0fPropertiesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value:\x02\x38\x01\x42\x11\n\x0f_project_env_id\"l\n\x10\x43onditionalValue\x12-\n\x08\x63riteria\x18\x01 \x03(\x0b\x32\x11.prefab.CriterionR\x08\x63riteria\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value\"\xc1\x05\n\tCriterion\x12#\n\rproperty_name\x18\x01 \x01(\tR\x0cpropertyName\x12?\n\x08operator\x18\x02 \x01(\x0e\x32#.prefab.Criterion.CriterionOperatorR\x08operator\x12\x39\n\x0evalue_to_match\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValueR\x0cvalueToMatch\"\x92\x04\n\x11\x43riterionOperator\x12\x0b\n\x07NOT_SET\x10\x00\x12\x11\n\rLOOKUP_KEY_IN\x10\x01\x12\x15\n\x11LOOKUP_KEY_NOT_IN\x10\x02\x12\n\n\x06IN_SEG\x10\x03\x12\x0e\n\nNOT_IN_SEG\x10\x04\x12\x0f\n\x0b\x41LWAYS_TRUE\x10\x05\x12\x12\n\x0ePROP_IS_ONE_OF\x10\x06\x12\x16\n\x12PROP_IS_NOT_ONE_OF\x10\x07\x12\x19\n\x15PROP_ENDS_WITH_ONE_OF\x10\x08\x12!\n\x1dPROP_DOES_NOT_END_WITH_ONE_OF\x10\t\x12\x16\n\x12HIERARCHICAL_MATCH\x10\n\x12\x10\n\x0cIN_INT_RANGE\x10\x0b\x12\x1b\n\x17PROP_STARTS_WITH_ONE_OF\x10\x0c\x12#\n\x1fPROP_DOES_NOT_START_WITH_ONE_OF\x10\r\x12\x18\n\x14PROP_CONTAINS_ONE_OF\x10\x0e\x12 \n\x1cPROP_DOES_NOT_CONTAIN_ONE_OF\x10\x0f\x12\x12\n\x0ePROP_LESS_THAN\x10\x10\x12\x1b\n\x17PROP_LESS_THAN_OR_EQUAL\x10\x11\x12\x15\n\x11PROP_GREATER_THAN\x10\x12\x12\x1e\n\x1aPROP_GREATER_THAN_OR_EQUAL\x10\x13\x12\x0f\n\x0bPROP_BEFORE\x10\x14\x12\x0e\n\nPROP_AFTER\x10\x15\"\xbb\x01\n\x07Loggers\x12(\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.LoggerR\x07loggers\x12\x19\n\x08start_at\x18\x02 \x01(\x03R\x07startAt\x12\x15\n\x06\x65nd_at\x18\x03 \x01(\x03R\x05\x65ndAt\x12#\n\rinstance_hash\x18\x04 \x01(\tR\x0cinstanceHash\x12!\n\tnamespace\x18\x05 \x01(\tH\x00R\tnamespace\x88\x01\x01\x42\x0c\n\n_namespace\"\x93\x02\n\x06Logger\x12\x1f\n\x0blogger_name\x18\x01 \x01(\tR\nloggerName\x12\x1b\n\x06traces\x18\x02 \x01(\x03H\x00R\x06traces\x88\x01\x01\x12\x1b\n\x06\x64\x65\x62ugs\x18\x03 \x01(\x03H\x01R\x06\x64\x65\x62ugs\x88\x01\x01\x12\x19\n\x05infos\x18\x04 \x01(\x03H\x02R\x05infos\x88\x01\x01\x12\x19\n\x05warns\x18\x05 \x01(\x03H\x03R\x05warns\x88\x01\x01\x12\x1b\n\x06\x65rrors\x18\x06 \x01(\x03H\x04R\x06\x65rrors\x88\x01\x01\x12\x1b\n\x06\x66\x61tals\x18\x07 \x01(\x03H\x05R\x06\x66\x61tals\x88\x01\x01\x42\t\n\x07_tracesB\t\n\x07_debugsB\x08\n\x06_infosB\x08\n\x06_warnsB\t\n\x07_errorsB\t\n\x07_fatals\"\x16\n\x14LoggerReportResponse\"\xd5\x04\n\rLimitResponse\x12\x16\n\x06passed\x18\x01 \x01(\x08R\x06passed\x12\x1d\n\nexpires_at\x18\x02 \x01(\x03R\texpiresAt\x12%\n\x0e\x65nforced_group\x18\x03 \x01(\tR\renforcedGroup\x12%\n\x0e\x63urrent_bucket\x18\x04 \x01(\x03R\rcurrentBucket\x12!\n\x0cpolicy_group\x18\x05 \x01(\tR\x0bpolicyGroup\x12G\n\x0bpolicy_name\x18\x06 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNamesR\npolicyName\x12!\n\x0cpolicy_limit\x18\x07 \x01(\x05R\x0bpolicyLimit\x12\x16\n\x06\x61mount\x18\x08 \x01(\x03R\x06\x61mount\x12$\n\x0elimit_reset_at\x18\t \x01(\x03R\x0climitResetAt\x12\x46\n\x0csafety_level\x18\n \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevelR\x0bsafetyLevel\"\xa9\x01\n\x10LimitPolicyNames\x12\x0b\n\x07NOT_SET\x10\x00\x12\x14\n\x10SECONDLY_ROLLING\x10\x01\x12\x14\n\x10MINUTELY_ROLLING\x10\x03\x12\x12\n\x0eHOURLY_ROLLING\x10\x05\x12\x11\n\rDAILY_ROLLING\x10\x07\x12\x13\n\x0fMONTHLY_ROLLING\x10\x08\x12\x0c\n\x08INFINITE\x10\t\x12\x12\n\x0eYEARLY_ROLLING\x10\n\"\xed\x02\n\x0cLimitRequest\x12\x1d\n\naccount_id\x18\x01 \x01(\x03R\taccountId\x12%\n\x0e\x61\x63quire_amount\x18\x02 \x01(\x05R\racquireAmount\x12\x16\n\x06groups\x18\x03 \x03(\tR\x06groups\x12I\n\x0elimit_combiner\x18\x04 \x01(\x0e\x32\".prefab.LimitRequest.LimitCombinerR\rlimitCombiner\x12\x34\n\x16\x61llow_partial_response\x18\x05 \x01(\x08R\x14\x61llowPartialResponse\x12\x46\n\x0csafety_level\x18\x06 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevelR\x0bsafetyLevel\"6\n\rLimitCombiner\x12\x0b\n\x07NOT_SET\x10\x00\x12\x0b\n\x07MINIMUM\x10\x01\x12\x0b\n\x07MAXIMUM\x10\x02\"9\n\nContextSet\x12+\n\x08\x63ontexts\x18\x01 \x03(\x0b\x32\x0f.prefab.ContextR\x08\x63ontexts\"\xb0\x01\n\x07\x43ontext\x12\x17\n\x04type\x18\x01 \x01(\tH\x00R\x04type\x88\x01\x01\x12\x33\n\x06values\x18\x02 \x03(\x0b\x32\x1b.prefab.Context.ValuesEntryR\x06values\x1aN\n\x0bValuesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value:\x02\x38\x01\x42\x07\n\x05_type\"\xb3\x01\n\x08Identity\x12\x1b\n\x06lookup\x18\x01 \x01(\tH\x00R\x06lookup\x88\x01\x01\x12@\n\nattributes\x18\x02 \x03(\x0b\x32 .prefab.Identity.AttributesEntryR\nattributes\x1a=\n\x0f\x41ttributesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\t\n\x07_lookup\"\xa6\x03\n\x18\x43onfigEvaluationMetaData\x12-\n\x10\x63onfig_row_index\x18\x01 \x01(\x03H\x00R\x0e\x63onfigRowIndex\x88\x01\x01\x12;\n\x17\x63onditional_value_index\x18\x02 \x01(\x03H\x01R\x15\x63onditionalValueIndex\x88\x01\x01\x12\x35\n\x14weighted_value_index\x18\x03 \x01(\x03H\x02R\x12weightedValueIndex\x88\x01\x01\x12+\n\x04type\x18\x04 \x01(\x0e\x32\x12.prefab.ConfigTypeH\x03R\x04type\x88\x01\x01\x12\x13\n\x02id\x18\x05 \x01(\x03H\x04R\x02id\x88\x01\x01\x12<\n\nvalue_type\x18\x06 \x01(\x0e\x32\x18.prefab.Config.ValueTypeH\x05R\tvalueType\x88\x01\x01\x42\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_indexB\x07\n\x05_typeB\x05\n\x03_idB\r\n\x0b_value_type\"\xf0\x03\n\x11\x43lientConfigValue\x12\x12\n\x03int\x18\x01 \x01(\x03H\x00R\x03int\x12\x18\n\x06string\x18\x02 \x01(\tH\x00R\x06string\x12\x18\n\x06\x64ouble\x18\x03 \x01(\x01H\x00R\x06\x64ouble\x12\x14\n\x04\x62ool\x18\x04 \x01(\x08H\x00R\x04\x62ool\x12/\n\tlog_level\x18\x05 \x01(\x0e\x32\x10.prefab.LogLevelH\x00R\x08logLevel\x12\x35\n\x0bstring_list\x18\x07 \x01(\x0b\x32\x12.prefab.StringListH\x00R\nstringList\x12/\n\tint_range\x18\x08 \x01(\x0b\x32\x10.prefab.IntRangeH\x00R\x08intRange\x12\x34\n\x08\x64uration\x18\t \x01(\x0b\x32\x16.prefab.ClientDurationH\x00R\x08\x64uration\x12\"\n\x04json\x18\n \x01(\x0b\x32\x0c.prefab.JsonH\x00R\x04json\x12\x63\n\x1a\x63onfig_evaluation_metadata\x18\x06 \x01(\x0b\x32 .prefab.ConfigEvaluationMetaDataH\x01R\x18\x63onfigEvaluationMetadata\x88\x01\x01\x42\x06\n\x04typeB\x1d\n\x1b_config_evaluation_metadata\"`\n\x0e\x43lientDuration\x12\x18\n\x07seconds\x18\x01 \x01(\x03R\x07seconds\x12\x14\n\x05nanos\x18\x02 \x01(\x05R\x05nanos\x12\x1e\n\ndefinition\x18\x03 \x01(\tR\ndefinition\"\xd8\x02\n\x11\x43onfigEvaluations\x12=\n\x06values\x18\x01 \x03(\x0b\x32%.prefab.ConfigEvaluations.ValuesEntryR\x06values\x12\x44\n\x0f\x61pikey_metadata\x18\x02 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00R\x0e\x61pikeyMetadata\x88\x01\x01\x12@\n\x0f\x64\x65\x66\x61ult_context\x18\x03 \x01(\x0b\x32\x12.prefab.ContextSetH\x01R\x0e\x64\x65\x66\x61ultContext\x88\x01\x01\x1aT\n\x0bValuesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12/\n\x05value\x18\x02 \x01(\x0b\x32\x19.prefab.ClientConfigValueR\x05value:\x02\x38\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_context\"\xf4\x02\n\x0fLimitDefinition\x12G\n\x0bpolicy_name\x18\x02 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNamesR\npolicyName\x12\x14\n\x05limit\x18\x03 \x01(\x05R\x05limit\x12\x14\n\x05\x62urst\x18\x04 \x01(\x05R\x05\x62urst\x12\x1d\n\naccount_id\x18\x05 \x01(\x03R\taccountId\x12#\n\rlast_modified\x18\x06 \x01(\x03R\x0clastModified\x12\x1e\n\nreturnable\x18\x07 \x01(\x08R\nreturnable\x12\x46\n\x0csafety_level\x18\x08 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevelR\x0bsafetyLevel\"@\n\x0bSafetyLevel\x12\x0b\n\x07NOT_SET\x10\x00\x12\x12\n\x0eL4_BEST_EFFORT\x10\x04\x12\x10\n\x0cL5_BOMBPROOF\x10\x05\"M\n\x10LimitDefinitions\x12\x39\n\x0b\x64\x65\x66initions\x18\x01 \x03(\x0b\x32\x17.prefab.LimitDefinitionR\x0b\x64\x65\x66initions\"\xc8\x01\n\x0f\x42ufferedRequest\x12\x1d\n\naccount_id\x18\x01 \x01(\x03R\taccountId\x12\x16\n\x06method\x18\x02 \x01(\tR\x06method\x12\x10\n\x03uri\x18\x03 \x01(\tR\x03uri\x12\x12\n\x04\x62ody\x18\x04 \x01(\tR\x04\x62ody\x12!\n\x0climit_groups\x18\x05 \x03(\tR\x0blimitGroups\x12!\n\x0c\x63ontent_type\x18\x06 \x01(\tR\x0b\x63ontentType\x12\x12\n\x04\x66ifo\x18\x07 \x01(\x08R\x04\x66ifo\"\xde\x01\n\x0c\x42\x61tchRequest\x12\x1d\n\naccount_id\x18\x01 \x01(\x03R\taccountId\x12\x16\n\x06method\x18\x02 \x01(\tR\x06method\x12\x10\n\x03uri\x18\x03 \x01(\tR\x03uri\x12\x12\n\x04\x62ody\x18\x04 \x01(\tR\x04\x62ody\x12!\n\x0climit_groups\x18\x05 \x03(\tR\x0blimitGroups\x12%\n\x0e\x62\x61tch_template\x18\x06 \x01(\tR\rbatchTemplate\x12\'\n\x0f\x62\x61tch_separator\x18\x07 \x01(\tR\x0e\x62\x61tchSeparator\")\n\rBasicResponse\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\"C\n\x10\x43reationResponse\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\x12\x15\n\x06new_id\x18\x02 \x01(\x03R\x05newId\"\x9b\x01\n\x07IdBlock\x12\x1d\n\nproject_id\x18\x01 \x01(\x03R\tprojectId\x12$\n\x0eproject_env_id\x18\x02 \x01(\x03R\x0cprojectEnvId\x12#\n\rsequence_name\x18\x03 \x01(\tR\x0csequenceName\x12\x14\n\x05start\x18\x04 \x01(\x03R\x05start\x12\x10\n\x03\x65nd\x18\x05 \x01(\x03R\x03\x65nd\"\x8e\x01\n\x0eIdBlockRequest\x12\x1d\n\nproject_id\x18\x01 \x01(\x03R\tprojectId\x12$\n\x0eproject_env_id\x18\x02 \x01(\x03R\x0cprojectEnvId\x12#\n\rsequence_name\x18\x03 \x01(\tR\x0csequenceName\x12\x12\n\x04size\x18\x04 \x01(\x03R\x04size\"\xa8\x01\n\x0c\x43ontextShape\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12\x45\n\x0b\x66ield_types\x18\x02 \x03(\x0b\x32$.prefab.ContextShape.FieldTypesEntryR\nfieldTypes\x1a=\n\x0f\x46ieldTypesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01\"n\n\rContextShapes\x12,\n\x06shapes\x18\x01 \x03(\x0b\x32\x14.prefab.ContextShapeR\x06shapes\x12!\n\tnamespace\x18\x02 \x01(\tH\x00R\tnamespace\x88\x01\x01\x42\x0c\n\n_namespace\"T\n\rEvaluatedKeys\x12\x12\n\x04keys\x18\x01 \x03(\tR\x04keys\x12!\n\tnamespace\x18\x02 \x01(\tH\x00R\tnamespace\x88\x01\x01\x42\x0c\n\n_namespace\"\xc3\x01\n\x0f\x45valuatedConfig\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12%\n\x0e\x63onfig_version\x18\x02 \x01(\x03R\rconfigVersion\x12+\n\x06result\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValueR\x06result\x12,\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSetR\x07\x63ontext\x12\x1c\n\ttimestamp\x18\x05 \x01(\x03R\ttimestamp\"E\n\x10\x45valuatedConfigs\x12\x31\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x17.prefab.EvaluatedConfigR\x07\x63onfigs\"\xb6\x04\n\x17\x43onfigEvaluationCounter\x12\x14\n\x05\x63ount\x18\x01 \x01(\x03R\x05\x63ount\x12 \n\tconfig_id\x18\x02 \x01(\x03H\x00R\x08\x63onfigId\x88\x01\x01\x12*\n\x0eselected_index\x18\x03 \x01(\rH\x01R\rselectedIndex\x88\x01\x01\x12?\n\x0eselected_value\x18\x04 \x01(\x0b\x32\x13.prefab.ConfigValueH\x02R\rselectedValue\x88\x01\x01\x12-\n\x10\x63onfig_row_index\x18\x05 \x01(\rH\x03R\x0e\x63onfigRowIndex\x88\x01\x01\x12;\n\x17\x63onditional_value_index\x18\x06 \x01(\rH\x04R\x15\x63onditionalValueIndex\x88\x01\x01\x12\x35\n\x14weighted_value_index\x18\x07 \x01(\rH\x05R\x12weightedValueIndex\x88\x01\x01\x12>\n\x06reason\x18\x08 \x01(\x0e\x32&.prefab.ConfigEvaluationCounter.ReasonR\x06reason\"\x15\n\x06Reason\x12\x0b\n\x07UNKNOWN\x10\x00\x42\x0c\n\n_config_idB\x11\n\x0f_selected_indexB\x11\n\x0f_selected_valueB\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_index\"\x90\x01\n\x17\x43onfigEvaluationSummary\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12&\n\x04type\x18\x02 \x01(\x0e\x32\x12.prefab.ConfigTypeR\x04type\x12;\n\x08\x63ounters\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationCounterR\x08\x63ounters\"\x82\x01\n\x19\x43onfigEvaluationSummaries\x12\x14\n\x05start\x18\x01 \x01(\x03R\x05start\x12\x10\n\x03\x65nd\x18\x02 \x01(\x03R\x03\x65nd\x12=\n\tsummaries\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationSummaryR\tsummaries\"s\n\x15LoggersTelemetryEvent\x12(\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.LoggerR\x07loggers\x12\x19\n\x08start_at\x18\x02 \x01(\x03R\x07startAt\x12\x15\n\x06\x65nd_at\x18\x03 \x01(\x03R\x05\x65ndAt\"\xd9\x02\n\x0eTelemetryEvent\x12\x41\n\tsummaries\x18\x02 \x01(\x0b\x32!.prefab.ConfigEvaluationSummariesH\x00R\tsummaries\x12\x44\n\x10\x65xample_contexts\x18\x03 \x01(\x0b\x32\x17.prefab.ExampleContextsH\x00R\x0f\x65xampleContexts\x12\x38\n\x0c\x63lient_stats\x18\x04 \x01(\x0b\x32\x13.prefab.ClientStatsH\x00R\x0b\x63lientStats\x12\x39\n\x07loggers\x18\x05 \x01(\x0b\x32\x1d.prefab.LoggersTelemetryEventH\x00R\x07loggers\x12>\n\x0e\x63ontext_shapes\x18\x06 \x01(\x0b\x32\x15.prefab.ContextShapesH\x00R\rcontextShapesB\t\n\x07payload\"f\n\x0fTelemetryEvents\x12#\n\rinstance_hash\x18\x01 \x01(\tR\x0cinstanceHash\x12.\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x16.prefab.TelemetryEventR\x06\x65vents\"3\n\x17TelemetryEventsResponse\x12\x18\n\x07success\x18\x01 \x01(\x08R\x07success\"E\n\x0f\x45xampleContexts\x12\x32\n\x08\x65xamples\x18\x01 \x03(\x0b\x32\x16.prefab.ExampleContextR\x08\x65xamples\"b\n\x0e\x45xampleContext\x12\x1c\n\ttimestamp\x18\x01 \x01(\x03R\ttimestamp\x12\x32\n\ncontextSet\x18\x02 \x01(\x0b\x32\x12.prefab.ContextSetR\ncontextSet\"e\n\x0b\x43lientStats\x12\x14\n\x05start\x18\x01 \x01(\x03R\x05start\x12\x10\n\x03\x65nd\x18\x02 \x01(\x03R\x03\x65nd\x12.\n\x13\x64ropped_event_count\x18\x03 \x01(\x04R\x11\x64roppedEventCount*:\n\x0eProvidedSource\x12\x1b\n\x17PROVIDED_SOURCE_NOT_SET\x10\x00\x12\x0b\n\x07\x45NV_VAR\x10\x01*\x82\x01\n\nConfigType\x12\x17\n\x13NOT_SET_CONFIG_TYPE\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\x10\n\x0c\x46\x45\x41TURE_FLAG\x10\x02\x12\r\n\tLOG_LEVEL\x10\x03\x12\x0b\n\x07SEGMENT\x10\x04\x12\x14\n\x10LIMIT_DEFINITION\x10\x05\x12\x0b\n\x07\x44\x45LETED\x10\x06*a\n\x08LogLevel\x12\x15\n\x11NOT_SET_LOG_LEVEL\x10\x00\x12\t\n\x05TRACE\x10\x01\x12\t\n\x05\x44\x45\x42UG\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\x08\n\x04WARN\x10\x05\x12\t\n\x05\x45RROR\x10\x06\x12\t\n\x05\x46\x41TAL\x10\t*G\n\tOnFailure\x12\x0b\n\x07NOT_SET\x10\x00\x12\x10\n\x0cLOG_AND_PASS\x10\x01\x12\x10\n\x0cLOG_AND_FAIL\x10\x02\x12\t\n\x05THROW\x10\x03\x42L\n\x13\x63loud.prefab.domainB\x06PrefabZ-github.com/prefab-cloud/prefab-cloud-go/protob\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cprefab.proto\x12\x06prefab\"{\n\x14\x43onfigServicePointer\x12\x1d\n\nproject_id\x18\x01 \x01(\x03R\tprojectId\x12\x1e\n\x0bstart_at_id\x18\x02 \x01(\x03R\tstartAtId\x12$\n\x0eproject_env_id\x18\x03 \x01(\x03R\x0cprojectEnvId\"\xa7\x05\n\x0b\x43onfigValue\x12\x12\n\x03int\x18\x01 \x01(\x03H\x00R\x03int\x12\x18\n\x06string\x18\x02 \x01(\tH\x00R\x06string\x12\x16\n\x05\x62ytes\x18\x03 \x01(\x0cH\x00R\x05\x62ytes\x12\x18\n\x06\x64ouble\x18\x04 \x01(\x01H\x00R\x06\x64ouble\x12\x14\n\x04\x62ool\x18\x05 \x01(\x08H\x00R\x04\x62ool\x12\x41\n\x0fweighted_values\x18\x06 \x01(\x0b\x32\x16.prefab.WeightedValuesH\x00R\x0eweightedValues\x12\x44\n\x10limit_definition\x18\x07 \x01(\x0b\x32\x17.prefab.LimitDefinitionH\x00R\x0flimitDefinition\x12/\n\tlog_level\x18\t \x01(\x0e\x32\x10.prefab.LogLevelH\x00R\x08logLevel\x12\x35\n\x0bstring_list\x18\n \x01(\x0b\x32\x12.prefab.StringListH\x00R\nstringList\x12/\n\tint_range\x18\x0b \x01(\x0b\x32\x10.prefab.IntRangeH\x00R\x08intRange\x12.\n\x08provided\x18\x0c \x01(\x0b\x32\x10.prefab.ProvidedH\x00R\x08provided\x12\x31\n\x08\x64uration\x18\x0f \x01(\x0b\x32\x13.prefab.IsoDurationH\x00R\x08\x64uration\x12\"\n\x04json\x18\x10 \x01(\x0b\x32\x0c.prefab.JsonH\x00R\x04json\x12\'\n\x0c\x63onfidential\x18\r \x01(\x08H\x01R\x0c\x63onfidential\x88\x01\x01\x12&\n\x0c\x64\x65\x63rypt_with\x18\x0e \x01(\tH\x02R\x0b\x64\x65\x63ryptWith\x88\x01\x01\x42\x06\n\x04typeB\x0f\n\r_confidentialB\x0f\n\r_decrypt_with\"\x1a\n\x04Json\x12\x12\n\x04json\x18\x01 \x01(\tR\x04json\"-\n\x0bIsoDuration\x12\x1e\n\ndefinition\x18\x01 \x01(\tR\ndefinition\"r\n\x08Provided\x12\x33\n\x06source\x18\x01 \x01(\x0e\x32\x16.prefab.ProvidedSourceH\x00R\x06source\x88\x01\x01\x12\x1b\n\x06lookup\x18\x02 \x01(\tH\x01R\x06lookup\x88\x01\x01\x42\t\n\x07_sourceB\t\n\x07_lookup\"N\n\x08IntRange\x12\x19\n\x05start\x18\x01 \x01(\x03H\x00R\x05start\x88\x01\x01\x12\x15\n\x03\x65nd\x18\x02 \x01(\x03H\x01R\x03\x65nd\x88\x01\x01\x42\x08\n\x06_startB\x06\n\x04_end\"$\n\nStringList\x12\x16\n\x06values\x18\x01 \x03(\tR\x06values\"R\n\rWeightedValue\x12\x16\n\x06weight\x18\x01 \x01(\x05R\x06weight\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value\"\xa2\x01\n\x0eWeightedValues\x12>\n\x0fweighted_values\x18\x01 \x03(\x0b\x32\x15.prefab.WeightedValueR\x0eweightedValues\x12\x36\n\x15hash_by_property_name\x18\x02 \x01(\tH\x00R\x12hashByPropertyName\x88\x01\x01\x42\x18\n\x16_hash_by_property_name\"g\n\x0e\x41piKeyMetadata\x12\x1a\n\x06key_id\x18\x01 \x01(\tH\x00R\x05keyId\x88\x01\x01\x12\x1c\n\x07user_id\x18\x03 \x01(\tH\x01R\x06userId\x88\x01\x01\x42\t\n\x07_key_idB\n\n\x08_user_idJ\x04\x08\x02\x10\x03\"\xea\x02\n\x07\x43onfigs\x12(\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x0e.prefab.ConfigR\x07\x63onfigs\x12R\n\x16\x63onfig_service_pointer\x18\x02 \x01(\x0b\x32\x1c.prefab.ConfigServicePointerR\x14\x63onfigServicePointer\x12\x44\n\x0f\x61pikey_metadata\x18\x03 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00R\x0e\x61pikeyMetadata\x88\x01\x01\x12@\n\x0f\x64\x65\x66\x61ult_context\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSetH\x01R\x0e\x64\x65\x66\x61ultContext\x88\x01\x01\x12\"\n\nkeep_alive\x18\x05 \x01(\x08H\x02R\tkeepAlive\x88\x01\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_contextB\r\n\x0b_keep_alive\"\xe3\x04\n\x06\x43onfig\x12\x0e\n\x02id\x18\x01 \x01(\x03R\x02id\x12\x1d\n\nproject_id\x18\x02 \x01(\x03R\tprojectId\x12\x10\n\x03key\x18\x03 \x01(\tR\x03key\x12\x30\n\nchanged_by\x18\x04 \x01(\x0b\x32\x11.prefab.ChangedByR\tchangedBy\x12%\n\x04rows\x18\x05 \x03(\x0b\x32\x11.prefab.ConfigRowR\x04rows\x12>\n\x10\x61llowable_values\x18\x06 \x03(\x0b\x32\x13.prefab.ConfigValueR\x0f\x61llowableValues\x12\x33\n\x0b\x63onfig_type\x18\x07 \x01(\x0e\x32\x12.prefab.ConfigTypeR\nconfigType\x12\x1e\n\x08\x64raft_id\x18\x08 \x01(\x03H\x00R\x07\x64raftId\x88\x01\x01\x12\x37\n\nvalue_type\x18\t \x01(\x0e\x32\x18.prefab.Config.ValueTypeR\tvalueType\x12+\n\x12send_to_client_sdk\x18\n \x01(\x08R\x0fsendToClientSdk\"\xb6\x01\n\tValueType\x12\x16\n\x12NOT_SET_VALUE_TYPE\x10\x00\x12\x07\n\x03INT\x10\x01\x12\n\n\x06STRING\x10\x02\x12\t\n\x05\x42YTES\x10\x03\x12\n\n\x06\x44OUBLE\x10\x04\x12\x08\n\x04\x42OOL\x10\x05\x12\x14\n\x10LIMIT_DEFINITION\x10\x07\x12\r\n\tLOG_LEVEL\x10\t\x12\x0f\n\x0bSTRING_LIST\x10\n\x12\r\n\tINT_RANGE\x10\x0b\x12\x0c\n\x08\x44URATION\x10\x0c\x12\x08\n\x04JSON\x10\rB\x0b\n\t_draft_id\"X\n\tChangedBy\x12\x17\n\x07user_id\x18\x01 \x01(\x03R\x06userId\x12\x14\n\x05\x65mail\x18\x02 \x01(\tR\x05\x65mail\x12\x1c\n\napi_key_id\x18\x03 \x01(\tR\x08\x61piKeyId\"\x92\x02\n\tConfigRow\x12)\n\x0eproject_env_id\x18\x01 \x01(\x03H\x00R\x0cprojectEnvId\x88\x01\x01\x12\x30\n\x06values\x18\x02 \x03(\x0b\x32\x18.prefab.ConditionalValueR\x06values\x12\x41\n\nproperties\x18\x03 \x03(\x0b\x32!.prefab.ConfigRow.PropertiesEntryR\nproperties\x1aR\n\x0fPropertiesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value:\x02\x38\x01\x42\x11\n\x0f_project_env_id\"l\n\x10\x43onditionalValue\x12-\n\x08\x63riteria\x18\x01 \x03(\x0b\x32\x11.prefab.CriterionR\x08\x63riteria\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value\"\xbc\x06\n\tCriterion\x12#\n\rproperty_name\x18\x01 \x01(\tR\x0cpropertyName\x12?\n\x08operator\x18\x02 \x01(\x0e\x32#.prefab.Criterion.CriterionOperatorR\x08operator\x12\x39\n\x0evalue_to_match\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValueR\x0cvalueToMatch\"\x8d\x05\n\x11\x43riterionOperator\x12\x0b\n\x07NOT_SET\x10\x00\x12\x11\n\rLOOKUP_KEY_IN\x10\x01\x12\x15\n\x11LOOKUP_KEY_NOT_IN\x10\x02\x12\n\n\x06IN_SEG\x10\x03\x12\x0e\n\nNOT_IN_SEG\x10\x04\x12\x0f\n\x0b\x41LWAYS_TRUE\x10\x05\x12\x12\n\x0ePROP_IS_ONE_OF\x10\x06\x12\x16\n\x12PROP_IS_NOT_ONE_OF\x10\x07\x12\x19\n\x15PROP_ENDS_WITH_ONE_OF\x10\x08\x12!\n\x1dPROP_DOES_NOT_END_WITH_ONE_OF\x10\t\x12\x16\n\x12HIERARCHICAL_MATCH\x10\n\x12\x10\n\x0cIN_INT_RANGE\x10\x0b\x12\x1b\n\x17PROP_STARTS_WITH_ONE_OF\x10\x0c\x12#\n\x1fPROP_DOES_NOT_START_WITH_ONE_OF\x10\r\x12\x18\n\x14PROP_CONTAINS_ONE_OF\x10\x0e\x12 \n\x1cPROP_DOES_NOT_CONTAIN_ONE_OF\x10\x0f\x12\x12\n\x0ePROP_LESS_THAN\x10\x10\x12\x1b\n\x17PROP_LESS_THAN_OR_EQUAL\x10\x11\x12\x15\n\x11PROP_GREATER_THAN\x10\x12\x12\x1e\n\x1aPROP_GREATER_THAN_OR_EQUAL\x10\x13\x12\x0f\n\x0bPROP_BEFORE\x10\x14\x12\x0e\n\nPROP_AFTER\x10\x15\x12\x10\n\x0cPROP_MATCHES\x10\x16\x12\x17\n\x13PROP_DOES_NOT_MATCH\x10\x17\x12\x19\n\x15PROP_SEMVER_LESS_THAN\x10\x18\x12\x15\n\x11PROP_SEMVER_EQUAL\x10\x19\x12\x1c\n\x18PROP_SEMVER_GREATER_THAN\x10\x1a\"\xbb\x01\n\x07Loggers\x12(\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.LoggerR\x07loggers\x12\x19\n\x08start_at\x18\x02 \x01(\x03R\x07startAt\x12\x15\n\x06\x65nd_at\x18\x03 \x01(\x03R\x05\x65ndAt\x12#\n\rinstance_hash\x18\x04 \x01(\tR\x0cinstanceHash\x12!\n\tnamespace\x18\x05 \x01(\tH\x00R\tnamespace\x88\x01\x01\x42\x0c\n\n_namespace\"\x93\x02\n\x06Logger\x12\x1f\n\x0blogger_name\x18\x01 \x01(\tR\nloggerName\x12\x1b\n\x06traces\x18\x02 \x01(\x03H\x00R\x06traces\x88\x01\x01\x12\x1b\n\x06\x64\x65\x62ugs\x18\x03 \x01(\x03H\x01R\x06\x64\x65\x62ugs\x88\x01\x01\x12\x19\n\x05infos\x18\x04 \x01(\x03H\x02R\x05infos\x88\x01\x01\x12\x19\n\x05warns\x18\x05 \x01(\x03H\x03R\x05warns\x88\x01\x01\x12\x1b\n\x06\x65rrors\x18\x06 \x01(\x03H\x04R\x06\x65rrors\x88\x01\x01\x12\x1b\n\x06\x66\x61tals\x18\x07 \x01(\x03H\x05R\x06\x66\x61tals\x88\x01\x01\x42\t\n\x07_tracesB\t\n\x07_debugsB\x08\n\x06_infosB\x08\n\x06_warnsB\t\n\x07_errorsB\t\n\x07_fatals\"\x16\n\x14LoggerReportResponse\"\xd5\x04\n\rLimitResponse\x12\x16\n\x06passed\x18\x01 \x01(\x08R\x06passed\x12\x1d\n\nexpires_at\x18\x02 \x01(\x03R\texpiresAt\x12%\n\x0e\x65nforced_group\x18\x03 \x01(\tR\renforcedGroup\x12%\n\x0e\x63urrent_bucket\x18\x04 \x01(\x03R\rcurrentBucket\x12!\n\x0cpolicy_group\x18\x05 \x01(\tR\x0bpolicyGroup\x12G\n\x0bpolicy_name\x18\x06 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNamesR\npolicyName\x12!\n\x0cpolicy_limit\x18\x07 \x01(\x05R\x0bpolicyLimit\x12\x16\n\x06\x61mount\x18\x08 \x01(\x03R\x06\x61mount\x12$\n\x0elimit_reset_at\x18\t \x01(\x03R\x0climitResetAt\x12\x46\n\x0csafety_level\x18\n \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevelR\x0bsafetyLevel\"\xa9\x01\n\x10LimitPolicyNames\x12\x0b\n\x07NOT_SET\x10\x00\x12\x14\n\x10SECONDLY_ROLLING\x10\x01\x12\x14\n\x10MINUTELY_ROLLING\x10\x03\x12\x12\n\x0eHOURLY_ROLLING\x10\x05\x12\x11\n\rDAILY_ROLLING\x10\x07\x12\x13\n\x0fMONTHLY_ROLLING\x10\x08\x12\x0c\n\x08INFINITE\x10\t\x12\x12\n\x0eYEARLY_ROLLING\x10\n\"\xed\x02\n\x0cLimitRequest\x12\x1d\n\naccount_id\x18\x01 \x01(\x03R\taccountId\x12%\n\x0e\x61\x63quire_amount\x18\x02 \x01(\x05R\racquireAmount\x12\x16\n\x06groups\x18\x03 \x03(\tR\x06groups\x12I\n\x0elimit_combiner\x18\x04 \x01(\x0e\x32\".prefab.LimitRequest.LimitCombinerR\rlimitCombiner\x12\x34\n\x16\x61llow_partial_response\x18\x05 \x01(\x08R\x14\x61llowPartialResponse\x12\x46\n\x0csafety_level\x18\x06 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevelR\x0bsafetyLevel\"6\n\rLimitCombiner\x12\x0b\n\x07NOT_SET\x10\x00\x12\x0b\n\x07MINIMUM\x10\x01\x12\x0b\n\x07MAXIMUM\x10\x02\"9\n\nContextSet\x12+\n\x08\x63ontexts\x18\x01 \x03(\x0b\x32\x0f.prefab.ContextR\x08\x63ontexts\"\xb0\x01\n\x07\x43ontext\x12\x17\n\x04type\x18\x01 \x01(\tH\x00R\x04type\x88\x01\x01\x12\x33\n\x06values\x18\x02 \x03(\x0b\x32\x1b.prefab.Context.ValuesEntryR\x06values\x1aN\n\x0bValuesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValueR\x05value:\x02\x38\x01\x42\x07\n\x05_type\"\xb3\x01\n\x08Identity\x12\x1b\n\x06lookup\x18\x01 \x01(\tH\x00R\x06lookup\x88\x01\x01\x12@\n\nattributes\x18\x02 \x03(\x0b\x32 .prefab.Identity.AttributesEntryR\nattributes\x1a=\n\x0f\x41ttributesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\t\n\x07_lookup\"\xa6\x03\n\x18\x43onfigEvaluationMetaData\x12-\n\x10\x63onfig_row_index\x18\x01 \x01(\x03H\x00R\x0e\x63onfigRowIndex\x88\x01\x01\x12;\n\x17\x63onditional_value_index\x18\x02 \x01(\x03H\x01R\x15\x63onditionalValueIndex\x88\x01\x01\x12\x35\n\x14weighted_value_index\x18\x03 \x01(\x03H\x02R\x12weightedValueIndex\x88\x01\x01\x12+\n\x04type\x18\x04 \x01(\x0e\x32\x12.prefab.ConfigTypeH\x03R\x04type\x88\x01\x01\x12\x13\n\x02id\x18\x05 \x01(\x03H\x04R\x02id\x88\x01\x01\x12<\n\nvalue_type\x18\x06 \x01(\x0e\x32\x18.prefab.Config.ValueTypeH\x05R\tvalueType\x88\x01\x01\x42\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_indexB\x07\n\x05_typeB\x05\n\x03_idB\r\n\x0b_value_type\"\xf0\x03\n\x11\x43lientConfigValue\x12\x12\n\x03int\x18\x01 \x01(\x03H\x00R\x03int\x12\x18\n\x06string\x18\x02 \x01(\tH\x00R\x06string\x12\x18\n\x06\x64ouble\x18\x03 \x01(\x01H\x00R\x06\x64ouble\x12\x14\n\x04\x62ool\x18\x04 \x01(\x08H\x00R\x04\x62ool\x12/\n\tlog_level\x18\x05 \x01(\x0e\x32\x10.prefab.LogLevelH\x00R\x08logLevel\x12\x35\n\x0bstring_list\x18\x07 \x01(\x0b\x32\x12.prefab.StringListH\x00R\nstringList\x12/\n\tint_range\x18\x08 \x01(\x0b\x32\x10.prefab.IntRangeH\x00R\x08intRange\x12\x34\n\x08\x64uration\x18\t \x01(\x0b\x32\x16.prefab.ClientDurationH\x00R\x08\x64uration\x12\"\n\x04json\x18\n \x01(\x0b\x32\x0c.prefab.JsonH\x00R\x04json\x12\x63\n\x1a\x63onfig_evaluation_metadata\x18\x06 \x01(\x0b\x32 .prefab.ConfigEvaluationMetaDataH\x01R\x18\x63onfigEvaluationMetadata\x88\x01\x01\x42\x06\n\x04typeB\x1d\n\x1b_config_evaluation_metadata\"`\n\x0e\x43lientDuration\x12\x18\n\x07seconds\x18\x01 \x01(\x03R\x07seconds\x12\x14\n\x05nanos\x18\x02 \x01(\x05R\x05nanos\x12\x1e\n\ndefinition\x18\x03 \x01(\tR\ndefinition\"\xd8\x02\n\x11\x43onfigEvaluations\x12=\n\x06values\x18\x01 \x03(\x0b\x32%.prefab.ConfigEvaluations.ValuesEntryR\x06values\x12\x44\n\x0f\x61pikey_metadata\x18\x02 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00R\x0e\x61pikeyMetadata\x88\x01\x01\x12@\n\x0f\x64\x65\x66\x61ult_context\x18\x03 \x01(\x0b\x32\x12.prefab.ContextSetH\x01R\x0e\x64\x65\x66\x61ultContext\x88\x01\x01\x1aT\n\x0bValuesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12/\n\x05value\x18\x02 \x01(\x0b\x32\x19.prefab.ClientConfigValueR\x05value:\x02\x38\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_context\"\xf4\x02\n\x0fLimitDefinition\x12G\n\x0bpolicy_name\x18\x02 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNamesR\npolicyName\x12\x14\n\x05limit\x18\x03 \x01(\x05R\x05limit\x12\x14\n\x05\x62urst\x18\x04 \x01(\x05R\x05\x62urst\x12\x1d\n\naccount_id\x18\x05 \x01(\x03R\taccountId\x12#\n\rlast_modified\x18\x06 \x01(\x03R\x0clastModified\x12\x1e\n\nreturnable\x18\x07 \x01(\x08R\nreturnable\x12\x46\n\x0csafety_level\x18\x08 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevelR\x0bsafetyLevel\"@\n\x0bSafetyLevel\x12\x0b\n\x07NOT_SET\x10\x00\x12\x12\n\x0eL4_BEST_EFFORT\x10\x04\x12\x10\n\x0cL5_BOMBPROOF\x10\x05\"M\n\x10LimitDefinitions\x12\x39\n\x0b\x64\x65\x66initions\x18\x01 \x03(\x0b\x32\x17.prefab.LimitDefinitionR\x0b\x64\x65\x66initions\"\xc8\x01\n\x0f\x42ufferedRequest\x12\x1d\n\naccount_id\x18\x01 \x01(\x03R\taccountId\x12\x16\n\x06method\x18\x02 \x01(\tR\x06method\x12\x10\n\x03uri\x18\x03 \x01(\tR\x03uri\x12\x12\n\x04\x62ody\x18\x04 \x01(\tR\x04\x62ody\x12!\n\x0climit_groups\x18\x05 \x03(\tR\x0blimitGroups\x12!\n\x0c\x63ontent_type\x18\x06 \x01(\tR\x0b\x63ontentType\x12\x12\n\x04\x66ifo\x18\x07 \x01(\x08R\x04\x66ifo\"\xde\x01\n\x0c\x42\x61tchRequest\x12\x1d\n\naccount_id\x18\x01 \x01(\x03R\taccountId\x12\x16\n\x06method\x18\x02 \x01(\tR\x06method\x12\x10\n\x03uri\x18\x03 \x01(\tR\x03uri\x12\x12\n\x04\x62ody\x18\x04 \x01(\tR\x04\x62ody\x12!\n\x0climit_groups\x18\x05 \x03(\tR\x0blimitGroups\x12%\n\x0e\x62\x61tch_template\x18\x06 \x01(\tR\rbatchTemplate\x12\'\n\x0f\x62\x61tch_separator\x18\x07 \x01(\tR\x0e\x62\x61tchSeparator\")\n\rBasicResponse\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\"C\n\x10\x43reationResponse\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\x12\x15\n\x06new_id\x18\x02 \x01(\x03R\x05newId\"\x9b\x01\n\x07IdBlock\x12\x1d\n\nproject_id\x18\x01 \x01(\x03R\tprojectId\x12$\n\x0eproject_env_id\x18\x02 \x01(\x03R\x0cprojectEnvId\x12#\n\rsequence_name\x18\x03 \x01(\tR\x0csequenceName\x12\x14\n\x05start\x18\x04 \x01(\x03R\x05start\x12\x10\n\x03\x65nd\x18\x05 \x01(\x03R\x03\x65nd\"\x8e\x01\n\x0eIdBlockRequest\x12\x1d\n\nproject_id\x18\x01 \x01(\x03R\tprojectId\x12$\n\x0eproject_env_id\x18\x02 \x01(\x03R\x0cprojectEnvId\x12#\n\rsequence_name\x18\x03 \x01(\tR\x0csequenceName\x12\x12\n\x04size\x18\x04 \x01(\x03R\x04size\"\xa8\x01\n\x0c\x43ontextShape\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12\x45\n\x0b\x66ield_types\x18\x02 \x03(\x0b\x32$.prefab.ContextShape.FieldTypesEntryR\nfieldTypes\x1a=\n\x0f\x46ieldTypesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01\"n\n\rContextShapes\x12,\n\x06shapes\x18\x01 \x03(\x0b\x32\x14.prefab.ContextShapeR\x06shapes\x12!\n\tnamespace\x18\x02 \x01(\tH\x00R\tnamespace\x88\x01\x01\x42\x0c\n\n_namespace\"T\n\rEvaluatedKeys\x12\x12\n\x04keys\x18\x01 \x03(\tR\x04keys\x12!\n\tnamespace\x18\x02 \x01(\tH\x00R\tnamespace\x88\x01\x01\x42\x0c\n\n_namespace\"\xc3\x01\n\x0f\x45valuatedConfig\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12%\n\x0e\x63onfig_version\x18\x02 \x01(\x03R\rconfigVersion\x12+\n\x06result\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValueR\x06result\x12,\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSetR\x07\x63ontext\x12\x1c\n\ttimestamp\x18\x05 \x01(\x03R\ttimestamp\"E\n\x10\x45valuatedConfigs\x12\x31\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x17.prefab.EvaluatedConfigR\x07\x63onfigs\"\xb6\x04\n\x17\x43onfigEvaluationCounter\x12\x14\n\x05\x63ount\x18\x01 \x01(\x03R\x05\x63ount\x12 \n\tconfig_id\x18\x02 \x01(\x03H\x00R\x08\x63onfigId\x88\x01\x01\x12*\n\x0eselected_index\x18\x03 \x01(\rH\x01R\rselectedIndex\x88\x01\x01\x12?\n\x0eselected_value\x18\x04 \x01(\x0b\x32\x13.prefab.ConfigValueH\x02R\rselectedValue\x88\x01\x01\x12-\n\x10\x63onfig_row_index\x18\x05 \x01(\rH\x03R\x0e\x63onfigRowIndex\x88\x01\x01\x12;\n\x17\x63onditional_value_index\x18\x06 \x01(\rH\x04R\x15\x63onditionalValueIndex\x88\x01\x01\x12\x35\n\x14weighted_value_index\x18\x07 \x01(\rH\x05R\x12weightedValueIndex\x88\x01\x01\x12>\n\x06reason\x18\x08 \x01(\x0e\x32&.prefab.ConfigEvaluationCounter.ReasonR\x06reason\"\x15\n\x06Reason\x12\x0b\n\x07UNKNOWN\x10\x00\x42\x0c\n\n_config_idB\x11\n\x0f_selected_indexB\x11\n\x0f_selected_valueB\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_index\"\x90\x01\n\x17\x43onfigEvaluationSummary\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12&\n\x04type\x18\x02 \x01(\x0e\x32\x12.prefab.ConfigTypeR\x04type\x12;\n\x08\x63ounters\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationCounterR\x08\x63ounters\"\x82\x01\n\x19\x43onfigEvaluationSummaries\x12\x14\n\x05start\x18\x01 \x01(\x03R\x05start\x12\x10\n\x03\x65nd\x18\x02 \x01(\x03R\x03\x65nd\x12=\n\tsummaries\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationSummaryR\tsummaries\"s\n\x15LoggersTelemetryEvent\x12(\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.LoggerR\x07loggers\x12\x19\n\x08start_at\x18\x02 \x01(\x03R\x07startAt\x12\x15\n\x06\x65nd_at\x18\x03 \x01(\x03R\x05\x65ndAt\"\xd9\x02\n\x0eTelemetryEvent\x12\x41\n\tsummaries\x18\x02 \x01(\x0b\x32!.prefab.ConfigEvaluationSummariesH\x00R\tsummaries\x12\x44\n\x10\x65xample_contexts\x18\x03 \x01(\x0b\x32\x17.prefab.ExampleContextsH\x00R\x0f\x65xampleContexts\x12\x38\n\x0c\x63lient_stats\x18\x04 \x01(\x0b\x32\x13.prefab.ClientStatsH\x00R\x0b\x63lientStats\x12\x39\n\x07loggers\x18\x05 \x01(\x0b\x32\x1d.prefab.LoggersTelemetryEventH\x00R\x07loggers\x12>\n\x0e\x63ontext_shapes\x18\x06 \x01(\x0b\x32\x15.prefab.ContextShapesH\x00R\rcontextShapesB\t\n\x07payload\"f\n\x0fTelemetryEvents\x12#\n\rinstance_hash\x18\x01 \x01(\tR\x0cinstanceHash\x12.\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x16.prefab.TelemetryEventR\x06\x65vents\"3\n\x17TelemetryEventsResponse\x12\x18\n\x07success\x18\x01 \x01(\x08R\x07success\"E\n\x0f\x45xampleContexts\x12\x32\n\x08\x65xamples\x18\x01 \x03(\x0b\x32\x16.prefab.ExampleContextR\x08\x65xamples\"b\n\x0e\x45xampleContext\x12\x1c\n\ttimestamp\x18\x01 \x01(\x03R\ttimestamp\x12\x32\n\ncontextSet\x18\x02 \x01(\x0b\x32\x12.prefab.ContextSetR\ncontextSet\"e\n\x0b\x43lientStats\x12\x14\n\x05start\x18\x01 \x01(\x03R\x05start\x12\x10\n\x03\x65nd\x18\x02 \x01(\x03R\x03\x65nd\x12.\n\x13\x64ropped_event_count\x18\x03 \x01(\x04R\x11\x64roppedEventCount*:\n\x0eProvidedSource\x12\x1b\n\x17PROVIDED_SOURCE_NOT_SET\x10\x00\x12\x0b\n\x07\x45NV_VAR\x10\x01*\x82\x01\n\nConfigType\x12\x17\n\x13NOT_SET_CONFIG_TYPE\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\x10\n\x0c\x46\x45\x41TURE_FLAG\x10\x02\x12\r\n\tLOG_LEVEL\x10\x03\x12\x0b\n\x07SEGMENT\x10\x04\x12\x14\n\x10LIMIT_DEFINITION\x10\x05\x12\x0b\n\x07\x44\x45LETED\x10\x06*a\n\x08LogLevel\x12\x15\n\x11NOT_SET_LOG_LEVEL\x10\x00\x12\t\n\x05TRACE\x10\x01\x12\t\n\x05\x44\x45\x42UG\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\x08\n\x04WARN\x10\x05\x12\t\n\x05\x45RROR\x10\x06\x12\t\n\x05\x46\x41TAL\x10\t*G\n\tOnFailure\x12\x0b\n\x07NOT_SET\x10\x00\x12\x10\n\x0cLOG_AND_PASS\x10\x01\x12\x10\n\x0cLOG_AND_FAIL\x10\x02\x12\t\n\x05THROW\x10\x03\x42L\n\x13\x63loud.prefab.domainB\x06PrefabZ-github.com/prefab-cloud/prefab-cloud-go/protob\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -32,14 +32,14 @@ _CONFIGEVALUATIONS_VALUESENTRY._serialized_options = b'8\001' _CONTEXTSHAPE_FIELDTYPESENTRY._options = None _CONTEXTSHAPE_FIELDTYPESENTRY._serialized_options = b'8\001' - _globals['_PROVIDEDSOURCE']._serialized_start=10587 - _globals['_PROVIDEDSOURCE']._serialized_end=10645 - _globals['_CONFIGTYPE']._serialized_start=10648 - _globals['_CONFIGTYPE']._serialized_end=10778 - _globals['_LOGLEVEL']._serialized_start=10780 - _globals['_LOGLEVEL']._serialized_end=10877 - _globals['_ONFAILURE']._serialized_start=10879 - _globals['_ONFAILURE']._serialized_end=10950 + _globals['_PROVIDEDSOURCE']._serialized_start=10710 + _globals['_PROVIDEDSOURCE']._serialized_end=10768 + _globals['_CONFIGTYPE']._serialized_start=10771 + _globals['_CONFIGTYPE']._serialized_end=10901 + _globals['_LOGLEVEL']._serialized_start=10903 + _globals['_LOGLEVEL']._serialized_end=11000 + _globals['_ONFAILURE']._serialized_start=11002 + _globals['_ONFAILURE']._serialized_end=11073 _globals['_CONFIGSERVICEPOINTER']._serialized_start=24 _globals['_CONFIGSERVICEPOINTER']._serialized_end=147 _globals['_CONFIGVALUE']._serialized_start=150 @@ -75,93 +75,93 @@ _globals['_CONDITIONALVALUE']._serialized_start=2840 _globals['_CONDITIONALVALUE']._serialized_end=2948 _globals['_CRITERION']._serialized_start=2951 - _globals['_CRITERION']._serialized_end=3656 + _globals['_CRITERION']._serialized_end=3779 _globals['_CRITERION_CRITERIONOPERATOR']._serialized_start=3126 - _globals['_CRITERION_CRITERIONOPERATOR']._serialized_end=3656 - _globals['_LOGGERS']._serialized_start=3659 - _globals['_LOGGERS']._serialized_end=3846 - _globals['_LOGGER']._serialized_start=3849 - _globals['_LOGGER']._serialized_end=4124 - _globals['_LOGGERREPORTRESPONSE']._serialized_start=4126 - _globals['_LOGGERREPORTRESPONSE']._serialized_end=4148 - _globals['_LIMITRESPONSE']._serialized_start=4151 - _globals['_LIMITRESPONSE']._serialized_end=4748 - _globals['_LIMITRESPONSE_LIMITPOLICYNAMES']._serialized_start=4579 - _globals['_LIMITRESPONSE_LIMITPOLICYNAMES']._serialized_end=4748 - _globals['_LIMITREQUEST']._serialized_start=4751 - _globals['_LIMITREQUEST']._serialized_end=5116 - _globals['_LIMITREQUEST_LIMITCOMBINER']._serialized_start=5062 - _globals['_LIMITREQUEST_LIMITCOMBINER']._serialized_end=5116 - _globals['_CONTEXTSET']._serialized_start=5118 - _globals['_CONTEXTSET']._serialized_end=5175 - _globals['_CONTEXT']._serialized_start=5178 - _globals['_CONTEXT']._serialized_end=5354 - _globals['_CONTEXT_VALUESENTRY']._serialized_start=5267 - _globals['_CONTEXT_VALUESENTRY']._serialized_end=5345 - _globals['_IDENTITY']._serialized_start=5357 - _globals['_IDENTITY']._serialized_end=5536 - _globals['_IDENTITY_ATTRIBUTESENTRY']._serialized_start=5464 - _globals['_IDENTITY_ATTRIBUTESENTRY']._serialized_end=5525 - _globals['_CONFIGEVALUATIONMETADATA']._serialized_start=5539 - _globals['_CONFIGEVALUATIONMETADATA']._serialized_end=5961 - _globals['_CLIENTCONFIGVALUE']._serialized_start=5964 - _globals['_CLIENTCONFIGVALUE']._serialized_end=6460 - _globals['_CLIENTDURATION']._serialized_start=6462 - _globals['_CLIENTDURATION']._serialized_end=6558 - _globals['_CONFIGEVALUATIONS']._serialized_start=6561 - _globals['_CONFIGEVALUATIONS']._serialized_end=6905 - _globals['_CONFIGEVALUATIONS_VALUESENTRY']._serialized_start=6781 - _globals['_CONFIGEVALUATIONS_VALUESENTRY']._serialized_end=6865 - _globals['_LIMITDEFINITION']._serialized_start=6908 - _globals['_LIMITDEFINITION']._serialized_end=7280 - _globals['_LIMITDEFINITION_SAFETYLEVEL']._serialized_start=7216 - _globals['_LIMITDEFINITION_SAFETYLEVEL']._serialized_end=7280 - _globals['_LIMITDEFINITIONS']._serialized_start=7282 - _globals['_LIMITDEFINITIONS']._serialized_end=7359 - _globals['_BUFFEREDREQUEST']._serialized_start=7362 - _globals['_BUFFEREDREQUEST']._serialized_end=7562 - _globals['_BATCHREQUEST']._serialized_start=7565 - _globals['_BATCHREQUEST']._serialized_end=7787 - _globals['_BASICRESPONSE']._serialized_start=7789 - _globals['_BASICRESPONSE']._serialized_end=7830 - _globals['_CREATIONRESPONSE']._serialized_start=7832 - _globals['_CREATIONRESPONSE']._serialized_end=7899 - _globals['_IDBLOCK']._serialized_start=7902 - _globals['_IDBLOCK']._serialized_end=8057 - _globals['_IDBLOCKREQUEST']._serialized_start=8060 - _globals['_IDBLOCKREQUEST']._serialized_end=8202 - _globals['_CONTEXTSHAPE']._serialized_start=8205 - _globals['_CONTEXTSHAPE']._serialized_end=8373 - _globals['_CONTEXTSHAPE_FIELDTYPESENTRY']._serialized_start=8312 - _globals['_CONTEXTSHAPE_FIELDTYPESENTRY']._serialized_end=8373 - _globals['_CONTEXTSHAPES']._serialized_start=8375 - _globals['_CONTEXTSHAPES']._serialized_end=8485 - _globals['_EVALUATEDKEYS']._serialized_start=8487 - _globals['_EVALUATEDKEYS']._serialized_end=8571 - _globals['_EVALUATEDCONFIG']._serialized_start=8574 - _globals['_EVALUATEDCONFIG']._serialized_end=8769 - _globals['_EVALUATEDCONFIGS']._serialized_start=8771 - _globals['_EVALUATEDCONFIGS']._serialized_end=8840 - _globals['_CONFIGEVALUATIONCOUNTER']._serialized_start=8843 - _globals['_CONFIGEVALUATIONCOUNTER']._serialized_end=9409 - _globals['_CONFIGEVALUATIONCOUNTER_REASON']._serialized_start=9262 - _globals['_CONFIGEVALUATIONCOUNTER_REASON']._serialized_end=9283 - _globals['_CONFIGEVALUATIONSUMMARY']._serialized_start=9412 - _globals['_CONFIGEVALUATIONSUMMARY']._serialized_end=9556 - _globals['_CONFIGEVALUATIONSUMMARIES']._serialized_start=9559 - _globals['_CONFIGEVALUATIONSUMMARIES']._serialized_end=9689 - _globals['_LOGGERSTELEMETRYEVENT']._serialized_start=9691 - _globals['_LOGGERSTELEMETRYEVENT']._serialized_end=9806 - _globals['_TELEMETRYEVENT']._serialized_start=9809 - _globals['_TELEMETRYEVENT']._serialized_end=10154 - _globals['_TELEMETRYEVENTS']._serialized_start=10156 - _globals['_TELEMETRYEVENTS']._serialized_end=10258 - _globals['_TELEMETRYEVENTSRESPONSE']._serialized_start=10260 - _globals['_TELEMETRYEVENTSRESPONSE']._serialized_end=10311 - _globals['_EXAMPLECONTEXTS']._serialized_start=10313 - _globals['_EXAMPLECONTEXTS']._serialized_end=10382 - _globals['_EXAMPLECONTEXT']._serialized_start=10384 - _globals['_EXAMPLECONTEXT']._serialized_end=10482 - _globals['_CLIENTSTATS']._serialized_start=10484 - _globals['_CLIENTSTATS']._serialized_end=10585 + _globals['_CRITERION_CRITERIONOPERATOR']._serialized_end=3779 + _globals['_LOGGERS']._serialized_start=3782 + _globals['_LOGGERS']._serialized_end=3969 + _globals['_LOGGER']._serialized_start=3972 + _globals['_LOGGER']._serialized_end=4247 + _globals['_LOGGERREPORTRESPONSE']._serialized_start=4249 + _globals['_LOGGERREPORTRESPONSE']._serialized_end=4271 + _globals['_LIMITRESPONSE']._serialized_start=4274 + _globals['_LIMITRESPONSE']._serialized_end=4871 + _globals['_LIMITRESPONSE_LIMITPOLICYNAMES']._serialized_start=4702 + _globals['_LIMITRESPONSE_LIMITPOLICYNAMES']._serialized_end=4871 + _globals['_LIMITREQUEST']._serialized_start=4874 + _globals['_LIMITREQUEST']._serialized_end=5239 + _globals['_LIMITREQUEST_LIMITCOMBINER']._serialized_start=5185 + _globals['_LIMITREQUEST_LIMITCOMBINER']._serialized_end=5239 + _globals['_CONTEXTSET']._serialized_start=5241 + _globals['_CONTEXTSET']._serialized_end=5298 + _globals['_CONTEXT']._serialized_start=5301 + _globals['_CONTEXT']._serialized_end=5477 + _globals['_CONTEXT_VALUESENTRY']._serialized_start=5390 + _globals['_CONTEXT_VALUESENTRY']._serialized_end=5468 + _globals['_IDENTITY']._serialized_start=5480 + _globals['_IDENTITY']._serialized_end=5659 + _globals['_IDENTITY_ATTRIBUTESENTRY']._serialized_start=5587 + _globals['_IDENTITY_ATTRIBUTESENTRY']._serialized_end=5648 + _globals['_CONFIGEVALUATIONMETADATA']._serialized_start=5662 + _globals['_CONFIGEVALUATIONMETADATA']._serialized_end=6084 + _globals['_CLIENTCONFIGVALUE']._serialized_start=6087 + _globals['_CLIENTCONFIGVALUE']._serialized_end=6583 + _globals['_CLIENTDURATION']._serialized_start=6585 + _globals['_CLIENTDURATION']._serialized_end=6681 + _globals['_CONFIGEVALUATIONS']._serialized_start=6684 + _globals['_CONFIGEVALUATIONS']._serialized_end=7028 + _globals['_CONFIGEVALUATIONS_VALUESENTRY']._serialized_start=6904 + _globals['_CONFIGEVALUATIONS_VALUESENTRY']._serialized_end=6988 + _globals['_LIMITDEFINITION']._serialized_start=7031 + _globals['_LIMITDEFINITION']._serialized_end=7403 + _globals['_LIMITDEFINITION_SAFETYLEVEL']._serialized_start=7339 + _globals['_LIMITDEFINITION_SAFETYLEVEL']._serialized_end=7403 + _globals['_LIMITDEFINITIONS']._serialized_start=7405 + _globals['_LIMITDEFINITIONS']._serialized_end=7482 + _globals['_BUFFEREDREQUEST']._serialized_start=7485 + _globals['_BUFFEREDREQUEST']._serialized_end=7685 + _globals['_BATCHREQUEST']._serialized_start=7688 + _globals['_BATCHREQUEST']._serialized_end=7910 + _globals['_BASICRESPONSE']._serialized_start=7912 + _globals['_BASICRESPONSE']._serialized_end=7953 + _globals['_CREATIONRESPONSE']._serialized_start=7955 + _globals['_CREATIONRESPONSE']._serialized_end=8022 + _globals['_IDBLOCK']._serialized_start=8025 + _globals['_IDBLOCK']._serialized_end=8180 + _globals['_IDBLOCKREQUEST']._serialized_start=8183 + _globals['_IDBLOCKREQUEST']._serialized_end=8325 + _globals['_CONTEXTSHAPE']._serialized_start=8328 + _globals['_CONTEXTSHAPE']._serialized_end=8496 + _globals['_CONTEXTSHAPE_FIELDTYPESENTRY']._serialized_start=8435 + _globals['_CONTEXTSHAPE_FIELDTYPESENTRY']._serialized_end=8496 + _globals['_CONTEXTSHAPES']._serialized_start=8498 + _globals['_CONTEXTSHAPES']._serialized_end=8608 + _globals['_EVALUATEDKEYS']._serialized_start=8610 + _globals['_EVALUATEDKEYS']._serialized_end=8694 + _globals['_EVALUATEDCONFIG']._serialized_start=8697 + _globals['_EVALUATEDCONFIG']._serialized_end=8892 + _globals['_EVALUATEDCONFIGS']._serialized_start=8894 + _globals['_EVALUATEDCONFIGS']._serialized_end=8963 + _globals['_CONFIGEVALUATIONCOUNTER']._serialized_start=8966 + _globals['_CONFIGEVALUATIONCOUNTER']._serialized_end=9532 + _globals['_CONFIGEVALUATIONCOUNTER_REASON']._serialized_start=9385 + _globals['_CONFIGEVALUATIONCOUNTER_REASON']._serialized_end=9406 + _globals['_CONFIGEVALUATIONSUMMARY']._serialized_start=9535 + _globals['_CONFIGEVALUATIONSUMMARY']._serialized_end=9679 + _globals['_CONFIGEVALUATIONSUMMARIES']._serialized_start=9682 + _globals['_CONFIGEVALUATIONSUMMARIES']._serialized_end=9812 + _globals['_LOGGERSTELEMETRYEVENT']._serialized_start=9814 + _globals['_LOGGERSTELEMETRYEVENT']._serialized_end=9929 + _globals['_TELEMETRYEVENT']._serialized_start=9932 + _globals['_TELEMETRYEVENT']._serialized_end=10277 + _globals['_TELEMETRYEVENTS']._serialized_start=10279 + _globals['_TELEMETRYEVENTS']._serialized_end=10381 + _globals['_TELEMETRYEVENTSRESPONSE']._serialized_start=10383 + _globals['_TELEMETRYEVENTSRESPONSE']._serialized_end=10434 + _globals['_EXAMPLECONTEXTS']._serialized_start=10436 + _globals['_EXAMPLECONTEXTS']._serialized_end=10505 + _globals['_EXAMPLECONTEXT']._serialized_start=10507 + _globals['_EXAMPLECONTEXT']._serialized_end=10605 + _globals['_CLIENTSTATS']._serialized_start=10607 + _globals['_CLIENTSTATS']._serialized_end=10708 # @@protoc_insertion_point(module_scope) diff --git a/prefab_pb2.pyi b/prefab_pb2.pyi index 4aeb3c4..e2f8a8f 100644 --- a/prefab_pb2.pyi +++ b/prefab_pb2.pyi @@ -611,6 +611,11 @@ class Criterion(google.protobuf.message.Message): PROP_GREATER_THAN_OR_EQUAL: Criterion._CriterionOperator.ValueType # 19 PROP_BEFORE: Criterion._CriterionOperator.ValueType # 20 PROP_AFTER: Criterion._CriterionOperator.ValueType # 21 + PROP_MATCHES: Criterion._CriterionOperator.ValueType # 22 + PROP_DOES_NOT_MATCH: Criterion._CriterionOperator.ValueType # 23 + PROP_SEMVER_LESS_THAN: Criterion._CriterionOperator.ValueType # 24 + PROP_SEMVER_EQUAL: Criterion._CriterionOperator.ValueType # 25 + PROP_SEMVER_GREATER_THAN: Criterion._CriterionOperator.ValueType # 26 class CriterionOperator(_CriterionOperator, metaclass=_CriterionOperatorEnumTypeWrapper): ... NOT_SET: Criterion.CriterionOperator.ValueType # 0 @@ -636,6 +641,11 @@ class Criterion(google.protobuf.message.Message): PROP_GREATER_THAN_OR_EQUAL: Criterion.CriterionOperator.ValueType # 19 PROP_BEFORE: Criterion.CriterionOperator.ValueType # 20 PROP_AFTER: Criterion.CriterionOperator.ValueType # 21 + PROP_MATCHES: Criterion.CriterionOperator.ValueType # 22 + PROP_DOES_NOT_MATCH: Criterion.CriterionOperator.ValueType # 23 + PROP_SEMVER_LESS_THAN: Criterion.CriterionOperator.ValueType # 24 + PROP_SEMVER_EQUAL: Criterion.CriterionOperator.ValueType # 25 + PROP_SEMVER_GREATER_THAN: Criterion.CriterionOperator.ValueType # 26 PROPERTY_NAME_FIELD_NUMBER: builtins.int OPERATOR_FIELD_NUMBER: builtins.int diff --git a/tests/prefab-cloud-integration-test-data b/tests/prefab-cloud-integration-test-data index 1f1da6c..4ccd647 160000 --- a/tests/prefab-cloud-integration-test-data +++ b/tests/prefab-cloud-integration-test-data @@ -1 +1 @@ -Subproject commit 1f1da6c72bd962f4003dffd64622b9913219e189 +Subproject commit 4ccd6472078b1ef0a8088cc2fb242c39939f8bf1 diff --git a/tests/test_criteria_evaluator.py b/tests/test_criteria_evaluator.py index a0cdeb3..95cffa3 100644 --- a/tests/test_criteria_evaluator.py +++ b/tests/test_criteria_evaluator.py @@ -329,7 +329,7 @@ def test_prop_does_not_end_with_one_of(self): config, project_env_id, resolver=None, base_client=None ) - assert evaluator.evaluate({}).raw_config_value().string == desired_value + assert evaluator.evaluate({}).raw_config_value().string == default_value assert ( evaluator.evaluate(context({"user": {"email": "example@prefab.cloud"}})) .raw_config_value() @@ -419,7 +419,7 @@ def test_prop_does_not_start_with_one_of(self): config, project_env_id, resolver=None, base_client=None ) - assert evaluator.evaluate({}).raw_config_value().string == desired_value + assert evaluator.evaluate({}).raw_config_value().string == default_value assert ( evaluator.evaluate(context({"user": {"email": "nope"}})) .raw_config_value() @@ -509,7 +509,7 @@ def test_prop_does_not_contain_one_of(self): config, project_env_id, resolver=None, base_client=None ) - assert evaluator.evaluate({}).raw_config_value().string == desired_value + assert evaluator.evaluate({}).raw_config_value().string == default_value assert ( evaluator.evaluate(context({"user": {"email": "nope"}})) .raw_config_value() diff --git a/tests/test_integration.py b/tests/test_integration.py index 75405bc..10eac2d 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -46,27 +46,28 @@ } -def build_options_with_overrides(options, overrides): - if overrides is None: - return options - if overrides.get("on_no_default") == 2: - options.on_no_default = "RETURN_NONE" - if overrides.get("namespace") is not None: - options.namespace = overrides["namespace"] - on_connection_failure = overrides.get("on_init_failure") - if on_connection_failure: - if on_connection_failure not in OnConnectionFailure: - raise Exception( - f"value of on_init_failure {on_connection_failure} maps to no known value" - ) - options.on_connection_failure = OnConnectionFailure[on_connection_failure] - options.connection_timeout_seconds = overrides.get( - "initialization_timeout_sec", options.connection_timeout_seconds - ) - if overrides.get("context_upload_mode"): - options.context_upload_mode = ContextUploadMode[ - overrides["context_upload_mode"] - ] +def build_options_with_overrides(options, overrides, global_context): + if overrides: + if overrides.get("on_no_default") == 2: + options.on_no_default = "RETURN_NONE" + if overrides.get("namespace") is not None: + options.namespace = overrides["namespace"] + on_connection_failure = overrides.get("on_init_failure") + if on_connection_failure: + if on_connection_failure not in OnConnectionFailure: + raise Exception( + f"value of on_init_failure {on_connection_failure} maps to no known value" + ) + options.on_connection_failure = OnConnectionFailure[on_connection_failure] + options.connection_timeout_seconds = overrides.get( + "initialization_timeout_sec", options.connection_timeout_seconds + ) + if overrides.get("context_upload_mode"): + options.context_upload_mode = ContextUploadMode[ + overrides["context_upload_mode"] + ] + if global_context: + options.global_context = global_context return options @@ -94,7 +95,7 @@ def load_test_cases_from_file(filename): for test_set in yaml_data["tests"]: test_info = { "name": test_set.get("name") or "", - "globalContext": test_set.get("context"), + "globalContext": test_set.get("contexts", {}).get("global"), "fileName": filename, } for case in test_set["cases"]: @@ -116,21 +117,27 @@ def run_test( options, input_key="key", function="get", - global_context=None, expected_modifier=(lambda x: x), ): case = test["case"] input = case["input"] expected = case["expected"] type = case.get("type") - options = build_options_with_overrides(options, case.get("client_overrides")) + options = build_options_with_overrides( + options, + case.get("client_overrides"), + global_context=case.get("contexts", {}).get("global"), + ) with Client(options) as client: - if global_context: - Context.set_current(Context(global_context)) + block_context = case.get("contexts", {}).get("block") + if block_context: + Context.set_current(Context(block_context)) key = input[input_key] default = input.get("default") - if input.get("context"): - context = Context(input["context"]) + + local_context = case.get("contexts", {}).get("local") + if local_context: + context = Context(local_context) else: context = None if function == "get": @@ -155,9 +162,15 @@ def run_test( def run_telemetry_test(test, options, global_context=None): case = test["case"] - options = build_options_with_overrides(options, case.get("client_overrides")) - if global_context: - Context.set_current(Context(global_context)) + options = build_options_with_overrides( + options, case.get("client_overrides"), global_context=global_context + ) + block_context = case.get("contexts", {}).get("block") + if block_context: + Context.set_current(Context(block_context)) + local_context = case.get("contexts", {}).get("local") + if local_context: + raise RuntimeError("local_context not supported yet in telemetry test") client = Client(options) with patch.object(client, "post", wraps=client.post) as spy_method: if case["aggregator"] == "log_path": @@ -217,7 +230,7 @@ def run_context_instances_telemetry_test(test, case, client, spy_post_method): def run_evaluation_summary_telemetry_test(test, case, client, spy_post_method): - for key in case["data"]: + for key in case.get("data", {})["keys"]: client.config_client().get(key) client.telemetry_manager.flush_and_block() url, telemetry_events = spy_post_method.call_args.args @@ -295,7 +308,6 @@ def test_enabled_with_contexts(self, options, testcase): options, input_key="flag", function="enabled", - global_context=testcase["testInfo"].get("globalContext"), ) @pytest.mark.parametrize( @@ -321,7 +333,6 @@ def test_get_log_level(self, options, testcase): run_test( testcase, options, - global_context=testcase["testInfo"].get("globalContext"), expected_modifier=(lambda x: LLV(x)), ) @@ -347,4 +358,4 @@ def test_get_weighted_values(self, options, testcase): ids=make_id_from_test_case, ) def test_post(self, options, testcase): - run_telemetry_test(testcase, options) + run_telemetry_test(testcase, options, global_context=None) diff --git a/tests/test_semantic_version.py b/tests/test_semantic_version.py new file mode 100644 index 0000000..d92c81f --- /dev/null +++ b/tests/test_semantic_version.py @@ -0,0 +1,190 @@ +from collections import namedtuple +import pytest + +from prefab_cloud_python.semantic_version import SemanticVersion + + +class TestSemanticVersion: + VersionTestCase = namedtuple( + "VersionTestCase", ["description", "input", "expected_result"] + ) + + ComparisonTestCase = namedtuple( + "ComparisonTestCase", ["description", "version1", "version2", "expected_result"] + ) + + @pytest.mark.parametrize( + "case", + [ + VersionTestCase( + "basic version parse succeeds", + "1.2.3", + { + "major": 1, + "minor": 2, + "patch": 3, + "prerelease": "", + "build_metadata": "", + }, + ), + VersionTestCase( + "version with prerelease parse succeeds", + "1.2.3-alpha.1", + { + "major": 1, + "minor": 2, + "patch": 3, + "prerelease": "alpha.1", + "build_metadata": "", + }, + ), + VersionTestCase( + "version with build metadata parse succeeds", + "1.2.3+build.123", + { + "major": 1, + "minor": 2, + "patch": 3, + "prerelease": "", + "build_metadata": "build.123", + }, + ), + VersionTestCase( + "version with prerelease and build metadata parse succeeds", + "1.2.3-alpha.1+build.123", + { + "major": 1, + "minor": 2, + "patch": 3, + "prerelease": "alpha.1", + "build_metadata": "build.123", + }, + ), + VersionTestCase( + "version with zero values parse succeeds", + "0.0.0", + { + "major": 0, + "minor": 0, + "patch": 0, + "prerelease": "", + "build_metadata": "", + }, + ), + ], + ids=lambda c: c.description, + ) + def test_version_parsing(self, case: VersionTestCase) -> None: + version = SemanticVersion.parse(case.input) + assert version.major == case.expected_result["major"] + assert version.minor == case.expected_result["minor"] + assert version.patch == case.expected_result["patch"] + assert version.prerelease == case.expected_result["prerelease"] + assert version.build_metadata == case.expected_result["build_metadata"] + + @pytest.mark.parametrize( + "case", + [ + VersionTestCase("empty string returns None", "", None), + VersionTestCase("invalid format returns None", "1.2", None), + VersionTestCase("invalid numbers returns None", "1.2.a", None), + VersionTestCase("invalid prerelease format returns None", "1.2.3-", None), + VersionTestCase( + "invalid build metadata format returns None", "1.2.3+", None + ), + ], + ids=lambda c: c.description, + ) + def test_parse_quietly_invalid_versions(self, case: VersionTestCase) -> None: + result = SemanticVersion.parse_quietly(case.input) + assert result == case.expected_result + + @pytest.mark.parametrize( + "case", + [ + ComparisonTestCase("equal versions compare as equal", "1.2.3", "1.2.3", 0), + ComparisonTestCase( + "higher major version compares greater", "2.0.0", "1.2.3", 1 + ), + ComparisonTestCase( + "lower major version compares less", "1.2.3", "2.0.0", -1 + ), + ComparisonTestCase( + "higher minor version compares greater", "1.3.0", "1.2.3", 1 + ), + ComparisonTestCase( + "higher patch version compares greater", "1.2.4", "1.2.3", 1 + ), + ComparisonTestCase( + "prerelease version compares less than release", + "1.2.3-alpha", + "1.2.3", + -1, + ), + ComparisonTestCase( + "build metadata doesn't affect comparison", + "1.2.3+build.1", + "1.2.3+build.2", + 0, + ), + ComparisonTestCase( + "prerelease ordering is correct", "1.2.3-alpha.2", "1.2.3-alpha.1", 1 + ), + ComparisonTestCase( + "alpha.1 comes before beta.1", "1.0.0-alpha.1", "1.0.0-beta.1", -1 + ), + ], + ids=lambda c: c.description, + ) + def test_version_comparison(self, case: ComparisonTestCase) -> None: + version1 = SemanticVersion.parse(case.version1) + version2 = SemanticVersion.parse(case.version2) + assert version1.compare(version2) == case.expected_result + + def test_sorting(self) -> None: + versions = [ + "2.0.0", + "1.0.0", + "1.1.0", + "1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-alpha.beta", + "1.0.0-beta", + "1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-rc.1", + ] + + # Create SemanticVersion objects + version_objects = [SemanticVersion.parse(v) for v in versions] + + # Sort them + sorted_versions = sorted(version_objects) + + # Expected order after sorting + expected_order = [ + "1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-alpha.beta", + "1.0.0-beta", + "1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-rc.1", + "1.0.0", + "1.1.0", + "2.0.0", + ] + + assert [str(v) for v in sorted_versions] == expected_order + + def test_equality(self) -> None: + version1 = SemanticVersion.parse("1.2.3-alpha+build.1") + version2 = SemanticVersion.parse("1.2.3-alpha+build.2") + version3 = SemanticVersion.parse("1.2.3-beta+build.1") + + # Same version with different build metadata should be equal + assert version1 == version2 + # Different prerelease versions should not be equal + assert version1 != version3 + # Non-SemanticVersion comparison should return NotImplemented + assert version1.__eq__("1.2.3") is NotImplemented diff --git a/tests/test_simple_criterion_evaluators.py b/tests/test_simple_criterion_evaluators.py new file mode 100644 index 0000000..7ef59f5 --- /dev/null +++ b/tests/test_simple_criterion_evaluators.py @@ -0,0 +1,515 @@ +from collections import namedtuple +from datetime import datetime, timezone, timedelta + +import pytest +import prefab_pb2 as Prefab +from prefab_cloud_python.simple_criterion_evaluators import ( + NumericOperators, + StringOperators, + DateOperators, + SemverOperators, + RegexMatchOperators, +) + + +class TestNumericComparisons: + NumberTestCase = namedtuple( + "NumberTestCase", # Kept your original name + [ + "description", + "contextValue", + "operator", + "criterionValue", + "expectedMatchResult", + ], + ) + + @pytest.mark.parametrize( + "case", + [ + NumberTestCase( + "2 is greater than 1", + 2.1, + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN, + 1.1, + True, + ), + NumberTestCase( + "2 is not greater than 2", + 2, + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN, + 2, + False, + ), + NumberTestCase( + "1 is not greater than 2", + 1, + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN, + 2, + False, + ), + NumberTestCase( + "2 is greater than or equal to 1", + 2.1, + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN_OR_EQUAL, + 1.1, + True, + ), + NumberTestCase( + "2 is greater than or equal to 2", + 2, + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN_OR_EQUAL, + 2, + True, + ), + NumberTestCase( + "1 is not greater than or equal to 2", + 1, + Prefab.Criterion.CriterionOperator.PROP_GREATER_THAN_OR_EQUAL, + 2, + False, + ), # + NumberTestCase( + "1.1 is less than 2", + 1.1, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN, + 2, + True, + ), + NumberTestCase( + "2 is not less than 2", + 2, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN, + 2, + False, + ), + NumberTestCase( + "2 is not less than 2", + 2, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN, + 1, + False, + ), + NumberTestCase( + "1.1 is less than or equal to 2", + 1.1, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN_OR_EQUAL, + 2, + True, + ), + NumberTestCase( + "2 is less than or equal to 2", + 2, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN_OR_EQUAL, + 2, + True, + ), + NumberTestCase( + "2 is not less than or equal to 1", + 2, + Prefab.Criterion.CriterionOperator.PROP_LESS_THAN_OR_EQUAL, + 1, + False, + ), + ], + ids=lambda c: c.description, + ) + def test_operator(self, case: NumberTestCase) -> None: + result = NumericOperators.evaluate( + case.contextValue, case.operator, case.criterionValue + ) + assert result == case.expectedMatchResult + + +class TestStringOperations: + StringTestCase = namedtuple( + "StringTestCase", # Kept your original name + [ + "description", + "contextValue", + "operator", + "criterionValue", + "expectedMatchResult", + ], + ) + + @pytest.mark.parametrize( + "case", + [ + StringTestCase( + "foobar starts with foo is true", + "foobar", + Prefab.Criterion.CriterionOperator.PROP_STARTS_WITH_ONE_OF, + ["foo", "abc"], + True, + ), + StringTestCase( + "foobar does not start with foo is false", + "foobar", + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_START_WITH_ONE_OF, + ["foo", "abc"], + False, + ), + StringTestCase( + "foobar ends with bar is true", + "foobar", + Prefab.Criterion.CriterionOperator.PROP_ENDS_WITH_ONE_OF, + ["abc", "bar"], + True, + ), + StringTestCase( + "foobar does not end with bar is false", + "foobar", + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_END_WITH_ONE_OF, + ["abc", "bar"], + False, + ), + StringTestCase( + "foobar contains oo is true", + "foobar", + Prefab.Criterion.CriterionOperator.PROP_CONTAINS_ONE_OF, + ["oo", "abc"], + True, + ), + StringTestCase( + "foobar does not contain oo is false", + "foobar", + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_CONTAIN_ONE_OF, + ["oo", "abc"], + False, + ), + ], + ids=lambda c: c.description, + ) + def test_operator(self, case: StringTestCase) -> None: + result = StringOperators.evaluate( + case.contextValue, case.operator, case.criterionValue + ) + assert result == case.expectedMatchResult + + +class TestDateOperations: + DateTestCase = namedtuple( + "DateTestCase", + [ + "description", + "contextValue", + "operator", + "criterionValue", + "expectedMatchResult", + ], + ) + + # Reference timestamps for testing + REFERENCE_TIME = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + REFERENCE_MILLIS = int(REFERENCE_TIME.timestamp() * 1000) + + ONE_HOUR_MILLIS = 3600 * 1000 + ONE_DAY_MILLIS = 24 * ONE_HOUR_MILLIS + + @pytest.mark.parametrize( + "case", + [ + # Tests with RFC3339 strings + DateTestCase( + "RFC3339 date before reference time returns true", + "2023-12-31T12:00:00Z", + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + True, + ), + DateTestCase( + "RFC3339 date after reference time returns false", + "2023-12-31T12:00:00Z", + Prefab.Criterion.CriterionOperator.PROP_AFTER, + REFERENCE_MILLIS, + False, + ), + DateTestCase( + "RFC3339 date with timezone offset before reference returns true", + "2023-12-31T14:00:00+02:00", # Same as 12:00 UTC + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + True, + ), + DateTestCase( + "RFC3339 exact match with before returns false", + "2024-01-01T12:00:00Z", + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + False, + ), + # Tests with millisecond timestamps + DateTestCase( + "Millisecond timestamp before reference returns true", + REFERENCE_MILLIS - ONE_DAY_MILLIS, + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + True, + ), + DateTestCase( + "Millisecond timestamp after reference returns true", + REFERENCE_MILLIS + ONE_HOUR_MILLIS, + Prefab.Criterion.CriterionOperator.PROP_AFTER, + REFERENCE_MILLIS, + True, + ), + # Tests with Datetime instances + DateTestCase( + "datetime before reference returns true", + REFERENCE_TIME - timedelta(days=1), + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + True, + ), + # Tests with Date instances (will assume midnight) + DateTestCase( + "datetime before reference returns true", + (REFERENCE_TIME - timedelta(days=1)).date(), + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + True, + ), + # Edge cases and invalid inputs + DateTestCase( + "Invalid RFC3339 format returns false", + "2024-13-01T12:00:00Z", # Invalid month + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + False, + ), + DateTestCase( + "Non-supported operator returns false", + "2024-01-01T12:00:00Z", + "UNSUPPORTED_OPERATOR", + REFERENCE_MILLIS, + False, + ), + DateTestCase( + "Invalid millisecond timestamp format returns false", + "not_a_number", + Prefab.Criterion.CriterionOperator.PROP_BEFORE, + REFERENCE_MILLIS, + False, + ), + ], + ids=lambda c: c.description, + ) + def test_operator(self, case: DateTestCase) -> None: + result = DateOperators.evaluate( + case.contextValue, case.operator, case.criterionValue + ) + assert result == case.expectedMatchResult + + +class TestSemverOperators: + OperatorTestCase = namedtuple( + "OperatorTestCase", + [ + "description", + "context_value", + "operator", + "criterion_value", + "expected_result", + ], + ) + + @pytest.mark.parametrize( + "case", + [ + # Valid semver comparisons + OperatorTestCase( + "equal versions return true", + "1.2.3", + Prefab.Criterion.CriterionOperator.PROP_SEMVER_EQUAL, + "1.2.3", + True, + ), + OperatorTestCase( + "equal versions with prerelease return true", + "1.2.3-alpha", + Prefab.Criterion.CriterionOperator.PROP_SEMVER_EQUAL, + "1.2.3-alpha", + True, + ), + OperatorTestCase( + "greater than comparison returns true", + "2.0.0", + Prefab.Criterion.CriterionOperator.PROP_SEMVER_GREATER_THAN, + "1.9.9", + True, + ), + OperatorTestCase( + "less than comparison returns true", + "1.9.9", + Prefab.Criterion.CriterionOperator.PROP_SEMVER_LESS_THAN, + "2.0.0", + True, + ), + # Invalid versions + OperatorTestCase( + "invalid context value returns false", + "not.a.version", + Prefab.Criterion.CriterionOperator.PROP_SEMVER_EQUAL, + "1.0.0", + False, + ), + OperatorTestCase( + "invalid criterion value returns false", + "1.0.0", + Prefab.Criterion.CriterionOperator.PROP_SEMVER_EQUAL, + "not.a.version", + False, + ), + OperatorTestCase( + "both invalid versions return false", + "invalid1", + Prefab.Criterion.CriterionOperator.PROP_SEMVER_EQUAL, + "invalid2", + False, + ), + # Unsupported operator + OperatorTestCase( + "unsupported operator returns false", + "1.0.0", + "UNSUPPORTED_OPERATOR", + "1.0.0", + False, + ), + ], + ids=lambda c: c.description, + ) + def test_operator(self, case: OperatorTestCase) -> None: + result = SemverOperators.evaluate( + case.context_value, case.operator, case.criterion_value + ) + assert result == case.expected_result + + +class TestRegexMatchOperators: + RegexTestCase = namedtuple( + "RegexTestCase", + [ + "description", + "context_value", + "operator", + "criterion_value", + "expected_result", + ], + ) + + @pytest.mark.parametrize( + "case", + [ + # Basic matching + RegexTestCase( + "simple regex match returns true", + "hello world", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + "world", + True, + ), + RegexTestCase( + "simple regex non-match returns false", + "hello world", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + "universe", + False, + ), + RegexTestCase( + "does not match returns true for non-matching regex", + "hello world", + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_MATCH, + "universe", + True, + ), + # Pattern features + RegexTestCase( + "match with wildcard returns true", + "hello world", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + "hel+o", + True, + ), + RegexTestCase( + "match with character class returns true", + "hello123", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + r"\d+", + True, + ), + RegexTestCase( + "match with start anchor returns false if not at start", + "hello world", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + "^world", + False, + ), + # Invalid patterns + RegexTestCase( + "invalid regex pattern returns false", + "hello world", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + "[unclosed", + False, + ), + RegexTestCase( + "invalid regex with does_not_match returns false", + "hello world", + Prefab.Criterion.CriterionOperator.PROP_DOES_NOT_MATCH, + "[unclosed", + False, + ), + # Non-string inputs + RegexTestCase( + "numeric context value returns false", + 123, + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + r"\d+", + False, + ), + RegexTestCase( + "numeric pattern returns false", + "123", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + 123, + False, + ), + # Empty strings + RegexTestCase( + "empty context value can still match", + "", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + "^$", + True, + ), + RegexTestCase( + "empty pattern is valid regex", + "hello", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + "", + True, + ), + # Special cases + RegexTestCase( + "None context value returns false", + None, + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + ".*", + False, + ), + RegexTestCase( + "None pattern returns false", + "hello", + Prefab.Criterion.CriterionOperator.PROP_MATCHES, + None, + False, + ), + ], + ids=lambda c: c.description, + ) + def test_operator(self, case: RegexTestCase) -> None: + result = RegexMatchOperators.evaluate( + case.context_value, case.operator, case.criterion_value + ) + assert result == case.expected_result