Skip to content

Commit 3768d56

Browse files
committed
Factored out PydanticApplication from examples.
1 parent 690c8c3 commit 3768d56

File tree

21 files changed

+248
-161
lines changed

21 files changed

+248
-161
lines changed

docs/topics/examples/aggregate7.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This is demonstrated in the example below with the :class:`~examples.aggregate7.
1313
which is used in both aggregate events and aggregate state, and which is reconstructed from serialised string
1414
values, representing only the name of the trick, from both recorded aggregate events and from recorded snapshots.
1515

16+
1617
Pydantic mapper and orjson transcoder
1718
-------------------------------------
1819

@@ -33,6 +34,14 @@ available in Python.
3334
.. literalinclude:: ../../../examples/aggregate7/orjsonpydantic.py
3435
:pyobject: OrjsonTranscoder
3536

37+
The :class:`~examples.aggregate7.orjsonpydantic.PydanticApplication` class is a
38+
subclass of the library's :class:`~eventsourcing.application.Application` class
39+
which is configured to use :class:`~examples.aggregate7.orjsonpydantic.PydanticMapper`
40+
and :class:`~examples.aggregate7.orjsonpydantic.OrjsonTranscoder`.
41+
42+
.. literalinclude:: ../../../examples/aggregate7/orjsonpydantic.py
43+
:pyobject: PydanticApplication
44+
3645

3746
Pydantic model for immutable aggregate
3847
--------------------------------------
@@ -53,8 +62,8 @@ The code below shows how to define an immutable aggregate in a functional style,
5362
Application
5463
-----------
5564

56-
The :class:`~examples.aggregate7.application.DogSchool` application in this example uses the library's
57-
:class:`~eventsourcing.application.Application` class. It must receive the new events that are returned
65+
The :class:`~examples.aggregate7.application.DogSchool` application in this example uses the
66+
:class:`~examples.aggregate7.orjsonpydantic.PydanticApplication`. It must receive the new events that are returned
5867
by the aggregate command methods, and pass them to its :func:`~eventsourcing.application.Application.save`
5968
method. The aggregate projector function must also be supplied when reconstructing an aggregate from the
6069
repository, and when taking snapshots.

docs/topics/examples/aggregate8.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ are defined using Pydantic. The main advantage of using Pydantic here is that an
1414
used in the domain model will be automatically serialised and deserialised, without needing also to
1515
define custom :ref:`transcoding<Transcodings>` classes.
1616

17+
1718
Pydantic model for mutable aggregate
1819
------------------------------------
1920

@@ -33,10 +34,8 @@ The code below shows how to define an aggregate using the Pydantic and the libra
3334
Application
3435
-----------
3536

36-
The :class:`~examples.aggregate8.application.DogSchool` application in this example uses the library's
37-
:class:`~eventsourcing.application.Application` class. It also uses the
38-
:class:`~examples.aggregate7.orjsonpydantic.PydanticMapper` and
39-
:class:`~examples.aggregate7.orjsonpydantic.OrjsonTranscoder` classes
37+
The :class:`~examples.aggregate8.application.DogSchool` application in this example uses the
38+
:class:`~examples.aggregate7.orjsonpydantic.PydanticApplication` class
4039
from :doc:`example 7 </topics/examples/aggregate7>`.
4140

4241
.. literalinclude:: ../../../examples/aggregate8/application.py

docs/topics/examples/shop-standard.rst

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@ Application 6 - Shopping cart
66
This example suggests how a shopping cart might be implemented.
77

88

9+
Application
10+
-----------
11+
12+
.. literalinclude:: ../../../examples/shopstandard/application.py
13+
:pyobject: Shop
14+
15+
.. literalinclude:: ../../../examples/shopstandard/domain.py
16+
:pyobject: ProductDetails
17+
918
Domain model
1019
------------
1120

1221
.. literalinclude:: ../../../examples/shopstandard/domain.py
1322
:pyobject: Product
1423

15-
.. literalinclude:: ../../../examples/shopstandard/domain.py
16-
:pyobject: CartItem
17-
1824
.. literalinclude:: ../../../examples/shopstandard/domain.py
1925
:pyobject: Cart
2026

21-
Application
22-
-----------
23-
24-
.. literalinclude:: ../../../examples/shopstandard/application.py
25-
:pyobject: Shop
26-
2727
.. literalinclude:: ../../../examples/shopstandard/domain.py
28-
:pyobject: ProductDetails
28+
:pyobject: CartItem
2929

3030

3131
Exceptions
@@ -38,3 +38,28 @@ Test
3838

3939
.. literalinclude:: ../../../examples/shopvertical/test.py
4040
:pyobject: TestShop
41+
42+
Code reference
43+
--------------
44+
45+
.. automodule:: examples.shopstandard.application
46+
:show-inheritance:
47+
:member-order: bysource
48+
:members:
49+
:undoc-members:
50+
:special-members: __init__
51+
52+
.. automodule:: examples.shopstandard.domain
53+
:show-inheritance:
54+
:member-order: bysource
55+
:members:
56+
:undoc-members:
57+
:special-members: __init__
58+
59+
.. automodule:: examples.shopstandard.exceptions
60+
:show-inheritance:
61+
:member-order: bysource
62+
:members:
63+
:undoc-members:
64+
:special-members: __init__
65+

docs/topics/examples/shop-vertical.rst

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,84 @@ Integration test
105105

106106
.. literalinclude:: ../../../examples/shopvertical/test.py
107107
:pyobject: TestShop
108+
109+
Code reference
110+
--------------
111+
112+
.. automodule:: examples.shopvertical.slices.add_product_to_shop.cmd
113+
:show-inheritance:
114+
:member-order: bysource
115+
:members:
116+
:undoc-members:
117+
:special-members: __init__
118+
119+
.. automodule:: examples.shopvertical.slices.adjust_product_inventory.cmd
120+
:show-inheritance:
121+
:member-order: bysource
122+
:members:
123+
:undoc-members:
124+
:special-members: __init__
125+
126+
.. automodule:: examples.shopvertical.slices.list_products_in_shop.query
127+
:show-inheritance:
128+
:member-order: bysource
129+
:members:
130+
:undoc-members:
131+
:special-members: __init__
132+
133+
.. automodule:: examples.shopvertical.slices.get_cart_items.query
134+
:show-inheritance:
135+
:member-order: bysource
136+
:members:
137+
:undoc-members:
138+
:special-members: __init__
139+
140+
.. automodule:: examples.shopvertical.slices.add_item_to_cart.cmd
141+
:show-inheritance:
142+
:member-order: bysource
143+
:members:
144+
:undoc-members:
145+
:special-members: __init__
146+
147+
.. automodule:: examples.shopvertical.slices.remove_item_from_cart.cmd
148+
:show-inheritance:
149+
:member-order: bysource
150+
:members:
151+
:undoc-members:
152+
:special-members: __init__
153+
154+
.. automodule:: examples.shopvertical.slices.clear_cart.cmd
155+
:show-inheritance:
156+
:member-order: bysource
157+
:members:
158+
:undoc-members:
159+
:special-members: __init__
160+
161+
.. automodule:: examples.shopvertical.slices.submit_cart.cmd
162+
:show-inheritance:
163+
:member-order: bysource
164+
:members:
165+
:undoc-members:
166+
:special-members: __init__
167+
168+
.. automodule:: examples.shopvertical.events
169+
:show-inheritance:
170+
:member-order: bysource
171+
:members:
172+
:undoc-members:
173+
:special-members: __init__
174+
175+
.. automodule:: examples.shopvertical.exceptions
176+
:show-inheritance:
177+
:member-order: bysource
178+
:members:
179+
:undoc-members:
180+
:special-members: __init__
181+
182+
.. automodule:: examples.shopvertical.common
183+
:show-inheritance:
184+
:member-order: bysource
185+
:members:
186+
:undoc-members:
187+
:special-members: __init__
188+

examples/aggregate7/application.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING, Any, ClassVar
3+
from typing import TYPE_CHECKING, Any
44

5-
from eventsourcing.application import Application
6-
from eventsourcing.utils import get_topic
75
from examples.aggregate7.domainmodel import Trick, add_trick, project_dog, register_dog
86
from examples.aggregate7.immutablemodel import Snapshot
9-
from examples.aggregate7.orjsonpydantic import OrjsonTranscoder, PydanticMapper
7+
from examples.aggregate7.orjsonpydantic import PydanticApplication
108

119
if TYPE_CHECKING:
1210
from uuid import UUID
1311

1412

15-
class DogSchool(Application):
13+
class DogSchool(PydanticApplication):
1614
is_snapshotting_enabled = True
1715
snapshot_class = Snapshot
18-
env: ClassVar[dict[str, str]] = {
19-
"TRANSCODER_TOPIC": get_topic(OrjsonTranscoder),
20-
"MAPPER_TOPIC": get_topic(PydanticMapper),
21-
}
2216

2317
def register_dog(self, name: str) -> UUID:
2418
event = register_dog(name)

examples/aggregate7/orjsonpydantic.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING, Any, cast
3+
from typing import TYPE_CHECKING, Any, ClassVar, cast
44

55
import orjson
6+
from pydantic import BaseModel
67

8+
from eventsourcing.application import Application
79
from eventsourcing.persistence import Mapper, StoredEvent, Transcoder
810
from eventsourcing.utils import get_topic, resolve_topic
911

1012
if TYPE_CHECKING:
11-
from pydantic import BaseModel
12-
1313
from eventsourcing.domain import DomainEventProtocol
1414

1515

1616
class PydanticMapper(Mapper):
1717
def to_stored_event(self, domain_event: DomainEventProtocol) -> StoredEvent:
1818
topic = get_topic(domain_event.__class__)
19-
event_state = cast("BaseModel", domain_event).model_dump(mode="json")
19+
event_state = cast(BaseModel, domain_event).model_dump(mode="json")
2020
stored_state = self.transcoder.encode(event_state)
2121
if self.compressor:
2222
stored_state = self.compressor.compress(stored_state)
@@ -46,3 +46,10 @@ def encode(self, obj: Any) -> bytes:
4646

4747
def decode(self, data: bytes) -> Any:
4848
return orjson.loads(data)
49+
50+
51+
class PydanticApplication(Application):
52+
env: ClassVar[dict[str, str]] = {
53+
"TRANSCODER_TOPIC": get_topic(OrjsonTranscoder),
54+
"MAPPER_TOPIC": get_topic(PydanticMapper),
55+
}

examples/aggregate8/application.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING, Any, ClassVar
3+
from typing import TYPE_CHECKING, Any
44

5-
from eventsourcing.application import Application
6-
from eventsourcing.utils import get_topic
7-
from examples.aggregate7.orjsonpydantic import OrjsonTranscoder, PydanticMapper
5+
from examples.aggregate7.orjsonpydantic import PydanticApplication
86
from examples.aggregate8.domainmodel import Dog, Trick
97

108
if TYPE_CHECKING:
119
from uuid import UUID
1210

1311

14-
class DogSchool(Application):
12+
class DogSchool(PydanticApplication):
1513
is_snapshotting_enabled = True
16-
env: ClassVar[dict[str, str]] = {
17-
"TRANSCODER_TOPIC": get_topic(OrjsonTranscoder),
18-
"MAPPER_TOPIC": get_topic(PydanticMapper),
19-
}
2014

2115
def register_dog(self, name: str) -> UUID:
2216
dog = Dog(name)

0 commit comments

Comments
 (0)