mongo-aggro 0.1.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

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.
Files changed (53) hide show
  1. mongo_aggro/__init__.py +400 -0
  2. mongo_aggro/accumulators.py +30 -12
  3. mongo_aggro/base.py +49 -9
  4. mongo_aggro/expressions/__init__.py +396 -0
  5. mongo_aggro/expressions/arithmetic.py +329 -0
  6. mongo_aggro/expressions/array.py +425 -0
  7. mongo_aggro/expressions/base.py +180 -0
  8. mongo_aggro/expressions/bitwise.py +84 -0
  9. mongo_aggro/expressions/comparison.py +161 -0
  10. mongo_aggro/expressions/conditional.py +117 -0
  11. mongo_aggro/expressions/date.py +665 -0
  12. mongo_aggro/expressions/encrypted.py +116 -0
  13. mongo_aggro/expressions/logical.py +72 -0
  14. mongo_aggro/expressions/object.py +122 -0
  15. mongo_aggro/expressions/set.py +150 -0
  16. mongo_aggro/expressions/size.py +48 -0
  17. mongo_aggro/expressions/string.py +365 -0
  18. mongo_aggro/expressions/trigonometry.py +283 -0
  19. mongo_aggro/expressions/type.py +205 -0
  20. mongo_aggro/expressions/variable.py +73 -0
  21. mongo_aggro/expressions/window.py +327 -0
  22. mongo_aggro/operators/__init__.py +65 -0
  23. mongo_aggro/operators/array.py +41 -0
  24. mongo_aggro/operators/base.py +15 -0
  25. mongo_aggro/operators/bitwise.py +81 -0
  26. mongo_aggro/operators/comparison.py +82 -0
  27. mongo_aggro/operators/element.py +32 -0
  28. mongo_aggro/operators/geo.py +171 -0
  29. mongo_aggro/operators/logical.py +111 -0
  30. mongo_aggro/operators/misc.py +102 -0
  31. mongo_aggro/operators/regex.py +25 -0
  32. mongo_aggro/stages/__init__.py +110 -0
  33. mongo_aggro/stages/array.py +69 -0
  34. mongo_aggro/stages/change.py +109 -0
  35. mongo_aggro/stages/core.py +170 -0
  36. mongo_aggro/stages/geo.py +93 -0
  37. mongo_aggro/stages/group.py +154 -0
  38. mongo_aggro/stages/join.py +221 -0
  39. mongo_aggro/stages/misc.py +45 -0
  40. mongo_aggro/stages/output.py +136 -0
  41. mongo_aggro/stages/search.py +315 -0
  42. mongo_aggro/stages/session.py +111 -0
  43. mongo_aggro/stages/stats.py +152 -0
  44. mongo_aggro/stages/transform.py +136 -0
  45. mongo_aggro/stages/window.py +139 -0
  46. mongo_aggro-0.2.2.dist-info/METADATA +193 -0
  47. mongo_aggro-0.2.2.dist-info/RECORD +49 -0
  48. {mongo_aggro-0.1.0.dist-info → mongo_aggro-0.2.2.dist-info}/WHEEL +1 -1
  49. mongo_aggro/operators.py +0 -247
  50. mongo_aggro/stages.py +0 -990
  51. mongo_aggro-0.1.0.dist-info/METADATA +0 -537
  52. mongo_aggro-0.1.0.dist-info/RECORD +0 -9
  53. {mongo_aggro-0.1.0.dist-info → mongo_aggro-0.2.2.dist-info}/licenses/LICENSE +0 -0
mongo_aggro/__init__.py CHANGED
@@ -16,6 +16,13 @@ Example:
16
16
  >>>
17
17
  >>> # Pass directly to MongoDB - no need to call any methods
18
18
  >>> results = collection.aggregate(pipeline)
