neuroglia-python 0.7.8__tar.gz → 0.7.9__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.8 → neuroglia_python-0.7.9}/PKG-INFO +1 -1
  2. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/pyproject.toml +1 -1
  3. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/__init__.py +1 -1
  4. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/serialization/json.py +52 -1
  5. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/LICENSE +0 -0
  6. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/README.md +0 -0
  7. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/application/__init__.py +0 -0
  8. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/application/background_scheduler.py +0 -0
  9. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/coordination/__init__.py +0 -0
  10. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/coordination/abstractions.py +0 -0
  11. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/coordination/leader_election.py +0 -0
  12. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/coordination/redis_backend.py +0 -0
  13. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/core/__init__.py +0 -0
  14. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/core/module_loader.py +0 -0
  15. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/core/operation_result.py +0 -0
  16. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/core/problem_details.py +0 -0
  17. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/core/type_extensions.py +0 -0
  18. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/core/type_finder.py +0 -0
  19. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/core/type_registry.py +0 -0
  20. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/__init__.py +0 -0
  21. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/abstractions.py +0 -0
  22. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/exceptions.py +0 -0
  23. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/__init__.py +0 -0
  24. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/abstractions.py +0 -0
  25. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/event_sourcing/__init__.py +0 -0
  26. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/event_sourcing/abstractions.py +0 -0
  27. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/event_sourcing/event_sourcing_repository.py +0 -0
  28. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/event_sourcing/event_store/__init__.py +0 -0
  29. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/event_sourcing/event_store/event_store.py +0 -0
  30. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/event_sourcing/read_model_reconciliator.py +0 -0
  31. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/filesystem/__init__.py +0 -0
  32. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/filesystem/filesystem_repository.py +0 -0
  33. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/memory/__init__.py +0 -0
  34. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/memory/memory_repository.py +0 -0
  35. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/mongo/__init__.py +0 -0
  36. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/mongo/enhanced_mongo_repository.py +0 -0
  37. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/mongo/mongo_repository.py +0 -0
  38. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/mongo/motor_query.py +0 -0
  39. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/mongo/motor_repository.py +0 -0
  40. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/mongo/serialization_helper.py +0 -0
  41. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/mongo/typed_mongo_query.py +0 -0
  42. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/resources/__init__.py +0 -0
  43. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/resources/in_memory_storage_backend.py +0 -0
  44. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/resources/postgres_resource_store.py +0 -0
  45. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/resources/redis_resource_store.py +0 -0
  46. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/resources/resource_repository.py +0 -0
  47. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/infrastructure/tracing_mixin.py +0 -0
  48. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/queries/generic/__init__.py +0 -0
  49. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/queries/generic/get_by_id_query.py +0 -0
  50. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/queries/generic/list_query.py +0 -0
  51. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/queryable.py +0 -0
  52. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/__init__.py +0 -0
  53. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/abstractions.py +0 -0
  54. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/controller.py +0 -0
  55. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/serializers/__init__.py +0 -0
  56. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/serializers/xml_serializer.py +0 -0
  57. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/serializers/yaml_serializer.py +0 -0
  58. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/state_machine.py +0 -0
  59. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/resources/watcher.py +0 -0
  60. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/data/unit_of_work.py +0 -0
  61. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/dependency_injection/__init__.py +0 -0
  62. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/dependency_injection/service_provider.py +0 -0
  63. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/dependency_injection/service_provider_backup.py +0 -0
  64. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/__init__.py +0 -0
  65. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/__init__.py +0 -0
  66. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/cloud_event.py +0 -0
  67. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/decorators.py +0 -0
  68. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/infrastructure/__init__.py +0 -0
  69. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_bus.py +0 -0
  70. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_ingestor.py +0 -0
  71. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_middleware.py +0 -0
  72. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/cloud_events/infrastructure/cloud_event_publisher.py +0 -0
  73. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/eventing/tracing.py +0 -0
  74. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/expressions/__init__.py +0 -0
  75. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/expressions/javascript_expression_translator.py +0 -0
  76. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/extensions/cqrs_metrics_extensions.py +0 -0
  77. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/extensions/mediator_extensions.py +0 -0
  78. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/extensions/state_persistence_extensions.py +0 -0
  79. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/hosting/__init__.py +0 -0
  80. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/hosting/abstractions.py +0 -0
  81. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/hosting/configuration/data_access_layer.py +0 -0
  82. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/hosting/web.py +0 -0
  83. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/integration/__init__.py +0 -0
  84. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/integration/cache_repository.py +0 -0
  85. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/integration/http_service_client.py +0 -0
  86. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/integration/models.py +0 -0
  87. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/logging/__init__.py +0 -0
  88. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/logging/logger.py +0 -0
  89. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mapping/__init__.py +0 -0
  90. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mapping/mapper.py +0 -0
  91. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/__init__.py +0 -0
  92. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/behaviors/domain_event_cloudevent_behavior.py +0 -0
  93. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/behaviors/domain_event_dispatching_middleware.py +0 -0
  94. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/mediator.py +0 -0
  95. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/metrics_middleware.py +0 -0
  96. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/pipeline_behavior.py +0 -0
  97. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/simple.py +0 -0
  98. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mediation/tracing_middleware.py +0 -0
  99. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mvc/__init__.py +0 -0
  100. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/mvc/controller_base.py +0 -0
  101. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/observability/__init__.py +0 -0
  102. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/observability/framework.py +0 -0
  103. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/observability/logging.py +0 -0
  104. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/observability/metrics.py +0 -0
  105. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/observability/otel_sdk.py +0 -0
  106. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/observability/settings.py +0 -0
  107. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/observability/tracing.py +0 -0
  108. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/py.typed +0 -0
  109. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/reactive/__init__.py +0 -0
  110. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/reactive/rx_async.py +0 -0
  111. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/serialization/__init__.py +0 -0
  112. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/serialization/abstractions.py +0 -0
  113. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/serialization/aggregate_serializer.py +0 -0
  114. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/utils/__init__.py +0 -0
  115. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/utils/camel_model.py +0 -0
  116. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/utils/case_conversion.py +0 -0
  117. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/validation/__init__.py +0 -0
  118. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/validation/business_rules.py +0 -0
  119. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/src/neuroglia/validation/exceptions.py +0 -0
  120. {neuroglia_python-0.7.8 → neuroglia_python-0.7.9}/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.8
