Browse Source

what am i doing anymore

Khaleel Al-Adhami 6 months ago
parent
commit
5f0546f32e

+ 172 - 187
poetry.lock

@@ -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.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"},
-    {file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"},
-    {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.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.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"},
-    {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"},
-    {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"},
-    {file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"},
-    {file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"},
-    {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"},
-    {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"},
-    {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"},
-    {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.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.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"},
-    {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"},
-    {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"},
-    {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"},
-    {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"},
-    {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"},
-    {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"},
-    {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"},
-    {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.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.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"},
-    {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"},
-    {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"},
-    {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"},
-    {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"},
-    {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"},
-    {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"},
-    {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"},
-    {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.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.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"},
-    {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"},
-    {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"},
-    {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"},
-    {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"},
-    {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"},
-    {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"},
-    {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"},
-    {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.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.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"},
-    {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"},
-    {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"},
-    {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"},
-    {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"},
-    {file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"},
-    {file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"},
-    {file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"},
-    {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.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.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"},
-    {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"},
-    {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"},
-    {file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"},
-    {file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"},
-    {file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"},
-    {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"},
+    {file = "coverage-7.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d5fc459f1b62aa328b5c6943b4fa060fa63e7749e41c974929c503dc01d0527b"},
+    {file = "coverage-7.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:197fc6b5e6271c4f822486cabbd91f32e73f784076b69c91179c5a9fec2d1442"},
+    {file = "coverage-7.6.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a7cab0762dfbf0b0cd6eb22f7bceade31bda0f0647f9420cbb45571de4493a3"},
+    {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.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.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fe4ea637711f1f1895895578972e3d0ed5efb6ef970ba0e2e26d9fad1e3c820e"},
+    {file = "coverage-7.6.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1d5f036235a747cd30be433ef7ba6dab5ac41d8dc69d54094d5438c34fe8d565"},
+    {file = "coverage-7.6.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a6ab7b88b1a614bc1db015e68048eb29b0c30ffa01be3d7d04da1f320db0f01"},
+    {file = "coverage-7.6.5-cp310-cp310-win32.whl", hash = "sha256:ad712a72cd734fb4265041005011bbf61f8d6cba74e12c91f14a9cda63a80a64"},
+    {file = "coverage-7.6.5-cp310-cp310-win_amd64.whl", hash = "sha256:61e03bb66c087b74aea6c28d10a49f72eca98b95438a8db1ae6dfcdd060f9039"},
+    {file = "coverage-7.6.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dffec9f67f4eb8bc9c5df720833f1f1ca36b73d86e6f95b422ca5210e264cc26"},
+    {file = "coverage-7.6.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2fde790ac0024af19fc5327fd50890dad0c31b653f6d2ed91ab2810c046bfe22"},
+    {file = "coverage-7.6.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3250186381ec8e9b71234fb92ef77da87d81cbf20df3364f8f5ebf7180ec030d"},
+    {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.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.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:caf4d6af23af0e0df4e40e9985f6063d7f5434f225ee4d4ed7001f1428302403"},
+    {file = "coverage-7.6.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5dcf2da597fe616a41c59e29fd8d390ac2149aeed421172eef14470c7e9dcd06"},
+    {file = "coverage-7.6.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebc76107d896a53116e5ef21998f321b630b574a65b78b01176ca64e8978b43e"},
+    {file = "coverage-7.6.5-cp311-cp311-win32.whl", hash = "sha256:0e9e4cd48dca252d99bb97b14f13b5940813937cc7ec568418c1a195dec9cbcc"},
+    {file = "coverage-7.6.5-cp311-cp311-win_amd64.whl", hash = "sha256:a6eb14739a20c5a46073c8ad066ada17d91d14599ed98d724614db46fbae867b"},
+    {file = "coverage-7.6.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9ae01c434cb0d445008257bb42dcd38112190e5bfc3a4480fde49572b16bc2ae"},
+    {file = "coverage-7.6.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c72ef3be899f389c9f0934a9d06a28fa097ade096760102c732583c04cc31d75"},
+    {file = "coverage-7.6.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2fc574b4fb082a0141d4df00079c4877d46cb98e8ec979cbd9a92426f5abd8a"},
+    {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.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.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b22f96d3f2425942a649d786f57ae431425c9a970afae784cd865c1ffee34bad"},
+    {file = "coverage-7.6.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:70eca9c6bf742feaf3ee453c1aaa932c2ab88ca420f411d90aa43ae831127b22"},
+    {file = "coverage-7.6.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c4bafec5da3498d498a4ca3136f5a01fded487c6a54f18aea0bcd673feedf1b"},
+    {file = "coverage-7.6.5-cp312-cp312-win32.whl", hash = "sha256:edecf498cabb335e8a683eb672558355bb9536d4397c54f1e135d9b8910512a3"},
+    {file = "coverage-7.6.5-cp312-cp312-win_amd64.whl", hash = "sha256:e7c40ae56761d3c08f916019b2f8579a147f93be8e12f0f2bf4edc4ea9e1c0ab"},
+    {file = "coverage-7.6.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:49ea4a739dc14856d7c5f935da90db123b77a850cfddcfacb490a28de8f87257"},
+    {file = "coverage-7.6.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0c51339a28aa43d0f2b1211e57ceeeeed5e09f4deb6fc543d939de68069e81e"},
+    {file = "coverage-7.6.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:040c3d5cf4db24e7cb890bf4b547a25bd3a3516c58c9f2a22f822199ee2ad8ed"},
+    {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.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.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:559cdb21aca30810e648ac08270535c1d2e17226ebbdf90860a060d3680cb05f"},
+    {file = "coverage-7.6.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:23e2dd956277061f24d9eda7539113a9c35a9409a9935647a34ced79b8aacb75"},
+    {file = "coverage-7.6.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3e7c4ccb41dc9830b2ca8592e401045a81740f627c7c0348bdc3b7373ce52f8e"},
+    {file = "coverage-7.6.5-cp313-cp313-win32.whl", hash = "sha256:9d3565bb7deaa12d634426f113e6b106028c535667ba7756af65f00464981ba5"},
+    {file = "coverage-7.6.5-cp313-cp313-win_amd64.whl", hash = "sha256:5039410420d9ddcd5b8566d3afbb28b89d70c4481dbb283ea543263cbefa2b67"},
+    {file = "coverage-7.6.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:77b640aa78d4d9f620fb2e1b2a41b0d196120c188d0a7f678761d668d6251fcc"},
+    {file = "coverage-7.6.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bb3799f6279df37e369027128926de4c159e6399000316ebd7a69e55b84dc97f"},
+    {file = "coverage-7.6.5-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55aba7ab64e8af37a18064f23f399dff10041fa3aaf201528f12004968638b9f"},
+    {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.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.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1dc99aece5f899955eece053a798e279f7fe7059dd5e2a95af82878cfe4a44e1"},
+    {file = "coverage-7.6.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1b14515f83ffa7a6787e725d804c6b11dd317a6bd0373d8519a61e4a587fe534"},
+    {file = "coverage-7.6.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9fa6d90130165346935541f3762933dae07e237ff7d6d780fae556039f08a470"},
+    {file = "coverage-7.6.5-cp313-cp313t-win32.whl", hash = "sha256:1be9ec4c49becb35955b9d69c27e6385aedd40d233f1cf065e8430c59924b30e"},
+    {file = "coverage-7.6.5-cp313-cp313t-win_amd64.whl", hash = "sha256:7ff4fd7679df56e36fc838ef227e95e3aa1b0ca0548daede7f8ae6e54479c115"},
+    {file = "coverage-7.6.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:23abf0846290aa57d629c4f4181d0d56cbaa45d3999e60cb0df1d2bab7bc6bfe"},
+    {file = "coverage-7.6.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4903685e8059e170182ac4681ee72d2dfbb92692225023c1e325a9d85c1be31"},
+    {file = "coverage-7.6.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ad9621fd9773b1461f8942da4130fbb16ee0a877eb58bc57532ea41cce20d3e"},
+    {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.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.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4601dacd88556c94c9fb5063b9354b1fe971af9a5b25b2575faefd12bf8170a5"},
+    {file = "coverage-7.6.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e5aa3d62285ef1b16f655e1ae298c6fa919209637d317934e382e9b99c28c118"},
+    {file = "coverage-7.6.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8cb5601620c3d98d2c98847272acc2406333d43c9d7d49386d879bd451677429"},
+    {file = "coverage-7.6.5-cp39-cp39-win32.whl", hash = "sha256:c32428f6285344caedd945236f31c46645bb10faae8702d1409bb49df218e55a"},
+    {file = "coverage-7.6.5-cp39-cp39-win_amd64.whl", hash = "sha256:809e868eee27d056bc72590c69940c119775d218681b1a8ef9ba0ef8d7693e53"},
+    {file = "coverage-7.6.5-pp39.pp310-none-any.whl", hash = "sha256:49145276f39f940b18a539e1e4a378e06c64a127922450ffd2fb82b9fe1ad3d9"},
+    {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.4.tar.gz", hash = "sha256:db653475586b091cb8b2fec2ac54a680ac6a158e07406e1abae31679e8826349"},
+    {file = "fastapi-0.115.5-py3-none-any.whl", hash = "sha256:596b95adbe1474da47049e802f9a65ab2ffa9c2b07e7efee70eb8a66c9f2f796"},
+    {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.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"},
+    {file = "identify-2.6.2-py2.py3-none-any.whl", hash = "sha256:c097384259f49e372f4ea00a19719d95ae27dd5ff0fd77ad630aa891306b82f3"},
+    {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.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
+    {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
+    {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.334.tar.gz", hash = "sha256:3adaf10f1f4209575dc022f9c897f7ef024639b7ea5b3cbe49302147e6949cd4"},
+    {file = "pyright-1.1.389-py3-none-any.whl", hash = "sha256:41e9620bba9254406dc1f621a88ceab5a88af4c826feb4f614d95691ed243a60"},
+    {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.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"},
+    {file = "setuptools-75.5.0-py3-none-any.whl", hash = "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"},
+    {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)"]
-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)"]
+check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.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)"]
-type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.12.*)", "pytest-mypy"]
+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,<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.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
+    {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"},
+    {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-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"},
-    {file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"},
-    {file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"},
-    {file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"},
-    {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-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"},
-    {file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"},
-    {file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"},
-    {file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"},
-    {file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"},
-    {file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"},
-    {file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"},
-    {file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"},
-    {file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"},
-    {file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"},
-    {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-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"},
-    {file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"},
-    {file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"},
-    {file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"},
-    {file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"},
-    {file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"},
-    {file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"},
-    {file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"},
-    {file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"},
-    {file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"},
-    {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-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"},
-    {file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"},
-    {file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"},
-    {file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"},
-    {file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"},
-    {file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"},
-    {file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"},
-    {file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"},
-    {file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"},
-    {file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"},
-    {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-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"},
-    {file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"},
-    {file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"},
-    {file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"},
-    {file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"},
-    {file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"},
-    {file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"},
-    {file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"},
-    {file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"},
-    {file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"},
-    {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-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"},
-    {file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"},
-    {file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"},
-    {file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"},
-    {file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"},
-    {file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"},
-    {file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"},
-    {file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"},
-    {file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"},
-    {file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"},
-    {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-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"},
-    {file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"},
-    {file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"},
-    {file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"},
-    {file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"},
-    {file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"},
-    {file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"},
-    {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"},
-    {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"},
+    {file = "websockets-14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a0adf84bc2e7c86e8a202537b4fd50e6f7f0e4a6b6bf64d7ccb96c4cd3330b29"},
+    {file = "websockets-14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90b5d9dfbb6d07a84ed3e696012610b6da074d97453bd01e0e30744b472c8179"},
+    {file = "websockets-14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2177ee3901075167f01c5e335a6685e71b162a54a89a56001f1c3e9e3d2ad250"},
+    {file = "websockets-14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f14a96a0034a27f9d47fd9788913924c89612225878f8078bb9d55f859272b0"},
+    {file = "websockets-14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f874ba705deea77bcf64a9da42c1f5fc2466d8f14daf410bc7d4ceae0a9fcb0"},
+    {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-14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bea45f19b7ca000380fbd4e02552be86343080120d074b87f25593ce1700ad58"},
+    {file = "websockets-14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:219c8187b3ceeadbf2afcf0f25a4918d02da7b944d703b97d12fb01510869078"},
+    {file = "websockets-14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ad2ab2547761d79926effe63de21479dfaf29834c50f98c4bf5b5480b5838434"},
+    {file = "websockets-14.1-cp310-cp310-win32.whl", hash = "sha256:1288369a6a84e81b90da5dbed48610cd7e5d60af62df9851ed1d1d23a9069f10"},
+    {file = "websockets-14.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0744623852f1497d825a49a99bfbec9bea4f3f946df6eb9d8a2f0c37a2fec2e"},
+    {file = "websockets-14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:449d77d636f8d9c17952628cc7e3b8faf6e92a17ec581ec0c0256300717e1512"},
+    {file = "websockets-14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a35f704be14768cea9790d921c2c1cc4fc52700410b1c10948511039be824aac"},
+    {file = "websockets-14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b1f3628a0510bd58968c0f60447e7a692933589b791a6b572fcef374053ca280"},
+    {file = "websockets-14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c3deac3748ec73ef24fc7be0b68220d14d47d6647d2f85b2771cb35ea847aa1"},
+    {file = "websockets-14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7048eb4415d46368ef29d32133134c513f507fff7d953c18c91104738a68c3b3"},
+    {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-14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc1fc87428c1d18b643479caa7b15db7d544652e5bf610513d4a3478dbe823d0"},
+    {file = "websockets-14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f95ba34d71e2fa0c5d225bde3b3bdb152e957150100e75c86bc7f3964c450d89"},
+    {file = "websockets-14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9481a6de29105d73cf4515f2bef8eb71e17ac184c19d0b9918a3701c6c9c4f23"},
+    {file = "websockets-14.1-cp311-cp311-win32.whl", hash = "sha256:368a05465f49c5949e27afd6fbe0a77ce53082185bbb2ac096a3a8afaf4de52e"},
+    {file = "websockets-14.1-cp311-cp311-win_amd64.whl", hash = "sha256:6d24fc337fc055c9e83414c94e1ee0dee902a486d19d2a7f0929e49d7d604b09"},
+    {file = "websockets-14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed"},
+    {file = "websockets-14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d"},
+    {file = "websockets-14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707"},
+    {file = "websockets-14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a"},
+    {file = "websockets-14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45"},
+    {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-14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058"},
+    {file = "websockets-14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4"},
+    {file = "websockets-14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05"},
+    {file = "websockets-14.1-cp312-cp312-win32.whl", hash = "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0"},
+    {file = "websockets-14.1-cp312-cp312-win_amd64.whl", hash = "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f"},
+    {file = "websockets-14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9"},
+    {file = "websockets-14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b"},
+    {file = "websockets-14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3"},
+    {file = "websockets-14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59"},
+    {file = "websockets-14.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2"},
+    {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-14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9"},
+    {file = "websockets-14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7"},
+    {file = "websockets-14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a"},
+    {file = "websockets-14.1-cp313-cp313-win32.whl", hash = "sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6"},
+    {file = "websockets-14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0"},
+    {file = "websockets-14.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:01bb2d4f0a6d04538d3c5dfd27c0643269656c28045a53439cbf1c004f90897a"},
+    {file = "websockets-14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:414ffe86f4d6f434a8c3b7913655a1a5383b617f9bf38720e7c0799fac3ab1c6"},
+    {file = "websockets-14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fda642151d5affdee8a430bd85496f2e2517be3a2b9d2484d633d5712b15c56"},
+    {file = "websockets-14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd7c11968bc3860d5c78577f0dbc535257ccec41750675d58d8dc66aa47fe52c"},
+    {file = "websockets-14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a032855dc7db987dff813583d04f4950d14326665d7e714d584560b140ae6b8b"},
+    {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-14.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:39450e6215f7d9f6f7bc2a6da21d79374729f5d052333da4d5825af8a97e6735"},
+    {file = "websockets-14.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ceada5be22fa5a5a4cdeec74e761c2ee7db287208f54c718f2df4b7e200b8d4a"},
+    {file = "websockets-14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3fc753451d471cff90b8f467a1fc0ae64031cf2d81b7b34e1811b7e2691bc4bc"},
+    {file = "websockets-14.1-cp39-cp39-win32.whl", hash = "sha256:14839f54786987ccd9d03ed7f334baec0f02272e7ec4f6e9d427ff584aeea8b4"},
+    {file = "websockets-14.1-cp39-cp39-win_amd64.whl", hash = "sha256:d9fd19ecc3a4d5ae82ddbfb30962cf6d874ff943e56e0c81f5169be2fda62979"},
+    {file = "websockets-14.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e5dc25a9dbd1a7f61eca4b7cb04e74ae4b963d658f9e4f9aad9cd00b688692c8"},
+    {file = "websockets-14.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:04a97aca96ca2acedf0d1f332c861c5a4486fdcba7bcef35873820f940c4231e"},
+    {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df174ece723b228d3e8734a6f2a6febbd413ddec39b3dc592f5a4aa0aff28098"},
+    {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-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-14.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a42d3ecbb2db5080fc578314439b1d79eef71d323dc661aa616fb492436af5d"},
+    {file = "websockets-14.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddaa4a390af911da6f680be8be4ff5aaf31c4c834c1a9147bc21cbcbca2d4370"},
+    {file = "websockets-14.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4c805c6034206143fbabd2d259ec5e757f8b29d0a2f0bf3d2fe5d1f60147a4a"},
+    {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:205f672a6c2c671a86d33f6d47c9b35781a998728d2c7c2a3e1cf3333fcb62b7"},
+    {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-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-14.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:25225cc79cfebc95ba1d24cd3ab86aaa35bcd315d12fa4358939bd55e9bd74a5"},
+    {file = "websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e"},
+    {file = "websockets-14.1.tar.gz", hash = "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8"},
 ]
 ]
 
 
 [[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.44.0.tar.gz", hash = "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49"},
+    {file = "wheel-0.45.0-py3-none-any.whl", hash = "sha256:52f0baa5e6522155090a09c6bd95718cc46956d1b51d537ea5454249edb671c7"},
+    {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.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"},
+    {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"},
+    {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"

+ 2 - 1
pyproject.toml

@@ -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"

+ 27 - 0
reflex/.templates/web/utils/state.js

@@ -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.

+ 3 - 19
reflex/components/core/cond.py

@@ -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):
-            raise ValueError("Both arguments must be components.")
-        return Cond.create(cond_var, c1, c2)
+        c2 = c2 if c2 is not None else Fragment.create()
 
 
-    # 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
-            merge_var_data=VarData(imports=_IS_TRUE_IMPORT),
-        ),  # type: ignore
+        cond_var.bool(),
         c1,
         c1,
         c2,
         c2,
     )
     )

+ 219 - 58
reflex/vars/base.py

@@ -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
+    def to(self, output: Type[int]) -> NumberVar[int]: ...
 
 
     @overload
     @overload
-    def to(self, output: Type[bool]) -> BooleanVar: ...
+    def to(self, output: type[float]) -> NumberVar[float]: ...
 
 
     @overload
     @overload
-    def to(self, output: type[int] | type[float]) -> NumberVar: ...
+    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],
-    ) -> ArrayVar: ...
+        output: type[Sequence[VALUE]] | type[set[VALUE]],
+    ) -> 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
+    def guess_type(self: Var[str]) -> StringVar: ...  # pyright: ignore [reportOverlappingOverload]
 
 
     @overload
     @overload
-    def guess_type(self: Var[list] | Var[tuple] | Var[set]) -> ArrayVar: ...
+    def guess_type(self: Var[Sequence[VALUE]]) -> ArrayVar[Sequence[VALUE]]: ...
 
 
     @overload
     @overload
-    def guess_type(self: Var[dict]) -> ObjectVar[dict]: ...
+    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,
-        second_endpoint: int | NumberVar | None = None,
-        step: int | NumberVar | None = None,
-    ) -> ArrayVar[List[int]]:
+        first_endpoint: int | Var[int],
+        second_endpoint: int | Var[int] | None = None,
+        step: int | Var[int] | None = None,
+        /,
+    ) -> 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]],
-) -> ArgsFunctionOperation[ReflexCallable[[], T]]: ...
+    func: Callable[[Var[V1], Var[V2], Var[V3]], CustomVarOperationReturn[T]],
+) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3], T]]: ...
 
 
 
 
 @overload
 @overload
 def var_operation(
 def var_operation(
-    func: Callable[[Var[V1]], CustomVarOperationReturn[T]],
-) -> ArgsFunctionOperation[ReflexCallable[[V1], T]]: ...
+    func: Callable[[Var[V1], Var[V2], VarWithDefault[V3]], CustomVarOperationReturn[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]],
-) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3], T]]: ...
+    func: Callable[
+        [
+            Var[V1],
+            VarWithDefault[V2],
+        ],
+        CustomVarOperationReturn[T],
+    ],
+) -> ArgsFunctionOperation[
+    ReflexCallable[
+        [
+            V1,
+            VarWithDefault[V2],
+        ],
+        T,
+    ]
+]: ...
+
+
+@overload
+def var_operation(
+    func: Callable[
+        [
+            VarWithDefault[V1],
+            VarWithDefault[V2],
+        ],
+        CustomVarOperationReturn[T],
+    ],
+) -> ArgsFunctionOperation[
+    ReflexCallable[
+        [
+            VarWithDefault[V1],
+            VarWithDefault[V2],
+        ],
+        T,
+    ]
+]: ...
 
 
 
 
 @overload
 @overload
 def var_operation(
 def var_operation(
-    func: Callable[[Var[V1], Var[V2], Var[V3], Var[V4]], CustomVarOperationReturn[T]],
-) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3, V4], T]]: ...
+    func: Callable[[Var[V1]], CustomVarOperationReturn[T]],
+) -> ArgsFunctionOperation[ReflexCallable[[V1], 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]],
         CustomVarOperationReturn[T],
         CustomVarOperationReturn[T],
     ],
     ],
-) -> ArgsFunctionOperation[ReflexCallable[[V1, V2, V3, V4, V5], 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):
-                    var_datas.extend(_extract_var_data(sub.values()))
+                if (
+                    (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)
-        if callable(values):
-            var_datas.extend(_extract_var_data(values()))
+        values_fn = getattr(value, "values", None)
+        if callable(values_fn) and isinstance((values := values_fn()), Iterable):
+            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 (

+ 217 - 28
reflex/vars/function.py

@@ -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(
-        self: FunctionVar[ReflexCallable[P, R]], *args: Var | Any
-    ) -> VarOperationCall[P, R]: ...
+    def call(self: FunctionVar[NoReturn], *args: Var | Any) -> VarOperationCall: ...
 
 
-    @overload
-    def call(self, *args: Var | Any) -> Var: ...
-
-    def call(self, *args: Var | Any) -> Var:  # type: ignore
+    def call(self, *args: Var | Any) -> VarOperationCall:  # 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:
-            raise VarTypeError(f"Invalid number of arguments provided to {str(self)}")
+        if arg_len is not None:
+            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()
-            for arg in self._args.args
+            (arg if isinstance(arg, str) else arg.to_javascript())
+            + (
+                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,

+ 41 - 139
reflex/vars/number.py

@@ -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: ...
-
-    @overload
-    def __add__(self, other: NoReturn) -> NoReturn: ...
-
-    def __add__(self, other: Any):
+    def __add__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __radd__(self, other: NoReturn) -> NoReturn: ...
-
-    def __radd__(self, other: Any):
+    def __radd__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __sub__(self, other: NoReturn) -> NoReturn: ...
-
-    def __sub__(self, other: Any):
+    def __sub__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __rsub__(self, other: NoReturn) -> NoReturn: ...
-
-    def __rsub__(self, other: Any):
+    def __rsub__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __truediv__(self, other: NoReturn) -> NoReturn: ...
-
-    def __truediv__(self, other: Any):
+    def __truediv__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __rtruediv__(self, other: NoReturn) -> NoReturn: ...
-
-    def __rtruediv__(self, other: Any):
+    def __rtruediv__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __floordiv__(self, other: NoReturn) -> NoReturn: ...
-
-    def __floordiv__(self, other: Any):
+    def __floordiv__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __rfloordiv__(self, other: NoReturn) -> NoReturn: ...
-
-    def __rfloordiv__(self, other: Any):
+    def __rfloordiv__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __mod__(self, other: NoReturn) -> NoReturn: ...
-
-    def __mod__(self, other: Any):
+    def __mod__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __rmod__(self, other: NoReturn) -> NoReturn: ...
-
-    def __rmod__(self, other: Any):
+    def __rmod__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __pow__(self, other: NoReturn) -> NoReturn: ...
-
-    def __pow__(self, other: Any):
+    def __pow__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __rpow__(self, other: NoReturn) -> NoReturn: ...
-
-    def __rpow__(self, other: Any):
+    def __rpow__(self, other: number_types) -> NumberVar:
         """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: ...
-
-    @overload
-    def __lt__(self, other: NoReturn) -> NoReturn: ...
-
-    def __lt__(self, other: Any):
+    def __lt__(self, other: number_types) -> BooleanVar:
         """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)
-
-    @overload
-    def __le__(self, other: number_types) -> BooleanVar: ...
+        return less_than_operation(self, +other).guess_type()
 
 
-    @overload
-    def __le__(self, other: NoReturn) -> NoReturn: ...
-
-    def __le__(self, other: Any):
+    def __le__(self, other: number_types) -> BooleanVar:
         """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)
+            return equal_operation(self, +other).guess_type()
+        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)
-
-    @overload
-    def __gt__(self, other: number_types) -> BooleanVar: ...
+            return not_equal_operation(self, +other).guess_type()
+        return not_equal_operation(self, other).guess_type()
 
 
-    @overload
-    def __gt__(self, other: NoReturn) -> NoReturn: ...
-
-    def __gt__(self, other: Any):
+    def __gt__(self, other: number_types) -> BooleanVar:
         """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)
-
-    @overload
-    def __ge__(self, other: number_types) -> BooleanVar: ...
+        return greater_than_operation(self, +other).guess_type()
 
 
-    @overload
-    def __ge__(self, other: NoReturn) -> NoReturn: ...
-
-    def __ge__(self, other: Any):
+    def __ge__(self, other: number_types) -> BooleanVar:
         """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:
-        """Create the comparison operation.
-
-        Args:
-            lhs: The first value.
-            rhs: The second value.
-
-        Returns:
-            The comparison operation.
-        """
-        return operation(lhs, rhs).guess_type()
+    operation.__name__ = func.__name__
 
 
-    return wrapper
+    return var_operation(operation)
 
 
 
 
 @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")
-U = TypeVar("U")
+T = TypeVar("T", bound=Any)
+U = TypeVar("U", bound=Any)
 
 
 
 
 @var_operation
 @var_operation

+ 13 - 24
reflex/vars/object.py

@@ -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
+ 482 - 791
reflex/vars/sequence.py


+ 5 - 3
tests/units/components/core/test_foreach.py

@@ -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]):
-    assert element._var_type == List[str]
+def display_nested_list_element(
+    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]))
 
 

Some files were not shown because too many files changed in this diff