eventsourcing 9.3.2__tar.gz → 9.3.3__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.

Potentially problematic release.


This version of eventsourcing might be problematic. Click here for more details.

Files changed (145) hide show
  1. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/PKG-INFO +3 -8
  2. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7/application.py +6 -1
  3. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7/domainmodel.py +5 -7
  4. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7/test_application.py +7 -0
  5. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7a/domainmodel.py +5 -7
  6. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate8/domainmodel.py +23 -17
  7. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate8/test_application.py +7 -0
  8. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/postgres.py +2 -1
  9. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/system.py +3 -1
  10. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_postgres.py +2 -1
  11. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/pyproject.toml +13 -31
  12. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/AUTHORS +0 -0
  13. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/LICENSE +0 -0
  14. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/README.md +0 -0
  15. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/__init__.py +0 -0
  16. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/application.py +0 -0
  17. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/cipher.py +0 -0
  18. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/compressor.py +0 -0
  19. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/dispatch.py +0 -0
  20. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/domain.py +0 -0
  21. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/__init__.py +0 -0
  22. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate1/__init__.py +0 -0
  23. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate1/application.py +0 -0
  24. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate1/domainmodel.py +0 -0
  25. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate1/test_application.py +0 -0
  26. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate2/__init__.py +0 -0
  27. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate2/application.py +0 -0
  28. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate2/domainmodel.py +0 -0
  29. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate2/test_application.py +0 -0
  30. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate3/__init__.py +0 -0
  31. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate3/application.py +0 -0
  32. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate3/domainmodel.py +0 -0
  33. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate3/test_application.py +0 -0
  34. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate4/__init__.py +0 -0
  35. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate4/application.py +0 -0
  36. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate4/domainmodel.py +0 -0
  37. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate4/test_application.py +0 -0
  38. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate5/__init__.py +0 -0
  39. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate5/application.py +0 -0
  40. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate5/domainmodel.py +0 -0
  41. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate5/test_application.py +0 -0
  42. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6/__init__.py +0 -0
  43. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6/application.py +0 -0
  44. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6/domainmodel.py +0 -0
  45. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6/test_application.py +0 -0
  46. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6a/__init__.py +0 -0
  47. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6a/application.py +0 -0
  48. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6a/domainmodel.py +0 -0
  49. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate6a/test_application.py +0 -0
  50. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7/__init__.py +0 -0
  51. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7/persistence.py +0 -0
  52. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7/test_compression_and_encryption.py +0 -0
  53. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7/test_snapshotting_intervals.py +0 -0
  54. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7a/__init__.py +0 -0
  55. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7a/application.py +0 -0
  56. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7a/test_application.py +0 -0
  57. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate7a/test_compression_and_encryption.py +0 -0
  58. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate8/__init__.py +0 -0
  59. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate8/application.py +0 -0
  60. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate8/persistence.py +0 -0
  61. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate8/test_compression_and_encryption.py +0 -0
  62. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/aggregate8/test_snapshotting_intervals.py +0 -0
  63. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/bankaccounts/__init__.py +0 -0
  64. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/bankaccounts/application.py +0 -0
  65. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/bankaccounts/domainmodel.py +0 -0
  66. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/bankaccounts/test.py +0 -0
  67. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/cargoshipping/__init__.py +0 -0
  68. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/cargoshipping/application.py +0 -0
  69. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/cargoshipping/domainmodel.py +0 -0
  70. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/cargoshipping/interface.py +0 -0
  71. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/cargoshipping/test.py +0 -0
  72. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagement/__init__.py +0 -0
  73. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagement/application.py +0 -0
  74. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagement/domainmodel.py +0 -0
  75. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagement/test.py +0 -0
  76. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagement/utils.py +0 -0
  77. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagementsystem/__init__.py +0 -0
  78. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagementsystem/application.py +0 -0
  79. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagementsystem/postgres.py +0 -0
  80. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagementsystem/sqlite.py +0 -0
  81. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagementsystem/system.py +0 -0
  82. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/contentmanagementsystem/test_system.py +0 -0
  83. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchablecontent/__init__.py +0 -0
  84. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchablecontent/application.py +0 -0
  85. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchablecontent/persistence.py +0 -0
  86. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchablecontent/postgres.py +0 -0
  87. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchablecontent/sqlite.py +0 -0
  88. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchablecontent/test_application.py +0 -0
  89. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchablecontent/test_recorder.py +0 -0
  90. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchabletimestamps/__init__.py +0 -0
  91. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchabletimestamps/application.py +0 -0
  92. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchabletimestamps/persistence.py +0 -0
  93. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchabletimestamps/postgres.py +0 -0
  94. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchabletimestamps/sqlite.py +0 -0
  95. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/searchabletimestamps/test_searchabletimestamps.py +0 -0
  96. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/test_invoice.py +0 -0
  97. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/examples/test_parking_lot.py +0 -0
  98. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/interface.py +0 -0
  99. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/persistence.py +0 -0
  100. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/popo.py +0 -0
  101. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/py.typed +0 -0
  102. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/sqlite.py +0 -0
  103. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/__init__.py +0 -0
  104. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application.py +0 -0
  105. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/__init__.py +0 -0
  106. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_application_with_automatic_snapshotting.py +0 -0
  107. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_application_with_popo.py +0 -0
  108. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_application_with_postgres.py +0 -0
  109. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_application_with_sqlite.py +0 -0
  110. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_cache.py +0 -0
  111. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_event_sourced_log.py +0 -0
  112. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_notificationlog.py +0 -0
  113. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_notificationlogreader.py +0 -0
  114. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_processapplication.py +0 -0
  115. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_processingpolicy.py +0 -0
  116. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_repository.py +0 -0
  117. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_snapshotting.py +0 -0
  118. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/application_tests/test_upcasting.py +0 -0
  119. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/docs_tests/__init__.py +0 -0
  120. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/docs_tests/test_docs.py +0 -0
  121. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/domain.py +0 -0
  122. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/domain_tests/__init__.py +0 -0
  123. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/domain_tests/test_aggregate.py +0 -0
  124. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/domain_tests/test_aggregate_decorators.py +0 -0
  125. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/domain_tests/test_domainevent.py +0 -0
  126. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/interface_tests/__init__.py +0 -0
  127. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/interface_tests/test_remotenotificationlog.py +0 -0
  128. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence.py +0 -0
  129. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/__init__.py +0 -0
  130. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_aes.py +0 -0
  131. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_connection_pool.py +0 -0
  132. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_eventstore.py +0 -0
  133. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_infrastructure_factory.py +0 -0
  134. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_mapper.py +0 -0
  135. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_noninterleaving_notification_ids.py +0 -0
  136. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_popo.py +0 -0
  137. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_sqlite.py +0 -0
  138. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/persistence_tests/test_transcoder.py +0 -0
  139. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/postgres_utils.py +0 -0
  140. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/system_tests/__init__.py +0 -0
  141. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/system_tests/test_runner.py +0 -0
  142. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/system_tests/test_system.py +0 -0
  143. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/utils_tests/__init__.py +0 -0
  144. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/tests/utils_tests/test_utils.py +0 -0
  145. {eventsourcing-9.3.2 → eventsourcing-9.3.3}/eventsourcing/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eventsourcing
