eventsourcing 9.4.0b2__py3-none-any.whl → 9.4.0b3__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.

@@ -31,9 +31,7 @@ if TYPE_CHECKING:
31
31
 
32
32
 
33
33
  class Transcoding(ABC):
34
- """
35
- Abstract base class for custom transcodings.
36
- """
34
+ """Abstract base class for custom transcodings."""
37
35
 
38
36
  type: type
39
37
  name: str
@@ -48,9 +46,7 @@ class Transcoding(ABC):
48
46
 
49
47
 
50
48
  class Transcoder(ABC):
51
- """
52
- Abstract base class for transcoders.
53
- """
49
+ """Abstract base class for transcoders."""
54
50
 
55
51
  @abstractmethod
56
52
  def encode(self, obj: Any) -> bytes:
@@ -62,15 +58,11 @@ class Transcoder(ABC):
62
58
 
63
59
 
64
60
  class TranscodingNotRegisteredError(EventSourcingError, TypeError):
65
- """
66
- Raised when a transcoding isn't registered with JSONTranscoder.
67
- """
61
+ """Raised when a transcoding isn't registered with JSONTranscoder."""
68
62
 
69
63
 
70
64
  class JSONTranscoder(Transcoder):
71
- """
72
- Extensible transcoder that uses the Python :mod:`json` module.
73
- """
65
+ """Extensible transcoder that uses the Python :mod:`json` module."""
74
66
 
75
67
  def __init__(self) -> None:
76
68
  self.types: dict[type, Transcoding] = {}
@@ -83,22 +75,16 @@ class JSONTranscoder(Transcoder):
83
75
  self.decoder = json.JSONDecoder(object_hook=self._decode_obj)
84
76
 
85
77
  def register(self, transcoding: Transcoding) -> None:
86
- """
87
- Registers given transcoding with the transcoder.
88
- """
78
+ """Registers given transcoding with the transcoder."""
89
79
  self.types[transcoding.type] = transcoding
90
80
  self.names[transcoding.name] = transcoding
91
81
 
92
82
  def encode(self, obj: Any) -> bytes:
93
- """
94
- Encodes given object as a bytes array.
95
- """
83
+ """Encodes given object as a bytes array."""
96
84
  return self.encoder.encode(obj).encode("utf8")
97
85
 
98
86
  def decode(self, data: bytes) -> Any:
99
- """
100
- Decodes bytes array as previously encoded object.
101
- """
87
+ """Decodes bytes array as previously encoded object."""
102
88
  return self.decoder.decode(data.decode("utf8"))
103
89
 
104
90
  def _encode_obj(self, o: Any) -> dict[str, Any]:
@@ -130,10 +116,10 @@ class JSONTranscoder(Transcoder):
130
116
  return d
131
117
  else:
132
118
  try:
133
- transcoding = self.names[cast(str, _type_)]
119
+ transcoding = self.names[cast("str", _type_)]
134
120
  except KeyError as e:
135
121
  msg = (
136
- f"Data serialized with name '{cast(str, _type_)}' is not "
122
+ f"Data serialized with name '{cast('str', _type_)}' is not "
137
123
  "deserializable. Please register a "
138
124
  "custom transcoding for this type."
139
125
  )
@@ -145,9 +131,7 @@ class JSONTranscoder(Transcoder):
145
131
 
146
132
 
147
133
  class UUIDAsHex(Transcoding):
148
- """
149
- Transcoding that represents :class:`UUID` objects as hex values.
150
- """
134
+ """Transcoding that represents :class:`UUID` objects as hex values."""
151
135
 
152
136
  type = UUID
153
137
  name = "uuid_hex"
@@ -161,9 +145,7 @@ class UUIDAsHex(Transcoding):
161
145
 
162
146
 
163
147
  class DecimalAsStr(Transcoding):
164
- """
165
- Transcoding that represents :class:`Decimal` objects as strings.
166
- """
148
+ """Transcoding that represents :class:`Decimal` objects as strings."""
167
149
 
168
150
  type = Decimal
169
151
  name = "decimal_str"
@@ -176,9 +158,7 @@ class DecimalAsStr(Transcoding):
176
158
 
177
159
 
178
160
  class DatetimeAsISO(Transcoding):
179
- """
180
- Transcoding that represents :class:`datetime` objects as ISO strings.
181
- """
161
+ """Transcoding that represents :class:`datetime` objects as ISO strings."""
182
162
 
