Iterators QuerySet Method (#688)

* feat: add iterator function with sample docstring

* feat: implement the iterator queryset method

* feat: completed the docstring of iterator method

* test: write test function to check iterator result

* refactor: use iterate method instead fetch_all

* fix: debuging syntax error in kwargs of iterator

* feat: write a base sample doc for iterator method

* refactor: add ouput comment iterator docs example

* refactor: check change pk yield ormar model

* test: write new test to coverage iterator queryset

* fix: debuging new user model class 3 number

* fix: iterate on user3 model class

* fix: debug id field in user3 model by main user

* fix: remove prefetch_related for iterator method

* fix: debug mypy test for type annotation

* fix: added type annotation for rows variable

* simplify row checks as processing is expensive, raise exception on prefetch_related with iterator

* fix coverage

* fix mypy, bump mypy in pre-commit to newest version

* refactor: update document and test uuid pk type

* feat: write docs of iterate in quesrysetproxy

* feat: write iterate method querysetproxy tests

* fix: debuging new test written uuid pk

* refactor: seperate iterate test modules

* refactor: change description and handle empty set

* feat: added iterate method in readme files

* fix: set pragma: no cover for raised test

Co-authored-by: collerek <collerek@gmail.com>
This commit is contained in:
Sepehr Bazyar
2022-07-04 15:11:28 +04:30
committed by GitHub
parent 20cddde2f4
commit 06c3bdb5eb
8 changed files with 403 additions and 3 deletions

View File

@ -12,6 +12,7 @@ from typing import (
TypeVar,
Union,
cast,
AsyncGenerator,
)
import databases
@ -1055,6 +1056,55 @@ class QuerySet(Generic[T]):
return result_rows
async def iterate( # noqa: A003
self,
*args: Any,
**kwargs: Any,
) -> AsyncGenerator["T", None]:
"""
Return async iterable generator for all rows from a database for given model.
Passing args and/or kwargs is a shortcut and equals to calling
`filter(*args, **kwargs).iterate()`.
If there are no rows meeting the criteria an empty async generator is returned.
:param kwargs: fields names and proper value types
:type kwargs: Any
:return: asynchronous iterable generator of returned models
:rtype: AsyncGenerator[Model]
"""
if self._prefetch_related:
raise QueryDefinitionError(
"Prefetch related queries are not supported in iterators"
)
if kwargs or args:
async for result in self.filter(*args, **kwargs).iterate():
yield result
return
expr = self.build_select_expression()
rows: list = []
last_primary_key = None
pk_alias = self.model.get_column_alias(self.model_meta.pkname)
async for row in self.database.iterate(query=expr):
current_primary_key = row[pk_alias]
if last_primary_key == current_primary_key or last_primary_key is None:
last_primary_key = current_primary_key
rows.append(row)
continue
yield self._process_query_result_rows(rows)[0]
last_primary_key = current_primary_key
rows = [row]
if rows:
yield self._process_query_result_rows(rows)[0]
async def create(self, **kwargs: Any) -> "T":
"""
Creates the model instance, saves it in a database and returns the updates model

View File

@ -14,6 +14,7 @@ from typing import ( # noqa: I100, I201
TypeVar,
Union,
cast,
AsyncGenerator,
)
import ormar # noqa: I100, I202
@ -431,6 +432,28 @@ class QuerysetProxy(Generic[T]):
self._register_related(all_items)
return all_items
async def iterate( # noqa: A003
self,
*args: Any,
**kwargs: Any,
) -> AsyncGenerator["T", None]:
"""
Return async iterable generator for all rows from a database for given model.
Passing args and/or kwargs is a shortcut and equals to calling
`filter(*args, **kwargs).iterate()`.
If there are no rows meeting the criteria an empty async generator is returned.
:param kwargs: fields names and proper value types
:type kwargs: Any
:return: asynchronous iterable generator of returned models
:rtype: AsyncGenerator[Model]
"""
async for item in self.queryset.iterate(*args, **kwargs):
yield item
async def create(self, **kwargs: Any) -> "T":
"""
Creates the model instance, saves it in a database and returns the updates model