Skip to content
This repository has been archived by the owner on Mar 24, 2024. It is now read-only.

Commit

Permalink
port to sqlalchemy 2 (#310)
Browse files Browse the repository at this point in the history
* port to sqlalchemy 2

* port to sqlalchemy 2
  • Loading branch information
lsbardel authored Apr 1, 2023
1 parent cf891da commit 052fb42
Show file tree
Hide file tree
Showing 10 changed files with 703 additions and 572 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"RedirectOutput"
],
"args": [
"tests/pagination/test_cursor_pagination.py::test_bad_cursor"
"tests/core/test_cruddb.py"
]
}
]
Expand Down
10 changes: 5 additions & 5 deletions openapi/db/commands.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import click
from sqlalchemy import inspect
from sqlalchemy_utils import create_database, database_exists, drop_database

from openapi.cli import open_api_cli
Expand Down Expand Up @@ -125,13 +126,12 @@ def create(ctx, dbname: str, force: str):
"""Creates a new database"""
engine = get_db(ctx).sync_engine
url = engine.url.set(database=dbname)
store = str(url)
if database_exists(store):
if database_exists(url):
if force:
drop_database(store)
drop_database(url)
else:
return click.echo(f"database {dbname} already available")
create_database(store)
create_database(url)
click.echo(f"database {dbname} created")


Expand All @@ -147,7 +147,7 @@ def tables(ctx, db):
"""List all tables managed by the app"""
d = get_db(ctx)
if db:
tables = d.sync_engine.table_names()
tables = inspect(d.sync_engine).get_table_names()
else:
tables = d.metadata.tables
for name in sorted(tables):
Expand Down
10 changes: 5 additions & 5 deletions openapi/db/dbmodel.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Union, cast

from sqlalchemy import Column, Table, func, select
from sqlalchemy import Column, Table, func, insert, select
from sqlalchemy.sql import Select, and_, or_
from sqlalchemy.sql.dml import Delete, Insert, Update