183
163
  type = datetime
184
164
  name = "datetime_iso"
@@ -193,8 +173,7 @@ class DatetimeAsISO(Transcoding):
193
173
 
194
174
  @dataclass(frozen=True)
195
175
  class StoredEvent:
196
- """
197
- Frozen dataclass that represents :class:`~eventsourcing.domain.DomainEvent`
176
+ """Frozen dataclass that represents :class:`~eventsourcing.domain.DomainEvent`
198
177
  objects, such as aggregate :class:`~eventsourcing.domain.Aggregate.Event`
199
178
  objects and :class:`~eventsourcing.domain.Snapshot` objects.
200
179
  """
@@ -210,56 +189,39 @@ class StoredEvent:
210
189
 
211
190
 
212
191
  class Compressor(ABC):
213
- """
214
- Base class for compressors.
215
- """
192
+ """Base class for compressors."""
216
193
 
217
194
  @abstractmethod
218
195
  def compress(self, data: bytes) -> bytes:
219
- """
220
- Compress bytes.
221
- """
196
+ """Compress bytes."""
222
197
 
223
198
  @abstractmethod
224
199
  def decompress(self, data: bytes) -> bytes:
225
- """
226
- Decompress bytes.
227
- """
200
+ """Decompress bytes."""
228
201
 
229
202
 
230
203
  class Cipher(ABC):
231
- """
232
- Base class for ciphers.
233
- """
204
+ """Base class for ciphers."""
234
205
 
235
206
  @abstractmethod
236
207
  def __init__(self, environment: Environment):
237
- """
238
- Initialises cipher with given environment.
239
- """
208
+ """Initialises cipher with given environment."""
240
209
 
241
210
  @abstractmethod
242
211
  def encrypt(self, plaintext: bytes) -> bytes:
243
- """
244
- Return ciphertext for given plaintext.
245
- """
212
+ """Return ciphertext for given plaintext."""
246
213
 
247
214
  @abstractmethod
248
215
  def decrypt(self, ciphertext: bytes) -> bytes:
249
- """
250
- Return plaintext for given ciphertext.
251
- """
216
+ """Return plaintext for given ciphertext."""
252
217
 
253
218
 
254
219
  class MapperDeserialisationError(EventSourcingError, ValueError):
255
- """
256
- Raised when deserialization fails in a Mapper.
257
- """
220
+ """Raised when deserialization fails in a Mapper."""
258
221
 
259
222
 
260
223
  class Mapper:
261
- """
262
- Converts between domain event objects and :class:`StoredEvent` objects.
224
+ """Converts between domain event objects and :class:`StoredEvent` objects.
263
225
 
264
226
  Uses a :class:`Transcoder`, and optionally a cryptographic cipher and compressor.
265
227
  """
@@ -275,9 +237,7 @@ class Mapper:
275
237
  self.cipher = cipher
276
238
 
277
239
  def to_stored_event(self, domain_event: DomainEventProtocol) -> StoredEvent:
278
- """
279
- Converts the given domain event to a :class:`StoredEvent` object.
280
- """
240
+ """Converts the given domain event to a :class:`StoredEvent` object."""
281
241
  topic = get_topic(domain_event.__class__)
282
242
  event_state = domain_event.__dict__.copy()
283
243
  originator_id = event_state.pop("originator_id")
@@ -298,9 +258,7 @@ class Mapper:
298
258
  )
299
259
 
300
260
  def to_domain_event(self, stored_event: StoredEvent) -> DomainEventProtocol:
301
- """
302
- Converts the given :class:`StoredEvent` to a domain event object.
303
- """
261
+ """Converts the given :class:`StoredEvent` to a domain event object."""
304
262
  stored_state = stored_event.state
305
263
  try:
306
264
  if self.cipher:
@@ -332,42 +290,34 @@ class Mapper:
332
290
 
333
291
 
334
292
  class RecordConflictError(EventSourcingError):
335
- """
336
- Legacy exception, replaced with IntegrityError.
337
- """
293
+ """Legacy exception, replaced with IntegrityError."""
338
294
 
339
295
 
340
296
  class PersistenceError(EventSourcingError):
341
- """
342
- The base class of the other exceptions in this module.
297
+ """The base class of the other exceptions in this module.
343
298
 
