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"} 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): def make_random_value(table: str, column: str, length: int):
"""Generate a unique, random value for a string column in a table. """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 if not engine: # pragma: no cover
engine = get_engine() engine = get_engine()
Session = scoped_session( Session = scoped_session(sessionmaker(autoflush=False, bind=engine))
sessionmaker(autocommit=True, autoflush=False, bind=engine)
)
_sessions[dbname] = Session() _sessions[dbname] = Session()
return _sessions.get(dbname) return _sessions.get(dbname)
@ -158,7 +167,7 @@ def add(model):
def begin(): def begin():
"""Begin an SQLAlchemy SessionTransaction.""" """Begin an SQLAlchemy SessionTransaction."""
return get_session().begin() return Committer(get_session())
def retry_deadlock(func): def retry_deadlock(func):
@ -217,7 +226,7 @@ def get_sqlalchemy_url():
parts = sqlalchemy.__version__.split(".") parts = sqlalchemy.__version__.split(".")
major = int(parts[0]) major = int(parts[0])
minor = int(parts[1]) 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 constructor = URL.create
aur_db_backend = aurweb.config.get("database", "backend") 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)) engine = aurweb.db.get_engine(echo=(args.verbose >= 1))
aurweb.schema.metadata.create_all(engine) aurweb.schema.metadata.create_all(engine)
conn = engine.connect() conn = engine.connect()
feed_initial_data(conn) with conn.begin():
feed_initial_data(conn)
conn.close() conn.close()
if args.use_alembic: if args.use_alembic:

View file

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

View file

@ -210,7 +210,7 @@ class PackageSearch:
# in terms of performance. We should improve this; there's no # in terms of performance. We should improve this; there's no
# reason it should take _longer_. # reason it should take _longer_.
column = getattr( 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) name = getattr(models.Package.Name, order)
self.query = self.query.order_by(column(), name()) 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 # in terms of performance. We should improve this; there's no
# reason it should take _longer_. # reason it should take _longer_.
column = getattr( column = getattr(
case([(models.PackageNotification.UserID == self.user.ID, 1)], else_=0), case((models.PackageNotification.UserID == self.user.ID, 1), else_=0),
order, order,
) )
name = getattr(models.Package.Name, order) name = getattr(models.Package.Name, order)

View file

@ -145,7 +145,7 @@ async def index(request: Request):
.order_by( .order_by(
# Order primarily by the Status column being PENDING_ID, # Order primarily by the Status column being PENDING_ID,
# and secondarily by RequestTS; both in descending order. # 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(), models.PackageRequest.RequestTS.desc(),
) )
.limit(50) .limit(50)

View file

