eventsourcing 9.4.0a5__py3-none-any.whl → 9.4.0a7__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.

@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
  from abc import ABC, abstractmethod
5
+ from collections.abc import Iterable, Iterator, Sequence
5
6
  from copy import deepcopy
6
7
  from dataclasses import dataclass
7
8
  from itertools import chain
@@ -11,22 +12,13 @@ from typing import (
11
12
  Any,
12
13
  Callable,
13
14
  ClassVar,
14
- Dict,
15
15
  Generic,
16
- Iterable,
17
- Iterator,
18
- List,
19
16
  Optional,
20
- Sequence,
21
- Tuple,
22
- Type,
23
17
  TypeVar,
24
18
  cast,
25
19
  )
26
20
  from warnings import warn
27
21
 
28
- from typing_extensions import deprecated
29
-
30
22
  from eventsourcing.domain import (
31
23
  Aggregate,
32
24
  CanMutateProtocol,
@@ -96,7 +88,7 @@ T = TypeVar("T")
96
88
 
97
89
  class Cache(Generic[S, T]):
98
90
  def __init__(self) -> None:
99
- self.cache: Dict[S, Any] = {}
91
+ self.cache: dict[S, Any] = {}
100
92
 
101
93
  def get(self, key: S, *, evict: bool = False) -> T:
102
94
  if evict:
@@ -127,7 +119,7 @@ class LRUCache(Cache[S, T]):
127
119
  self.maxsize = maxsize
128
120
  self.full = False
129
121
  self.lock = Lock() # because linkedlist updates aren't threadsafe
130
- self.root: List[Any] = [] # root of the circular doubly linked list
122
+ self.root: list[Any] = [] # root of the circular doubly linked list
131
123
  self.clear()
132
124
 
133
125
  def clear(self) -> None:
@@ -253,7 +245,7 @@ class Repository:
253
245
  self._fastforward_locks_cache: LRUCache[UUID, Lock] = LRUCache(
254
246
  maxsize=self.FASTFORWARD_LOCKS_CACHE_MAXSIZE
255
247
  )
256
- self._fastforward_locks_inuse: Dict[UUID, Tuple[Lock, int]] = {}
248
+ self._fastforward_locks_inuse: dict[UUID, tuple[Lock, int]] = {}
257
249
 
258
250
  def get(
259
251
  self,
@@ -415,12 +407,12 @@ class Section:
415
407
  Constructor arguments:
416
408
 
417
409
  :param Optional[str] id: section ID of this section e.g. "1,10"
418
- :param List[Notification] items: a list of event notifications
410
+ :param list[Notification] items: a list of event notifications
419
411
  :param Optional[str] next_id: section ID of the following section
420
412
  """
421
413
 
422
414
  id: str | None
423
- items: List[Notification]
415
+ items: list[Notification]
424
416
  next_id: str | None
425
417
 
426
418
 
@@ -446,7 +438,7 @@ class NotificationLog(ABC):
446
438
  topics: Sequence[str] = (),
447
439
  *,
448
440
  inclusive_of_start: bool = True,
449
- ) -> List[Notification]:
441
+ ) -> list[Notification]:
450
442
  """
451
443
  Returns a selection of
452
444
  :class:`~eventsourcing.persistence.Notification` objects
@@ -536,7 +528,7 @@ class LocalNotificationLog(NotificationLog):
536
528
  topics: Sequence[str] = (),
537
529
  *,
538
530
  inclusive_of_start: bool = True,
539
- ) -> List[Notification]:
531
+ ) -> list[Notification]:
540
532
  """
541
533
  Returns a selection of
542
534
  :class:`~eventsourcing.persistence.Notification` objects
@@ -573,9 +565,9 @@ class ProcessingEvent:
573
565
  Initialises the process event with the given tracking object.
574
566
  """
575
567
  self.tracking = tracking
576
- self.events: List[DomainEventProtocol] = []
577
- self.aggregates: Dict[UUID, MutableOrImmutableAggregate] = {}
578
- self.saved_kwargs: Dict[Any, Any] = {}
568
+ self.events: list[DomainEventProtocol] = []
569
+ self.aggregates: dict[UUID, MutableOrImmutableAggregate] = {}
570
+ self.saved_kwargs: dict[Any, Any] = {}
579
571
 