344
299
  Exception class names follow https://www.python.org/dev/peps/pep-0249/#exceptions
345
300
  """
346
301
 
347
302
 
348
303
  class InterfaceError(PersistenceError):
349
- """
350
- Exception raised for errors that are related to the database
304
+ """Exception raised for errors that are related to the database
351
305
  interface rather than the database itself.
352
306
  """
353
307
 
354
308
 
355
309
  class DatabaseError(PersistenceError):
356
- """
357
- Exception raised for errors that are related to the database.
358
- """
310
+ """Exception raised for errors that are related to the database."""
359
311
 
360
312
 
361
313
  class DataError(DatabaseError):
362
- """
363
- Exception raised for errors that are due to problems with the
314
+ """Exception raised for errors that are due to problems with the
364
315
  processed data like division by zero, numeric value out of range, etc.
365
316
  """
366
317
 
367
318
 
368
319
  class OperationalError(DatabaseError):
369
- """
370
- Exception raised for errors that are related to the database's
320
+ """Exception raised for errors that are related to the database's
371
321
  operation and not necessarily under the control of the programmer,
372
322
  e.g. an unexpected disconnect occurs, the data source name is not
373
323
  found, a transaction could not be processed, a memory allocation
@@ -376,31 +326,27 @@ class OperationalError(DatabaseError):
376
326
 
377
327
 
378
328
  class IntegrityError(DatabaseError, RecordConflictError):
379
- """
380
- Exception raised when the relational integrity of the
329
+ """Exception raised when the relational integrity of the
381
330
  database is affected, e.g. a foreign key check fails.
382
331
  """
383
332
 
384
333
 
385
334
  class InternalError(DatabaseError):
386
- """
387
- Exception raised when the database encounters an internal
335
+ """Exception raised when the database encounters an internal
388
336
  error, e.g. the cursor is not valid anymore, the transaction
389
337
  is out of sync, etc.
390
338
  """
391
339
 
392
340
 
393
341
  class ProgrammingError(DatabaseError):
394
- """
395
- Exception raised for database programming errors, e.g. table
342
+ """Exception raised for database programming errors, e.g. table
396
343
  not found or already exists, syntax error in the SQL statement,
397
344
  wrong number of parameters specified, etc.
398
345
  """
399
346
 
400
347
 
401
348
  class NotSupportedError(DatabaseError):
402
- """
403
- Exception raised in case a method or database API was used
349
+ """Exception raised in case a method or database API was used
404
350
  which is not supported by the database, e.g. calling the
405
351
  rollback() method on a connection that does not support
406
352
  transaction or has transactions turned off.
@@ -408,9 +354,7 @@ class NotSupportedError(DatabaseError):
408
354
 
409
355
 
410
356
  class WaitInterruptedError(PersistenceError):
411
- """
412
- Raised when waiting for a tracking record is interrupted.
413
- """
357
+ """Raised when waiting for a tracking record is interrupted."""
414
358
 
415
359
 
416
360
  class Recorder:
@@ -418,17 +362,13 @@ class Recorder:
418
362
 
419
363
 
420
364
  class AggregateRecorder(Recorder, ABC):
421
- """
422
- Abstract base class for inserting and selecting stored events.
423
- """
365
+ """Abstract base class for inserting and selecting stored events."""
424
366
 
425
367
  @abstractmethod
426
368
  def insert_events(
427
369
  self, stored_events: list[StoredEvent], **kwargs: Any
428
370
  ) -> Sequence[int] | None:
429
- """
430
- Writes stored events into database.
431
- """
371
+ """Writes stored events into database."""
432
372
 
433
373
  @abstractmethod
434
374
  def select_events(
@@ -440,24 +380,19 @@ class AggregateRecorder(Recorder, ABC):
440
380
  desc: bool = False,
441
381
  limit: int | None = None,
442
382
  ) -> list[StoredEvent]:
443
- """
444
- Reads stored events from database.
445
- """
383
+ """Reads stored events from database."""
446
384
 
447
385
 
448
386
  @dataclass(frozen=True)
449
387
  class Notification(StoredEvent):
450
- """
451
- Frozen dataclass that represents domain event notifications.
452
- """
388
+ """Frozen dataclass that represents domain event notifications."""
453
389
 
454
390
  id: int
455
391
  """Position in an application sequence."""
456
392
 
457
393
 
