From 46a3f07f0e2d4ee1669b53f6d6eedc35fd1e19b4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 12:50:00 +0000 Subject: [PATCH 1/2] Update dependency SQLAlchemy to v2 --- poetry.lock | 109 +++++++++++++++++++++++++------------------------ pyproject.toml | 2 +- 2 files changed, 57 insertions(+), 54 deletions(-) diff --git a/poetry.lock b/poetry.lock index 495bd25b4..4786df1c1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2329,77 +2329,80 @@ files = [ [[package]] name = "sqlalchemy" -version = "1.4.46" +version = "2.0.0" description = "Database Abstraction Library" category = "main" optional = true -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -files = [ - {file = "SQLAlchemy-1.4.46-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:7001f16a9a8e06488c3c7154827c48455d1c1507d7228d43e781afbc8ceccf6d"}, - {file = "SQLAlchemy-1.4.46-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c7a46639ba058d320c9f53a81db38119a74b8a7a1884df44d09fbe807d028aaf"}, - {file = "SQLAlchemy-1.4.46-cp27-cp27m-win32.whl", hash = "sha256:c04144a24103135ea0315d459431ac196fe96f55d3213bfd6d39d0247775c854"}, - {file = "SQLAlchemy-1.4.46-cp27-cp27m-win_amd64.whl", hash = "sha256:7b81b1030c42b003fc10ddd17825571603117f848814a344d305262d370e7c34"}, - {file = "SQLAlchemy-1.4.46-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:939f9a018d2ad04036746e15d119c0428b1e557470361aa798e6e7d7f5875be0"}, - {file = "SQLAlchemy-1.4.46-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b7f4b6aa6e87991ec7ce0e769689a977776db6704947e562102431474799a857"}, - {file = "SQLAlchemy-1.4.46-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbf17ac9a61e7a3f1c7ca47237aac93cabd7f08ad92ac5b96d6f8dea4287fc1"}, - {file = "SQLAlchemy-1.4.46-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7f8267682eb41a0584cf66d8a697fef64b53281d01c93a503e1344197f2e01fe"}, - {file = "SQLAlchemy-1.4.46-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cb0ad8a190bc22d2112001cfecdec45baffdf41871de777239da6a28ed74b6"}, - {file = "SQLAlchemy-1.4.46-cp310-cp310-win32.whl", hash = "sha256:5f752676fc126edc1c4af0ec2e4d2adca48ddfae5de46bb40adbd3f903eb2120"}, - {file = "SQLAlchemy-1.4.46-cp310-cp310-win_amd64.whl", hash = "sha256:31de1e2c45e67a5ec1ecca6ec26aefc299dd5151e355eb5199cd9516b57340be"}, - {file = "SQLAlchemy-1.4.46-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d68e1762997bfebf9e5cf2a9fd0bcf9ca2fdd8136ce7b24bbd3bbfa4328f3e4a"}, - {file = "SQLAlchemy-1.4.46-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d112b0f3c1bc5ff70554a97344625ef621c1bfe02a73c5d97cac91f8cd7a41e"}, - {file = "SQLAlchemy-1.4.46-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69fac0a7054d86b997af12dc23f581cf0b25fb1c7d1fed43257dee3af32d3d6d"}, - {file = "SQLAlchemy-1.4.46-cp311-cp311-win32.whl", hash = "sha256:887865924c3d6e9a473dc82b70977395301533b3030d0f020c38fd9eba5419f2"}, - {file = "SQLAlchemy-1.4.46-cp311-cp311-win_amd64.whl", hash = "sha256:984ee13543a346324319a1fb72b698e521506f6f22dc37d7752a329e9cd00a32"}, - {file = "SQLAlchemy-1.4.46-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:9167d4227b56591a4cc5524f1b79ccd7ea994f36e4c648ab42ca995d28ebbb96"}, - {file = "SQLAlchemy-1.4.46-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d61e9ecc849d8d44d7f80894ecff4abe347136e9d926560b818f6243409f3c86"}, - {file = "SQLAlchemy-1.4.46-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3ec187acf85984263299a3f15c34a6c0671f83565d86d10f43ace49881a82718"}, - {file = "SQLAlchemy-1.4.46-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9883f5fae4fd8e3f875adc2add69f8b945625811689a6c65866a35ee9c0aea23"}, - {file = "SQLAlchemy-1.4.46-cp36-cp36m-win32.whl", hash = "sha256:535377e9b10aff5a045e3d9ada8a62d02058b422c0504ebdcf07930599890eb0"}, - {file = "SQLAlchemy-1.4.46-cp36-cp36m-win_amd64.whl", hash = "sha256:18cafdb27834fa03569d29f571df7115812a0e59fd6a3a03ccb0d33678ec8420"}, - {file = "SQLAlchemy-1.4.46-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:a1ad90c97029cc3ab4ffd57443a20fac21d2ec3c89532b084b073b3feb5abff3"}, - {file = "SQLAlchemy-1.4.46-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4847f4b1d822754e35707db913396a29d874ee77b9c3c3ef3f04d5a9a6209618"}, - {file = "SQLAlchemy-1.4.46-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c5a99282848b6cae0056b85da17392a26b2d39178394fc25700bcf967e06e97a"}, - {file = "SQLAlchemy-1.4.46-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4b1cc7835b39835c75cf7c20c926b42e97d074147c902a9ebb7cf2c840dc4e2"}, - {file = "SQLAlchemy-1.4.46-cp37-cp37m-win32.whl", hash = "sha256:c522e496f9b9b70296a7675272ec21937ccfc15da664b74b9f58d98a641ce1b6"}, - {file = "SQLAlchemy-1.4.46-cp37-cp37m-win_amd64.whl", hash = "sha256:ae067ab639fa499f67ded52f5bc8e084f045d10b5ac7bb928ae4ca2b6c0429a5"}, - {file = "SQLAlchemy-1.4.46-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:e3c1808008124850115a3f7e793a975cfa5c8a26ceeeb9ff9cbb4485cac556df"}, - {file = "SQLAlchemy-1.4.46-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d164df3d83d204c69f840da30b292ac7dc54285096c6171245b8d7807185aa"}, - {file = "SQLAlchemy-1.4.46-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b33ffbdbbf5446cf36cd4cc530c9d9905d3c2fe56ed09e25c22c850cdb9fac92"}, - {file = "SQLAlchemy-1.4.46-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d94682732d1a0def5672471ba42a29ff5e21bb0aae0afa00bb10796fc1e28dd"}, - {file = "SQLAlchemy-1.4.46-cp38-cp38-win32.whl", hash = "sha256:f8cb80fe8d14307e4124f6fad64dfd87ab749c9d275f82b8b4ec84c84ecebdbe"}, - {file = "SQLAlchemy-1.4.46-cp38-cp38-win_amd64.whl", hash = "sha256:07e48cbcdda6b8bc7a59d6728bd3f5f574ffe03f2c9fb384239f3789c2d95c2e"}, - {file = "SQLAlchemy-1.4.46-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:1b1e5e96e2789d89f023d080bee432e2fef64d95857969e70d3cadec80bd26f0"}, - {file = "SQLAlchemy-1.4.46-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3714e5b33226131ac0da60d18995a102a17dddd42368b7bdd206737297823ad"}, - {file = "SQLAlchemy-1.4.46-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:955162ad1a931fe416eded6bb144ba891ccbf9b2e49dc7ded39274dd9c5affc5"}, - {file = "SQLAlchemy-1.4.46-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6e4cb5c63f705c9d546a054c60d326cbde7421421e2d2565ce3e2eee4e1a01f"}, - {file = "SQLAlchemy-1.4.46-cp39-cp39-win32.whl", hash = "sha256:51e1ba2884c6a2b8e19109dc08c71c49530006c1084156ecadfaadf5f9b8b053"}, - {file = "SQLAlchemy-1.4.46-cp39-cp39-win_amd64.whl", hash = "sha256:315676344e3558f1f80d02535f410e80ea4e8fddba31ec78fe390eff5fb8f466"}, - {file = "SQLAlchemy-1.4.46.tar.gz", hash = "sha256:6913b8247d8a292ef8315162a51931e2b40ce91681f1b6f18f697045200c4a30"}, +python-versions = ">=3.7" +files = [ + {file = "SQLAlchemy-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:807d4f83dcf0b7fd60b7af5f677e3d20151083c3454304813e450f6f6e4b4a5c"}, + {file = "SQLAlchemy-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:419228c073060face5e35388ddf00229f1be3664c91143f6e6897d67254589f7"}, + {file = "SQLAlchemy-2.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e052ae0c2a887472a74405e3afa5aa5c75cddc8a98a49bbf4a84a09dbc1cb896"}, + {file = "SQLAlchemy-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0bc643a0228179bfcbc8df81c8d197b843e48d97073f41f90ada8f6aad1614d"}, + {file = "SQLAlchemy-2.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:492dfab60c3df7105c97474a08408f15a506966340643eeaf40f59daa08a516e"}, + {file = "SQLAlchemy-2.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:20ef6ed15ecc17036523157e1f9900f0fa9163c29ce793d441b0bdd337057354"}, + {file = "SQLAlchemy-2.0.0-cp310-cp310-win32.whl", hash = "sha256:86bc43f80b3fdae55f2dc6a3b0a9fe6f5c69001763e4095998e467b068a037d2"}, + {file = "SQLAlchemy-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:6e6cb16419328100fc92ee676bcb09846034586461aeb96c89a072feb48c9a6d"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a0b4047d7d9405005637fbfd70122746c78f2dada934067bfdd439bc934cb5fb"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b850d709cddfe0fa03f0ce7d58389947813053a3cfd5c7cc2fa5a49b77b7f7b5"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:176ddfce8d720f90ffccfecfe66f41b1af8906bb74acc536068d067bdb0fd080"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0794ed9ed2cc3c42475998baf3ead135ce3849e72993fd61c82722a1def8a5"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3758f3e12dd7a1448d8d2c5d4d36dc32a504a0ff6dded23b06d955c73f1b71b4"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7a2709d68ec901add77aa378253568905ba8112ae82ae8b3d3e85fd56b06f44d"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c658c985830d4d80598387b2eca5944507acc9d52af8ec867d4c9fa0d4e27fd7"}, + {file = "SQLAlchemy-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:92b828f195bb967f85bda508bed5b4fe24b4ef0cac9ac2d9e403584ba504a304"}, + {file = "SQLAlchemy-2.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7b2231470060cd55b870806fb654f2ba66f7fc822f56fe594fa1fbd95e646da5"}, + {file = "SQLAlchemy-2.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:228851937becdbaeefdc937a3b43e9711b0a094eccc745f00b993ecd860a913b"}, + {file = "SQLAlchemy-2.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b4428bf59a5f12549f92f4274c8b2667313f105e36a7822c47727ea5572e0f7"}, + {file = "SQLAlchemy-2.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d1b1004e00023b37cc2385da670db28cb3dd96b9f01aafc3f9c437c030bf73f8"}, + {file = "SQLAlchemy-2.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a0f6d402a12ce2dc9243553ae8088459e94540b2afc4b4c3fc3a0272b9aa2827"}, + {file = "SQLAlchemy-2.0.0-cp37-cp37m-win32.whl", hash = "sha256:c1cae76f84755527c269ceb49e3a79ff370101bfd93d3f9d298bd7951e1b5e41"}, + {file = "SQLAlchemy-2.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:83db15a39539c6acb92075215aa68b9757085717d222ef678b0040cdf192adbb"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c6934dfa9ab53853b1d31723ea2b8ea494de73ad3f36ea42f5859b74cb3afc3"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:05923707b416b7034c0b14e59e14614cb1432647188ba46bcfd911998cdea48d"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33a05cc9533a580f94a69852c8dea26d7dec0bc8182bb8d68180a5103c0b0add"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6e4a17bbcb882fcff597d6ffdf113144383ea346bcae97079b96faaf7d460fb"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:54fa0308430ea13239557b6b38a41988ab9d0356420879b2e8b976f58c8b8229"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6c75b77de2fd99bd19a609c00e870325574000c441f7bdb0cd33d15961ed93bc"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-win32.whl", hash = "sha256:28f8371e07c66f7bd8d665c0532e68986e1616f0505bef05a9bcb384889f94f2"}, + {file = "SQLAlchemy-2.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:2051899b520a4332da0fe7098d155e0981044aed91567623c7aff4bd4addddc8"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0fb3b58ba21898b94255e86da5e3bfc15cf99e039babcaccaa2ce10b6322929e"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77666361fdd70868a414762d0eead141183caf1e0cb6735484c0cad6d41ac869"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dc81c03d4bccc82c81e4e21da5cea2071eca2fcddb248b462b151911c4b47b8"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b17bc162c317973d87613eac869cc50c1fef7a8b9d657b7d7f764ab5d9fee72"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7809546951b4a5ad1f0b5d5c87b42218af8c0574f50e89d141dfff531c069389"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:606f55614af6777261e54cb5d541a5c555539c5abc5e0b40d299c9a3bd06fae5"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-win32.whl", hash = "sha256:47348dad936e0899e2910853df1af736a84b3bddbd5dfe6471a5a39e00b32f06"}, + {file = "SQLAlchemy-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:13929b9806b002e3018a2f4d6666466298f43043c53b037a27520d8e8dad238d"}, + {file = "SQLAlchemy-2.0.0-py3-none-any.whl", hash = "sha256:192210daec1062e93fcc732de0c602c4b58097257c56874baa6e491849e82ceb"}, + {file = "SQLAlchemy-2.0.0.tar.gz", hash = "sha256:92388d03220eda6d744277a4d2cbcbb557509c7f7582215f61f8a04ec264be59"}, ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (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\")"} +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\""} +typing-extensions = ">=4.2.0" [package.extras] aiomysql = ["aiomysql", "greenlet (!=0.4.17)"] aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] asyncio = ["greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] mssql = ["pyodbc"] mssql-pymssql = ["pymssql"] mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] -mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"] mysql-connector = ["mysql-connector-python"] -oracle = ["cx-oracle (>=7)", "cx-oracle (>=7,<8)"] +oracle = ["cx-oracle (>=7)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] postgresql = ["psycopg2 (>=2.7)"] postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] postgresql-psycopg2binary = ["psycopg2-binary"] postgresql-psycopg2cffi = ["psycopg2cffi"] -pymysql = ["pymysql", "pymysql (<1)"] +pymysql = ["pymysql"] sqlcipher = ["sqlcipher3-binary"] [[package]] @@ -2645,7 +2648,7 @@ files = [ name = "typing-extensions" version = "4.4.0" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3003,4 +3006,4 @@ test-images = ["scikit-image"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "f38176dc28ab4521940b028c6cb87392bfa472e5920ac955e49c260fd3a4be75" +content-hash = "b72b64e6cc2d668399470147d93ccd47295e91620b77e4717b5354cf88a90cc4" diff --git a/pyproject.toml b/pyproject.toml index f6583b4dd..e03436d30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,7 +84,7 @@ pyramid-tm = { version = "2.5", optional = true } sentry-sdk = { version = "1.14.0", optional = true } ujson = { version = "5.7.0", optional = true } cee_syslog_handler = { version = "0.6.0", optional = true } -SQLAlchemy = { version = "1.4.46", optional = true } +SQLAlchemy = { version = "2.0.0", optional = true } SQLAlchemy-Utils = { version = "0.39.0", optional = true } "zope.interface" = { version = "5.5.2", optional = true } "zope.sqlalchemy" = { version = "1.6", optional = true } From b8662b4de5293dedf005832d0129c19f344dcb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Brunner?= Date: Wed, 1 Feb 2023 15:26:38 +0100 Subject: [PATCH 2/2] Apply the update to SQLAlchemy 2.0 --- .prospector.yaml | 1 + c2cwsgiutils/db.py | 75 +++++++++++++---------- c2cwsgiutils/errors.py | 9 +-- c2cwsgiutils/health_check.py | 57 ++++++++++------- c2cwsgiutils/models_graph.py | 2 +- c2cwsgiutils/request_tracking/_sql.py | 4 +- c2cwsgiutils/scripts/stats_db.py | 68 ++++++++++++++------ c2cwsgiutils/sql_profiler/_impl.py | 7 ++- c2cwsgiutils/sqlalchemylogger/_models.py | 5 +- c2cwsgiutils/sqlalchemylogger/handlers.py | 8 ++- pyproject.toml | 1 + 11 files changed, 153 insertions(+), 84 deletions(-) diff --git a/.prospector.yaml b/.prospector.yaml index 2fdecb6e5..eba3f7ba7 100644 --- a/.prospector.yaml +++ b/.prospector.yaml @@ -40,6 +40,7 @@ pycodestyle: disable: - E203 # Whitespace before ':', duplicated with black, with error in array - E722 # do not use bare 'except', duplicated with pylint + - E261 # at least two spaces before inline comment, duplicated with black pydocstyle: disable: diff --git a/c2cwsgiutils/db.py b/c2cwsgiutils/db.py index 349edaf2e..1ebf95472 100644 --- a/c2cwsgiutils/db.py +++ b/c2cwsgiutils/db.py @@ -35,7 +35,7 @@ def setup_session( force_master: Optional[Iterable[str]] = None, force_slave: Optional[Iterable[str]] = None, ) -> Tuple[ - Union[sqlalchemy.orm.Session, sqlalchemy.orm.scoped_session], + Union[sqlalchemy.orm.Session, sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]], sqlalchemy.engine.Engine, sqlalchemy.engine.Engine, ]: @@ -67,7 +67,7 @@ def setup_session( slave_prefix = master_prefix settings = config.registry.settings rw_engine = sqlalchemy.engine_from_config(settings, master_prefix + ".") - rw_engine.c2c_name = master_prefix + rw_engine.c2c_name = master_prefix # type: ignore factory = sqlalchemy.orm.sessionmaker(bind=rw_engine) register(factory) db_session = sqlalchemy.orm.scoped_session(factory) @@ -76,14 +76,14 @@ def setup_session( if settings[master_prefix + ".url"] != settings.get(slave_prefix + ".url"): LOG.info("Using a slave DB for reading %s", master_prefix) ro_engine = sqlalchemy.engine_from_config(config.get_settings(), slave_prefix + ".") - ro_engine.c2c_name = slave_prefix + ro_engine.c2c_name = slave_prefix # type: ignore tween_name = master_prefix.replace(".", "_") _add_tween(config, tween_name, db_session, force_master, force_slave) else: ro_engine = rw_engine - db_session.c2c_rw_bind = rw_engine - db_session.c2c_ro_bind = ro_engine + db_session.c2c_rw_bind = rw_engine # type: ignore + db_session.c2c_ro_bind = ro_engine # type: ignore return db_session, rw_engine, ro_engine @@ -95,7 +95,7 @@ def create_session( force_master: Optional[Iterable[str]] = None, force_slave: Optional[Iterable[str]] = None, **engine_config: Any, -) -> Union[sqlalchemy.orm.Session, sqlalchemy.orm.scoped_session]: +) -> Union[sqlalchemy.orm.Session, sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]]: """ Create a SQLAlchemy session. @@ -133,21 +133,21 @@ def create_session( LOG.info("Using a slave DB for reading %s", name) ro_engine = sqlalchemy.create_engine(slave_url, **engine_config) _add_tween(config, name, db_session, force_master, force_slave) - rw_engine.c2c_name = name + "_master" - ro_engine.c2c_name = name + "_slave" + rw_engine.c2c_name = name + "_master" # type: ignore + ro_engine.c2c_name = name + "_slave" # type: ignore else: - rw_engine.c2c_name = name + rw_engine.c2c_name = name # type: ignore ro_engine = rw_engine - db_session.c2c_rw_bind = rw_engine - db_session.c2c_ro_bind = ro_engine + db_session.c2c_rw_bind = rw_engine # type: ignore + db_session.c2c_ro_bind = ro_engine # type: ignore return db_session def _add_tween( config: pyramid.config.Configurator, name: str, - db_session: Union[sqlalchemy.orm.Session, sqlalchemy.orm.scoped_session], + db_session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], force_master: Optional[Iterable[str]], force_slave: Optional[Iterable[str]], ) -> None: @@ -176,11 +176,19 @@ def db_chooser_tween(request: pyramid.request.Request) -> Any: not has_force_master and (request.method in ("GET", "OPTIONS") or any(r.match(method_path) for r in slave_paths)) ): - LOG.debug("Using %s database for: %s", db_session.c2c_ro_bind.c2c_name, method_path) - session.bind = db_session.c2c_ro_bind + LOG.debug( + "Using %s database for: %s", + db_session.c2c_ro_bind.c2c_name, # type: ignore + method_path, + ) + session.bind = db_session.c2c_ro_bind # type: ignore else: - LOG.debug("Using %s database for: %s", db_session.c2c_rw_bind.c2c_name, method_path) - session.bind = db_session.c2c_rw_bind + LOG.debug( + "Using %s database for: %s", + db_session.c2c_rw_bind.c2c_name, # type: ignore + method_path, + ) + session.bind = db_session.c2c_rw_bind # type: ignore try: return handler(request) @@ -193,7 +201,7 @@ def db_chooser_tween(request: pyramid.request.Request) -> Any: config.add_tween("c2cwsgiutils.db.tweens." + name, over="pyramid_tm.tm_tween_factory") -class SessionFactory(sessionmaker): # type: ignore +class SessionFactory(sessionmaker[sqlalchemy.orm.Session]): # pylint: disable=unsubscriptable-object """The custom session factory that manage the read only and read write sessions.""" def __init__( @@ -213,18 +221,18 @@ def __init__( def engine_name(self, readwrite: bool) -> str: if readwrite: - return cast(str, self.rw_engine.c2c_name) - return cast(str, self.ro_engine.c2c_name) + return cast(str, self.rw_engine.c2c_name) # type: ignore + return cast(str, self.ro_engine.c2c_name) # type: ignore - def __call__( + def __call__( # type: ignore self, request: Optional[pyramid.request.Request], readwrite: Optional[bool] = None, **local_kw: Any - ) -> sqlalchemy.orm.Session: + ) -> sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]: if readwrite is not None: if readwrite and not force_readonly: - LOG.debug("Using %s database", self.rw_engine.c2c_name) + LOG.debug("Using %s database", self.rw_engine.c2c_name) # type: ignore self.configure(bind=self.rw_engine) else: - LOG.debug("Using %s database", self.ro_engine.c2c_name) + LOG.debug("Using %s database", self.ro_engine.c2c_name) # type: ignore self.configure(bind=self.ro_engine) else: assert request is not None @@ -237,12 +245,12 @@ def __call__( or any(r.match(method_path) for r in self.slave_paths) ) ): - LOG.debug("Using %s database for: %s", self.ro_engine.c2c_name, method_path) + LOG.debug("Using %s database for: %s", self.ro_engine.c2c_name, method_path) # type: ignore self.configure(bind=self.ro_engine) else: - LOG.debug("Using %s database for: %s", self.rw_engine.c2c_name, method_path) + LOG.debug("Using %s database for: %s", self.rw_engine.c2c_name, method_path) # type: ignore self.configure(bind=self.rw_engine) - return super().__call__(**local_kw) + return super().__call__(**local_kw) # type: ignore def get_engine( @@ -252,7 +260,9 @@ def get_engine( return engine_from_config(settings, prefix) -def get_session_factory(engine: sqlalchemy.engine.Engine) -> sessionmaker: +def get_session_factory( + engine: sqlalchemy.engine.Engine, +) -> sessionmaker[sqlalchemy.orm.Session]: # pylint: disable=unsubscriptable-object """Get the session factory from the engine.""" factory = sessionmaker() factory.configure(bind=engine) @@ -260,7 +270,7 @@ def get_session_factory(engine: sqlalchemy.engine.Engine) -> sessionmaker: def get_tm_session( - session_factory: sessionmaker, + session_factory: sessionmaker[sqlalchemy.orm.Session], # pylint: disable=unsubscriptable-object transaction_manager: transaction.TransactionManager, ) -> sqlalchemy.orm.Session: """ @@ -319,6 +329,7 @@ def get_tm_session( request = dbsession.info["request"] """ dbsession = session_factory() + assert isinstance(dbsession, sqlalchemy.orm.Session), type(dbsession) zope.sqlalchemy.register(dbsession, transaction_manager=transaction_manager) return dbsession @@ -327,7 +338,7 @@ def get_tm_session_pyramid( session_factory: SessionFactory, transaction_manager: transaction.TransactionManager, request: pyramid.request.Request, -) -> sqlalchemy.orm.Session: +) -> sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]: """ Get a ``sqlalchemy.orm.Session`` instance backed by a transaction. @@ -367,13 +378,13 @@ def init( dbengine = settings.get("dbengine") if not dbengine: rw_engine = get_engine(settings, master_prefix + ".") - rw_engine.c2c_name = master_prefix + rw_engine.c2c_name = master_prefix # type: ignore # Setup a slave DB connection and add a tween to use it. if slave_prefix and settings[master_prefix + ".url"] != settings.get(slave_prefix + ".url"): LOG.info("Using a slave DB for reading %s", master_prefix) ro_engine = get_engine(config.get_settings(), slave_prefix + ".") - ro_engine.c2c_name = slave_prefix + ro_engine.c2c_name = slave_prefix # type: ignore else: ro_engine = rw_engine else: @@ -389,6 +400,8 @@ def dbsession(request: pyramid.request.Request) -> sqlalchemy.orm.Session: if dbsession is None: # request.tm is the transaction manager used by pyramid_tm dbsession = get_tm_session_pyramid(session_factory, request.tm, request=request) + assert dbsession is not None + assert isinstance(dbsession, sqlalchemy.orm.Session), type(dbsession) return dbsession config.add_request_method(dbsession, reify=True) diff --git a/c2cwsgiutils/errors.py b/c2cwsgiutils/errors.py index 8ead774b3..f42144f50 100644 --- a/c2cwsgiutils/errors.py +++ b/c2cwsgiutils/errors.py @@ -107,10 +107,11 @@ def _include_dev_details(request: pyramid.request.Request) -> bool: def _integrity_error( exception: sqlalchemy.exc.StatementError, request: pyramid.request.Request ) -> pyramid.response.Response: - def reduce_info_sent(e: sqlalchemy.exc.StatementError) -> None: - # remove details (SQL statement and links to SQLAlchemy) from the error - e.statement = None - e.code = None + def reduce_info_sent(e: Exception) -> None: + if isinstance(e, sqlalchemy.exc.StatementError): + # remove details (SQL statement and links to SQLAlchemy) from the error + e.statement = None + e.code = None return _do_error(request, 400, exception, reduce_info_sent=reduce_info_sent) diff --git a/c2cwsgiutils/health_check.py b/c2cwsgiutils/health_check.py index 183dc2ec7..9bbc87fa0 100644 --- a/c2cwsgiutils/health_check.py +++ b/c2cwsgiutils/health_check.py @@ -22,6 +22,7 @@ import requests import sqlalchemy.engine import sqlalchemy.orm +import sqlalchemy.sql from pyramid.httpexceptions import HTTPNotFound import c2cwsgiutils.db @@ -58,7 +59,7 @@ class _Binding: def name(self) -> str: raise NotImplementedError() - def __enter__(self) -> sqlalchemy.orm.Session: + def __enter__(self) -> sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]: raise NotImplementedError() def __exit__( @@ -78,21 +79,23 @@ def __init__(self, session: c2cwsgiutils.db.SessionFactory, readwrite: bool): def name(self) -> str: return self.session.engine_name(self.readwrite) - def __enter__(self) -> sqlalchemy.orm.Session: + def __enter__(self) -> sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]: return self.session(None, self.readwrite) class _OldBinding(_Binding): - def __init__(self, session: sqlalchemy.orm.scoping.scoped_session, engine: sqlalchemy.engine.Engine): + def __init__( + self, session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], engine: sqlalchemy.engine.Engine + ): self.session = session self.engine = engine self.prev_bind = None def name(self) -> str: - return cast(str, self.engine.c2c_name) + return cast(str, self.engine.c2c_name) # type: ignore - def __enter__(self) -> sqlalchemy.orm.Session: - self.prev_bind = self.session.bind + def __enter__(self) -> sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]: + self.prev_bind = self.session.bind # type: ignore self.session.bind = self.engine return self.session @@ -107,7 +110,7 @@ def __exit__( def _get_binding_class( - session: Union[sqlalchemy.orm.scoping.scoped_session, c2cwsgiutils.db.SessionFactory], + session: Union[sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], c2cwsgiutils.db.SessionFactory], ro_engin: sqlalchemy.engine.Engine, rw_engin: sqlalchemy.engine.Engine, readwrite: bool, @@ -119,15 +122,15 @@ def _get_binding_class( def _get_bindings( - session: Union[sqlalchemy.orm.scoping.scoped_session, c2cwsgiutils.db.SessionFactory], + session: Union[sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], c2cwsgiutils.db.SessionFactory], engine_type: EngineType, -) -> List[sqlalchemy.engine.Engine]: +) -> List[_Binding]: if isinstance(session, c2cwsgiutils.db.SessionFactory): ro_engin = session.ro_engine rw_engin = session.rw_engine else: - ro_engin = session.c2c_ro_bind - rw_engin = session.c2c_rw_bind + ro_engin = session.c2c_ro_bind # type: ignore + rw_engin = session.c2c_rw_bind # type: ignore if rw_engin == ro_engin: engine_type = EngineType.WRITE_ONLY @@ -192,8 +195,8 @@ def __init__(self, config: pyramid.config.Configurator) -> None: def add_db_session_check( self, - session: Union[sqlalchemy.orm.scoping.scoped_session, c2cwsgiutils.db.SessionFactory], - query_cb: Optional[Callable[[sqlalchemy.orm.scoping.scoped_session], Any]] = None, + session: Union[sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], c2cwsgiutils.db.SessionFactory], + query_cb: Optional[Callable[[sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]], Any]] = None, at_least_one_model: Optional[object] = None, level: int = 1, engine_type: EngineType = EngineType.READ_AND_WRITE, @@ -220,7 +223,7 @@ def add_db_session_check( def add_alembic_check( self, - session: Union[sqlalchemy.orm.scoping.scoped_session, c2cwsgiutils.db.SessionFactory], + session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], alembic_ini_path: str, level: int = 2, name: str = "alembic", @@ -249,17 +252,21 @@ def add_alembic_check( if version_schema is None: version_schema = config.get(name, "version_table_schema", fallback="public") + assert version_schema if version_table is None: version_table = config.get(name, "version_table", fallback="alembic_version") + assert version_table class _Check: - def __init__(self, session: sqlalchemy.orm.scoping.scoped_session) -> None: + def __init__(self, session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]) -> None: self.session = session def __call__(self, request: pyramid.request.Request) -> str: + assert version_schema + assert version_table for binding in _get_bindings(self.session, EngineType.READ_AND_WRITE): - with binding as session: + with binding as binded_session: if stats.USE_TAGS: key = ["sql", "manual", "health_check", "alembic"] tags: Optional[Dict[str, str]] = {"conf": alembic_ini_path, "con": binding.name()} @@ -274,11 +281,15 @@ def __call__(self, request: pyramid.request.Request) -> str: ] tags = None with stats.timer_context(key, tags): - quote = session.bind.dialect.identifier_preparer.quote - (actual_version,) = session.execute( - "SELECT version_num FROM " # nosec - f"{quote(version_schema)}.{quote(version_table)}" + result = binded_session.execute( + sqlalchemy.text( + "SELECT version_num FROM " # nosec + f"{sqlalchemy.sql.quoted_name(version_schema, True)}." + f"{sqlalchemy.sql.quoted_name(version_table, True)}" + ) ).fetchone() + assert result is not None + (actual_version,) = result if stats.USE_TAGS: stats.increment_counter( ["alembic_version"], 1, tags={"version": actual_version, "name": name} @@ -492,7 +503,7 @@ def _run_one( @staticmethod def _create_db_engine_check( binding: _Binding, - query_cb: Callable[[sqlalchemy.orm.scoping.scoped_session], None], + query_cb: Callable[[sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]], None], ) -> Tuple[str, Callable[[pyramid.request.Request], None]]: def check(request: pyramid.request.Request) -> None: with binding as session: @@ -508,8 +519,8 @@ def check(request: pyramid.request.Request) -> None: return "db_engine_" + binding.name(), check @staticmethod - def _at_least_one(model: Any) -> Callable[[sqlalchemy.orm.scoping.scoped_session], Any]: - def query(session: sqlalchemy.orm.scoping.scoped_session) -> None: + def _at_least_one(model: Any) -> Callable[[sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]], Any]: + def query(session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session]) -> None: result = session.query(model).first() if result is None: raise HTTPNotFound(model.__name__ + " record not found") diff --git a/c2cwsgiutils/models_graph.py b/c2cwsgiutils/models_graph.py index 2f494c9f8..fc0e3e24f 100644 --- a/c2cwsgiutils/models_graph.py +++ b/c2cwsgiutils/models_graph.py @@ -71,7 +71,7 @@ def _get_all_cols(symbol: Any) -> List[str]: # Those are not fields pass elif isinstance(member, sa.sql.schema.SchemaItem): - cols.append(member_name + ("[null]" if member.nullable else "")) + cols.append(member_name + ("[null]" if member.nullable else "")) # type: ignore elif isinstance(member, sa.orm.attributes.InstrumentedAttribute): nullable = ( member.property.columns[0].nullable diff --git a/c2cwsgiutils/request_tracking/_sql.py b/c2cwsgiutils/request_tracking/_sql.py index fd151b7ef..e06d78222 100644 --- a/c2cwsgiutils/request_tracking/_sql.py +++ b/c2cwsgiutils/request_tracking/_sql.py @@ -8,7 +8,9 @@ def _add_session_id(session: Session, _transaction: Any, _connection: Any) -> None: request = get_current_request() if request is not None: - session.execute("set application_name=:session_id", params={"session_id": request.c2c_request_id}) + session.execute( + sqlalchemy.text("set application_name=:session_id"), params={"session_id": request.c2c_request_id} + ) def init() -> None: diff --git a/c2cwsgiutils/scripts/stats_db.py b/c2cwsgiutils/scripts/stats_db.py index 66545a7d1..cea445e9d 100755 --- a/c2cwsgiutils/scripts/stats_db.py +++ b/c2cwsgiutils/scripts/stats_db.py @@ -99,16 +99,27 @@ def report_error(self) -> None: raise self._error -def do_table(session: sqlalchemy.orm.scoped_session, schema: str, table: str, reporter: Reporter) -> None: +def do_table( + session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], + schema: str, + table: str, + reporter: Reporter, +) -> None: """Do the stats on a table.""" _do_table_count(reporter, schema, session, table) _do_table_size(reporter, schema, session, table) _do_indexes(reporter, schema, session, table) -def _do_indexes(reporter: Reporter, schema: str, session: sqlalchemy.orm.scoped_session, table: str) -> None: +def _do_indexes( + reporter: Reporter, + schema: str, + session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], + table: str, +) -> None: for index_name, size_main, size_fsm, number_of_scans, tuples_read, tuples_fetched in session.execute( - """ + sqlalchemy.text( + """ SELECT foo.indexname, pg_relation_size(concat(quote_ident(foo.schemaname), '.', quote_ident(foo.indexrelname)), 'main'), @@ -127,7 +138,8 @@ def _do_indexes(reporter: Reporter, schema: str, session: sqlalchemy.orm.scoped_ ) AS foo ON t.tablename = foo.ctablename AND t.schemaname=foo.schemaname WHERE t.schemaname=:schema AND t.tablename=:table - """, + """ + ), params={"schema": schema, "table": table}, ): for fork, value in (("main", size_main), ("fsm", size_fsm)): @@ -147,37 +159,53 @@ def _do_indexes(reporter: Reporter, schema: str, session: sqlalchemy.orm.scoped_ def _do_table_size( - reporter: Reporter, schema: str, session: sqlalchemy.orm.scoped_session, table: str + reporter: Reporter, + schema: str, + session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], + table: str, ) -> None: - size: int = 0 - (size,) = session.execute( - """ + result = session.execute( + sqlalchemy.text( + """ SELECT pg_table_size(c.oid) AS total_bytes FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE relkind = 'r' AND nspname=:schema AND relname=:table - """, + """ + ), params={"schema": schema, "table": table}, ).fetchone() + assert result is not None + size: int + (size,) = result reporter.do_report([schema, table], size, kind="size", tags={"schema": schema, "table": table}) def _do_table_count( - reporter: Reporter, schema: str, session: sqlalchemy.orm.scoped_session, table: str + reporter: Reporter, + schema: str, + session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], + table: str, ) -> None: - quote = session.bind.dialect.identifier_preparer.quote # We request and estimation of the count as a real count is very slow on big tables # and seems to cause replicatin lags. This estimate is updated on ANALYZE and VACUUM. - (count,) = session.execute( - "SELECT reltuples::bigint AS count FROM pg_class " # nosec - f"WHERE oid = '{quote(schema)}.{quote(table)}'::regclass;" + result = session.execute( + sqlalchemy.text( # nosec + "SELECT reltuples::bigint AS count FROM pg_class " + f"WHERE oid = '{sqlalchemy.sql.quoted_name(schema, True)}." + f"{sqlalchemy.sql.quoted_name(table, True)}'::regclass;" + ) ).fetchone() + assert result is not None + (count,) = result reporter.do_report([schema, table], count, kind="count", tags={"schema": schema, "table": table}) -def do_extra(session: sqlalchemy.orm.scoped_session, extra: str, reporter: Reporter) -> None: +def do_extra( + session: sqlalchemy.orm.scoped_session[sqlalchemy.orm.Session], extra: str, reporter: Reporter +) -> None: """Do an extra report.""" - for metric, count in session.execute(extra): + for metric, count in session.execute(sqlalchemy.text(extra)): reporter.do_report(str(metric).split("."), count, kind="count", tags={"metric": metric}) @@ -193,12 +221,14 @@ def _do_dtats_db(args: argparse.Namespace) -> None: raise tables = session.execute( - """ + sqlalchemy.text( + """ SELECT table_schema, table_name FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_schema IN :schemas - """, + """ + ), params={"schemas": tuple(args.schema)}, - ) + ).fetchall() for schema, table in tables: LOG.info("Process table %s.%s.", schema, table) try: diff --git a/c2cwsgiutils/sql_profiler/_impl.py b/c2cwsgiutils/sql_profiler/_impl.py index 24c7f25b8..4338bbd47 100644 --- a/c2cwsgiutils/sql_profiler/_impl.py +++ b/c2cwsgiutils/sql_profiler/_impl.py @@ -45,7 +45,12 @@ def profile( LOG.info("parameters: %s", repr(parameters)) with conn.engine.begin() as c: output = "\n ".join( - [row[0] for row in c.execute("EXPLAIN ANALYZE " + statement, parameters)] + [ + row[0] + for row in c.execute( + sqlalchemy.text(f"EXPLAIN ANALYZE {statement}"), parameters + ) + ] ) LOG.info(output) except Exception: # nosec # pylint: disable=broad-except diff --git a/c2cwsgiutils/sqlalchemylogger/_models.py b/c2cwsgiutils/sqlalchemylogger/_models.py index 4bac635c8..fd3692c4d 100644 --- a/c2cwsgiutils/sqlalchemylogger/_models.py +++ b/c2cwsgiutils/sqlalchemylogger/_models.py @@ -21,7 +21,10 @@ class Log(Base): # type: ignore level = Column(String) # info, debug, or error? trace = Column(String) # the full traceback printout msg = Column(String) # any custom log you may have included - created_at = Column(DateTime, default=func.now()) # the current timestamp + created_at = Column( # the current timestamp + DateTime, + default=func.now(), # pylint: disable=not-callable + ) def __init__(self, logger: Any = None, level: Any = None, trace: Any = None, msg: Any = None) -> None: self.logger = logger diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index ffd852731..99041a563 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -98,9 +98,11 @@ def create_db(self) -> None: if not isinstance(self.Log.__table_args__, type(None)) and self.Log.__table_args__.get( "schema", None ): - if not self.engine.dialect.has_schema(self.engine, self.Log.__table_args__["schema"]): - with self.engine.begin() as connection: - connection.execute(sqlalchemy.schema.CreateSchema(self.Log.__table_args__["schema"])) + with self.engine.begin() as connection: + if not self.engine.dialect.has_schema(connection, self.Log.__table_args__["schema"]): + connection.execute( + sqlalchemy.schema.CreateSchema(self.Log.__table_args__["schema"]), # type: ignore + ) Base.metadata.create_all(self.engine) def emit(self, record: Any) -> None: diff --git a/pyproject.toml b/pyproject.toml index e03436d30..0164a3a04 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -183,3 +183,4 @@ format-jinja = """ [tool.poetry-plugin-tweak-dependencies-version] default = "present" +sqlalchemy = ">=1.4.0,<3.0.0"