580
572
  def collect_events(
581
573
  self,
@@ -618,15 +610,15 @@ class Application:
618
610
  """
619
611
 
620
612
  name = "Application"
621
- env: ClassVar[Dict[str, str]] = {}
613
+ env: ClassVar[dict[str, str]] = {}
622
614
  is_snapshotting_enabled: bool = False
623
615
  snapshotting_intervals: ClassVar[
624
- Dict[Type[MutableOrImmutableAggregate], int] | None
616
+ dict[type[MutableOrImmutableAggregate], int] | None
625
617
  ] = None
626
618
  snapshotting_projectors: ClassVar[
627
- Dict[Type[MutableOrImmutableAggregate], ProjectorFunction[Any, Any]] | None
619
+ dict[type[MutableOrImmutableAggregate], ProjectorFunction[Any, Any]] | None
628
620
  ] = None
629
- snapshot_class: Type[SnapshotProtocol] = Snapshot
621
+ snapshot_class: type[SnapshotProtocol] = Snapshot
630
622
  log_section_size = 10
631
623
  notify_topics: Sequence[str] = []
632
624
 
@@ -792,7 +784,7 @@ class Application:
792
784
  self,
793
785
  *objs: MutableOrImmutableAggregate | DomainEventProtocol | None,
794
786
  **kwargs: Any,
795
- ) -> List[Recording]:
787
+ ) -> list[Recording]:
796
788
  """
797
789
  Collects pending events from given aggregates and
798
790
  puts them in the application's event store.
@@ -805,7 +797,7 @@ class Application:
805
797
  self.notify(processing_event.events) # Deprecated.
806
798
  return recordings
807
799
 
808
- def _record(self, processing_event: ProcessingEvent) -> List[Recording]:
800
+ def _record(self, processing_event: ProcessingEvent) -> list[Recording]:
809
801
  """
810
802
  Records given process event in the application's recorder.
811
803
  """
@@ -885,7 +877,7 @@ class Application:
885
877
  snapshot = snapshot_class.take(aggregate)
886
878
  self.snapshots.put([snapshot])
887
879
 
888
- def notify(self, new_events: List[DomainEventProtocol]) -> None:
880
+ def notify(self, new_events: list[DomainEventProtocol]) -> None:
889
881
  """
890
882
  Deprecated.
891
883
 
@@ -895,7 +887,7 @@ class Application:
895
887
  need to take action when new domain events have been saved.
896
888
  """
897
889
 
898
- def _notify(self, recordings: List[Recording]) -> None:
890
+ def _notify(self, recordings: list[Recording]) -> None:
899
891
  """
900
892
  Called after new aggregate events have been saved. This
901
893
  method on this class doesn't actually do anything,
@@ -911,14 +903,7 @@ class Application:
911
903
  TApplication = TypeVar("TApplication", bound=Application)
912
904
 
913
905
 
914
- @deprecated(
915
- "AggregateNotFound is deprecated, use AggregateNotFoundError instead", category=None
916
- )
917
- class AggregateNotFound(EventSourcingError): # noqa: N818
918
- pass
919
-
920
-
921
- class AggregateNotFoundError(AggregateNotFound):
906
+ class AggregateNotFoundError(EventSourcingError):
922
907
  """
923
908
  Raised when an :class:`~eventsourcing.domain.Aggregate`
924
909
  object is not found in a :class:`Repository`.
@@ -944,7 +929,7 @@ class EventSourcedLog(Generic[TDomainEvent]):
944
929
  self,
945
930
  events: EventStore,
946
931
  originator_id: UUID,
947
- logged_cls: Type[TDomainEvent], # TODO: Rename to 'event_class' in v10.
932
+ logged_cls: type[TDomainEvent], # TODO: Rename to 'event_class' in v10.
948
933
  ):
949
934
  self.events = events
950
935
  self.originator_id = originator_id
@@ -966,7 +951,7 @@ class EventSourcedLog(Generic[TDomainEvent]):
966
951
 
967
952
  def _trigger_event(
968
953
  self,
969
- logged_cls: Type[T] | None,
954
+ logged_cls: type[T] | None,
970
955
  next_originator_version: int | None = None,
971
956
  **kwargs: Any,
972
957
  ) -> T:
eventsourcing/domain.py CHANGED
@@ -1,23 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import dataclasses
4
+ import importlib
3
5
  import inspect
4
6
  import os
5
- from dataclasses import dataclass
6
7
  from datetime import datetime, tzinfo
7
- from functools import lru_cache
8
+ from functools import cache
8
9
  from types import FunctionType, WrapperDescriptorType
