-
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
aggregate()
, insert_many()
and save()
Queries
- Loading branch information
Showing
11 changed files
with
454 additions
and
341 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import operator | ||
from abc import abstractmethod | ||
from functools import reduce | ||
from sys import version_info | ||
|
||
from pydantic_core._pydantic_core import ValidationError | ||
|
||
from panther.db.cursor import Cursor | ||
from panther.db.utils import prepare_id_for_query | ||
from panther.exceptions import DatabaseError | ||
|
||
if version_info >= (3, 11): | ||
from typing import Self, Iterator | ||
else: | ||
from typing import TypeVar | ||
|
||
Self = TypeVar('Self', bound='BaseQuery') | ||
|
||
|
||
class BaseQuery: | ||
@classmethod | ||
def _merge(cls, *args, is_mongo: bool = False) -> dict: | ||
prepare_id_for_query(*args, is_mongo=is_mongo) | ||
return reduce(operator.ior, filter(None, args), {}) | ||
|
||
@classmethod | ||
def _clean_error_message(cls, validation_error: ValidationError, is_updating: bool = False) -> str: | ||
error = ', '.join( | ||
'{field}="{error}"'.format( | ||
field='.'.join(loc for loc in e['loc']), | ||
error=e['msg'] | ||
) | ||
for e in validation_error.errors() | ||
if not is_updating or e['type'] != 'missing' | ||
) | ||
return f'{cls.__name__}({error})' if error else '' | ||
|
||
@classmethod | ||
def _validate_data(cls, *, data: dict, is_updating: bool = False): | ||
"""Validate document before inserting to collection""" | ||
try: | ||
cls(**data) | ||
except ValidationError as validation_error: | ||
if error := cls._clean_error_message(validation_error=validation_error, is_updating=is_updating): | ||
raise DatabaseError(error) | ||
|
||
@classmethod | ||
def _create_model_instance(cls, document: dict): | ||
"""Prevent getting errors from document insertion""" | ||
try: | ||
return cls(**document) | ||
except ValidationError as validation_error: | ||
if error := cls._clean_error_message(validation_error=validation_error): | ||
raise DatabaseError(error) | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def find_one(cls, *args, **kwargs) -> Self | None: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def find(cls, *args, **kwargs) -> list[Self] | Cursor: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def first(cls, *args, **kwargs) -> Self | None: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def last(cls, *args, **kwargs): | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def aggregate(cls, *args, **kwargs) -> Iterator[dict]: | ||
raise NotImplementedError | ||
|
||
# # # # # Count # # # # # | ||
@classmethod | ||
@abstractmethod | ||
async def count(cls, *args, **kwargs) -> int: | ||
raise NotImplementedError | ||
|
||
# # # # # Insert # # # # # | ||
@classmethod | ||
@abstractmethod | ||
async def insert_one(cls, *args, **kwargs) -> Self: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def insert_many(cls, *args, **kwargs) -> list[Self]: | ||
raise NotImplementedError | ||
|
||
# # # # # Delete # # # # # | ||
@abstractmethod | ||
async def delete(self) -> None: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def delete_one(cls, *args, **kwargs) -> bool: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def delete_many(cls, *args, **kwargs) -> int: | ||
raise NotImplementedError | ||
|
||
# # # # # Update # # # # # | ||
@abstractmethod | ||
async def update(self, *args, **kwargs) -> None: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def update_one(cls, *args, **kwargs) -> bool: | ||
raise NotImplementedError | ||
|
||
@classmethod | ||
@abstractmethod | ||
async def update_many(cls, *args, **kwargs) -> int: | ||
raise NotImplementedError |
Oops, something went wrong.