eventsourcing 9.4.0a3__py3-none-any.whl → 9.4.0a4__py3-none-any.whl

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.

@@ -486,7 +486,9 @@ class ApplicationRecorder(AggregateRecorder):
486
486
  """
487
487
 
488
488
  @abstractmethod
489
- def subscribe(self, gt: int | None = None) -> Subscription[ApplicationRecorder]:
489
+ def subscribe(
490
+ self, gt: int | None = None, topics: Sequence[str] = ()
491
+ ) -> Subscription[ApplicationRecorder]:
490
492
  """
491
493
  Returns an iterator of Notification objects representing events from an
492
494
  application sequence.
@@ -1311,10 +1313,14 @@ TApplicationRecorder_co = TypeVar(
1311
1313
 
1312
1314
  class Subscription(Iterator[Notification], Generic[TApplicationRecorder_co]):
1313
1315
  def __init__(
1314
- self, recorder: TApplicationRecorder_co, gt: int | None = None
1316
+ self,
1317
+ recorder: TApplicationRecorder_co,
1318
+ gt: int | None = None,
1319
+ topics: Sequence[str] = (),
1315
1320
  ) -> None:
1316
1321
  self._recorder = recorder
1317
1322
  self._last_notification_id = gt
1323
+ self._topics = topics
1318
1324
  self._has_been_entered = False
1319
1325
  self._has_been_stopped = False
1320
1326
 
@@ -1349,9 +1355,12 @@ class Subscription(Iterator[Notification], Generic[TApplicationRecorder_co]):
1349
1355
 
1350
1356
  class ListenNotifySubscription(Subscription[TApplicationRecorder_co]):
1351
1357
  def __init__(
1352
- self, recorder: TApplicationRecorder_co, gt: int | None = None
1358
+ self,
1359
+ recorder: TApplicationRecorder_co,
1360
+ gt: int | None = None,
1361
+ topics: Sequence[str] = (),
1353
1362
  ) -> None:
1354
- super().__init__(recorder=recorder, gt=gt)
1363
+ super().__init__(recorder=recorder, gt=gt, topics=topics)
1355
1364
  self._select_limit = 500
1356
1365
  self._notifications: List[Notification] = []
1357
1366
  self._notifications_index: int = 0
@@ -1410,6 +1419,7 @@ class ListenNotifySubscription(Subscription[TApplicationRecorder_co]):
1410
1419
  notifications = self._recorder.select_notifications(
1411
1420
  start=self._last_notification_id or 0,
1412
1421
  limit=self._select_limit,
1422
+ topics=self._topics,
1413
1423
  inclusive_of_start=False,
1414
1424
  )
1415
1425
  if len(notifications) > 0:
eventsourcing/popo.py CHANGED
@@ -14,6 +14,7 @@ from eventsourcing.persistence import (
14
14
  Notification,
15
15
  ProcessRecorder,
16
16
  StoredEvent,
17
+ Subscription,
17
18
  Tracking,
18
19
  TrackingRecorder,
19
20
  )
@@ -155,8 +156,10 @@ class POPOApplicationRecorder(POPOAggregateRecorder, ApplicationRecorder):
155
156
  with self._database_lock:
156
157
  return len(self._stored_events) or None
157
158
 
158
- def subscribe(self, gt: int | None = None) -> POPOSubscription:
159
- return POPOSubscription(self, gt)
159
+ def subscribe(
160
+ self, gt: int | None = None, topics: Sequence[str] = ()
161
+ ) -> Subscription[ApplicationRecorder]:
162
+ return POPOSubscription(recorder=self, gt=gt, topics=topics)
160
163
 
161
164
  def listen(self, event: Event) -> None:
162
165
  self._listeners.add(event)
@@ -172,10 +175,13 @@ class POPOApplicationRecorder(POPOAggregateRecorder, ApplicationRecorder):
172
175
 
173
176
  class POPOSubscription(ListenNotifySubscription[POPOApplicationRecorder]):
174
177
  def __init__(
175
- self, recorder: POPOApplicationRecorder, gt: int | None = None
178
+ self,
179
+ recorder: POPOApplicationRecorder,
180
+ gt: int | None = None,
181
+ topics: Sequence[str] = (),
176
182
  ) -> None:
177
183
  assert isinstance(recorder, POPOApplicationRecorder)
178
- super().__init__(recorder=recorder, gt=gt)
184
+ super().__init__(recorder=recorder, gt=gt, topics=topics)
179
185
  self._recorder.listen(self._has_been_notified)
180
186
 
181
187
  def stop(self) -> None:
eventsourcing/postgres.py CHANGED
@@ -30,6 +30,7 @@ from eventsourcing.persistence import (
30
30
  ProcessRecorder,
31
31
  ProgrammingError,
32
32
  StoredEvent,
33
+ Subscription,
33
34
  Tracking,
34
35
  TrackingRecorder,
35
36
  )
@@ -524,16 +525,21 @@ class PostgresApplicationRecorder(PostgresAggregateRecorder, ApplicationRecorder
524
525
  raise ProgrammingError(msg)
525
526
  return notification_ids
526
527
 
527
- def subscribe(self, gt: int | None = None) -> PostgresSubscription:
528
- return PostgresSubscription(self, gt)
528
+ def subscribe(
529
+ self, gt: int | None = None, topics: Sequence[str] = ()
530
+ ) -> Subscription[ApplicationRecorder]:
531
+ return PostgresSubscription(recorder=self, gt=gt, topics=topics)
529
532
 
530
533
 
531
534
  class PostgresSubscription(ListenNotifySubscription[PostgresApplicationRecorder]):
532
535
  def __init__(
533
- self, recorder: PostgresApplicationRecorder, gt: int | None = None
536
+ self,
537
+ recorder: PostgresApplicationRecorder,
538
+ gt: int | None = None,
539
+ topics: Sequence[str] = (),
534
540
  ) -> None:
535
541
  assert isinstance(recorder, PostgresApplicationRecorder)
536
- super().__init__(recorder=recorder, gt=gt)
542
+ super().__init__(recorder=recorder, gt=gt, topics=topics)
537
543
  self._listen_thread = Thread(target=self._listen)
538
544
  self._listen_thread.start()
539
545
 
@@ -5,7 +5,17 @@ import weakref
5
5
  from abc import ABC, abstractmethod
6
6
  from threading import Event, Thread
7
7
  from traceback import format_exc
8
- from typing import TYPE_CHECKING, Any, Dict, Generic, Iterator, Tuple, Type, TypeVar
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Any,
11
+ Dict,
12
+ Generic,
13
+ Iterator,
14
+ Sequence,
15
+ Tuple,
16
+ Type,
17
+ TypeVar,
18
+ )
9
19
  from warnings import warn
10
20
 
11
21
  from eventsourcing.application import Application
@@ -37,11 +47,12 @@ class ApplicationSubscription(Iterator[Tuple[DomainEventProtocol, Tracking]]):
37
47
  self,
38
48
  app: Application,
39
49
  gt: int | None = None,
50
+ topics: Sequence[str] = (),
40
51
  ):