9
10
  from typing import (
10
11
  TYPE_CHECKING,
11
12
  Any,
12
13
  Callable,
13
- Dict,
14
14
  Generic,
15
- Iterable,
16
- List,
17
15
  Protocol,
18
- Sequence,
19
- Tuple,
20
- Type,
21
16
  TypeVar,
22
17
  Union,
23
18
  cast,
@@ -29,6 +24,10 @@ from warnings import warn
29
24
 
30
25
  from eventsourcing.utils import get_method_name, get_topic, resolve_topic
31
26
 
27
+ if TYPE_CHECKING:
28
+ from collections.abc import Iterable, Sequence
29
+
30
+
32
31
  TZINFO: tzinfo = resolve_topic(os.getenv("TZINFO_TOPIC", "datetime:timezone.utc"))
33
32
  """
34
33
  A Python :py:obj:`tzinfo` object that defaults to UTC (:py:obj:`timezone.utc`). Used
@@ -294,7 +293,7 @@ class CanInitAggregate(CanMutateAggregate):
294
293
  assert aggregate is None
295
294
 
296
295
  # Resolve originator topic.
297
- aggregate_class: Type[TAggregate] = resolve_topic(self.originator_topic)
296
+ aggregate_class: type[TAggregate] = resolve_topic(self.originator_topic)
298
297
 
299
298
  # Construct an aggregate object (a "shell" of the correct object type).
300
299
  agg = aggregate_class.__new__(aggregate_class)
@@ -333,12 +332,12 @@ class MetaDomainEvent(type):
333
332
  """
334
333
 
335
334
  def __new__(
336
- cls, name: str, bases: Tuple[Type[TDomainEvent], ...], cls_dict: Dict[str, Any]
337
- ) -> Type[TDomainEvent]:
335
+ cls, name: str, bases: tuple[type[TDomainEvent], ...], cls_dict: dict[str, Any]
336
+ ) -> type[TDomainEvent]:
338
337
  event_cls = cast(
339
- Type[TDomainEvent], super().__new__(cls, name, bases, cls_dict)
338
+ type[TDomainEvent], super().__new__(cls, name, bases, cls_dict)
340
339
  )
341
- event_cls = dataclass(frozen=True)(event_cls)
340
+ event_cls = dataclasses.dataclass(frozen=True)(event_cls)
342
341
  event_cls.__signature__ = inspect.signature(event_cls.__init__) # type: ignore
343
342
  return event_cls
344
343
 
@@ -398,20 +397,20 @@ TLogEvent = TypeVar("TLogEvent", bound=DomainEventProtocol)
398
397
 
399
398
 
400
399
  def _filter_kwargs_for_method_params(
401
- kwargs: Dict[str, Any], method: Callable[..., Any]
402
- ) -> Dict[str, Any]:
400
+ kwargs: dict[str, Any], method: Callable[..., Any]
401
+ ) -> dict[str, Any]:
403
402
  names = _spec_filter_kwargs_for_method_params(method)
404
403
  return {k: v for k, v in kwargs.items() if k in names}
405
404
 
406
405
 
407
- @lru_cache(maxsize=None)
406
+ @cache
408
407
  def _spec_filter_kwargs_for_method_params(method: Callable[..., Any]) -> set[str]:
409
408
  method_signature = inspect.signature(method)
410
409
  return set(method_signature.parameters)
411
410
 
412
411
 
413
412
  if TYPE_CHECKING:
414
- EventSpecType = Union[str, Type[CanMutateAggregate]]
413
+ EventSpecType = Union[str, type[CanMutateAggregate]]
415
414
 
416
415
  CommandMethod = Callable[..., None]
417
416
  DecoratedObjType = Union[CommandMethod, property]
@@ -425,7 +424,7 @@ class CommandMethodDecorator:
425
424
  decorated_obj: DecoratedObjType,
426
425
  ):
427
426
  self.is_name_inferred_from_method = False
428
- self.given_event_cls: Type[CanMutateAggregate] | None = None
427
+ self.given_event_cls: type[CanMutateAggregate] | None = None
429
428
  self.event_cls_name: str | None = None
430
429
  self.decorated_property: property | None = None
431
430
  self.is_property_setter = False
@@ -740,12 +739,12 @@ class BoundCommandMethodDecorator:
740
739
 
741
740
 
742
741
  given_event_classes: set[type] = set()