19
+
20
+ Expression operators with Python syntax:
21
+ >>> from mongo_aggro import Match, Expr
22
+ >>> from mongo_aggro.expressions import F
23
+ >>>
24
+ >>> # Use Python operators for MongoDB expressions
25
+ >>> Match(query=Expr((F("status") == "active") & (F("age") > 18)))
19
26
  """
20
27
 
21
28
  from .accumulators import (
@@ -48,20 +55,185 @@ from .base import (
48
55
  BaseStage,
49
56
  Pipeline,
50
57
  SortSpec,
58
+ serialize_value,
59
+ )
60
+ from .expressions import ( # Arithmetic expressions; Set expressions; Comparison expressions; Array expressions; Conditional expressions; Type conversion expressions; Date expressions; Encrypted string expressions; Object expressions; Additional array expressions; Variable expressions; Miscellaneous expressions; Logical expressions; Window expressions; Regex expressions; String expressions
61
+ AbsExpr,
62
+ AcosExpr,
63
+ AcoshExpr,
64
+ AddExpr,
65
+ AllElementsTrueExpr,
66
+ AndExpr,
67
+ AnyElementTrueExpr,
68
+ ArrayElemAtExpr,
69
+ ArraySizeExpr,
70
+ ArrayToObjectExpr,
71
+ AsinExpr,
72
+ AsinhExpr,
73
+ Atan2Expr,
74
+ AtanExpr,
75
+ AtanhExpr,
76
+ BinarySizeExpr,
77
+ BitAndExpr,
78
+ BitNotExpr,
79
+ BitOrExpr,
80
+ BitXorExpr,
81
+ BottomExpr,
82
+ BottomNWindowExpr,
83
+ BsonSizeExpr,
84
+ CeilExpr,
85
+ CmpExpr,
86
+ ConcatArraysExpr,
87
+ ConcatExpr,
88
+ CondExpr,
89
+ ConvertExpr,
90
+ CosExpr,
91
+ CoshExpr,
92
+ CovariancePopExpr,
93
+ CovarianceSampExpr,
94
+ DateAddExpr,
95
+ DateDiffExpr,
96
+ DateFromPartsExpr,
97
+ DateFromStringExpr,
98
+ DateSubtractExpr,
99
+ DateToPartsExpr,
100
+ DateToStringExpr,
101
+ DateTruncExpr,
102
+ DayOfMonthExpr,
103
+ DayOfWeekExpr,
104
+ DayOfYearExpr,
105
+ DegreesToRadiansExpr,
106
+ DenseRankExpr,
107
+ DerivativeExpr,
108
+ DivideExpr,
109
+ DocumentNumberExpr,
110
+ EncStrContainsExpr,
111
+ EncStrEndsWithExpr,
112
+ EncStrNormalizedEqExpr,
113
+ EncStrStartsWithExpr,
114
+ EqExpr,
115
+ ExpExpr,
116
+ ExpMovingAvgExpr,
117
+ ExpressionBase,
118
+ F,
119
+ Field,
120
+ FilterExpr,
121
+ FirstNExpr,
122
+ FloorExpr,
123
+ GetFieldExpr,
124
+ GteExpr,
125
+ GtExpr,
126
+ HourExpr,
127
+ IfNullExpr,
128
+ InArrayExpr,
129
+ IndexOfArrayExpr,
130
+ IntegralExpr,
131
+ IsArrayExpr,
132
+ IsNumberExpr,
133
+ IsoDayOfWeekExpr,
134
+ IsoWeekExpr,
135
+ IsoWeekYearExpr,
136
+ LastNExpr,
137
+ LetExpr,
138
+ LinearFillExpr,
139
+ LiteralExpr,
140
+ LnExpr,
141
+ LocfExpr,
142
+ Log10Expr,
143
+ LogExpr,
144
+ LteExpr,
145
+ LtExpr,
146
+ LTrimExpr,
147
+ MapExpr,
148
+ MaxNExpr,
149
+ MergeObjectsExpr,
150
+ MillisecondExpr,
151
+ MinNExpr,
152
+ MinuteExpr,
153
+ ModExpr,
154
+ MonthExpr,
155
+ MultiplyExpr,
156
+ NeExpr,
157
+ NotExpr,
158
+ ObjectToArrayExpr,
159
+ OrExpr,
160
+ PowExpr,
161
+ RadiansToDegreesExpr,
162
+ RandExpr,
163
+ RangeExpr,
164
+ RankExpr,
165
+ ReduceExpr,
166
+ RegexFindAllExpr,
167
+ RegexFindExpr,
168
+ RegexMatchExpr,
169
+ ReplaceAllExpr,
170
+ ReplaceOneExpr,
171
+ ReverseArrayExpr,
172
+ RoundExpr,
173
+ RTrimExpr,
174
+ SecondExpr,
175
+ SetDifferenceExpr,
176
+ SetEqualsExpr,
177
+ SetFieldExpr,
178
+ SetIntersectionExpr,
179
+ SetIsSubsetExpr,
180
+ SetUnionExpr,
181
+ ShiftExpr,
182
+ SinExpr,
183
+ SinhExpr,
184
+ SliceExpr,
185
+ SortArrayExpr,
186
+ SplitExpr,
187
+ SqrtExpr,
188
+ StrCaseCmpExpr,
189
+ StrLenCPExpr,
190
+ SubstrCPExpr,
191
+ SubtractExpr,
192
+ SwitchBranch,
193
+ SwitchExpr,
194
+ TanExpr,
195
+ TanhExpr,
196
+ ToBoolExpr,
197
+ ToDateExpr,
198
+ ToDecimalExpr,
199
+ ToDoubleExpr,
200
+ ToIntExpr,
201
+ ToLongExpr,
202
+ ToLowerExpr,
203
+ ToObjectIdExpr,
204
+ TopExpr,
205
+ TopNWindowExpr,
206
+ ToStringExpr,
207
+ ToUpperExpr,
208
+ TrimExpr,
209
+ TruncExpr,
210
+ TypeExpr,
211
+ WeekExpr,
212
+ YearExpr,
51
213
  )
52
214
  from .operators import (
53
215
  All,
54
216
  And,
217
+ BitsAllClear,
218
+ BitsAllSet,
219
+ BitsAnyClear,
220
+ BitsAnySet,
55
221
  ElemMatch,
56
222
  Eq,
57
223
  Exists,
58
224
  Expr,
225
+ GeoIntersects,
226
+ GeoWithin,
59
227
  Gt,
60
228
  Gte,
61
229
  In,
230
+ JsonSchema,
62
231
  Lt,
63
232
  Lte,
233
+ Mod,
64
234
  Ne,
235
+ Near,
236
+ NearSphere,
65
237
  Nin,
66
238
  Nor,
67
239
  Not,
@@ -69,13 +241,19 @@ from .operators import (
69
241
  QueryOperator,
70
242
  Regex,
71
243
  Size,
244
+ Text,
72
245
  Type,
246
+ Where,
73
247
  )
74
248
  from .stages import (
75
249
  AddFields,
76
250
  Bucket,
77
251
  BucketAuto,
252
+ ChangeStream,
253
+ ChangeStreamSplitLargeEvent,
254
+ CollStats,
78
255
  Count,
256
+ CurrentOp,
79
257
  Densify,
80
258
  Documents,
81
259
  Facet,
@@ -83,16 +261,27 @@ from .stages import (
83
261
  GeoNear,
84
262
  GraphLookup,
85
263
  Group,
264
+ IndexStats,
86
265
  Limit,
266
+ ListClusterCatalog,
267
+ ListLocalSessions,
268
+ ListSampledQueries,
269
+ ListSearchIndexes,
270
+ ListSessions,
87
271
  Lookup,
88
272
  Match,
89
273
  Merge,
90
274
  Out,
275
+ PlanCacheStats,
91
276
  Project,
277
+ QuerySettings,
278
+ RankFusion,
92
279
  Redact,
93
280
  ReplaceRoot,
94
281
  ReplaceWith,
95
282
  Sample,
283
+ Search,
284
+ SearchMeta,
96
285
  Set,
97
286
  SetWindowFields,
98
287
  Skip,
@@ -101,6 +290,7 @@ from .stages import (
101
290
  UnionWith,
102
291
  Unset,
103
292
  Unwind,
293
+ VectorSearch,
104
294
  )
105
295
 
106
296
  __all__ = [
@@ -109,9 +299,182 @@ __all__ = [
109
299
  "BaseStage",
110
300
  "SortSpec",
111
301
  "AggregationInput",
302
+ "serialize_value",
112
303
  # Sort direction constants
113
304
  "ASCENDING",
114
305
  "DESCENDING",
306
+ # Expression operators (new)
307
+ "F",
308
+ "Field",
309
+ "ExpressionBase",
310
+ "EqExpr",
311
+ "NeExpr",
312
+ "GtExpr",
313
+ "GteExpr",
314
+ "LtExpr",
315
+ "LteExpr",
316
+ "CmpExpr",
317
+ "AndExpr",
318
+ "OrExpr",
319
+ "NotExpr",
320
+ # Arithmetic expressions
321
+ "AddExpr",
322
+ "SubtractExpr",
323
+ "MultiplyExpr",
324
+ "DivideExpr",
325
+ "AbsExpr",
326
+ "ModExpr",
327
+ # Conditional expressions
328
+ "CondExpr",
329
+ "IfNullExpr",
330
+ "SwitchExpr",
331
+ "SwitchBranch",
332
+ # String expressions
333
+ "ConcatExpr",
334
+ "SplitExpr",
335
+ "ToLowerExpr",
336
+ "ToUpperExpr",
337
+ # Array expressions
338
+ "ArraySizeExpr",
339
+ "SliceExpr",
340
+ "FilterExpr",
341
+ "MapExpr",
342
+ "ReduceExpr",
343
+ # Date expressions
344
+ "DateAddExpr",
345
+ "DateSubtractExpr",
346
+ "DateDiffExpr",
347
+ "DateToStringExpr",
348
+ "DateFromStringExpr",
349
+ # Type conversion expressions
350
+ "ToDateExpr",
351
+ "ToStringExpr",
352
+ "ToIntExpr",
353
+ "ToDoubleExpr",
354
+ "ToBoolExpr",
355
+ "ToObjectIdExpr",
356
+ "ConvertExpr",
357
+ "TypeExpr",
358
+ "ToLongExpr",
359
+ "ToDecimalExpr",
360
+ "IsNumberExpr",
361
+ # Set expressions
362
+ "SetUnionExpr",
363
+ "SetIntersectionExpr",
364
+ "SetDifferenceExpr",
365
+ "SetEqualsExpr",
366
+ "SetIsSubsetExpr",
367
+ "AnyElementTrueExpr",
368
+ "AllElementsTrueExpr",
369
+ # Object expressions
370
+ "MergeObjectsExpr",
371
+ "ObjectToArrayExpr",
372
+ "ArrayToObjectExpr",
373
+ "GetFieldExpr",
374
+ "SetFieldExpr",
375
+ # Variable expressions
376
+ "LetExpr",
377
+ # Miscellaneous expressions
378
+ "LiteralExpr",
379
+ "RandExpr",
380
+ # Additional array expressions
381
+ "ArrayElemAtExpr",
382
+ "ConcatArraysExpr",
383
+ "InArrayExpr",
384
+ "IndexOfArrayExpr",
385
+ "IsArrayExpr",
386
+ "ReverseArrayExpr",
387
+ "SortArrayExpr",
388
+ "RangeExpr",
389
+ "FirstNExpr",
390
+ "LastNExpr",
391
+ "MaxNExpr",
392
+ "MinNExpr",
393
+ # Additional string expressions
394
+ "TrimExpr",
395
+ "LTrimExpr",
396
+ "RTrimExpr",
397
+ "ReplaceOneExpr",
398
+ "ReplaceAllExpr",
399
+ "RegexMatchExpr",
400
+ "RegexFindExpr",
401
+ "RegexFindAllExpr",
402
+ "SubstrCPExpr",
403
+ "StrLenCPExpr",
404
+ "StrCaseCmpExpr",
405
+ # Additional arithmetic expressions
406
+ "CeilExpr",
407
+ "FloorExpr",
408
+ "RoundExpr",
409
+ "TruncExpr",
410
+ "SqrtExpr",
411
+ "PowExpr",
412
+ "ExpExpr",
413
+ "LnExpr",
414
+ "Log10Expr",
415
+ "LogExpr",
416
+ # Trigonometry expressions
417
+ "SinExpr",
418
+ "CosExpr",
419
+ "TanExpr",
420
+ "AsinExpr",
421
+ "AcosExpr",
422
+ "AtanExpr",
423
+ "Atan2Expr",
424
+ "SinhExpr",
425
+ "CoshExpr",
426
+ "TanhExpr",
427
+ "AsinhExpr",
428
+ "AcoshExpr",
429
+ "AtanhExpr",
430
+ "DegreesToRadiansExpr",
431
+ "RadiansToDegreesExpr",
432
+ # Bitwise expressions
433
+ "BitAndExpr",
434
+ "BitOrExpr",
435
+ "BitXorExpr",
436
+ "BitNotExpr",
437
+ # Data size expressions
438
+ "BsonSizeExpr",
439
+ "BinarySizeExpr",
440
+ # Date part expressions
441
+ "YearExpr",
442
+ "MonthExpr",
443
+ "DayOfMonthExpr",
444
+ "DayOfWeekExpr",
445
+ "DayOfYearExpr",
446
+ "HourExpr",
447
+ "MinuteExpr",
448
+ "SecondExpr",
449
+ "MillisecondExpr",
450
+ "WeekExpr",
451
+ "IsoWeekExpr",
452
+ "IsoWeekYearExpr",
453
+ "IsoDayOfWeekExpr",
454
+ "DateFromPartsExpr",
455
+ "DateToPartsExpr",
456
+ "DateTruncExpr",
457
+ # Window expressions
458
+ "RankExpr",
459
+ "DenseRankExpr",
460
+ "DocumentNumberExpr",
461
+ "ShiftExpr",
462
+ "ExpMovingAvgExpr",
463
+ "DerivativeExpr",
464
+ "IntegralExpr",
465
+ "CovariancePopExpr",
466
+ "CovarianceSampExpr",
467
+ "LinearFillExpr",
468
+ "LocfExpr",
469
+ "TopExpr",
470
+ "BottomExpr",
471
+ "TopNWindowExpr",
472
+ "BottomNWindowExpr",
473
+ # Encrypted string expressions
474
+ "EncStrContainsExpr",
475
+ "EncStrStartsWithExpr",
476
+ "EncStrEndsWithExpr",
477
+ "EncStrNormalizedEqExpr",
115
478
  # Query operators
116
479
  "QueryOperator",
117
480
  "And",
@@ -133,6 +496,21 @@ __all__ = [
133
496
  "ElemMatch",
134
497
  "Size",
135
498
  "All",
499
+ # Bitwise query operators
500
+ "BitsAllClear",
501
+ "BitsAllSet",
502
+ "BitsAnyClear",
503
+ "BitsAnySet",
504
+ # Geospatial query operators
505
+ "GeoIntersects",
506
+ "GeoWithin",
507
+ "Near",
508
+ "NearSphere",
509
+ # Misc query operators
510
+ "Mod",
511
+ "JsonSchema",
512
+ "Where",
513
+ "Text",
136
514
  # Accumulators
137
515
  "Accumulator",
138
516
  "Sum",
@@ -185,4 +563,26 @@ __all__ = [
185
563
  "Densify",
186
564
  "Fill",
187
565
  "Documents",
566
+ # Statistics stages
567
+ "CollStats",
568
+ "IndexStats",
569
+ "PlanCacheStats",
570
+ # Session stages
571
+ "ListSessions",
572
+ "ListLocalSessions",
573
+ "ListSampledQueries",
574
+ # Change stream stages
575
+ "ChangeStream",
576
+ "ChangeStreamSplitLargeEvent",
577
+ # Admin stages
578
+ "CurrentOp",
579
+ "ListClusterCatalog",
580
+ "ListSearchIndexes",
581
+ # Atlas search stages
582
+ "Search",
583
+ "SearchMeta",
584
+ "VectorSearch",
585
+ # Advanced stages
586
+ "QuerySettings",
587
+ "RankFusion",
188
588
  ]
@@ -452,21 +452,39 @@ class MinN(Accumulator):
452
452
 
453
453
  def merge_accumulators(*accumulators: Accumulator) -> dict[str, Any]:
454
454
  """
