Skip to content

Commit 48ed3c5

Browse files
authored
128-revival-bugfixes-and-enhancements (#140)
* Fix express function * Fix allow to create/use expressions for objects that are not yet interfaced * Add missing tests on test_pipeline part I * Add stages for pipeline class * WIP debugging field names * formatting * Factorizing generate_enum_member * Fix generate_enum_member and some buggy enum member names * Refactored generate_enum_member * Cleaning * Fix project stage * Fix SortByCount * Fix sort * Fix match * WIP Debugging lookup * Fixed lookup stage * Fixed SearchBase * bump version 0.21.0 -> 0.22.0 * Fix sort * Update CI * Update CI
1 parent cffc059 commit 48ed3c5

File tree

43 files changed

+2374
-1457
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2374
-1457
lines changed

.github/workflows/python-app-ci.yml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ jobs:
2323
uses: actions/setup-python@v3
2424
with:
2525
python-version: "3.10"
26+
- name: Install uv
27+
uses: astral-sh/setup-uv@v3
28+
with:
29+
version: "latest"
2630
- name: Install dependencies
2731
run: |
28-
python -m pip install --upgrade pip
29-
pip install flake8 pytest
30-
if ${{ -f requirements.txt }}; then pip install -r requirements.txt; fi
31-
python -m pip install -e .
32+
uv sync --all-extras
33+
uv pip install -e .
3234
#- name: Lint with flake8
3335
# run: |
3436
# # stop the build if there are Python syntax errors or undefined names
@@ -39,7 +41,7 @@ jobs:
3941
env:
4042
MONGODB_PASSWORD: ${{secrets.MONGODB_PASSWORD}}
4143
run: |
42-
pytest
44+
uv run pytest
4345
4446
lint-and-format-backend:
4547
continue-on-error: true
@@ -56,6 +58,10 @@ jobs:
5658
uses: actions/setup-python@v3
5759
with:
5860
python-version: "3.10"
61+
- name: Install uv
62+
uses: astral-sh/setup-uv@v3
63+
with:
64+
version: "latest"
5965

6066
- name: Check Black formatting
6167
uses: reviewdog/action-black@v3
@@ -76,8 +82,7 @@ jobs:
7682
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7783
run: |
7884
cd monggregate
79-
pip3 install ruff
80-
ruff check . \
85+
uv run --with ruff ruff check . \
8186
| reviewdog -name=Ruff -reporter=local -reporter=github-pr-review -efm="%f:%l:%c: %m" -filter-mode=added -fail-on-error=true
8287
8388
- name: Check Mypy linting
@@ -87,7 +92,7 @@ jobs:
8792
github_token: ${{ secrets.GITHUB_TOKEN }}
8893
reporter: github-pr-review
8994
filter_mode: added
90-
setup_command: pip3 install --no-cache-dir --upgrade -r ../requirements/all.txt
95+
setup_command: uv sync --all-extras
9196
setup_method: install
9297
level: warning
9398
workdir: mongreggate

.github/workflows/python-app.yml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@ jobs:
2323
uses: actions/setup-python@v3
2424
with:
2525
python-version: "3.10"
26+
- name: Install uv
27+
uses: astral-sh/setup-uv@v3
28+
with:
29+
version: "latest"
2630
- name: Install dependencies
2731
run: |
28-
python -m pip install --upgrade pip
29-
pip install .
30-
pip install -r requirements/core.txt
31-
pip install -r requirements/testing.txt
32+
uv sync --all-extras
33+
uv pip install -e .
3234
- name: Test with pytest
3335
env:
3436
MONGODB_PASSWORD: ${{secrets.MONGODB_PASSWORD}}
3537
run: |
36-
pytest
38+
uv run pytest
3739
3840
lint-and-format-backend:
3941
continue-on-error: true
@@ -50,6 +52,10 @@ jobs:
5052
uses: actions/setup-python@v3
5153
with:
5254
python-version: "3.10"
55+
- name: Install uv
56+
uses: astral-sh/setup-uv@v3
57+
with:
58+
version: "latest"
5359

5460
- name: Check Black formatting
5561
uses: reviewdog/action-black@v3
@@ -68,8 +74,7 @@ jobs:
6874
env:
6975
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7076
run: |
71-
pip3 install ruff
72-
ruff check . \
77+
uv run --with ruff ruff check . \
7378
| reviewdog -name=Ruff -reporter=local -reporter=github-pr-review -efm="%f:%l:%c: %m" -filter-mode=added -fail-on-error=false
7479
7580
- name: Check Mypy linting
@@ -79,7 +84,7 @@ jobs:
7984
github_token: ${{ secrets.GITHUB_TOKEN }}
8085
reporter: github-pr-review
8186
filter_mode: added
82-
setup_command: pip3 install --no-cache-dir --upgrade -r requirements/all.txt
87+
setup_command: uv sync --all-extras
8388
setup_method: install
8489
level: warning
8590
mypy_flags: --python-version 3.10

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ dist
1717
test.py
1818
site/
1919
.pypirc
20-
clean_pycache.ps1
20+
clean_pycache.ps1
21+
test_deployments

pyproject.toml

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[project]
44
name = "monggregate"
5-
version = "0.21.0"
5+
version = "0.22.0"
66
description = "MongoDB aggregation pipelines made easy. Joins, grouping, counting and much more..."
77
readme = "README.md"
88
authors = [{ name = "Vianney Mixtur", email = "vianney.mixtur@outlook.fr" }]
@@ -22,12 +22,18 @@ dependencies = [
2222
"typing-extensions>=4.0",
2323
]
2424

25+
[project.optional-dependencies]
26+
mongodb = [
27+
"pymongo>=3.0.0",
28+
"motor>=3.0.0",
29+
]
30+
2531
[project.urls]
2632
Homepage = "https://github.com/VianneyMI/monggregate"
2733
documentation = "https://vianneymi.github.io/monggregate/"
2834

2935
[tool.bumpver]
30-
current_version = "0.21.0"
36+
current_version = "0.22.0"
3137
version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
3238
commit_message = "bump version {old_version} -> {new_version}"
3339
commit = true
@@ -41,11 +47,37 @@ push = false
4147
]
4248
"src/monggregate/__init__.py" = ['__version__ = "{version}"']
4349