743
- decorated_methods: Dict[type, CommandMethod] = {}
744
- aggregate_has_many_created_event_classes: Dict[type, List[str]] = {}
742
+ decorated_methods: dict[type, CommandMethod] = {}
743
+ aggregate_has_many_created_event_classes: dict[type, list[str]] = {}
745
744
 
746
745
 
747
- decorated_event_classes: Dict[
748
- CommandMethodDecorator, Type[MetaAggregate.DecoratedEvent]
746
+ decorated_event_classes: dict[
747
+ CommandMethodDecorator, type[MetaAggregate.DecoratedEvent]
749
748
  ] = {}
750
749
 
751
750
 
@@ -767,10 +766,10 @@ def _check_no_variable_params(method: FunctionType) -> None:
767
766
  def _coerce_args_to_kwargs(
768
767
  method: FunctionType | WrapperDescriptorType,
769
768
  args: Iterable[Any],
770
- kwargs: Dict[str, Any],
769
+ kwargs: dict[str, Any],
771
770
  *,
772
771
  expects_id: bool = False,
773
- ) -> Dict[str, Any]:
772
+ ) -> dict[str, Any]:
774
773
  assert isinstance(method, (FunctionType, WrapperDescriptorType))
775
774
 
776
775
  args = tuple(args)
@@ -789,14 +788,14 @@ def _coerce_args_to_kwargs(
789
788
  return copy_kwargs
790
789
 
791
790
 
792
- @lru_cache(maxsize=None)
791
+ @cache
793
792
  def _spec_coerce_args_to_kwargs(
794
793
  method: FunctionType | WrapperDescriptorType,
795
794
  len_args: int,
796
- kwargs_keys: Tuple[str],
795
+ kwargs_keys: tuple[str],
797
796
  *,
798
797
  expects_id: bool,
799
- ) -> Tuple[Tuple[Tuple[int, str], ...], Tuple[Tuple[str, Any], ...]]:
798
+ ) -> tuple[tuple[tuple[int, str], ...], tuple[tuple[str, Any], ...]]:
800
799
  method_signature = inspect.signature(method)
801
800
  positional_names = []
802
801
  keyword_defaults = {}