455
- Merge multiple accumulators into a single dictionary for Group stage.
455
+ Combine typed accumulator instances into a dict for Group stage.
456
+
457
+ This helper provides type-safe accumulator definitions with IDE
458
+ autocomplete and validation, instead of writing raw MongoDB dicts.
459
+
460
+ Args:
461
+ *accumulators: Accumulator instances (Sum, Avg, Max, etc.)
462
+
463
+ Returns:
464
+ Combined dict suitable for Group's accumulators parameter.
456
465
 
457
466
  Example:
458
- >>> merge_accumulators(
459
- ... Sum(name="total", field="amount"),
460
- ... Avg(name="average", field="amount"),
461
- ... Count_(name="count")
467
+ Using typed accumulators (recommended for type safety):
468
+
469
+ >>> Group(
470
+ ... id="$category",
471
+ ... accumulators=merge_accumulators(
472
+ ... Sum(name="total", field="amount"),
473
+ ... Avg(name="average", field="price"),
474
+ ... Count_(name="count"),
475
+ ... )
476
+ ... )
477
+
478
+ Equivalent raw dict (less type safety):
479
+
480
+ >>> Group(
481
+ ... id="$category",
482
+ ... accumulators={
483
+ ... "total": {"$sum": "$amount"},
484
+ ... "average": {"$avg": "$price"},
485
+ ... "count": {"$count": {}},
486
+ ... }
462
487
  ... )
463
- {
464
- "total": {
465
- "$sum": "$amount"},
466
- "average": {"$avg": "$amount"},
467
- "count": {"$count": {}
468
- }
469
- }
470
488
  """
471
489
  result: dict[str, Any] = {}
472
490
  for acc in accumulators:
mongo_aggro/base.py CHANGED
@@ -1,12 +1,14 @@
1
1
  """Base classes for MongoDB aggregation pipeline stages."""
2
2
 
3
- from abc import ABC, abstractmethod
4
3
  from collections.abc import Iterator
5
- from typing import Any, Self
4
+ from typing import TYPE_CHECKING, Any, Protocol, Self, runtime_checkable
6
5
 
7
- from pydantic import GetCoreSchemaHandler
6
+ from pydantic import BaseModel, GetCoreSchemaHandler
8
7
  from pydantic_core import CoreSchema, core_schema
9
8
 
9
+ if TYPE_CHECKING:
10
+ pass
11
+
10
12
  # Sort direction constants for use with Sort stage and with_sort method
11
13
  ASCENDING: int = 1
12
14
  DESCENDING: int = -1
@@ -18,10 +20,45 @@ SortSpec = dict[str, int]
18
20
  AggregationInput = tuple[list[dict[str, Any]], SortSpec]
19
21
 
20
22
 
21
- class BaseStage(ABC):
22
- """Abstract base class for all MongoDB aggregation pipeline stages."""
23
+ def serialize_value(v: Any) -> Any:
24
+ """
25
+ Recursively serialize values for MongoDB expressions.
26
+
27
+ Handles:
28
+ - Field objects: returns the field path string (e.g., "$status")
29
+ - BaseModel instances: calls model_dump() for Pydantic serialization
30
+ - Lists: recursively serializes each element
31
+ - Dicts: recursively serializes each value
32
+ - Other values: returns as-is
33
+
34
+ Args:
35
+ v: Any value to serialize
36
+
37
+ Returns:
38
+ MongoDB-compatible serialized value
39
+ """
40
+ # Import here to avoid circular imports
41
+ from mongo_aggro.expressions import Field
42
+
43
+ if isinstance(v, Field):
44
+ return str(v)
45
+ elif isinstance(v, BaseModel):
46
+ return v.model_dump()
47
+ elif isinstance(v, list):
48
+ return [serialize_value(item) for item in v]
49
+ elif isinstance(v, dict):
50
+ return {k: serialize_value(val) for k, val in v.items()}
51
+ return v
52
+
53
+
54
+ @runtime_checkable
55
+ class BaseStage(Protocol):
56
+ """Protocol for MongoDB aggregation pipeline stages.
57
+
58
+ Any class implementing model_dump() -> dict[str, Any] is a valid stage.
59
+ This enables structural typing - no inheritance required.
60
+ """
23
61
 
24
- @abstractmethod
25
62
  def model_dump(self) -> dict[str, Any]:
26
63
  """
27
64
  Convert the stage to its MongoDB dictionary representation.
@@ -29,7 +66,7 @@ class BaseStage(ABC):
29
66
  Returns:
30
67
  dict[str, Any]: MongoDB aggregation stage dictionary
31
68
  """
32
- pass
69
+ ...
33
70
 
34
71
 
35
72
  class Pipeline:
@@ -185,8 +222,11 @@ class Pipeline:
185
222
  return core_schema.is_instance_schema(cls)
186
223
 
187
224
 
188
- class _RawStage(BaseStage):
189
- """Internal class for wrapping raw dictionary stages."""
225
+ class _RawStage:
226
+ """Internal class for wrapping raw dictionary stages.
227
+
228
+ Implements BaseStage protocol.
229
+ """
190
230
 
191
231
  def __init__(self, raw: dict[str, Any]) -> None:
192
232
  self._raw = raw