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

Potentially problematic release.


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

Files changed (145) hide show
  1. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/PKG-INFO +1 -1
  2. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/pyproject.toml +2 -8
  3. eventsourcing-9.3.3/eventsourcing/examples/aggregate1/__init__.py +0 -0
  4. eventsourcing-9.3.3/eventsourcing/examples/aggregate1/application.py +0 -27
  5. eventsourcing-9.3.3/eventsourcing/examples/aggregate1/domainmodel.py +0 -16
  6. eventsourcing-9.3.3/eventsourcing/examples/aggregate1/test_application.py +0 -37
  7. eventsourcing-9.3.3/eventsourcing/examples/aggregate2/__init__.py +0 -0
  8. eventsourcing-9.3.3/eventsourcing/examples/aggregate2/application.py +0 -27
  9. eventsourcing-9.3.3/eventsourcing/examples/aggregate2/domainmodel.py +0 -22
  10. eventsourcing-9.3.3/eventsourcing/examples/aggregate2/test_application.py +0 -37
  11. eventsourcing-9.3.3/eventsourcing/examples/aggregate3/__init__.py +0 -0
  12. eventsourcing-9.3.3/eventsourcing/examples/aggregate3/application.py +0 -27
  13. eventsourcing-9.3.3/eventsourcing/examples/aggregate3/domainmodel.py +0 -38
  14. eventsourcing-9.3.3/eventsourcing/examples/aggregate3/test_application.py +0 -37
  15. eventsourcing-9.3.3/eventsourcing/examples/aggregate4/__init__.py +0 -0
  16. eventsourcing-9.3.3/eventsourcing/examples/aggregate4/application.py +0 -27
  17. eventsourcing-9.3.3/eventsourcing/examples/aggregate4/domainmodel.py +0 -114
  18. eventsourcing-9.3.3/eventsourcing/examples/aggregate4/test_application.py +0 -38
  19. eventsourcing-9.3.3/eventsourcing/examples/aggregate5/__init__.py +0 -0
  20. eventsourcing-9.3.3/eventsourcing/examples/aggregate5/application.py +0 -27
  21. eventsourcing-9.3.3/eventsourcing/examples/aggregate5/domainmodel.py +0 -131
  22. eventsourcing-9.3.3/eventsourcing/examples/aggregate5/test_application.py +0 -38
  23. eventsourcing-9.3.3/eventsourcing/examples/aggregate6/__init__.py +0 -0
  24. eventsourcing-9.3.3/eventsourcing/examples/aggregate6/application.py +0 -30
  25. eventsourcing-9.3.3/eventsourcing/examples/aggregate6/domainmodel.py +0 -123
  26. eventsourcing-9.3.3/eventsourcing/examples/aggregate6/test_application.py +0 -38
  27. eventsourcing-9.3.3/eventsourcing/examples/aggregate6a/__init__.py +0 -0
  28. eventsourcing-9.3.3/eventsourcing/examples/aggregate6a/application.py +0 -40
  29. eventsourcing-9.3.3/eventsourcing/examples/aggregate6a/domainmodel.py +0 -149
  30. eventsourcing-9.3.3/eventsourcing/examples/aggregate6a/test_application.py +0 -45
  31. eventsourcing-9.3.3/eventsourcing/examples/aggregate7/__init__.py +0 -0
  32. eventsourcing-9.3.3/eventsourcing/examples/aggregate7/application.py +0 -53
  33. eventsourcing-9.3.3/eventsourcing/examples/aggregate7/domainmodel.py +0 -142
  34. eventsourcing-9.3.3/eventsourcing/examples/aggregate7/persistence.py +0 -57
  35. eventsourcing-9.3.3/eventsourcing/examples/aggregate7/test_application.py +0 -45
  36. eventsourcing-9.3.3/eventsourcing/examples/aggregate7/test_compression_and_encryption.py +0 -45
  37. eventsourcing-9.3.3/eventsourcing/examples/aggregate7/test_snapshotting_intervals.py +0 -67
  38. eventsourcing-9.3.3/eventsourcing/examples/aggregate7a/__init__.py +0 -0
  39. eventsourcing-9.3.3/eventsourcing/examples/aggregate7a/application.py +0 -56
  40. eventsourcing-9.3.3/eventsourcing/examples/aggregate7a/domainmodel.py +0 -168
  41. eventsourcing-9.3.3/eventsourcing/examples/aggregate7a/test_application.py +0 -46
  42. eventsourcing-9.3.3/eventsourcing/examples/aggregate7a/test_compression_and_encryption.py +0 -45
  43. eventsourcing-9.3.3/eventsourcing/examples/aggregate8/__init__.py +0 -0
  44. eventsourcing-9.3.3/eventsourcing/examples/aggregate8/application.py +0 -47
  45. eventsourcing-9.3.3/eventsourcing/examples/aggregate8/domainmodel.py +0 -71
  46. eventsourcing-9.3.3/eventsourcing/examples/aggregate8/persistence.py +0 -57
  47. eventsourcing-9.3.3/eventsourcing/examples/aggregate8/test_application.py +0 -44
  48. eventsourcing-9.3.3/eventsourcing/examples/aggregate8/test_compression_and_encryption.py +0 -44
  49. eventsourcing-9.3.3/eventsourcing/examples/aggregate8/test_snapshotting_intervals.py +0 -38
  50. eventsourcing-9.3.3/eventsourcing/examples/bankaccounts/__init__.py +0 -0
  51. eventsourcing-9.3.3/eventsourcing/examples/bankaccounts/application.py +0 -70
  52. eventsourcing-9.3.3/eventsourcing/examples/bankaccounts/domainmodel.py +0 -56
  53. eventsourcing-9.3.3/eventsourcing/examples/bankaccounts/test.py +0 -173
  54. eventsourcing-9.3.3/eventsourcing/examples/cargoshipping/__init__.py +0 -0
  55. eventsourcing-9.3.3/eventsourcing/examples/cargoshipping/application.py +0 -126
  56. eventsourcing-9.3.3/eventsourcing/examples/cargoshipping/domainmodel.py +0 -330
  57. eventsourcing-9.3.3/eventsourcing/examples/cargoshipping/interface.py +0 -143
  58. eventsourcing-9.3.3/eventsourcing/examples/cargoshipping/test.py +0 -231
  59. eventsourcing-9.3.3/eventsourcing/examples/contentmanagement/__init__.py +0 -0
  60. eventsourcing-9.3.3/eventsourcing/examples/contentmanagement/application.py +0 -118
  61. eventsourcing-9.3.3/eventsourcing/examples/contentmanagement/domainmodel.py +0 -69
  62. eventsourcing-9.3.3/eventsourcing/examples/contentmanagement/test.py +0 -180
  63. eventsourcing-9.3.3/eventsourcing/examples/contentmanagement/utils.py +0 -26
  64. eventsourcing-9.3.3/eventsourcing/examples/contentmanagementsystem/__init__.py +0 -0
  65. eventsourcing-9.3.3/eventsourcing/examples/contentmanagementsystem/application.py +0 -54
  66. eventsourcing-9.3.3/eventsourcing/examples/contentmanagementsystem/postgres.py +0 -17
  67. eventsourcing-9.3.3/eventsourcing/examples/contentmanagementsystem/sqlite.py +0 -17
  68. eventsourcing-9.3.3/eventsourcing/examples/contentmanagementsystem/system.py +0 -14
  69. eventsourcing-9.3.3/eventsourcing/examples/contentmanagementsystem/test_system.py +0 -180
  70. eventsourcing-9.3.3/eventsourcing/examples/searchablecontent/__init__.py +0 -0
  71. eventsourcing-9.3.3/eventsourcing/examples/searchablecontent/application.py +0 -45
  72. eventsourcing-9.3.3/eventsourcing/examples/searchablecontent/persistence.py +0 -23
  73. eventsourcing-9.3.3/eventsourcing/examples/searchablecontent/postgres.py +0 -118
  74. eventsourcing-9.3.3/eventsourcing/examples/searchablecontent/sqlite.py +0 -136
  75. eventsourcing-9.3.3/eventsourcing/examples/searchablecontent/test_application.py +0 -110
  76. eventsourcing-9.3.3/eventsourcing/examples/searchablecontent/test_recorder.py +0 -68
  77. eventsourcing-9.3.3/eventsourcing/examples/searchabletimestamps/__init__.py +0 -0
  78. eventsourcing-9.3.3/eventsourcing/examples/searchabletimestamps/application.py +0 -32
  79. eventsourcing-9.3.3/eventsourcing/examples/searchabletimestamps/persistence.py +0 -20
  80. eventsourcing-9.3.3/eventsourcing/examples/searchabletimestamps/postgres.py +0 -110
  81. eventsourcing-9.3.3/eventsourcing/examples/searchabletimestamps/sqlite.py +0 -99
  82. eventsourcing-9.3.3/eventsourcing/examples/searchabletimestamps/test_searchabletimestamps.py +0 -94
  83. eventsourcing-9.3.3/eventsourcing/examples/test_invoice.py +0 -176
  84. eventsourcing-9.3.3/eventsourcing/examples/test_parking_lot.py +0 -206
  85. eventsourcing-9.3.3/eventsourcing/tests/__init__.py +0 -0
  86. eventsourcing-9.3.3/eventsourcing/tests/application_tests/__init__.py +0 -0
  87. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_application_with_automatic_snapshotting.py +0 -55
  88. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_application_with_popo.py +0 -22
  89. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_application_with_postgres.py +0 -75
  90. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_application_with_sqlite.py +0 -72
  91. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_cache.py +0 -134
  92. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_event_sourced_log.py +0 -162
  93. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_notificationlog.py +0 -232
  94. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_notificationlogreader.py +0 -126
  95. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_processapplication.py +0 -110
  96. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_processingpolicy.py +0 -109
  97. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_repository.py +0 -504
  98. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_snapshotting.py +0 -68
  99. eventsourcing-9.3.3/eventsourcing/tests/application_tests/test_upcasting.py +0 -459
  100. eventsourcing-9.3.3/eventsourcing/tests/docs_tests/__init__.py +0 -0
  101. eventsourcing-9.3.3/eventsourcing/tests/docs_tests/test_docs.py +0 -293
  102. eventsourcing-9.3.3/eventsourcing/tests/domain_tests/__init__.py +0 -0
  103. eventsourcing-9.3.3/eventsourcing/tests/domain_tests/test_aggregate.py +0 -1200
  104. eventsourcing-9.3.3/eventsourcing/tests/domain_tests/test_aggregate_decorators.py +0 -1604
  105. eventsourcing-9.3.3/eventsourcing/tests/domain_tests/test_domainevent.py +0 -80
  106. eventsourcing-9.3.3/eventsourcing/tests/interface_tests/__init__.py +0 -0
  107. eventsourcing-9.3.3/eventsourcing/tests/interface_tests/test_remotenotificationlog.py +0 -258
  108. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/__init__.py +0 -0
  109. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_aes.py +0 -93
  110. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_connection_pool.py +0 -722
  111. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_eventstore.py +0 -72
  112. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_infrastructure_factory.py +0 -21
  113. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_mapper.py +0 -113
  114. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_noninterleaving_notification_ids.py +0 -69
  115. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_popo.py +0 -124
  116. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_postgres.py +0 -1120
  117. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_sqlite.py +0 -348
  118. eventsourcing-9.3.3/eventsourcing/tests/persistence_tests/test_transcoder.py +0 -44
  119. eventsourcing-9.3.3/eventsourcing/tests/system_tests/__init__.py +0 -0
  120. eventsourcing-9.3.3/eventsourcing/tests/system_tests/test_runner.py +0 -935
  121. eventsourcing-9.3.3/eventsourcing/tests/system_tests/test_system.py +0 -284
  122. eventsourcing-9.3.3/eventsourcing/tests/utils_tests/__init__.py +0 -0
  123. eventsourcing-9.3.3/eventsourcing/tests/utils_tests/test_utils.py +0 -226
  124. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/AUTHORS +0 -0
  125. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/LICENSE +0 -0
  126. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/README.md +0 -0
  127. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/__init__.py +0 -0
  128. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/application.py +0 -0
  129. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/cipher.py +0 -0
  130. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/compressor.py +0 -0
  131. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/dispatch.py +0 -0
  132. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/domain.py +0 -0
  133. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/interface.py +0 -0
  134. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/persistence.py +0 -0
  135. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/popo.py +0 -0
  136. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/postgres.py +0 -0
  137. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/py.typed +0 -0
  138. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/sqlite.py +0 -0
  139. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/system.py +0 -0
  140. {eventsourcing-9.3.3/eventsourcing/examples → eventsourcing-9.3.4/eventsourcing/tests}/__init__.py +0 -0
  141. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/tests/application.py +0 -0
  142. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/tests/domain.py +0 -0
  143. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/tests/persistence.py +0 -0
  144. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/tests/postgres_utils.py +0 -0
  145. {eventsourcing-9.3.3 → eventsourcing-9.3.4}/eventsourcing/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eventsourcing
