fix(deps): upgrade to sqlalchemy version 2

Bump sqlalchemy to version 2.0.17

There are quite some changes that happened with v2.
We are currently relying on the "auto-commit" feature which was removed.
For the moment we can use a wrapper class to mimic the auto-commit
behavior allowing us to move to v2.

Ultimately, the (db) session management needs some overhaul though.

Signed-off-by: moson-mo <mo-son@mailbox.org>
This commit is contained in:
moson-mo 2023-06-30 11:05:18 +02:00 committed by moson
parent 9eda6a42c6
commit ec090d7b30
No known key found for this signature in database
GPG key ID: 4A4760AB4EE15296
12 changed files with 112 additions and 170 deletions

View file

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

View file

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

View file

@ -1,6 +1,6 @@
import json
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import declarative_base
from aurweb import util

View file

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

View file

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

View file

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

View file

@ -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()

197
poetry.lock generated
View file

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

View file

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

View file

@ -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()

View file

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

View file

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