neuroglia-python 0.7.3__tar.gz → 0.7.4__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.
Files changed (120) hide show
  1. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/PKG-INFO +1 -1
  2. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/pyproject.toml +1 -1
  3. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/__init__.py +1 -1
  4. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/queryable.py +62 -12
  5. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/hosting/configuration/data_access_layer.py +79 -17
  6. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/LICENSE +0 -0
  7. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/README.md +0 -0
  8. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/application/__init__.py +0 -0
  9. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/application/background_scheduler.py +0 -0
  10. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/coordination/__init__.py +0 -0
  11. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/coordination/abstractions.py +0 -0
  12. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/coordination/leader_election.py +0 -0
  13. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/coordination/redis_backend.py +0 -0
  14. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/core/__init__.py +0 -0
  15. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/core/module_loader.py +0 -0
  16. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/core/operation_result.py +0 -0
  17. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/core/problem_details.py +0 -0
  18. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/core/type_extensions.py +0 -0
  19. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/core/type_finder.py +0 -0
  20. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/core/type_registry.py +0 -0
  21. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/__init__.py +0 -0
  22. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/abstractions.py +0 -0
  23. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/exceptions.py +0 -0
  24. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/__init__.py +0 -0
  25. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/abstractions.py +0 -0
  26. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/event_sourcing/__init__.py +0 -0
  27. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/event_sourcing/abstractions.py +0 -0
  28. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/event_sourcing/event_sourcing_repository.py +0 -0
  29. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/event_sourcing/event_store/__init__.py +0 -0
  30. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/event_sourcing/event_store/event_store.py +0 -0
  31. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/event_sourcing/read_model_reconciliator.py +0 -0
  32. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/filesystem/__init__.py +0 -0
  33. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/filesystem/filesystem_repository.py +0 -0
  34. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/memory/__init__.py +0 -0
  35. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/memory/memory_repository.py +0 -0
  36. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/mongo/__init__.py +0 -0
  37. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/mongo/enhanced_mongo_repository.py +0 -0
  38. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/mongo/mongo_repository.py +0 -0
  39. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/mongo/motor_query.py +0 -0
  40. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/mongo/motor_repository.py +0 -0
  41. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/mongo/serialization_helper.py +0 -0
  42. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/mongo/typed_mongo_query.py +0 -0
  43. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/resources/__init__.py +0 -0
  44. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/resources/in_memory_storage_backend.py +0 -0
  45. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/resources/postgres_resource_store.py +0 -0
  46. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/resources/redis_resource_store.py +0 -0
  47. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/resources/resource_repository.py +0 -0
  48. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/infrastructure/tracing_mixin.py +0 -0
  49. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/queries/generic/__init__.py +0 -0
  50. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/queries/generic/get_by_id_query.py +0 -0
  51. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/queries/generic/list_query.py +0 -0
  52. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/__init__.py +0 -0
  53. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/abstractions.py +0 -0
  54. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/controller.py +0 -0
  55. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/serializers/__init__.py +0 -0
  56. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/serializers/xml_serializer.py +0 -0
  57. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/serializers/yaml_serializer.py +0 -0
  58. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/state_machine.py +0 -0
  59. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/resources/watcher.py +0 -0
  60. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/data/unit_of_work.py +0 -0
  61. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/dependency_injection/__init__.py +0 -0
  62. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/dependency_injection/service_provider.py +0 -0
  63. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/dependency_injection/service_provider_backup.py +0 -0
  64. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/__init__.py +0 -0
  65. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/__init__.py +0 -0
  66. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/cloud_event.py +0 -0
  67. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/decorators.py +0 -0
  68. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/infrastructure/__init__.py +0 -0
  69. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_bus.py +0 -0
  70. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_ingestor.py +0 -0
  71. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_middleware.py +0 -0
  72. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_publisher.py +0 -0
  73. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/eventing/tracing.py +0 -0
  74. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/expressions/__init__.py +0 -0
  75. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/expressions/javascript_expression_translator.py +0 -0
  76. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/extensions/cqrs_metrics_extensions.py +0 -0
  77. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/extensions/mediator_extensions.py +0 -0
  78. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/extensions/state_persistence_extensions.py +0 -0
  79. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/hosting/__init__.py +0 -0
  80. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/hosting/abstractions.py +0 -0
  81. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/hosting/web.py +0 -0
  82. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/integration/__init__.py +0 -0
  83. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/integration/cache_repository.py +0 -0
  84. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/integration/http_service_client.py +0 -0
  85. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/integration/models.py +0 -0
  86. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/logging/__init__.py +0 -0
  87. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/logging/logger.py +0 -0
  88. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mapping/__init__.py +0 -0
  89. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mapping/mapper.py +0 -0
  90. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/__init__.py +0 -0
  91. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/behaviors/domain_event_cloudevent_behavior.py +0 -0
  92. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/behaviors/domain_event_dispatching_middleware.py +0 -0
  93. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/mediator.py +0 -0
  94. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/metrics_middleware.py +0 -0
  95. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/pipeline_behavior.py +0 -0
  96. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/simple.py +0 -0
  97. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mediation/tracing_middleware.py +0 -0
  98. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mvc/__init__.py +0 -0
  99. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/mvc/controller_base.py +0 -0
  100. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/observability/__init__.py +0 -0
  101. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/observability/framework.py +0 -0
  102. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/observability/logging.py +0 -0
  103. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/observability/metrics.py +0 -0
  104. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/observability/otel_sdk.py +0 -0
  105. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/observability/settings.py +0 -0
  106. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/observability/tracing.py +0 -0
  107. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/py.typed +0 -0
  108. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/reactive/__init__.py +0 -0
  109. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/reactive/rx_async.py +0 -0
  110. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/serialization/__init__.py +0 -0
  111. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/serialization/abstractions.py +0 -0
  112. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/serialization/aggregate_serializer.py +0 -0
  113. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/serialization/json.py +0 -0
  114. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/utils/__init__.py +0 -0
  115. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/utils/camel_model.py +0 -0
  116. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/utils/case_conversion.py +0 -0
  117. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/validation/__init__.py +0 -0
  118. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/validation/business_rules.py +0 -0
  119. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/validation/exceptions.py +0 -0
  120. {neuroglia_python-0.7.3 → neuroglia_python-0.7.4}/src/neuroglia/validation/validators.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuroglia-python
