what am i doing anymore

This commit is contained in:
Khaleel Al-Adhami 2024-11-15 14:53:51 -08:00
parent 2c04153013
commit 5f0546f32e
10 changed files with 1498 additions and 1742 deletions

359
poetry.lock generated
View File

@ -1,4 +1,4 @@
# 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.4 and should not be changed by hand.
[[package]] [[package]]
name = "alembic" name = "alembic"
@ -386,73 +386,73 @@ files = [
[[package]] [[package]]
name = "coverage" name = "coverage"
version = "7.6.4" version = "7.6.5"
description = "Code coverage measurement for Python" description = "Code coverage measurement for Python"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
files = [ files = [
{file = "coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07"}, {file = "coverage-7.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d5fc459f1b62aa328b5c6943b4fa060fa63e7749e41c974929c503dc01d0527b"},
{file = "coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"}, {file = "coverage-7.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:197fc6b5e6271c4f822486cabbd91f32e73f784076b69c91179c5a9fec2d1442"},
{file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"}, {file = "coverage-7.6.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a7cab0762dfbf0b0cd6eb22f7bceade31bda0f0647f9420cbb45571de4493a3"},
{file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51"}, {file = "coverage-7.6.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee4559597f53455d70b9935e25c21fd05aebbb8d540af04097f7cf6dc7562754"},
{file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491"}, {file = "coverage-7.6.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e68b894ee1a170da94b7da381527f277ec00c67f6141e79aa1ce8eebbb5561"},
{file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"}, {file = "coverage-7.6.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fe4ea637711f1f1895895578972e3d0ed5efb6ef970ba0e2e26d9fad1e3c820e"},
{file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"}, {file = "coverage-7.6.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1d5f036235a747cd30be433ef7ba6dab5ac41d8dc69d54094d5438c34fe8d565"},
{file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"}, {file = "coverage-7.6.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a6ab7b88b1a614bc1db015e68048eb29b0c30ffa01be3d7d04da1f320db0f01"},
{file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"}, {file = "coverage-7.6.5-cp310-cp310-win32.whl", hash = "sha256:ad712a72cd734fb4265041005011bbf61f8d6cba74e12c91f14a9cda63a80a64"},
{file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"}, {file = "coverage-7.6.5-cp310-cp310-win_amd64.whl", hash = "sha256:61e03bb66c087b74aea6c28d10a49f72eca98b95438a8db1ae6dfcdd060f9039"},
{file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, {file = "coverage-7.6.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dffec9f67f4eb8bc9c5df720833f1f1ca36b73d86e6f95b422ca5210e264cc26"},
{file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, {file = "coverage-7.6.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2fde790ac0024af19fc5327fd50890dad0c31b653f6d2ed91ab2810c046bfe22"},
{file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, {file = "coverage-7.6.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3250186381ec8e9b71234fb92ef77da87d81cbf20df3364f8f5ebf7180ec030d"},
{file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, {file = "coverage-7.6.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ecfa205ce1fab6d8e94fe011eec04f6035a6069f70c331efd7cd1cd2d33d897"},
{file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, {file = "coverage-7.6.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15af7bfbc37de33e7df3f740cc735057606c63bbe44aee8b07339a3e7bb8ecf6"},
{file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, {file = "coverage-7.6.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:caf4d6af23af0e0df4e40e9985f6063d7f5434f225ee4d4ed7001f1428302403"},
{file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, {file = "coverage-7.6.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5dcf2da597fe616a41c59e29fd8d390ac2149aeed421172eef14470c7e9dcd06"},
{file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, {file = "coverage-7.6.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebc76107d896a53116e5ef21998f321b630b574a65b78b01176ca64e8978b43e"},
{file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, {file = "coverage-7.6.5-cp311-cp311-win32.whl", hash = "sha256:0e9e4cd48dca252d99bb97b14f13b5940813937cc7ec568418c1a195dec9cbcc"},
{file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, {file = "coverage-7.6.5-cp311-cp311-win_amd64.whl", hash = "sha256:a6eb14739a20c5a46073c8ad066ada17d91d14599ed98d724614db46fbae867b"},
{file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, {file = "coverage-7.6.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9ae01c434cb0d445008257bb42dcd38112190e5bfc3a4480fde49572b16bc2ae"},
{file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, {file = "coverage-7.6.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c72ef3be899f389c9f0934a9d06a28fa097ade096760102c732583c04cc31d75"},
{file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, {file = "coverage-7.6.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2fc574b4fb082a0141d4df00079c4877d46cb98e8ec979cbd9a92426f5abd8a"},
{file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, {file = "coverage-7.6.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1bc0eba158ad9d1883efb4f1bf08f88a999e091daf30454fd5f136322e700c72"},
{file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, {file = "coverage-7.6.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a360b282c0acbf3541cc67e8d8a2a65589ea6cfa10c7e8a48e318bf28ca90f94"},
{file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, {file = "coverage-7.6.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b22f96d3f2425942a649d786f57ae431425c9a970afae784cd865c1ffee34bad"},
{file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, {file = "coverage-7.6.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:70eca9c6bf742feaf3ee453c1aaa932c2ab88ca420f411d90aa43ae831127b22"},
{file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, {file = "coverage-7.6.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c4bafec5da3498d498a4ca3136f5a01fded487c6a54f18aea0bcd673feedf1b"},
{file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, {file = "coverage-7.6.5-cp312-cp312-win32.whl", hash = "sha256:edecf498cabb335e8a683eb672558355bb9536d4397c54f1e135d9b8910512a3"},
{file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, {file = "coverage-7.6.5-cp312-cp312-win_amd64.whl", hash = "sha256:e7c40ae56761d3c08f916019b2f8579a147f93be8e12f0f2bf4edc4ea9e1c0ab"},
{file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, {file = "coverage-7.6.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:49ea4a739dc14856d7c5f935da90db123b77a850cfddcfacb490a28de8f87257"},
{file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, {file = "coverage-7.6.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0c51339a28aa43d0f2b1211e57ceeeeed5e09f4deb6fc543d939de68069e81e"},
{file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, {file = "coverage-7.6.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:040c3d5cf4db24e7cb890bf4b547a25bd3a3516c58c9f2a22f822199ee2ad8ed"},
{file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, {file = "coverage-7.6.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0b7e67f9d3b156ab93fce71485fadd043ab04b45d5d88623c6d94f7d16ced5b"},
{file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, {file = "coverage-7.6.5-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e078bfb114025c55fdbaa802f4c13e20e6ce4e10a96918d7234656b41f69e649"},
{file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, {file = "coverage-7.6.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:559cdb21aca30810e648ac08270535c1d2e17226ebbdf90860a060d3680cb05f"},
{file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, {file = "coverage-7.6.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:23e2dd956277061f24d9eda7539113a9c35a9409a9935647a34ced79b8aacb75"},
{file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, {file = "coverage-7.6.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3e7c4ccb41dc9830b2ca8592e401045a81740f627c7c0348bdc3b7373ce52f8e"},
{file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, {file = "coverage-7.6.5-cp313-cp313-win32.whl", hash = "sha256:9d3565bb7deaa12d634426f113e6b106028c535667ba7756af65f00464981ba5"},
{file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, {file = "coverage-7.6.5-cp313-cp313-win_amd64.whl", hash = "sha256:5039410420d9ddcd5b8566d3afbb28b89d70c4481dbb283ea543263cbefa2b67"},
{file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, {file = "coverage-7.6.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:77b640aa78d4d9f620fb2e1b2a41b0d196120c188d0a7f678761d668d6251fcc"},
{file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, {file = "coverage-7.6.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bb3799f6279df37e369027128926de4c159e6399000316ebd7a69e55b84dc97f"},
{file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, {file = "coverage-7.6.5-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55aba7ab64e8af37a18064f23f399dff10041fa3aaf201528f12004968638b9f"},
{file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, {file = "coverage-7.6.5-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6065a988d724dd3328cb21e97378bef0549b2f8b7ac0a3376785d9f7f05dc736"},
{file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, {file = "coverage-7.6.5-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f092d222e4286cdd1ab9707da36944c11ba6294d8c9b18534057f03e6866367"},
{file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, {file = "coverage-7.6.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1dc99aece5f899955eece053a798e279f7fe7059dd5e2a95af82878cfe4a44e1"},
{file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, {file = "coverage-7.6.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1b14515f83ffa7a6787e725d804c6b11dd317a6bd0373d8519a61e4a587fe534"},
{file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, {file = "coverage-7.6.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9fa6d90130165346935541f3762933dae07e237ff7d6d780fae556039f08a470"},
{file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, {file = "coverage-7.6.5-cp313-cp313t-win32.whl", hash = "sha256:1be9ec4c49becb35955b9d69c27e6385aedd40d233f1cf065e8430c59924b30e"},
{file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, {file = "coverage-7.6.5-cp313-cp313t-win_amd64.whl", hash = "sha256:7ff4fd7679df56e36fc838ef227e95e3aa1b0ca0548daede7f8ae6e54479c115"},
{file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"}, {file = "coverage-7.6.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:23abf0846290aa57d629c4f4181d0d56cbaa45d3999e60cb0df1d2bab7bc6bfe"},
{file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"}, {file = "coverage-7.6.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4903685e8059e170182ac4681ee72d2dfbb92692225023c1e325a9d85c1be31"},
{file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"}, {file = "coverage-7.6.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ad9621fd9773b1461f8942da4130fbb16ee0a877eb58bc57532ea41cce20d3e"},
{file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376"}, {file = "coverage-7.6.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7324358a77f37ffd8ba94d3c8326eb316c972ec72264f36fc3be04cff8542465"},
{file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0"}, {file = "coverage-7.6.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf182001229411cd6a90d180973b345bd6fe255dbbac362100e6a625dfb107f5"},
{file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"}, {file = "coverage-7.6.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4601dacd88556c94c9fb5063b9354b1fe971af9a5b25b2575faefd12bf8170a5"},
{file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"}, {file = "coverage-7.6.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e5aa3d62285ef1b16f655e1ae298c6fa919209637d317934e382e9b99c28c118"},
{file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"}, {file = "coverage-7.6.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8cb5601620c3d98d2c98847272acc2406333d43c9d7d49386d879bd451677429"},
{file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"}, {file = "coverage-7.6.5-cp39-cp39-win32.whl", hash = "sha256:c32428f6285344caedd945236f31c46645bb10faae8702d1409bb49df218e55a"},
{file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"}, {file = "coverage-7.6.5-cp39-cp39-win_amd64.whl", hash = "sha256:809e868eee27d056bc72590c69940c119775d218681b1a8ef9ba0ef8d7693e53"},
{file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"}, {file = "coverage-7.6.5-pp39.pp310-none-any.whl", hash = "sha256:49145276f39f940b18a539e1e4a378e06c64a127922450ffd2fb82b9fe1ad3d9"},
{file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, {file = "coverage-7.6.5.tar.gz", hash = "sha256:6069188329fbe0a63876719099076261ce7a1adeea95bf236cff4353a8451b0d"},
] ]
[package.dependencies] [package.dependencies]
@ -585,13 +585,13 @@ test = ["pytest (>=6)"]
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.115.4" version = "0.115.5"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "fastapi-0.115.4-py3-none-any.whl", hash = "sha256:0b504a063ffb3cf96a5e27dc1bc32c80ca743a2528574f9cdc77daa2d31b4742"}, {file = "fastapi-0.115.5-py3-none-any.whl", hash = "sha256:596b95adbe1474da47049e802f9a65ab2ffa9c2b07e7efee70eb8a66c9f2f796"},
{file = "fastapi-0.115.4.tar.gz", hash = "sha256:db653475586b091cb8b2fec2ac54a680ac6a158e07406e1abae31679e8826349"}, {file = "fastapi-0.115.5.tar.gz", hash = "sha256:0e7a4d0dc0d01c68df21887cce0945e72d3c48b9f4f79dfe7a7d53aa08fbb289"},
] ]
[package.dependencies] [package.dependencies]
@ -785,13 +785,13 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]] [[package]]
name = "identify" name = "identify"
version = "2.6.1" version = "2.6.2"
description = "File identification library for Python" description = "File identification library for Python"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
files = [ files = [
{file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, {file = "identify-2.6.2-py2.py3-none-any.whl", hash = "sha256:c097384259f49e372f4ea00a19719d95ae27dd5ff0fd77ad630aa891306b82f3"},
{file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, {file = "identify-2.6.2.tar.gz", hash = "sha256:fab5c716c24d7a789775228823797296a2994b075fb6080ac83a102772a98cbd"},
] ]
[package.extras] [package.extras]
@ -1288,13 +1288,13 @@ attrs = ">=19.2.0"
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "24.1" version = "24.2"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
] ]
[[package]] [[package]]
@ -1350,8 +1350,8 @@ files = [
[package.dependencies] [package.dependencies]
numpy = [ numpy = [
{version = ">=1.23.2", markers = "python_version == \"3.11\""},
{version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""},
{version = ">=1.23.2", markers = "python_version == \"3.11\""},
{version = ">=1.22.4", markers = "python_version < \"3.11\""}, {version = ">=1.22.4", markers = "python_version < \"3.11\""},
] ]
python-dateutil = ">=2.8.2" python-dateutil = ">=2.8.2"
@ -1669,8 +1669,8 @@ files = [
annotated-types = ">=0.6.0" annotated-types = ">=0.6.0"
pydantic-core = "2.23.4" pydantic-core = "2.23.4"
typing-extensions = [ typing-extensions = [
{version = ">=4.6.1", markers = "python_version < \"3.13\""},
{version = ">=4.12.2", markers = "python_version >= \"3.13\""}, {version = ">=4.12.2", markers = "python_version >= \"3.13\""},
{version = ">=4.6.1", markers = "python_version < \"3.13\""},
] ]
[package.extras] [package.extras]
@ -1822,21 +1822,23 @@ files = [
[[package]] [[package]]
name = "pyright" name = "pyright"
version = "1.1.334" version = "1.1.389"
description = "Command line wrapper for pyright" description = "Command line wrapper for pyright"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "pyright-1.1.334-py3-none-any.whl", hash = "sha256:dcb13e8358e021189672c4d6ebcad192ab061e4c7225036973ec493183c6da68"}, {file = "pyright-1.1.389-py3-none-any.whl", hash = "sha256:41e9620bba9254406dc1f621a88ceab5a88af4c826feb4f614d95691ed243a60"},
{file = "pyright-1.1.334.tar.gz", hash = "sha256:3adaf10f1f4209575dc022f9c897f7ef024639b7ea5b3cbe49302147e6949cd4"}, {file = "pyright-1.1.389.tar.gz", hash = "sha256:716bf8cc174ab8b4dcf6828c3298cac05c5ed775dda9910106a5dcfe4c7fe220"},
] ]
[package.dependencies] [package.dependencies]
nodeenv = ">=1.6.0" nodeenv = ">=1.6.0"
typing-extensions = ">=4.1"
[package.extras] [package.extras]
all = ["twine (>=3.4.1)"] all = ["nodejs-wheel-binaries", "twine (>=3.4.1)"]
dev = ["twine (>=3.4.1)"] dev = ["twine (>=3.4.1)"]
nodejs = ["nodejs-wheel-binaries"]
[[package]] [[package]]
name = "pysocks" name = "pysocks"
@ -2350,23 +2352,23 @@ websocket-client = ">=1.8,<2.0"
[[package]] [[package]]
name = "setuptools" name = "setuptools"
version = "75.3.0" version = "75.5.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages" description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
files = [ files = [
{file = "setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd"}, {file = "setuptools-75.5.0-py3-none-any.whl", hash = "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"},
{file = "setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"}, {file = "setuptools-75.5.0.tar.gz", hash = "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef"},
] ]
[package.extras] [package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] core = ["importlib-metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
cover = ["pytest-cov"] cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
enabler = ["pytest-enabler (>=2.2)"] enabler = ["pytest-enabler (>=2.2)"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.12.*)", "pytest-mypy"] type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
[[package]] [[package]]
name = "shellingham" name = "shellingham"
@ -2634,13 +2636,13 @@ files = [
[[package]] [[package]]
name = "tomli" name = "tomli"
version = "2.0.2" version = "2.1.0"
description = "A lil' TOML parser" description = "A lil' TOML parser"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"},
{file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, {file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"},
] ]
[[package]] [[package]]
@ -2828,108 +2830,91 @@ test = ["websockets"]
[[package]] [[package]]
name = "websockets" name = "websockets"
version = "13.1" version = "14.1"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
files = [ files = [
{file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"}, {file = "websockets-14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a0adf84bc2e7c86e8a202537b4fd50e6f7f0e4a6b6bf64d7ccb96c4cd3330b29"},
{file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"}, {file = "websockets-14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90b5d9dfbb6d07a84ed3e696012610b6da074d97453bd01e0e30744b472c8179"},
{file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"}, {file = "websockets-14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2177ee3901075167f01c5e335a6685e71b162a54a89a56001f1c3e9e3d2ad250"},
{file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"}, {file = "websockets-14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f14a96a0034a27f9d47fd9788913924c89612225878f8078bb9d55f859272b0"},
{file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"}, {file = "websockets-14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f874ba705deea77bcf64a9da42c1f5fc2466d8f14daf410bc7d4ceae0a9fcb0"},
{file = "websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700"}, {file = "websockets-14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9607b9a442392e690a57909c362811184ea429585a71061cd5d3c2b98065c199"},
{file = "websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"}, {file = "websockets-14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bea45f19b7ca000380fbd4e02552be86343080120d074b87f25593ce1700ad58"},
{file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"}, {file = "websockets-14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:219c8187b3ceeadbf2afcf0f25a4918d02da7b944d703b97d12fb01510869078"},
{file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"}, {file = "websockets-14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ad2ab2547761d79926effe63de21479dfaf29834c50f98c4bf5b5480b5838434"},
{file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"}, {file = "websockets-14.1-cp310-cp310-win32.whl", hash = "sha256:1288369a6a84e81b90da5dbed48610cd7e5d60af62df9851ed1d1d23a9069f10"},
{file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"}, {file = "websockets-14.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0744623852f1497d825a49a99bfbec9bea4f3f946df6eb9d8a2f0c37a2fec2e"},
{file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"}, {file = "websockets-14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:449d77d636f8d9c17952628cc7e3b8faf6e92a17ec581ec0c0256300717e1512"},
{file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"}, {file = "websockets-14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a35f704be14768cea9790d921c2c1cc4fc52700410b1c10948511039be824aac"},
{file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"}, {file = "websockets-14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b1f3628a0510bd58968c0f60447e7a692933589b791a6b572fcef374053ca280"},
{file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"}, {file = "websockets-14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c3deac3748ec73ef24fc7be0b68220d14d47d6647d2f85b2771cb35ea847aa1"},
{file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"}, {file = "websockets-14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7048eb4415d46368ef29d32133134c513f507fff7d953c18c91104738a68c3b3"},
{file = "websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096"}, {file = "websockets-14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cf0ad281c979306a6a34242b371e90e891bce504509fb6bb5246bbbf31e7b6"},
{file = "websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"}, {file = "websockets-14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc1fc87428c1d18b643479caa7b15db7d544652e5bf610513d4a3478dbe823d0"},
{file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"}, {file = "websockets-14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f95ba34d71e2fa0c5d225bde3b3bdb152e957150100e75c86bc7f3964c450d89"},
{file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"}, {file = "websockets-14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9481a6de29105d73cf4515f2bef8eb71e17ac184c19d0b9918a3701c6c9c4f23"},
{file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"}, {file = "websockets-14.1-cp311-cp311-win32.whl", hash = "sha256:368a05465f49c5949e27afd6fbe0a77ce53082185bbb2ac096a3a8afaf4de52e"},
{file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"}, {file = "websockets-14.1-cp311-cp311-win_amd64.whl", hash = "sha256:6d24fc337fc055c9e83414c94e1ee0dee902a486d19d2a7f0929e49d7d604b09"},
{file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"}, {file = "websockets-14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed"},
{file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"}, {file = "websockets-14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d"},
{file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"}, {file = "websockets-14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707"},
{file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"}, {file = "websockets-14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a"},
{file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"}, {file = "websockets-14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45"},
{file = "websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9"}, {file = "websockets-14.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58"},
{file = "websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"}, {file = "websockets-14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058"},
{file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"}, {file = "websockets-14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4"},
{file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"}, {file = "websockets-14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05"},
{file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"}, {file = "websockets-14.1-cp312-cp312-win32.whl", hash = "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0"},
{file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"}, {file = "websockets-14.1-cp312-cp312-win_amd64.whl", hash = "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f"},
{file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"}, {file = "websockets-14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9"},
{file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"}, {file = "websockets-14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b"},
{file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"}, {file = "websockets-14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3"},
{file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"}, {file = "websockets-14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59"},
{file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"}, {file = "websockets-14.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2"},
{file = "websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5"}, {file = "websockets-14.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77569d19a13015e840b81550922056acabc25e3f52782625bc6843cfa034e1da"},
{file = "websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"}, {file = "websockets-14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9"},
{file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"}, {file = "websockets-14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7"},
{file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"}, {file = "websockets-14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a"},
{file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"}, {file = "websockets-14.1-cp313-cp313-win32.whl", hash = "sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6"},
{file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"}, {file = "websockets-14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0"},
{file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"}, {file = "websockets-14.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:01bb2d4f0a6d04538d3c5dfd27c0643269656c28045a53439cbf1c004f90897a"},
{file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"}, {file = "websockets-14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:414ffe86f4d6f434a8c3b7913655a1a5383b617f9bf38720e7c0799fac3ab1c6"},
{file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"}, {file = "websockets-14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fda642151d5affdee8a430bd85496f2e2517be3a2b9d2484d633d5712b15c56"},
{file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"}, {file = "websockets-14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd7c11968bc3860d5c78577f0dbc535257ccec41750675d58d8dc66aa47fe52c"},
{file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"}, {file = "websockets-14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a032855dc7db987dff813583d04f4950d14326665d7e714d584560b140ae6b8b"},
{file = "websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54"}, {file = "websockets-14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7e7ea2f782408c32d86b87a0d2c1fd8871b0399dd762364c731d86c86069a78"},
{file = "websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"}, {file = "websockets-14.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:39450e6215f7d9f6f7bc2a6da21d79374729f5d052333da4d5825af8a97e6735"},
{file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"}, {file = "websockets-14.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ceada5be22fa5a5a4cdeec74e761c2ee7db287208f54c718f2df4b7e200b8d4a"},
{file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"}, {file = "websockets-14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3fc753451d471cff90b8f467a1fc0ae64031cf2d81b7b34e1811b7e2691bc4bc"},
{file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"}, {file = "websockets-14.1-cp39-cp39-win32.whl", hash = "sha256:14839f54786987ccd9d03ed7f334baec0f02272e7ec4f6e9d427ff584aeea8b4"},
{file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"}, {file = "websockets-14.1-cp39-cp39-win_amd64.whl", hash = "sha256:d9fd19ecc3a4d5ae82ddbfb30962cf6d874ff943e56e0c81f5169be2fda62979"},
{file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"}, {file = "websockets-14.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e5dc25a9dbd1a7f61eca4b7cb04e74ae4b963d658f9e4f9aad9cd00b688692c8"},
{file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"}, {file = "websockets-14.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:04a97aca96ca2acedf0d1f332c861c5a4486fdcba7bcef35873820f940c4231e"},
{file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"}, {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df174ece723b228d3e8734a6f2a6febbd413ddec39b3dc592f5a4aa0aff28098"},
{file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"}, {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:034feb9f4286476f273b9a245fb15f02c34d9586a5bc936aff108c3ba1b21beb"},
{file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"}, {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c308dabd2b380807ab64b62985eaccf923a78ebc572bd485375b9ca2b7dc7"},
{file = "websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79"}, {file = "websockets-14.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a42d3ecbb2db5080fc578314439b1d79eef71d323dc661aa616fb492436af5d"},
{file = "websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"}, {file = "websockets-14.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddaa4a390af911da6f680be8be4ff5aaf31c4c834c1a9147bc21cbcbca2d4370"},
{file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"}, {file = "websockets-14.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4c805c6034206143fbabd2d259ec5e757f8b29d0a2f0bf3d2fe5d1f60147a4a"},
{file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"}, {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:205f672a6c2c671a86d33f6d47c9b35781a998728d2c7c2a3e1cf3333fcb62b7"},
{file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"}, {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef440054124728cc49b01c33469de06755e5a7a4e83ef61934ad95fc327fbb0"},
{file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"}, {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7591d6f440af7f73c4bd9404f3772bfee064e639d2b6cc8c94076e71b2471c1"},
{file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"}, {file = "websockets-14.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:25225cc79cfebc95ba1d24cd3ab86aaa35bcd315d12fa4358939bd55e9bd74a5"},
{file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"}, {file = "websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e"},
{file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"}, {file = "websockets-14.1.tar.gz", hash = "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8"},
{file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6"},
{file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a"},
{file = "websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23"},
{file = "websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b"},
{file = "websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51"},
{file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7"},
{file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d"},
{file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027"},
{file = "websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978"},
{file = "websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e"},
{file = "websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09"},
{file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842"},
{file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb"},
{file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20"},
{file = "websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678"},
{file = "websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f"},
{file = "websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878"},
] ]
[[package]] [[package]]
name = "wheel" name = "wheel"
version = "0.44.0" version = "0.45.0"
description = "A built-package format for Python" description = "A built-package format for Python"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "wheel-0.44.0-py3-none-any.whl", hash = "sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f"}, {file = "wheel-0.45.0-py3-none-any.whl", hash = "sha256:52f0baa5e6522155090a09c6bd95718cc46956d1b51d537ea5454249edb671c7"},
{file = "wheel-0.44.0.tar.gz", hash = "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49"}, {file = "wheel-0.45.0.tar.gz", hash = "sha256:a57353941a3183b3d5365346b567a260a0602a0f8a635926a7dede41b94c674a"},
] ]
[package.extras] [package.extras]
@ -3030,13 +3015,13 @@ h11 = ">=0.9.0,<1"
[[package]] [[package]]
name = "zipp" name = "zipp"
version = "3.20.2" version = "3.21.0"
description = "Backport of pathlib-compatible object wrapper for zip files" description = "Backport of pathlib-compatible object wrapper for zip files"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
files = [ files = [
{file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"},
{file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"},
] ]
[package.extras] [package.extras]
@ -3050,4 +3035,4 @@ type = ["pytest-mypy"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "937f0cadb1a4566117dad8d0be6018ad1a8fe9aeb19c499d2a010d36ef391ee1" content-hash = "8efad13f953b1865334876fa726e321ea73c0ca6591553ecf5d562425a2c52ee"

View File

@ -63,7 +63,7 @@ reflex-chakra = ">=0.6.0"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
pytest = ">=7.1.2,<9.0" pytest = ">=7.1.2,<9.0"
pytest-mock = ">=3.10.0,<4.0" pytest-mock = ">=3.10.0,<4.0"
pyright = ">=1.1.229,<1.1.335" pyright = ">=1.1.229,<=1.1.389"
darglint = ">=1.8.1,<2.0" darglint = ">=1.8.1,<2.0"
dill = ">=0.3.8" dill = ">=0.3.8"
toml = ">=0.10.2,<1.0" toml = ">=0.10.2,<1.0"
@ -88,6 +88,7 @@ requires = ["poetry-core>=1.5.1"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"
[tool.pyright] [tool.pyright]
reportIncompatibleMethodOverride = false
[tool.ruff] [tool.ruff]
target-version = "py39" target-version = "py39"

View File

@ -859,6 +859,33 @@ export const isTrue = (val) => {
return Boolean(val); return Boolean(val);
}; };
/**
* Returns a copy of a section of an array.
* @param {Array | string} arrayLike The array to slice.
* @param {[number, number, number]} slice The slice to apply.
* @returns The sliced array.
*/
export const atSlice = (arrayLike, slice) => {
const array = [...arrayLike];
const [startSlice, endSlice, stepSlice] = slice;
if (stepSlice ?? null === null) {
return array.slice(startSlice ?? undefined, endSlice ?? undefined);
}
const step = stepSlice ?? 1;
if (step > 0) {
return array
.slice(startSlice ?? undefined, endSlice ?? undefined)
.filter((_, i) => i % step === 0);
}
const actualStart = (endSlice ?? null) === null ? 0 : endSlice + 1;
const actualEnd =
(startSlice ?? null) === null ? array.length : startSlice + 1;
return array
.slice(actualStart, actualEnd)
.reverse()
.filter((_, i) => i % step === 0);
};
/** /**
* Get the value from a ref. * Get the value from a ref.
* @param ref The ref to get the value from. * @param ref The ref to get the value from.

View File

@ -138,34 +138,18 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
""" """
# Convert the condition to a Var. # Convert the condition to a Var.
cond_var = LiteralVar.create(condition) cond_var = LiteralVar.create(condition)
if cond_var is None:
raise ValueError("The condition must be set.")
# If the first component is a component, create a Cond component. # If the first component is a component, create a Fragment if the second component is not set.
if isinstance(c1, BaseComponent): if isinstance(c1, BaseComponent):
if c2 is not None and not isinstance(c2, BaseComponent): c2 = c2 if c2 is not None else Fragment.create()
raise ValueError("Both arguments must be components.")
return Cond.create(cond_var, c1, c2)
# Otherwise, create a conditional Var.
# Check that the second argument is valid. # Check that the second argument is valid.
if isinstance(c2, BaseComponent):
raise ValueError("Both arguments must be props.")
if c2 is None: if c2 is None:
raise ValueError("For conditional vars, the second argument must be set.") raise ValueError("For conditional vars, the second argument must be set.")
def create_var(cond_part):
return LiteralVar.create(cond_part)
# convert the truth and false cond parts into vars so the _var_data can be obtained.
c1 = create_var(c1)
c2 = create_var(c2)
# Create the conditional var. # Create the conditional var.
return ternary_operation( return ternary_operation(
cond_var.bool()._replace( # type: ignore cond_var.bool(),
merge_var_data=VarData(imports=_IS_TRUE_IMPORT),
), # type: ignore
c1, c1,
c2, c2,
) )

View File

@ -26,7 +26,9 @@ from typing import (
Iterable, Iterable,
List, List,
Literal, Literal,
NoReturn,
Optional, Optional,
Sequence,
Set, Set,
Tuple, Tuple,
Type, Type,
@ -69,6 +71,7 @@ from reflex.utils.types import (
_isinstance, _isinstance,
get_origin, get_origin,
has_args, has_args,
typehint_issubclass,
unionize, unionize,
) )
@ -82,6 +85,9 @@ if TYPE_CHECKING:
VAR_TYPE = TypeVar("VAR_TYPE", covariant=True) VAR_TYPE = TypeVar("VAR_TYPE", covariant=True)
VALUE = TypeVar("VALUE")
INT_OR_FLOAT = TypeVar("INT_OR_FLOAT", int, float)
FAKE_VAR_TYPE = TypeVar("FAKE_VAR_TYPE")
OTHER_VAR_TYPE = TypeVar("OTHER_VAR_TYPE") OTHER_VAR_TYPE = TypeVar("OTHER_VAR_TYPE")
warnings.filterwarnings("ignore", message="fields may not start with an underscore") warnings.filterwarnings("ignore", message="fields may not start with an underscore")
@ -545,11 +551,11 @@ class Var(Generic[VAR_TYPE]):
@classmethod @classmethod
def create( def create(
cls, cls,
value: Any, value: FAKE_VAR_TYPE,
_var_is_local: bool | None = None, _var_is_local: bool | None = None,
_var_is_string: bool | None = None, _var_is_string: bool | None = None,
_var_data: VarData | None = None, _var_data: VarData | None = None,
) -> Var: ) -> Var[FAKE_VAR_TYPE]:
"""Create a var from a value. """Create a var from a value.
Args: Args:
@ -587,7 +593,7 @@ class Var(Generic[VAR_TYPE]):
return LiteralVar.create(value) return LiteralVar.create(value)
if _var_is_string is False or _var_is_local is True: if _var_is_string is False or _var_is_local is True:
return cls( return Var(
_js_expr=value, _js_expr=value,
_var_data=_var_data, _var_data=_var_data,
) )
@ -629,19 +635,22 @@ class Var(Generic[VAR_TYPE]):
return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._js_expr}" return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._js_expr}"
@overload @overload
def to(self, output: Type[str]) -> StringVar: ... def to(self, output: Type[bool]) -> BooleanVar: ... # pyright: ignore [reportOverlappingOverload]
@overload @overload
def to(self, output: Type[bool]) -> BooleanVar: ... def to(self, output: Type[int]) -> NumberVar[int]: ...
@overload @overload
def to(self, output: type[int] | type[float]) -> NumberVar: ... def to(self, output: type[float]) -> NumberVar[float]: ...
@overload
def to(self, output: Type[str]) -> StringVar: ... # pyright: ignore [reportOverlappingOverload]
@overload @overload
def to( def to(
self, self,
output: type[list] | type[tuple] | type[set], output: type[Sequence[VALUE]] | type[set[VALUE]],
) -> ArrayVar: ... ) -> ArrayVar[Sequence[VALUE]]: ...
@overload @overload
def to( def to(
@ -728,20 +737,29 @@ class Var(Generic[VAR_TYPE]):
return self return self
# We use `NoReturn` here to catch `Var[Any]` and `Var[Unknown]` cases first.
@overload @overload
def guess_type(self: Var[str]) -> StringVar: ... def guess_type(self: Var[NoReturn]) -> Var: ... # pyright: ignore [reportOverlappingOverload]
@overload @overload
def guess_type(self: Var[bool]) -> BooleanVar: ... def guess_type(self: Var[bool]) -> BooleanVar: ...
@overload @overload
def guess_type(self: Var[int] | Var[float] | Var[int | float]) -> NumberVar: ... def guess_type(self: Var[INT_OR_FLOAT]) -> NumberVar[INT_OR_FLOAT]: ...
@overload @overload
def guess_type(self: Var[list] | Var[tuple] | Var[set]) -> ArrayVar: ... def guess_type(self: Var[str]) -> StringVar: ... # pyright: ignore [reportOverlappingOverload]
@overload @overload
def guess_type(self: Var[dict]) -> ObjectVar[dict]: ... def guess_type(self: Var[Sequence[VALUE]]) -> ArrayVar[Sequence[VALUE]]: ...
@overload
def guess_type(self: Var[Set[VALUE]]) -> ArrayVar[Set[VALUE]]: ...
@overload
def guess_type(
self: Var[Dict[VALUE, OTHER_VAR_TYPE]],
) -> ObjectVar[Dict[VALUE, OTHER_VAR_TYPE]]: ...
@overload @overload
def guess_type(self) -> Self: ... def guess_type(self) -> Self: ...
@ -925,7 +943,7 @@ class Var(Generic[VAR_TYPE]):
""" """
from .number import equal_operation from .number import equal_operation
return equal_operation(self, other) return equal_operation(self, other).guess_type()
def __ne__(self, other: Var | Any) -> BooleanVar: def __ne__(self, other: Var | Any) -> BooleanVar:
"""Check if the current object is not equal to the given object. """Check if the current object is not equal to the given object.
@ -948,7 +966,7 @@ class Var(Generic[VAR_TYPE]):
""" """
from .number import boolify from .number import boolify
return boolify(self).guess_type() return boolify(self) # pyright: ignore [reportReturnType]
def __and__(self, other: Var | Any) -> Var: def __and__(self, other: Var | Any) -> Var:
"""Perform a logical AND operation on the current instance and another variable. """Perform a logical AND operation on the current instance and another variable.
@ -1150,7 +1168,7 @@ class Var(Generic[VAR_TYPE]):
@overload @overload
@classmethod @classmethod
def range(cls, stop: int | NumberVar, /) -> ArrayVar[List[int]]: ... def range(cls, stop: int | NumberVar, /) -> ArrayVar[Sequence[int]]: ...
@overload @overload
@classmethod @classmethod
@ -1160,15 +1178,16 @@ class Var(Generic[VAR_TYPE]):
end: int | NumberVar, end: int | NumberVar,
step: int | NumberVar = 1, step: int | NumberVar = 1,
/, /,
) -> ArrayVar[List[int]]: ... ) -> ArrayVar[Sequence[int]]: ...
@classmethod @classmethod
def range( def range(
cls, cls,
first_endpoint: int | NumberVar, first_endpoint: int | Var[int],
second_endpoint: int | NumberVar | None = None, second_endpoint: int | Var[int] | None = None,
step: int | NumberVar | None = None, step: int | Var[int] | None = None,
) -> ArrayVar[List[int]]: /,
) -> ArrayVar[Sequence[int]]:
"""Create a range of numbers. """Create a range of numbers.
Args: Args:
@ -1181,7 +1200,11 @@ class Var(Generic[VAR_TYPE]):
""" """
from .sequence import ArrayVar from .sequence import ArrayVar
return ArrayVar.range(first_endpoint, second_endpoint, step) if second_endpoint is None:
return ArrayVar.range.call(first_endpoint).guess_type()
if step is None:
return ArrayVar.range.call(first_endpoint, second_endpoint).guess_type()
return ArrayVar.range.call(first_endpoint, second_endpoint, step).guess_type()
def __bool__(self) -> bool: def __bool__(self) -> bool:
"""Raise exception if using Var in a boolean context. """Raise exception if using Var in a boolean context.
@ -1221,6 +1244,27 @@ VAR_SUBCLASS = TypeVar("VAR_SUBCLASS", bound=Var)
VAR_INSIDE = TypeVar("VAR_INSIDE") VAR_INSIDE = TypeVar("VAR_INSIDE")
class VarWithDefault(Var[VAR_TYPE]):
"""Annotate an optional argument."""
def __init__(self, default_value: VAR_TYPE):
"""Initialize the default value.
Args:
default_value: The default value.
"""
self._default = default_value
@property
def default(self) -> Var[VAR_TYPE]:
"""Get the default value.
Returns:
The default value.
"""
return Var.create(self._default)
class ToOperation: class ToOperation:
"""A var operation that converts a var to another type.""" """A var operation that converts a var to another type."""
@ -1362,9 +1406,6 @@ class LiteralVar(Var):
Raises: Raises:
TypeError: If the value is not a supported type for LiteralVar. TypeError: If the value is not a supported type for LiteralVar.
""" """
from .object import LiteralObjectVar
from .sequence import LiteralStringVar
if isinstance(value, Var): if isinstance(value, Var):
if _var_data is None: if _var_data is None:
return value return value
@ -1377,6 +1418,9 @@ class LiteralVar(Var):
from reflex.event import EventHandler from reflex.event import EventHandler
from reflex.utils.format import get_event_handler_parts from reflex.utils.format import get_event_handler_parts
from .object import LiteralObjectVar
from .sequence import LiteralStringVar
if isinstance(value, EventHandler): if isinstance(value, EventHandler):
return Var(_js_expr=".".join(filter(None, get_event_handler_parts(value)))) return Var(_js_expr=".".join(filter(None, get_event_handler_parts(value))))
@ -1466,7 +1510,7 @@ def get_python_literal(value: Union[LiteralVar, Any]) -> Any | None:
return value return value
def validate_arg(type_hint: GenericType) -> Callable[[Any], bool]: def validate_arg(type_hint: GenericType) -> Callable[[Any], str | None]:
"""Create a validator for an argument. """Create a validator for an argument.
Args: Args:
@ -1477,7 +1521,15 @@ def validate_arg(type_hint: GenericType) -> Callable[[Any], bool]:
""" """
def validate(value: Any): def validate(value: Any):
return True if isinstance(value, LiteralVar):
if not _isinstance(value._var_value, type_hint):
return f"Expected {type_hint} but got {value._var_value} of type {type(value._var_value)}."
elif isinstance(value, Var):
if not typehint_issubclass(value._var_type, type_hint):
return f"Expected {type_hint} but got {value._var_type}."
else:
if not _isinstance(value, type_hint):
return f"Expected {type_hint} but got {value} of type {type(value)}."
return validate return validate
@ -1505,14 +1557,58 @@ class TypeComputer(Protocol):
@overload @overload
def var_operation( def var_operation(
func: Callable[[], CustomVarOperationReturn[T]], func: Callable[[Var[V1], Var[V2], Var[V3]], CustomVarOperationReturn[T]],
) -> ArgsFunctionOperation[ReflexCallable[[], T]]: ... ) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3], T]]: ...
@overload @overload
def var_operation( def var_operation(
func: Callable[[Var[V1]], CustomVarOperationReturn[T]], func: Callable[[Var[V1], Var[V2], VarWithDefault[V3]], CustomVarOperationReturn[T]],
) -> ArgsFunctionOperation[ReflexCallable[[V1], T]]: ... ) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, VarWithDefault[V3]], T]]: ...
@overload
def var_operation(
func: Callable[
[
Var[V1],
VarWithDefault[V2],
VarWithDefault[V3],
],
CustomVarOperationReturn[T],
],
) -> ArgsFunctionOperation[
ReflexCallable[
[
V1,
VarWithDefault[V2],
VarWithDefault[V3],
],
T,
]
]: ...
@overload
def var_operation(
func: Callable[
[
VarWithDefault[V1],
VarWithDefault[V2],
VarWithDefault[V3],
],
CustomVarOperationReturn[T],
],
) -> ArgsFunctionOperation[
ReflexCallable[
[
VarWithDefault[V1],
VarWithDefault[V1],
VarWithDefault[V1],
],
T,
]
]: ...
@overload @overload
@ -1523,23 +1619,68 @@ def var_operation(
@overload @overload
def var_operation( def var_operation(
func: Callable[[Var[V1], Var[V2], Var[V3]], CustomVarOperationReturn[T]], func: Callable[
) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3], T]]: ... [
Var[V1],
VarWithDefault[V2],
@overload ],
def var_operation( CustomVarOperationReturn[T],
func: Callable[[Var[V1], Var[V2], Var[V3], Var[V4]], CustomVarOperationReturn[T]], ],
) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3, V4], T]]: ... ) -> ArgsFunctionOperation[
ReflexCallable[
[
V1,
VarWithDefault[V2],
],
T,
]
]: ...
@overload @overload
def var_operation( def var_operation(
func: Callable[ func: Callable[
[Var[V1], Var[V2], Var[V3], Var[V4], Var[V5]], [
VarWithDefault[V1],
VarWithDefault[V2],
],
CustomVarOperationReturn[T], CustomVarOperationReturn[T],
], ],
) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3, V4, V5], T]]: ... ) -> ArgsFunctionOperation[
ReflexCallable[
[
VarWithDefault[V1],
VarWithDefault[V2],
],
T,
]
]: ...
@overload
def var_operation(
func: Callable[[Var[V1]], CustomVarOperationReturn[T]],
) -> ArgsFunctionOperation[ReflexCallable[[V1], T]]: ...
@overload
def var_operation(
func: Callable[
[VarWithDefault[V1]],
CustomVarOperationReturn[T],
],
) -> ArgsFunctionOperation[
ReflexCallable[
[VarWithDefault[V1]],
T,
]
]: ...
@overload
def var_operation(
func: Callable[[], CustomVarOperationReturn[T]],
) -> ArgsFunctionOperation[ReflexCallable[[], T]]: ...
def var_operation( def var_operation(
@ -1568,6 +1709,7 @@ def var_operation(
func_name = func.__name__ func_name = func.__name__
func_arg_spec = inspect.getfullargspec(func) func_arg_spec = inspect.getfullargspec(func)
func_signature = inspect.signature(func)
if func_arg_spec.kwonlyargs: if func_arg_spec.kwonlyargs:
raise TypeError(f"Function {func_name} cannot have keyword-only arguments.") raise TypeError(f"Function {func_name} cannot have keyword-only arguments.")
@ -1576,10 +1718,23 @@ def var_operation(
arg_names = func_arg_spec.args arg_names = func_arg_spec.args
arg_default_values: Sequence[inspect.Parameter.empty | VarWithDefault] = tuple(
(
default_value
if isinstance(
(default_value := func_signature.parameters[arg_name].default),
VarWithDefault,
)
else inspect.Parameter.empty()
)
for arg_name in arg_names
)
type_hints = get_type_hints(func) type_hints = get_type_hints(func)
if not all( if not all(
(get_origin((type_hint := type_hints.get(arg_name, Any))) or type_hint) is Var (get_origin((type_hint := type_hints.get(arg_name, Any))) or type_hint)
in (Var, VarWithDefault)
and len(get_args(type_hint)) <= 1 and len(get_args(type_hint)) <= 1
for arg_name in arg_names for arg_name in arg_names
): ):
@ -1606,13 +1761,22 @@ def var_operation(
args_operation = ArgsFunctionOperation.create( args_operation = ArgsFunctionOperation.create(
tuple(map(str, arg_vars)), tuple(map(str, arg_vars)),
custom_operation_return, custom_operation_return,
default_values=arg_default_values,
validators=tuple( validators=tuple(
validate_arg(type_hints.get(arg_name, Any)) for arg_name in arg_names validate_arg(arg_type)
if not isinstance(arg_type, TypeVar)
else validate_arg(arg_type.__bound__ or Any)
for _, arg_type in args_with_type_hints
), ),
function_name=func_name, function_name=func_name,
type_computer=custom_operation_return._type_computer, type_computer=custom_operation_return._type_computer,
_var_type=ReflexCallable[ _var_type=ReflexCallable[
tuple(arg_python_type for _, arg_python_type in args_with_type_hints), # type: ignore tuple(
arg_python_type
if isinstance(arg_default_values[i], inspect.Parameter)
else VarWithDefault[arg_python_type]
for i, (_, arg_python_type) in enumerate(args_with_type_hints)
), # type: ignore
custom_operation_return._var_type, custom_operation_return._var_type,
], ],
) )
@ -2018,10 +2182,10 @@ class ComputedVar(Var[RETURN_TYPE]):
@overload @overload
def __get__( def __get__(
self: ComputedVar[list[LIST_INSIDE]], self: ComputedVar[Sequence[LIST_INSIDE]],
instance: None, instance: None,
owner: Type, owner: Type,
) -> ArrayVar[list[LIST_INSIDE]]: ... ) -> ArrayVar[Sequence[LIST_INSIDE]]: ...
@overload @overload
def __get__( def __get__(
@ -2030,13 +2194,6 @@ class ComputedVar(Var[RETURN_TYPE]):
owner: Type, owner: Type,
) -> ArrayVar[set[LIST_INSIDE]]: ... ) -> ArrayVar[set[LIST_INSIDE]]: ...
@overload
def __get__(
self: ComputedVar[tuple[LIST_INSIDE, ...]],
instance: None,
owner: Type,
) -> ArrayVar[tuple[LIST_INSIDE, ...]]: ...
@overload @overload
def __get__(self, instance: None, owner: Type) -> ComputedVar[RETURN_TYPE]: ... def __get__(self, instance: None, owner: Type) -> ComputedVar[RETURN_TYPE]: ...
@ -2175,7 +2332,7 @@ class ComputedVar(Var[RETURN_TYPE]):
d.update( d.update(
self._deps( self._deps(
objclass=objclass, objclass=objclass,
obj=ref_obj, obj=ref_obj, # pyright: ignore [reportArgumentType]
) )
) )
# recurse into property fget functions # recurse into property fget functions
@ -2218,7 +2375,7 @@ class ComputedVar(Var[RETURN_TYPE]):
with contextlib.suppress(AttributeError): with contextlib.suppress(AttributeError):
delattr(instance, self._cache_attr) delattr(instance, self._cache_attr)
def _determine_var_type(self) -> Type: def _determine_var_type(self) -> GenericType:
"""Get the type of the var. """Get the type of the var.
Returns: Returns:
@ -2672,8 +2829,12 @@ def _extract_var_data(value: Iterable) -> list[VarData | None]:
var_datas.append(sub._var_data) var_datas.append(sub._var_data)
elif not isinstance(sub, str): elif not isinstance(sub, str):
# Recurse into dict values. # Recurse into dict values.
if hasattr(sub, "values") and callable(sub.values): if (
var_datas.extend(_extract_var_data(sub.values())) (values_fn := getattr(sub, "values", None)) is not None
and callable(values_fn)
and isinstance((values := values_fn()), Iterable)
):
var_datas.extend(_extract_var_data(values))
# Recurse into iterable values (or dict keys). # Recurse into iterable values (or dict keys).
var_datas.extend(_extract_var_data(sub)) var_datas.extend(_extract_var_data(sub))
@ -2682,9 +2843,9 @@ def _extract_var_data(value: Iterable) -> list[VarData | None]:
var_datas.append(value._var_data) var_datas.append(value._var_data)
else: else:
# Recurse when value is a dict itself. # Recurse when value is a dict itself.
values = getattr(value, "values", None) values_fn = getattr(value, "values", None)
if callable(values): if callable(values_fn) and isinstance((values := values_fn()), Iterable):
var_datas.extend(_extract_var_data(values())) var_datas.extend(_extract_var_data(values))
return var_datas return var_datas
@ -2966,10 +3127,10 @@ class Field(Generic[T]):
@overload @overload
def __get__( def __get__(
self: Field[List[V]] | Field[Set[V]] | Field[Tuple[V, ...]], self: Field[Sequence[V]] | Field[Set[V]],
instance: None, instance: None,
owner, owner,
) -> ArrayVar[List[V]]: ... ) -> ArrayVar[Sequence[V]]: ...
@overload @overload
def __get__( def __get__(
@ -3151,7 +3312,7 @@ def nary_type_computer(
def type_computer(*args: Var): def type_computer(*args: Var):
if len(args) != len(types): if len(args) != len(types):
return ( return (
ReflexCallable[[], types[len(args)]], # type: ignore types[len(args)],
functools.partial(type_computer, *args), functools.partial(type_computer, *args),
) )
return ( return (

View File

@ -3,14 +3,25 @@
from __future__ import annotations from __future__ import annotations
import dataclasses import dataclasses
import inspect
import sys import sys
from typing import Any, Callable, Optional, Sequence, Tuple, Type, Union, overload from typing import (
Any,
Callable,
NoReturn,
Optional,
Sequence,
Tuple,
Type,
Union,
overload,
)
from typing_extensions import Concatenate, Generic, ParamSpec, TypeVar from typing_extensions import Concatenate, Generic, ParamSpec, TypeVar
from reflex.utils import format from reflex.utils import format
from reflex.utils.exceptions import VarTypeError from reflex.utils.exceptions import VarTypeError
from reflex.utils.types import GenericType from reflex.utils.types import GenericType, Unset, get_origin
from .base import ( from .base import (
CachedVarOperation, CachedVarOperation,
@ -19,12 +30,14 @@ from .base import (
TypeComputer, TypeComputer,
Var, Var,
VarData, VarData,
VarWithDefault,
cached_property_no_lock, cached_property_no_lock,
unwrap_reflex_callalbe, unwrap_reflex_callalbe,
) )
P = ParamSpec("P") P = ParamSpec("P")
R = TypeVar("R") R = TypeVar("R")
R2 = TypeVar("R2")
V1 = TypeVar("V1") V1 = TypeVar("V1")
V2 = TypeVar("V2") V2 = TypeVar("V2")
V3 = TypeVar("V3") V3 = TypeVar("V3")
@ -47,20 +60,39 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
@overload @overload
def partial( def partial(
self: FunctionVar[ReflexCallable[Concatenate[V1, P], R]], self: FunctionVar[ReflexCallable[Concatenate[VarWithDefault[V1], P], R]]
| FunctionVar[ReflexCallable[Concatenate[V1, P], R]],
arg1: Union[V1, Var[V1]], arg1: Union[V1, Var[V1]],
) -> FunctionVar[ReflexCallable[P, R]]: ... ) -> FunctionVar[ReflexCallable[P, R]]: ...
@overload @overload
def partial( def partial(
self: FunctionVar[ReflexCallable[Concatenate[V1, V2, P], R]], self: FunctionVar[
ReflexCallable[Concatenate[VarWithDefault[V1], VarWithDefault[V2], P], R]
]
| FunctionVar[ReflexCallable[Concatenate[V1, VarWithDefault[V2], P], R]]
| FunctionVar[ReflexCallable[Concatenate[V1, V2, P], R]],
arg1: Union[V1, Var[V1]], arg1: Union[V1, Var[V1]],
arg2: Union[V2, Var[V2]], arg2: Union[V2, Var[V2]],
) -> FunctionVar[ReflexCallable[P, R]]: ... ) -> FunctionVar[ReflexCallable[P, R]]: ...
@overload @overload
def partial( def partial(
self: FunctionVar[ReflexCallable[Concatenate[V1, V2, V3, P], R]], self: FunctionVar[
ReflexCallable[
Concatenate[
VarWithDefault[V1], VarWithDefault[V2], VarWithDefault[V3], P
],
R,
]
]
| FunctionVar[
ReflexCallable[
Concatenate[V1, VarWithDefault[V2], VarWithDefault[V3], P], R
]
]
| FunctionVar[ReflexCallable[Concatenate[V1, V2, VarWithDefault[V3], P], R]]
| FunctionVar[ReflexCallable[Concatenate[V1, V2, V3, P], R]],
arg1: Union[V1, Var[V1]], arg1: Union[V1, Var[V1]],
arg2: Union[V2, Var[V2]], arg2: Union[V2, Var[V2]],
arg3: Union[V3, Var[V3]], arg3: Union[V3, Var[V3]],
@ -148,11 +180,58 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
_var_type=partial_types, _var_type=partial_types,
) )
@overload
def call(self: FunctionVar[ReflexCallable[[], R]]) -> VarOperationCall[[], R]: ...
@overload
def call(
self: FunctionVar[ReflexCallable[[VarWithDefault[V1]], R]],
arg1: Union[V1, Var[V1], Unset] = Unset(),
) -> VarOperationCall[[VarWithDefault[V1]], R]: ...
@overload
def call(
self: FunctionVar[ReflexCallable[[VarWithDefault[V1], VarWithDefault[V2]], R]],
arg1: Union[V1, Var[V1], Unset] = Unset(),
arg2: Union[V2, Var[V2], Unset] = Unset(),
) -> VarOperationCall[[VarWithDefault[V1], VarWithDefault[V2]], R]: ...
@overload
def call(
self: FunctionVar[
ReflexCallable[
[VarWithDefault[V1], VarWithDefault[V2], VarWithDefault[V3]], R
]
],
arg1: Union[V1, Var[V1], Unset] = Unset(),
arg2: Union[V2, Var[V2], Unset] = Unset(),
arg3: Union[V3, Var[V3], Unset] = Unset(),
) -> VarOperationCall[
[VarWithDefault[V1], VarWithDefault[V2], VarWithDefault[V3]], R
]: ...
@overload @overload
def call( def call(
self: FunctionVar[ReflexCallable[[V1], R]], arg1: Union[V1, Var[V1]] self: FunctionVar[ReflexCallable[[V1], R]], arg1: Union[V1, Var[V1]]
) -> VarOperationCall[[V1], R]: ... ) -> VarOperationCall[[V1], R]: ...
@overload
def call(
self: FunctionVar[ReflexCallable[[V1, VarWithDefault[V2]], R]],
arg1: Union[V1, Var[V1]],
arg2: Union[V2, Var[V2], Unset] = Unset(),
) -> VarOperationCall[[V1, VarWithDefault[V2]], R]: ...
@overload
def call(
self: FunctionVar[
ReflexCallable[[V1, VarWithDefault[V2], VarWithDefault[V3]], R]
],
arg1: Union[V1, Var[V1]],
arg2: Union[V2, Var[V2], Unset] = Unset(),
arg3: Union[V3, Var[V3], Unset] = Unset(),
) -> VarOperationCall[[V1, VarWithDefault[V2], VarWithDefault[V3]], R]: ...
@overload @overload
def call( def call(
self: FunctionVar[ReflexCallable[[V1, V2], R]], self: FunctionVar[ReflexCallable[[V1, V2], R]],
@ -160,6 +239,14 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
arg2: Union[V2, Var[V2]], arg2: Union[V2, Var[V2]],
) -> VarOperationCall[[V1, V2], R]: ... ) -> VarOperationCall[[V1, V2], R]: ...
@overload
def call(
self: FunctionVar[ReflexCallable[[V1, V2, VarWithDefault[V3]], R]],
arg1: Union[V1, Var[V1]],
arg2: Union[V2, Var[V2]],
arg3: Union[V3, Var[V3], Unset] = Unset(),
) -> VarOperationCall[[V1, V2, VarWithDefault[V3]], R]: ...
@overload @overload
def call( def call(
self: FunctionVar[ReflexCallable[[V1, V2, V3], R]], self: FunctionVar[ReflexCallable[[V1, V2, V3], R]],
@ -198,15 +285,11 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
arg6: Union[V6, Var[V6]], arg6: Union[V6, Var[V6]],
) -> VarOperationCall[[V1, V2, V3, V4, V5, V6], R]: ... ) -> VarOperationCall[[V1, V2, V3, V4, V5, V6], R]: ...
# Capture Any to allow for arbitrary number of arguments
@overload @overload
def call( def call(self: FunctionVar[NoReturn], *args: Var | Any) -> VarOperationCall: ...
self: FunctionVar[ReflexCallable[P, R]], *args: Var | Any
) -> VarOperationCall[P, R]: ...
@overload def call(self, *args: Var | Any) -> VarOperationCall: # type: ignore
def call(self, *args: Var | Any) -> Var: ...
def call(self, *args: Var | Any) -> Var: # type: ignore
"""Call the function with the given arguments. """Call the function with the given arguments.
Args: Args:
@ -218,13 +301,53 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
Raises: Raises:
VarTypeError: If the number of arguments is invalid VarTypeError: If the number of arguments is invalid
""" """
required_arg_len = self._required_arg_len()
arg_len = self._arg_len() arg_len = self._arg_len()
if arg_len is not None and len(args) != arg_len: if arg_len is not None:
raise VarTypeError(f"Invalid number of arguments provided to {str(self)}") if len(args) < required_arg_len:
raise VarTypeError(
f"Passed {len(args)} arguments, expected at least {required_arg_len} for {str(self)}"
)
if len(args) > arg_len:
raise VarTypeError(
f"Passed {len(args)} arguments, expected at most {arg_len} for {str(self)}"
)
args = tuple(map(LiteralVar.create, args)) args = tuple(map(LiteralVar.create, args))
self._pre_check(*args) self._pre_check(*args)
return_type = self._return_type(*args) return_type = self._return_type(*args)
return VarOperationCall.create(self, *args, _var_type=return_type).guess_type() return VarOperationCall.create(self, *args, _var_type=return_type)
def chain(
self: FunctionVar[ReflexCallable[P, R]],
other: FunctionVar[ReflexCallable[[R], R2]]
| FunctionVar[ReflexCallable[[R, VarWithDefault[Any]], R2]]
| FunctionVar[
ReflexCallable[[R, VarWithDefault[Any], VarWithDefault[Any]], R2]
],
) -> FunctionVar[ReflexCallable[P, R2]]:
"""Chain two functions together.
Args:
other: The other function to chain.
Returns:
The chained function.
"""
self_arg_type, self_return_type = unwrap_reflex_callalbe(self._var_type)
_, other_return_type = unwrap_reflex_callalbe(other._var_type)
return ArgsFunctionOperationBuilder.create(
(),
VarOperationCall.create(
other,
VarOperationCall.create(
self, Var(_js_expr="...args"), _var_type=self_return_type
),
_var_type=other_return_type,
),
rest="arg",
_var_type=ReflexCallable[self_arg_type, other_return_type], # pyright: ignore [reportInvalidTypeArguments]
)
def _partial_type( def _partial_type(
self, *args: Var | Any self, *args: Var | Any
@ -253,6 +376,21 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
return len(args_types) return len(args_types)
return None return None
def _required_arg_len(self) -> int:
"""Get the number of required arguments the function takes.
Returns:
The number of required arguments the function takes.
"""
args_types, _ = unwrap_reflex_callalbe(self._var_type)
if isinstance(args_types, tuple):
return sum(
1
for arg_type in args_types
if get_origin(arg_type) is not VarWithDefault
)
return 0
def _return_type(self, *args: Var | Any) -> GenericType: def _return_type(self, *args: Var | Any) -> GenericType:
"""Override the type of the function call with the given arguments. """Override the type of the function call with the given arguments.
@ -265,7 +403,9 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
partial_types, _ = self._partial_type(*args) partial_types, _ = self._partial_type(*args)
return unwrap_reflex_callalbe(partial_types)[1] return unwrap_reflex_callalbe(partial_types)[1]
def _pre_check(self, *args: Var | Any) -> Tuple[Callable[[Any], bool], ...]: def _pre_check(
self, *args: Var | Any
) -> Tuple[Callable[[Any], Optional[str]], ...]:
"""Check if the function can be called with the given arguments. """Check if the function can be called with the given arguments.
Args: Args:
@ -276,6 +416,30 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]):
""" """
return tuple() return tuple()
@overload
def __get__(self, instance: None, owner: Any) -> FunctionVar[CALLABLE_TYPE]: ...
@overload
def __get__(
self: FunctionVar[ReflexCallable[Concatenate[V1, P], R]],
instance: Var[V1],
owner: Any,
) -> FunctionVar[ReflexCallable[P, R]]: ...
def __get__(self, instance: Any, owner: Any):
"""Get the function var.
Args:
instance: The instance of the class.
owner: The owner of the class.
Returns:
The function var.
"""
if instance is None:
return self
return self.partial(instance)
__call__ = call __call__ = call
@ -321,7 +485,9 @@ class FunctionStringVar(FunctionVar[CALLABLE_TYPE]):
class VarOperationCall(Generic[P, R], CachedVarOperation, Var[R]): class VarOperationCall(Generic[P, R], CachedVarOperation, Var[R]):
"""Base class for immutable vars that are the result of a function call.""" """Base class for immutable vars that are the result of a function call."""
_func: Optional[FunctionVar[ReflexCallable[P, R]]] = dataclasses.field(default=None) _func: Optional[FunctionVar[ReflexCallable[..., R]]] = dataclasses.field(
default=None
)
_args: Tuple[Union[Var, Any], ...] = dataclasses.field(default_factory=tuple) _args: Tuple[Union[Var, Any], ...] = dataclasses.field(default_factory=tuple)
@cached_property_no_lock @cached_property_no_lock
@ -331,7 +497,8 @@ class VarOperationCall(Generic[P, R], CachedVarOperation, Var[R]):
Returns: Returns:
The name of the var. The name of the var.
""" """
return f"({str(self._func)}({', '.join([str(LiteralVar.create(arg)) for arg in self._args])}))" func_str = str(self._func)
return f"({func_str}({', '.join([str(LiteralVar.create(arg)) for arg in self._args])}))"
@cached_property_no_lock @cached_property_no_lock
def _cached_get_all_var_data(self) -> VarData | None: def _cached_get_all_var_data(self) -> VarData | None:
@ -422,8 +589,16 @@ def format_args_function_operation(
""" """
arg_names_str = ", ".join( arg_names_str = ", ".join(
[ [
arg if isinstance(arg, str) else arg.to_javascript() (arg if isinstance(arg, str) else arg.to_javascript())
for arg in self._args.args + (
f" = {str(default_value.default)}"
if i < len(self._default_values)
and not isinstance(
(default_value := self._default_values[i]), inspect.Parameter.empty
)
else ""
)
for i, arg in enumerate(self._args.args)
] ]
+ ([f"...{self._args.rest}"] if self._args.rest else []) + ([f"...{self._args.rest}"] if self._args.rest else [])
) )
@ -442,7 +617,7 @@ def format_args_function_operation(
def pre_check_args( def pre_check_args(
self: ArgsFunctionOperation | ArgsFunctionOperationBuilder, *args: Var | Any self: ArgsFunctionOperation | ArgsFunctionOperationBuilder, *args: Var | Any
) -> Tuple[Callable[[Any], bool], ...]: ) -> Tuple[Callable[[Any], Optional[str]], ...]:
"""Check if the function can be called with the given arguments. """Check if the function can be called with the given arguments.
Args: Args:
@ -456,14 +631,14 @@ def pre_check_args(
VarTypeError: If the arguments are invalid. VarTypeError: If the arguments are invalid.
""" """
for i, (validator, arg) in enumerate(zip(self._validators, args)): for i, (validator, arg) in enumerate(zip(self._validators, args)):
if not validator(arg): if (validation_message := validator(arg)) is not None:
arg_name = self._args.args[i] if i < len(self._args.args) else None arg_name = self._args.args[i] if i < len(self._args.args) else None
if arg_name is not None: if arg_name is not None:
raise VarTypeError( raise VarTypeError(
f"Invalid argument {str(arg)} provided to {arg_name} in {self._function_name or 'var operation'}" f"Invalid argument {str(arg)} provided to {arg_name} in {self._function_name or 'var operation'}. {validation_message}"
) )
raise VarTypeError( raise VarTypeError(
f"Invalid argument {str(arg)} provided to argument {i} in {self._function_name or 'var operation'}" f"Invalid argument {str(arg)} provided to argument {i} in {self._function_name or 'var operation'}. {validation_message}"
) )
return self._validators[len(args) :] return self._validators[len(args) :]
@ -497,7 +672,10 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
"""Base class for immutable function defined via arguments and return expression.""" """Base class for immutable function defined via arguments and return expression."""
_args: FunctionArgs = dataclasses.field(default_factory=FunctionArgs) _args: FunctionArgs = dataclasses.field(default_factory=FunctionArgs)
_validators: Tuple[Callable[[Any], bool], ...] = dataclasses.field( _default_values: Tuple[VarWithDefault | inspect.Parameter.empty, ...] = (
dataclasses.field(default_factory=tuple)
)
_validators: Tuple[Callable[[Any], Optional[str]], ...] = dataclasses.field(
default_factory=tuple default_factory=tuple
) )
_return_expr: Union[Var, Any] = dataclasses.field(default=None) _return_expr: Union[Var, Any] = dataclasses.field(default=None)
@ -516,8 +694,10 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
cls, cls,
args_names: Sequence[Union[str, DestructuredArg]], args_names: Sequence[Union[str, DestructuredArg]],
return_expr: Var | Any, return_expr: Var | Any,
/,
default_values: Sequence[VarWithDefault | inspect.Parameter.empty] = (),
rest: str | None = None, rest: str | None = None,
validators: Sequence[Callable[[Any], bool]] = (), validators: Sequence[Callable[[Any], Optional[str]]] = (),
function_name: str = "", function_name: str = "",
explicit_return: bool = False, explicit_return: bool = False,
type_computer: Optional[TypeComputer] = None, type_computer: Optional[TypeComputer] = None,
@ -529,6 +709,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
Args: Args:
args_names: The names of the arguments. args_names: The names of the arguments.
return_expr: The return expression of the function. return_expr: The return expression of the function.
default_values: The default values of the arguments.
rest: The name of the rest argument. rest: The name of the rest argument.
validators: The validators for the arguments. validators: The validators for the arguments.
function_name: The name of the function. function_name: The name of the function.
@ -545,6 +726,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
_var_type=_var_type, _var_type=_var_type,
_var_data=_var_data, _var_data=_var_data,
_args=FunctionArgs(args=tuple(args_names), rest=rest), _args=FunctionArgs(args=tuple(args_names), rest=rest),
_default_values=tuple(default_values),
_function_name=function_name, _function_name=function_name,
_validators=tuple(validators), _validators=tuple(validators),
_return_expr=return_expr, _return_expr=return_expr,
@ -564,7 +746,10 @@ class ArgsFunctionOperationBuilder(
"""Base class for immutable function defined via arguments and return expression with the builder pattern.""" """Base class for immutable function defined via arguments and return expression with the builder pattern."""
_args: FunctionArgs = dataclasses.field(default_factory=FunctionArgs) _args: FunctionArgs = dataclasses.field(default_factory=FunctionArgs)
_validators: Tuple[Callable[[Any], bool], ...] = dataclasses.field( _default_values: Tuple[VarWithDefault | inspect.Parameter.empty, ...] = (
dataclasses.field(default_factory=tuple)
)
_validators: Tuple[Callable[[Any], Optional[str]], ...] = dataclasses.field(
default_factory=tuple default_factory=tuple
) )
_return_expr: Union[Var, Any] = dataclasses.field(default=None) _return_expr: Union[Var, Any] = dataclasses.field(default=None)
@ -583,8 +768,10 @@ class ArgsFunctionOperationBuilder(
cls, cls,
args_names: Sequence[Union[str, DestructuredArg]], args_names: Sequence[Union[str, DestructuredArg]],
return_expr: Var | Any, return_expr: Var | Any,
/,
default_values: Sequence[VarWithDefault | inspect.Parameter.empty] = (),
rest: str | None = None, rest: str | None = None,
validators: Sequence[Callable[[Any], bool]] = (), validators: Sequence[Callable[[Any], Optional[str]]] = (),
function_name: str = "", function_name: str = "",
explicit_return: bool = False, explicit_return: bool = False,
type_computer: Optional[TypeComputer] = None, type_computer: Optional[TypeComputer] = None,
@ -596,6 +783,7 @@ class ArgsFunctionOperationBuilder(
Args: Args:
args_names: The names of the arguments. args_names: The names of the arguments.
return_expr: The return expression of the function. return_expr: The return expression of the function.
default_values: The default values of the arguments.
rest: The name of the rest argument. rest: The name of the rest argument.
validators: The validators for the arguments. validators: The validators for the arguments.
function_name: The name of the function. function_name: The name of the function.
@ -612,6 +800,7 @@ class ArgsFunctionOperationBuilder(
_var_type=_var_type, _var_type=_var_type,
_var_data=_var_data, _var_data=_var_data,
_args=FunctionArgs(args=tuple(args_names), rest=rest), _args=FunctionArgs(args=tuple(args_names), rest=rest),
_default_values=tuple(default_values),
_function_name=function_name, _function_name=function_name,
_validators=tuple(validators), _validators=tuple(validators),
_return_expr=return_expr, _return_expr=return_expr,

View File

@ -30,6 +30,7 @@ from .base import (
NUMBER_T = TypeVar("NUMBER_T", int, float, Union[int, float], bool) NUMBER_T = TypeVar("NUMBER_T", int, float, Union[int, float], bool)
if TYPE_CHECKING: if TYPE_CHECKING:
from .function import FunctionVar
from .sequence import ArrayVar from .sequence import ArrayVar
@ -53,13 +54,7 @@ def raise_unsupported_operand_types(
class NumberVar(Var[NUMBER_T], python_types=(int, float)): class NumberVar(Var[NUMBER_T], python_types=(int, float)):
"""Base class for immutable number vars.""" """Base class for immutable number vars."""
@overload def __add__(self, other: number_types) -> NumberVar:
def __add__(self, other: number_types) -> NumberVar: ...
@overload
def __add__(self, other: NoReturn) -> NoReturn: ...
def __add__(self, other: Any):
"""Add two numbers. """Add two numbers.
Args: Args:
@ -72,13 +67,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
raise_unsupported_operand_types("+", (type(self), type(other))) raise_unsupported_operand_types("+", (type(self), type(other)))
return number_add_operation(self, +other).guess_type() return number_add_operation(self, +other).guess_type()
@overload def __radd__(self, other: number_types) -> NumberVar:
def __radd__(self, other: number_types) -> NumberVar: ...
@overload
def __radd__(self, other: NoReturn) -> NoReturn: ...
def __radd__(self, other: Any):
"""Add two numbers. """Add two numbers.
Args: Args:
@ -91,13 +80,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
raise_unsupported_operand_types("+", (type(other), type(self))) raise_unsupported_operand_types("+", (type(other), type(self)))
return number_add_operation(+other, self).guess_type() return number_add_operation(+other, self).guess_type()
@overload def __sub__(self, other: number_types) -> NumberVar:
def __sub__(self, other: number_types) -> NumberVar: ...
@overload
def __sub__(self, other: NoReturn) -> NoReturn: ...
def __sub__(self, other: Any):
"""Subtract two numbers. """Subtract two numbers.
Args: Args:
@ -111,13 +94,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_subtract_operation(self, +other).guess_type() return number_subtract_operation(self, +other).guess_type()
@overload def __rsub__(self, other: number_types) -> NumberVar:
def __rsub__(self, other: number_types) -> NumberVar: ...
@overload
def __rsub__(self, other: NoReturn) -> NoReturn: ...
def __rsub__(self, other: Any):
"""Subtract two numbers. """Subtract two numbers.
Args: Args:
@ -193,13 +170,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_multiply_operation(+other, self).guess_type() return number_multiply_operation(+other, self).guess_type()
@overload def __truediv__(self, other: number_types) -> NumberVar:
def __truediv__(self, other: number_types) -> NumberVar: ...
@overload
def __truediv__(self, other: NoReturn) -> NoReturn: ...
def __truediv__(self, other: Any):
"""Divide two numbers. """Divide two numbers.
Args: Args:
@ -213,13 +184,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_true_division_operation(self, +other).guess_type() return number_true_division_operation(self, +other).guess_type()
@overload def __rtruediv__(self, other: number_types) -> NumberVar:
def __rtruediv__(self, other: number_types) -> NumberVar: ...
@overload
def __rtruediv__(self, other: NoReturn) -> NoReturn: ...
def __rtruediv__(self, other: Any):
"""Divide two numbers. """Divide two numbers.
Args: Args:
@ -233,13 +198,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_true_division_operation(+other, self).guess_type() return number_true_division_operation(+other, self).guess_type()
@overload def __floordiv__(self, other: number_types) -> NumberVar:
def __floordiv__(self, other: number_types) -> NumberVar: ...
@overload
def __floordiv__(self, other: NoReturn) -> NoReturn: ...
def __floordiv__(self, other: Any):
"""Floor divide two numbers. """Floor divide two numbers.
Args: Args:
@ -253,13 +212,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_floor_division_operation(self, +other).guess_type() return number_floor_division_operation(self, +other).guess_type()
@overload def __rfloordiv__(self, other: number_types) -> NumberVar:
def __rfloordiv__(self, other: number_types) -> NumberVar: ...
@overload
def __rfloordiv__(self, other: NoReturn) -> NoReturn: ...
def __rfloordiv__(self, other: Any):
"""Floor divide two numbers. """Floor divide two numbers.
Args: Args:
@ -273,13 +226,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_floor_division_operation(+other, self).guess_type() return number_floor_division_operation(+other, self).guess_type()
@overload def __mod__(self, other: number_types) -> NumberVar:
def __mod__(self, other: number_types) -> NumberVar: ...
@overload
def __mod__(self, other: NoReturn) -> NoReturn: ...
def __mod__(self, other: Any):
"""Modulo two numbers. """Modulo two numbers.
Args: Args:
@ -293,13 +240,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_modulo_operation(self, +other).guess_type() return number_modulo_operation(self, +other).guess_type()
@overload def __rmod__(self, other: number_types) -> NumberVar:
def __rmod__(self, other: number_types) -> NumberVar: ...
@overload
def __rmod__(self, other: NoReturn) -> NoReturn: ...
def __rmod__(self, other: Any):
"""Modulo two numbers. """Modulo two numbers.
Args: Args:
@ -313,13 +254,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_modulo_operation(+other, self).guess_type() return number_modulo_operation(+other, self).guess_type()
@overload def __pow__(self, other: number_types) -> NumberVar:
def __pow__(self, other: number_types) -> NumberVar: ...
@overload
def __pow__(self, other: NoReturn) -> NoReturn: ...
def __pow__(self, other: Any):
"""Exponentiate two numbers. """Exponentiate two numbers.
Args: Args:
@ -333,13 +268,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
return number_exponent_operation(self, +other).guess_type() return number_exponent_operation(self, +other).guess_type()
@overload def __rpow__(self, other: number_types) -> NumberVar:
def __rpow__(self, other: number_types) -> NumberVar: ...
@overload
def __rpow__(self, other: NoReturn) -> NoReturn: ...
def __rpow__(self, other: Any):
"""Exponentiate two numbers. """Exponentiate two numbers.
Args: Args:
@ -409,13 +338,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
""" """
return number_trunc_operation(self).guess_type() return number_trunc_operation(self).guess_type()
@overload def __lt__(self, other: number_types) -> BooleanVar:
def __lt__(self, other: number_types) -> BooleanVar: ...
@overload
def __lt__(self, other: NoReturn) -> NoReturn: ...
def __lt__(self, other: Any):
"""Less than comparison. """Less than comparison.
Args: Args:
@ -426,15 +349,9 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
""" """
if not isinstance(other, NUMBER_TYPES): if not isinstance(other, NUMBER_TYPES):
raise_unsupported_operand_types("<", (type(self), type(other))) raise_unsupported_operand_types("<", (type(self), type(other)))
return less_than_operation(self, +other) return less_than_operation(self, +other).guess_type()
@overload def __le__(self, other: number_types) -> BooleanVar:
def __le__(self, other: number_types) -> BooleanVar: ...
@overload
def __le__(self, other: NoReturn) -> NoReturn: ...
def __le__(self, other: Any):
"""Less than or equal comparison. """Less than or equal comparison.
Args: Args:
@ -445,9 +362,9 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
""" """
if not isinstance(other, NUMBER_TYPES): if not isinstance(other, NUMBER_TYPES):
raise_unsupported_operand_types("<=", (type(self), type(other))) raise_unsupported_operand_types("<=", (type(self), type(other)))
return less_than_or_equal_operation(self, +other) return less_than_or_equal_operation(self, +other).guess_type()
def __eq__(self, other: Any): def __eq__(self, other: Any) -> BooleanVar:
"""Equal comparison. """Equal comparison.
Args: Args:
@ -457,10 +374,10 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
The result of the comparison. The result of the comparison.
""" """
if isinstance(other, NUMBER_TYPES): if isinstance(other, NUMBER_TYPES):
return equal_operation(self, +other) return equal_operation(self, +other).guess_type()
return equal_operation(self, other) return equal_operation(self, other).guess_type()
def __ne__(self, other: Any): def __ne__(self, other: Any) -> BooleanVar:
"""Not equal comparison. """Not equal comparison.
Args: Args:
@ -470,16 +387,10 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
The result of the comparison. The result of the comparison.
""" """
if isinstance(other, NUMBER_TYPES): if isinstance(other, NUMBER_TYPES):
return not_equal_operation(self, +other) return not_equal_operation(self, +other).guess_type()
return not_equal_operation(self, other) return not_equal_operation(self, other).guess_type()
@overload def __gt__(self, other: number_types) -> BooleanVar:
def __gt__(self, other: number_types) -> BooleanVar: ...
@overload
def __gt__(self, other: NoReturn) -> NoReturn: ...
def __gt__(self, other: Any):
"""Greater than comparison. """Greater than comparison.
Args: Args:
@ -490,15 +401,9 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
""" """
if not isinstance(other, NUMBER_TYPES): if not isinstance(other, NUMBER_TYPES):
raise_unsupported_operand_types(">", (type(self), type(other))) raise_unsupported_operand_types(">", (type(self), type(other)))
return greater_than_operation(self, +other) return greater_than_operation(self, +other).guess_type()
@overload def __ge__(self, other: number_types) -> BooleanVar:
def __ge__(self, other: number_types) -> BooleanVar: ...
@overload
def __ge__(self, other: NoReturn) -> NoReturn: ...
def __ge__(self, other: Any):
"""Greater than or equal comparison. """Greater than or equal comparison.
Args: Args:
@ -509,9 +414,9 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
""" """
if not isinstance(other, NUMBER_TYPES): if not isinstance(other, NUMBER_TYPES):
raise_unsupported_operand_types(">=", (type(self), type(other))) raise_unsupported_operand_types(">=", (type(self), type(other)))
return greater_than_or_equal_operation(self, +other) return greater_than_or_equal_operation(self, +other).guess_type()
def bool(self): def bool(self) -> BooleanVar:
"""Boolean conversion. """Boolean conversion.
Returns: Returns:
@ -863,7 +768,7 @@ def boolean_to_number_operation(value: Var[bool]):
def comparison_operator( def comparison_operator(
func: Callable[[Var, Var], str], func: Callable[[Var, Var], str],
) -> Callable[[Var | Any, Var | Any], BooleanVar]: ) -> FunctionVar[ReflexCallable[[Any, Any], bool]]:
"""Decorator to create a comparison operation. """Decorator to create a comparison operation.
Args: Args:
@ -873,26 +778,15 @@ def comparison_operator(
The comparison operation. The comparison operation.
""" """
@var_operation
def operation(lhs: Var[Any], rhs: Var[Any]): def operation(lhs: Var[Any], rhs: Var[Any]):
return var_operation_return( return var_operation_return(
js_expression=func(lhs, rhs), js_expression=func(lhs, rhs),
var_type=bool, var_type=bool,
) )
def wrapper(lhs: Var | Any, rhs: Var | Any) -> BooleanVar: operation.__name__ = func.__name__
"""Create the comparison operation.
Args: return var_operation(operation)
lhs: The first value.
rhs: The second value.
Returns:
The comparison operation.
"""
return operation(lhs, rhs).guess_type()
return wrapper
@comparison_operator @comparison_operator
@ -1104,6 +998,14 @@ _IS_TRUE_IMPORT: ImportDict = {
f"$/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")], f"$/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")],
} }
_AT_SLICE_IMPORT: ImportDict = {
f"$/{Dirs.STATE_PATH}": [ImportVar(tag="atSlice")],
}
_RANGE_IMPORT: ImportDict = {
f"$/{Dirs.UTILS}/helpers/range": [ImportVar(tag="range", is_default=True)],
}
@var_operation @var_operation
def boolify(value: Var): def boolify(value: Var):
@ -1122,8 +1024,8 @@ def boolify(value: Var):
) )
T = TypeVar("T") T = TypeVar("T", bound=Any)
U = TypeVar("U") U = TypeVar("U", bound=Any)
@var_operation @var_operation

View File

@ -11,6 +11,7 @@ from typing import (
Dict, Dict,
List, List,
NoReturn, NoReturn,
Sequence,
Tuple, Tuple,
Type, Type,
TypeVar, TypeVar,
@ -71,9 +72,9 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
) -> Type[VALUE_TYPE]: ... ) -> Type[VALUE_TYPE]: ...
@overload @overload
def _value_type(self) -> Type: ... def _value_type(self) -> GenericType: ...
def _value_type(self) -> Type: def _value_type(self) -> GenericType:
"""Get the type of the values of the object. """Get the type of the values of the object.
Returns: Returns:
@ -85,7 +86,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
args = get_args(self._var_type) if issubclass(fixed_type, dict) else () args = get_args(self._var_type) if issubclass(fixed_type, dict) else ()
return args[1] if args else Any return args[1] if args else Any
def keys(self) -> ArrayVar[List[str]]: def keys(self) -> ArrayVar[Sequence[str]]:
"""Get the keys of the object. """Get the keys of the object.
Returns: Returns:
@ -96,7 +97,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
@overload @overload
def values( def values(
self: ObjectVar[Dict[Any, VALUE_TYPE]], self: ObjectVar[Dict[Any, VALUE_TYPE]],
) -> ArrayVar[List[VALUE_TYPE]]: ... ) -> ArrayVar[Sequence[VALUE_TYPE]]: ...
@overload @overload
def values(self) -> ArrayVar: ... def values(self) -> ArrayVar: ...
@ -112,7 +113,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
@overload @overload
def entries( def entries(
self: ObjectVar[Dict[Any, VALUE_TYPE]], self: ObjectVar[Dict[Any, VALUE_TYPE]],
) -> ArrayVar[List[Tuple[str, VALUE_TYPE]]]: ... ) -> ArrayVar[Sequence[Tuple[str, VALUE_TYPE]]]: ...
@overload @overload
def entries(self) -> ArrayVar: ... def entries(self) -> ArrayVar: ...
@ -163,9 +164,9 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
@overload @overload
def __getitem__( def __getitem__(
self: ObjectVar[Dict[Any, list[ARRAY_INNER_TYPE]]], self: ObjectVar[Dict[Any, Sequence[ARRAY_INNER_TYPE]]],
key: Var | Any, key: Var | Any,
) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ... ) -> ArrayVar[Sequence[ARRAY_INNER_TYPE]]: ...
@overload @overload
def __getitem__( def __getitem__(
@ -173,12 +174,6 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
key: Var | Any, key: Var | Any,
) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ... ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
@overload
def __getitem__(
self: ObjectVar[Dict[Any, tuple[ARRAY_INNER_TYPE, ...]]],
key: Var | Any,
) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
@overload @overload
def __getitem__( def __getitem__(
self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]], self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
@ -202,7 +197,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
# NoReturn is used here to catch when key value is Any # NoReturn is used here to catch when key value is Any
@overload @overload
def __getattr__( def __getattr__( # pyright: ignore [reportOverlappingOverload]
self: ObjectVar[Dict[Any, NoReturn]], self: ObjectVar[Dict[Any, NoReturn]],
name: str, name: str,
) -> Var: ... ) -> Var: ...
@ -225,9 +220,9 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
@overload @overload
def __getattr__( def __getattr__(
self: ObjectVar[Dict[Any, list[ARRAY_INNER_TYPE]]], self: ObjectVar[Dict[Any, Sequence[ARRAY_INNER_TYPE]]],
name: str, name: str,
) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ... ) -> ArrayVar[Sequence[ARRAY_INNER_TYPE]]: ...
@overload @overload
def __getattr__( def __getattr__(
@ -235,12 +230,6 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
name: str, name: str,
) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ... ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
@overload
def __getattr__(
self: ObjectVar[Dict[Any, tuple[ARRAY_INNER_TYPE, ...]]],
name: str,
) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
@overload @overload
def __getattr__( def __getattr__(
self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]], self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
@ -311,7 +300,7 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
default_factory=dict default_factory=dict
) )
def _key_type(self) -> Type: def _key_type(self) -> GenericType:
"""Get the type of the keys of the object. """Get the type of the keys of the object.
Returns: Returns:
@ -320,7 +309,7 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
args_list = typing.get_args(self._var_type) args_list = typing.get_args(self._var_type)
return args_list[0] if args_list else Any return args_list[0] if args_list else Any
def _value_type(self) -> Type: def _value_type(self) -> GenericType:
"""Get the type of the values of the object. """Get the type of the values of the object.
Returns: Returns:

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
from typing import Dict, List, Set, Tuple, Union from typing import Dict, List, Sequence, Set, Tuple, Union
import pytest import pytest
@ -115,8 +115,10 @@ def display_colors_set(color):
return box(text(color)) return box(text(color))
def display_nested_list_element(element: ArrayVar[List[str]], index: NumberVar[int]): def display_nested_list_element(
assert element._var_type == List[str] element: ArrayVar[Sequence[str]], index: NumberVar[int]
):
assert element._var_type == Sequence[str]
assert index._var_type is int assert index._var_type is int
return box(text(element[index])) return box(text(element[index]))