python-event-sourcery 0.4.0a19__tar.gz → 0.4.1a0__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 (56) hide show
  1. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/PKG-INFO +1 -1
  2. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/backend.py +31 -28
  3. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/in_memory.py +3 -3
  4. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/interfaces.py +21 -38
  5. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/subscription.py +12 -15
  6. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/__init__.py +4 -4
  7. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_kurrentdb/__init__.py +4 -4
  8. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/__init__.py +12 -18
  9. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/event_store.py +1 -1
  10. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/pyproject.toml +1 -1
  11. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/LICENSE +0 -0
  12. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/__init__.py +0 -0
  13. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_sourcing/__init__.py +0 -0
  14. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_sourcing/aggregate.py +0 -0
  15. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_sourcing/repository.py +0 -0
  16. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/__init__.py +0 -0
  17. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/dispatcher.py +0 -0
  18. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/event/__init__.py +0 -0
  19. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/event/_dto.py +0 -0
  20. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/event/_encryption.py +0 -0
  21. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/event/_registry.py +0 -0
  22. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/event/_serde.py +0 -0
  23. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/event_store.py +0 -0
  24. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/exceptions.py +0 -0
  25. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/outbox.py +0 -0
  26. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/stream_id.py +0 -0
  27. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/tenant_id.py +0 -0
  28. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/event_store/versioning.py +0 -0
  29. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/py.typed +0 -0
  30. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/read_model/__init__.py +0 -0
  31. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/read_model/cursors_dao.py +0 -0
  32. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery/read_model/projector.py +0 -0
  33. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/dto.py +0 -0
  34. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/event_store.py +0 -0
  35. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/migrations/0001_initial.py +0 -0
  36. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/migrations/__init__.py +0 -0
  37. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/models.py +0 -0
  38. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/outbox.py +0 -0
  39. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/py.typed +0 -0
  40. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_django/subscription.py +0 -0
  41. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_kurrentdb/dto.py +0 -0
  42. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_kurrentdb/event_store.py +0 -0
  43. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_kurrentdb/outbox.py +0 -0
  44. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_kurrentdb/py.typed +0 -0
  45. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_kurrentdb/stream.py +0 -0
  46. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_kurrentdb/subscription.py +0 -0
  47. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/cursors_dao.py +0 -0
  48. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/dto.py +0 -0
  49. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/guid.py +0 -0
  50. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/jsonb.py +0 -0
  51. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/models/__init__.py +0 -0
  52. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/models/base.py +0 -0
  53. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/models/default.py +0 -0
  54. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/outbox.py +0 -0
  55. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/py.typed +0 -0
  56. {python_event_sourcery-0.4.0a19 → python_event_sourcery-0.4.1a0}/event_sourcery_sqlalchemy/subscription.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: python-event-sourcery
3
- Version: 0.4.0a19
3
+ Version: 0.4.1a0
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Your Name
@@ -1,9 +1,7 @@
1
- import abc
2
- from collections import UserDict
3
- from collections.abc import Iterator
1
+ from collections.abc import Callable, Iterator
4
2
  from contextlib import AbstractContextManager
5
3
  from functools import wraps
6
- from typing import NoReturn, Protocol, TypeVar, cast
4
+ from typing import NoReturn, TypeVar, cast
7
5
 
8
6
  from typing_extensions import Self
9
7
 
@@ -46,12 +44,10 @@ class NoOutboxStorageStrategy(OutboxStorageStrategy):
46
44
  return iter([])
47
45
 
48
46
 
49
- T_co = TypeVar("T_co", covariant=True)
50
47
  T = TypeVar("T")
48
+ T_co = TypeVar("T_co", covariant=True)
51
49
 
52
-
53
- class _Provider(Protocol[T_co]):
54
- def __call__(self, container: "_Container") -> T_co: ...
50
+ _Provider = Callable[["_Container"], T]
55
51
 
56
52
 
57
53
  def singleton(provider: _Provider[T]) -> _Provider[T]:
@@ -75,32 +71,39 @@ def not_configured(error_message: str) -> _Provider[T]:
75
71
  return _raise
76
72
 
77
73
 