3
+ Version: 0.7.9
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.8"
3
+ version = "0.7.9"
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.8"
65
+ __version__ = "0.7.9"
66
66
  __author__ = "Neuroglia Team"
67
67
  __email__ = "team@neuroglia.io"
68
68
  __license__ = "Apache"
@@ -445,6 +445,10 @@ class JsonSerializer(TextSerializer):
445
445
 
446
446
  def _deserialize_object(self, data: dict, expected_type: type) -> Any:
447
447
  """Deserialize a dictionary into an object using type annotations."""
448
+ # Handle Pydantic BaseModel types using model_validate for proper initialization
449
+ if self._is_pydantic_model(expected_type):
450
+ return expected_type.model_validate(data)
451
+
448
452
  fields = {}
449
453
 
450
454
  # Collect all type annotations from the class hierarchy
@@ -733,6 +737,10 @@ class JsonSerializer(TextSerializer):
733
737
  object.__setattr__(instance, key, val)
734
738
  return instance
735
739
 
740
+ # Handle Pydantic BaseModel deserialization
741
+ if self._is_pydantic_model(expected_type):
742
+ return expected_type.model_validate(value)
743
+
736
744
  origin_expected = get_origin(expected_type)
737
745
  if expected_type == dict or origin_expected is dict:
738
746
  # If the expected type is a plain dict, we need to deserialize each value in the dict.
@@ -770,20 +778,41 @@ class JsonSerializer(TextSerializer):
770
778
  # Check if the item should be a dataclass instance
771
779
  if isinstance(v, dict) and is_dataclass(item_type):
772
780
  # Deserialize dict to dataclass using proper field deserialization
781
+ # Use get_type_hints() to properly resolve type annotations (e.g., dict[str, Any])
782
+ try:
783
+ dataclass_type_hints = get_type_hints(item_type)
784
+ except (NameError, TypeError, AttributeError):
785
+ dataclass_type_hints = {field.name: field.type for field in fields(item_type)}
786
+ except Exception:
787
+ dataclass_type_hints = {field.name: field.type for field in fields(item_type)}
773
788
  field_dict = {}
774
789
  for field in fields(item_type):
775
790
  if field.name in v:
776
- field_type = field.type
791
+ field_type = dataclass_type_hints.get(field.name, field.type)
777
792
  if isinstance(field_type, str):
778
793
  field_dict[field.name] = v[field.name]
779
794
  else:
780
795
  field_value = self._deserialize_nested(v[field.name], field_type)
781
796
  field_dict[field.name] = field_value
797
+ # Ensure Optional fields missing from the payload are explicitly populated
798
+ for field in fields(item_type):
799
+ if field.name in field_dict:
800
+ continue
801
+ resolved_type = dataclass_type_hints.get(field.name, field.type)
802
+ if field.default is not MISSING:
803
+ field_dict[field.name] = field.default
804
+ elif field.default_factory is not MISSING: # type: ignore[attr-defined]
805
+ field_dict[field.name] = field.default_factory() # type: ignore[attr-defined]
806
+ elif self._is_optional_type(resolved_type):
807
+ field_dict[field.name] = None
782
808
  # Create instance and set fields (works for frozen and non-frozen dataclasses)
783
809
  item_instance: Any = object.__new__(cast(type, item_type))
784
810
  for key, val in field_dict.items():
785
811
  object.__setattr__(item_instance, key, val)
786
812
  values.append(item_instance)
813
+ elif isinstance(v, dict) and self._is_pydantic_model(item_type):
814
+ # Use Pydantic's model_validate for proper model initialization
815
+ values.append(item_type.model_validate(v))
787
816
  else:
788
817
  # For non-dataclass types, use regular deserialization
789
818
  deserialized = self._deserialize_nested(v, item_type)
@@ -842,6 +871,28 @@ class JsonSerializer(TextSerializer):
842
871
  return any(arg is type(None) for arg in get_args(annotation))
843
872
  return False
844
873
 
874
+ def _is_pydantic_model(self, cls: Any) -> bool:
875
+ """
876
+ Check if a type is a Pydantic BaseModel subclass.
877
+
878
+ Uses duck typing to avoid hard dependency on Pydantic being installed.
879
+ Pydantic v2 models have a `model_validate` classmethod that accepts dict data.
880
+
881
+ Args:
882
+ cls: The type to check
883
+
884
+ Returns:
885
+ True if the type appears to be a Pydantic BaseModel, False otherwise
886
+ """
887
+ if not isinstance(cls, type):
888
+ return False
889
+ # Check for Pydantic v2 model_validate method (preferred detection)
890
+ if hasattr(cls, "model_validate") and callable(getattr(cls, "model_validate", None)):
891
+ # Additional check: Pydantic models also have model_fields
892
+ if hasattr(cls, "model_fields"):
893
+ return True
894
+ return False
895
+
845
896
  @staticmethod
846
897
  def configure(builder: "ApplicationBuilderBase", modules: Optional[list[str]] = None) -> "ApplicationBuilderBase":
847
898
  """