41
52
  self.name = app.name
42
53
  self.recorder = app.recorder
43
54
  self.mapper = app.mapper
44
- self.subscription = self.recorder.subscribe(gt=gt)
55
+ self.subscription = self.recorder.subscribe(gt=gt, topics=topics)
45
56
 
46
57
  def __enter__(self) -> Self:
47
58
  self.subscription.__enter__()
@@ -68,6 +79,9 @@ class ApplicationSubscription(Iterator[Tuple[DomainEventProtocol, Tracking]]):
68
79
 
69
80
  class Projection(ABC, Generic[TTrackingRecorder]):
70
81
  name: str = ""
82
+ """Name of projection, used to pick prefixed environment variables."""
83
+ topics: Sequence[str] = ()
84
+ """Event topics, used to filter events in database."""
71
85
 
72
86
  def __init__(
73
87
  self,
@@ -112,12 +126,13 @@ class ProjectionRunner(Generic[TApplication, TTrackingRecorder]):
112
126
  self.projection_factory.tracking_recorder(tracking_recorder_class)
113
127
  )
114
128
 
129
+ self.projection = projection_class(
130
+ tracking_recorder=self.tracking_recorder,
131
+ )
115
132
  self.subscription = ApplicationSubscription(
116
133
  app=self.app,
117
134
  gt=self.tracking_recorder.max_tracking_id(self.app.name),
118
- )
119
- self.projection = projection_class(
120
- tracking_recorder=self.tracking_recorder,
135
+ topics=self.projection.topics,
121
136
  )
