Skip to content

Commit

Permalink
fix: tests and linter
Browse files Browse the repository at this point in the history
  • Loading branch information
Ale-Cas committed Jan 20, 2024
1 parent b10adc9 commit 90e9a1b
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 9 deletions.
4 changes: 3 additions & 1 deletion src/querytyper/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""querytyper package."""
from querytyper.mongo import MongoQuery, MongoModelMetaclass
from querytyper.mongo import MongoModelMetaclass, MongoQuery, exists, regex_query

__all__ = [
"MongoQuery",
"MongoModelMetaclass",
"regex_query",
"exists",
]
4 changes: 3 additions & 1 deletion src/querytyper/mongo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""querytyper package."""
from querytyper.mongo.query import MongoQuery, MongoModelMetaclass
from querytyper.mongo.query import MongoModelMetaclass, MongoQuery, exists, regex_query

__all__ = [
"MongoQuery",
"MongoModelMetaclass",
"regex_query",
"exists",
]
15 changes: 9 additions & 6 deletions src/querytyper/mongo/query.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""MongoQuery ."""
import re
from collections.abc import Iterable
from pprint import pformat
import re
from typing import Any, Generic, Tuple, Type, TypeVar, Union, cast, Dict
from typing import Any, Dict, Generic, Tuple, Type, TypeVar, Union, cast

from pydantic import BaseModel
from pydantic.main import ModelMetaclass
Expand All @@ -28,6 +28,11 @@ def __init__(self, *args: Any) -> None:
# clean up MongoQuery _dict at each instantiation
MongoQuery._dict = {}

def __del__(self) -> None:
"""MongoQuery destructor."""
self._dict = {}
MongoQuery._dict = {}

def __repr__(self) -> str:
"""Overload repr method to pretty format it."""
return pformat(self._dict)
Expand Down Expand Up @@ -102,9 +107,7 @@ def __eq__( # type: ignore[override]
"""Overload == operator."""
_dict = MongoQuery._dict
field = _dict.get(self.name)
if isinstance(other, re.Pattern):
_dict[self.name] = {"$regex": other.pattern}
elif field is None:
if field is None:
_dict[self.name] = other
else:
_dict[self.name] = (
Expand Down Expand Up @@ -154,7 +157,7 @@ def exists(
raise TypeError(f"Field must be a QueryField or str, {type(field)} is not supported.")


def field_regex(
def regex_query(
field: Union[QueryField[str], str],
regex: re.Pattern[str],
) -> QueryCondition:
Expand Down
108 changes: 107 additions & 1 deletion tests/mongo/test_query.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"""Test mongo query implementation."""

import re
from typing import Dict, List, Optional

import pytest
from pydantic import BaseModel
from querytyper import MongoQuery, MongoModelMetaclass

from querytyper import MongoModelMetaclass, MongoQuery, exists, regex_query
from querytyper.mongo.query import QueryCondition


class Dummy(BaseModel):
Expand All @@ -28,6 +33,16 @@ def test_query_equals() -> None:
assert query._dict == {"str_field": "a"}


def test_query_less_then() -> None:
"""Test MongoQuery less_then override."""
query = MongoQuery(QueryModel.int_field <= 1)
assert isinstance(query, MongoQuery)
assert query._dict == {"int_field": {"$lte": 1}}
query = MongoQuery(QueryModel.int_field < 1)
assert isinstance(query, MongoQuery)
assert query._dict == {"int_field": {"$lt": 1}}


def test_query_and() -> None:
"""Test MongoQuery equals override."""
query = MongoQuery((QueryModel.str_field == "a") & (QueryModel.int_field >= 1))
Expand All @@ -47,3 +62,94 @@ def test_query_in() -> None:
query = MongoQuery(QueryModel.str_field in ["a", "b"])
assert isinstance(query, MongoQuery)
assert query._dict == {"str_field": ["a", "b"]}


def test_query_init_error() -> None:
"""Test MongoQuery equals override."""
with pytest.raises(
TypeError,
match="MongoQuery argument must be a QueryCondition or a boolean value, <class 'str'> is not supported.",
):
MongoQuery("random string")


def test_query_repr() -> None:
"""Test MongoQuery equals override."""
query = MongoQuery(QueryModel.str_field == "a")
assert isinstance(query, MongoQuery)
assert repr(query) == "{'str_field': 'a'}"


def test_query_condition_repr() -> None:
"""Test MongoQuery equals override."""
condition = QueryCondition(QueryModel.str_field == "a")
assert isinstance(condition, QueryCondition)
assert repr(condition) == "{'str_field': 'a'}"


def test_querycondition_and() -> None:
"""Test Query condition & override."""
conditions = QueryCondition(QueryModel.str_field == "a") & QueryCondition(
QueryModel.int_field >= 1
)
assert isinstance(conditions, QueryCondition)
# test also boolean is supported
conditions = QueryCondition(QueryModel.str_field == "a") & True
assert isinstance(conditions, QueryCondition)
condition = QueryCondition(QueryModel.str_field == "a")
conditions = True & condition
assert isinstance(conditions, QueryCondition)
assert isinstance(condition, QueryCondition)
assert condition == MongoQuery._dict


def test_metaclass_type_errors() -> None:
"""Test MongoModelMetaclass."""
with pytest.raises(
TypeError,
match="The class with metaclass MongoModelMetaclass requires a base class that inherits from BaseModel",
):

class Test(metaclass=MongoModelMetaclass):
"""Test class."""

class AnotherDummy(BaseModel):
"""Dummy base model."""

another_field: str

with pytest.raises(
TypeError, match="MongoModelMetaclass does not support multiple inheritance"
):

class MultipleInheritanceTest(Dummy, AnotherDummy, metaclass=MongoModelMetaclass):
"""Test class."""

with pytest.raises(TypeError, match="The base class must inherit from BaseModel"):

class TestNoBaseModel(str, metaclass=MongoModelMetaclass):
"""Test class."""


def test_regex_query() -> None:
"""Test regex query."""
condition = regex_query(QueryModel.str_field, re.compile("^a"))
assert isinstance(condition, QueryCondition)
assert condition == {"str_field": {"$regex": "^a"}}
condition = regex_query("str_field", re.compile("^a"))
assert isinstance(condition, QueryCondition)
assert condition == {"str_field": {"$regex": "^a"}}


def test_exists_query() -> None:
"""Test exists query."""
condition = exists(QueryModel.str_field)
assert isinstance(condition, QueryCondition)
assert condition == {"str_field": {"$exists": True}}
condition = exists("str_field")
assert isinstance(condition, QueryCondition)
assert condition == {"str_field": {"$exists": True}}
with pytest.raises(
TypeError, match="Field must be a QueryField or str, <class 'int'> is not supported."
):
exists(1)

0 comments on commit 90e9a1b

Please sign in to comment.