From f55003f5d08007c170c86a5ab5a24eec4cf9a879 Mon Sep 17 00:00:00 2001 From: Ultraproduct <4291996-LightlessNight@users.noreply.gitlab.com> Date: Fri, 31 Jul 2020 01:38:09 -0500 Subject: [PATCH 01/13] Implement order by --- orm/models.py | 27 ++++++++++++++++++++++++- tests/test_models.py | 48 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/orm/models.py b/orm/models.py index e61d159..ca3859f 100644 --- a/orm/models.py +++ b/orm/models.py @@ -50,8 +50,9 @@ def __new__( class QuerySet: ESCAPE_CHARACTERS = ['%', '_'] - def __init__(self, model_cls=None, filter_clauses=None, select_related=None, limit_count=None, offset=None): + def __init__(self, model_cls=None, filter_clauses=None, select_related=None, limit_count=None, offset=None, order_args=None): self.model_cls = model_cls + self.order_args = [] if order_args is None else order_args self.filter_clauses = [] if filter_clauses is None else filter_clauses self._select_related = [] if select_related is None else select_related self.limit_count = limit_count @@ -90,6 +91,10 @@ def build_select_expression(self): clause = sqlalchemy.sql.and_(*self.filter_clauses) expr = expr.where(clause) + if self.order_args: + order_args = self._prepared_order() + expr = expr.order_by(*order_args) + if self.limit_count: expr = expr.limit(self.limit_count) @@ -181,6 +186,26 @@ def select_related(self, related): offset=self.query_offset ) + def _prepared_order(self): + prepared = [] + for order in self.order_args: + desc = order.startswith('-') + col_name = order.lstrip('-') if desc else order + col = self.model_cls.__table__.columns[col_name] + prepared.append(col.desc() if desc else col) + + return prepared + + def order_by(self, *args): + return self.__class__( + model_cls=self.model_cls, + filter_clauses=self.filter_clauses, + select_related=self._select_related, + limit_count=self.limit_count, + offset=self.query_offset, + order_args=args, + ) + async def exists(self) -> bool: expr = self.build_select_expression() expr = sqlalchemy.exists(expr).select() diff --git a/tests/test_models.py b/tests/test_models.py index ddd9fde..0ff9ad2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,4 +1,5 @@ import asyncio +import datetime import functools import pytest @@ -20,6 +21,7 @@ class User(orm.Model): id = orm.Integer(primary_key=True) name = orm.String(max_length=100) + timestamp = orm.DateTime(allow_null=True) class Product(orm.Model): @@ -56,11 +58,12 @@ def run_sync(*args, **kwargs): def test_model_class(): - assert list(User.fields.keys()) == ["id", "name"] + assert list(User.fields.keys()) == ["id", "name", "timestamp"] assert isinstance(User.fields["id"], orm.Integer) assert User.fields["id"].primary_key is True assert isinstance(User.fields["name"], orm.String) assert User.fields["name"].max_length == 100 + assert isinstance(User.fields["timestamp"], orm.DateTime) assert isinstance(User.__table__, sqlalchemy.Table) @@ -157,6 +160,49 @@ async def test_model_filter(): assert await products.count() == 3 +@async_adapter +async def test_model_order_by(): + async with database: + await User.objects.create(name="Tom") + await User.objects.create(name="Allen") + await User.objects.create(name="Bob") + users = await User.objects.order_by("name").all() + assert len(users) == 3 + assert users[0].name == "Allen" + assert users[1].name == "Bob" + assert users[2].name == "Tom" + + +@async_adapter +async def test_model_order_by_desc(): + async with database: + await User.objects.create(name="Tom") + await User.objects.create(name="Allen") + await User.objects.create(name="Bob") + users = await User.objects.order_by("-name").all() + assert len(users) == 3 + assert users[0].name == "Tom" + assert users[1].name == "Bob" + assert users[2].name == "Allen" + + +@async_adapter +async def test_model_order_by_multi(): + async with database: + await User.objects.create(name="Tom", timestamp=datetime.datetime(2020, 1, 1)) + await User.objects.create(name="Tom", timestamp=datetime.datetime(2020, 7, 1)) + await User.objects.create(name="Allen", timestamp=datetime.datetime(2020, 6, 1)) + await User.objects.create(name="Acker", timestamp=datetime.datetime(2020, 12, 1)) + users = await User.objects.order_by("name", "-timestamp").all() + assert len(users) == 4 + assert users[0].name == "Acker" + assert users[1].name == "Allen" + assert users[2].name == "Tom" + assert users[2].timestamp == datetime.datetime(2020, 7, 1) + assert users[3].name == "Tom" + assert users[3].timestamp == datetime.datetime(2020, 1, 1) + + @async_adapter async def test_model_exists(): async with database: From 559f0239a36fd78fad96b4c836ab2e524a06f733 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Thu, 19 Aug 2021 18:03:45 +0430 Subject: [PATCH 02/13] format fix --- orm/models.py | 19 ++++++++++--------- tests/test_columns.py | 2 +- tests/test_foreignkey.py | 2 +- tests/test_models.py | 6 ++++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/orm/models.py b/orm/models.py index bbff84f..7d43172 100644 --- a/orm/models.py +++ b/orm/models.py @@ -48,14 +48,15 @@ def __new__( class QuerySet: ESCAPE_CHARACTERS = ["%", "_"] + def __init__( - self, - model_cls=None, - filter_clauses=None, - select_related=None, - limit_count=None, - offset=None, - order_args=None, + self, + model_cls=None, + filter_clauses=None, + select_related=None, + limit_count=None, + offset=None, + order_args=None, ): self.model_cls = model_cls self.order_args = [] if order_args is None else order_args @@ -209,8 +210,8 @@ def select_related(self, related): def _prepared_order(self): prepared = [] for order in self.order_args: - desc = order.startswith('-') - col_name = order.lstrip('-') if desc else order + desc = order.startswith("-") + col_name = order.lstrip("-") if desc else order col = self.model_cls.__table__.columns[col_name] prepared.append(col.desc() if desc else col) diff --git a/tests/test_columns.py b/tests/test_columns.py index 1dcb008..a2cb33c 100644 --- a/tests/test_columns.py +++ b/tests/test_columns.py @@ -3,10 +3,10 @@ import functools from enum import Enum -import databases import pytest import sqlalchemy +import databases import orm from tests.settings import DATABASE_URL diff --git a/tests/test_foreignkey.py b/tests/test_foreignkey.py index 4e0e957..58b5ad6 100644 --- a/tests/test_foreignkey.py +++ b/tests/test_foreignkey.py @@ -1,10 +1,10 @@ import asyncio import functools -import databases import pytest import sqlalchemy +import databases import orm from tests.settings import DATABASE_URL diff --git a/tests/test_models.py b/tests/test_models.py index e25d65a..099ddb5 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -2,10 +2,10 @@ import datetime import functools -import databases import pytest import sqlalchemy +import databases import orm from tests.settings import DATABASE_URL @@ -209,7 +209,9 @@ async def test_model_order_by_multi(): await User.objects.create(name="Tom", timestamp=datetime.datetime(2020, 1, 1)) await User.objects.create(name="Tom", timestamp=datetime.datetime(2020, 7, 1)) await User.objects.create(name="Allen", timestamp=datetime.datetime(2020, 6, 1)) - await User.objects.create(name="Acker", timestamp=datetime.datetime(2020, 12, 1)) + await User.objects.create( + name="Acker", timestamp=datetime.datetime(2020, 12, 1) + ) users = await User.objects.order_by("name", "-timestamp").all() assert len(users) == 4 assert users[0].name == "Acker" From 63637dea07d2ff8a15bc1cc5c9e0d54d83a61d52 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Thu, 19 Aug 2021 18:08:49 +0430 Subject: [PATCH 03/13] fix imports --- tests/test_columns.py | 2 +- tests/test_foreignkey.py | 2 +- tests/test_models.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_columns.py b/tests/test_columns.py index a2cb33c..1dcb008 100644 --- a/tests/test_columns.py +++ b/tests/test_columns.py @@ -3,10 +3,10 @@ import functools from enum import Enum +import databases import pytest import sqlalchemy -import databases import orm from tests.settings import DATABASE_URL diff --git a/tests/test_foreignkey.py b/tests/test_foreignkey.py index 58b5ad6..4e0e957 100644 --- a/tests/test_foreignkey.py +++ b/tests/test_foreignkey.py @@ -1,10 +1,10 @@ import asyncio import functools +import databases import pytest import sqlalchemy -import databases import orm from tests.settings import DATABASE_URL diff --git a/tests/test_models.py b/tests/test_models.py index 099ddb5..e45344a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -2,10 +2,10 @@ import datetime import functools +import databases import pytest import sqlalchemy -import databases import orm from tests.settings import DATABASE_URL From 55a9dd6d2fac7d929d3fe0bd15c45b78c072cd19 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Thu, 19 Aug 2021 18:36:54 +0430 Subject: [PATCH 04/13] minor cleanups --- orm/models.py | 22 +++++++++++----------- tests/test_models.py | 28 ++++++++++------------------ 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/orm/models.py b/orm/models.py index 7d43172..afbef28 100644 --- a/orm/models.py +++ b/orm/models.py @@ -99,7 +99,7 @@ def build_select_expression(self): expr = expr.where(clause) if self.order_args: - order_args = self._prepared_order() + order_args = self._prepare_order_args() expr = expr.order_by(*order_args) if self.limit_count: @@ -207,16 +207,6 @@ def select_related(self, related): offset=self.query_offset, ) - def _prepared_order(self): - prepared = [] - for order in self.order_args: - desc = order.startswith("-") - col_name = order.lstrip("-") if desc else order - col = self.model_cls.__table__.columns[col_name] - prepared.append(col.desc() if desc else col) - - return prepared - def order_by(self, *args): return self.__class__( model_cls=self.model_cls, @@ -311,6 +301,16 @@ async def create(self, **kwargs): instance.pk = await self.database.execute(expr) return instance + def _prepare_order_args(self): + prepared_args = [] + for order_arg in self.order_args: + is_desc = order_arg.startswith("-") + column_name = order_arg.lstrip("-") if is_desc else order_arg + column = self.model_cls.__table__.columns[column_name] + prepared_args.append(column.desc() if is_desc else column) + + return prepared_args + class Model(typesystem.Schema, metaclass=ModelMetaclass): __abstract__ = True diff --git a/tests/test_models.py b/tests/test_models.py index e45344a..fd34027 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,5 +1,4 @@ import asyncio -import datetime import functools import databases @@ -20,7 +19,6 @@ class User(orm.Model): id = orm.Integer(primary_key=True) name = orm.String(max_length=100) - timestamp = orm.DateTime(allow_null=True) class Product(orm.Model): @@ -57,12 +55,11 @@ def run_sync(*args, **kwargs): def test_model_class(): - assert list(User.fields.keys()) == ["id", "name", "timestamp"] + assert list(User.fields.keys()) == ["id", "name"] assert isinstance(User.fields["id"], orm.Integer) assert User.fields["id"].primary_key is True assert isinstance(User.fields["name"], orm.String) assert User.fields["name"].max_length == 100 - assert isinstance(User.fields["timestamp"], orm.DateTime) assert isinstance(User.__table__, sqlalchemy.Table) @@ -206,20 +203,15 @@ async def test_model_order_by_desc(): @async_adapter async def test_model_order_by_multi(): async with database: - await User.objects.create(name="Tom", timestamp=datetime.datetime(2020, 1, 1)) - await User.objects.create(name="Tom", timestamp=datetime.datetime(2020, 7, 1)) - await User.objects.create(name="Allen", timestamp=datetime.datetime(2020, 6, 1)) - await User.objects.create( - name="Acker", timestamp=datetime.datetime(2020, 12, 1) - ) - users = await User.objects.order_by("name", "-timestamp").all() - assert len(users) == 4 - assert users[0].name == "Acker" - assert users[1].name == "Allen" - assert users[2].name == "Tom" - assert users[2].timestamp == datetime.datetime(2020, 7, 1) - assert users[3].name == "Tom" - assert users[3].timestamp == datetime.datetime(2020, 1, 1) + await User.objects.create(name="Tom") + await User.objects.create(name="Tom") + await User.objects.create(name="Allen") + users = await User.objects.order_by("name", "-id").all() + assert len(users) == 3 + assert users[0].name == "Allen" + assert users[0].id == 3 + assert users[1].name == "Tom" + assert users[1].id == 2 @async_adapter From 97eefa1671bb21547b8e98fd25002bce6e594aa7 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 20 Aug 2021 11:12:13 +0430 Subject: [PATCH 05/13] try different `async_adapter` --- tests/test_models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index fd34027..55025c1 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -47,7 +47,11 @@ def async_adapter(wrapped_func): @functools.wraps(wrapped_func) def run_sync(*args, **kwargs): - loop = asyncio.new_event_loop() + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = asyncio.new_event_loop() + task = wrapped_func(*args, **kwargs) return loop.run_until_complete(task) From 89657f8e778c486e1d83033649cfd0e3305de22b Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 20 Aug 2021 11:15:44 +0430 Subject: [PATCH 06/13] revert async_adapter --- .github/workflows/test-suite.yml | 2 +- tests/test_models.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 87ee45e..183fdc6 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10.0-rc.1"] + python-version: ["3.6", "3.7", "3.9", "3.10.0-rc.1"] steps: - uses: "actions/checkout@v2" diff --git a/tests/test_models.py b/tests/test_models.py index 55025c1..fd34027 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -47,11 +47,7 @@ def async_adapter(wrapped_func): @functools.wraps(wrapped_func) def run_sync(*args, **kwargs): - try: - loop = asyncio.get_running_loop() - except RuntimeError: - loop = asyncio.new_event_loop() - + loop = asyncio.new_event_loop() task = wrapped_func(*args, **kwargs) return loop.run_until_complete(task) From 7ba733727ddddb10c38450c97bbf875fb2e677f0 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 20 Aug 2021 11:19:38 +0430 Subject: [PATCH 07/13] add python3.8 --- .github/workflows/test-suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 183fdc6..87ee45e 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - python-version: ["3.6", "3.7", "3.9", "3.10.0-rc.1"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10.0-rc.1"] steps: - uses: "actions/checkout@v2" From fe925288db45eaa091e470048ea4e366f1e7e87b Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 20 Aug 2021 11:30:48 +0430 Subject: [PATCH 08/13] add pytest-asyncio --- requirements.txt | 1 + tests/test_columns.py | 18 +----------------- tests/test_foreignkey.py | 25 ++++-------------------- tests/test_models.py | 41 ++++++++++++---------------------------- 4 files changed, 18 insertions(+), 67 deletions(-) diff --git a/requirements.txt b/requirements.txt index 73d0670..6cb41ac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,5 @@ flake8 isort mypy pytest +pytest-asyncio pytest-cov diff --git a/tests/test_columns.py b/tests/test_columns.py index 1dcb008..3847e98 100644 --- a/tests/test_columns.py +++ b/tests/test_columns.py @@ -1,6 +1,4 @@ -import asyncio import datetime -import functools from enum import Enum import databases @@ -47,21 +45,7 @@ def create_test_database(): metadata.drop_all(engine) -def async_adapter(wrapped_func): - """ - Decorator used to run async test cases. - """ - - @functools.wraps(wrapped_func) - def run_sync(*args, **kwargs): - loop = asyncio.new_event_loop() - task = wrapped_func(*args, **kwargs) - return loop.run_until_complete(task) - - return run_sync - - -@async_adapter +@pytest.mark.asyncio async def test_model_crud(): async with database: await Example.objects.create() diff --git a/tests/test_foreignkey.py b/tests/test_foreignkey.py index 4e0e957..e93f480 100644 --- a/tests/test_foreignkey.py +++ b/tests/test_foreignkey.py @@ -1,6 +1,3 @@ -import asyncio -import functools - import databases import pytest import sqlalchemy @@ -69,21 +66,7 @@ def create_test_database(): metadata.drop_all(engine) -def async_adapter(wrapped_func): - """ - Decorator used to run async test cases. - """ - - @functools.wraps(wrapped_func) - def run_sync(*args, **kwargs): - loop = asyncio.new_event_loop() - task = wrapped_func(*args, **kwargs) - return loop.run_until_complete(task) - - return run_sync - - -@async_adapter +@pytest.mark.asyncio async def test_model_crud(): async with database: album = await Album.objects.create(name="Malibu") @@ -100,7 +83,7 @@ async def test_model_crud(): assert track.album.name == "Malibu" -@async_adapter +@pytest.mark.asyncio async def test_select_related(): async with database: album = await Album.objects.create(name="Malibu") @@ -122,7 +105,7 @@ async def test_select_related(): assert len(tracks) == 6 -@async_adapter +@pytest.mark.asyncio async def test_fk_filter(): async with database: malibu = await Album.objects.create(name="Malibu") @@ -166,7 +149,7 @@ async def test_fk_filter(): assert track.album.name == "Malibu" -@async_adapter +@pytest.mark.asyncio async def test_multiple_fk(): async with database: acme = await Organisation.objects.create(ident="ACME Ltd") diff --git a/tests/test_models.py b/tests/test_models.py index fd34027..a12af23 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,6 +1,3 @@ -import asyncio -import functools - import databases import pytest import sqlalchemy @@ -40,20 +37,6 @@ def create_test_database(): metadata.drop_all(engine) -def async_adapter(wrapped_func): - """ - Decorator used to run async test cases. - """ - - @functools.wraps(wrapped_func) - def run_sync(*args, **kwargs): - loop = asyncio.new_event_loop() - task = wrapped_func(*args, **kwargs) - return loop.run_until_complete(task) - - return run_sync - - def test_model_class(): assert list(User.fields.keys()) == ["id", "name"] assert isinstance(User.fields["id"], orm.Integer) @@ -69,7 +52,7 @@ def test_model_pk(): assert user.id == 1 -@async_adapter +@pytest.mark.asyncio async def test_model_crud(): async with database: users = await User.objects.all() @@ -95,7 +78,7 @@ async def test_model_crud(): assert users == [] -@async_adapter +@pytest.mark.asyncio async def test_model_get(): async with database: with pytest.raises(orm.NoMatch): @@ -114,7 +97,7 @@ async def test_model_get(): assert same_user.pk == user.pk -@async_adapter +@pytest.mark.asyncio async def test_model_filter(): async with database: await User.objects.create(name="Tom") @@ -174,7 +157,7 @@ async def test_model_filter(): assert await products.count() == 3 -@async_adapter +@pytest.mark.asyncio async def test_model_order_by(): async with database: await User.objects.create(name="Tom") @@ -187,7 +170,7 @@ async def test_model_order_by(): assert users[2].name == "Tom" -@async_adapter +@pytest.mark.asyncio async def test_model_order_by_desc(): async with database: await User.objects.create(name="Tom") @@ -200,7 +183,7 @@ async def test_model_order_by_desc(): assert users[2].name == "Allen" -@async_adapter +@pytest.mark.asyncio async def test_model_order_by_multi(): async with database: await User.objects.create(name="Tom") @@ -214,7 +197,7 @@ async def test_model_order_by_multi(): assert users[1].id == 2 -@async_adapter +@pytest.mark.asyncio async def test_model_exists(): async with database: await User.objects.create(name="Tom") @@ -222,7 +205,7 @@ async def test_model_exists(): assert await User.objects.filter(name="Jane").exists() is False -@async_adapter +@pytest.mark.asyncio async def test_model_count(): async with database: await User.objects.create(name="Tom") @@ -233,7 +216,7 @@ async def test_model_count(): assert await User.objects.filter(name__icontains="T").count() == 1 -@async_adapter +@pytest.mark.asyncio async def test_model_limit(): async with database: await User.objects.create(name="Tom") @@ -243,7 +226,7 @@ async def test_model_limit(): assert len(await User.objects.limit(2).all()) == 2 -@async_adapter +@pytest.mark.asyncio async def test_model_limit_with_filter(): async with database: await User.objects.create(name="Tom") @@ -253,7 +236,7 @@ async def test_model_limit_with_filter(): assert len(await User.objects.limit(2).filter(name__iexact="Tom").all()) == 2 -@async_adapter +@pytest.mark.asyncio async def test_offset(): async with database: await User.objects.create(name="Tom") @@ -263,7 +246,7 @@ async def test_offset(): assert users[0].name == "Jane" -@async_adapter +@pytest.mark.asyncio async def test_model_first(): async with database: tom = await User.objects.create(name="Tom") From 889812af04ba7194f5ffaddb327d4898b5264d76 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Tue, 24 Aug 2021 15:47:43 +0430 Subject: [PATCH 09/13] add anyio --- setup.py | 2 +- tests/conftest.py | 6 ++++++ tests/test_columns.py | 3 ++- tests/test_foreignkey.py | 6 ++---- tests/test_models.py | 14 ++------------ 5 files changed, 13 insertions(+), 18 deletions(-) create mode 100644 tests/conftest.py diff --git a/setup.py b/setup.py index 5e55658..8f12135 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ def get_packages(package): packages=get_packages(PACKAGE), package_data={PACKAGE: ["py.typed"]}, data_files=[("", ["LICENSE.md"])], - install_requires=["databases>=0.2.1", "typesystem"], + install_requires=["anyio>=3.0.0,<4", "databases>=0.2.1", "typesystem"], extras_require={ "postgresql": ["asyncpg"], "mysql": ["aiomysql"], diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..2fa5cff --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,6 @@ +import pytest + + +@pytest.fixture +def anyio_backend(): + return ("asyncio", {"debug": True}) diff --git a/tests/test_columns.py b/tests/test_columns.py index 3847e98..e0aaea3 100644 --- a/tests/test_columns.py +++ b/tests/test_columns.py @@ -8,6 +8,8 @@ import orm from tests.settings import DATABASE_URL +pytestmark = pytest.mark.anyio + database = databases.Database(DATABASE_URL, force_rollback=True) metadata = sqlalchemy.MetaData() @@ -45,7 +47,6 @@ def create_test_database(): metadata.drop_all(engine) -@pytest.mark.asyncio async def test_model_crud(): async with database: await Example.objects.create() diff --git a/tests/test_foreignkey.py b/tests/test_foreignkey.py index e93f480..99fd4c8 100644 --- a/tests/test_foreignkey.py +++ b/tests/test_foreignkey.py @@ -5,6 +5,8 @@ import orm from tests.settings import DATABASE_URL +pytestmark = pytest.mark.anyio + database = databases.Database(DATABASE_URL, force_rollback=True) metadata = sqlalchemy.MetaData() @@ -66,7 +68,6 @@ def create_test_database(): metadata.drop_all(engine) -@pytest.mark.asyncio async def test_model_crud(): async with database: album = await Album.objects.create(name="Malibu") @@ -83,7 +84,6 @@ async def test_model_crud(): assert track.album.name == "Malibu" -@pytest.mark.asyncio async def test_select_related(): async with database: album = await Album.objects.create(name="Malibu") @@ -105,7 +105,6 @@ async def test_select_related(): assert len(tracks) == 6 -@pytest.mark.asyncio async def test_fk_filter(): async with database: malibu = await Album.objects.create(name="Malibu") @@ -149,7 +148,6 @@ async def test_fk_filter(): assert track.album.name == "Malibu" -@pytest.mark.asyncio async def test_multiple_fk(): async with database: acme = await Organisation.objects.create(ident="ACME Ltd") diff --git a/tests/test_models.py b/tests/test_models.py index a12af23..772c363 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -5,6 +5,8 @@ import orm from tests.settings import DATABASE_URL +pytestmark = pytest.mark.anyio + database = databases.Database(DATABASE_URL, force_rollback=True) metadata = sqlalchemy.MetaData() @@ -52,7 +54,6 @@ def test_model_pk(): assert user.id == 1 -@pytest.mark.asyncio async def test_model_crud(): async with database: users = await User.objects.all() @@ -78,7 +79,6 @@ async def test_model_crud(): assert users == [] -@pytest.mark.asyncio async def test_model_get(): async with database: with pytest.raises(orm.NoMatch): @@ -97,7 +97,6 @@ async def test_model_get(): assert same_user.pk == user.pk -@pytest.mark.asyncio async def test_model_filter(): async with database: await User.objects.create(name="Tom") @@ -157,7 +156,6 @@ async def test_model_filter(): assert await products.count() == 3 -@pytest.mark.asyncio async def test_model_order_by(): async with database: await User.objects.create(name="Tom") @@ -170,7 +168,6 @@ async def test_model_order_by(): assert users[2].name == "Tom" -@pytest.mark.asyncio async def test_model_order_by_desc(): async with database: await User.objects.create(name="Tom") @@ -183,7 +180,6 @@ async def test_model_order_by_desc(): assert users[2].name == "Allen" -@pytest.mark.asyncio async def test_model_order_by_multi(): async with database: await User.objects.create(name="Tom") @@ -197,7 +193,6 @@ async def test_model_order_by_multi(): assert users[1].id == 2 -@pytest.mark.asyncio async def test_model_exists(): async with database: await User.objects.create(name="Tom") @@ -205,7 +200,6 @@ async def test_model_exists(): assert await User.objects.filter(name="Jane").exists() is False -@pytest.mark.asyncio async def test_model_count(): async with database: await User.objects.create(name="Tom") @@ -216,7 +210,6 @@ async def test_model_count(): assert await User.objects.filter(name__icontains="T").count() == 1 -@pytest.mark.asyncio async def test_model_limit(): async with database: await User.objects.create(name="Tom") @@ -226,7 +219,6 @@ async def test_model_limit(): assert len(await User.objects.limit(2).all()) == 2 -@pytest.mark.asyncio async def test_model_limit_with_filter(): async with database: await User.objects.create(name="Tom") @@ -236,7 +228,6 @@ async def test_model_limit_with_filter(): assert len(await User.objects.limit(2).filter(name__iexact="Tom").all()) == 2 -@pytest.mark.asyncio async def test_offset(): async with database: await User.objects.create(name="Tom") @@ -246,7 +237,6 @@ async def test_offset(): assert users[0].name == "Jane" -@pytest.mark.asyncio async def test_model_first(): async with database: tom = await User.objects.create(name="Tom") From d8eef31c0f1e1a7b69ec644187c942431fe9b344 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Tue, 24 Aug 2021 15:58:11 +0430 Subject: [PATCH 10/13] Update setup.py Co-authored-by: Thomas Grainger --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8f12135..5e55658 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ def get_packages(package): packages=get_packages(PACKAGE), package_data={PACKAGE: ["py.typed"]}, data_files=[("", ["LICENSE.md"])], - install_requires=["anyio>=3.0.0,<4", "databases>=0.2.1", "typesystem"], + install_requires=["databases>=0.2.1", "typesystem"], extras_require={ "postgresql": ["asyncpg"], "mysql": ["aiomysql"], From 89839b4163c3743d26f5475302b71febf6b77953 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Tue, 24 Aug 2021 15:59:24 +0430 Subject: [PATCH 11/13] add anyio to test requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 6cb41ac..d2af520 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ twine wheel # Testing +anyio>=3.0.0,<4 autoflake black codecov From 8ad745712634a78542545484f9ff128008430768 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Tue, 24 Aug 2021 16:18:47 +0430 Subject: [PATCH 12/13] remove pytest-asyncio --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d2af520..2b39c79 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,5 +14,4 @@ flake8 isort mypy pytest -pytest-asyncio pytest-cov From b8ccba2276416040c85367c716473308cc0953a1 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Tue, 24 Aug 2021 16:22:49 +0430 Subject: [PATCH 13/13] rebase master --- orm/models.py | 26 -------------------------- tests/test_models.py | 37 ------------------------------------- 2 files changed, 63 deletions(-) diff --git a/orm/models.py b/orm/models.py index afbef28..be6e9c6 100644 --- a/orm/models.py +++ b/orm/models.py @@ -56,10 +56,8 @@ def __init__( select_related=None, limit_count=None, offset=None, - order_args=None, ): self.model_cls = model_cls - self.order_args = [] if order_args is None else order_args self.filter_clauses = [] if filter_clauses is None else filter_clauses self._select_related = [] if select_related is None else select_related self.limit_count = limit_count @@ -98,10 +96,6 @@ def build_select_expression(self): clause = sqlalchemy.sql.and_(*self.filter_clauses) expr = expr.where(clause) - if self.order_args: - order_args = self._prepare_order_args() - expr = expr.order_by(*order_args) - if self.limit_count: expr = expr.limit(self.limit_count) @@ -207,16 +201,6 @@ def select_related(self, related): offset=self.query_offset, ) - def order_by(self, *args): - return self.__class__( - model_cls=self.model_cls, - filter_clauses=self.filter_clauses, - select_related=self._select_related, - limit_count=self.limit_count, - offset=self.query_offset, - order_args=args, - ) - async def exists(self) -> bool: expr = self.build_select_expression() expr = sqlalchemy.exists(expr).select() @@ -301,16 +285,6 @@ async def create(self, **kwargs): instance.pk = await self.database.execute(expr) return instance - def _prepare_order_args(self): - prepared_args = [] - for order_arg in self.order_args: - is_desc = order_arg.startswith("-") - column_name = order_arg.lstrip("-") if is_desc else order_arg - column = self.model_cls.__table__.columns[column_name] - prepared_args.append(column.desc() if is_desc else column) - - return prepared_args - class Model(typesystem.Schema, metaclass=ModelMetaclass): __abstract__ = True diff --git a/tests/test_models.py b/tests/test_models.py index 772c363..0bc6940 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -156,43 +156,6 @@ async def test_model_filter(): assert await products.count() == 3 -async def test_model_order_by(): - async with database: - await User.objects.create(name="Tom") - await User.objects.create(name="Allen") - await User.objects.create(name="Bob") - users = await User.objects.order_by("name").all() - assert len(users) == 3 - assert users[0].name == "Allen" - assert users[1].name == "Bob" - assert users[2].name == "Tom" - - -async def test_model_order_by_desc(): - async with database: - await User.objects.create(name="Tom") - await User.objects.create(name="Allen") - await User.objects.create(name="Bob") - users = await User.objects.order_by("-name").all() - assert len(users) == 3 - assert users[0].name == "Tom" - assert users[1].name == "Bob" - assert users[2].name == "Allen" - - -async def test_model_order_by_multi(): - async with database: - await User.objects.create(name="Tom") - await User.objects.create(name="Tom") - await User.objects.create(name="Allen") - users = await User.objects.order_by("name", "-id").all() - assert len(users) == 3 - assert users[0].name == "Allen" - assert users[0].id == 3 - assert users[1].name == "Tom" - assert users[1].id == 2 - - async def test_model_exists(): async with database: await User.objects.create(name="Tom")