python-event-sourcery 0.4.0a10__tar.gz → 0.4.0a13__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.
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/PKG-INFO +4 -3
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/__init__.py +2 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/event/dto.py +16 -8
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/event/serde.py +6 -2
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/dto.py +11 -6
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/outbox.py +7 -4
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/pyproject.toml +2 -2
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/LICENSE +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/__init__.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/aggregate/__init__.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/aggregate/aggregate.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/aggregate/repository.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/dispatcher.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/event/__init__.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/event/registry.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/event_store.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/exceptions.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/factory.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/in_memory.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/interfaces.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/outbox.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/stream_id.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/subscription.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/tenant_id.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/event_store/versioning.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/py.typed +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/read_model/__init__.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/read_model/cursors_dao.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/read_model/projector.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/__init__.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/event_store.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/outbox.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/py.typed +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/stream.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/subscription.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/__init__.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/cursors_dao.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/dto.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/event_store.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/guid.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/jsonb.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/models.py +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/py.typed +0 -0
- {python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/subscription.py +0 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: python-event-sourcery
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.0a13
|
|
4
4
|
Summary:
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Your Name
|
|
7
7
|
Author-email: you@example.com
|
|
8
|
-
Requires-Python: >=3.10
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
15
|
Provides-Extra: django
|
|
15
16
|
Provides-Extra: esdb
|
|
16
17
|
Provides-Extra: sqlalchemy
|
|
@@ -4,6 +4,7 @@ __all__ = [
|
|
|
4
4
|
"Dispatcher",
|
|
5
5
|
"Entry",
|
|
6
6
|
"Event",
|
|
7
|
+
"Context",
|
|
7
8
|
"EventRegistry",
|
|
8
9
|
"EventStore",
|
|
9
10
|
"ExplicitVersioning",
|
|
@@ -29,6 +30,7 @@ __all__ = [
|
|
|
29
30
|
from event_sourcery.event_store import exceptions, factory, interfaces, subscription
|
|
30
31
|
from event_sourcery.event_store.dispatcher import Dispatcher, Listener
|
|
31
32
|
from event_sourcery.event_store.event import (
|
|
33
|
+
Context,
|
|
32
34
|
Entry,
|
|
33
35
|
Event,
|
|
34
36
|
EventRegistry,
|
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
import dataclasses
|
|
2
|
+
from datetime import datetime, timezone
|
|
2
3
|
from typing import Any, ClassVar, Generic, TypeAlias, TypeVar
|
|
3
4
|
from uuid import UUID, uuid4
|
|
4
5
|
|
|
5
|
-
from pydantic import BaseModel
|
|
6
|
+
from pydantic import BaseModel
|
|
6
7
|
|
|
7
8
|
from event_sourcery.event_store.event.registry import EventRegistry
|
|
8
9
|
from event_sourcery.event_store.stream_id import StreamId
|
|
9
10
|
from event_sourcery.event_store.tenant_id import DEFAULT_TENANT, TenantId
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
@dataclasses.dataclass(frozen=True)
|
|
12
14
|
class RawEvent(BaseModel):
|
|
13
15
|
uuid: UUID
|
|
14
16
|
stream_id: StreamId
|
|
15
17
|
created_at: datetime
|
|
16
|
-
version: int | None = None
|
|
17
18
|
name: str
|
|
18
19
|
data: dict
|
|
19
20
|
context: dict
|
|
21
|
+
version: int | None = None
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
Position: TypeAlias = int
|
|
23
25
|
|
|
24
26
|
|
|
27
|
+
@dataclasses.dataclass(frozen=True)
|
|
25
28
|
class RecordedRaw(BaseModel):
|
|
26
29
|
entry: RawEvent
|
|
27
30
|
position: Position
|
|
@@ -52,7 +55,8 @@ class Context(BaseModel, extra="allow"):
|
|
|
52
55
|
causation_id: UUID | None = None
|
|
53
56
|
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
@dataclasses.dataclass()
|
|
59
|
+
class WrappedEvent(Generic[TEvent]):
|
|
56
60
|
"""Wrapper for events with all relevant metadata.
|
|
57
61
|
|
|
58
62
|
Returned from EventStore when loading events from a stream.
|
|
@@ -69,20 +73,24 @@ class WrappedEvent(BaseModel, Generic[TEvent], extra="forbid"):
|
|
|
69
73
|
|
|
70
74
|
event: TEvent
|
|
71
75
|
version: int | None
|
|
72
|
-
uuid: UUID =
|
|
73
|
-
created_at: datetime =
|
|
74
|
-
|
|
76
|
+
uuid: UUID = dataclasses.field(default_factory=uuid4)
|
|
77
|
+
created_at: datetime = dataclasses.field(
|
|
78
|
+
default_factory=lambda: datetime.now(timezone.utc).replace(tzinfo=None)
|
|
79
|
+
)
|
|
80
|
+
context: Context = dataclasses.field(default_factory=Context)
|
|
75
81
|
|
|
76
82
|
@classmethod
|
|
77
83
|
def wrap(cls, event: TEvent, version: int | None) -> "WrappedEvent[TEvent]":
|
|
78
84
|
return WrappedEvent[TEvent](event=event, version=version)
|
|
79
85
|
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
@dataclasses.dataclass(frozen=True)
|
|
88
|
+
class Entry:
|
|
82
89
|
wrapped_event: WrappedEvent
|
|
83
90
|
stream_id: StreamId
|
|
84
91
|
|
|
85
92
|
|
|
93
|
+
@dataclasses.dataclass(frozen=True)
|
|
86
94
|
class Recorded(Entry):
|
|
87
95
|
position: Position
|
|
88
96
|
tenant_id: TenantId = DEFAULT_TENANT
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import dataclasses
|
|
1
2
|
from collections.abc import Mapping, Sequence
|
|
2
3
|
from dataclasses import dataclass
|
|
3
4
|
from typing import cast
|
|
4
5
|
|
|
5
6
|
from event_sourcery.event_store.event.dto import (
|
|
7
|
+
Context,
|
|
6
8
|
Event,
|
|
7
9
|
RawEvent,
|
|
8
10
|
Recorded,
|
|
@@ -18,12 +20,14 @@ class Serde:
|
|
|
18
20
|
registry: EventRegistry
|
|
19
21
|
|
|
20
22
|
def deserialize(self, event: RawEvent) -> WrappedEvent:
|
|
21
|
-
event_as_dict =
|
|
23
|
+
event_as_dict = dataclasses.asdict(event)
|
|
22
24
|
del event_as_dict["stream_id"]
|
|
23
25
|
del event_as_dict["name"]
|
|
24
26
|
data = cast(Mapping, event_as_dict.pop("data"))
|
|
27
|
+
context = event_as_dict.pop("context", {})
|
|
28
|
+
event_as_dict["context"] = Context(**context)
|
|
25
29
|
event_type = self.registry.type_for_name(event.name)
|
|
26
|
-
return WrappedEvent[event_type]( # type: ignore
|
|
30
|
+
return WrappedEvent[event_type]( # type: ignore[valid-type]
|
|
27
31
|
**event_as_dict,
|
|
28
32
|
event=event_type(**data),
|
|
29
33
|
)
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/dto.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from datetime import datetime
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Any, Literal, cast
|
|
4
4
|
|
|
5
5
|
from esdbclient import NewEvent, RecordedEvent
|
|
6
6
|
|
|
@@ -10,15 +10,22 @@ from event_sourcery_esdb import stream
|
|
|
10
10
|
ES_PREFIX = "$es-"
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def raw_event(
|
|
13
|
+
def raw_event(
|
|
14
|
+
from_entry: RecordedEvent, version: int | Literal["undefined"] = "undefined"
|
|
15
|
+
) -> RawEvent:
|
|
14
16
|
metadata = json.loads(from_entry.metadata.decode("utf-8"))
|
|
15
17
|
created_at = datetime.fromisoformat(metadata.pop("created_at"))
|
|
16
18
|
position = stream.Position(from_entry.stream_position)
|
|
19
|
+
if version == "undefined":
|
|
20
|
+
version = position.as_version()
|
|
21
|
+
|
|
22
|
+
version = cast(int, version)
|
|
23
|
+
|
|
17
24
|
return RawEvent(
|
|
18
25
|
uuid=from_entry.id,
|
|
19
26
|
stream_id=stream.Name.from_stream_name(from_entry.stream_name).uuid,
|
|
20
27
|
created_at=created_at,
|
|
21
|
-
version=
|
|
28
|
+
version=version,
|
|
22
29
|
name=from_entry.type,
|
|
23
30
|
data=json.loads(from_entry.data.decode("utf-8")),
|
|
24
31
|
context={k: v for k, v in metadata.items() if not k.startswith(ES_PREFIX)},
|
|
@@ -28,9 +35,7 @@ def raw_event(from_entry: RecordedEvent) -> RawEvent:
|
|
|
28
35
|
def snapshot(from_entry: RecordedEvent) -> RawEvent:
|
|
29
36
|
metadata = json.loads(from_entry.metadata.decode("utf-8"))
|
|
30
37
|
position = metadata[f"{ES_PREFIX}stream_position"]
|
|
31
|
-
|
|
32
|
-
event.version = stream.Position(position).as_version()
|
|
33
|
-
return event
|
|
38
|
+
return raw_event(from_entry, version=stream.Position(position).as_version())
|
|
34
39
|
|
|
35
40
|
|
|
36
41
|
def new_entry(from_raw: RawEvent, **metadata: Any) -> NewEvent:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import dataclasses
|
|
1
2
|
import logging
|
|
2
3
|
from collections.abc import Generator, Iterator
|
|
3
4
|
from contextlib import AbstractContextManager, contextmanager
|
|
4
5
|
from dataclasses import dataclass
|
|
5
|
-
from datetime import datetime
|
|
6
|
+
from datetime import datetime, timezone
|
|
6
7
|
from typing import cast
|
|
7
8
|
from uuid import UUID
|
|
8
9
|
|
|
@@ -31,15 +32,17 @@ class SqlAlchemyOutboxStorageStrategy(OutboxStorageStrategy):
|
|
|
31
32
|
if not self._filterer(record.entry):
|
|
32
33
|
continue
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
stream_id = record.entry.stream_id
|
|
36
|
+
as_dict = dataclasses.asdict(record.entry)
|
|
37
|
+
as_dict.pop("stream_id")
|
|
35
38
|
created_at = cast(datetime, as_dict["created_at"])
|
|
36
39
|
as_dict["created_at"] = created_at.isoformat()
|
|
37
40
|
as_dict["uuid"] = str(as_dict["uuid"])
|
|
38
|
-
as_dict["stream_id"] = str(
|
|
41
|
+
as_dict["stream_id"] = str(stream_id)
|
|
39
42
|
as_dict["tenant_id"] = str(record.tenant_id)
|
|
40
43
|
rows.append(
|
|
41
44
|
{
|
|
42
|
-
"created_at": datetime.
|
|
45
|
+
"created_at": datetime.now(timezone.utc).replace(tzinfo=None),
|
|
43
46
|
"data": as_dict,
|
|
44
47
|
"stream_name": record.entry.stream_id.name,
|
|
45
48
|
"position": record.position,
|
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/__init__.py
RENAMED
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/event_store.py
RENAMED
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/outbox.py
RENAMED
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/py.typed
RENAMED
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_esdb/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/dto.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/guid.py
RENAMED
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/jsonb.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_event_sourcery-0.4.0a10 → python_event_sourcery-0.4.0a13}/event_sourcery_sqlalchemy/py.typed
RENAMED
|
File without changes
|
|
File without changes
|