50+
[tool.setuptools]
51+
packages = ["monggregate", "tests"]
52+
53+
[tool.setuptools.package-dir]
54+
monggregate = "src/monggregate"
55+
tests = "tests"
56+
4457
[dependency-groups]
45-
dev = [
58+
test = [
4659
"pytest>=8.3.5",
60+
"pytest-html>=3.2.0",
61+
"python-dotenv>=1.0.0",
62+
"certifi",
63+
]
64+
lint = [
65+
"mypy>=1.6.1",
66+
"ruff",
67+
"black",
4768
]
4869
doc = [
4970
"mkdocs==1.5.2",
5071
"mkdocs-material==9.2.7",
5172
]
73+
dev = [
74+
"pytest>=8.3.5",
75+
"pytest-html>=3.2.0",
76+
"python-dotenv>=1.0.0",
77+
"certifi",
78+
"mypy>=1.6.1",
79+
"ruff",
80+
"black",
81+
"mkdocs==1.5.2",
82+
"mkdocs-material==9.2.7",
83+
]

pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[pytest]
22
# Be careful when registering the mark the semi-colon (:) should be right after the mark without any space before it.
3+
pythonpath = . tests
34
markers =
45
unit: unit tests
56
functional: functional tests

src/monggregate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
__all__ = ["Pipeline", "S", "SS"]
77

8-
__version__ = "0.21.0"
8+
__version__ = "0.22.0"
99
__author__ = "Vianney Mixtur"
1010
__contact__ = "prenom.nom@outlook.fr"
1111
__copyright__ = "Copyright © 2022-2024 Vianney Mixtur"

src/monggregate/base.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,21 @@ class Config(pyd.BaseConfig):
7272
alias_generator = camelize
7373

7474

75+
class ExpressionWrapper(BaseModel):
76+
"""Wrapper for an expression.
77+
78+
To be used for Stage, Operator or other MongoDB object that hasn't been interfaced yet in `monggregate`.
79+
"""
80+
81+
_expression: Expression
82+
83+
@property
84+
def expression(self) -> Expression:
85+
"""Expression property"""
86+
87+
return self.expression
88+
89+
7590
def isbasemodel(instance: Any) -> TypeGuard[BaseModel]:
7691
"""Returns true if instance is an instance of BaseModel"""
7792

@@ -82,24 +97,20 @@ def express(obj: Any) -> dict | list[dict]:
8297
"""Resolves an expression encapsulated in an object from a class inheriting from BaseModel"""
8398

8499
if isbasemodel(obj):
100+
# If it's a BaseModel instance, get its expression
85101
output: dict | list = obj.expression
86-
elif isinstance(obj, list) and any(map(isbasemodel, obj)):
102+
elif isinstance(obj, list):
103+
# Always process lists recursively - they might contain nested BaseModel instances
87104
output = []
88105
for element in obj:
89-
if isinstance(element, BaseModel):
90-
output.append(
91-
element.expression
92-
) # probably should call express(element)
93-
else:
94-
output.append(element)
106+
output.append(express(element))
95107
elif isinstance(obj, dict):
108+
# Always process dictionaries recursively - they might contain nested BaseModel instances
96109
output = {}
97110
for key, value in obj.items():
98-
if isinstance(value, BaseModel):
99-
output[key] = value.expression # probably should call express(value)
100-
else:
101-
output[key] = express(value)
111+
output[key] = express(value)
102112
else:
113+
# For primitive types (int, str, bool, None, etc.), return as-is
103114
output = obj
104115

105116
return output

src/monggregate/operators/operator.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
"""Operator Module"""
22

33
# Standard Library imports
4-
#----------------------------
4+
# ----------------------------
55
from abc import ABC
66

77
# Package imports
88
# ---------------------------
99
from monggregate.base import BaseModel
1010
from monggregate.utils import StrEnum
1111

12+
1213
class Operator(BaseModel, ABC):
1314
"""MongoDB operator abstract base class"""
1415

16+
1517
class OperatorEnum(StrEnum):
1618
"""Enumeration of available operators"""
1719

18-
1920
ABS = "$abs"
2021
ACCUMULATOR = "$accumulator"
2122
ACOS = "$acos"
@@ -34,7 +35,7 @@ class OperatorEnum(StrEnum):
3435
ATANH = "$atanh"
3536
AVG = "$avg"
3637
BINARY_SIZE = "$binarySize"
37-
BSON_SIZE ="$bsonSize"
38+
BSON_SIZE = "$bsonSize"
3839
CEIL = "$ceil"
3940
CMP = "$cmp"
4041
CONCAT = "$concat"
@@ -47,15 +48,15 @@ class OperatorEnum(StrEnum):
4748
DATE_FROM_STRING = "$dateFromString"
4849
DATE_TO_PARTS = "$dateToParts"
4950
DATE_TO_STRING = "$dateToString"
50-
DAY_OF_MONTH ="$dayOfMonth"
51+
DAY_OF_MONTH = "$dayOfMonth"
5152
DAY_OF_WEEK = "$dayOfWeek"
5253
DAY_OF_YEAR = "$dayOfYear"
5354
DEGREES_TO_RADIANS = "$degreesToRadians"
5455
DIVIDE = "$divide"
5556
EQ = "$eq"
5657
EXP = "$exp"
5758
FILTER = "$filter"
58-
FIRST = "$first" # two operators one for array one for accumulator
59+
FIRST = "$first" # two operators one for array one for accumulator
5960
FLOOR = "$floor"
6061
FUNCTION = "$function"
6162
GET_FIELD = "$getField"
@@ -71,9 +72,9 @@ class OperatorEnum(StrEnum):
7172
IS_NUMBER = "$isNumber"
7273
ISO_DAY_OF_WEEK = "$isoDayOfWeek"
7374
ISO_WEEK = "$isoWeek"
74-
ISO_WEEK_YEAR ="$isoWeekYear"
75+
ISO_WEEK_YEAR = "$isoWeekYear"
7576
LAST = "$last" # two operators one for array one for accumulator
76-
LET ="$let"
77+
LET = "$let"
7778
LITERAL = "$literal"
7879
LN = "$ln"
7980
LOG = "$log"
@@ -85,26 +86,26 @@ class OperatorEnum(StrEnum):
8586
MAX = "$max"
8687
MERGE_OBJECTS = "$mergeObjects"
8788
META = "$meta"
88-
MILLI_SECOND = "$millisecond"
89+
MILLISECOND = "$millisecond"
8990
MIN = "$min"
90-
MINUTE ="$minute"
91-
MOD ="$mod"
91+
MINUTE = "$minute"
92+
MOD = "$mod"
9293
MONTH = "$month"
93-
MULTIPLY ="$multiply"
94-
NE ="$ne"
95-
NOT ="$not"
96-
OBJECT_TO_ARRAY ="$objectToArray"
94+
MULTIPLY = "$multiply"
95+
NE = "$ne"
96+
NOT = "$not"
97+
OBJECT_TO_ARRAY = "$objectToArray"
9798
OR = "$or"
9899
POW = "$pow"
99100
PUSH = "$push"
100101
RADIANS_TO_DEGREES = "$radiansToDegrees"
101102
RAND = "$rand"
102103
RANGE = "$range"
103104
REDUCE = "$reduce"
104-
REGEX_FIND ="$regexFind"
105+
REGEX_FIND = "$regexFind"
105106
REGEX_FIND_ALL = "$regexFindAll"
106107
REGEX_MATCH = "$regexMatch"
107-
REPLACE_ONE ="$replaceOne"
108+
REPLACE_ONE = "$replaceOne"
108109
REPLACE_ALL = "$replaceAll"
109110
REVERSE_ARRAY = "$reverseArray"
110111
ROUND = "$round"
@@ -126,16 +127,16 @@ class OperatorEnum(StrEnum):
126127
STD_DEV_SAMP = "$stdDevSamp"
127128
STR_LEN_BYTES = "$strLenBytes"
128129
STR_LEN_CP = "$strLenCP"
129-
STR_CASE_CMP = "$strcasecmp"
130+
STRCASECMP = "$strcasecmp"
130131
SUBSTR = "$substr"
131132
SUBSTR_BYTES = "$substrBytes"
132133
SUBSTR_CP = "$substrCP"
133-
SUBSTRACT = "$subtract"
134+
SUBTRACT = "$subtract"
134135
SUM = "$sum"
135136
SWITCH = "$switch"
136137
TAN = "$tan"
137138
TANH = "$tanh"
138-
TO_BOOL ="$toBool"
139+
TO_BOOL = "$toBool"
139140
TO_DATE = "$toDate"
140141
TO_DECIMAL = "$toDecimal"
141142
TO_DOUBLE = "$toDouble"
@@ -150,4 +151,4 @@ class OperatorEnum(StrEnum):
150151
TYPE = "$type"
151152
WEEK = "$week"
152153
YEAR = "$year"
153-
ZIP = "$zip"
154+
ZIP = "$zip"

0 commit comments

Comments
 (0)