diff --git a/poetry.lock b/poetry.lock index e8ffb4a7..c10bedc1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4932,6 +4932,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -4939,8 +4940,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -4957,6 +4965,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -4964,6 +4973,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -5552,64 +5562,65 @@ files = [ [[package]] name = "sqlalchemy" -version = "2.0.28" +version = "2.0.29" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0b148ab0438f72ad21cb004ce3bdaafd28465c4276af66df3b9ecd2037bf252"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbda76961eb8f27e6ad3c84d1dc56d5bc61ba8f02bd20fcf3450bd421c2fcc9c"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feea693c452d85ea0015ebe3bb9cd15b6f49acc1a31c28b3c50f4db0f8fb1e71"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5da98815f82dce0cb31fd1e873a0cb30934971d15b74e0d78cf21f9e1b05953f"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5adf383c73f2d49ad15ff363a8748319ff84c371eed59ffd0127355d6ea1da"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56856b871146bfead25fbcaed098269d90b744eea5cb32a952df00d542cdd368"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-win32.whl", hash = "sha256:943aa74a11f5806ab68278284a4ddd282d3fb348a0e96db9b42cb81bf731acdc"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-win_amd64.whl", hash = "sha256:c6c4da4843e0dabde41b8f2e8147438330924114f541949e6318358a56d1875a"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46a3d4e7a472bfff2d28db838669fc437964e8af8df8ee1e4548e92710929adc"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3dd67b5d69794cfe82862c002512683b3db038b99002171f624712fa71aeaa"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61e2e41656a673b777e2f0cbbe545323dbe0d32312f590b1bc09da1de6c2a02"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0315d9125a38026227f559488fe7f7cee1bd2fbc19f9fd637739dc50bb6380b2"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af8ce2d31679006e7b747d30a89cd3ac1ec304c3d4c20973f0f4ad58e2d1c4c9"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:81ba314a08c7ab701e621b7ad079c0c933c58cdef88593c59b90b996e8b58fa5"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-win32.whl", hash = "sha256:1ee8bd6d68578e517943f5ebff3afbd93fc65f7ef8f23becab9fa8fb315afb1d"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-win_amd64.whl", hash = "sha256:ad7acbe95bac70e4e687a4dc9ae3f7a2f467aa6597049eeb6d4a662ecd990bb6"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d3499008ddec83127ab286c6f6ec82a34f39c9817f020f75eca96155f9765097"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b66fcd38659cab5d29e8de5409cdf91e9986817703e1078b2fdaad731ea66f5"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea30da1e76cb1acc5b72e204a920a3a7678d9d52f688f087dc08e54e2754c67"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:124202b4e0edea7f08a4db8c81cc7859012f90a0d14ba2bf07c099aff6e96462"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e23b88c69497a6322b5796c0781400692eca1ae5532821b39ce81a48c395aae9"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b6303bfd78fb3221847723104d152e5972c22367ff66edf09120fcde5ddc2e2"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-win32.whl", hash = "sha256:a921002be69ac3ab2cf0c3017c4e6a3377f800f1fca7f254c13b5f1a2f10022c"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-win_amd64.whl", hash = "sha256:b4a2cf92995635b64876dc141af0ef089c6eea7e05898d8d8865e71a326c0385"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e91b5e341f8c7f1e5020db8e5602f3ed045a29f8e27f7f565e0bdee3338f2c7"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45c7b78dfc7278329f27be02c44abc0d69fe235495bb8e16ec7ef1b1a17952db"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eba73ef2c30695cb7eabcdb33bb3d0b878595737479e152468f3ba97a9c22a4"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5df5d1dafb8eee89384fb7a1f79128118bc0ba50ce0db27a40750f6f91aa99d5"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2858bbab1681ee5406650202950dc8f00e83b06a198741b7c656e63818633526"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-win32.whl", hash = "sha256:9461802f2e965de5cff80c5a13bc945abea7edaa1d29360b485c3d2b56cdb075"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-win_amd64.whl", hash = "sha256:a6bec1c010a6d65b3ed88c863d56b9ea5eeefdf62b5e39cafd08c65f5ce5198b"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:843a882cadebecc655a68bd9a5b8aa39b3c52f4a9a5572a3036fb1bb2ccdc197"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dbb990612c36163c6072723523d2be7c3eb1517bbdd63fe50449f56afafd1133"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7e4baf9161d076b9a7e432fce06217b9bd90cfb8f1d543d6e8c4595627edb9"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0a5354cb4de9b64bccb6ea33162cb83e03dbefa0d892db88a672f5aad638a75"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fffcc8edc508801ed2e6a4e7b0d150a62196fd28b4e16ab9f65192e8186102b6"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aca7b6d99a4541b2ebab4494f6c8c2f947e0df4ac859ced575238e1d6ca5716b"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-win32.whl", hash = "sha256:8c7f10720fc34d14abad5b647bc8202202f4948498927d9f1b4df0fb1cf391b7"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-win_amd64.whl", hash = "sha256:243feb6882b06a2af68ecf4bec8813d99452a1b62ba2be917ce6283852cf701b"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc4974d3684f28b61b9a90fcb4c41fb340fd4b6a50c04365704a4da5a9603b05"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87724e7ed2a936fdda2c05dbd99d395c91ea3c96f029a033a4a20e008dd876bf"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68722e6a550f5de2e3cfe9da6afb9a7dd15ef7032afa5651b0f0c6b3adb8815d"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328529f7c7f90adcd65aed06a161851f83f475c2f664a898af574893f55d9e53"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:df40c16a7e8be7413b885c9bf900d402918cc848be08a59b022478804ea076b8"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:426f2fa71331a64f5132369ede5171c52fd1df1bd9727ce621f38b5b24f48750"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-win32.whl", hash = "sha256:33157920b233bc542ce497a81a2e1452e685a11834c5763933b440fedd1d8e2d"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-win_amd64.whl", hash = "sha256:2f60843068e432311c886c5f03c4664acaef507cf716f6c60d5fde7265be9d7b"}, - {file = "SQLAlchemy-2.0.28-py3-none-any.whl", hash = "sha256:78bb7e8da0183a8301352d569900d9d3594c48ac21dc1c2ec6b3121ed8b6c986"}, - {file = "SQLAlchemy-2.0.28.tar.gz", hash = "sha256:dd53b6c4e6d960600fd6532b79ee28e2da489322fcf6648738134587faf767b6"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c142852ae192e9fe5aad5c350ea6befe9db14370b34047e1f0f7cf99e63c63b"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99a1e69d4e26f71e750e9ad6fdc8614fbddb67cfe2173a3628a2566034e223c7"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef3fbccb4058355053c51b82fd3501a6e13dd808c8d8cd2561e610c5456013c"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d6753305936eddc8ed190e006b7bb33a8f50b9854823485eed3a886857ab8d1"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0f3ca96af060a5250a8ad5a63699180bc780c2edf8abf96c58af175921df847a"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c4520047006b1d3f0d89e0532978c0688219857eb2fee7c48052560ae76aca1e"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-win32.whl", hash = "sha256:b2a0e3cf0caac2085ff172c3faacd1e00c376e6884b5bc4dd5b6b84623e29e4f"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-win_amd64.whl", hash = "sha256:01d10638a37460616708062a40c7b55f73e4d35eaa146781c683e0fa7f6c43fb"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:308ef9cb41d099099fffc9d35781638986870b29f744382904bf9c7dadd08513"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:296195df68326a48385e7a96e877bc19aa210e485fa381c5246bc0234c36c78e"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a13b917b4ffe5a0a31b83d051d60477819ddf18276852ea68037a144a506efb9"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f6d971255d9ddbd3189e2e79d743ff4845c07f0633adfd1de3f63d930dbe673"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:61405ea2d563407d316c63a7b5271ae5d274a2a9fbcd01b0aa5503635699fa1e"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:de7202ffe4d4a8c1e3cde1c03e01c1a3772c92858837e8f3879b497158e4cb44"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-win32.whl", hash = "sha256:b5d7ed79df55a731749ce65ec20d666d82b185fa4898430b17cb90c892741520"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-win_amd64.whl", hash = "sha256:205f5a2b39d7c380cbc3b5dcc8f2762fb5bcb716838e2d26ccbc54330775b003"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d96710d834a6fb31e21381c6d7b76ec729bd08c75a25a5184b1089141356171f"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:52de4736404e53c5c6a91ef2698c01e52333988ebdc218f14c833237a0804f1b"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c7b02525ede2a164c5fa5014915ba3591730f2cc831f5be9ff3b7fd3e30958e"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dfefdb3e54cd15f5d56fd5ae32f1da2d95d78319c1f6dfb9bcd0eb15d603d5d"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a88913000da9205b13f6f195f0813b6ffd8a0c0c2bd58d499e00a30eb508870c"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fecd5089c4be1bcc37c35e9aa678938d2888845a134dd016de457b942cf5a758"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-win32.whl", hash = "sha256:8197d6f7a3d2b468861ebb4c9f998b9df9e358d6e1cf9c2a01061cb9b6cf4e41"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-win_amd64.whl", hash = "sha256:9b19836ccca0d321e237560e475fd99c3d8655d03da80c845c4da20dda31b6e1"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:87a1d53a5382cdbbf4b7619f107cc862c1b0a4feb29000922db72e5a66a5ffc0"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0732dffe32333211801b28339d2a0babc1971bc90a983e3035e7b0d6f06b93"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90453597a753322d6aa770c5935887ab1fc49cc4c4fdd436901308383d698b4b"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ea311d4ee9a8fa67f139c088ae9f905fcf0277d6cd75c310a21a88bf85e130f5"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5f20cb0a63a3e0ec4e169aa8890e32b949c8145983afa13a708bc4b0a1f30e03"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-win32.whl", hash = "sha256:e5bbe55e8552019c6463709b39634a5fc55e080d0827e2a3a11e18eb73f5cdbd"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-win_amd64.whl", hash = "sha256:c2f9c762a2735600654c654bf48dad388b888f8ce387b095806480e6e4ff6907"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e614d7a25a43a9f54fcce4675c12761b248547f3d41b195e8010ca7297c369c"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:471fcb39c6adf37f820350c28aac4a7df9d3940c6548b624a642852e727ea586"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:988569c8732f54ad3234cf9c561364221a9e943b78dc7a4aaf35ccc2265f1930"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dddaae9b81c88083e6437de95c41e86823d150f4ee94bf24e158a4526cbead01"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:334184d1ab8f4c87f9652b048af3f7abea1c809dfe526fb0435348a6fef3d380"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:38b624e5cf02a69b113c8047cf7f66b5dfe4a2ca07ff8b8716da4f1b3ae81567"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-win32.whl", hash = "sha256:bab41acf151cd68bc2b466deae5deeb9e8ae9c50ad113444151ad965d5bf685b"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-win_amd64.whl", hash = "sha256:52c8011088305476691b8750c60e03b87910a123cfd9ad48576d6414b6ec2a1d"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3071ad498896907a5ef756206b9dc750f8e57352113c19272bdfdc429c7bd7de"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dba622396a3170974f81bad49aacebd243455ec3cc70615aeaef9e9613b5bca5"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b184e3de58009cc0bf32e20f137f1ec75a32470f5fede06c58f6c355ed42a72"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c37f1050feb91f3d6c32f864d8e114ff5545a4a7afe56778d76a9aec62638ba"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bda7ce59b06d0f09afe22c56714c65c957b1068dee3d5e74d743edec7daba552"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:25664e18bef6dc45015b08f99c63952a53a0a61f61f2e48a9e70cec27e55f699"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-win32.whl", hash = "sha256:77d29cb6c34b14af8a484e831ab530c0f7188f8efed1c6a833a2c674bf3c26ec"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-win_amd64.whl", hash = "sha256:04c487305ab035a9548f573763915189fc0fe0824d9ba28433196f8436f1449c"}, + {file = "SQLAlchemy-2.0.29-py3-none-any.whl", hash = "sha256:dc4ee2d4ee43251905f88637d5281a8d52e916a021384ec10758826f5cbae305"}, + {file = "SQLAlchemy-2.0.29.tar.gz", hash = "sha256:bd9566b8e58cabd700bc367b60e90d9349cd16f0984973f98a9a09f9c64e86f0"}, ] [package.dependencies] greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +mypy = {version = ">=0.910", optional = true, markers = "extra == \"mypy\""} typing-extensions = ">=4.6.0" [package.extras] @@ -5637,21 +5648,6 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3_binary"] -[[package]] -name = "sqlalchemy-stubs" -version = "0.4" -description = "SQLAlchemy stubs and mypy plugin" -optional = false -python-versions = "*" -files = [ - {file = "sqlalchemy-stubs-0.4.tar.gz", hash = "sha256:c665d6dd4482ef642f01027fa06c3d5e91befabb219dc71fc2a09e7d7695f7ae"}, - {file = "sqlalchemy_stubs-0.4-py3-none-any.whl", hash = "sha256:5eec7aa110adf9b957b631799a72fef396b23ff99fe296df726645d01e312aa5"}, -] - -[package.dependencies] -mypy = ">=0.790" -typing-extensions = ">=3.7.4" - [[package]] name = "sqlparse" version = "0.4.4" @@ -6884,4 +6880,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.11,<3.12" -content-hash = "f90f3e83318c5c0f4c4689fc73e315b6eeda76ddf34b7647fd5f0859767b1a0b" +content-hash = "402c47a5e38eef5bbd38a63cc8116f11b4abf0d676c9b411a2d7f425748e9c4c" diff --git a/pyproject.toml b/pyproject.toml index 6713bb7d..74bcc3bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ python = "^3.11,<3.12" python-dotenv = "^1.0.0" openai = "<1.8" tenacity = "^8.2.2" -sqlalchemy = "^2.0.23" +sqlalchemy = {extras = ["mypy"], version = "^2.0.29"} aiohttp = "^3.8.5" colorlog = "^6.7.0" chromadb = "^0.4.10" @@ -28,7 +28,6 @@ playwright = "^1.39.0" pre-commit = "^3.5.0" pillow = "^10.1.0" starlette-context = "^0.3.6" -sqlalchemy-stubs = "^0.4" ddtrace = "^2.3.2" pydantic = "^2.5.2" pydantic-settings = "^2.1.0" @@ -96,3 +95,6 @@ line_length = 120 sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] skip_glob = [".tox", "__pycache__", "*.pyc", "venv*/*", "reports", "venv", "env", "node_modules", ".env", ".venv", "dist"] skip = ["webeye/actions/__init__.py", "forge/sdk/__init__.py"] + +[tool.mypy] +plugins = "sqlalchemy.ext.mypy.plugin" diff --git a/skyvern/forge/sdk/db/client.py b/skyvern/forge/sdk/db/client.py index 9a8e2a18..e73c9541 100644 --- a/skyvern/forge/sdk/db/client.py +++ b/skyvern/forge/sdk/db/client.py @@ -2,9 +2,9 @@ from datetime import datetime from typing import Any import structlog -from sqlalchemy import and_, create_engine, delete +from sqlalchemy import and_, delete, select from sqlalchemy.exc import SQLAlchemyError -from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from skyvern.exceptions import WorkflowParameterNotFound from skyvern.forge.sdk.artifact.models import Artifact, ArtifactType @@ -63,8 +63,8 @@ class AgentDB: def __init__(self, database_string: str, debug_enabled: bool = False) -> None: super().__init__() self.debug_enabled = debug_enabled - self.engine = create_engine(database_string, json_serializer=_custom_json_serializer) - self.Session = sessionmaker(bind=self.engine) + self.engine = create_async_engine(database_string, json_serializer=_custom_json_serializer) + self.Session = async_sessionmaker(bind=self.engine) async def create_task( self, @@ -83,7 +83,7 @@ class AgentDB: error_code_mapping: dict[str, str] | None = None, ) -> Task: try: - with self.Session() as session: + async with self.Session() as session: new_task = TaskModel( status="created", url=url, @@ -101,8 +101,8 @@ class AgentDB: error_code_mapping=error_code_mapping, ) session.add(new_task) - session.commit() - session.refresh(new_task) + await session.commit() + await session.refresh(new_task) return convert_to_task(new_task, self.debug_enabled) except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) @@ -119,7 +119,7 @@ class AgentDB: organization_id: str | None = None, ) -> Step: try: - with self.Session() as session: + async with self.Session() as session: new_step = StepModel( task_id=task_id, order=order, @@ -128,8 +128,8 @@ class AgentDB: organization_id=organization_id, ) session.add(new_step) - session.commit() - session.refresh(new_step) + await session.commit() + await session.refresh(new_step) return convert_to_step(new_step, debug_enabled=self.debug_enabled) except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) @@ -148,7 +148,7 @@ class AgentDB: organization_id: str | None = None, ) -> Artifact: try: - with self.Session() as session: + async with self.Session() as session: new_artifact = ArtifactModel( artifact_id=artifact_id, task_id=task_id, @@ -158,8 +158,8 @@ class AgentDB: organization_id=organization_id, ) session.add(new_artifact) - session.commit() - session.refresh(new_artifact) + await session.commit() + await session.refresh(new_artifact) return convert_to_artifact(new_artifact, self.debug_enabled) except SQLAlchemyError: LOG.exception("SQLAlchemyError", exc_info=True) @@ -171,13 +171,12 @@ class AgentDB: async def get_task(self, task_id: str, organization_id: str | None = None) -> Task | None: """Get a task by its id""" try: - with self.Session() as session: + async with self.Session() as session: if task_obj := ( - session.query(TaskModel) - .filter_by(task_id=task_id) - .filter_by(organization_id=organization_id) - .first() - ): + await session.scalars( + select(TaskModel).filter_by(task_id=task_id).filter_by(organization_id=organization_id) + ) + ).first(): return convert_to_task(task_obj, self.debug_enabled) else: LOG.info("Task not found", task_id=task_id, organization_id=organization_id) @@ -191,13 +190,12 @@ class AgentDB: async def get_step(self, task_id: str, step_id: str, organization_id: str | None = None) -> Step | None: try: - with self.Session() as session: + async with self.Session() as session: if step := ( - session.query(StepModel) - .filter_by(step_id=step_id) - .filter_by(organization_id=organization_id) - .first() - ): + await session.scalars( + select(StepModel).filter_by(step_id=step_id).filter_by(organization_id=organization_id) + ) + ).first(): return convert_to_step(step, debug_enabled=self.debug_enabled) else: @@ -211,15 +209,16 @@ class AgentDB: async def get_task_steps(self, task_id: str, organization_id: str | None = None) -> list[Step]: try: - with self.Session() as session: - if ( - steps := session.query(StepModel) - .filter_by(task_id=task_id) - .filter_by(organization_id=organization_id) - .order_by(StepModel.order) - .order_by(StepModel.retry_index) - .all() - ): + async with self.Session() as session: + if steps := ( + await session.scalars( + select(StepModel) + .filter_by(task_id=task_id) + .filter_by(organization_id=organization_id) + .order_by(StepModel.order) + .order_by(StepModel.retry_index) + ) + ).all(): return [convert_to_step(step, debug_enabled=self.debug_enabled) for step in steps] else: return [] @@ -232,15 +231,16 @@ class AgentDB: async def get_task_step_models(self, task_id: str, organization_id: str | None = None) -> list[StepModel]: try: - with self.Session() as session: + async with self.Session() as session: return ( - session.query(StepModel) - .filter_by(task_id=task_id) - .filter_by(organization_id=organization_id) - .order_by(StepModel.order) - .order_by(StepModel.retry_index) - .all() - ) + await session.scalars( + select(StepModel) + .filter_by(task_id=task_id) + .filter_by(organization_id=organization_id) + .order_by(StepModel.order) + .order_by(StepModel.retry_index) + ) + ).all() except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) raise @@ -250,14 +250,15 @@ class AgentDB: async def get_latest_step(self, task_id: str, organization_id: str | None = None) -> Step | None: try: - with self.Session() as session: + async with self.Session() as session: if step := ( - session.query(StepModel) - .filter_by(task_id=task_id) - .filter_by(organization_id=organization_id) - .order_by(StepModel.order.desc()) - .first() - ): + await session.scalars( + select(StepModel) + .filter_by(task_id=task_id) + .filter_by(organization_id=organization_id) + .order_by(StepModel.order.desc()) + ) + ).first(): return convert_to_step(step, debug_enabled=self.debug_enabled) else: LOG.info("Latest step not found", task_id=task_id, organization_id=organization_id) @@ -281,14 +282,15 @@ class AgentDB: incremental_cost: float | None = None, ) -> Step: try: - with self.Session() as session: - if ( - step := session.query(StepModel) - .filter_by(task_id=task_id) - .filter_by(step_id=step_id) - .filter_by(organization_id=organization_id) - .first() - ): + async with self.Session() as session: + if step := ( + await session.scalars( + select(StepModel) + .filter_by(task_id=task_id) + .filter_by(step_id=step_id) + .filter_by(organization_id=organization_id) + ) + ).first(): if status is not None: step.status = status if output is not None: @@ -300,7 +302,7 @@ class AgentDB: if incremental_cost is not None: step.step_cost = incremental_cost + float(step.step_cost or 0) - session.commit() + await session.commit() updated_step = await self.get_step(task_id, step_id, organization_id) if not updated_step: raise NotFoundError("Step not found") @@ -331,13 +333,12 @@ class AgentDB: "At least one of status, extracted_information, or failure_reason must be provided to update the task" ) try: - with self.Session() as session: - if ( - task := session.query(TaskModel) - .filter_by(task_id=task_id) - .filter_by(organization_id=organization_id) - .first() - ): + async with self.Session() as session: + if task := ( + await session.scalars( + select(TaskModel).filter_by(task_id=task_id).filter_by(organization_id=organization_id) + ) + ).first(): if status is not None: task.status = status if extracted_information is not None: @@ -346,7 +347,7 @@ class AgentDB: task.failure_reason = failure_reason if errors is not None: task.errors = errors - session.commit() + await session.commit() updated_task = await self.get_task(task_id, organization_id=organization_id) if not updated_task: raise NotFoundError("Task not found") @@ -374,16 +375,17 @@ class AgentDB: raise ValueError(f"Page must be greater than 0, got {page}") try: - with self.Session() as session: + async with self.Session() as session: db_page = page - 1 # offset logic is 0 based tasks = ( - session.query(TaskModel) - .filter_by(organization_id=organization_id) - .order_by(TaskModel.created_at.desc()) - .limit(page_size) - .offset(db_page * page_size) - .all() - ) + await session.scalars( + select(TaskModel) + .filter_by(organization_id=organization_id) + .order_by(TaskModel.created_at.desc()) + .limit(page_size) + .offset(db_page * page_size) + ) + ).all() return [convert_to_task(task, debug_enabled=self.debug_enabled) for task in tasks] except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) @@ -394,10 +396,10 @@ class AgentDB: async def get_organization(self, organization_id: str) -> Organization | None: try: - with self.Session() as session: + async with self.Session() as session: if organization := ( - session.query(OrganizationModel).filter_by(organization_id=organization_id).first() - ): + await session.scalars(select(OrganizationModel).filter_by(organization_id=organization_id)) + ).first(): return convert_to_organization(organization) else: return None @@ -414,15 +416,15 @@ class AgentDB: webhook_callback_url: str | None = None, max_steps_per_run: int | None = None, ) -> Organization: - with self.Session() as session: + async with self.Session() as session: org = OrganizationModel( organization_name=organization_name, webhook_callback_url=webhook_callback_url, max_steps_per_run=max_steps_per_run, ) session.add(org) - session.commit() - session.refresh(org) + await session.commit() + await session.refresh(org) return convert_to_organization(org) @@ -432,14 +434,15 @@ class AgentDB: token_type: OrganizationAuthTokenType, ) -> OrganizationAuthToken | None: try: - with self.Session() as session: + async with self.Session() as session: if token := ( - session.query(OrganizationAuthTokenModel) - .filter_by(organization_id=organization_id) - .filter_by(token_type=token_type) - .filter_by(valid=True) - .first() - ): + await session.scalars( + select(OrganizationAuthTokenModel) + .filter_by(organization_id=organization_id) + .filter_by(token_type=token_type) + .filter_by(valid=True) + ) + ).first(): return convert_to_organization_auth_token(token) else: return None @@ -457,15 +460,16 @@ class AgentDB: token: str, ) -> OrganizationAuthToken | None: try: - with self.Session() as session: + async with self.Session() as session: if token_obj := ( - session.query(OrganizationAuthTokenModel) - .filter_by(organization_id=organization_id) - .filter_by(token_type=token_type) - .filter_by(token=token) - .filter_by(valid=True) - .first() - ): + await session.scalars( + select(OrganizationAuthTokenModel) + .filter_by(organization_id=organization_id) + .filter_by(token_type=token_type) + .filter_by(token=token) + .filter_by(valid=True) + ) + ).first(): return convert_to_organization_auth_token(token_obj) else: return None @@ -482,15 +486,15 @@ class AgentDB: token_type: OrganizationAuthTokenType, token: str, ) -> OrganizationAuthToken: - with self.Session() as session: + async with self.Session() as session: token = OrganizationAuthTokenModel( organization_id=organization_id, token_type=token_type, token=token, ) session.add(token) - session.commit() - session.refresh(token) + await session.commit() + await session.refresh(token) return convert_to_organization_auth_token(token) @@ -501,14 +505,15 @@ class AgentDB: organization_id: str | None = None, ) -> list[Artifact]: try: - with self.Session() as session: + async with self.Session() as session: if artifacts := ( - session.query(ArtifactModel) - .filter_by(task_id=task_id) - .filter_by(step_id=step_id) - .filter_by(organization_id=organization_id) - .all() - ): + await session.scalars( + select(ArtifactModel) + .filter_by(task_id=task_id) + .filter_by(step_id=step_id) + .filter_by(organization_id=organization_id) + ) + ).all(): return [convert_to_artifact(artifact, self.debug_enabled) for artifact in artifacts] else: return [] @@ -525,13 +530,14 @@ class AgentDB: organization_id: str, ) -> Artifact | None: try: - with self.Session() as session: + async with self.Session() as session: if artifact := ( - session.query(ArtifactModel) - .filter_by(artifact_id=artifact_id) - .filter_by(organization_id=organization_id) - .first() - ): + await session.scalars( + select(ArtifactModel) + .filter_by(artifact_id=artifact_id) + .filter_by(organization_id=organization_id) + ) + ).first(): return convert_to_artifact(artifact, self.debug_enabled) else: return None @@ -550,16 +556,17 @@ class AgentDB: organization_id: str | None = None, ) -> Artifact | None: try: - with self.Session() as session: + async with self.Session() as session: artifact = ( - session.query(ArtifactModel) - .filter_by(task_id=task_id) - .filter_by(step_id=step_id) - .filter_by(organization_id=organization_id) - .filter_by(artifact_type=artifact_type) - .order_by(ArtifactModel.created_at.desc()) - .first() - ) + await session.scalars( + select(ArtifactModel) + .filter_by(task_id=task_id) + .filter_by(step_id=step_id) + .filter_by(organization_id=organization_id) + .filter_by(artifact_type=artifact_type) + .order_by(ArtifactModel.created_at.desc()) + ) + ).first() if artifact: return convert_to_artifact(artifact, self.debug_enabled) return None @@ -577,16 +584,17 @@ class AgentDB: organization_id: str | None = None, ) -> Artifact | None: try: - with self.Session() as session: + async with self.Session() as session: artifact = ( - session.query(ArtifactModel) - .join(TaskModel, TaskModel.task_id == ArtifactModel.task_id) - .filter(TaskModel.workflow_run_id == workflow_run_id) - .filter(ArtifactModel.artifact_type == artifact_type) - .filter(ArtifactModel.organization_id == organization_id) - .order_by(ArtifactModel.created_at.desc()) - .first() - ) + await session.scalars( + select(ArtifactModel) + .join(TaskModel, TaskModel.task_id == ArtifactModel.task_id) + .filter(TaskModel.workflow_run_id == workflow_run_id) + .filter(ArtifactModel.artifact_type == artifact_type) + .filter(ArtifactModel.organization_id == organization_id) + .order_by(ArtifactModel.created_at.desc()) + ) + ).first() if artifact: return convert_to_artifact(artifact, self.debug_enabled) return None @@ -605,8 +613,8 @@ class AgentDB: organization_id: str | None = None, ) -> Artifact | None: try: - with self.Session() as session: - artifact_query = session.query(ArtifactModel).filter_by(task_id=task_id) + async with self.Session() as session: + artifact_query = select(ArtifactModel).filter_by(task_id=task_id) if step_id: artifact_query = artifact_query.filter_by(step_id=step_id) if organization_id: @@ -614,7 +622,7 @@ class AgentDB: if artifact_types: artifact_query = artifact_query.filter(ArtifactModel.artifact_type.in_(artifact_types)) - artifact = artifact_query.order_by(ArtifactModel.created_at.desc()).first() + artifact = (await session.scalars(artifact_query.order_by(ArtifactModel.created_at.desc()))).first() if artifact: return convert_to_artifact(artifact, self.debug_enabled) return None @@ -632,15 +640,11 @@ class AgentDB: before: datetime | None = None, ) -> Task | None: try: - with self.Session() as session: - query = ( - session.query(TaskModel) - .filter_by(organization_id=organization_id) - .filter_by(workflow_id=workflow_id) - ) + async with self.Session() as session: + query = select(TaskModel).filter_by(organization_id=organization_id).filter_by(workflow_id=workflow_id) if before: query = query.filter(TaskModel.created_at < before) - task = query.order_by(TaskModel.created_at.desc()).first() + task = (await session.scalars(query.order_by(TaskModel.created_at.desc()))).first() if task: return convert_to_task(task, debug_enabled=self.debug_enabled) return None @@ -655,7 +659,7 @@ class AgentDB: workflow_definition: dict[str, Any], description: str | None = None, ) -> Workflow: - with self.Session() as session: + async with self.Session() as session: workflow = WorkflowModel( organization_id=organization_id, title=title, @@ -663,14 +667,16 @@ class AgentDB: workflow_definition=workflow_definition, ) session.add(workflow) - session.commit() - session.refresh(workflow) + await session.commit() + await session.refresh(workflow) return convert_to_workflow(workflow, self.debug_enabled) async def get_workflow(self, workflow_id: str) -> Workflow | None: try: - with self.Session() as session: - if workflow := session.query(WorkflowModel).filter_by(workflow_id=workflow_id).first(): + async with self.Session() as session: + if workflow := ( + await session.scalars(select(WorkflowModel).filter_by(workflow_id=workflow_id)) + ).first(): return convert_to_workflow(workflow, self.debug_enabled) return None except SQLAlchemyError: @@ -684,8 +690,8 @@ class AgentDB: description: str | None = None, workflow_definition: dict[str, Any] | None = None, ) -> Workflow | None: - with self.Session() as session: - workflow = session.query(WorkflowModel).filter_by(workflow_id=workflow_id).first() + async with self.Session() as session: + workflow = (await session.scalars(select(WorkflowModel).filter_by(workflow_id=workflow_id))).first() if workflow: if title: workflow.title = title @@ -693,8 +699,8 @@ class AgentDB: workflow.description = description if workflow_definition: workflow.workflow_definition = workflow_definition - session.commit() - session.refresh(workflow) + await session.commit() + await session.refresh(workflow) return convert_to_workflow(workflow, self.debug_enabled) LOG.error("Workflow not found, nothing to update", workflow_id=workflow_id) return None @@ -703,7 +709,7 @@ class AgentDB: self, workflow_id: str, proxy_location: ProxyLocation | None = None, webhook_callback_url: str | None = None ) -> WorkflowRun: try: - with self.Session() as session: + async with self.Session() as session: workflow_run = WorkflowRunModel( workflow_id=workflow_id, proxy_location=proxy_location, @@ -711,28 +717,32 @@ class AgentDB: webhook_callback_url=webhook_callback_url, ) session.add(workflow_run) - session.commit() - session.refresh(workflow_run) + await session.commit() + await session.refresh(workflow_run) return convert_to_workflow_run(workflow_run) except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) raise async def update_workflow_run(self, workflow_run_id: str, status: WorkflowRunStatus) -> WorkflowRun | None: - with self.Session() as session: - workflow_run = session.query(WorkflowRunModel).filter_by(workflow_run_id=workflow_run_id).first() + async with self.Session() as session: + workflow_run = ( + await session.scalars(select(WorkflowRunModel).filter_by(workflow_run_id=workflow_run_id)) + ).first() if workflow_run: workflow_run.status = status - session.commit() - session.refresh(workflow_run) + await session.commit() + await session.refresh(workflow_run) return convert_to_workflow_run(workflow_run) LOG.error("WorkflowRun not found, nothing to update", workflow_run_id=workflow_run_id) return None async def get_workflow_run(self, workflow_run_id: str) -> WorkflowRun | None: try: - with self.Session() as session: - if workflow_run := session.query(WorkflowRunModel).filter_by(workflow_run_id=workflow_run_id).first(): + async with self.Session() as session: + if workflow_run := ( + await session.scalars(select(WorkflowRunModel).filter_by(workflow_run_id=workflow_run_id)) + ).first(): return convert_to_workflow_run(workflow_run) return None except SQLAlchemyError: @@ -741,8 +751,10 @@ class AgentDB: async def get_workflow_runs(self, workflow_id: str) -> list[WorkflowRun]: try: - with self.Session() as session: - workflow_runs = session.query(WorkflowRunModel).filter_by(workflow_id=workflow_id).all() + async with self.Session() as session: + workflow_runs = ( + await session.scalars(select(WorkflowRunModel).filter_by(workflow_id=workflow_id)) + ).all() return [convert_to_workflow_run(run) for run in workflow_runs] except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) @@ -757,7 +769,7 @@ class AgentDB: description: str | None = None, ) -> WorkflowParameter: try: - with self.Session() as session: + async with self.Session() as session: workflow_parameter = WorkflowParameterModel( workflow_id=workflow_id, workflow_parameter_type=workflow_parameter_type, @@ -766,8 +778,8 @@ class AgentDB: description=description, ) session.add(workflow_parameter) - session.commit() - session.refresh(workflow_parameter) + await session.commit() + await session.refresh(workflow_parameter) return convert_to_workflow_parameter(workflow_parameter, self.debug_enabled) except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) @@ -780,7 +792,7 @@ class AgentDB: aws_key: str, description: str | None = None, ) -> AWSSecretParameter: - with self.Session() as session: + async with self.Session() as session: aws_secret_parameter = AWSSecretParameterModel( workflow_id=workflow_id, key=key, @@ -788,8 +800,8 @@ class AgentDB: description=description, ) session.add(aws_secret_parameter) - session.commit() - session.refresh(aws_secret_parameter) + await session.commit() + await session.refresh(aws_secret_parameter) return convert_to_aws_secret_parameter(aws_secret_parameter) async def create_output_parameter( @@ -798,21 +810,23 @@ class AgentDB: key: str, description: str | None = None, ) -> OutputParameter: - with self.Session() as session: + async with self.Session() as session: output_parameter = OutputParameterModel( key=key, description=description, workflow_id=workflow_id, ) session.add(output_parameter) - session.commit() - session.refresh(output_parameter) + await session.commit() + await session.refresh(output_parameter) return convert_to_output_parameter(output_parameter) async def get_workflow_output_parameters(self, workflow_id: str) -> list[OutputParameter]: try: - with self.Session() as session: - output_parameters = session.query(OutputParameterModel).filter_by(workflow_id=workflow_id).all() + async with self.Session() as session: + output_parameters = ( + await session.scalars(select(OutputParameterModel).filter_by(workflow_id=workflow_id)) + ).all() return [convert_to_output_parameter(parameter) for parameter in output_parameters] except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) @@ -820,13 +834,14 @@ class AgentDB: async def get_workflow_run_output_parameters(self, workflow_run_id: str) -> list[WorkflowRunOutputParameter]: try: - with self.Session() as session: + async with self.Session() as session: workflow_run_output_parameters = ( - session.query(WorkflowRunOutputParameterModel) - .filter_by(workflow_run_id=workflow_run_id) - .order_by(WorkflowRunOutputParameterModel.created_at) - .all() - ) + await session.scalars( + select(WorkflowRunOutputParameterModel) + .filter_by(workflow_run_id=workflow_run_id) + .order_by(WorkflowRunOutputParameterModel.created_at) + ) + ).all() return [ convert_to_workflow_run_output_parameter(parameter, self.debug_enabled) for parameter in workflow_run_output_parameters @@ -839,15 +854,15 @@ class AgentDB: self, workflow_run_id: str, output_parameter_id: str, value: dict[str, Any] | list | str | None ) -> WorkflowRunOutputParameter: try: - with self.Session() as session: + async with self.Session() as session: workflow_run_output_parameter = WorkflowRunOutputParameterModel( workflow_run_id=workflow_run_id, output_parameter_id=output_parameter_id, value=value, ) session.add(workflow_run_output_parameter) - session.commit() - session.refresh(workflow_run_output_parameter) + await session.commit() + await session.refresh(workflow_run_output_parameter) return convert_to_workflow_run_output_parameter(workflow_run_output_parameter, self.debug_enabled) except SQLAlchemyError: @@ -856,8 +871,10 @@ class AgentDB: async def get_workflow_parameters(self, workflow_id: str) -> list[WorkflowParameter]: try: - with self.Session() as session: - workflow_parameters = session.query(WorkflowParameterModel).filter_by(workflow_id=workflow_id).all() + async with self.Session() as session: + workflow_parameters = ( + await session.scalars(select(WorkflowParameterModel).filter_by(workflow_id=workflow_id)) + ).all() return [convert_to_workflow_parameter(parameter) for parameter in workflow_parameters] except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) @@ -865,10 +882,12 @@ class AgentDB: async def get_workflow_parameter(self, workflow_parameter_id: str) -> WorkflowParameter | None: try: - with self.Session() as session: + async with self.Session() as session: if workflow_parameter := ( - session.query(WorkflowParameterModel).filter_by(workflow_parameter_id=workflow_parameter_id).first() - ): + await session.scalars( + select(WorkflowParameterModel).filter_by(workflow_parameter_id=workflow_parameter_id) + ) + ).first(): return convert_to_workflow_parameter(workflow_parameter, self.debug_enabled) return None except SQLAlchemyError: @@ -879,15 +898,15 @@ class AgentDB: self, workflow_run_id: str, workflow_parameter_id: str, value: Any ) -> WorkflowRunParameter: try: - with self.Session() as session: + async with self.Session() as session: workflow_run_parameter = WorkflowRunParameterModel( workflow_run_id=workflow_run_id, workflow_parameter_id=workflow_parameter_id, value=value, ) session.add(workflow_run_parameter) - session.commit() - session.refresh(workflow_run_parameter) + await session.commit() + await session.refresh(workflow_run_parameter) workflow_parameter = await self.get_workflow_parameter(workflow_parameter_id) if not workflow_parameter: raise WorkflowParameterNotFound(workflow_parameter_id) @@ -900,10 +919,10 @@ class AgentDB: self, workflow_run_id: str ) -> list[tuple[WorkflowParameter, WorkflowRunParameter]]: try: - with self.Session() as session: + async with self.Session() as session: workflow_run_parameters = ( - session.query(WorkflowRunParameterModel).filter_by(workflow_run_id=workflow_run_id).all() - ) + await session.scalars(select(WorkflowRunParameterModel).filter_by(workflow_run_id=workflow_run_id)) + ).all() results = [] for workflow_run_parameter in workflow_run_parameters: workflow_parameter = await self.get_workflow_parameter(workflow_run_parameter.workflow_parameter_id) @@ -926,13 +945,14 @@ class AgentDB: async def get_last_task_for_workflow_run(self, workflow_run_id: str) -> Task | None: try: - with self.Session() as session: + async with self.Session() as session: if task := ( - session.query(TaskModel) - .filter_by(workflow_run_id=workflow_run_id) - .order_by(TaskModel.created_at.desc()) - .first() - ): + await session.scalars( + select(TaskModel) + .filter_by(workflow_run_id=workflow_run_id) + .order_by(TaskModel.created_at.desc()) + ) + ).first(): return convert_to_task(task, debug_enabled=self.debug_enabled) return None except SQLAlchemyError: @@ -941,20 +961,19 @@ class AgentDB: async def get_tasks_by_workflow_run_id(self, workflow_run_id: str) -> list[Task]: try: - with self.Session() as session: + async with self.Session() as session: tasks = ( - session.query(TaskModel) - .filter_by(workflow_run_id=workflow_run_id) - .order_by(TaskModel.created_at) - .all() - ) + await session.scalars( + select(TaskModel).filter_by(workflow_run_id=workflow_run_id).order_by(TaskModel.created_at) + ) + ).all() return [convert_to_task(task, debug_enabled=self.debug_enabled) for task in tasks] except SQLAlchemyError: LOG.error("SQLAlchemyError", exc_info=True) raise async def delete_task_artifacts(self, organization_id: str, task_id: str) -> None: - with self.Session() as session: + async with self.Session() as session: # delete artifacts by filtering organization_id and task_id stmt = delete(ArtifactModel).where( and_( @@ -962,11 +981,11 @@ class AgentDB: ArtifactModel.task_id == task_id, ) ) - session.execute(stmt) - session.commit() + await session.execute(stmt) + await session.commit() async def delete_task_steps(self, organization_id: str, task_id: str) -> None: - with self.Session() as session: + async with self.Session() as session: # delete artifacts by filtering organization_id and task_id stmt = delete(StepModel).where( and_( @@ -974,5 +993,5 @@ class AgentDB: StepModel.task_id == task_id, ) ) - session.execute(stmt) - session.commit() + await session.execute(stmt) + await session.commit() diff --git a/skyvern/forge/sdk/db/models.py b/skyvern/forge/sdk/db/models.py index e4302f65..5eff3626 100644 --- a/skyvern/forge/sdk/db/models.py +++ b/skyvern/forge/sdk/db/models.py @@ -1,6 +1,7 @@ import datetime from sqlalchemy import JSON, Boolean, Column, DateTime, Enum, ForeignKey, Integer, Numeric, String, UnicodeText +from sqlalchemy.ext.asyncio import AsyncAttrs from sqlalchemy.orm import DeclarativeBase from skyvern.forge.sdk.db.enums import OrganizationAuthTokenType @@ -19,7 +20,7 @@ from skyvern.forge.sdk.db.id import ( from skyvern.forge.sdk.schemas.tasks import ProxyLocation -class Base(DeclarativeBase): +class Base(AsyncAttrs, DeclarativeBase): pass