78
- class _Container(UserDict[type[T], _Provider[T] | T]):
74
+ class _Container:
75
+ def __init__(self) -> None:
76
+ self.providers: dict[type, _Provider] = {}
77
+
79
78
  def __getitem__(self, _type: type[T]) -> T:
80
- provider = cast(_Provider[T], self.data[_type])
81
- return provider(self)
79
+ return cast(_Provider[T], self.providers[_type])(self)
82
80
 
83
81
  def __setitem__(self, _type: type[T], value: T | _Provider[T]) -> None:
84
- self.data[_type] = (
85
- cast(_Provider[T], lambda _: value) if isinstance(value, _type) else value
82
+ self.providers[_type] = (
83
+ cast(_Provider[T], lambda _: value)
84
+ if isinstance(value, _type)
85
+ else cast(_Provider[T], value)
86
86
  )
87
87
 
88
+ def get(self, _type: type[T], default: T | None = None) -> T | None:
89
+ if _type not in self.providers:
90
+ return default
91
+ return self[_type]
92
+
88
93
  def copy(self) -> Self:
89
94
  new: Self = self.__class__()
90
- new.data.update(self.data.copy())
95
+ new.providers.update(self.providers.copy())
91
96
  return new
92
97
 
93
98
 
94
99
  class Backend(_Container):
95
- tenant_id: TenantId
96
-
97
100
  def __init__(self) -> None:
98
101
  super().__init__()
99
- self.tenant_id = DEFAULT_TENANT
100
- self[EventRegistry] = lambda _: EventRegistry()
101
- self[EncryptionStrategy] = lambda _: NoEncryptionStrategy()
102
+ self[TenantId] = DEFAULT_TENANT
103
+ self[EventRegistry] = EventRegistry()
104
+ self[EncryptionStrategy] = NoEncryptionStrategy()
102
105
  self[EncryptionKeyStorageStrategy] = (
103
- lambda c: NoKeyStorageStrategy().scoped_for_tenant(c.tenant_id)
106
+ lambda c: NoKeyStorageStrategy().scoped_for_tenant(c[TenantId])
104
107
  )
105
108
  self[Encryption] = lambda c: Encryption(
106
109
  registry=c[EventRegistry],
@@ -133,23 +136,23 @@ class Backend(_Container):
133
136
 
134
137
  @property
135
138
  def event_store(self) -> EventStore:
136
- return cast(EventStore, self[EventStore])
139
+ return self[EventStore]
137
140
 
138
141
  @property
139
142
  def outbox(self) -> Outbox:
140
- return cast(Outbox, self[Outbox])
143
+ return self[Outbox]
141
144
 
142
145
  @property
143
146
  def subscriber(self) -> subscription.PositionPhase:
144
- return cast(subscription.PositionPhase, self[subscription.PositionPhase])
147
+ return self[subscription.PositionPhase]
145
148
 
146
149
  def in_tenant_mode(self, tenant_id: TenantId) -> Self:
147
150
  in_tenant_mode = self.copy()
148
- in_tenant_mode.tenant_id = tenant_id
151
+ in_tenant_mode[TenantId] = tenant_id
149
152
  return in_tenant_mode
150
153
 
151
- @abc.abstractmethod
152
- def with_outbox(self, filterer: OutboxFiltererStrategy = no_filter) -> Self: ...
154
+ def with_outbox(self, filterer: OutboxFiltererStrategy = no_filter) -> Self:
155
+ raise NotImplementedError()
153
156
 
154
157
  def with_encryption(
155
158
  self,
@@ -158,12 +161,12 @@ class Backend(_Container):
158
161
  ) -> Self:
159
162
  self[EncryptionStrategy] = strategy
160
163
  self[EncryptionKeyStorageStrategy] = lambda c: key_storage.scoped_for_tenant(
161
- c.tenant_id
164
+ c[TenantId],
162
165
  )
163
166
  return self
164
167
 
165
168
 
166
- class TransactionalBackend(Backend, abc.ABC):
169
+ class TransactionalBackend(Backend):
167
170
  def __init__(self) -> None:
168
171
  super().__init__()
169
172
  self[Listeners] = singleton(lambda _: Listeners())
@@ -310,7 +310,7 @@ class InMemoryBackend(TransactionalBackend):
310
310
  c[Storage],
311
311
  c[Dispatcher],
312
312
  outbox_strategy=c.get(InMemoryOutboxStorageStrategy),
313
- ).scoped_for_tenant(c.tenant_id)
313
+ ).scoped_for_tenant(c[TenantId])
314
314
  self[SubscriptionStrategy] = lambda c: InMemorySubscriptionStrategy(c[Storage])