3
- Version: 9.3.2
3
+ Version: 9.3.3
4
4
  Summary: Event sourcing in Python
5
5
  Home-page: https://github.com/pyeventsourcing/eventsourcing
6
6
  License: BSD 3-Clause
@@ -25,15 +25,10 @@ Classifier: Programming Language :: Python :: 3.12
25
25
  Classifier: Programming Language :: Python :: 3.13
26
26
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
27
  Provides-Extra: crypto
28
- Provides-Extra: docs
29
28
  Provides-Extra: postgres
30
- Requires-Dist: Sphinx ; extra == "docs"
31
29
  Requires-Dist: backports.zoneinfo ; python_version < "3.9"
32
- Requires-Dist: orjson ; extra == "docs"
33
- Requires-Dist: psycopg[c,pool] (<=3.2.1) ; (python_full_version <= "3.12.999999") and (extra == "postgres")
34
- Requires-Dist: pycryptodome (>=3.20,<3.21) ; extra == "crypto"
35
- Requires-Dist: pydantic ; extra == "docs"
36
- Requires-Dist: sphinx_rtd_theme ; extra == "docs"
30
+ Requires-Dist: psycopg[c,pool] (<=3.2.99999) ; extra == "postgres"
31
+ Requires-Dist: pycryptodome (>=3.21,<3.22) ; extra == "crypto"
37
32
  Requires-Dist: typing_extensions