@ -110,7 +110,7 @@ async def requests( # noqa: C901
filtered.order_by( filtered.order_by(
# Order primarily by the Status column being PENDING_ID, # Order primarily by the Status column being PENDING_ID,
# and secondarily by RequestTS; both in descending order. # 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(), PackageRequest.RequestTS.desc(),
) )
.limit(PP) .limit(PP)

View file

@ -1,3 +1,5 @@
from sqlalchemy import text
import aurweb.db import aurweb.db
from aurweb import models from aurweb import models
@ -56,8 +58,10 @@ def setup_test_db(*args):
models.User.__tablename__, 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: for table in tables:
aurweb.db.get_session().execute(f"DELETE FROM {table}") session.execute(text(f"DELETE FROM {table}"))
aurweb.db.get_session().execute("SET FOREIGN_KEY_CHECKS = 1") session.execute(text("SET FOREIGN_KEY_CHECKS = 1"))
aurweb.db.get_session().expunge_all() 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]] [[package]]
name = "aiofiles" name = "aiofiles"
version = "23.1.0" version = "23.1.0"
description = "File support for asyncio." description = "File support for asyncio."
category = "main"
optional = false optional = false
python-versions = ">=3.7,<4.0" python-versions = ">=3.7,<4.0"
files = [ files = [
@ -16,7 +15,6 @@ files = [
name = "alembic" name = "alembic"
version = "1.11.2" version = "1.11.2"
description = "A database migration tool for SQLAlchemy." description = "A database migration tool for SQLAlchemy."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -36,7 +34,6 @@ tz = ["python-dateutil"]
name = "anyio" name = "anyio"
version = "3.6.2" version = "3.6.2"
description = "High level compatibility layer for multiple asynchronous event loop implementations" description = "High level compatibility layer for multiple asynchronous event loop implementations"
category = "main"
optional = false optional = false
python-versions = ">=3.6.2" python-versions = ">=3.6.2"
files = [ files = [
@ -57,7 +54,6 @@ trio = ["trio (>=0.16,<0.22)"]
name = "asgiref" name = "asgiref"
version = "3.7.2" version = "3.7.2"
description = "ASGI specs, helper code, and adapters" description = "ASGI specs, helper code, and adapters"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -75,7 +71,6 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
name = "async-timeout" name = "async-timeout"
version = "4.0.2" version = "4.0.2"
description = "Timeout context manager for asyncio programs" description = "Timeout context manager for asyncio programs"
category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
@ -87,7 +82,6 @@ files = [
name = "authlib" name = "authlib"
version = "1.2.1" version = "1.2.1"
description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients." description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients."
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -102,7 +96,6 @@ cryptography = ">=3.2"
name = "bcrypt" name = "bcrypt"
version = "4.0.1" version = "4.0.1"
description = "Modern password hashing for your software and your servers" description = "Modern password hashing for your software and your servers"
category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
@ -137,7 +130,6 @@ typecheck = ["mypy"]
name = "bleach" name = "bleach"
version = "6.0.0" version = "6.0.0"
description = "An easy safelist-based HTML-sanitizing tool." description = "An easy safelist-based HTML-sanitizing tool."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -156,7 +148,6 @@ css = ["tinycss2 (>=1.1.0,<1.2)"]
name = "certifi" name = "certifi"
version = "2023.5.7" version = "2023.5.7"
description = "Python package for providing Mozilla's CA Bundle." description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
@ -168,7 +159,6 @@ files = [
name = "cffi" name = "cffi"
version = "1.15.1" version = "1.15.1"
description = "Foreign Function Interface for Python calling C code." description = "Foreign Function Interface for Python calling C code."
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -245,7 +235,6 @@ pycparser = "*"
name = "charset-normalizer" name = "charset-normalizer"
version = "3.1.0" version = "3.1.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false optional = false
python-versions = ">=3.7.0" python-versions = ">=3.7.0"
files = [ files = [
@ -330,7 +319,6 @@ files = [
name = "click" name = "click"
version = "8.1.3" version = "8.1.3"
description = "Composable command line interface toolkit" description = "Composable command line interface toolkit"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -345,7 +333,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
name = "colorama" name = "colorama"
version = "0.4.6" version = "0.4.6"
description = "Cross-platform colored terminal text." description = "Cross-platform colored terminal text."
category = "main"
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [ files = [
@ -357,7 +344,6 @@ files = [
name = "coverage" name = "coverage"
version = "7.2.7" version = "7.2.7"
description = "Code coverage measurement for Python" description = "Code coverage measurement for Python"
category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -433,7 +419,6 @@ toml = ["tomli"]
name = "cryptography" name = "cryptography"
version = "40.0.2" version = "40.0.2"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
@ -475,7 +460,6 @@ tox = ["tox"]
name = "dnspython" name = "dnspython"
version = "2.3.0" version = "2.3.0"
description = "DNS toolkit" description = "DNS toolkit"
category = "main"
optional = false optional = false
python-versions = ">=3.7,<4.0" python-versions = ">=3.7,<4.0"
files = [ files = [
@ -496,7 +480,6 @@ wmi = ["wmi (>=1.5.1,<2.0.0)"]
name = "email-validator" name = "email-validator"
version = "2.0.0.post2" version = "2.0.0.post2"
description = "A robust email address syntax and deliverability validation library." description = "A robust email address syntax and deliverability validation library."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -512,7 +495,6 @@ idna = ">=2.0.0"
name = "exceptiongroup" name = "exceptiongroup"
version = "1.1.1" version = "1.1.1"
description = "Backport of PEP 654 (exception groups)" description = "Backport of PEP 654 (exception groups)"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -527,7 +509,6 @@ test = ["pytest (>=6)"]
name = "execnet" name = "execnet"
version = "1.9.0" version = "1.9.0"
description = "execnet: rapid multi-Python deployment" description = "execnet: rapid multi-Python deployment"
category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [ files = [
@ -542,7 +523,6 @@ testing = ["pre-commit"]
name = "fakeredis" name = "fakeredis"
version = "2.17.0" version = "2.17.0"
description = "Python implementation of redis API, can be used for testing purposes." description = "Python implementation of redis API, can be used for testing purposes."
category = "main"
optional = false optional = false
python-versions = ">=3.7,<4.0" python-versions = ">=3.7,<4.0"
files = [ files = [
@ -562,7 +542,6 @@ lua = ["lupa (>=1.14,<2.0)"]
name = "fastapi" name = "fastapi"
version = "0.100.1" version = "0.100.1"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -582,7 +561,6 @@ all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)"
name = "feedgen" name = "feedgen"
version = "0.9.0" version = "0.9.0"
description = "Feed Generator (ATOM, RSS, Podcasts)" description = "Feed Generator (ATOM, RSS, Podcasts)"
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -597,7 +575,6 @@ python-dateutil = "*"
name = "filelock" name = "filelock"
version = "3.12.2" version = "3.12.2"
description = "A platform independent file lock." description = "A platform independent file lock."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -613,7 +590,6 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p
name = "greenlet" name = "greenlet"
version = "2.0.2" version = "2.0.2"
description = "Lightweight in-process concurrent programming" description = "Lightweight in-process concurrent programming"
category = "main"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
files = [ files = [
@ -687,7 +663,6 @@ test = ["objgraph", "psutil"]
name = "gunicorn" name = "gunicorn"
version = "21.2.0" version = "21.2.0"
description = "WSGI HTTP Server for UNIX" description = "WSGI HTTP Server for UNIX"
category = "main"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.5"
files = [ files = [
@ -708,7 +683,6 @@ tornado = ["tornado (>=0.2)"]
name = "h11" name = "h11"
version = "0.14.0" version = "0.14.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -720,7 +694,6 @@ files = [
name = "h2" name = "h2"
version = "4.1.0" version = "4.1.0"
description = "HTTP/2 State-Machine based protocol implementation" description = "HTTP/2 State-Machine based protocol implementation"
category = "main"
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.6.1"
files = [ files = [
@ -736,7 +709,6 @@ hyperframe = ">=6.0,<7"
name = "hpack" name = "hpack"
version = "4.0.0" version = "4.0.0"
description = "Pure-Python HPACK header compression" description = "Pure-Python HPACK header compression"
category = "main"
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.6.1"
files = [ files = [
@ -748,7 +720,6 @@ files = [
name = "httpcore" name = "httpcore"
version = "0.17.0" version = "0.17.0"
description = "A minimal low-level HTTP client." description = "A minimal low-level HTTP client."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -760,17 +731,16 @@ files = [
anyio = ">=3.0,<5.0" anyio = ">=3.0,<5.0"
certifi = "*" certifi = "*"
h11 = ">=0.13,<0.15" h11 = ">=0.13,<0.15"
sniffio = ">=1.0.0,<2.0.0" sniffio = "==1.*"
[package.extras] [package.extras]
http2 = ["h2 (>=3,<5)"] http2 = ["h2 (>=3,<5)"]
socks = ["socksio (>=1.0.0,<2.0.0)"] socks = ["socksio (==1.*)"]
[[package]] [[package]]
name = "httpx" name = "httpx"
version = "0.24.1" version = "0.24.1"
description = "The next generation HTTP client." description = "The next generation HTTP client."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -786,15 +756,14 @@ sniffio = "*"
[package.extras] [package.extras]
brotli = ["brotli", "brotlicffi"] 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)"] http2 = ["h2 (>=3,<5)"]
socks = ["socksio (>=1.0.0,<2.0.0)"] socks = ["socksio (==1.*)"]
[[package]] [[package]]
name = "hypercorn" name = "hypercorn"
version = "0.14.4" version = "0.14.4"
description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn" description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -819,7 +788,6 @@ uvloop = ["uvloop"]
name = "hyperframe" name = "hyperframe"
version = "6.0.1" version = "6.0.1"
description = "HTTP/2 framing layer for Python" description = "HTTP/2 framing layer for Python"
category = "main"
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.6.1"
files = [ files = [
@ -831,7 +799,6 @@ files = [
name = "idna" name = "idna"
version = "3.4" version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)" description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.5"
files = [ files = [
@ -843,7 +810,6 @@ files = [
name = "importlib-metadata" name = "importlib-metadata"
version = "6.6.0" version = "6.6.0"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -863,7 +829,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag
name = "iniconfig" name = "iniconfig"
version = "2.0.0" version = "2.0.0"
description = "brain-dead simple config-ini parsing" description = "brain-dead simple config-ini parsing"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -875,7 +840,6 @@ files = [
name = "itsdangerous" name = "itsdangerous"
version = "2.1.2" version = "2.1.2"
description = "Safely pass data to untrusted environments and back." description = "Safely pass data to untrusted environments and back."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -887,7 +851,6 @@ files = [
name = "jinja2" name = "jinja2"
version = "3.1.2" version = "3.1.2"
description = "A very fast and expressive template engine." description = "A very fast and expressive template engine."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -905,7 +868,6 @@ i18n = ["Babel (>=2.7)"]
name = "lxml" name = "lxml"
version = "4.9.3" version = "4.9.3"
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
files = [ files = [
@ -1013,7 +975,6 @@ source = ["Cython (>=0.29.35)"]
name = "mako" name = "mako"
version = "1.2.4" version = "1.2.4"
description = "A super-fast templating language that borrows the best ideas from the existing templating languages." description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1033,7 +994,6 @@ testing = ["pytest"]
name = "markdown" name = "markdown"
version = "3.4.4" version = "3.4.4"
description = "Python implementation of John Gruber's Markdown." description = "Python implementation of John Gruber's Markdown."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1052,7 +1012,6 @@ testing = ["coverage", "pyyaml"]
name = "markupsafe" name = "markupsafe"
version = "2.1.2" version = "2.1.2"
description = "Safely add untrusted strings to HTML/XML markup." description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1112,7 +1071,6 @@ files = [
name = "mysqlclient" name = "mysqlclient"
version = "2.2.0" version = "2.2.0"
description = "Python interface to MySQL" description = "Python interface to MySQL"
category = "main"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
@ -1129,7 +1087,6 @@ files = [
name = "orjson" name = "orjson"
version = "3.9.2" version = "3.9.2"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1185,7 +1142,6 @@ files = [
name = "packaging" name = "packaging"
version = "23.1" version = "23.1"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1197,7 +1153,6 @@ files = [
name = "paginate" name = "paginate"
version = "0.5.6" version = "0.5.6"
description = "Divides large result sets into pages for easier browsing" description = "Divides large result sets into pages for easier browsing"
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1208,7 +1163,6 @@ files = [
name = "parse" name = "parse"
version = "1.19.0" version = "1.19.0"
description = "parse() is the opposite of format()" description = "parse() is the opposite of format()"
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1220,7 +1174,6 @@ files = [
name = "pluggy" name = "pluggy"
version = "1.0.0" version = "1.0.0"
description = "plugin and hook calling mechanisms for python" description = "plugin and hook calling mechanisms for python"
category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
@ -1236,7 +1189,6 @@ testing = ["pytest", "pytest-benchmark"]
name = "posix-ipc" name = "posix-ipc"
version = "1.1.1" version = "1.1.1"
description = "POSIX IPC primitives (semaphores, shared memory and message queues) for Python" description = "POSIX IPC primitives (semaphores, shared memory and message queues) for Python"
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1252,7 +1204,6 @@ files = [
name = "priority" name = "priority"
version = "2.0.0" version = "2.0.0"
description = "A pure-Python implementation of the HTTP/2 priority tree" description = "A pure-Python implementation of the HTTP/2 priority tree"
category = "main"
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.6.1"
files = [ files = [
@ -1264,7 +1215,6 @@ files = [
name = "prometheus-client" name = "prometheus-client"
version = "0.16.0" version = "0.16.0"
description = "Python client for the Prometheus monitoring system." description = "Python client for the Prometheus monitoring system."
category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
@ -1279,7 +1229,6 @@ twisted = ["twisted"]
name = "prometheus-fastapi-instrumentator" name = "prometheus-fastapi-instrumentator"
version = "6.1.0" version = "6.1.0"
description = "Instrument your FastAPI with Prometheus metrics." description = "Instrument your FastAPI with Prometheus metrics."
category = "main"
optional = false optional = false
python-versions = ">=3.7.0,<4.0.0" python-versions = ">=3.7.0,<4.0.0"
files = [ files = [
@ -1295,7 +1244,6 @@ prometheus-client = ">=0.8.0,<1.0.0"
name = "protobuf" name = "protobuf"
version = "4.23.4" version = "4.23.4"
description = "" description = ""
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1318,7 +1266,6 @@ files = [
name = "pyalpm" name = "pyalpm"
version = "0.10.6" version = "0.10.6"
description = "libalpm bindings for Python 3" description = "libalpm bindings for Python 3"
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1329,7 +1276,6 @@ files = [
name = "pycparser" name = "pycparser"
version = "2.21" version = "2.21"
description = "C parser in Python" description = "C parser in Python"
category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [ files = [
@ -1341,7 +1287,6 @@ files = [
name = "pydantic" name = "pydantic"
version = "1.10.7" version = "1.10.7"
description = "Data validation and settings management using python type hints" description = "Data validation and settings management using python type hints"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1394,7 +1339,6 @@ email = ["email-validator (>=1.0.3)"]
name = "pygit2" name = "pygit2"
version = "1.12.2" version = "1.12.2"
description = "Python bindings for libgit2." description = "Python bindings for libgit2."
category = "main"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
@ -1438,7 +1382,6 @@ cffi = ">=1.9.1"
name = "pytest" name = "pytest"
version = "7.4.0" version = "7.4.0"
description = "pytest: simple powerful testing with Python" description = "pytest: simple powerful testing with Python"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1461,7 +1404,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no
name = "pytest-asyncio" name = "pytest-asyncio"
version = "0.21.1" version = "0.21.1"
description = "Pytest support for asyncio" description = "Pytest support for asyncio"
category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1480,7 +1422,6 @@ testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy
name = "pytest-cov" name = "pytest-cov"
version = "4.1.0" version = "4.1.0"
description = "Pytest plugin for measuring coverage." description = "Pytest plugin for measuring coverage."
category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1499,7 +1440,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale
name = "pytest-tap" name = "pytest-tap"
version = "3.4" version = "3.4"
description = "Test Anything Protocol (TAP) reporting plugin for pytest" description = "Test Anything Protocol (TAP) reporting plugin for pytest"
category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1515,7 +1455,6 @@ pytest = ">=3.0"
name = "pytest-xdist" name = "pytest-xdist"
version = "3.3.1" version = "3.3.1"
description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1536,7 +1475,6 @@ testing = ["filelock"]
name = "python-dateutil" name = "python-dateutil"
version = "2.8.2" version = "2.8.2"
description = "Extensions to the standard Python datetime module" description = "Extensions to the standard Python datetime module"
category = "main"
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
files = [ files = [
@ -1551,7 +1489,6 @@ six = ">=1.5"
name = "python-multipart" name = "python-multipart"
version = "0.0.6" version = "0.0.6"
description = "A streaming multipart parser for Python" description = "A streaming multipart parser for Python"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1566,7 +1503,6 @@ dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatc
name = "redis" name = "redis"
version = "4.6.0" version = "4.6.0"
description = "Python client for Redis database and key-value store" description = "Python client for Redis database and key-value store"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1585,7 +1521,6 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
name = "requests" name = "requests"
version = "2.31.0" version = "2.31.0"
description = "Python HTTP for Humans." description = "Python HTTP for Humans."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1607,7 +1542,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
name = "six" name = "six"
version = "1.16.0" version = "1.16.0"
description = "Python 2 and 3 compatibility utilities" description = "Python 2 and 3 compatibility utilities"
category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [ files = [
@ -1619,7 +1553,6 @@ files = [
name = "sniffio" name = "sniffio"
version = "1.3.0" version = "1.3.0"
description = "Sniff out which async library your code is running under" description = "Sniff out which async library your code is running under"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1631,7 +1564,6 @@ files = [
name = "sortedcontainers" name = "sortedcontainers"
version = "2.4.0" version = "2.4.0"
description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1641,81 +1573,86 @@ files = [
[[package]] [[package]]
name = "sqlalchemy" name = "sqlalchemy"
version = "1.4.49" version = "2.0.17"
description = "Database Abstraction Library" description = "Database Abstraction Library"
category = "main"
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" python-versions = ">=3.7"
files = [ files = [
{file = "SQLAlchemy-1.4.49-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e126cf98b7fd38f1e33c64484406b78e937b1a280e078ef558b95bf5b6895f6"}, {file = "SQLAlchemy-2.0.17-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:04383f1e3452f6739084184e427e9d5cb4e68ddc765d52157bf5ef30d5eca14f"},
{file = "SQLAlchemy-1.4.49-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:03db81b89fe7ef3857b4a00b63dedd632d6183d4ea5a31c5d8a92e000a41fc71"}, {file = "SQLAlchemy-2.0.17-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:724355973297bbe547f3eb98b46ade65a67a3d5a6303f17ab59a2dc6fb938943"},
{file = "SQLAlchemy-1.4.49-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:95b9df9afd680b7a3b13b38adf6e3a38995da5e162cc7524ef08e3be4e5ed3e1"}, {file = "SQLAlchemy-2.0.17-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf07ff9920cb3ca9d73525dfd4f36ddf9e1a83734ea8b4f724edfd9a2c6e82d9"},
{file = "SQLAlchemy-1.4.49-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a63e43bf3f668c11bb0444ce6e809c1227b8f067ca1068898f3008a273f52b09"}, {file = "SQLAlchemy-2.0.17-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f389f77c68dc22cb51f026619291c4a38aeb4b7ecb5f998fd145b2d81ca513"},
{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-2.0.17-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba03518e64d86f000dc24ab3d3a1aa876bcbaa8aa15662ac2df5e81537fa3394"},
{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-2.0.17-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:218fb20c01e95004f50a3062bf4c447dcb360cab8274232f31947e254f118298"},
{file = "SQLAlchemy-1.4.49-cp310-cp310-win32.whl", hash = "sha256:5fb1ebdfc8373b5a291485757bd6431de8d7ed42c27439f543c81f6c8febd729"}, {file = "SQLAlchemy-2.0.17-cp310-cp310-win32.whl", hash = "sha256:b47be4c6281a86670ea5cfbbbe6c3a65366a8742f5bc8b986f790533c60b5ddb"},
{file = "SQLAlchemy-1.4.49-cp310-cp310-win_amd64.whl", hash = "sha256:f8a65990c9c490f4651b5c02abccc9f113a7f56fa482031ac8cb88b70bc8ccaa"}, {file = "SQLAlchemy-2.0.17-cp310-cp310-win_amd64.whl", hash = "sha256:74ddcafb6488f382854a7da851c404c394be3729bb3d91b02ad86c5458140eff"},
{file = "SQLAlchemy-1.4.49-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8923dfdf24d5aa8a3adb59723f54118dd4fe62cf59ed0d0d65d940579c1170a4"}, {file = "SQLAlchemy-2.0.17-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:51736cfb607cf4e8fafb693906f9bc4e5ee55be0b096d44bd7f20cd8489b8571"},
{file = "SQLAlchemy-1.4.49-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9ab2c507a7a439f13ca4499db6d3f50423d1d65dc9b5ed897e70941d9e135b0"}, {file = "SQLAlchemy-2.0.17-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8741d3d401383e54b2aada37cbd10f55c5d444b360eae3a82f74a2be568a7710"},
{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-2.0.17-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ead58cae2a089eee1b0569060999cb5f2b2462109498a0937cc230a7556945a1"},
{file = "SQLAlchemy-1.4.49-cp311-cp311-win32.whl", hash = "sha256:82b08e82da3756765c2e75f327b9bf6b0f043c9c3925fb95fb51e1567fa4ee87"}, {file = "SQLAlchemy-2.0.17-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f40e3a7d0a464f1c8593f2991e5520b2f5b26da24e88000bbd4423f86103d4f"},
{file = "SQLAlchemy-1.4.49-cp311-cp311-win_amd64.whl", hash = "sha256:171e04eeb5d1c0d96a544caf982621a1711d078dbc5c96f11d6469169bd003f1"}, {file = "SQLAlchemy-2.0.17-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:21583808d37f126a647652c90332ac1d3a102edf3c94bcc3319edcc0ea2300cc"},
{file = "SQLAlchemy-1.4.49-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:36e58f8c4fe43984384e3fbe6341ac99b6b4e083de2fe838f0fdb91cebe9e9cb"}, {file = "SQLAlchemy-2.0.17-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f593170fc09c5abb1205a738290b39532f7380094dc151805009a07ae0e85330"},
{file = "SQLAlchemy-1.4.49-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b31e67ff419013f99ad6f8fc73ee19ea31585e1e9fe773744c0f3ce58c039c30"}, {file = "SQLAlchemy-2.0.17-cp311-cp311-win32.whl", hash = "sha256:b0eaf82cc844f6b46defe15ad243ea00d1e39ed3859df61130c263dc7204da6e"},
{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-2.0.17-cp311-cp311-win_amd64.whl", hash = "sha256:1822620c89779b85f7c23d535c8e04b79c517739ae07aaed48c81e591ed5498e"},
{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-2.0.17-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2269b1f9b8be47e52b70936069a25a3771eff53367aa5cc59bb94f28a6412e13"},
{file = "SQLAlchemy-1.4.49-cp36-cp36m-win32.whl", hash = "sha256:706bfa02157b97c136547c406f263e4c6274a7b061b3eb9742915dd774bbc264"}, {file = "SQLAlchemy-2.0.17-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48111d56afea5699bab72c38ec95561796b81befff9e13d1dd5ce251ab25f51d"},
{file = "SQLAlchemy-1.4.49-cp36-cp36m-win_amd64.whl", hash = "sha256:a7f7b5c07ae5c0cfd24c2db86071fb2a3d947da7bd487e359cc91e67ac1c6d2e"}, {file = "SQLAlchemy-2.0.17-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28da17059ecde53e2d10ba813d38db942b9f6344360b2958b25872d5cb729d35"},
{file = "SQLAlchemy-1.4.49-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:4afbbf5ef41ac18e02c8dc1f86c04b22b7a2125f2a030e25bbb4aff31abb224b"}, {file = "SQLAlchemy-2.0.17-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:48b40dc2895841ea89d89df9eb3ac69e2950a659db20a369acf4259f68e6dc1f"},
{file = "SQLAlchemy-1.4.49-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24e300c0c2147484a002b175f4e1361f102e82c345bf263242f0449672a4bccf"}, {file = "SQLAlchemy-2.0.17-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7f31d4e7ca1dd8ca5a27fd5eaa0f9e2732fe769ff7dd35bf7bba179597e4df07"},
{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-2.0.17-cp37-cp37m-win32.whl", hash = "sha256:7830e01b02d440c27f2a5be68296e74ccb55e6a5b5962ffafd360b98930b2e5e"},
{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-2.0.17-cp37-cp37m-win_amd64.whl", hash = "sha256:234678ed6576531b8e4be255b980f20368bf07241a2e67b84e6b0fe679edb9c4"},
{file = "SQLAlchemy-1.4.49-cp37-cp37m-win32.whl", hash = "sha256:647e0b309cb4512b1f1b78471fdaf72921b6fa6e750b9f891e09c6e2f0e5326f"}, {file = "SQLAlchemy-2.0.17-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c6ff5767d954f6091113fedcaaf49cdec2197ae4c5301fe83d5ae4393c82f33"},
{file = "SQLAlchemy-1.4.49-cp37-cp37m-win_amd64.whl", hash = "sha256:ab73ed1a05ff539afc4a7f8cf371764cdf79768ecb7d2ec691e3ff89abbc541e"}, {file = "SQLAlchemy-2.0.17-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa995b21f853864996e4056d9fde479bcecf8b7bff4beb3555eebbbba815f35d"},
{file = "SQLAlchemy-1.4.49-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:37ce517c011560d68f1ffb28af65d7e06f873f191eb3a73af5671e9c3fada08a"}, {file = "SQLAlchemy-2.0.17-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:125f9f7e62ddf8b590c069729080ffe18b68a20d9882eb0947f72e06274601d7"},
{file = "SQLAlchemy-1.4.49-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1878ce508edea4a879015ab5215546c444233881301e97ca16fe251e89f1c55"}, {file = "SQLAlchemy-2.0.17-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b114a16bc03dfe20b625062e456affd7b9938286e05a3f904a025b9aacc29dd4"},
{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-2.0.17-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf175d26f6787cce30fe6c04303ca0aeeb0ad40eeb22e3391f24b32ec432a1e1"},
{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-2.0.17-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e2d5c3596254cf1a96474b98e7ce20041c74c008b0f101c1cb4f8261cb77c6d3"},
{file = "SQLAlchemy-1.4.49-cp38-cp38-win32.whl", hash = "sha256:f167c8175ab908ce48bd6550679cc6ea20ae169379e73c7720a28f89e53aa532"}, {file = "SQLAlchemy-2.0.17-cp38-cp38-win32.whl", hash = "sha256:513411d73503a6fc5804f01fae3b3d44f267c1b3a06cfeac02e9286a7330e857"},
{file = "SQLAlchemy-1.4.49-cp38-cp38-win_amd64.whl", hash = "sha256:45806315aae81a0c202752558f0df52b42d11dd7ba0097bf71e253b4215f34f4"}, {file = "SQLAlchemy-2.0.17-cp38-cp38-win_amd64.whl", hash = "sha256:40a3dc52b2b16f08b5c16b9ee7646329e4b3411e9280e5e8d57b19eaa51cbef4"},
{file = "SQLAlchemy-1.4.49-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:b6d0c4b15d65087738a6e22e0ff461b407533ff65a73b818089efc8eb2b3e1de"}, {file = "SQLAlchemy-2.0.17-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e3189432db2f5753b4fde1aa90a61c69976f4e7e31d1cf4611bfe3514ed07478"},
{file = "SQLAlchemy-1.4.49-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a843e34abfd4c797018fd8d00ffffa99fd5184c421f190b6ca99def4087689bd"}, {file = "SQLAlchemy-2.0.17-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6150560fcffc6aee5ec9a97419ac768c7a9f56baf7a7eb59cb4b1b6a4d463ad9"},
{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-2.0.17-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910d45bf3673f0e4ef13858674bd23cfdafdc8368b45b948bf511797dbbb401d"},
{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-2.0.17-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0aeb3afaa19f187a70fa592fbe3c20a056b57662691fd3abf60f016aa5c1848"},
{file = "SQLAlchemy-1.4.49-cp39-cp39-win32.whl", hash = "sha256:ec2268de67f73b43320383947e74700e95c6770d0c68c4e615e9897e46296294"}, {file = "SQLAlchemy-2.0.17-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:36a87e26fe8fa8c466fae461a8fcb780d0a1cbf8206900759fc6fe874475a3ce"},
{file = "SQLAlchemy-1.4.49-cp39-cp39-win_amd64.whl", hash = "sha256:bbdf16372859b8ed3f4d05f925a984771cd2abd18bd187042f24be4886c2a15f"}, {file = "SQLAlchemy-2.0.17-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e3a6b2788f193756076061626679c5c5a6d600ddf8324f986bc72004c3e9d92e"},
{file = "SQLAlchemy-1.4.49.tar.gz", hash = "sha256:06ff25cbae30c396c4b7737464f2a7fc37a67b7da409993b182b024cec80aed9"}, {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] [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] [package.extras]
aiomysql = ["aiomysql", "greenlet (!=0.4.17)"] aiomysql = ["aiomysql", "greenlet (!=0.4.17)"]
aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]
asyncio = ["greenlet (!=0.4.17)"] asyncio = ["greenlet (!=0.4.17)"]
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "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 = ["pyodbc"]
mssql-pymssql = ["pymssql"] mssql-pymssql = ["pymssql"]
mssql-pyodbc = ["pyodbc"] mssql-pyodbc = ["pyodbc"]
mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] mypy = ["mypy (>=0.910)"]
mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] mysql = ["mysqlclient (>=1.4.0)"]
mysql-connector = ["mysql-connector-python"] 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 = ["psycopg2 (>=2.7)"]
postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] 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-psycopg2binary = ["psycopg2-binary"]
postgresql-psycopg2cffi = ["psycopg2cffi"] postgresql-psycopg2cffi = ["psycopg2cffi"]
pymysql = ["pymysql", "pymysql (<1)"] postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
pymysql = ["pymysql"]
sqlcipher = ["sqlcipher3-binary"] sqlcipher = ["sqlcipher3-binary"]
[[package]] [[package]]
name = "srcinfo" name = "srcinfo"
version = "0.1.2" version = "0.1.2"
description = "A small library to parse .SRCINFO files" description = "A small library to parse .SRCINFO files"
category = "main"
optional = false optional = false
python-versions = ">=3.7,<4.0" python-versions = ">=3.7,<4.0"
files = [ files = [
@ -1730,7 +1667,6 @@ parse = ">=1.19.0,<2.0.0"
name = "starlette" name = "starlette"
version = "0.27.0" version = "0.27.0"
description = "The little ASGI library that shines." description = "The little ASGI library that shines."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1749,7 +1685,6 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyam
name = "tap-py" name = "tap-py"
version = "3.1" version = "3.1"
description = "Test Anything Protocol (TAP) tools" description = "Test Anything Protocol (TAP) tools"
category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1764,7 +1699,6 @@ yaml = ["PyYAML (>=5.1)", "more-itertools"]
name = "tomli" name = "tomli"
version = "2.0.1" version = "2.0.1"
description = "A lil' TOML parser" description = "A lil' TOML parser"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1776,7 +1710,6 @@ files = [
name = "tomlkit" name = "tomlkit"
version = "0.12.1" version = "0.12.1"
description = "Style preserving TOML library" description = "Style preserving TOML library"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1788,7 +1721,6 @@ files = [
name = "typing-extensions" name = "typing-extensions"
version = "4.5.0" version = "4.5.0"
description = "Backported and Experimental Type Hints for Python 3.7+" description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1800,7 +1732,6 @@ files = [
name = "urllib3" name = "urllib3"
version = "2.0.2" version = "2.0.2"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1818,7 +1749,6 @@ zstd = ["zstandard (>=0.18.0)"]
name = "uvicorn" name = "uvicorn"
version = "0.23.2" version = "0.23.2"
description = "The lightning-fast ASGI server." description = "The lightning-fast ASGI server."
category = "main"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
@ -1838,7 +1768,6 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)",
name = "watchfiles" name = "watchfiles"
version = "0.19.0" version = "0.19.0"
description = "Simple, modern and high performance file watching and code reload in python." description = "Simple, modern and high performance file watching and code reload in python."
category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1873,7 +1802,6 @@ anyio = ">=3.0.0"
name = "webencodings" name = "webencodings"
version = "0.5.1" version = "0.5.1"
description = "Character encoding aliases for legacy web content" description = "Character encoding aliases for legacy web content"
category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
@ -1885,7 +1813,6 @@ files = [
name = "werkzeug" name = "werkzeug"
version = "2.3.6" version = "2.3.6"
description = "The comprehensive WSGI web application library." description = "The comprehensive WSGI web application library."
category = "main"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
@ -1903,7 +1830,6 @@ watchdog = ["watchdog (>=2.3)"]
name = "wsproto" name = "wsproto"
version = "1.2.0" version = "1.2.0"
description = "WebSockets state-machine based protocol implementation" description = "WebSockets state-machine based protocol implementation"
category = "main"
optional = false optional = false
python-versions = ">=3.7.0" python-versions = ">=3.7.0"
files = [ files = [
@ -1918,7 +1844,6 @@ h11 = ">=0.9.0,<1"
name = "zipp" name = "zipp"
version = "3.15.0" version = "3.15.0"
description = "Backport of pathlib-compatible object wrapper for zip files" description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -1933,4 +1858,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.9,<3.12" 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" Jinja2 = "^3.1.2"
Markdown = "^3.4.3" Markdown = "^3.4.3"
Werkzeug = "^2.3.3" Werkzeug = "^2.3.3"
SQLAlchemy = "^1.4.48" SQLAlchemy = "2.0.17"
# ASGI # ASGI
uvicorn = "^0.23.0" uvicorn = "^0.23.0"

View file

@ -44,7 +44,7 @@ from multiprocessing import Lock
import py import py
import pytest import pytest
from posix_ipc import O_CREAT, Semaphore 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 import URL
from sqlalchemy.engine.base import Engine from sqlalchemy.engine.base import Engine
from sqlalchemy.exc import ProgrammingError from sqlalchemy.exc import ProgrammingError
@ -106,15 +106,16 @@ def _create_database(engine: Engine, dbname: str) -> None:
:param dbname: Database name to create :param dbname: Database name to create
""" """
conn = engine.connect() conn = engine.connect()
try: with conn.begin():
conn.execute(f"CREATE DATABASE {dbname}") try:
except ProgrammingError: # pragma: no cover conn.execute(text(f"CREATE DATABASE {dbname}"))
# The database most likely already existed if we hit except ProgrammingError: # pragma: no cover
# a ProgrammingError. Just drop the database and try # The database most likely already existed if we hit
# again. If at that point things still fail, any # a ProgrammingError. Just drop the database and try
# exception will be propogated up to the caller. # again. If at that point things still fail, any
conn.execute(f"DROP DATABASE {dbname}") # exception will be propogated up to the caller.
conn.execute(f"CREATE DATABASE {dbname}") conn.execute(text(f"DROP DATABASE {dbname}"))
conn.execute(text(f"CREATE DATABASE {dbname}"))
conn.close() conn.close()
initdb.run(AlembicArgs) initdb.run(AlembicArgs)
@ -126,9 +127,10 @@ def _drop_database(engine: Engine, dbname: str) -> None:
:param engine: Engine returned by test_engine() :param engine: Engine returned by test_engine()
:param dbname: Database name to drop :param dbname: Database name to drop
""" """
aurweb.schema.metadata.drop_all(bind=engine) # aurweb.schema.metadata.drop_all(bind=engine)
conn = engine.connect() conn = engine.connect()
conn.execute(f"DROP DATABASE {dbname}") with conn.begin():
conn.execute(text(f"DROP DATABASE {dbname}"))
conn.close() conn.close()

View file

@ -24,5 +24,6 @@ def test_run():
aurweb.initdb.run(Args()) aurweb.initdb.run(Args())
# Check that constant table rows got added via initdb. # 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 assert record is not None

View file

@ -1,5 +1,5 @@
import pytest import pytest
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError, SAWarning
from aurweb import db, time from aurweb import db, time
from aurweb.db import create, rollback 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): def test_tu_voteinfo_null_agenda_raises(user: User):
with pytest.raises(IntegrityError): with pytest.raises(IntegrityError), pytest.warns(SAWarning):
with db.begin(): with db.begin():
create( create(
TUVoteInfo, TUVoteInfo,
@ -123,7 +123,7 @@ def test_tu_voteinfo_null_agenda_raises(user: User):
def test_tu_voteinfo_null_user_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(): with db.begin():
create( create(
TUVoteInfo, TUVoteInfo,
@ -137,7 +137,7 @@ def test_tu_voteinfo_null_user_raises(user: User):
def test_tu_voteinfo_null_submitted_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(): with db.begin():
create( create(
TUVoteInfo, TUVoteInfo,
@ -151,7 +151,7 @@ def test_tu_voteinfo_null_submitted_raises(user: User):
def test_tu_voteinfo_null_end_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(): with db.begin():
create( create(
TUVoteInfo, TUVoteInfo,