@@ -874,7 +873,7 @@ def _spec_coerce_args_to_kwargs(
874
873
  return enumerated_args_names, keyword_defaults_items
875
874
 
876
875
 
877
- def _raise_missing_names_type_error(missing_names: List[str], msg: str) -> None:
876
+ def _raise_missing_names_type_error(missing_names: list[str], msg: str) -> None:
878
877
  msg += missing_names[0]
879
878
  if len(missing_names) == 2:
880
879
  msg += f" and {missing_names[1]}"
@@ -888,6 +887,34 @@ _annotations_mention_id: set[MetaAggregate[Aggregate]] = set()
888
887
  _init_mentions_id: set[MetaAggregate[Aggregate]] = set()
889
888
 
890
889
 
890
+ def _ensure_idempotent_dataclass(module_name: str) -> None:
891
+ module = importlib.import_module(module_name)
892
+ if (
893
+ "dataclass" in module.__dict__
894
+ and module.__dict__["dataclass"] == dataclasses.dataclass
895
+ and "__original_dataclass_func__" not in module.__dict__
896
+ ):
897
+ module.__dict__["__original_dataclass_func__"] = module.__dict__["dataclass"]
898
+ module.__dict__["dataclass"] = _idempotent_dataclass
899
+
900
+
901
+ def _idempotent_dataclass(cls: type[object] | None = None, /, **kwargs: Any) -> Any:
902
+
903
+ def idempotent_wrap(cls: type[object]) -> type[object]:
904
+ # Avoid processing dataclass twice.
905
+ if "__dataclass_fields__" in cls.__dict__:
906
+ return cls
907
+ return dataclasses.dataclass(**kwargs)(cls)
908
+
909
+ # See if we're being called as @dataclass or @dataclass().
910
+ if cls is None:
911
+ # We're called with parens.
912
+ return idempotent_wrap
913
+
914
+ # We're called as @dataclass without parens.
915
+ return idempotent_wrap(cls)
916
+
917
+
891
918
  class MetaAggregate(type, Generic[TAggregate]):
892
919
  """
893
920
  Metaclass for aggregate classes.
@@ -920,12 +947,18 @@ class MetaAggregate(type, Generic[TAggregate]):
920
947
  # Call the original method with event attribute values.
921
948
  decorated_method(aggregate, **kwargs)
922
949
 
923
- _created_event_class: Type[CanInitAggregate]
950
+ _created_event_class: type[CanInitAggregate]
924
951
 
925
952
  def __new__(cls, *args: Any, **_: Any) -> MetaAggregate[Aggregate]:
926
953
  """
927
954
  Configures aggregate class definition.
928
955
  """
956
+
957
+ # Avoid processing dataclass twice. This avoids dataclasses.Field(init=False)
958
+ # attributes being reduced to annotation only and then appearing in __init__
959
+ # method signature when class is reprocessed, and other similar problems.
960
+ _ensure_idempotent_dataclass(module_name=args[2]["__module__"])
961
+
929
962
  try:
930
963
  class_annotations = args[2]["__annotations__"]
931
964
  except KeyError:
@@ -939,8 +972,8 @@ class MetaAggregate(type, Generic[TAggregate]):
939
972
  else:
940
973
  annotations_mention_id = True
941
974
  aggregate_cls = type.__new__(cls, *args)
942
- if class_annotations:
943
- aggregate_cls = dataclass(eq=False, repr=False)(aggregate_cls)
975
+ if class_annotations or any(dataclasses.is_dataclass(base) for base in args[1]):
976
+ aggregate_cls = dataclasses.dataclass(eq=False, repr=False)(aggregate_cls)
944
977
  if annotations_mention_id:
945
978
  _annotations_mention_id.add(aggregate_cls)
946
979
  return aggregate_cls
@@ -957,7 +990,7 @@ class MetaAggregate(type, Generic[TAggregate]):
957
990
 
958
991
  # Identify or define a base event class for this aggregate.
959
992
  base_event_name = "Event"
960
- base_event_cls: Type[CanMutateAggregate]
993
+ base_event_cls: type[CanMutateAggregate]
961
994
  try:
962
995
  base_event_cls = cls.__dict__[base_event_name]
963
996
  except KeyError:
@@ -967,7 +1000,7 @@ class MetaAggregate(type, Generic[TAggregate]):
967
1000
  setattr(cls, base_event_name, base_event_cls)
968
1001
 
969
1002
  # Make sure all events defined on aggregate subclass the base event class.
970
- created_event_classes: Dict[str, Type[CanInitAggregate]] = {}
1003
+ created_event_classes: dict[str, type[CanInitAggregate]] = {}
971
1004
  for name, value in tuple(cls.__dict__.items()):
972
1005
  if name == base_event_name:
973
1006
  # Don't subclass the base event class again.
@@ -987,7 +1020,7 @@ class MetaAggregate(type, Generic[TAggregate]):
987
1020
  created_event_classes[name] = value
988
1021
 
989
1022
  # Disallow using both '_created_event_class' and 'created_event_name'.
990
- created_event_class: Type[CanInitAggregate] | None = cls.__dict__.get(
1023
+ created_event_class: type[CanInitAggregate] | None = cls.__dict__.get(
991
1024
  "_created_event_class"
992
1025
  )
993
1026
  if created_event_class and created_event_name:
@@ -1015,7 +1048,7 @@ class MetaAggregate(type, Generic[TAggregate]):
1015
1048
  # Does the decorator specify a "created" event class?
1016
1049
  if init_decorator.given_event_cls:
1017
1050
  created_event_class = cast(
1018
- Type[CanInitAggregate], init_decorator.given_event_cls
1051
+ type[CanInitAggregate], init_decorator.given_event_cls
1019
1052
  )
1020
1053
  # Does the decorator specify a "created" event name?
1021
1054
  elif init_decorator.event_cls_name:
@@ -1093,11 +1126,11 @@ class MetaAggregate(type, Generic[TAggregate]):
1093
1126
  # Define a "created" event class for this aggregate.
1094
1127
  if issubclass(base_created_event_cls, base_event_cls):
1095
1128
  # Don't subclass from base event class twice.
1096
- bases: Tuple[Type[CanMutateAggregate], ...] = (base_created_event_cls,)
1129
+ bases: tuple[type[CanMutateAggregate], ...] = (base_created_event_cls,)
1097
1130
  else:
1098
1131
  bases = (base_created_event_cls, base_event_cls)
1099
1132
  created_event_class = cast(
1100
- Type[CanInitAggregate],
1133
+ type[CanInitAggregate],
1101
1134
  cls._define_event_class(
1102
1135
  created_event_name,
1103
1136
  bases,
@@ -1160,7 +1193,7 @@ class MetaAggregate(type, Generic[TAggregate]):
1160
1193
 
1161
1194
  # Define event class as subclass of given class.
1162
1195
  given_subclass = cast(
1163
- Type[CanMutateAggregate],
1196
+ type[CanMutateAggregate],
1164
1197
  getattr(cls, event_decorator.given_event_cls.__name__),
1165
1198
  )
1166
1199
  event_cls = cls._define_event_class(
@@ -1194,7 +1227,7 @@ class MetaAggregate(type, Generic[TAggregate]):
1194
1227
 
1195
1228
  # Remember which event class to trigger.
1196
1229
  decorated_event_classes[event_decorator] = cast(
1197
- Type[MetaAggregate.DecoratedEvent], event_cls
1230
+ type[MetaAggregate.DecoratedEvent], event_cls
1198
1231
  )
1199
1232
 
1200
1233
  # Check any create_id method defined on this class is static or class method.
@@ -1208,7 +1241,7 @@ class MetaAggregate(type, Generic[TAggregate]):
1208
1241
  raise TypeError(msg)
1209
1242
 
1210
1243
  # Get the parameters of the create_id method that will be used by this class.
1211
- cls._create_id_param_names: List[str] = []
1244
+ cls._create_id_param_names: list[str] = []
1212
1245
  for name, param in inspect.signature(cls.create_id).parameters.items():
1213
1246
  if param.kind in [param.KEYWORD_ONLY, param.POSITIONAL_OR_KEYWORD]:
1214
1247
  cls._create_id_param_names.append(name)
@@ -1230,9 +1263,9 @@ class MetaAggregate(type, Generic[TAggregate]):
1230
1263
  def _define_event_class(
1231
1264
  cls,
1232
1265
  name: str,
1233
- bases: Tuple[Type[CanMutateAggregate], ...],
1266
+ bases: tuple[type[CanMutateAggregate], ...],
1234
1267
  apply_method: CommandMethod | None,
1235
- ) -> Type[CanMutateAggregate]:
1268
+ ) -> type[CanMutateAggregate]:
1236
1269
  # Define annotations for the event class (specs the init method).
1237
1270
  annotations = {}
1238
1271
  if apply_method is not None:
@@ -1256,7 +1289,7 @@ class MetaAggregate(type, Generic[TAggregate]):
1256
1289
  }
1257
1290
 
1258
1291
  # Create the event class object.
1259
- return cast(Type[CanMutateAggregate], type(name, bases, event_cls_dict))
1292
+ return cast(type[CanMutateAggregate], type(name, bases, event_cls_dict))
1260
1293
 
1261
1294
  def __call__(
1262
1295
  cls: MetaAggregate[TAggregate], *args: Any, **kwargs: Any
@@ -1286,7 +1319,7 @@ class MetaAggregate(type, Generic[TAggregate]):
1286
1319
 
1287
1320
  def _create(
1288
1321
  cls: MetaAggregate[TAggregate],
1289
- event_class: Type[CanInitAggregate],
1322
+ event_class: type[CanInitAggregate],
1290
1323
  **kwargs: Any,
1291
1324
  ) -> TAggregate:
1292
1325
  raise NotImplementedError # pragma: no cover
@@ -1308,8 +1341,8 @@ class Aggregate(metaclass=MetaAggregate):
1308
1341
 
1309
1342
  @classmethod
1310
1343
  def _create(
1311
- cls: Type[TAggregate],
1312
- event_class: Type[CanInitAggregate],
1344
+ cls: type[TAggregate],
1345
+ event_class: type[CanInitAggregate],
1313
1346
  *,
1314
1347
  id: UUID | None = None, # noqa: A002
1315
1348
  **kwargs: Any,
@@ -1359,7 +1392,7 @@ class Aggregate(metaclass=MetaAggregate):
1359
1392
  self._version = originator_version
1360
1393
  self._created_on = timestamp
1361
1394
  self._modified_on = timestamp
1362
- self._pending_events: List[CanMutateAggregate] = []
1395
+ self._pending_events: list[CanMutateAggregate] = []
1363
1396
 
1364
1397
  @property
1365
1398
  def id(self) -> UUID:
@@ -1398,7 +1431,7 @@ class Aggregate(metaclass=MetaAggregate):
1398
1431
  self._modified_on = modified_on
1399
1432
 
1400
1433
  @property
1401
- def pending_events(self) -> List[CanMutateAggregate]:
1434
+ def pending_events(self) -> list[CanMutateAggregate]:
1402
1435
  """
1403
1436
  A list of pending events.
1404
1437
  """
@@ -1423,7 +1456,7 @@ class Aggregate(metaclass=MetaAggregate):
1423
1456
 
1424
1457
  def trigger_event(
1425
1458
  self,
1426
- event_class: Type[CanMutateAggregate],
1459
+ event_class: type[CanMutateAggregate],
1427
1460
  **kwargs: Any,
1428
1461
  ) -> None:
1429
1462
  """
@@ -1480,7 +1513,7 @@ def aggregate(
1480
1513
  cls: Any | None = None,
1481
1514
  *,
1482
1515
  created_event_name: str = "",
1483
- ) -> Type[Aggregate] | Callable[[Any], Type[Aggregate]]:
1516
+ ) -> type[Aggregate] | Callable[[Any], type[Aggregate]]:
1484
1517
  """
1485
1518
  Converts the class that was passed in to inherit from Aggregate.
1486
1519
 
@@ -1498,7 +1531,7 @@ def aggregate(
1498
1531
  pass
1499
1532
  """