3
- Version: 0.7.3
3
+ Version: 0.7.4
4
4
  Summary: Port from .NET to Python of the Neuroglia Framework
5
5
  License: Apache
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "neuroglia-python"
3
- version = "0.7.3"
3
+ version = "0.7.4"
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"
@@ -62,7 +62,7 @@ __all__ = [
62
62
  ]
63
63
 
64
64
  # Framework metadata
65
- __version__ = "0.7.3"
65
+ __version__ = "0.7.4"
66
66
  __author__ = "Neuroglia Team"
67
67
  __email__ = "team@neuroglia.io"
68
68
  __license__ = "Apache"
@@ -1,6 +1,5 @@
1
1
  import ast
2
2
  import inspect
3
- import os
4
3
  from abc import ABC, abstractclassmethod
5
4
  from ast import Attribute, Name, NodeTransformer, expr
6
5
  from collections.abc import Callable
@@ -146,7 +145,9 @@ class Queryable(Generic[T]):
146
145
 
147
146
  def order_by(self, selector: Callable[[T], Any]):
148
147
  """Orders the sequence using the specified attribute"""
149
- selector_source = self._get_lambda_source_code(selector)
148
+ frame = inspect.currentframe().f_back
149
+ frame_info = inspect.getframeinfo(frame)
150
+ selector_source = self._get_lambda_source_code(selector, frame_info.positions.end_col_offset)
150
151
  selector_tree = ast.parse(selector_source)
151
152
  selector_lambda_expression = selector_tree.body[0].value
152
153
  if not isinstance(selector_lambda_expression.body, Attribute):
@@ -160,7 +161,9 @@ class Queryable(Generic[T]):
160
161
 
161
162
  def order_by_descending(self, selector: Callable[[T], Any]):
