Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

72 expressions improvements #117

Merged
merged 16 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
venv
.venv
.coverage
.env
notes.md
**/*~
Expand Down
5 changes: 2 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ import os

from dotenv import load_dotenv
import pymongo
from monggregate import Pipeline, S, Expression
from monggregate import Pipeline, S

# Creating connexion string securely
load_dotenv(verbose=True)
Expand All @@ -142,8 +142,7 @@ client = pymongo.MongoClient(MONGODB_URI)
db = client["sample_mflix"]

# Using expressions
comments_count = Expression.field("comments").size()

comments_count = S.size(S.comments)

# Creating the pipeline
pipeline = Pipeline()
Expand Down
9 changes: 9 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[mypy]
show_column_numbers = True
implicit_optional = False
disallow_untyped_defs = True
disallow_untyped_calls = True
follow_imports = silent
ignore_missing_imports = True
plugins = pydantic.mypy
explicit_package_bases = True
5 changes: 2 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ import os

from dotenv import load_dotenv
import pymongo
from monggregate import Pipeline, S, Expression
from monggregate import Pipeline, S

# Creating connexion string securely
load_dotenv(verbose=True)
Expand All @@ -142,8 +142,7 @@ client = pymongo.MongoClient(MONGODB_URI)
db = client["sample_mflix"]

# Using expressions
comments_count = Expression.field("comments").size()

comments_count = S.size(S.comments)

# Creating the pipeline
pipeline = Pipeline()
Expand Down
3 changes: 1 addition & 2 deletions src/monggregate/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""App Package"""

from monggregate.expressions import Expression
from monggregate.dollar import S, SS
from monggregate.pipeline import Pipeline

__all__ = ["Expression", "S", "SS", "Pipeline"]
__all__ = ["Pipeline", "S", "SS"]

__version__ = "0.21.0"
__author__ = "Vianney Mixtur"
Expand Down
16 changes: 0 additions & 16 deletions src/monggregate/_run.py

This file was deleted.

32 changes: 20 additions & 12 deletions src/monggregate/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
#----------------------------
from abc import ABC, abstractmethod
from typing import Any, TypeGuard
from typing_extensions import Self


# 3rd Party imports
# ---------------------------
try:
import pydantic.v1 as pyd
except ModuleNotFoundError:
import pydantic as pyd
import pydantic as pyd # type: ignore[no-redef]


from humps.main import camelize
Expand All @@ -24,32 +25,39 @@ class Singleton:
"""Singleton metaclass"""

_instance = None
def __new__(cls, *args, **kwargs):
def __new__(cls, *args:Any, **kwargs:Any)->Self:
if not isinstance(cls._instance, cls):
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance

Expression = dict[str, Any]

class BaseModel(pyd.BaseModel, ABC):
"""Mongreggate base class"""

def to_expression(self)->Expression|list[Expression]:
"""Converts an instance of a class inheriting from BaseModel to an expression"""

return self.express(self)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [mypy] reported by reviewdog 🐶
Incompatible return value type (got "dict[Any, Any] | list[dict[Any, Any]]", expected "dict[Any, Any]") [return-value]


@classmethod
def resolve(cls, obj:Any)->dict|list[dict]:
def express(cls, obj:Any)->Expression|list[Expression]:
"""Resolves an expression encapsulated in an object from a class inheriting from BaseModel"""

return resolve(obj)
return express(obj)

@property
@abstractmethod
def statement(self)->dict:
def expression(self)->Expression:
"""Stage statement absctract method"""

# this is a lazy attribute
# what is currently in generate statement should go in here

def __call__(self)->dict:
def __call__(self)->Expression|list[Expression]:
"""Makes an instance of any class inheriting from this class callable"""

return self.resolve(self.statement)
return self.to_expression()

class Config(pyd.BaseConfig):
"""Base configuration for classes inheriting from this"""
Expand All @@ -65,25 +73,25 @@ def isbasemodel(instance:Any)->TypeGuard[BaseModel]:

return isinstance(instance, BaseModel)

def resolve(obj:Any)->dict|list[dict]:
def express(obj:Any)->dict|list[dict]:
"""Resolves an expression encapsulated in an object from a class inheriting from BaseModel"""

if isbasemodel(obj):
output:dict|list = obj.statement
output:dict|list = obj.expression
elif isinstance(obj, list) and any(map(isbasemodel, obj)):
output = []
for element in obj:
if isinstance(element, BaseModel):
output.append(element.statement)
output.append(element.expression)
else:
output.append(element)
elif isinstance(obj, dict):
output = {}
for key, value in obj.items():
if isinstance(value, BaseModel):
output[key] = value.statement
output[key] = value.expression
else:
output[key] = resolve(value)
output[key] = express(value)
else:
output = obj

Expand Down
Loading
Loading