mongo-pipebuilder 0.2.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/LICENSE +1 -0
- {mongo_pipebuilder-0.2.1/src/mongo_pipebuilder.egg-info → mongo_pipebuilder-0.2.2}/PKG-INFO +2 -1
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/README.md +1 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/pyproject.toml +1 -1
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder/__init__.py +1 -1
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder/builder.py +22 -11
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2/src/mongo_pipebuilder.egg-info}/PKG-INFO +2 -1
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/tests/test_builder.py +16 -1
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/tests/test_builder_validation.py +1 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/tests/test_builder_validation_existing.py +11 -4
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/setup.cfg +0 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder.egg-info/SOURCES.txt +0 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder.egg-info/dependency_links.txt +0 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder.egg-info/requires.txt +0 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder.egg-info/top_level.txt +0 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/tests/test_builder_debug.py +0 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/tests/test_builder_insert.py +0 -0
- {mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/tests/test_builder_validation_new.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mongo-pipebuilder
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Type-safe, fluent MongoDB aggregation pipeline builder
|
|
5
5
|
Author-email: seligoroff <seligoroff@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -373,3 +373,4 @@ See [DEVELOPMENT.md](DEVELOPMENT.md) for development guidelines.
|
|
|
373
373
|
|
|
374
374
|
MIT License - see [LICENSE](LICENSE) file for details.
|
|
375
375
|
|
|
376
|
+
|
|
@@ -158,36 +158,47 @@ class PipelineBuilder:
|
|
|
158
158
|
self._stages.append({"$project": fields})
|
|
159
159
|
return self
|
|
160
160
|
|
|
161
|
-
def group(self, group_by: Dict[str, Any], accumulators: Dict[str, Any]) -> Self:
|
|
161
|
+
def group(self, group_by: Union[str, Dict[str, Any], Any], accumulators: Dict[str, Any]) -> Self:
|
|
162
162
|
"""
|
|
163
163
|
Add a $group stage for grouping documents.
|
|
164
164
|
|
|
165
165
|
Args:
|
|
166
|
-
group_by: Expression for grouping (becomes _id)
|
|
166
|
+
group_by: Expression for grouping (becomes _id). Can be:
|
|
167
|
+
- A string (field path, e.g., "$category")
|
|
168
|
+
- A dict (composite key, e.g., {"category": "$category"})
|
|
169
|
+
- Any other value (null, number, etc.)
|
|
167
170
|
accumulators: Dictionary with accumulators (sum, avg, count, etc.)
|
|
168
171
|
|
|
169
172
|
Returns:
|
|
170
173
|
Self for method chaining
|
|
171
174
|
|
|
172
175
|
Raises:
|
|
173
|
-
TypeError: If
|
|
174
|
-
ValueError: If both group_by and accumulators are empty
|
|
176
|
+
TypeError: If accumulators is not a dictionary
|
|
177
|
+
ValueError: If both group_by and accumulators are empty (when group_by is dict/str)
|
|
175
178
|
|
|
176
179
|
Example:
|
|
177
180
|
>>> builder.group(
|
|
178
|
-
... group_by=
|
|
181
|
+
... group_by="$category", # String field path
|
|
182
|
+
... accumulators={"total": {"$sum": "$amount"}}
|
|
183
|
+
... )
|
|
184
|
+
>>> builder.group(
|
|
185
|
+
... group_by={"category": "$category"}, # Composite key
|
|
179
186
|
... accumulators={"total": {"$sum": "$amount"}}
|
|
180
187
|
... )
|
|
181
188
|
"""
|
|
182
|
-
if not isinstance(group_by, dict):
|
|
183
|
-
raise TypeError(f"group_by must be a dict, got {type(group_by)}")
|
|
184
189
|
if not isinstance(accumulators, dict):
|
|
185
190
|
raise TypeError(f"accumulators must be a dict, got {type(accumulators)}")
|
|
186
191
|
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
if
|
|
190
|
-
|
|
192
|
+
# Validate empty cases
|
|
193
|
+
# group_by can be None, empty string, empty dict, etc. - all are valid in MongoDB
|
|
194
|
+
# But if it's a string and empty, or dict and empty, and accumulators is also empty,
|
|
195
|
+
# it's likely an error
|
|
196
|
+
if isinstance(group_by, dict):
|
|
197
|
+
if not group_by and not accumulators:
|
|
198
|
+
raise ValueError("group_by and accumulators cannot both be empty")
|
|
199
|
+
elif isinstance(group_by, str):
|
|
200
|
+
if not group_by and not accumulators:
|
|
201
|
+
raise ValueError("group_by and accumulators cannot both be empty")
|
|
191
202
|
|
|
192
203
|
group_stage = {"_id": group_by, **accumulators}
|
|
193
204
|
self._stages.append({"$group": group_stage})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mongo-pipebuilder
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Type-safe, fluent MongoDB aggregation pipeline builder
|
|
5
5
|
Author-email: seligoroff <seligoroff@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -373,3 +373,4 @@ See [DEVELOPMENT.md](DEVELOPMENT.md) for development guidelines.
|
|
|
373
373
|
|
|
374
374
|
MIT License - see [LICENSE](LICENSE) file for details.
|
|
375
375
|
|
|
376
|
+
|
|
@@ -78,7 +78,7 @@ class TestPipelineBuilder:
|
|
|
78
78
|
assert pipeline == [{"$project": {"name": 1, "email": 1, "_id": 0}}]
|
|
79
79
|
|
|
80
80
|
def test_group_stage(self):
|
|
81
|
-
"""Test adding $group stage."""
|
|
81
|
+
"""Test adding $group stage with dict."""
|
|
82
82
|
builder = PipelineBuilder()
|
|
83
83
|
pipeline = builder.group(
|
|
84
84
|
group_by={"category": "$category"},
|
|
@@ -92,6 +92,21 @@ class TestPipelineBuilder:
|
|
|
92
92
|
}
|
|
93
93
|
}]
|
|
94
94
|
|
|
95
|
+
def test_group_stage_with_string(self):
|
|
96
|
+
"""Test adding $group stage with string field path."""
|
|
97
|
+
builder = PipelineBuilder()
|
|
98
|
+
pipeline = builder.group(
|
|
99
|
+
group_by="$categoryType",
|
|
100
|
+
accumulators={"total": {"$sum": "$amount"}}
|
|
101
|
+
).build()
|
|
102
|
+
|
|
103
|
+
assert pipeline == [{
|
|
104
|
+
"$group": {
|
|
105
|
+
"_id": "$categoryType",
|
|
106
|
+
"total": {"$sum": "$amount"}
|
|
107
|
+
}
|
|
108
|
+
}]
|
|
109
|
+
|
|
95
110
|
def test_unwind_stage(self):
|
|
96
111
|
"""Test adding $unwind stage."""
|
|
97
112
|
builder = PipelineBuilder()
|
{mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/tests/test_builder_validation_existing.py
RENAMED
|
@@ -72,11 +72,18 @@ class TestGroupValidation:
|
|
|
72
72
|
pipeline = builder.group({}, {"count": {"$sum": 1}}).build()
|
|
73
73
|
assert pipeline == [{"$group": {"_id": {}, "count": {"$sum": 1}}}]
|
|
74
74
|
|
|
75
|
-
def
|
|
76
|
-
"""Test that group(
|
|
75
|
+
def test_group_with_string_group_by(self):
|
|
76
|
+
"""Test that group() accepts string for group_by (field path)."""
|
|
77
77
|
builder = PipelineBuilder()
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
# String field path is valid in MongoDB
|
|
79
|
+
pipeline = builder.group("$categoryType", {"total": {"$sum": "$amount"}}).build()
|
|
80
|
+
assert pipeline == [{"$group": {"_id": "$categoryType", "total": {"$sum": "$amount"}}}]
|
|
81
|
+
|
|
82
|
+
def test_group_empty_string_with_empty_accumulators_raises_error(self):
|
|
83
|
+
"""Test that group('', {}) raises ValueError."""
|
|
84
|
+
builder = PipelineBuilder()
|
|
85
|
+
with pytest.raises(ValueError, match="group_by and accumulators cannot both be empty"):
|
|
86
|
+
builder.group("", {})
|
|
80
87
|
|
|
81
88
|
def test_group_invalid_accumulators_type_raises_error(self):
|
|
82
89
|
"""Test that group({}, 123) raises TypeError."""
|
|
File without changes
|
{mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder.egg-info/requires.txt
RENAMED
|
File without changes
|
{mongo_pipebuilder-0.2.1 → mongo_pipebuilder-0.2.2}/src/mongo_pipebuilder.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|