162
163
  """Orders the sequence in a descending fashion using the specified attribute"""
163
- selector_source = self._get_lambda_source_code(selector)
164
+ frame = inspect.currentframe().f_back
165
+ frame_info = inspect.getframeinfo(frame)
166
+ selector_source = self._get_lambda_source_code(selector, frame_info.positions.end_col_offset)
164
167
  selector_tree = ast.parse(selector_source)
165
168
  selector_lambda_expression = selector_tree.body[0].value
166
169
  if not isinstance(selector_lambda_expression.body, Attribute):
@@ -175,8 +178,9 @@ class Queryable(Generic[T]):
175
178
  def select(self, selector: Callable[[T], Any]):
176
179
  """Projects each element of a sequence into a new form"""
177
180
  frame = inspect.currentframe().f_back
181
+ frame_info = inspect.getframeinfo(frame)
178
182
  variables = {**frame.f_locals}
179
- selector_source = self._get_lambda_source_code(selector)
183
+ selector_source = self._get_lambda_source_code(selector, frame_info.positions.end_col_offset)
180
184
  selector_tree = ast.parse(selector_source)
181
185
  selector_lambda_expression = selector_tree.body[0].value
182
186
  if not isinstance(selector_lambda_expression.body, Attribute) and not isinstance(selector_lambda_expression.body, ast.List):
@@ -239,18 +243,64 @@ class Queryable(Generic[T]):
239
243
  function (Callable): The lambda to get the source code of
240
244
  max_col_offset (int): The maximum column offset to walk the AST tree for the target lamba
241
245
 
246
+ Returns:
247
+ Optional[str]: The lambda source code, or None if extraction fails
248
+
242
249
  Notes:
243
250
  Credits to https://gist.github.com/Xion/617c1496ff45f3673a5692c3b0e3f75a
251
+
252
+ This method handles the case where the lambda is on a continuation line
253
+ that starts with '.' (common in method chaining). In such cases, the raw
254
+ source line is invalid Python syntax, so we prepend a dummy identifier
255
+ to make it parseable.
256
+
257
+ For multi-line continuations (backslash or implicit), we only process
258
+ the first line containing the lambda, as that's sufficient for extraction.
244
259
  """
245
- source_lines, _ = inspect.getsourcelines(function)
246
- if len(source_lines) != 1:
260
+ try:
261
+ source_lines, _ = inspect.getsourcelines(function)
262
+ except (OSError, TypeError) as e:
263
+ # Cannot extract source (e.g., built-in functions, C extensions)
247
264
  return None
248
- source_text = os.linesep.join(source_lines).strip()
249
- source_ast = ast.parse(source_text)
250
- lambda_node = next(
251
- (node for node in ast.walk(source_ast) if isinstance(node, ast.Lambda) and node.col_offset <= max_col_offset),
252
- None,
253
- )
265
+
266
+ # For multi-line sources (continuation), use only the first line
267
+ # The lambda itself is typically on the first line
268
+ if len(source_lines) == 0:
269
+ return None
270
+
271
+ # Strip the line and remove trailing backslash if present (line continuation)
272
+ source_text = source_lines[0].strip().rstrip("\\").strip()
273
+
274
+ # Handle continuation lines that start with '.' (method chaining)
275
+ # These are invalid Python syntax on their own
276
+ offset_adjustment = 0
277
+ if source_text.startswith("."):
278
+ source_text = "_" + source_text # Prepend dummy identifier
279
+ offset_adjustment = 1
280
+
281
+ try:
282
+ source_ast = ast.parse(source_text)
283
+ except SyntaxError:
284
+ return None
285
+
286
+ # Adjust max_col_offset if we prepended a dummy identifier
287
+ # Set to None if not provided to match all lambdas
288
+ adjusted_max_col_offset = None
289
+ if max_col_offset is not None:
290
+ adjusted_max_col_offset = max_col_offset + offset_adjustment
291
+
292
+ # Find lambda node within the adjusted column offset
293
+ if adjusted_max_col_offset is not None:
294
+ lambda_node = next(
295
+ (node for node in ast.walk(source_ast) if isinstance(node, ast.Lambda) and node.col_offset <= adjusted_max_col_offset),
296
+ None,
297
+ )
298
+ else:
299
+ lambda_node = next(
300
+ (node for node in ast.walk(source_ast) if isinstance(node, ast.Lambda)),
301
+ None,
302
+ )
303
+
254
304
  if lambda_node is None:
255
305
  return None
256
306
  lambda_text = source_text[lambda_node.col_offset : lambda_node.end_col_offset]
@@ -23,15 +23,26 @@ class DataAccessLayer:
23
23
  """Represents a helper class used to configure an application's Write Model DAL