3
- Version: 9.3.3
3
+ Version: 9.3.4
4
4
  Summary: Event sourcing in Python
5
5
  Home-page: https://github.com/pyeventsourcing/eventsourcing
6
6
  License: BSD 3-Clause
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "eventsourcing"
3
- version = "9.3.3"
3
+ version = "9.3.4"
4
4
 
5
5
  description = "Event sourcing in Python"
6
6
  authors = [
@@ -30,10 +30,6 @@ readme = "README.md"
30
30
  homepage = "https://github.com/pyeventsourcing/eventsourcing"
31
31
  repository = "https://github.com/pyeventsourcing/eventsourcing"
32
32
  include = ["eventsourcing/py.typed"]
33
- packages = [
34
- { include = "eventsourcing" },
35
- { include = "eventsourcing/tests" },
36
- ]
37
33
  keywords=[
38
34
  "event sourcing",
39
35
  "event store",
@@ -97,9 +93,7 @@ exclude = '''
97
93
 
98
94
  [tool.coverage.run]
99
95
  branch = true
100
- omit = [
101
- "esdbclient/protos/*"
102
- ]
96
+ omit = []
103
97
 
104
98
  [tool.coverage.report]
105
99
  exclude_lines = [
@@ -1,27 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, Dict
4
-
5
- from eventsourcing.application import Application
6
- from eventsourcing.examples.aggregate1.domainmodel import Dog
7
-
8
- if TYPE_CHECKING: # pragma: nocover
9
- from uuid import UUID
10
-
11
-
12
- class DogSchool(Application):
13
- is_snapshotting_enabled = True
14
-
15
- def register_dog(self, name: str) -> UUID:
16
- dog = Dog(name)
17
- self.save(dog)
18
- return dog.id
19
-
20
- def add_trick(self, dog_id: UUID, trick: str) -> None:
21
- dog: Dog = self.repository.get(dog_id)
22
- dog.add_trick(trick)
23
- self.save(dog)
24
-
25
- def get_dog(self, dog_id: UUID) -> Dict[str, Any]:
26
- dog: Dog = self.repository.get(dog_id)
27
- return {"name": dog.name, "tricks": tuple(dog.tricks)}
@@ -1,16 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import List
4
-
5
- from eventsourcing.domain import Aggregate, event
6
-
7
-
8
- class Dog(Aggregate):
9
- @event("Registered")
10
- def __init__(self, name: str) -> None:
11
- self.name = name
12
- self.tricks: List[str] = []
13
-
14
- @event("TrickAdded")
15
- def add_trick(self, trick: str) -> None:
16
- self.tricks.append(trick)
@@ -1,37 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from unittest import TestCase
4
-
5
- from eventsourcing.examples.aggregate1.application import DogSchool
6
-
7
-
8
- class TestDogSchool(TestCase):
9
- def test_dog_school(self) -> None:
10
- # Construct application object.
11
- school = DogSchool()
12
-
13
- # Evolve application state.
14
- dog_id = school.register_dog("Fido")
15
- school.add_trick(dog_id, "roll over")
16
- school.add_trick(dog_id, "play dead")
17
-
18
- # Query application state.
19
- dog = school.get_dog(dog_id)
20
- assert dog["name"] == "Fido"
21
- assert dog["tricks"] == ("roll over", "play dead")
22
-
23
- # Select notifications.
24
- notifications = school.notification_log.select(start=1, limit=10)
25
- assert len(notifications) == 3
26
-
27
- # Take snapshot.
28
- school.take_snapshot(dog_id, version=3)
29
- dog = school.get_dog(dog_id)
30
- assert dog["name"] == "Fido"
31
- assert dog["tricks"] == ("roll over", "play dead")
32
-
33
- # Continue with snapshotted aggregate.
34
- school.add_trick(dog_id, "fetch ball")
35
- dog = school.get_dog(dog_id)
36
- assert dog["name"] == "Fido"
37
- assert dog["tricks"] == ("roll over", "play dead", "fetch ball")
@@ -1,27 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, Dict
4
-
5
- from eventsourcing.application import Application
6
- from eventsourcing.examples.aggregate2.domainmodel import Dog
7
-
8
- if TYPE_CHECKING: # pragma: nocover
9
- from uuid import UUID
10
-
11
-
12
- class DogSchool(Application):
13
- is_snapshotting_enabled = True
14
-
15
- def register_dog(self, name: str) -> UUID:
16
- dog = Dog(name)
17
- self.save(dog)
18
- return dog.id
19
-
20
- def add_trick(self, dog_id: UUID, trick: str) -> None:
21
- dog: Dog = self.repository.get(dog_id)
22
- dog.add_trick(trick)
23
- self.save(dog)
24
-
25
- def get_dog(self, dog_id: UUID) -> Dict[str, Any]:
26
- dog: Dog = self.repository.get(dog_id)
27
- return {"name": dog.name, "tricks": tuple(dog.tricks)}
@@ -1,22 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import List
4
-
5
- from eventsourcing.domain import Aggregate, event
6
-
7
-
8
- class Dog(Aggregate):
9
- class Registered(Aggregate.Created):
10
- name: str
11
-
12
- class TrickAdded(Aggregate.Event):
13
- trick: str
14
-
15
- @event(Registered)
16
- def __init__(self, name: str) -> None:
17
- self.name = name
18
- self.tricks: List[str] = []
19
-
20
- @event(TrickAdded)
21
- def add_trick(self, trick: str) -> None:
22
- self.tricks.append(trick)
@@ -1,37 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from unittest import TestCase
4
-
5
- from eventsourcing.examples.aggregate2.application import DogSchool
6
-
7
-
8
- class TestDogSchool(TestCase):
9
- def test_dog_school(self) -> None:
10
- # Construct application object.
11
- school = DogSchool()
12
-
13
- # Evolve application state.
14
- dog_id = school.register_dog("Fido")
15
- school.add_trick(dog_id, "roll over")
16
- school.add_trick(dog_id, "play dead")
17
-
18
- # Query application state.
19
- dog = school.get_dog(dog_id)
20
- assert dog["name"] == "Fido"
21
- assert dog["tricks"] == ("roll over", "play dead")
22
-
23
- # Select notifications.
24
- notifications = school.notification_log.select(start=1, limit=10)
25
- assert len(notifications) == 3
26
-
27
- # Take snapshot.
28
- school.take_snapshot(dog_id, version=3)
29
- dog = school.get_dog(dog_id)
30
- assert dog["name"] == "Fido"
31
- assert dog["tricks"] == ("roll over", "play dead")
32
-
33
- # Continue with snapshotted aggregate.
34
- school.add_trick(dog_id, "fetch ball")
35
- dog = school.get_dog(dog_id)
36
- assert dog["name"] == "Fido"
37
- assert dog["tricks"] == ("roll over", "play dead", "fetch ball")
@@ -1,27 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, Dict
4
-
5
- from eventsourcing.application import Application
6
- from eventsourcing.examples.aggregate3.domainmodel import Dog
7
-
8
- if TYPE_CHECKING: # pragma: nocover
9
- from uuid import UUID
10
-
11
-
12
- class DogSchool(Application):
13
- is_snapshotting_enabled = True
14
-
15
- def register_dog(self, name: str) -> UUID:
16
- dog = Dog.register(name=name)
17
- self.save(dog)
18
- return dog.id
19
-
20
- def add_trick(self, dog_id: UUID, trick: str) -> None:
21
- dog: Dog = self.repository.get(dog_id)
22
- dog.add_trick(trick)
23
- self.save(dog)
24
-
25
- def get_dog(self, dog_id: UUID) -> Dict[str, Any]:
26
- dog: Dog = self.repository.get(dog_id)
27
- return {"name": dog.name, "tricks": tuple(dog.tricks)}
@@ -1,38 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import List, cast
4
-
5
- from eventsourcing.dispatch import singledispatchmethod
6
- from eventsourcing.domain import Aggregate
7
-
8
-
9
- class Dog(Aggregate):
10
- class Event(Aggregate.Event):
11
- def apply(self, aggregate: Aggregate) -> None:
12
- cast(Dog, aggregate).apply(self)
13
-
14
- class Registered(Event, Aggregate.Created):
15
- name: str
16
-
17
- class TrickAdded(Event):
18
- trick: str
19
-
20
- @classmethod
21
- def register(cls, name: str) -> Dog:
22
- return cls._create(cls.Registered, name=name)
23
-
24
- def add_trick(self, trick: str) -> None:
25
- self.trigger_event(self.TrickAdded, trick=trick)
26
-
27
- @singledispatchmethod
28
- def apply(self, event: Event) -> None:
29
- """Applies event to aggregate."""
30
-
31
- @apply.register
32
- def _(self, event: Dog.Registered) -> None:
33
- self.name = event.name
34
- self.tricks: List[str] = []
35
-
36
- @apply.register
37
- def _(self, event: Dog.TrickAdded) -> None:
38
- self.tricks.append(event.trick)
@@ -1,37 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from unittest import TestCase
4
-
5
- from eventsourcing.examples.aggregate3.application import DogSchool
6
-
7
-
8
- class TestDogSchool(TestCase):
9
- def test_dog_school(self) -> None:
10
- # Construct application object.
11
- school = DogSchool()
12
-
13
- # Evolve application state.
14
- dog_id = school.register_dog("Fido")
15
- school.add_trick(dog_id, "roll over")
16
- school.add_trick(dog_id, "play dead")
17
-
18
- # Query application state.
19
- dog = school.get_dog(dog_id)
20
- assert dog["name"] == "Fido"
21
- assert dog["tricks"] == ("roll over", "play dead")
22
-
23
- # Select notifications.
24
- notifications = school.notification_log.select(start=1, limit=10)
25
- assert len(notifications) == 3
26
-
27
- # Take snapshot.
28
- school.take_snapshot(dog_id, version=3)
29
- dog = school.get_dog(dog_id)
30
- assert dog["name"] == "Fido"
31
- assert dog["tricks"] == ("roll over", "play dead")
32
-
33
- # Continue with snapshotted aggregate.
34
- school.add_trick(dog_id, "fetch ball")
35
- dog = school.get_dog(dog_id)
36
- assert dog["name"] == "Fido"
37
- assert dog["tricks"] == ("roll over", "play dead", "fetch ball")
@@ -1,27 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, Dict
4
-
5
- from eventsourcing.application import Application
6
- from eventsourcing.examples.aggregate4.domainmodel import Dog
7
-
8
- if TYPE_CHECKING: # pragma: nocover
9
- from uuid import UUID
10
-
11
-
12
- class DogSchool(Application):
13
- is_snapshotting_enabled = True
14
-
15
- def register_dog(self, name: str) -> UUID:
16
- dog = Dog.register(name)
17
- self.save(dog)
18
- return dog.id
19
-
20
- def add_trick(self, dog_id: UUID, trick: str) -> None:
21
- dog = self.repository.get(dog_id, projector_func=Dog.projector)
22
- dog.add_trick(trick)
23
- self.save(dog)
24
-
25
- def get_dog(self, dog_id: UUID) -> Dict[str, Any]:
26
- dog = self.repository.get(dog_id, projector_func=Dog.projector)
27
- return {"name": dog.name, "tricks": tuple(dog.tricks)}
@@ -1,114 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from datetime import datetime, timezone
5
- from typing import Any, Iterable, List, Type, TypeVar, cast
6
- from uuid import UUID, uuid4
7
-
8
- from eventsourcing.dispatch import singledispatchmethod
9
- from eventsourcing.domain import Snapshot
10
-
11
-
12
- @dataclass(frozen=True)
13
- class DomainEvent:
14
- originator_version: int
15
- originator_id: UUID
16
- timestamp: datetime
17
-
18
- @staticmethod
19
- def create_timestamp() -> datetime:
20
- return datetime.now(tz=timezone.utc)
21
-
22
-
23
- TAggregate = TypeVar("TAggregate", bound="Aggregate")
24
-
25
-
26
- class Aggregate:
27
- id: UUID
28
- version: int
29
- created_on: datetime
30
- _pending_events: List[DomainEvent]
31
-
32
- def __init__(self, event: DomainEvent):
33
- self.id = event.originator_id
34
- self.version = event.originator_version
35
- self.created_on = event.timestamp
36
-
37
- def trigger_event(
38
- self,
39
- event_class: Type[DomainEvent],
40
- **kwargs: Any,
41
- ) -> None:
42
- kwargs = kwargs.copy()
43
- kwargs.update(
44
- originator_id=self.id,
45
- originator_version=self.version + 1,
46
- timestamp=event_class.create_timestamp(),
47
- )
48
- new_event = event_class(**kwargs)
49
- self._apply(new_event)
50
- self._pending_events.append(new_event)
51
-
52
- @singledispatchmethod
53
- def _apply(self, event: DomainEvent) -> None:
54
- """Applies event to aggregate."""
55
-
56
- def collect_events(self) -> List[DomainEvent]:
57
- events, self._pending_events = self._pending_events, []
58
- return events
59
-
60
- @classmethod
61
- def projector(
62
- cls: Type[TAggregate],
63
- _: TAggregate | None,
64
- events: Iterable[DomainEvent],
65
- ) -> TAggregate | None:
66
- aggregate: TAggregate = object.__new__(cls)
67
- aggregate._pending_events = []
68
- for event in events:
69
- aggregate._apply(event)
70
- return aggregate
71
-
72
-
73
- class Dog(Aggregate):
74
- @dataclass(frozen=True)
75
- class Registered(DomainEvent):
76
- name: str
77
-
78
- @dataclass(frozen=True)
79
- class TrickAdded(DomainEvent):
80
- trick: str
81
-
82
- @classmethod
83
- def register(cls, name: str) -> Dog:
84
- event = cls.Registered(
85
- originator_id=uuid4(),
86
- originator_version=1,
87
- timestamp=DomainEvent.create_timestamp(),
88
- name=name,
89
- )
90
- dog = cast(Dog, cls.projector(None, [event]))
91
- dog._pending_events.append(event)
92
- return dog
93
-
94
- def add_trick(self, trick: str) -> None:
95
- self.trigger_event(self.TrickAdded, trick=trick)
96
-
97
- @singledispatchmethod
98
- def _apply(self, event: DomainEvent) -> None:
99
- """Applies event to aggregate."""
100
-
101
- @_apply.register(Registered)
102
- def _(self, event: Registered) -> None:
103
- super().__init__(event)
104
- self.name = event.name
105
- self.tricks: List[str] = []
106
-
107
- @_apply.register(TrickAdded)
108
- def _(self, event: TrickAdded) -> None:
109
- self.tricks.append(event.trick)
110
- self.version = event.originator_version
111
-
112
- @_apply.register(Snapshot)
113
- def _(self, event: Snapshot) -> None:
114
- self.__dict__.update(event.state)
@@ -1,38 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from unittest import TestCase
4
-
5
- from eventsourcing.examples.aggregate4.application import DogSchool
6
- from eventsourcing.examples.aggregate4.domainmodel import Dog
7
-
8
-
9
- class TestDogSchool(TestCase):
10
- def test_dog_school(self) -> None:
11
- # Construct application object.
12
- school = DogSchool()
13
-
14
- # Evolve application state.
15
- dog_id = school.register_dog("Fido")
16
- school.add_trick(dog_id, "roll over")
17
- school.add_trick(dog_id, "play dead")
18
-
19
- # Query application state.
20
- dog = school.get_dog(dog_id)
21
- assert dog["name"] == "Fido"
22
- assert dog["tricks"] == ("roll over", "play dead")
23
-
24
- # Select notifications.
25
- notifications = school.notification_log.select(start=1, limit=10)
26
- assert len(notifications) == 3
27
-
28
- # Take snapshot.
29
- school.take_snapshot(dog_id, version=3, projector_func=Dog.projector)
30
- dog = school.get_dog(dog_id)
31
- assert dog["name"] == "Fido"
32
- assert dog["tricks"] == ("roll over", "play dead")
33
-
34
- # Continue with snapshotted aggregate.
35
- school.add_trick(dog_id, "fetch ball")
36
- dog = school.get_dog(dog_id)
37
- assert dog["name"] == "Fido"
38
- assert dog["tricks"] == ("roll over", "play dead", "fetch ball")
@@ -1,27 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, Dict
4
-
5
- from eventsourcing.application import Application
6
- from eventsourcing.examples.aggregate5.domainmodel import Dog
7
-
8
- if TYPE_CHECKING: # pragma: nocover
9
- from uuid import UUID
10
-
11
-
12
- class DogSchool(Application):
13
- is_snapshotting_enabled = True
14
-
15
- def register_dog(self, name: str) -> UUID:
16
- dog, event = Dog.register(name)
17
- self.save(event)
18
- return dog.id
19
-
20
- def add_trick(self, dog_id: UUID, trick: str) -> None:
21
- dog = self.repository.get(dog_id, projector_func=Dog.projector)
22
- dog, event = dog.add_trick(trick)
23
- self.save(event)
24
-
25
- def get_dog(self, dog_id: UUID) -> Dict[str, Any]:
26
- dog = self.repository.get(dog_id, projector_func=Dog.projector)
27
- return {"name": dog.name, "tricks": dog.tricks}
@@ -1,131 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from datetime import datetime, timezone
5
- from typing import Any, Iterable, Tuple, Type, TypeVar
6
- from uuid import UUID, uuid4
7
-
8
- from eventsourcing.dispatch import singledispatchmethod
9
- from eventsourcing.domain import Snapshot # noqa: TCH001
10
-
11
-
12
- @dataclass(frozen=True)
13
- class DomainEvent:
14
- originator_id: UUID
15
- originator_version: int
16
- timestamp: datetime
17
-
18
- @staticmethod
19
- def create_timestamp() -> datetime:
20
- return datetime.now(tz=timezone.utc)
21
-
22
-
23
- TAggregate = TypeVar("TAggregate", bound="Aggregate")
24
-
25
-
26
- @dataclass(frozen=True)
27
- class Aggregate:
28
- id: UUID
29
- version: int
30
- created_on: datetime
31
- modified_on: datetime
32
-
33
- def trigger_event(
34
- self,
35
- event_class: Type[DomainEvent],
36
- **kwargs: Any,
37
- ) -> DomainEvent:
38
- kwargs = kwargs.copy()
39
- kwargs.update(
40
- originator_id=self.id,
41
- originator_version=self.version + 1,
42
- timestamp=event_class.create_timestamp(),
43
- )
44
- return event_class(**kwargs)
45
-
46
- @classmethod
47
- def projector(
48
- cls: Type[TAggregate],
49
- aggregate: TAggregate | None,
50
- events: Iterable[DomainEvent],
51
- ) -> TAggregate | None:
52
- for event in events:
53
- aggregate = cls.mutate(event, aggregate)
54
- return aggregate
55
-
56
- @singledispatchmethod
57
- @staticmethod
58
- def mutate(event: DomainEvent, aggregate: Any) -> Any:
59
- """Mutates aggregate with event."""
60
-
61
-
62
- @dataclass(frozen=True)
63
- class Dog(Aggregate):
64
- name: str
65
- tricks: Tuple[str, ...]
66
-
67
- @dataclass(frozen=True)
68
- class Registered(DomainEvent):
69
- name: str
70
-
71
- @dataclass(frozen=True)
72
- class TrickAdded(DomainEvent):
73
- trick: str
74
-
75
- @staticmethod
76
- def register(name: str) -> Tuple[Dog, DomainEvent]:
77
- event = Dog.Registered(
78
- originator_id=uuid4(),
79
- originator_version=1,
80
- timestamp=DomainEvent.create_timestamp(),
81
- name=name,
82
- )
83
- dog = Dog.mutate(event, None)
84
- return dog, event
85
-
86
- def add_trick(self, trick: str) -> Tuple[Dog, DomainEvent]:
87
- event = self.trigger_event(Dog.TrickAdded, trick=trick)
88
- dog = Dog.mutate(event, self)
89
- return dog, event
90
-
91
- @singledispatchmethod
92
- @classmethod
93
- def mutate(cls, event: DomainEvent, aggregate: Dog | None) -> Dog | None:
94
- """Mutates aggregate with event."""
95
-
96
- @mutate.register
97
- @classmethod
98
- def _(cls, event: Dog.Registered, _: Dog | None) -> Dog:
99
- return Dog(
100
- id=event.originator_id,
101
- version=event.originator_version,
102
- created_on=event.timestamp,
103
- modified_on=event.timestamp,
104
- name=event.name,
105
- tricks=(),
106
- )
107
-
108
- @mutate.register
109
- @classmethod
110
- def _(cls, event: Dog.TrickAdded, aggregate: Dog | None) -> Dog:
111
- assert aggregate is not None
112
- return Dog(
113
- id=aggregate.id,
114
- version=event.originator_version,
115
- created_on=aggregate.created_on,
116
- modified_on=event.timestamp,
117
- name=aggregate.name,
118
- tricks=(*aggregate.tricks, event.trick),
119
- )
120
-
121
- @mutate.register
122
- @classmethod
123
- def _(cls, event: Snapshot, _: Dog | None) -> Dog:
124
- return Dog(
125
- id=event.state["id"],
126
- version=event.state["version"],
127
- created_on=event.state["created_on"],
128
- modified_on=event.state["modified_on"],
129
- name=event.state["name"],
130
- tricks=tuple(event.state["tricks"]), # comes back from JSON as a list
131
- )