neuroglia-python 0.7.4__tar.gz → 0.7.5__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.
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/PKG-INFO +1 -1
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/pyproject.toml +1 -1
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/__init__.py +1 -1
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/event_sourcing/event_sourcing_repository.py +13 -3
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/mongo/mongo_repository.py +3 -3
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/mongo/motor_query.py +5 -4
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/mongo/motor_repository.py +98 -9
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/queryable.py +6 -1
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/LICENSE +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/README.md +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/application/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/application/background_scheduler.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/coordination/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/coordination/abstractions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/coordination/leader_election.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/coordination/redis_backend.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/core/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/core/module_loader.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/core/operation_result.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/core/problem_details.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/core/type_extensions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/core/type_finder.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/core/type_registry.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/abstractions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/exceptions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/abstractions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/event_sourcing/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/event_sourcing/abstractions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/event_sourcing/event_store/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/event_sourcing/event_store/event_store.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/event_sourcing/read_model_reconciliator.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/filesystem/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/filesystem/filesystem_repository.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/memory/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/memory/memory_repository.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/mongo/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/mongo/enhanced_mongo_repository.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/mongo/serialization_helper.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/mongo/typed_mongo_query.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/resources/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/resources/in_memory_storage_backend.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/resources/postgres_resource_store.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/resources/redis_resource_store.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/resources/resource_repository.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/tracing_mixin.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/queries/generic/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/queries/generic/get_by_id_query.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/queries/generic/list_query.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/abstractions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/controller.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/serializers/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/serializers/xml_serializer.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/serializers/yaml_serializer.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/state_machine.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/watcher.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/unit_of_work.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/dependency_injection/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/dependency_injection/service_provider.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/dependency_injection/service_provider_backup.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/cloud_event.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/decorators.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/infrastructure/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_bus.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_ingestor.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_middleware.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_publisher.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/tracing.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/expressions/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/expressions/javascript_expression_translator.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/extensions/cqrs_metrics_extensions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/extensions/mediator_extensions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/extensions/state_persistence_extensions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/hosting/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/hosting/abstractions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/hosting/configuration/data_access_layer.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/hosting/web.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/integration/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/integration/cache_repository.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/integration/http_service_client.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/integration/models.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/logging/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/logging/logger.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mapping/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mapping/mapper.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/behaviors/domain_event_cloudevent_behavior.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/behaviors/domain_event_dispatching_middleware.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/mediator.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/metrics_middleware.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/pipeline_behavior.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/simple.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/tracing_middleware.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mvc/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mvc/controller_base.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/observability/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/observability/framework.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/observability/logging.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/observability/metrics.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/observability/otel_sdk.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/observability/settings.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/observability/tracing.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/py.typed +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/reactive/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/reactive/rx_async.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/serialization/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/serialization/abstractions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/serialization/aggregate_serializer.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/serialization/json.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/utils/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/utils/camel_model.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/utils/case_conversion.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/validation/__init__.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/validation/business_rules.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/validation/exceptions.py +0 -0
- {neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/validation/validators.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "neuroglia-python"
|
|
3
|
-
version = "0.7.
|
|
3
|
+
version = "0.7.5"
|
|
4
4
|
description = "Port from .NET to Python of the Neuroglia Framework"
|
|
5
5
|
authors = ["Charles d'Avernas <charles.davernas@neuroglia.io>", "Bruno van de Werve <bvandewe@gmail.com>"]
|
|
6
6
|
license = "Apache"
|
|
@@ -113,10 +113,20 @@ class EventSourcingRepository(Generic[TAggregate, TKey], Repository[TAggregate,
|
|
|
113
113
|
return self._eventstore.contains_stream(self._build_stream_id_for(id))
|
|
114
114
|
|
|
115
115
|
async def get_async(self, id: TKey) -> Optional[TAggregate]:
|
|
116
|
-
"""
|
|
116
|
+
"""
|
|
117
|
+
Gets the aggregate with the specified id, if any.
|
|
118
|
+
|
|
119
|
+
Returns None if the stream does not exist.
|
|
120
|
+
"""
|
|
117
121
|
stream_id = self._build_stream_id_for(id)
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
try:
|
|
123
|
+
events = await self._eventstore.read_async(stream_id, StreamReadDirection.FORWARDS, 0)
|
|
124
|
+
if not events:
|
|
125
|
+
return None
|
|
126
|
+
return self._aggregator.aggregate(events, self.__orig_class__.__args__[0])
|
|
127
|
+
except Exception:
|
|
128
|
+
# If stream doesn't exist or any other error occurs, return None
|
|
129
|
+
return None
|
|
120
130
|
|
|
121
131
|
async def _do_add_async(self, aggregate: TAggregate) -> TAggregate:
|
|
122
132
|
"""Adds and persists the specified aggregate"""
|
|
@@ -38,8 +38,8 @@ class MongoRepositoryOptions(Generic[TEntity, TKey]):
|
|
|
38
38
|
class MongoQuery(Generic[T], Queryable[T]):
|
|
39
39
|
"""Represents a Mongo query"""
|
|
40
40
|
|
|
41
|
-
def __init__(self, query_provider: "MongoQueryProvider", expression: Optional[expr] = None):
|
|
42
|
-
super().__init__(query_provider, expression)
|
|
41
|
+
def __init__(self, query_provider: "MongoQueryProvider", expression: Optional[expr] = None, element_type: Optional[type] = None):
|
|
42
|
+
super().__init__(query_provider, expression, element_type)
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class MongoQueryBuilder(NodeVisitor):
|
|
@@ -114,7 +114,7 @@ class MongoQueryProvider(QueryProvider):
|
|
|
114
114
|
_collection: Collection
|
|
115
115
|
|
|
116
116
|
def create_query(self, element_type: type, expression: expr) -> Queryable:
|
|
117
|
-
return MongoQuery
|
|
117
|
+
return MongoQuery(self, expression, element_type)
|
|
118
118
|
|
|
119
119
|
def execute(self, expression: expr, query_type: type) -> Any:
|
|
120
120
|
query = MongoQueryBuilder(self._collection, JavaScriptExpressionTranslator()).build(expression)
|
|
@@ -64,15 +64,16 @@ class MotorQuery(Generic[T], Queryable[T]):
|
|
|
64
64
|
```
|
|
65
65
|
"""
|
|
66
66
|
|
|
67
|
-
def __init__(self, query_provider: "MotorQueryProvider", expression: Optional[expr] = None):
|
|
67
|
+
def __init__(self, query_provider: "MotorQueryProvider", expression: Optional[expr] = None, element_type: Optional[type] = None):
|
|
68
68
|
"""
|
|
69
69
|
Initialize a Motor query.
|
|
70
70
|
|
|
71
71
|
Args:
|
|
72
72
|
query_provider: The Motor query provider
|
|
73
73
|
expression: Optional AST expression for the query
|
|
74
|
+
element_type: Optional element type (used for chaining to preserve type info)
|
|
74
75
|
"""
|
|
75
|
-
super().__init__(query_provider, expression)
|
|
76
|
+
super().__init__(query_provider, expression, element_type)
|
|
76
77
|
|
|
77
78
|
async def to_list_async(self) -> list[T]:
|
|
78
79
|
"""
|
|
@@ -319,9 +320,9 @@ class MotorQueryProvider(QueryProvider):
|
|
|
319
320
|
expression: AST expression for the query
|
|
320
321
|
|
|
321
322
|
Returns:
|
|
322
|
-
New MotorQuery instance
|
|
323
|
+
New MotorQuery instance with element_type propagated
|
|
323
324
|
"""
|
|
324
|
-
return MotorQuery(self, expression)
|
|
325
|
+
return MotorQuery(self, expression, element_type)
|
|
325
326
|
|
|
326
327
|
def execute(self, expression: expr, query_type: type) -> Any:
|
|
327
328
|
"""
|
|
@@ -578,31 +578,68 @@ class MotorRepository(Generic[TEntity, TKey], QueryableRepository[TEntity, TKey]
|
|
|
578
578
|
|
|
579
579
|
return entities
|
|
580
580
|
|
|
581
|
-
async def find_async(
|
|
581
|
+
async def find_async(
|
|
582
|
+
self,
|
|
583
|
+
filter_dict: dict,
|
|
584
|
+
sort: Optional[list[tuple[str, int]]] = None,
|
|
585
|
+
limit: Optional[int] = None,
|
|
586
|
+
skip: Optional[int] = None,
|
|
587
|
+
projection: Optional[dict] = None,
|
|
588
|
+
) -> list[TEntity]:
|
|
582
589
|
"""
|
|
583
|
-
Find entities matching a MongoDB filter query.
|
|
590
|
+
Find entities matching a MongoDB filter query with optional sorting, pagination, and projection.
|
|
584
591
|
|
|
585
|
-
This provides direct access to MongoDB's query language for complex queries
|
|
592
|
+
This provides direct access to MongoDB's query language for complex queries
|
|
593
|
+
with full support for cursor operations.
|
|
586
594
|
|
|
587
595
|
Args:
|
|
588
596
|
filter_dict: MongoDB query filter (e.g., {"state.email": "user@example.com"})
|
|
597
|
+
sort: List of (field, direction) tuples. Direction: 1 for ascending, -1 for descending.
|
|
598
|
+
Example: [("name", 1), ("created_at", -1)]
|
|
599
|
+
limit: Maximum number of documents to return
|
|
600
|
+
skip: Number of documents to skip (for pagination)
|
|
601
|
+
projection: Fields to include/exclude. Example: {"name": 1, "email": 1}
|
|
589
602
|
|
|
590
603
|
Returns:
|
|
591
604
|
List of entities matching the filter
|
|
592
605
|
|
|
593
|
-
|
|
606
|
+
Examples:
|
|
594
607
|
```python
|
|
595
608
|
# Find all active users
|
|
596
609
|
active_users = await repository.find_async({"state.is_active": True})
|
|
597
610
|
|
|
598
|
-
# Find users by email domain
|
|
599
|
-
gmail_users = await repository.find_async(
|
|
600
|
-
"state.email": {"$regex": "@gmail.com$"}
|
|
601
|
-
|
|
611
|
+
# Find users by email domain with sorting
|
|
612
|
+
gmail_users = await repository.find_async(
|
|
613
|
+
{"state.email": {"$regex": "@gmail.com$"}},
|
|
614
|
+
sort=[("state.name", 1)]
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
# Paginated query with sorting
|
|
618
|
+
page_2_users = await repository.find_async(
|
|
619
|
+
{"state.is_active": True},
|
|
620
|
+
sort=[("state.created_at", -1)],
|
|
621
|
+
skip=20,
|
|
622
|
+
limit=10
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# Query with field projection (only return specific fields)
|
|
626
|
+
users = await repository.find_async(
|
|
627
|
+
{"state.is_active": True},
|
|
628
|
+
projection={"state.name": 1, "state.email": 1}
|
|
629
|
+
)
|
|
602
630
|
```
|
|
603
631
|
"""
|
|
632
|
+
cursor = self.collection.find(filter_dict, projection)
|
|
633
|
+
|
|
634
|
+
if sort:
|
|
635
|
+
cursor = cursor.sort(sort)
|
|
636
|
+
if skip:
|
|
637
|
+
cursor = cursor.skip(skip)
|
|
638
|
+
if limit:
|
|
639
|
+
cursor = cursor.limit(limit)
|
|
640
|
+
|
|
604
641
|
entities = []
|
|
605
|
-
async for doc in
|
|
642
|
+
async for doc in cursor:
|
|
606
643
|
entity = self._deserialize_entity(doc)
|
|
607
644
|
entities.append(entity)
|
|
608
645
|
|
|
@@ -631,6 +668,58 @@ class MotorRepository(Generic[TEntity, TKey], QueryableRepository[TEntity, TKey]
|
|
|
631
668
|
|
|
632
669
|
return self._deserialize_entity(doc)
|
|
633
670
|
|
|
671
|
+
async def count_async(self, filter_dict: Optional[dict] = None) -> int:
|
|
672
|
+
"""
|
|
673
|
+
Count documents matching a MongoDB filter query.
|
|
674
|
+
|
|
675
|
+
Args:
|
|
676
|
+
filter_dict: MongoDB query filter. If None or empty dict, counts all documents.
|
|
677
|
+
|
|
678
|
+
Returns:
|
|
679
|
+
Count of documents matching the filter
|
|
680
|
+
|
|
681
|
+
Examples:
|
|
682
|
+
```python
|
|
683
|
+
# Count all documents
|
|
684
|
+
total_count = await repository.count_async()
|
|
685
|
+
|
|
686
|
+
# Count with filter
|
|
687
|
+
active_count = await repository.count_async({"state.is_active": True})
|
|
688
|
+
|
|
689
|
+
# Useful for pagination
|
|
690
|
+
filter_query = {"state.status": "pending"}
|
|
691
|
+
total_pages = (await repository.count_async(filter_query) + page_size - 1) // page_size
|
|
692
|
+
```
|
|
693
|
+
"""
|
|
694
|
+
filter_dict = filter_dict or {}
|
|
695
|
+
return await self.collection.count_documents(filter_dict)
|
|
696
|
+
|
|
697
|
+
async def exists_async(self, filter_dict: dict) -> bool:
|
|
698
|
+
"""
|
|
699
|
+
Check if any document matches the MongoDB filter query.
|
|
700
|
+
|
|
701
|
+
This is more efficient than count_async for existence checks as it
|
|
702
|
+
stops after finding the first match.
|
|
703
|
+
|
|
704
|
+
Args:
|
|
705
|
+
filter_dict: MongoDB query filter
|
|
706
|
+
|
|
707
|
+
Returns:
|
|
708
|
+
True if at least one document matches, False otherwise
|
|
709
|
+
|
|
710
|
+
Examples:
|
|
711
|
+
```python
|
|
712
|
+
# Check if email already exists
|
|
713
|
+
email_exists = await repository.exists_async({"state.email": "user@example.com"})
|
|
714
|
+
if email_exists:
|
|
715
|
+
raise ValueError("Email already registered")
|
|
716
|
+
|
|
717
|
+
# Check if any active users exist
|
|
718
|
+
has_active = await repository.exists_async({"state.is_active": True})
|
|
719
|
+
```
|
|
720
|
+
"""
|
|
721
|
+
return await self.collection.count_documents(filter_dict, limit=1) > 0
|
|
722
|
+
|
|
634
723
|
@staticmethod
|
|
635
724
|
def configure(
|
|
636
725
|
builder: ApplicationBuilderBase,
|
|
@@ -79,9 +79,10 @@ class Queryable(Generic[T]):
|
|
|
79
79
|
- Repository Pattern Guide: https://bvandewe.github.io/pyneuro/patterns/
|
|
80
80
|
"""
|
|
81
81
|
|
|
82
|
-
def __init__(self, provider: QueryProvider, expression: Optional[expr] = None):
|
|
82
|
+
def __init__(self, provider: QueryProvider, expression: Optional[expr] = None, element_type: Optional[type] = None):
|
|
83
83
|
self.provider = provider
|
|
84
84
|
self.expression = ast.Name(id="__query") if expression is None else expression
|
|
85
|
+
self._element_type = element_type
|
|
85
86
|
|
|
86
87
|
expression: expr
|
|
87
88
|
""" Gets the expression that is associated with the queryable """
|
|
@@ -91,6 +92,10 @@ class Queryable(Generic[T]):
|
|
|
91
92
|
|
|
92
93
|
def get_element_type(self) -> type:
|
|
93
94
|
"""Gets the type of elements to query against"""
|
|
95
|
+
# Try explicit element type first (set during chaining)
|
|
96
|
+
if hasattr(self, "_element_type") and self._element_type is not None:
|
|
97
|
+
return self._element_type
|
|
98
|
+
# Fall back to __orig_class__ for initial query creation
|
|
94
99
|
return self.__orig_class__.__args__[0]
|
|
95
100
|
|
|
96
101
|
def first_or_default(self, predicate: Callable[[T], bool] = None) -> T:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/application/background_scheduler.py
RENAMED
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/coordination/abstractions.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/coordination/leader_election.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/coordination/redis_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/__init__.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/abstractions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/infrastructure/tracing_mixin.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/queries/generic/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/queries/generic/list_query.py
RENAMED
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/abstractions.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/controller.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/data/resources/state_machine.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/dependency_injection/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/__init__.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/cloud_event.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/eventing/cloud_events/decorators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/extensions/mediator_extensions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/integration/cache_repository.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/integration/http_service_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/metrics_middleware.py
RENAMED
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/pipeline_behavior.py
RENAMED
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/mediation/tracing_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/serialization/abstractions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neuroglia_python-0.7.4 → neuroglia_python-0.7.5}/src/neuroglia/validation/business_rules.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|