38
33
  Project-URL: Repository, https://github.com/pyeventsourcing/eventsourcing
39
34
  Description-Content-Type: text/markdown
@@ -36,7 +36,12 @@ class DogSchool(Application):
36
36
 
37
37
  def get_dog(self, dog_id: UUID) -> Dict[str, Any]:
38
38
  dog = self.repository.get(dog_id, projector_func=project_dog)
39
- return {"name": dog.name, "tricks": tuple([t.name for t in dog.tricks])}
39
+ return {
40
+ "name": dog.name,
41
+ "tricks": tuple([t.name for t in dog.tricks]),
42
+ "created_on": dog.created_on,
43
+ "modified_on": dog.modified_on,
44
+ }
40
45
 
41
46
  def construct_mapper(self) -> Mapper:
42
47
  return self.factory.mapper(
@@ -5,33 +5,31 @@ from functools import singledispatch
5
5
  from typing import Any, Callable, Dict, Iterable, Optional, Tuple, TypeVar
6
6
  from uuid import UUID, uuid4
7
7
 
8
- from pydantic import BaseModel
8
+ from pydantic import BaseModel, ConfigDict
9
9
 
10
10
  from eventsourcing.utils import get_topic
11
11
 
12
12
 
13
13
  class DomainEvent(BaseModel):
14
+ model_config = ConfigDict(frozen=True, extra="forbid")
15
+
14
16
  originator_id: UUID
15
17
  originator_version: int
16
18
  timestamp: datetime
17
19
 
18
- class Config:
19
- frozen = True
20
-
21
20
 
22
21
  def create_timestamp() -> datetime:
23
22
  return datetime.now(tz=timezone.utc)
24
23
 
25
24
 
26
25
  class Aggregate(BaseModel):
26
+ model_config = ConfigDict(frozen=True, extra="forbid")
27
+
27
28
  id: UUID
28
29
  version: int
29
30
  created_on: datetime
30
31
  modified_on: datetime
31
32
 
32
- class Config:
33
- frozen = True
34
-
35
33
 
36
34
  class Snapshot(DomainEvent):
37
35
  topic: str
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from datetime import datetime
3
4
  from unittest import TestCase
4
5
 
5
6
  from eventsourcing.examples.aggregate7.application import DogSchool
@@ -20,6 +21,8 @@ class TestDogSchool(TestCase):
20
21
  dog = school.get_dog(dog_id)
21
22
  self.assertEqual(dog["name"], "Fido")
22
23
  self.assertEqual(dog["tricks"], ("roll over", "play dead"))
24
+ self.assertIsInstance(dog["created_on"], datetime)
25
+ self.assertIsInstance(dog["modified_on"], datetime)
23
26
 
24
27
  # Select notifications.
25
28
  notifications = school.notification_log.select(start=1, limit=10)
@@ -30,9 +33,13 @@ class TestDogSchool(TestCase):
30
33
  dog = school.get_dog(dog_id)
31
34
  self.assertEqual(dog["name"], "Fido")
32
35
  self.assertEqual(dog["tricks"], ("roll over", "play dead"))
36
+ self.assertIsInstance(dog["created_on"], datetime)
37
+ self.assertIsInstance(dog["modified_on"], datetime)
33
38
 
34
39
  # Continue with snapshotted aggregate.
35
40
  school.add_trick(dog_id, "fetch ball")
36
41
  dog = school.get_dog(dog_id)
37
42
  self.assertEqual(dog["name"], "Fido")
38
43
  self.assertEqual(dog["tricks"], ("roll over", "play dead", "fetch ball"))
44
+ self.assertIsInstance(dog["created_on"], datetime)
45
+ self.assertIsInstance(dog["modified_on"], datetime)
@@ -7,33 +7,31 @@ from functools import singledispatch
7
7
  from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, TypeVar
8
8
  from uuid import UUID, uuid4
9
9
 
10
- from pydantic import BaseModel
10
+ from pydantic import BaseModel, ConfigDict
11
11
 
12
12
  from eventsourcing.utils import get_topic
13
13
 
14
14
 
15
15
  class DomainEvent(BaseModel):
16
+ model_config = ConfigDict(frozen=True, extra="forbid")
17
+
16
18
  originator_id: UUID
17
19
  originator_version: int
18
20
  timestamp: datetime
19
21
 
20
- class Config:
21
- frozen = True
22
-
23
22
 
24
23
  def create_timestamp() -> datetime:
25
24
  return datetime.now(tz=timezone.utc)
26
25
 
27
26
 
28
27
  class Aggregate(BaseModel):
28
+ model_config = ConfigDict(frozen=True, extra="forbid")
29
+
29
30
  id: UUID
30
31
  version: int
31
32
  created_on: datetime
32
33
  modified_on: datetime
33
34
 
34
- class Config:
35
- frozen = True
36
-
37
35
  def hold_event(self, event: DomainEvent) -> None:
38
36
  all_pending_events[id(self)].append(event)
39
37
 
@@ -1,10 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
- from datetime import datetime # noqa: TCH003
4
- from typing import List
5
- from uuid import UUID # noqa: TCH003
3
+ from datetime import datetime
4
+ from typing import Any, List
5
+ from uuid import UUID
6
6
 
7
- from pydantic import BaseModel, Extra
7
+ from pydantic import BaseModel, ConfigDict, TypeAdapter
8
8
 
9
9
  from eventsourcing.domain import (
10
10
  Aggregate as BaseAggregate,
@@ -16,25 +16,23 @@ from eventsourcing.domain import (
16
16
 
17
17
 
18
18
  class DomainEvent(BaseModel):
19
+ model_config = ConfigDict(frozen=True, extra="forbid")
20
+
19
21
  originator_id: UUID
20
22
  originator_version: int
21
23
  timestamp: datetime
22
24
 
23
- class Config:
24
- frozen = True
25
25
 
26
-
27
- class Aggregate(BaseAggregate):
28
- class Event(DomainEvent, CanMutateAggregate):
29
- pass
30
-
31
- class Created(Event, CanInitAggregate):
32
- originator_topic: str
26
+ datetime_adapter = TypeAdapter(datetime)
33
27
 
34
28
 
35
29
  class SnapshotState(BaseModel):
36
- class Config:
37
- extra = Extra.allow
30
+ model_config = ConfigDict(frozen=True, extra="allow")
31
+
32
+ def __init__(self, **kwargs: Any) -> None:
33
+ for key in ["_created_on", "_modified_on"]:
34
+ kwargs[key] = datetime_adapter.validate_python(kwargs[key])
35
+ super().__init__(**kwargs)
38
36
 
39
37
 
40
38
  class AggregateSnapshot(DomainEvent, CanSnapshotAggregate):
@@ -42,18 +40,26 @@ class AggregateSnapshot(DomainEvent, CanSnapshotAggregate):
42
40
  state: SnapshotState
43
41
 
44
42
 
43
+ class Aggregate(BaseAggregate):
44
+ class Event(DomainEvent, CanMutateAggregate):
45
+ pass
46
+
47
+ class Created(Event, CanInitAggregate):
48
+ originator_topic: str
49
+
50
+
45
51
  class Trick(BaseModel):
46
52
  name: str
47
53
 
48
54
 
49
- class DogState(SnapshotState):
55
+ class DogSnapshotState(SnapshotState):
50
56
  name: str
51
57
  tricks: List[Trick]
52
58
 
53
59
 
54
60
  class Dog(Aggregate):
55
61
  class Snapshot(AggregateSnapshot):
56
- state: DogState
62
+ state: DogSnapshotState
57
63
 
58
64
  @event("Registered")
59
65
  def __init__(self, name: str) -> None:
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from datetime import datetime
3
4
  from unittest import TestCase
4
5
 
5
6
  from eventsourcing.examples.aggregate8.application import DogSchool
@@ -19,6 +20,8 @@ class TestDogSchool(TestCase):
19
20
  dog = school.get_dog(dog_id)
20
21
  self.assertEqual(dog["name"], "Fido")
21
22
  self.assertEqual(dog["tricks"], ("roll over", "play dead"))
23
+ self.assertIsInstance(dog["created_on"], datetime)
24
+ self.assertIsInstance(dog["modified_on"], datetime)
22
25
 
23
26
  # Select notifications.
24
27
  notifications = school.notification_log.select(start=1, limit=10)
@@ -29,9 +32,13 @@ class TestDogSchool(TestCase):
29
32
  dog = school.get_dog(dog_id)
30
33
  self.assertEqual(dog["name"], "Fido")
31
34
  self.assertEqual(dog["tricks"], ("roll over", "play dead"))
35
+ self.assertIsInstance(dog["created_on"], datetime)
36
+ self.assertIsInstance(dog["modified_on"], datetime)
32
37
 
33
38
  # Continue with snapshotted aggregate.
34
39
  school.add_trick(dog_id, "fetch ball")
35
40
  dog = school.get_dog(dog_id)
36
41
  self.assertEqual(dog["name"], "Fido")
37
42
  self.assertEqual(dog["tricks"], ("roll over", "play dead", "fetch ball"))
43
+ self.assertIsInstance(dog["created_on"], datetime)
44
+ self.assertIsInstance(dog["modified_on"], datetime)
@@ -9,7 +9,6 @@ import psycopg.errors
9
9
  import psycopg_pool
10
10
  from psycopg import Connection, Cursor
11
11
  from psycopg.rows import DictRow, dict_row
12
- from typing_extensions import Self
13
12
 
14
13
  from eventsourcing.persistence import (
15
14
  AggregateRecorder,
@@ -34,6 +33,8 @@ from eventsourcing.utils import Environment, resolve_topic, retry, strtobool
34
33
  if TYPE_CHECKING: # pragma: nocover
35
34
  from uuid import UUID
36
35
 
36
+ from typing_extensions import Self
37
+
37
38
  logging.getLogger("psycopg.pool").setLevel(logging.CRITICAL)
38
39
  logging.getLogger("psycopg").setLevel(logging.CRITICAL)
39
40
 
@@ -8,6 +8,7 @@ from queue import Full, Queue
8
8
  from threading import Event, Lock, RLock, Thread
9
9
  from types import FrameType, ModuleType
10
10
  from typing import (
11
+ TYPE_CHECKING,
11
12
  Any,
12
13
  ClassVar,
13
14
  Dict,
@@ -22,7 +23,8 @@ from typing import (
22
23
  cast,
23
24
  )
24
25
 
25
- from typing_extensions import Self
26
+ if TYPE_CHECKING: # pragma: nocover
27
+ from typing_extensions import Self
26
28
 
27
29
  from eventsourcing.application import (
28
30
  Application,
@@ -232,6 +232,7 @@ class TestPostgresDatastore(TestCase):
232
232
  user="eventsourcing",
233
233
  password="wrong", # noqa: S106
234
234
  pool_size=1,
235
+ connect_timeout=3,
235
236
  ) as datastore:
236
237
 
237
238
  conn: Connection
@@ -261,7 +262,7 @@ class TestPostgresDatastore(TestCase):
261
262
  password="",
262
263
  pool_size=1,
263
264
  get_password_func=get_password_func,
264
- connect_timeout=10,
265
+ connect_timeout=3,
265
266
  ) as datastore, datastore.get_connection() as conn, conn.cursor() as curs:
266
267
  # Create a connection, and check it works (this test depends on psycopg
267
268
  # retrying attempt to connect, should call "get password" twice).
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "eventsourcing"
3
- version = "9.3.2"
3
+ version = "9.3.3"
4
4
 
5
5
  description = "Event sourcing in Python"
6
6
  authors = [
@@ -48,48 +48,27 @@ keywords=[
48
48
  python = ">=3.8,<4.0"
49
49
  typing_extensions = "*"
50
50
  "backports.zoneinfo" = { version = "*", python = "<3.9" }
51
- pycryptodome = { version = "~3.20", optional = true }
52
-
53
- psycopg = { version = "<=3.2.1", optional = true, extras = ["c", "pool"], python = "<=3.12.999999" }
54
-
55
- Sphinx = { version = "*", optional = true }
56
- sphinx_rtd_theme = { version = "*", optional = true }
57
- pydantic = { version = "*", optional = true }
58
- orjson = { version = "*", optional = true }
51
+ pycryptodome = { version = "~3.21", optional = true }
52
+ psycopg = { version = "<=3.2.99999", optional = true, extras=["c,pool"]}
59
53
 
60
54
  [tool.poetry.extras]
61
55
  crypto = ["pycryptodome"]
62
56
  postgres = ["psycopg"]
63
- docs = ["Sphinx", "sphinx_rtd_theme", "pydantic", "orjson"]
64
57
 
65
58
  [tool.poetry.group.dev.dependencies]
66
59
  black = { version = "*", allow-prereleases = true }
67
60
  coverage = "^7.2.7"
68
- flake8 = "*"
69
- flake8-broken-line = "*"
70
- flake8-bugbear = "*"
71
- flake8-coding = "*"
72
- flake8-isort = "*"
73
- flake8-tidy-imports = "*"
74
61
  isort = "*"
75
62
  mypy = "*"
76
- python-coveralls = "*"
77
- psycopg = [
78
- { version = "<=3.2.1", python = "<=3.12.999999" },
79
- { git = "https://github.com/psycopg/psycopg", branch="master", subdirectory = "psycopg", python = ">3.12.999999" }
80
- ]
81
- psycopg-binary = [
82
- { version = "<=3.2.1", python = "<=3.12.999999" },
83
- ]
84
- psycopg-c = [
85
- { git = "https://github.com/psycopg/psycopg", branch="master", subdirectory = "psycopg_c", python = ">3.12.999999" }
86
- ]
87
- psycopg-pool = [
88
- { version = "<=3.2.2", python = "<=3.12.999999" },
89
- { git = "https://github.com/psycopg/psycopg", branch="master", subdirectory = "psycopg_pool", python = ">3.12.999999" }
90
- ]
63
+ psycopg = { version = "<=3.2.99999", extras = ["binary", "pool"] }
91
64
  ruff = "^0.1.14"
92
65
 
66
+ [tool.poetry.group.docs.dependencies]
67
+ Sphinx = { version = "*"}
68
+ sphinx_rtd_theme = { version = "*"}
69
+ pydantic = { version = "~2.9"}
70
+ orjson = { version = "~3.10.11"}
71
+
93
72
 
94
73
  [build-system]
95
74
  requires = ["poetry-core>=1.0.0"]
@@ -218,6 +197,9 @@ unfixable = []
218
197
  # Allow unused variables when underscore-prefixed.
219
198
  dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
220
199
 
200
+ [tool.ruff.lint.flake8-type-checking]
201
+ runtime-evaluated-base-classes = ["pydantic.BaseModel"]
202
+
221
203
  [tool.ruff.format]
222
204
  # Like Black, use double quotes for strings.
223
205
  quote-style = "double"
File without changes
File without changes
File without changes