1500
1533
 
1501
- def decorator(cls_: Any) -> Type[Aggregate]:
1534
+ def decorator(cls_: Any) -> type[Aggregate]:
1502
1535
  if issubclass(cls_, Aggregate):
1503
1536
  msg = f"{cls_.__qualname__} is already an Aggregate"
1504
1537
  raise TypeError(msg)
@@ -1553,7 +1586,7 @@ class VersionError(OriginatorVersionError):
1553
1586
 
1554
1587
  class SnapshotProtocol(DomainEventProtocol, Protocol):
1555
1588
  @property
1556
- def state(self) -> Dict[str, Any]:
1589
+ def state(self) -> dict[str, Any]:
1557
1590
  """
1558
1591
  Snapshots have a read-only 'state'.
1559
1592
  """
@@ -1575,7 +1608,7 @@ class CanSnapshotAggregate(HasOriginatorIDVersion, CanCreateTimestamp):
1575
1608
 
1576
1609
  @classmethod
1577
1610
  def take(
1578
- cls: Type[TCanSnapshotAggregate],
1611
+ cls: type[TCanSnapshotAggregate],
1579
1612
  aggregate: MutableOrImmutableAggregate,
1580
1613
  ) -> TCanSnapshotAggregate:
1581
1614
  """
@@ -1601,7 +1634,7 @@ class CanSnapshotAggregate(HasOriginatorIDVersion, CanCreateTimestamp):
1601
1634
  """