Expand Down Expand Up @@ -71,7 +71,7 @@ async def db_delete(
async def db_count(
self,
table: Table,
filters: Dict,
filters: Optional[Dict] = None,
*,
conn: Optional[Connection] = None,
consumer: Any = None,
Expand All @@ -90,11 +90,11 @@ async def db_count(

async def db_count_query(
self,
sql_query,
sql_query: Select,
*,
conn: Optional[Connection] = None,
) -> int:
count_query = select([func.count()]).select_from(sql_query.alias("inner"))
count_query = select(func.count()).select_from(sql_query.alias("inner"))
async with self.ensure_connection(conn) as conn:
result = await conn.execute(count_query)
return result.scalar()
Expand Down Expand Up @@ -210,7 +210,7 @@ def insert_query(self, table: Table, records: Union[List[Dict], Dict]) -> Insert
record[col] = None
new_records.append(record)
records = new_records
return table.insert(records).returning(*table.columns)
return insert(table).values(records).returning(*table.columns)

# backward compatibility
get_insert = insert_query
Expand Down
6 changes: 5 additions & 1 deletion openapi/db/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ def create_config(app):
cfg.set_main_option("script_location", migrations)
cfg.config_file_name = os.path.join(migrations, "alembic.ini")
db = app["db"]
cfg.set_section_option("default", "sqlalchemy.url", str(db.sync_engine.url))
cfg.set_section_option(
"default",
"sqlalchemy.url",
db.sync_engine.url.render_as_string(hide_password=False),
)
# put database in main options
cfg.set_main_option("databases", "default")
# create empty logging section to avoid raising errors in env.py
Expand Down
1 change: 0 additions & 1 deletion openapi/pagination/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ def cursorPagination(
default_limit: int = DEF_PAGINATION_LIMIT,
max_limit: int = MAX_PAGINATION_LIMIT,
) -> Type[Pagination]:

if len(order_by_fields) == 0:
raise ValueError("orderable_fields must be specified")

Expand Down
1 change: 0 additions & 1 deletion openapi/sentry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@


def setup(app, dsn, env="dev", level=logging.ERROR, event_level=logging.ERROR):

sentry_sdk.init(
dsn=dsn,
environment=env,
Expand Down
1,199 changes: 663 additions & 536 deletions poetry.lock

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,52 +39,52 @@ issues = "https://github.com/quantmind/aio-openapi/issues"


[tool.poetry.dependencies]
python = ">=3.8,<4"
python = ">=3.8.1,<4"
aiohttp = "^3.8.0"
httptools = "^0.5.0"
simplejson = "^3.17.2"
asyncpg = "^0.26.0"
SQLAlchemy = "^1.4.27"
SQLAlchemy-Utils = "^0.38.2"
SQLAlchemy = { version="^2.0.8", extras=["asyncio"] }
SQLAlchemy-Utils = "^0.40.0"
psycopg2-binary = "^2.9.2"
click = "^8.0.3"
python-dateutil = "^2.8.2"
PyYAML = "^6.0"
email-validator = "^1.2.1"
alembic = "^1.8.1"
aiodns = {version = "^3.0.0", optional = true}
PyJWT = {version = "^2.3.0", optional = true}
colorlog = {version = "^6.6.0", optional = true}
phonenumbers = {version = "^8.12.37", optional = true}
Sphinx = {version = "^5.0.2", optional = true}
Sphinx = {version = "^6.1.3", optional = true}
sphinx-copybutton = {version = "^0.5.0", optional = true}
sphinx-autodoc-typehints = {version = "^1.12.0", optional = true}
aiohttp-theme = {version = "^0.1.6", optional = true}
recommonmark = {version = "^0.7.1", optional = true}
"backports.zoneinfo" = { version = "^0.2.1", python="<3.9" }
email-validator = "^1.2.1"
alembic = "^1.8.1"
asyncpg = "^0.27.0"

[tool.poetry.dev-dependencies]
black = "^22.3.0"
flake8 = "^5.0.4"
black = "^23.3.0"
flake8 = "^6.0.0"
pytest = "^7.1.1"
flake8-blind-except = "^0.2.0"
flake8-builtins = "^2.0.0"
flake8-commas = "^2.1.0"
codecov = "^2.1.12"
coverage = "^6.1.2"
coveralls = "^3.3.1"
mypy = "^0.982"
mypy = "^1.1.1"
sqlalchemy-stubs = "^0.4"
sentry-sdk = "^1.4.3"
python-dotenv = "^0.21.0"
python-dotenv = "^1.0.0"
openapi-spec-validator = "^0.3.1"
pytest-cov = "^4.0.0"
pytest-mock = "^3.6.1"
isort = "^5.10.1"
types-simplejson = "^3.17.5"
types-python-dateutil = "^2.8.11"
factory-boy = "^3.2.1"
pytest-asyncio = "^0.20.1"
pytest-asyncio = "^0.21.0"

[tool.poetry.extras]
dev = ["aiodns", "PyJWT", "colorlog", "phonenumbers"]
Expand Down
7 changes: 4 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest
from aiohttp.test_utils import TestClient
from aiohttp.web import Application
from sqlalchemy.engine.url import URL
from sqlalchemy_utils import create_database, database_exists

from openapi.db.dbmodel import CrudDB
Expand All @@ -16,8 +17,8 @@


@pytest.fixture(scope="session")
def sync_url() -> str:
return str(DB.sync_engine.url)
def sync_url() -> URL:
return DB.sync_engine.url


@pytest.fixture(autouse=True)
Expand All @@ -44,7 +45,7 @@ def event_loop():


@pytest.fixture(scope="session")
def clear_db(sync_url) -> CrudDB:
def clear_db(sync_url: URL) -> CrudDB:
if not database_exists(sync_url):
# drop_database(url)
create_database(sync_url)
Expand Down
15 changes: 8 additions & 7 deletions tests/core/test_cruddb.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@

async def test_upsert(db: CrudDB) -> None:
task = await db.db_upsert(db.tasks, dict(title="Example"), dict(severity=4))
assert task["id"]
assert task["severity"] == 4
assert task["done"] is None
assert task.id
assert task.severity == 4
assert task.done is None
task2 = await db.db_upsert(
db.tasks, dict(title="Example"), dict(done=datetime.now())
)
task2["id"] == task["id"]
assert task2["done"]
task2.id == task.id
assert task2.done
assert await db.db_count(db.tasks) == 1


async def test_upsert_no_data(db: CrudDB) -> None:
task = await db.db_upsert(db.tasks, dict(title="Example2"))
assert task["id"]
assert task["title"] == "Example2"
assert task.id
assert task.title == "Example2"

0 comments on commit 052fb42

Please sign in to comment.