diff --git a/aurweb/db.py b/aurweb/db.py index 8311f2be..acd2ba41 100644 --- a/aurweb/db.py +++ b/aurweb/db.py @@ -2,6 +2,17 @@ DRIVERS = {"mysql": "mysql+mysqldb"} +class Committer: + def __init__(self, session): + self.session = session + + def __enter__(self): + pass + + def __exit__(self, *args): + self.session.commit() + + def make_random_value(table: str, column: str, length: int): """Generate a unique, random value for a string column in a table. @@ -76,9 +87,7 @@ def get_session(engine=None): if not engine: # pragma: no cover engine = get_engine() - Session = scoped_session( - sessionmaker(autocommit=True, autoflush=False, bind=engine) - ) + Session = scoped_session(sessionmaker(autoflush=False, bind=engine)) _sessions[dbname] = Session() return _sessions.get(dbname) @@ -158,7 +167,7 @@ def add(model): def begin(): """Begin an SQLAlchemy SessionTransaction.""" - return get_session().begin() + return Committer(get_session()) def retry_deadlock(func): @@ -217,7 +226,7 @@ def get_sqlalchemy_url(): parts = sqlalchemy.__version__.split(".") major = int(parts[0]) minor = int(parts[1]) - if major == 1 and minor >= 4: # pragma: no cover + if (major == 1 and minor >= 4) or (major == 2): # pragma: no cover constructor = URL.create aur_db_backend = aurweb.config.get("database", "backend") diff --git a/aurweb/initdb.py b/aurweb/initdb.py index ee59212c..d1617bc0 100644 --- a/aurweb/initdb.py +++ b/aurweb/initdb.py @@ -59,7 +59,8 @@ def run(args): engine = aurweb.db.get_engine(echo=(args.verbose >= 1)) aurweb.schema.metadata.create_all(engine) conn = engine.connect() - feed_initial_data(conn) + with conn.begin(): + feed_initial_data(conn) conn.close() if args.use_alembic: diff --git a/aurweb/models/declarative.py b/aurweb/models/declarative.py index 22df31c7..b39605eb 100644 --- a/aurweb/models/declarative.py +++ b/aurweb/models/declarative.py @@ -1,6 +1,6 @@ import json -from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import declarative_base from aurweb import util diff --git a/aurweb/packages/search.py b/aurweb/packages/search.py index 78b27a9a..a28f38af 100644 --- a/aurweb/packages/search.py +++ b/aurweb/packages/search.py @@ -210,7 +210,7 @@ class PackageSearch: # in terms of performance. We should improve this; there's no # reason it should take _longer_. column = getattr( - case([(models.PackageVote.UsersID == self.user.ID, 1)], else_=0), order + case((models.PackageVote.UsersID == self.user.ID, 1), else_=0), order ) name = getattr(models.Package.Name, order) self.query = self.query.order_by(column(), name()) @@ -221,7 +221,7 @@ class PackageSearch: # in terms of performance. We should improve this; there's no # reason it should take _longer_. column = getattr( - case([(models.PackageNotification.UserID == self.user.ID, 1)], else_=0), + case((models.PackageNotification.UserID == self.user.ID, 1), else_=0), order, ) name = getattr(models.Package.Name, order) diff --git a/aurweb/routers/html.py b/aurweb/routers/html.py index 63cc3bb8..6c8c8e55 100644 --- a/aurweb/routers/html.py +++ b/aurweb/routers/html.py @@ -145,7 +145,7 @@ async def index(request: Request): .order_by( # Order primarily by the Status column being PENDING_ID, # and secondarily by RequestTS; both in descending order. - case([(models.PackageRequest.Status == PENDING_ID, 1)], else_=0).desc(), + case((models.PackageRequest.Status == PENDING_ID, 1), else_=0).desc(), models.PackageRequest.RequestTS.desc(), ) .limit(50) diff --git a/aurweb/routers/requests.py b/aurweb/routers/requests.py index a67419fe..fe058a9a 100644 --- a/aurweb/routers/requests.py +++ b/aurweb/routers/requests.py @@ -110,7 +110,7 @@ async def requests( # noqa: C901 filtered.order_by( # Order primarily by the Status column being PENDING_ID, # and secondarily by RequestTS; both in descending order. - case([(PackageRequest.Status == PENDING_ID, 1)], else_=0).desc(), + case((PackageRequest.Status == PENDING_ID, 1), else_=0).desc(), PackageRequest.RequestTS.desc(), ) .limit(PP) diff --git a/aurweb/testing/__init__.py b/aurweb/testing/__init__.py index 4451eb3a..4f60b5ff 100644 --- a/aurweb/testing/__init__.py +++ b/aurweb/testing/__init__.py @@ -1,3 +1,5 @@ +from sqlalchemy import text + import aurweb.db from aurweb import models @@ -56,8 +58,10 @@ def setup_test_db(*args): models.User.__tablename__, ] - aurweb.db.get_session().execute("SET FOREIGN_KEY_CHECKS = 0") + session = aurweb.db.get_session() + session.execute(text("SET FOREIGN_KEY_CHECKS = 0")) for table in tables: - aurweb.db.get_session().execute(f"DELETE FROM {table}") - aurweb.db.get_session().execute("SET FOREIGN_KEY_CHECKS = 1") - aurweb.db.get_session().expunge_all() + session.execute(text(f"DELETE FROM {table}")) + session.execute(text("SET FOREIGN_KEY_CHECKS = 1")) + session.expunge_all() + session.commit() diff --git a/poetry.lock b/poetry.lock index 623884a0..5df41fbf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "aiofiles" version = "23.1.0" description = "File support for asyncio." -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -16,7 +15,6 @@ files = [ name = "alembic" version = "1.11.2" description = "A database migration tool for SQLAlchemy." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -36,7 +34,6 @@ tz = ["python-dateutil"] name = "anyio" version = "3.6.2" description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "main" optional = false python-versions = ">=3.6.2" files = [ @@ -57,7 +54,6 @@ trio = ["trio (>=0.16,<0.22)"] name = "asgiref" version = "3.7.2" description = "ASGI specs, helper code, and adapters" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -75,7 +71,6 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] name = "async-timeout" version = "4.0.2" description = "Timeout context manager for asyncio programs" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -87,7 +82,6 @@ files = [ name = "authlib" version = "1.2.1" description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients." -category = "main" optional = false python-versions = "*" files = [ @@ -102,7 +96,6 @@ cryptography = ">=3.2" name = "bcrypt" version = "4.0.1" description = "Modern password hashing for your software and your servers" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -137,7 +130,6 @@ typecheck = ["mypy"] name = "bleach" version = "6.0.0" description = "An easy safelist-based HTML-sanitizing tool." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -156,7 +148,6 @@ css = ["tinycss2 (>=1.1.0,<1.2)"] name = "certifi" version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -168,7 +159,6 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." -category = "main" optional = false python-versions = "*" files = [ @@ -245,7 +235,6 @@ pycparser = "*" name = "charset-normalizer" version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -330,7 +319,6 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -345,7 +333,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -357,7 +344,6 @@ files = [ name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -433,7 +419,6 @@ toml = ["tomli"] name = "cryptography" version = "40.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -475,7 +460,6 @@ tox = ["tox"] name = "dnspython" version = "2.3.0" description = "DNS toolkit" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -496,7 +480,6 @@ wmi = ["wmi (>=1.5.1,<2.0.0)"] name = "email-validator" version = "2.0.0.post2" description = "A robust email address syntax and deliverability validation library." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -512,7 +495,6 @@ idna = ">=2.0.0" name = "exceptiongroup" version = "1.1.1" description = "Backport of PEP 654 (exception groups)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -527,7 +509,6 @@ test = ["pytest (>=6)"] name = "execnet" version = "1.9.0" description = "execnet: rapid multi-Python deployment" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -542,7 +523,6 @@ testing = ["pre-commit"] name = "fakeredis" version = "2.17.0" description = "Python implementation of redis API, can be used for testing purposes." -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -562,7 +542,6 @@ lua = ["lupa (>=1.14,<2.0)"] name = "fastapi" version = "0.100.1" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -582,7 +561,6 @@ all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)" name = "feedgen" version = "0.9.0" description = "Feed Generator (ATOM, RSS, Podcasts)" -category = "main" optional = false python-versions = "*" files = [ @@ -597,7 +575,6 @@ python-dateutil = "*" name = "filelock" version = "3.12.2" description = "A platform independent file lock." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -613,7 +590,6 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p name = "greenlet" version = "2.0.2" description = "Lightweight in-process concurrent programming" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" files = [ @@ -687,7 +663,6 @@ test = ["objgraph", "psutil"] name = "gunicorn" version = "21.2.0" description = "WSGI HTTP Server for UNIX" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -708,7 +683,6 @@ tornado = ["tornado (>=0.2)"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -720,7 +694,6 @@ files = [ name = "h2" version = "4.1.0" description = "HTTP/2 State-Machine based protocol implementation" -category = "main" optional = false python-versions = ">=3.6.1" files = [ @@ -736,7 +709,6 @@ hyperframe = ">=6.0,<7" name = "hpack" version = "4.0.0" description = "Pure-Python HPACK header compression" -category = "main" optional = false python-versions = ">=3.6.1" files = [ @@ -748,7 +720,6 @@ files = [ name = "httpcore" version = "0.17.0" description = "A minimal low-level HTTP client." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -760,17 +731,16 @@ files = [ anyio = ">=3.0,<5.0" certifi = "*" h11 = ">=0.13,<0.15" -sniffio = ">=1.0.0,<2.0.0" +sniffio = "==1.*" [package.extras] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] [[package]] name = "httpx" version = "0.24.1" description = "The next generation HTTP client." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -786,15 +756,14 @@ sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] -cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] [[package]] name = "hypercorn" version = "0.14.4" description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -819,7 +788,6 @@ uvloop = ["uvloop"] name = "hyperframe" version = "6.0.1" description = "HTTP/2 framing layer for Python" -category = "main" optional = false python-versions = ">=3.6.1" files = [ @@ -831,7 +799,6 @@ files = [ name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -843,7 +810,6 @@ files = [ name = "importlib-metadata" version = "6.6.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -863,7 +829,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -875,7 +840,6 @@ files = [ name = "itsdangerous" version = "2.1.2" description = "Safely pass data to untrusted environments and back." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -887,7 +851,6 @@ files = [ name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -905,7 +868,6 @@ i18n = ["Babel (>=2.7)"] name = "lxml" version = "4.9.3" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" files = [ @@ -1013,7 +975,6 @@ source = ["Cython (>=0.29.35)"] name = "mako" version = "1.2.4" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1033,7 +994,6 @@ testing = ["pytest"] name = "markdown" version = "3.4.4" description = "Python implementation of John Gruber's Markdown." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1052,7 +1012,6 @@ testing = ["coverage", "pyyaml"] name = "markupsafe" version = "2.1.2" description = "Safely add untrusted strings to HTML/XML markup." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1112,7 +1071,6 @@ files = [ name = "mysqlclient" version = "2.2.0" description = "Python interface to MySQL" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1129,7 +1087,6 @@ files = [ name = "orjson" version = "3.9.2" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1185,7 +1142,6 @@ files = [ name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1197,7 +1153,6 @@ files = [ name = "paginate" version = "0.5.6" description = "Divides large result sets into pages for easier browsing" -category = "main" optional = false python-versions = "*" files = [ @@ -1208,7 +1163,6 @@ files = [ name = "parse" version = "1.19.0" description = "parse() is the opposite of format()" -category = "main" optional = false python-versions = "*" files = [ @@ -1220,7 +1174,6 @@ files = [ name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1236,7 +1189,6 @@ testing = ["pytest", "pytest-benchmark"] name = "posix-ipc" version = "1.1.1" description = "POSIX IPC primitives (semaphores, shared memory and message queues) for Python" -category = "main" optional = false python-versions = "*" files = [ @@ -1252,7 +1204,6 @@ files = [ name = "priority" version = "2.0.0" description = "A pure-Python implementation of the HTTP/2 priority tree" -category = "main" optional = false python-versions = ">=3.6.1" files = [ @@ -1264,7 +1215,6 @@ files = [ name = "prometheus-client" version = "0.16.0" description = "Python client for the Prometheus monitoring system." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1279,7 +1229,6 @@ twisted = ["twisted"] name = "prometheus-fastapi-instrumentator" version = "6.1.0" description = "Instrument your FastAPI with Prometheus metrics." -category = "main" optional = false python-versions = ">=3.7.0,<4.0.0" files = [ @@ -1295,7 +1244,6 @@ prometheus-client = ">=0.8.0,<1.0.0" name = "protobuf" version = "4.23.4" description = "" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1318,7 +1266,6 @@ files = [ name = "pyalpm" version = "0.10.6" description = "libalpm bindings for Python 3" -category = "main" optional = false python-versions = "*" files = [ @@ -1329,7 +1276,6 @@ files = [ name = "pycparser" version = "2.21" description = "C parser in Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1341,7 +1287,6 @@ files = [ name = "pydantic" version = "1.10.7" description = "Data validation and settings management using python type hints" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1394,7 +1339,6 @@ email = ["email-validator (>=1.0.3)"] name = "pygit2" version = "1.12.2" description = "Python bindings for libgit2." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1438,7 +1382,6 @@ cffi = ">=1.9.1" name = "pytest" version = "7.4.0" description = "pytest: simple powerful testing with Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1461,7 +1404,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-asyncio" version = "0.21.1" description = "Pytest support for asyncio" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1480,7 +1422,6 @@ testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1499,7 +1440,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-tap" version = "3.4" description = "Test Anything Protocol (TAP) reporting plugin for pytest" -category = "dev" optional = false python-versions = "*" files = [ @@ -1515,7 +1455,6 @@ pytest = ">=3.0" name = "pytest-xdist" version = "3.3.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1536,7 +1475,6 @@ testing = ["filelock"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1551,7 +1489,6 @@ six = ">=1.5" name = "python-multipart" version = "0.0.6" description = "A streaming multipart parser for Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1566,7 +1503,6 @@ dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatc name = "redis" version = "4.6.0" description = "Python client for Redis database and key-value store" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1585,7 +1521,6 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)" name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1607,7 +1542,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1619,7 +1553,6 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1631,7 +1564,6 @@ files = [ name = "sortedcontainers" version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -category = "main" optional = false python-versions = "*" files = [ @@ -1641,81 +1573,86 @@ files = [ [[package]] name = "sqlalchemy" -version = "1.4.49" +version = "2.0.17" description = "Database Abstraction Library" -category = "main" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-1.4.49-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e126cf98b7fd38f1e33c64484406b78e937b1a280e078ef558b95bf5b6895f6"}, - {file = "SQLAlchemy-1.4.49-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:03db81b89fe7ef3857b4a00b63dedd632d6183d4ea5a31c5d8a92e000a41fc71"}, - {file = "SQLAlchemy-1.4.49-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:95b9df9afd680b7a3b13b38adf6e3a38995da5e162cc7524ef08e3be4e5ed3e1"}, - {file = "SQLAlchemy-1.4.49-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a63e43bf3f668c11bb0444ce6e809c1227b8f067ca1068898f3008a273f52b09"}, - {file = "SQLAlchemy-1.4.49-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f835c050ebaa4e48b18403bed2c0fda986525896efd76c245bdd4db995e51a4c"}, - {file = "SQLAlchemy-1.4.49-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c21b172dfb22e0db303ff6419451f0cac891d2e911bb9fbf8003d717f1bcf91"}, - {file = "SQLAlchemy-1.4.49-cp310-cp310-win32.whl", hash = "sha256:5fb1ebdfc8373b5a291485757bd6431de8d7ed42c27439f543c81f6c8febd729"}, - {file = "SQLAlchemy-1.4.49-cp310-cp310-win_amd64.whl", hash = "sha256:f8a65990c9c490f4651b5c02abccc9f113a7f56fa482031ac8cb88b70bc8ccaa"}, - {file = "SQLAlchemy-1.4.49-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8923dfdf24d5aa8a3adb59723f54118dd4fe62cf59ed0d0d65d940579c1170a4"}, - {file = "SQLAlchemy-1.4.49-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9ab2c507a7a439f13ca4499db6d3f50423d1d65dc9b5ed897e70941d9e135b0"}, - {file = "SQLAlchemy-1.4.49-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5debe7d49b8acf1f3035317e63d9ec8d5e4d904c6e75a2a9246a119f5f2fdf3d"}, - {file = "SQLAlchemy-1.4.49-cp311-cp311-win32.whl", hash = "sha256:82b08e82da3756765c2e75f327b9bf6b0f043c9c3925fb95fb51e1567fa4ee87"}, - {file = "SQLAlchemy-1.4.49-cp311-cp311-win_amd64.whl", hash = "sha256:171e04eeb5d1c0d96a544caf982621a1711d078dbc5c96f11d6469169bd003f1"}, - {file = "SQLAlchemy-1.4.49-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:36e58f8c4fe43984384e3fbe6341ac99b6b4e083de2fe838f0fdb91cebe9e9cb"}, - {file = "SQLAlchemy-1.4.49-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b31e67ff419013f99ad6f8fc73ee19ea31585e1e9fe773744c0f3ce58c039c30"}, - {file = "SQLAlchemy-1.4.49-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c14b29d9e1529f99efd550cd04dbb6db6ba5d690abb96d52de2bff4ed518bc95"}, - {file = "SQLAlchemy-1.4.49-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c40f3470e084d31247aea228aa1c39bbc0904c2b9ccbf5d3cfa2ea2dac06f26d"}, - {file = "SQLAlchemy-1.4.49-cp36-cp36m-win32.whl", hash = "sha256:706bfa02157b97c136547c406f263e4c6274a7b061b3eb9742915dd774bbc264"}, - {file = "SQLAlchemy-1.4.49-cp36-cp36m-win_amd64.whl", hash = "sha256:a7f7b5c07ae5c0cfd24c2db86071fb2a3d947da7bd487e359cc91e67ac1c6d2e"}, - {file = "SQLAlchemy-1.4.49-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:4afbbf5ef41ac18e02c8dc1f86c04b22b7a2125f2a030e25bbb4aff31abb224b"}, - {file = "SQLAlchemy-1.4.49-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24e300c0c2147484a002b175f4e1361f102e82c345bf263242f0449672a4bccf"}, - {file = "SQLAlchemy-1.4.49-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:201de072b818f8ad55c80d18d1a788729cccf9be6d9dc3b9d8613b053cd4836d"}, - {file = "SQLAlchemy-1.4.49-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7653ed6817c710d0c95558232aba799307d14ae084cc9b1f4c389157ec50df5c"}, - {file = "SQLAlchemy-1.4.49-cp37-cp37m-win32.whl", hash = "sha256:647e0b309cb4512b1f1b78471fdaf72921b6fa6e750b9f891e09c6e2f0e5326f"}, - {file = "SQLAlchemy-1.4.49-cp37-cp37m-win_amd64.whl", hash = "sha256:ab73ed1a05ff539afc4a7f8cf371764cdf79768ecb7d2ec691e3ff89abbc541e"}, - {file = "SQLAlchemy-1.4.49-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:37ce517c011560d68f1ffb28af65d7e06f873f191eb3a73af5671e9c3fada08a"}, - {file = "SQLAlchemy-1.4.49-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1878ce508edea4a879015ab5215546c444233881301e97ca16fe251e89f1c55"}, - {file = "SQLAlchemy-1.4.49-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e8e608983e6f85d0852ca61f97e521b62e67969e6e640fe6c6b575d4db68557"}, - {file = "SQLAlchemy-1.4.49-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccf956da45290df6e809ea12c54c02ace7f8ff4d765d6d3dfb3655ee876ce58d"}, - {file = "SQLAlchemy-1.4.49-cp38-cp38-win32.whl", hash = "sha256:f167c8175ab908ce48bd6550679cc6ea20ae169379e73c7720a28f89e53aa532"}, - {file = "SQLAlchemy-1.4.49-cp38-cp38-win_amd64.whl", hash = "sha256:45806315aae81a0c202752558f0df52b42d11dd7ba0097bf71e253b4215f34f4"}, - {file = "SQLAlchemy-1.4.49-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:b6d0c4b15d65087738a6e22e0ff461b407533ff65a73b818089efc8eb2b3e1de"}, - {file = "SQLAlchemy-1.4.49-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a843e34abfd4c797018fd8d00ffffa99fd5184c421f190b6ca99def4087689bd"}, - {file = "SQLAlchemy-1.4.49-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1c890421651b45a681181301b3497e4d57c0d01dc001e10438a40e9a9c25ee77"}, - {file = "SQLAlchemy-1.4.49-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d26f280b8f0a8f497bc10573849ad6dc62e671d2468826e5c748d04ed9e670d5"}, - {file = "SQLAlchemy-1.4.49-cp39-cp39-win32.whl", hash = "sha256:ec2268de67f73b43320383947e74700e95c6770d0c68c4e615e9897e46296294"}, - {file = "SQLAlchemy-1.4.49-cp39-cp39-win_amd64.whl", hash = "sha256:bbdf16372859b8ed3f4d05f925a984771cd2abd18bd187042f24be4886c2a15f"}, - {file = "SQLAlchemy-1.4.49.tar.gz", hash = "sha256:06ff25cbae30c396c4b7737464f2a7fc37a67b7da409993b182b024cec80aed9"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:04383f1e3452f6739084184e427e9d5cb4e68ddc765d52157bf5ef30d5eca14f"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:724355973297bbe547f3eb98b46ade65a67a3d5a6303f17ab59a2dc6fb938943"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf07ff9920cb3ca9d73525dfd4f36ddf9e1a83734ea8b4f724edfd9a2c6e82d9"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f389f77c68dc22cb51f026619291c4a38aeb4b7ecb5f998fd145b2d81ca513"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba03518e64d86f000dc24ab3d3a1aa876bcbaa8aa15662ac2df5e81537fa3394"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:218fb20c01e95004f50a3062bf4c447dcb360cab8274232f31947e254f118298"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-win32.whl", hash = "sha256:b47be4c6281a86670ea5cfbbbe6c3a65366a8742f5bc8b986f790533c60b5ddb"}, + {file = "SQLAlchemy-2.0.17-cp310-cp310-win_amd64.whl", hash = "sha256:74ddcafb6488f382854a7da851c404c394be3729bb3d91b02ad86c5458140eff"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:51736cfb607cf4e8fafb693906f9bc4e5ee55be0b096d44bd7f20cd8489b8571"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8741d3d401383e54b2aada37cbd10f55c5d444b360eae3a82f74a2be568a7710"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ead58cae2a089eee1b0569060999cb5f2b2462109498a0937cc230a7556945a1"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f40e3a7d0a464f1c8593f2991e5520b2f5b26da24e88000bbd4423f86103d4f"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:21583808d37f126a647652c90332ac1d3a102edf3c94bcc3319edcc0ea2300cc"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f593170fc09c5abb1205a738290b39532f7380094dc151805009a07ae0e85330"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-win32.whl", hash = "sha256:b0eaf82cc844f6b46defe15ad243ea00d1e39ed3859df61130c263dc7204da6e"}, + {file = "SQLAlchemy-2.0.17-cp311-cp311-win_amd64.whl", hash = "sha256:1822620c89779b85f7c23d535c8e04b79c517739ae07aaed48c81e591ed5498e"}, + {file = "SQLAlchemy-2.0.17-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2269b1f9b8be47e52b70936069a25a3771eff53367aa5cc59bb94f28a6412e13"}, + {file = "SQLAlchemy-2.0.17-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48111d56afea5699bab72c38ec95561796b81befff9e13d1dd5ce251ab25f51d"}, + {file = "SQLAlchemy-2.0.17-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28da17059ecde53e2d10ba813d38db942b9f6344360b2958b25872d5cb729d35"}, + {file = "SQLAlchemy-2.0.17-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:48b40dc2895841ea89d89df9eb3ac69e2950a659db20a369acf4259f68e6dc1f"}, + {file = "SQLAlchemy-2.0.17-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7f31d4e7ca1dd8ca5a27fd5eaa0f9e2732fe769ff7dd35bf7bba179597e4df07"}, + {file = "SQLAlchemy-2.0.17-cp37-cp37m-win32.whl", hash = "sha256:7830e01b02d440c27f2a5be68296e74ccb55e6a5b5962ffafd360b98930b2e5e"}, + {file = "SQLAlchemy-2.0.17-cp37-cp37m-win_amd64.whl", hash = "sha256:234678ed6576531b8e4be255b980f20368bf07241a2e67b84e6b0fe679edb9c4"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c6ff5767d954f6091113fedcaaf49cdec2197ae4c5301fe83d5ae4393c82f33"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa995b21f853864996e4056d9fde479bcecf8b7bff4beb3555eebbbba815f35d"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:125f9f7e62ddf8b590c069729080ffe18b68a20d9882eb0947f72e06274601d7"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b114a16bc03dfe20b625062e456affd7b9938286e05a3f904a025b9aacc29dd4"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf175d26f6787cce30fe6c04303ca0aeeb0ad40eeb22e3391f24b32ec432a1e1"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e2d5c3596254cf1a96474b98e7ce20041c74c008b0f101c1cb4f8261cb77c6d3"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-win32.whl", hash = "sha256:513411d73503a6fc5804f01fae3b3d44f267c1b3a06cfeac02e9286a7330e857"}, + {file = "SQLAlchemy-2.0.17-cp38-cp38-win_amd64.whl", hash = "sha256:40a3dc52b2b16f08b5c16b9ee7646329e4b3411e9280e5e8d57b19eaa51cbef4"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e3189432db2f5753b4fde1aa90a61c69976f4e7e31d1cf4611bfe3514ed07478"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6150560fcffc6aee5ec9a97419ac768c7a9f56baf7a7eb59cb4b1b6a4d463ad9"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910d45bf3673f0e4ef13858674bd23cfdafdc8368b45b948bf511797dbbb401d"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0aeb3afaa19f187a70fa592fbe3c20a056b57662691fd3abf60f016aa5c1848"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:36a87e26fe8fa8c466fae461a8fcb780d0a1cbf8206900759fc6fe874475a3ce"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e3a6b2788f193756076061626679c5c5a6d600ddf8324f986bc72004c3e9d92e"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-win32.whl", hash = "sha256:af7e2ba75bf84b64adb331918188dda634689a2abb151bc1a583e488363fd2f8"}, + {file = "SQLAlchemy-2.0.17-cp39-cp39-win_amd64.whl", hash = "sha256:394ac3adf3676fad76d4b8fcecddf747627f17f0738dc94bac15f303d05b03d4"}, + {file = "SQLAlchemy-2.0.17-py3-none-any.whl", hash = "sha256:cc9c2630c423ac4973492821b2969f5fe99d9736f3025da670095668fbfcd4d5"}, + {file = "SQLAlchemy-2.0.17.tar.gz", hash = "sha256:e186e9e95fb5d993b075c33fe4f38a22105f7ce11cecb5c17b5618181e356702"}, ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and platform_machine == \"aarch64\" or python_version >= \"3\" and platform_machine == \"ppc64le\" or python_version >= \"3\" and platform_machine == \"x86_64\" or python_version >= \"3\" and platform_machine == \"amd64\" or python_version >= \"3\" and platform_machine == \"AMD64\" or python_version >= \"3\" and platform_machine == \"win32\" or python_version >= \"3\" and platform_machine == \"WIN32\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} +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)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] +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)"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] sqlcipher = ["sqlcipher3-binary"] [[package]] name = "srcinfo" version = "0.1.2" description = "A small library to parse .SRCINFO files" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -1730,7 +1667,6 @@ parse = ">=1.19.0,<2.0.0" name = "starlette" version = "0.27.0" description = "The little ASGI library that shines." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1749,7 +1685,6 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyam name = "tap-py" version = "3.1" description = "Test Anything Protocol (TAP) tools" -category = "dev" optional = false python-versions = "*" files = [ @@ -1764,7 +1699,6 @@ yaml = ["PyYAML (>=5.1)", "more-itertools"] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1776,7 +1710,6 @@ files = [ name = "tomlkit" version = "0.12.1" description = "Style preserving TOML library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1788,7 +1721,6 @@ files = [ name = "typing-extensions" version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1800,7 +1732,6 @@ files = [ name = "urllib3" version = "2.0.2" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1818,7 +1749,6 @@ zstd = ["zstandard (>=0.18.0)"] name = "uvicorn" version = "0.23.2" description = "The lightning-fast ASGI server." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1838,7 +1768,6 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", name = "watchfiles" version = "0.19.0" description = "Simple, modern and high performance file watching and code reload in python." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1873,7 +1802,6 @@ anyio = ">=3.0.0" name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" -category = "main" optional = false python-versions = "*" files = [ @@ -1885,7 +1813,6 @@ files = [ name = "werkzeug" version = "2.3.6" description = "The comprehensive WSGI web application library." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1903,7 +1830,6 @@ watchdog = ["watchdog (>=2.3)"] name = "wsproto" version = "1.2.0" description = "WebSockets state-machine based protocol implementation" -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -1918,7 +1844,6 @@ h11 = ">=0.9.0,<1" name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1933,4 +1858,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "ac9dbb5b28292c4a3dd2318a2f5c9120dfaa117ee834fac05995c5d0cbdc460d" +content-hash = "581d8875a6b28f3373d2de7b5ca63f08c58f137edd74bb1c7d2f75ac816d680e" diff --git a/pyproject.toml b/pyproject.toml index 359923a0..cc262620 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ Authlib = "^1.2.0" Jinja2 = "^3.1.2" Markdown = "^3.4.3" Werkzeug = "^2.3.3" -SQLAlchemy = "^1.4.48" +SQLAlchemy = "2.0.17" # ASGI uvicorn = "^0.23.0" diff --git a/test/conftest.py b/test/conftest.py index 15a982aa..acfc1521 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -44,7 +44,7 @@ from multiprocessing import Lock import py import pytest from posix_ipc import O_CREAT, Semaphore -from sqlalchemy import create_engine +from sqlalchemy import create_engine, text from sqlalchemy.engine import URL from sqlalchemy.engine.base import Engine from sqlalchemy.exc import ProgrammingError @@ -106,15 +106,16 @@ def _create_database(engine: Engine, dbname: str) -> None: :param dbname: Database name to create """ conn = engine.connect() - try: - conn.execute(f"CREATE DATABASE {dbname}") - except ProgrammingError: # pragma: no cover - # The database most likely already existed if we hit - # a ProgrammingError. Just drop the database and try - # again. If at that point things still fail, any - # exception will be propogated up to the caller. - conn.execute(f"DROP DATABASE {dbname}") - conn.execute(f"CREATE DATABASE {dbname}") + with conn.begin(): + try: + conn.execute(text(f"CREATE DATABASE {dbname}")) + except ProgrammingError: # pragma: no cover + # The database most likely already existed if we hit + # a ProgrammingError. Just drop the database and try + # again. If at that point things still fail, any + # exception will be propogated up to the caller. + conn.execute(text(f"DROP DATABASE {dbname}")) + conn.execute(text(f"CREATE DATABASE {dbname}")) conn.close() initdb.run(AlembicArgs) @@ -126,9 +127,10 @@ def _drop_database(engine: Engine, dbname: str) -> None: :param engine: Engine returned by test_engine() :param dbname: Database name to drop """ - aurweb.schema.metadata.drop_all(bind=engine) + # aurweb.schema.metadata.drop_all(bind=engine) conn = engine.connect() - conn.execute(f"DROP DATABASE {dbname}") + with conn.begin(): + conn.execute(text(f"DROP DATABASE {dbname}")) conn.close() diff --git a/test/test_initdb.py b/test/test_initdb.py index db5edf74..5d82e385 100644 --- a/test/test_initdb.py +++ b/test/test_initdb.py @@ -24,5 +24,6 @@ def test_run(): aurweb.initdb.run(Args()) # Check that constant table rows got added via initdb. - record = aurweb.db.query(AccountType, AccountType.AccountType == "User").first() + with aurweb.db.begin(): + record = aurweb.db.query(AccountType, AccountType.AccountType == "User").first() assert record is not None diff --git a/test/test_tu_voteinfo.py b/test/test_tu_voteinfo.py index 34845b86..efd989c3 100644 --- a/test/test_tu_voteinfo.py +++ b/test/test_tu_voteinfo.py @@ -1,5 +1,5 @@ import pytest -from sqlalchemy.exc import IntegrityError +from sqlalchemy.exc import IntegrityError, SAWarning from aurweb import db, time from aurweb.db import create, rollback @@ -109,7 +109,7 @@ def test_tu_voteinfo_null_submitter_raises(user: User): def test_tu_voteinfo_null_agenda_raises(user: User): - with pytest.raises(IntegrityError): + with pytest.raises(IntegrityError), pytest.warns(SAWarning): with db.begin(): create( TUVoteInfo, @@ -123,7 +123,7 @@ def test_tu_voteinfo_null_agenda_raises(user: User): def test_tu_voteinfo_null_user_raises(user: User): - with pytest.raises(IntegrityError): + with pytest.raises(IntegrityError), pytest.warns(SAWarning): with db.begin(): create( TUVoteInfo, @@ -137,7 +137,7 @@ def test_tu_voteinfo_null_user_raises(user: User): def test_tu_voteinfo_null_submitted_raises(user: User): - with pytest.raises(IntegrityError): + with pytest.raises(IntegrityError), pytest.warns(SAWarning): with db.begin(): create( TUVoteInfo, @@ -151,7 +151,7 @@ def test_tu_voteinfo_null_submitted_raises(user: User): def test_tu_voteinfo_null_end_raises(user: User): - with pytest.raises(IntegrityError): + with pytest.raises(IntegrityError), pytest.warns(SAWarning): with db.begin(): create( TUVoteInfo,