1602
1635
  Reconstructs the snapshotted :class:`Aggregate` object.
1603
1636
  """
1604
- cls = cast(Type[Aggregate], resolve_topic(self.topic))
1637
+ cls = cast(type[Aggregate], resolve_topic(self.topic))
1605
1638
  aggregate_state = dict(self.state)
1606
1639
  from_version = aggregate_state.pop("class_version", 1)
1607
1640
  class_version = getattr(cls, "class_version", 1)
@@ -1634,4 +1667,4 @@ class Snapshot(CanSnapshotAggregate, DomainEvent):
1634
1667
  """
1635
1668
 
1636
1669
  topic: str
1637
- state: Dict[str, Any]
1670
+ state: dict[str, Any]
@@ -3,12 +3,15 @@ from __future__ import annotations
3
3
  import json
4
4
  from abc import ABC, abstractmethod
5
5
  from base64 import b64decode, b64encode
6
- from typing import Generic, List, Sequence
6
+ from typing import TYPE_CHECKING, Generic
7
7
  from uuid import UUID
8
8
 
9
9
  from eventsourcing.application import NotificationLog, Section, TApplication
10
10
  from eventsourcing.persistence import Notification
11
11
 
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Sequence
14
+
12
15
 
13
16
  class NotificationLogInterface(ABC):
14
17
  """
@@ -142,7 +145,7 @@ class NotificationLogJSONClient(NotificationLog):
142
145
  topics: Sequence[str] = (),
143
146
  *,
144
147
  inclusive_of_start: bool = True,
145
- ) -> List[Notification]:
148
+ ) -> list[Notification]:
146
149
  """
147
150
  Returns a selection of
148
151
  :class:`~eventsourcing.persistence.Notification` objects