458
394
  class ApplicationRecorder(AggregateRecorder):
459
- """
460
- Abstract base class for recording events in both aggregate
395
+ """Abstract base class for recording events in both aggregate
461
396
  and application sequences.
462
397
  """
463
398
 
@@ -471,8 +406,7 @@ class ApplicationRecorder(AggregateRecorder):
471
406
  *,
472
407
  inclusive_of_start: bool = True,
473
408
  ) -> list[Notification]:
474
- """
475
- Returns a list of Notification objects representing events from an
409
+ """Returns a list of Notification objects representing events from an
476
410
  application sequence. If `inclusive_of_start` is True (the default),
477
411
  the returned Notification objects will have IDs greater than or equal
478
412
  to `start` and less than or equal to `stop`. If `inclusive_of_start`
@@ -482,8 +416,7 @@ class ApplicationRecorder(AggregateRecorder):
482
416
 
483
417
  @abstractmethod
484
418
  def max_notification_id(self) -> int | None:
485
- """
486
- Returns the largest notification ID in an application sequence,
419
+ """Returns the largest notification ID in an application sequence,
487
420
  or None if no stored events have been recorded.
488
421
  """
489
422
 
@@ -491,8 +424,7 @@ class ApplicationRecorder(AggregateRecorder):
491
424
  def subscribe(
492
425
  self, gt: int | None = None, topics: Sequence[str] = ()
493
426
  ) -> Subscription[ApplicationRecorder]:
494
- """
495
- Returns an iterator of Notification objects representing events from an
427
+ """Returns an iterator of Notification objects representing events from an
496
428
  application sequence.
497
429
 
498
430
  The iterator will block after the last recorded event has been yielded, but
@@ -503,21 +435,17 @@ class ApplicationRecorder(AggregateRecorder):
503
435
 
504
436
 
505
437
  class TrackingRecorder(Recorder, ABC):
506
- """
507
- Abstract base class for recorders that record tracking
438
+ """Abstract base class for recorders that record tracking
508
439
  objects atomically with other state.
509
440
  """
510
441
 
511
442
  @abstractmethod
512
443
  def insert_tracking(self, tracking: Tracking) -> None:
513
- """
514
- Records a tracking object.
515
- """
444
+ """Records a tracking object."""
516
445
 
517
446
  @abstractmethod
518
447
  def max_tracking_id(self, application_name: str) -> int | None:
519
- """
520
- Returns the largest notification ID across all recorded tracking objects
448
+ """Returns the largest notification ID across all recorded tracking objects
521
449
  for the named application, or None if no tracking objects have been recorded.
522
450
  """
523
451
 
@@ -525,8 +453,7 @@ class TrackingRecorder(Recorder, ABC):
525
453
  def has_tracking_id(
526
454
  self, application_name: str, notification_id: int | None
527
455
  ) -> bool:
528
- """
529
- Returns True if a tracking object with the given application name
456
+ """Returns True if a tracking object with the given application name
530
457
  and notification ID has been recorded, and True if given notification_id is
531
458
  None, otherwise returns False.