315
315
 
316
316
  def configure(self, config: Config | None = None) -> Self:
@@ -318,10 +318,10 @@ class InMemoryBackend(TransactionalBackend):
318
318
  return self
319
319
 
320
320
  def with_outbox(self, filterer: OutboxFiltererStrategy = no_filter) -> Self:
321
- self[OutboxFiltererStrategy] = filterer
321
+ self[OutboxFiltererStrategy] = filterer # type: ignore[type-abstract]
322
322
  self[InMemoryOutboxStorageStrategy] = singleton(
323
323
  lambda c: InMemoryOutboxStorageStrategy(
324
- c[OutboxFiltererStrategy],
324
+ c[OutboxFiltererStrategy], # type: ignore[type-abstract]
325
325
  c[Config].outbox_attempts,
326
326
  )
327
327
  )
@@ -1,4 +1,3 @@
1
- import abc
2
1
  from collections.abc import Iterator
3
2
  from contextlib import AbstractContextManager
4
3
  from datetime import timedelta
@@ -17,25 +16,22 @@ class OutboxFiltererStrategy(Protocol):
17
16
  def __call__(self, entry: RawEvent) -> bool: ...
18
17
 
19
18
 
20
- class OutboxStorageStrategy(abc.ABC):
21
- @abc.abstractmethod
19
+ class OutboxStorageStrategy:
22
20
  def outbox_entries(
23
21
  self, limit: int
24
22
  ) -> Iterator[AbstractContextManager[RecordedRaw]]:
25
- pass
23
+ raise NotImplementedError()
26
24
 
27
25
 
28
- class SubscriptionStrategy(abc.ABC):
29
- @abc.abstractmethod
26
+ class SubscriptionStrategy:
30
27
  def subscribe_to_all(
31
28
  self,
32
29
  start_from: Position,
33
30
  batch_size: int,
34
31
  timelimit: timedelta,
35
32
  ) -> Iterator[list[RecordedRaw]]:
36
- pass
33
+ raise NotImplementedError()
37
34
 
38
- @abc.abstractmethod
39
35
  def subscribe_to_category(
40
36
  self,
41
37
  start_from: Position,
@@ -43,9 +39,8 @@ class SubscriptionStrategy(abc.ABC):
43
39
  timelimit: timedelta,
44
40
  category: str,
45
41
  ) -> Iterator[list[RecordedRaw]]:
46
- pass
42
+ raise NotImplementedError()
47
43
 
48
- @abc.abstractmethod
49
44
  def subscribe_to_events(
50
45
  self,
51
46
  start_from: Position,
@@ -53,66 +48,54 @@ class SubscriptionStrategy(abc.ABC):
53
48
  timelimit: timedelta,
54
49
  events: list[str],
55
50
  ) -> Iterator[list[RecordedRaw]]:
56
- pass
51
+ raise NotImplementedError()
57
52
 
58
53
 
59
- class StorageStrategy(abc.ABC):
60
- @abc.abstractmethod
54
+ class StorageStrategy:
61
55
  def fetch_events(
62
56
  self,
63
57
  stream_id: StreamId,
64
58
  start: int | None = None,
65
59
  stop: int | None = None,
66
60
  ) -> list[RawEvent]:
67
- pass
61
+ raise NotImplementedError()
68
62
 
69
- @abc.abstractmethod
70
63
  def insert_events(
71
64
  self, stream_id: StreamId, versioning: Versioning, events: list[RawEvent]
72
65
  ) -> None:
73
- pass
66
+ raise NotImplementedError()
74
67
 
75
- @abc.abstractmethod
76
68
  def save_snapshot(self, snapshot: RawEvent) -> None:
77
- pass
69
+ raise NotImplementedError()
78
70
 
79
- @abc.abstractmethod
80
71
  def delete_stream(self, stream_id: StreamId) -> None:
81
- pass
72
+ raise NotImplementedError()
82
73
 
83
74
  @property
84
- @abc.abstractmethod
85
75
  def current_position(self) -> Position | None:
86
- pass
76
+ raise NotImplementedError()
87
77
 
88
- @abc.abstractmethod
89
78
  def scoped_for_tenant(self, tenant_id: str) -> Self:
90
- pass
79
+ raise NotImplementedError()
91
80
 
92
81
 
93
- class EncryptionKeyStorageStrategy(abc.ABC):
94
- @abc.abstractmethod
82
+ class EncryptionKeyStorageStrategy:
95
83
  def get(self, subject_id: str) -> bytes | None:
96
- pass
84
+ raise NotImplementedError()
97
85
 
98
- @abc.abstractmethod
99
86
  def store(self, subject_id: str, key: bytes) -> None:
100
- pass
87
+ raise NotImplementedError()
101
88
 
102
- @abc.abstractmethod
103
89
  def delete(self, subject_id: str) -> None:
104
- pass
90
+ raise NotImplementedError()
105
91
 
106
- @abc.abstractmethod
107
92
  def scoped_for_tenant(self, tenant_id: TenantId) -> Self:
108
- pass
93
+ raise NotImplementedError()
109
94
 
110
95
 
111
- class EncryptionStrategy(abc.ABC):
112
- @abc.abstractmethod
96
+ class EncryptionStrategy:
113
97
  def encrypt(self, data: Any, key: bytes) -> str:
114
- pass
98
+ raise NotImplementedError()
115
99
 
116
- @abc.abstractmethod
117
100
  def decrypt(self, data: str, key: bytes) -> Any:
118
- pass
101
+ raise NotImplementedError()
@@ -1,4 +1,3 @@
1
- import abc
2
1
  import sys
3
2
  from collections.abc import Callable, Iterator
4
3
  from dataclasses import dataclass, field
@@ -19,31 +18,29 @@ from event_sourcery.event_store.stream_id import Category
19
18
  Seconds: TypeAlias = int | float
20
19
 
21
20
 
22
- class BuildPhase(abc.ABC):
23
- @abc.abstractmethod
24
- def build_iter(
25
- self, timelimit: Seconds | timedelta
26
- ) -> Iterator[Recorded | None]: ...
21
+ class BuildPhase:
22
+ def build_iter(self, timelimit: Seconds | timedelta) -> Iterator[Recorded | None]:
23
+ raise NotImplementedError()
27
24
 
28
- @abc.abstractmethod
29
25
  def build_batch(
30
26
  self,
31
27
  size: int,
32
28
  timelimit: Seconds | timedelta,
33
- ) -> Iterator[list[Recorded]]: ...
29
+ ) -> Iterator[list[Recorded]]:
30
+ raise NotImplementedError()
34
31
 
35
32
 
36
33
  class FilterPhase(BuildPhase):
37
- @abc.abstractmethod
38
- def to_category(self, category: Category) -> BuildPhase: ...
34
+ def to_category(self, category: Category) -> BuildPhase:
35
+ raise NotImplementedError()
39
36
 
40
- @abc.abstractmethod
41
- def to_events(self, events: list[type[Event]]) -> BuildPhase: ...
37
+ def to_events(self, events: list[type[Event]]) -> BuildPhase:
38
+ raise NotImplementedError()
42
39
 
43
40
 
44
- class PositionPhase(abc.ABC):
45
- @abc.abstractmethod
46
- def start_from(self, position: Position) -> FilterPhase: ...
41
+ class PositionPhase:
42
+ def start_from(self, position: Position) -> FilterPhase:
43
+ raise NotImplementedError()
47
44
 
48
45
 
49
46
  @dataclass(repr=False)
@@ -8,7 +8,7 @@ from datetime import timedelta
8
8
  from pydantic import BaseModel, ConfigDict, PositiveInt
9
9
  from typing_extensions import Self
10
10
 