122
137
  self._has_error = Event()
123
138
  self.thread_error: BaseException | None = None
eventsourcing/sqlite.py CHANGED
@@ -471,7 +471,9 @@ class SQLiteApplicationRecorder(
471
471
  c.execute(self.select_max_notification_id_statement)
472
472
  return c.fetchone()[0]
473
473
 
474
- def subscribe(self, gt: int | None = None) -> Subscription[ApplicationRecorder]:
474
+ def subscribe(
475
+ self, gt: int | None = None, topics: Sequence[str] = ()
476
+ ) -> Subscription[ApplicationRecorder]:
475
477
  msg = f"The {type(self).__qualname__} recorder does not support subscriptions"
476
478
  raise NotImplementedError(msg)
477
479
 
@@ -734,6 +734,18 @@ class ApplicationRecorderTestCase(TestCase, ABC):
734
734
  # Shouldn't get here...
735
735
  self.fail("Got here")
736
736
 
737
+ # Start a subscription with topics.
738
+ subscription = recorder.subscribe(gt=None, topics=["topic3"])
739
+ with subscription:
740
+ for notification in subscription:
741
+ self.assertEqual(notification.topic, "topic3")
742
+ if (
743
+ notification.originator_id == stored_event3.originator_id
744
+ and notification.originator_version
745
+ == stored_event3.originator_version
746
+ ):
747
+ break
748
+
737
749
  def close_db_connection(self, *args: Any) -> None:
738
750
  """"""
739
751
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eventsourcing
3
- Version: 9.4.0a3
3
+ Version: 9.4.0a4
4
4
  Summary: Event sourcing in Python
5
5
  Home-page: https://github.com/pyeventsourcing/eventsourcing
6
6
  License: BSD 3-Clause
@@ -6,21 +6,21 @@ eventsourcing/cryptography.py,sha256=ZsQFyeyMZysADqKy38ECV71j6EMMSbo3VQO7oRnC1h0
6
6
  eventsourcing/dispatch.py,sha256=yYSpT-jqc6l_wTdqEnfPJJfvsZN2Ta8g2anrVPWIcqQ,1412
7
7
  eventsourcing/domain.py,sha256=pNetJA4uKf1chgfNFKWv1Fke3_V5g0ygRv63WT7nsUc,58208
8
8
  eventsourcing/interface.py,sha256=LIFI9AZhoVWUAq4YjKosGCpinf51jmVLqw1Ii4npSHo,5079
9
- eventsourcing/persistence.py,sha256=h5laiUP4mc6Ur1PoDnNBLXRcl8V-2-ife_hYktlCmmM,45732
10
- eventsourcing/popo.py,sha256=4q4-l8iuEueqvYzGMzyFEiZaT8dm_PJNosmGwzRt1oo,9393
11
- eventsourcing/postgres.py,sha256=h4ETgjzZtj9a-otJkMfzHZSxD_hOUWyVTIVuESVI7y0,36138
12
- eventsourcing/projection.py,sha256=6UNNF_iVYR3nmOfoysgvhtjwYnEBTvsHkQM2gzXPTbQ,6489
9
+ eventsourcing/persistence.py,sha256=sfGq8BV1cnmrTy1OLoWXIObArgUD9wPHcEeM0KwZ5p8,45962
10
+ eventsourcing/popo.py,sha256=wBXoSVg53nVOsZVzKkrCOrXxzWe2HH1mC4aEV97rDdk,9565
11
+ eventsourcing/postgres.py,sha256=wu5b3Kvr4NO9yegCLAkIMDrjpkTVNisCXlFmCb74tAE,36306
12
+ eventsourcing/projection.py,sha256=xkMsl_VTfxtb4SOH3NwHjPRUN1L0ShFMdlp8pUEkjwE,6799
13
13
  eventsourcing/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- eventsourcing/sqlite.py,sha256=3bezfl3H9I366NnIwLpn4cz_L3fk0pHNiOSO_Hrq6Xw,21909
14
+ eventsourcing/sqlite.py,sha256=_zY-08IosW1idOnPPRg9rh0C3AyHT6yqwAv4WCOw-dg,21951
15
15
  eventsourcing/system.py,sha256=7cM3FBdvr64ZK_xItks1MW2yg1o0OZ1vtKtznFFB_4g,47114
16
16
  eventsourcing/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  eventsourcing/tests/application.py,sha256=Q_NFgRSRWovMcyQOZ8U1AoiIsnEHf_zCpHcP0ADaYvs,17369
18
18
  eventsourcing/tests/domain.py,sha256=lHSlY6jIoSeqlcPSbrrozEPUJGvJ8bgPrznlmzTxn2w,3254
19
- eventsourcing/tests/persistence.py,sha256=5y2675k-e-A3JjPVw4EVNSF-Oem96CVWMOMft_1NK-c,56601
19
+ eventsourcing/tests/persistence.py,sha256=M1EZPs8DhAOW8N_GSnALPcmz-pNVCJDx73pHaEJa138,57108
20
20
  eventsourcing/tests/postgres_utils.py,sha256=xymcGYasUXeZTBenkHz-ykD8HtrFjVM1Z7-qRrH6OQk,1364
21
21
  eventsourcing/utils.py,sha256=QPlHhltgEcL80RWcPJ_PTygzDwhfIowUS3Z5taw0_cA,8228
22
- eventsourcing-9.4.0a3.dist-info/AUTHORS,sha256=8aHOM4UbNZcKlD-cHpFRcM6RWyCqtwtxRev6DeUgVRs,137
23
- eventsourcing-9.4.0a3.dist-info/LICENSE,sha256=CQEQzcZO8AWXL5i3hIo4yVKrYjh2FBz6hCM7kpXWpw4,1512
24
- eventsourcing-9.4.0a3.dist-info/METADATA,sha256=a4kiNuw1ATJbhUMa-UbYnd5lDI6IH_qBtKuhCeAM7E0,9885
25
- eventsourcing-9.4.0a3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
26
- eventsourcing-9.4.0a3.dist-info/RECORD,,
22
+ eventsourcing-9.4.0a4.dist-info/AUTHORS,sha256=8aHOM4UbNZcKlD-cHpFRcM6RWyCqtwtxRev6DeUgVRs,137
23
+ eventsourcing-9.4.0a4.dist-info/LICENSE,sha256=CQEQzcZO8AWXL5i3hIo4yVKrYjh2FBz6hCM7kpXWpw4,1512
24
+ eventsourcing-9.4.0a4.dist-info/METADATA,sha256=5ZcTr1zycsekzuQOt2W24DYp1j2VtwAtbB9msJJC-S8,9885
25
+ eventsourcing-9.4.0a4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
26
+ eventsourcing-9.4.0a4.dist-info/RECORD,,