532
459
  """
@@ -538,8 +465,7 @@ class TrackingRecorder(Recorder, ABC):
538
465
  timeout: float = 1.0,
539
466
  interrupt: Event | None = None,
540
467
  ) -> None:
541
- """
542
- Block until a tracking object with the given application name and a
468
+ """Block until a tracking object with the given application name and a
543
469
  notification ID greater than equal to the given value has been recorded.
544
470
 
545
471
  Polls max_tracking_id() with exponential backoff until the timeout
@@ -594,9 +520,7 @@ class Recording:
594
520
 
595
521
 
596
522
  class EventStore:
597
- """
598
- Stores and retrieves domain events.
599
- """
523
+ """Stores and retrieves domain events."""
600
524
 
601
525
  def __init__(
602
526
  self,
@@ -609,9 +533,7 @@ class EventStore:
609
533
  def put(
610
534
  self, domain_events: Sequence[DomainEventProtocol], **kwargs: Any
611
535
  ) -> list[Recording]:
612
- """
613
- Stores domain events in aggregate sequence.
614
- """
536
+ """Stores domain events in aggregate sequence."""
615
537
  stored_events = list(map(self.mapper.to_stored_event, domain_events))
616
538
  recordings = []
617
539
  notification_ids = self.recorder.insert_events(stored_events, **kwargs)
@@ -641,9 +563,7 @@ class EventStore:
641
563
  desc: bool = False,
642
564
  limit: int | None = None,
643
565
  ) -> Iterator[DomainEventProtocol]:
644
- """
645
- Retrieves domain events from aggregate sequence.
646
- """
566
+ """Retrieves domain events from aggregate sequence."""
647
567
  return map(
648
568
  self.mapper.to_domain_event,
649
569
  self.recorder.select_events(
@@ -661,10 +581,12 @@ TTrackingRecorder = TypeVar(
661
581
  )
662
582
 
663
583
 
584
+ class InfrastructureFactoryError(EventSourcingError):
585
+ """Raised when an infrastructure factory cannot be created."""
586
+
587
+
664
588
  class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
665
- """
666
- Abstract base class for infrastructure factories.
667
- """
589
+ """Abstract base class for infrastructure factories."""
668
590
 
669
591
  PERSISTENCE_MODULE = "PERSISTENCE_MODULE"
670
592
  TRANSCODER_TOPIC = "TRANSCODER_TOPIC"
@@ -681,8 +603,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
681
603
  cls: type[InfrastructureFactory[TTrackingRecorder]],
682
604
  env: Environment | None = None,
683
605
  ) -> InfrastructureFactory[TTrackingRecorder]:
684
- """
685
- Constructs concrete infrastructure factory for given
606
+ """Constructs concrete infrastructure factory for given
686
607
  named application. Reads and resolves persistence
687
608
  topic from environment variable 'PERSISTENCE_MODULE'.
688
609
  """
@@ -714,7 +635,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
714
635
  f"'{topic}' from environment "
715
636
  f"variable '{cls.PERSISTENCE_MODULE}'"
716
637
  )
717
- raise OSError(msg) from e
638
+ raise InfrastructureFactoryError(msg) from e
718
639
 
719
640
  if isinstance(obj, ModuleType):
720
641
  # Find the factory in the module.
@@ -739,26 +660,25 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
739
660
  f"Found {len(factory_classes)} infrastructure factory classes in"
740
661
  f" '{topic}', expected 1."
741
662
  )
742
- raise AssertionError(msg)
663
+ raise InfrastructureFactoryError(msg)
743
664
  elif isinstance(obj, type) and issubclass(obj, InfrastructureFactory):
744
665
  factory_cls = obj
745
666
  else:
746
- msg = f"Not an infrastructure factory class or module: {topic}"
747
- raise AssertionError(msg)
667
+ msg = (
668
+ f"Topic '{topic}' didn't resolve to a persistence module "
669
+ f"or infrastructure factory class: {obj}"
670
+ )
671
+ raise InfrastructureFactoryError(msg)
748
672
  return factory_cls(env=env)
749
673
 
750
674
  def __init__(self, env: Environment):
751
- """
752
- Initialises infrastructure factory object with given application name.
753
- """
675
+ """Initialises infrastructure factory object with given application name."""
754
676
  self.env = env
755
677
 
756
678
  def transcoder(
757
679
  self,
758
680
  ) -> Transcoder:
759
- """
760
- Constructs a transcoder.
761
- """
681
+ """Constructs a transcoder."""
762
682
  transcoder_topic = self.env.get(self.TRANSCODER_TOPIC)
763
683
  if transcoder_topic:
764
684
  transcoder_class: type[Transcoder] = resolve_topic(transcoder_topic)
@@ -771,9 +691,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
771
691
  transcoder: Transcoder | None = None,
772
692
  mapper_class: type[Mapper] | None = None,
773
693
  ) -> Mapper:
774
- """
775
- Constructs a mapper.
776
- """
694
+ """Constructs a mapper."""
777
695
  if mapper_class is None:
778
696
  mapper_topic = self.env.get(self.MAPPER_TOPIC)
779
697
  mapper_class = resolve_topic(mapper_topic) if mapper_topic else Mapper
@@ -786,8 +704,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
786
704
  )
787
705
 
788
706
  def cipher(self) -> Cipher | None:
789
- """
790
- Reads environment variables 'CIPHER_TOPIC'
707
+ """Reads environment variables 'CIPHER_TOPIC'
791
708
  and 'CIPHER_KEY' to decide whether or not
792
709
  to construct a cipher.