11
- from event_sourcery.event_store import Dispatcher
11
+ from event_sourcery.event_store import Dispatcher, TenantId
12
12
  from event_sourcery.event_store.backend import (
13
13
  TransactionalBackend,
14
14
  no_filter,
@@ -40,7 +40,7 @@ class DjangoBackend(TransactionalBackend):
40
40
  self[StorageStrategy] = lambda c: DjangoStorageStrategy(
41
41
  c[Dispatcher],
42
42
  c.get(DjangoOutboxStorageStrategy, None),
43
- ).scoped_for_tenant(c.tenant_id)
43
+ ).scoped_for_tenant(c[TenantId])
44
44
  self[SubscriptionStrategy] = lambda c: DjangoSubscriptionStrategy(
45
45
  gap_retry_interval=c[Config].gap_retry_interval
46
46
  )
@@ -52,9 +52,9 @@ class DjangoBackend(TransactionalBackend):
52
52
  def with_outbox(self, filterer: OutboxFiltererStrategy = no_filter) -> Self:
53
53
  from event_sourcery_django.outbox import DjangoOutboxStorageStrategy
54
54
 
55
- self[OutboxFiltererStrategy] = filterer
55
+ self[OutboxFiltererStrategy] = filterer # type: ignore[type-abstract]
56
56
  self[DjangoOutboxStorageStrategy] = lambda c: DjangoOutboxStorageStrategy(
57
- c[OutboxFiltererStrategy],
57
+ c[OutboxFiltererStrategy], # type: ignore[type-abstract]
58
58
  c[Config].outbox_attempts,
59
59
  )
60
60
  self[OutboxStorageStrategy] = lambda c: c[DjangoOutboxStorageStrategy]
@@ -10,7 +10,7 @@ from kurrentdbclient import KurrentDBClient
10
10
  from pydantic import BaseModel, ConfigDict, PositiveFloat, PositiveInt
11
11
  from typing_extensions import Self
12
12
 
13
- from event_sourcery.event_store import Backend
13
+ from event_sourcery.event_store import Backend, TenantId
14
14
  from event_sourcery.event_store.backend import no_filter, not_configured
15
15
  from event_sourcery.event_store.interfaces import (
16
16
  OutboxFiltererStrategy,
@@ -45,7 +45,7 @@ class KurrentDBBackend(Backend):
45
45
  self[StorageStrategy] = lambda c: KurrentDBStorageStrategy(
46
46
  c[KurrentDBClient],
47
47
  c[Config].timeout,
48
- ).scoped_for_tenant(c.tenant_id)
48
+ ).scoped_for_tenant(c[TenantId])
49
49
  self[SubscriptionStrategy] = lambda c: KurrentDBSubscriptionStrategy(
50
50
  c[KurrentDBClient],
51
51
  )
@@ -56,10 +56,10 @@ class KurrentDBBackend(Backend):
56
56
  return self
57
57
 
58
58
  def with_outbox(self, filterer: OutboxFiltererStrategy = no_filter) -> Self:
59
- self[OutboxFiltererStrategy] = filterer
59
+ self[OutboxFiltererStrategy] = filterer # type: ignore[type-abstract]
60
60
  self[KurrentDBOutboxStorageStrategy] = lambda c: KurrentDBOutboxStorageStrategy(
61
61
  c[KurrentDBClient],
62
- c[OutboxFiltererStrategy],
62
+ c[OutboxFiltererStrategy], # type: ignore[type-abstract]
63
63
  c[Config].outbox_name,
64
64
  c[Config].outbox_attempts,
65
65
  c[Config].timeout,
@@ -19,7 +19,7 @@ from pydantic import BaseModel, ConfigDict, PositiveInt
19
19
  from sqlalchemy.orm import Session
20
20
  from typing_extensions import Self
21
21
 
22
- from event_sourcery.event_store import Dispatcher, TransactionalBackend
22
+ from event_sourcery.event_store import Dispatcher, TenantId, TransactionalBackend
23
23
  from event_sourcery.event_store.backend import no_filter, not_configured
24
24
  from event_sourcery.event_store.interfaces import (
25
25
  OutboxFiltererStrategy,
@@ -67,25 +67,22 @@ class SQLAlchemyBackend(TransactionalBackend):
67
67
 
68
68
  def __init__(self) -> None:
69
69
  super().__init__()
70
- self[BaseEvent] = not_configured(self.UNCONFIGURED_MESSAGE)
71
- self[BaseStream] = not_configured(self.UNCONFIGURED_MESSAGE)
72
- self[BaseSnapshot] = not_configured(self.UNCONFIGURED_MESSAGE)
73
- self[BaseOutboxEntry] = not_configured(self.UNCONFIGURED_MESSAGE)
70
+ self[Models] = not_configured(self.UNCONFIGURED_MESSAGE)
74
71
  self[Session] = not_configured(self.UNCONFIGURED_MESSAGE)
75
72
  self[Config] = not_configured(self.UNCONFIGURED_MESSAGE)
76
73
  self[StorageStrategy] = lambda c: SqlAlchemyStorageStrategy(
77
74
  c[Session],
78
75
  c[Dispatcher],
79
76
  c.get(SqlAlchemyOutboxStorageStrategy, None),
80
- c[BaseEvent],
81
- c[BaseSnapshot],
82
- c[BaseStream],
83
- ).scoped_for_tenant(c.tenant_id)
77
+ c[Models].event_model,
78
+ c[Models].snapshot_model,
79
+ c[Models].stream_model,
80
+ ).scoped_for_tenant(c[TenantId])
84
81
  self[SubscriptionStrategy] = lambda c: SqlAlchemySubscriptionStrategy(
85
82
  c[Session],
86
83
  c[Config].gap_retry_interval,
87
- c[BaseEvent],
88
- c[BaseStream],
84
+ c[Models].event_model,
85
+ c[Models].stream_model,
89
86
  )
90
87
 
91
88
  def configure(
@@ -104,20 +101,17 @@ class SQLAlchemyBackend(TransactionalBackend):
104
101
 
105
102
  self[Session] = session
106
103
  self[Config] = config or Config()
107
- self[BaseEvent] = lambda _: custom_models.event_model
108
- self[BaseStream] = lambda _: custom_models.stream_model
109
- self[BaseSnapshot] = lambda _: custom_models.snapshot_model
110
- self[BaseOutboxEntry] = lambda _: custom_models.outbox_entry_model
104
+ self[Models] = custom_models
111
105
  return self
112
106
 
113
107
  def with_outbox(self, filterer: OutboxFiltererStrategy = no_filter) -> Self:
114
- self[OutboxFiltererStrategy] = filterer
108
+ self[OutboxFiltererStrategy] = filterer # type: ignore[type-abstract]
115
109
  self[SqlAlchemyOutboxStorageStrategy] = (
116
110
  lambda c: SqlAlchemyOutboxStorageStrategy(
117
111
  c[Session],
118
- c[OutboxFiltererStrategy],
112
+ c[OutboxFiltererStrategy], # type: ignore[type-abstract]
119
113
  c[Config].outbox_attempts,
120
- c[BaseOutboxEntry],
114
+ c[Models].outbox_entry_model,
121
115
  )
122
116
  )
123
117
  self[OutboxStorageStrategy] = lambda c: c[SqlAlchemyOutboxStorageStrategy]
@@ -32,7 +32,7 @@ from event_sourcery_sqlalchemy.outbox import SqlAlchemyOutboxStorageStrategy
32
32
  class SqlAlchemyStorageStrategy(StorageStrategy):
33
33
  _session: Session
34
34
  _dispatcher: Dispatcher
35
- _outbox: SqlAlchemyOutboxStorageStrategy
35
+ _outbox: SqlAlchemyOutboxStorageStrategy | None
36
36
  _event_model: type[BaseEvent]
37
37
  _snapshot_model: type[BaseSnapshot]
38
38
  _stream_model: type[BaseStream]
@@ -3,7 +3,7 @@ name = "python-event-sourcery"
3
3
  requires-python = ">=3.10"
4
4
 
5
5
  [tool.poetry]
6
- version = "0.4.0a19"
6
+ version = "0.4.1a0"
7
7
  description = ""
8
8
  authors = ["Your Name <you@example.com>"]
9
9
  license = "MIT"