24
24
 
25
25
  Supports two configuration patterns:
26
- 1. Simplified: Pass options directly to constructor
26
+ 1. Simplified: Pass database_name, consumer_group, and delete_mode to constructor
27
27
  2. Custom: Pass custom repository_setup function to configure()
28
28
 
29
29
  Examples:
30
- # Simple configuration with default options
31
- DataAccessLayer.WriteModel().configure(builder, ["domain.entities"])
32
-
33
- # With custom delete mode
30
+ # Simple configuration with all required parameters
34
31
  from neuroglia.data.infrastructure.event_sourcing.abstractions import DeleteMode
32
+
33
+ DataAccessLayer.WriteModel(
34
+ database_name="myapp",
35
+ consumer_group="myapp_group",
36
+ delete_mode=DeleteMode.HARD
37
+ ).configure(builder, ["domain.entities"])
38
+
39
+ # Minimal configuration (uses default delete mode)
40
+ DataAccessLayer.WriteModel(
41
+ database_name="myapp",
42
+ consumer_group="myapp_group"
43
+ ).configure(builder, ["domain.entities"])
44
+
45
+ # Legacy: With EventSourcingRepositoryOptions (backwards compatible)
35
46
  from neuroglia.data.infrastructure.event_sourcing.event_sourcing_repository import (
36
47
  EventSourcingRepositoryOptions
37
48
  )
@@ -49,13 +60,42 @@ class DataAccessLayer:
49
60
  )
50
61
  """
51
62
 
52
- def __init__(self, options: Optional["EventSourcingRepositoryOptions"] = None):
63
+ def __init__(
64
+ self,
65
+ database_name: Optional[str] = None,
66
+ consumer_group: Optional[str] = None,
67
+ delete_mode: Optional["DeleteMode"] = None,
68
+ options: Optional["EventSourcingRepositoryOptions"] = None,
69
+ ):
53
70
  """Initialize WriteModel configuration
54
71
 
55
72
  Args:
56
- options: Optional repository options (e.g., delete_mode).
57
- If not provided, default options will be used.
73
+ database_name: Database/stream prefix for event store (e.g., "myapp").
74
+ Internally creates EventStoreOptions and calls ESEventStore.configure().
75
+ consumer_group: Consumer group name for event store subscriptions.
76
+ delete_mode: Optional deletion strategy (DISABLED, SOFT, HARD).
77
+ If not provided, defaults to DISABLED.
78
+ options: Legacy parameter for EventSourcingRepositoryOptions (backwards compatible).
79
+ If database_name is provided, this parameter is ignored.
80
+
81
+ Example:
82
+ ```python
83
+ # Simplified configuration (recommended)
84
+ DataAccessLayer.WriteModel(
85
+ database_name="myapp",
86
+ consumer_group="myapp_group",
87
+ delete_mode=DeleteMode.HARD
88
+ ).configure(builder, ["domain.entities"])
89
+
90
+ # Legacy (still supported)
91
+ DataAccessLayer.WriteModel(
92
+ options=EventSourcingRepositoryOptions(delete_mode=DeleteMode.HARD)
93
+ ).configure(builder, ["domain.entities"])
94
+ ```
58
95
  """
96
+ self._database_name = database_name
97
+ self._consumer_group = consumer_group
98
+ self._delete_mode = delete_mode
59
99
  self._options = options
60
100
 
61
101
  def configure(self, builder: ApplicationBuilderBase, modules: list[str], repository_setup: Optional[Callable[[ApplicationBuilderBase, type, type], None]] = None) -> ApplicationBuilderBase:
@@ -66,13 +106,14 @@ class DataAccessLayer:
66
106
  modules (List[str]): a list containing the names of the modules to scan for aggregate root types
67
107
  repository_setup (Optional[Callable[[ApplicationBuilderBase, Type, Type], None]]):
68
108
  Optional custom function to setup repositories. If provided, takes precedence over options.
69
- If not provided, uses simplified configuration with options (if any).
109
+ If not provided, uses simplified configuration with database_name/consumer_group or options.
70
110
 
71
111
  Returns:
72
112
  ApplicationBuilderBase: The configured builder
73
113
 
74
114
  Raises:
75
115
  ImportError: If EventSourcingRepository cannot be imported
116
+ ValueError: If database_name is provided without consumer_group
76
117
  """