793
710
  """
@@ -804,8 +721,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
804
721
  return cipher
805
722
 
806
723
  def compressor(self) -> Compressor | None:
807
- """
808
- Reads environment variable 'COMPRESSOR_TOPIC' to
724
+ """Reads environment variable 'COMPRESSOR_TOPIC' to
809
725
  decide whether or not to construct a compressor.
810
726
  """
811
727
  compressor: Compressor | None = None
@@ -825,9 +741,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
825
741
  mapper: Mapper | None = None,
826
742
  recorder: AggregateRecorder | None = None,
827
743
  ) -> EventStore:
828
- """
829
- Constructs an event store.
830
- """
744
+ """Constructs an event store."""
831
745
  return EventStore(
832
746
  mapper=mapper or self.mapper(),
833
747
  recorder=recorder or self.application_recorder(),
@@ -835,48 +749,36 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
835
749
 
836
750
  @abstractmethod
837
751
  def aggregate_recorder(self, purpose: str = "events") -> AggregateRecorder:
838
- """
839
- Constructs an aggregate recorder.
840
- """
752
+ """Constructs an aggregate recorder."""
841
753
 
842
754
  @abstractmethod
843
755
  def application_recorder(self) -> ApplicationRecorder:
844
- """
845
- Constructs an application recorder.
846
- """
756
+ """Constructs an application recorder."""
847
757
 
848
758
  @abstractmethod
849
759
  def tracking_recorder(
850
760
  self, tracking_recorder_class: type[TTrackingRecorder] | None = None
851
761
  ) -> TTrackingRecorder:
852
- """
853
- Constructs a tracking recorder.
854
- """
762
+ """Constructs a tracking recorder."""
855
763
 
856
764
  @abstractmethod
857
765
  def process_recorder(self) -> ProcessRecorder:
858
- """
859
- Constructs a process recorder.
860
- """
766
+ """Constructs a process recorder."""
861
767
 
862
768
  def is_snapshotting_enabled(self) -> bool:
863
- """
864
- Decides whether or not snapshotting is enabled by
769
+ """Decides whether or not snapshotting is enabled by
865
770
  reading environment variable 'IS_SNAPSHOTTING_ENABLED'.
866
771
  Snapshotting is not enabled by default.
867
772
  """
868
773
  return strtobool(self.env.get(self.IS_SNAPSHOTTING_ENABLED, "no"))
869
774
 
870
775
  def close(self) -> None:
871
- """
872
- Closes any database connections, and anything else that needs closing.
873
- """
776
+ """Closes any database connections, and anything else that needs closing."""
874
777
 
875
778
 
876
779
  @dataclass(frozen=True)
877
780
  class Tracking:
878
- """
879
- Frozen dataclass representing the position of a domain
781
+ """Frozen dataclass representing the position of a domain
880
782
  event :class:`Notification` in an application's notification log.
881
783
  """
882
784
 
@@ -963,20 +865,15 @@ TConnection = TypeVar("TConnection", bound=Connection[Any])
963
865
 
964
866
 
965
867
  class ConnectionPoolClosedError(EventSourcingError):
966
- """
967
- Raised when using a connection pool that is already closed.
968
- """
868
+ """Raised when using a connection pool that is already closed."""
969
869
 
970
870
 
971
871
  class ConnectionNotFromPoolError(EventSourcingError):
972
- """
973
- Raised when putting a connection in the wrong pool.
974
- """
872
+ """Raised when putting a connection in the wrong pool."""
975
873
 
976
874
 
977
875
  class ConnectionUnavailableError(OperationalError, TimeoutError):
978
- """
979
- Raised when a request to get a connection from a
876
+ """Raised when a request to get a connection from a
980
877
  connection pool times out.
981
878
  """
982
879
 
@@ -992,8 +889,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
992
889
  pre_ping: bool = False,
993
890
  mutually_exclusive_read_write: bool = False,
994
891
  ) -> None:
995
- """
996
- Initialises a new connection pool.
892
+ """Initialises a new connection pool.
997
893
 
998
894
  The 'pool_size' argument specifies the maximum number of connections
999
895
  that will be put into the pool when connections are returned. The
@@ -1044,9 +940,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
1044
940
 
1045
941
  @property
1046
942
  def num_in_use(self) -> int:
1047
- """
1048
- Indicates the total number of connections currently in use.
1049
- """
943
+ """Indicates the total number of connections currently in use."""
1050
944
  with self._put_condition:
1051
945
  return self._num_in_use
1052
946
 
@@ -1056,9 +950,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
1056
950
 
1057
951
  @property
1058
952
  def num_in_pool(self) -> int:
1059
- """
1060
- Indicates the number of connections currently in the pool.
1061
- """
953
+ """Indicates the number of connections currently in the pool."""
1062
954
  with self._put_condition:
1063
955
  return self._num_in_pool
1064
956
 
@@ -1077,8 +969,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
1077
969
  def get_connection(
1078
970
  self, timeout: float | None = None, is_writer: bool | None = None
1079
971
  ) -> TConnection:
1080
- """
1081
- Issues connections, or raises ConnectionPoolExhausted error.
972
+ """Issues connections, or raises ConnectionPoolExhausted error.
1082
973
  Provides "fairness" on attempts to get connections, meaning that
1083
974
  connections are issued in the same order as they are requested.
1084
975
 
@@ -1162,8 +1053,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
1162
1053
  raise ConnectionUnavailableError(msg)
1163
1054
 
1164
1055
  def _get_connection(self, timeout: float = 0.0) -> TConnection:
1165
- """
1166
- Gets or creates connections from pool within given
1056
+ """Gets or creates connections from pool within given
1167
1057
  time, otherwise raises a "pool exhausted" error.
1168
1058
 
1169
1059
  Waits for connections to be returned if the pool
@@ -1230,8 +1120,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
1230
1120
  return conn
1231
1121
 
1232
1122
  def put_connection(self, conn: TConnection) -> None:
1233
- """
1234
- Returns connections to the pool, or closes connection
1123
+ """Returns connections to the pool, or closes connection
1235
1124
  if the pool is full.
1236
1125
 
1237
1126
  Unlocks write lock after writer has returned, and
@@ -1240,7 +1129,6 @@ class ConnectionPool(ABC, Generic[TConnection]):
1240
1129
  Notifies waiters when connections have been returned,
1241
1130
  and when there are no longer any readers.
1242
1131
  """
1243
-
1244
1132
  # Start forgetting if this connection was for reading or writing.
1245
1133
  is_writer, conn.is_writer = conn.is_writer, None
1246
1134
 
@@ -1287,8 +1175,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
1287
1175
 
1288
1176
  @abstractmethod
1289
1177
  def _create_connection(self) -> TConnection:
1290
- """
1291
- Create a new connection.
1178
+ """Create a new connection.
1292
1179
 
1293
1180
  Subclasses should implement this method by
1294
1181
  creating a database connection of the type
@@ -1296,9 +1183,7 @@ class ConnectionPool(ABC, Generic[TConnection]):
1296
1183
  """
1297
1184
 
1298
1185
  def close(self) -> None:
1299
- """
1300
- Close the connection pool.
1301
- """
1186
+ """Close the connection pool."""
1302
1187
  with self._put_condition:
1303
1188
  if self._closed:
1304
1189
  return
@@ -1353,9 +1238,7 @@ class Subscription(Iterator[Notification], Generic[TApplicationRecorder_co]):
1353
1238
  self.stop()
1354
1239
 
1355
1240
  def stop(self) -> None:
1356
- """
1357
- Stops the subscription.
1358
- """
1241
+ """Stops the subscription."""
1359
1242
  self._has_been_stopped = True
1360
1243
 
1361
1244
  def __iter__(self) -> Self:
@@ -1363,9 +1246,7 @@ class Subscription(Iterator[Notification], Generic[TApplicationRecorder_co]):
1363
1246
 
1364
1247
  @abstractmethod
1365
1248
  def __next__(self) -> Notification:
1366
- """
1367
- Returns the next Notification object in the application sequence.
1368
- """
1249
+ """Returns the next Notification object in the application sequence."""
1369
1250
 
1370
1251
 
1371
1252
  class ListenNotifySubscription(Subscription[TApplicationRecorder_co]):
@@ -1390,9 +1271,7 @@ class ListenNotifySubscription(Subscription[TApplicationRecorder_co]):
1390
1271
  self._pull_thread.join()
1391
1272
 
1392
1273
  def stop(self) -> None:
1393
- """
1394
- Stops the subscription.
1395
- """
1274
+ """Stops the subscription."""
1396
1275
  super().stop()
1397
1276
  self._notifications_queue.put([])
1398
1277
  self._has_been_notified.set()