From 7d0c8fecf9c10049d2a76f24d37b2d67576f390d Mon Sep 17 00:00:00 2001 From: Sepehr Date: Thu, 28 Jul 2022 19:48:07 +0430 Subject: [PATCH 01/18] feat: add getitem magic method to slicing queryset --- ormar/queryset/queryset.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ormar/queryset/queryset.py b/ormar/queryset/queryset.py index 5ae40b6ef..35a8e314b 100644 --- a/ormar/queryset/queryset.py +++ b/ormar/queryset/queryset.py @@ -1217,3 +1217,30 @@ async def bulk_update( # noqa: CCR001 await cast(Type["Model"], self.model_cls).Meta.signals.post_bulk_update.send( sender=self.model_cls, instances=objects # type: ignore ) + + def __getitem__(self, key: Union[int, slice]) -> "QuerySet[T]": + """Retrieve an item or slice from the set of results.""" + + if not isinstance(key, (int, slice)): + raise TypeError(f"{key} is neither an integer nor a range.") + + if isinstance(key, int): + if key < 0: + raise ValueError("Negative indexing is not supported.") + + return self.rebuild_self(offset=key, limit_count=1) + + if key.step is not None and key.step != 1: + raise ValueError(f"{key.step} steps are not supported, only one.") + + if ( + (key.start is not None and key.start < 0) + or (key.stop is not None and key.stop < 0) + or (key.start is not None and key.stop is not None and key.stop < key.start) + ): + raise ValueError("The selected range is not valid.") + + return self.rebuild_self( + offset=key.start, + limit_count=key.stop - (key.start or 0) if key.stop is not None else None, + ) From 483394e5456b8750ca199bab2604ade8b141ee8a Mon Sep 17 00:00:00 2001 From: Sepehr Date: Thu, 28 Jul 2022 20:31:01 +0430 Subject: [PATCH 02/18] test: write two tests for check getitem slicing --- tests/test_queries/test_pagination.py | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index d49e5bf7f..385ec2a0c 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -108,3 +108,47 @@ async def test_proxy_pagination(): await user.cars.paginate(2, page_size=10).all() assert len(user.cars) == 10 assert user.cars[0].name == "10" + + +@pytest.mark.asyncio +async def test_slice_getitem_queryset_exceptions(): + async with database: + async with database.transaction(force_rollback=True): + with pytest.raises(TypeError): + await Car.objects["foo"].all() + + with pytest.raises(ValueError): + await Car.objects[-1].all() + + with pytest.raises(ValueError): + await Car.objects[::2].all() + + with pytest.raises(ValueError): + await Car.objects[2:1].all() + + +@pytest.mark.asyncio +async def test_slice_getitem_queryset_successfully(): + async with database: + async with database.transaction(force_rollback=True): + for i in range(10): + await Car(name=f"{i}").save() + + cars_page1 = await Car.objects[2:8].all() + assert len(cars_page1) == 6 + assert cars_page1[0].name == "2" + assert cars_page1[-1].name == "7" + + cars_page2 = await Car.objects[2:].all() + assert len(cars_page2) == 8 + assert cars_page2[0].name == "2" + assert cars_page2[-1].name == "10" + + cars_page3 = await Car.objects[:8].all() + assert len(cars_page3) == 7 + assert cars_page3[0].name == "0" + assert cars_page3[-1].name == "7" + + cars_page4 = await Car.objects[5].all() + assert len(cars_page4) == 1 + assert cars_page4[0].name == "6" From ef951ffeca32e93d60b54a0849e42b32d38f7505 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Thu, 28 Jul 2022 20:45:14 +0430 Subject: [PATCH 03/18] docs: add two note for slicing details in document --- docs/queries/pagination-and-rows-number.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/queries/pagination-and-rows-number.md b/docs/queries/pagination-and-rows-number.md index d29284254..5efabf6e5 100644 --- a/docs/queries/pagination-and-rows-number.md +++ b/docs/queries/pagination-and-rows-number.md @@ -73,7 +73,12 @@ tracks = await Track.objects.limit(1).all() So operations like `filter()`, `select_related()`, `limit()` and `offset()` etc. can be chained. - Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()` + Something like `Track.objects.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()` + +!!!note + You can slice the results; But note that negative indexing is not supported. + + Something like: `Track.objects[5:10].all()` ## offset @@ -107,8 +112,12 @@ tracks = await Track.objects.offset(1).limit(1).all() So operations like `filter()`, `select_related()`, `limit()` and `offset()` etc. can be chained. - Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()` + Something like `Track.objects.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()` + +!!!note + You can slice the results; But note that negative indexing is not supported. + Something like: `Track.objects[5:10].all()` ## get From 1055e9696292dada5aec71bda4d134d2b90d5409 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Thu, 28 Jul 2022 20:59:19 +0430 Subject: [PATCH 04/18] feat: added getitem for queryset proxy --- ormar/relations/querysetproxy.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ormar/relations/querysetproxy.py b/ormar/relations/querysetproxy.py index e27934dbf..223b87149 100644 --- a/ormar/relations/querysetproxy.py +++ b/ormar/relations/querysetproxy.py @@ -874,3 +874,11 @@ def order_by(self, columns: Union[List, str, "OrderAction"]) -> "QuerysetProxy[T return self.__class__( relation=self.relation, type_=self.type_, to=self.to, qryset=queryset ) + + def __getitem__(self, key: Union[int, slice]) -> "QuerysetProxy[T]": + """Retrieve an item or slice from the set of results.""" + + queryset = self.queryset[key] + return self.__class__( + relation=self.relation, type_=self.type_, to=self.to, qryset=queryset + ) From eda8259c96746ca1cdf0596bac49bcd3a26a784d Mon Sep 17 00:00:00 2001 From: Sepehr Date: Thu, 28 Jul 2022 21:24:46 +0430 Subject: [PATCH 05/18] fix: debuging for coverage test codes --- tests/test_queries/test_pagination.py | 38 ++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index 385ec2a0c..56b9b45b3 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -128,7 +128,7 @@ async def test_slice_getitem_queryset_exceptions(): @pytest.mark.asyncio -async def test_slice_getitem_queryset_successfully(): +async def test_slice_getitem_queryset_on_single_model(): async with database: async with database.transaction(force_rollback=True): for i in range(10): @@ -142,13 +142,43 @@ async def test_slice_getitem_queryset_successfully(): cars_page2 = await Car.objects[2:].all() assert len(cars_page2) == 8 assert cars_page2[0].name == "2" - assert cars_page2[-1].name == "10" + assert cars_page2[-1].name == "9" cars_page3 = await Car.objects[:8].all() - assert len(cars_page3) == 7 + assert len(cars_page3) == 8 assert cars_page3[0].name == "0" assert cars_page3[-1].name == "7" cars_page4 = await Car.objects[5].all() assert len(cars_page4) == 1 - assert cars_page4[0].name == "6" + assert cars_page4[0].name == "5" + + +@pytest.mark.asyncio +async def test_slice_getitem_queryset_on_relational_model(): + async with database: + async with database.transaction(force_rollback=True): + user = await User(name="Sep").save() + + for i in range(10): + c = await Car(name=f"{i}").save() + await user.cars.add(c) + + await user.cars[2:8].all() + assert len(user.cars) == 6 + assert user.cars[0].name == "2" + assert user.cars[-1].name == "7" + + await user.cars[2:].all() + assert len(user.cars) == 8 + assert user.cars[0].name == "2" + assert user.cars[-1].name == "9" + + await user.cars[:8].all() + assert len(user.cars) == 8 + assert user.cars[0].name == "0" + assert user.cars[-1].name == "7" + + await user.cars[5].all() + assert len(user.cars) == 1 + assert user.cars[0].name == "5" From b8c789e9af03c94b0cd041a97223cf1e286d47cc Mon Sep 17 00:00:00 2001 From: Sepehr Date: Thu, 28 Jul 2022 21:33:06 +0430 Subject: [PATCH 06/18] perf: try to better simplifying logical expression --- ormar/queryset/queryset.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ormar/queryset/queryset.py b/ormar/queryset/queryset.py index 35a8e314b..2cb84d19f 100644 --- a/ormar/queryset/queryset.py +++ b/ormar/queryset/queryset.py @@ -1233,10 +1233,10 @@ def __getitem__(self, key: Union[int, slice]) -> "QuerySet[T]": if key.step is not None and key.step != 1: raise ValueError(f"{key.step} steps are not supported, only one.") + start, stop = key.start is not None, key.stop is not None if ( - (key.start is not None and key.start < 0) - or (key.stop is not None and key.stop < 0) - or (key.start is not None and key.stop is not None and key.stop < key.start) + (start and key.start < 0) or (stop and key.stop < 0) + or (start and stop and key.stop < key.start) ): raise ValueError("The selected range is not valid.") From 13bc85a615ee6ecba1d76b142c74e37c72cd3316 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Thu, 28 Jul 2022 21:51:46 +0430 Subject: [PATCH 07/18] fix: remove getitem in childrens list models proxy --- ormar/relations/querysetproxy.py | 8 ------- tests/test_queries/test_pagination.py | 30 --------------------------- 2 files changed, 38 deletions(-) diff --git a/ormar/relations/querysetproxy.py b/ormar/relations/querysetproxy.py index 223b87149..e27934dbf 100644 --- a/ormar/relations/querysetproxy.py +++ b/ormar/relations/querysetproxy.py @@ -874,11 +874,3 @@ def order_by(self, columns: Union[List, str, "OrderAction"]) -> "QuerysetProxy[T return self.__class__( relation=self.relation, type_=self.type_, to=self.to, qryset=queryset ) - - def __getitem__(self, key: Union[int, slice]) -> "QuerysetProxy[T]": - """Retrieve an item or slice from the set of results.""" - - queryset = self.queryset[key] - return self.__class__( - relation=self.relation, type_=self.type_, to=self.to, qryset=queryset - ) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index 56b9b45b3..1afd0ba41 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -152,33 +152,3 @@ async def test_slice_getitem_queryset_on_single_model(): cars_page4 = await Car.objects[5].all() assert len(cars_page4) == 1 assert cars_page4[0].name == "5" - - -@pytest.mark.asyncio -async def test_slice_getitem_queryset_on_relational_model(): - async with database: - async with database.transaction(force_rollback=True): - user = await User(name="Sep").save() - - for i in range(10): - c = await Car(name=f"{i}").save() - await user.cars.add(c) - - await user.cars[2:8].all() - assert len(user.cars) == 6 - assert user.cars[0].name == "2" - assert user.cars[-1].name == "7" - - await user.cars[2:].all() - assert len(user.cars) == 8 - assert user.cars[0].name == "2" - assert user.cars[-1].name == "9" - - await user.cars[:8].all() - assert len(user.cars) == 8 - assert user.cars[0].name == "0" - assert user.cars[-1].name == "7" - - await user.cars[5].all() - assert len(user.cars) == 1 - assert user.cars[0].name == "5" From 7efd615366ecd0de3bb06727a05438aa9928b811 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 30 Jul 2022 14:03:23 +0430 Subject: [PATCH 08/18] refactor: simplifying check key data type --- ormar/queryset/queryset.py | 23 +++---------------- ormar/queryset/utils.py | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/ormar/queryset/queryset.py b/ormar/queryset/queryset.py index 3c19bfe55..c5a15cfa1 100644 --- a/ormar/queryset/queryset.py +++ b/ormar/queryset/queryset.py @@ -41,6 +41,7 @@ class LegacyRow(dict): # type: ignore from ormar.queryset.queries.prefetch_query import PrefetchQuery from ormar.queryset.queries.query import Query from ormar.queryset.reverse_alias_resolver import ReverseAliasResolver +from ormar.queryset.utils import get_limit_offset if TYPE_CHECKING: # pragma no cover from ormar import Model @@ -1224,23 +1225,5 @@ def __getitem__(self, key: Union[int, slice]) -> "QuerySet[T]": if not isinstance(key, (int, slice)): raise TypeError(f"{key} is neither an integer nor a range.") - if isinstance(key, int): - if key < 0: - raise ValueError("Negative indexing is not supported.") - - return self.rebuild_self(offset=key, limit_count=1) - - if key.step is not None and key.step != 1: - raise ValueError(f"{key.step} steps are not supported, only one.") - - start, stop = key.start is not None, key.stop is not None - if ( - (start and key.start < 0) or (stop and key.stop < 0) - or (start and stop and key.stop < key.start) - ): - raise ValueError("The selected range is not valid.") - - return self.rebuild_self( - offset=key.start, - limit_count=key.stop - (key.start or 0) if key.stop is not None else None, - ) + limit, offset = get_limit_offset(key=key) + return self.rebuild_self(offset=offset, limit_count=limit) diff --git a/ormar/queryset/utils.py b/ormar/queryset/utils.py index 4ebe07c7f..d41f8baaa 100644 --- a/ormar/queryset/utils.py +++ b/ormar/queryset/utils.py @@ -11,6 +11,7 @@ Tuple, Type, Union, + Literal, ) if TYPE_CHECKING: # pragma no cover @@ -340,3 +341,47 @@ def _process_through_field( else: relation = related_field.related_name return previous_model, relation, is_through + + +def _int_limit_offset(key: int) -> Tuple[Literal[1], int]: + """ + Returned the `Limit` & `Offset` Calculated for Integer Object. + + :param key: integer number in `__getitem__` + :type key: int + :return: limit_count, offset + :rtype: Tuple[Optional[int], Optional[int]] + """ + + if key < 0: + raise ValueError("Negative indexing is not supported.") + + return 1, key + + +def _slice_limit_offset(key: slice) -> Tuple[Optional[int], Optional[int]]: + """ + Returned the `Limit` & `Offset` Calculated for Slice Object. + + :param key: slice object in `__getitem__` + :type key: slice + :return: limit_count, offset + :rtype: Tuple[Optional[int], Optional[int]] + """ + + if key.step is not None and key.step != 1: + raise ValueError(f"{key.step} steps are not supported, only one.") + + start, stop = key.start is not None, key.stop is not None + if (start and key.start < 0) or (stop and key.stop < 0): + raise ValueError("The selected range is not valid.") + + limit_count: Optional[int] = max(key.stop - (key.start or 0), 0) if stop else None + return limit_count, key.start + + +def get_limit_offset(key: Union[int, slice]) -> Tuple[Optional[int], Optional[int]]: + """Utility to Select Limit Offset Function by `key` Type Slice or Integer""" + + func = _int_limit_offset if isinstance(key, int) else _slice_limit_offset + return func(key=key) From 66162850e513ed57b3f098010b3047cc0bc41f3a Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 30 Jul 2022 14:09:24 +0430 Subject: [PATCH 09/18] fix: debug wrong test for reverse slice --- tests/test_queries/test_pagination.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index ef66f0227..53aebec4d 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -135,9 +135,6 @@ async def test_slice_getitem_queryset_exceptions(): with pytest.raises(ValueError): await Car.objects[::2].all() - with pytest.raises(ValueError): - await Car.objects[2:1].all() - @pytest.mark.asyncio async def test_slice_getitem_queryset_on_single_model(): @@ -164,3 +161,7 @@ async def test_slice_getitem_queryset_on_single_model(): cars_page4 = await Car.objects[5].all() assert len(cars_page4) == 1 assert cars_page4[0].name == "5" + + cars_page5 = await Car.objects[8:2].all() + assert len(cars_page5) == 0 + assert cars_page5 == [] From 8c4f4ce89b978fb1f4835986a8697f071135446a Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 30 Jul 2022 14:16:00 +0430 Subject: [PATCH 10/18] test: write new test for coverage negative range --- tests/test_queries/test_pagination.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index 53aebec4d..080f1710d 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -135,6 +135,9 @@ async def test_slice_getitem_queryset_exceptions(): with pytest.raises(ValueError): await Car.objects[::2].all() + with pytest.raises(ValueError): + await Car.objects[-2:-1].all() + @pytest.mark.asyncio async def test_slice_getitem_queryset_on_single_model(): From 61f42e10a5317e33efb7bd9636c41b2ff6306bc8 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 30 Jul 2022 14:41:38 +0430 Subject: [PATCH 11/18] fix: set any type for get func variable --- ormar/queryset/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ormar/queryset/utils.py b/ormar/queryset/utils.py index d41f8baaa..2e374d0dd 100644 --- a/ormar/queryset/utils.py +++ b/ormar/queryset/utils.py @@ -12,6 +12,7 @@ Type, Union, Literal, + Callable, ) if TYPE_CHECKING: # pragma no cover @@ -383,5 +384,5 @@ def _slice_limit_offset(key: slice) -> Tuple[Optional[int], Optional[int]]: def get_limit_offset(key: Union[int, slice]) -> Tuple[Optional[int], Optional[int]]: """Utility to Select Limit Offset Function by `key` Type Slice or Integer""" - func = _int_limit_offset if isinstance(key, int) else _slice_limit_offset + func: Any = _int_limit_offset if isinstance(key, int) else _slice_limit_offset return func(key=key) From 595f86126d46e352fb82eb03f50d61db9467b26e Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 30 Jul 2022 15:40:13 +0430 Subject: [PATCH 12/18] fix: handle import error literal python 3.7 --- ormar/queryset/utils.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ormar/queryset/utils.py b/ormar/queryset/utils.py index 2e374d0dd..939eb1e0a 100644 --- a/ormar/queryset/utils.py +++ b/ormar/queryset/utils.py @@ -11,13 +11,16 @@ Tuple, Type, Union, - Literal, - Callable, ) if TYPE_CHECKING: # pragma no cover from ormar import Model, BaseField +try: + from typing import Literal # type: ignore +except ImportError: # pragma: no cover + from typing_extensions import Literal # type: ignore + def check_node_not_dict_or_not_last_node( part: str, is_last: bool, current_level: Any @@ -384,5 +387,5 @@ def _slice_limit_offset(key: slice) -> Tuple[Optional[int], Optional[int]]: def get_limit_offset(key: Union[int, slice]) -> Tuple[Optional[int], Optional[int]]: """Utility to Select Limit Offset Function by `key` Type Slice or Integer""" - func: Any = _int_limit_offset if isinstance(key, int) else _slice_limit_offset - return func(key=key) + func = _int_limit_offset if isinstance(key, int) else _slice_limit_offset + return func(key=key) # type: ignore From c53c4a9d83e90ba7116bd8b7d5331f5e9c433b96 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Fri, 26 Aug 2022 23:55:49 +0430 Subject: [PATCH 13/18] feat: added getitem slicing for queryset proxy --- ormar/relations/querysetproxy.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ormar/relations/querysetproxy.py b/ormar/relations/querysetproxy.py index e27934dbf..a3c96cffc 100644 --- a/ormar/relations/querysetproxy.py +++ b/ormar/relations/querysetproxy.py @@ -874,3 +874,19 @@ def order_by(self, columns: Union[List, str, "OrderAction"]) -> "QuerysetProxy[T return self.__class__( relation=self.relation, type_=self.type_, to=self.to, qryset=queryset ) + + def __getitem__(self, key: Union[int, slice]) -> "QuerysetProxy[T]": + """ + You can slice the results to desired number of parent models. + + Actual call delegated to QuerySet. + + :param key: numbers of models to slicing + :type key: int | slice + :return: QuerysetProxy + :rtype: QuerysetProxy + """ + queryset = self.queryset[key] + return self.__class__( + relation=self.relation, type_=self.type_, to=self.to, qryset=queryset + ) From 0457e56ac4d8b4bc0364fb5c7ec663e437b50af3 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 27 Aug 2022 00:02:02 +0430 Subject: [PATCH 14/18] test: write new test for slicing querysetproxy --- tests/test_queries/test_pagination.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index 080f1710d..cce8fc633 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -168,3 +168,28 @@ async def test_slice_getitem_queryset_on_single_model(): cars_page5 = await Car.objects[8:2].all() assert len(cars_page5) == 0 assert cars_page5 == [] + + +@pytest.mark.asyncio +async def test_slice_getitem_queryset_on_proxy(): + async with database: + async with database.transaction(force_rollback=True): + user = await User(name="Sep").save() + + for i in range(20): + c = await Car(name=f"{i}").save() + await user.cars.add(c) + + await user.cars[:5].all() + assert len(user.cars) == 5 + assert user.cars[0].name == "0" + assert user.cars[4].name == "4" + + await user.cars[5:10].all() + assert len(user.cars) == 5 + assert user.cars[0].name == "5" + assert user.cars[4].name == "9" + + await user.cars[10:].all() + assert len(user.cars) == 10 + assert user.cars[0].name == "10" From 65846e84090d3fffbfc1deb4d12a43aff4f2e27c Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 27 Aug 2022 00:09:51 +0430 Subject: [PATCH 15/18] fix: debug call all method on relation list models --- tests/test_queries/test_pagination.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index cce8fc633..be187a79e 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -180,16 +180,16 @@ async def test_slice_getitem_queryset_on_proxy(): c = await Car(name=f"{i}").save() await user.cars.add(c) - await user.cars[:5].all() + await user.cars[:5] assert len(user.cars) == 5 assert user.cars[0].name == "0" assert user.cars[4].name == "4" - await user.cars[5:10].all() + await user.cars[5:10] assert len(user.cars) == 5 assert user.cars[0].name == "5" assert user.cars[4].name == "9" - await user.cars[10:].all() + await user.cars[10:] assert len(user.cars) == 10 assert user.cars[0].name == "10" From b195662afc780760710ef2d6c1b757817798f91c Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 27 Aug 2022 00:15:52 +0430 Subject: [PATCH 16/18] fix: debug await expression slicing --- tests/test_queries/test_pagination.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index be187a79e..c873fca14 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -180,16 +180,16 @@ async def test_slice_getitem_queryset_on_proxy(): c = await Car(name=f"{i}").save() await user.cars.add(c) - await user.cars[:5] + user.cars[:5] assert len(user.cars) == 5 assert user.cars[0].name == "0" assert user.cars[4].name == "4" - await user.cars[5:10] + user.cars[5:10] assert len(user.cars) == 5 assert user.cars[0].name == "5" assert user.cars[4].name == "9" - await user.cars[10:] + user.cars[10:] assert len(user.cars) == 10 assert user.cars[0].name == "10" From 7330d56505e0d3c4574b05e463ce1f596fa61e13 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 27 Aug 2022 00:23:33 +0430 Subject: [PATCH 17/18] fix: save querysetproxy sliced into a list --- tests/test_queries/test_pagination.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index c873fca14..7f8ac61d5 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -180,16 +180,16 @@ async def test_slice_getitem_queryset_on_proxy(): c = await Car(name=f"{i}").save() await user.cars.add(c) - user.cars[:5] - assert len(user.cars) == 5 - assert user.cars[0].name == "0" - assert user.cars[4].name == "4" + cars_page1 = user.cars[:5] + assert len(cars_page1) == 5 + assert cars_page1[0].name == "0" + assert cars_page1[4].name == "4" - user.cars[5:10] - assert len(user.cars) == 5 - assert user.cars[0].name == "5" - assert user.cars[4].name == "9" + cars_page2 = user.cars[5:10] + assert len(cars_page2) == 5 + assert cars_page2[0].name == "5" + assert cars_page2[4].name == "9" - user.cars[10:] - assert len(user.cars) == 10 - assert user.cars[0].name == "10" + cars_page3 = user.cars[10:] + assert len(cars_page3) == 10 + assert cars_page3[0].name == "10" From 8a8186e6b3c1663bcf0293071bc4ecf4675718bf Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sat, 27 Aug 2022 16:33:42 +0430 Subject: [PATCH 18/18] fix: debuging tests with add filter method call --- tests/test_queries/test_pagination.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/test_queries/test_pagination.py b/tests/test_queries/test_pagination.py index 7f8ac61d5..70a9403c5 100644 --- a/tests/test_queries/test_pagination.py +++ b/tests/test_queries/test_pagination.py @@ -180,16 +180,19 @@ async def test_slice_getitem_queryset_on_proxy(): c = await Car(name=f"{i}").save() await user.cars.add(c) - cars_page1 = user.cars[:5] - assert len(cars_page1) == 5 - assert cars_page1[0].name == "0" - assert cars_page1[4].name == "4" + await user.cars.filter(id__gte=0)[:5].all() + assert len(user.cars) == 5 + assert user.cars[0].name == "0" + assert user.cars[4].name == "4" - cars_page2 = user.cars[5:10] - assert len(cars_page2) == 5 - assert cars_page2[0].name == "5" - assert cars_page2[4].name == "9" + await user.cars.filter(id__gte=0)[5:10].all() + assert len(user.cars) == 5 + assert user.cars[0].name == "5" + assert user.cars[4].name == "9" - cars_page3 = user.cars[10:] - assert len(cars_page3) == 10 - assert cars_page3[0].name == "10" + await user.cars.filter(id__gte=0)[10].all() + assert len(user.cars) == 1 + + await user.cars.filter(id__gte=0)[10:].all() + assert len(user.cars) == 10 + assert user.cars[0].name == "10"