77
118
  # If custom setup provided, use it (backwards compatible)
78
119
  if repository_setup is not None:
@@ -82,7 +123,26 @@ class DataAccessLayer:
82
123
  repository_setup(builder, aggregate_type, key_type)
83
124
  return builder
84
125
 
85
- # Otherwise use simplified configuration with options
126
+ # If database_name provided, configure event store and use simplified configuration
127
+ if self._database_name is not None:
128
+ if self._consumer_group is None:
129
+ raise ValueError("consumer_group is required when database_name is provided")
130
+
131
+ # Configure ESEventStore
132
+ from neuroglia.data.infrastructure.event_sourcing.abstractions import (
133
+ EventStoreOptions,
134
+ )
135
+ from neuroglia.data.infrastructure.event_sourcing.event_store.event_store import (
136
+ ESEventStore,
137
+ )
138
+
139
+ event_store_options = EventStoreOptions(
140
+ database_name=self._database_name,
141
+ consumer_group=self._consumer_group,
142
+ )
143
+ ESEventStore.configure(builder, event_store_options)
144
+
145
+ # Otherwise use simplified configuration with options or defaults
86
146
  return self._configure_with_options(builder, modules)
87
147
 
88
148
  def _configure_with_options(self, builder: ApplicationBuilderBase, modules: list[str]) -> ApplicationBuilderBase:
@@ -98,6 +158,7 @@ class DataAccessLayer:
98
158
  from neuroglia.data.infrastructure.abstractions import Repository
99
159
  from neuroglia.data.infrastructure.event_sourcing.abstractions import (
100
160
  Aggregator,
161
+ DeleteMode,
101
162
  EventStore,
102
163
  )
103
164
  from neuroglia.data.infrastructure.event_sourcing.event_sourcing_repository import (
@@ -107,6 +168,9 @@ class DataAccessLayer:
107
168
  from neuroglia.dependency_injection import ServiceProvider
108
169
  from neuroglia.mediation import Mediator
109
170
 
171
+ # Determine delete mode to use
172
+ delete_mode = self._delete_mode if self._delete_mode is not None else (self._options.delete_mode if self._options else DeleteMode.DISABLED)
173
+
110
174
  # Discover and configure each aggregate type
111
175
  for module in [ModuleLoader.load(module_name) for module_name in modules]:
112
176
  for aggregate_type in TypeFinder.get_types(
@@ -115,13 +179,11 @@ class DataAccessLayer:
115
179
  ):
116
180
  key_type = str # todo: reflect from DTO base type
117
181
 
118
- # Create type-specific options if global options provided
119
- typed_options = None
120
- if self._options:
121
- typed_options = EventSourcingRepositoryOptions[aggregate_type, key_type]( # type: ignore
122
- delete_mode=self._options.delete_mode,
123
- soft_delete_method_name=self._options.soft_delete_method_name,
124
- )
182
+ # Create type-specific options
183
+ typed_options = EventSourcingRepositoryOptions[aggregate_type, key_type]( # type: ignore
184
+ delete_mode=delete_mode,
185
+ soft_delete_method_name=self._options.soft_delete_method_name if self._options else "mark_as_deleted",
186
+ )
125
187
 
126
188
  # Create factory function with proper closure
127
189
  def make_factory(et, kt, opts):