eventsourcing 9.3.0a1__py3-none-any.whl → 9.3.0b1__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.

eventsourcing/domain.py CHANGED
@@ -941,6 +941,7 @@ class MetaAggregate(type, Generic[TAggregate]):
941
941
  setattr(cls, base_event_name, base_event_cls)
942
942
 
943
943
  # Make sure all events defined on aggregate subclass the base event class.
944
+ created_event_classes: Dict[str, Type[CanInitAggregate]] = {}
944
945
  for name, value in tuple(cls.__dict__.items()):
945
946
  if name == base_event_name:
946
947
  # Don't subclass the base event class again.
@@ -955,31 +956,20 @@ class MetaAggregate(type, Generic[TAggregate]):
955
956
  ):
956
957
  sub_class = cls._define_event_class(name, (value, base_event_cls), None)
957
958
  setattr(cls, name, sub_class)
958
-
959
- # Identify or define the aggregate's "created" event class.
960
- created_event_class: Type[CanInitAggregate] | None = None
961
-
962
- # Has the "created" event class been indicated with '_created_event_class'.
963
- if "_created_event_class" in cls.__dict__:
964
- created_event_class = cls.__dict__["_created_event_class"]
965
- if isinstance(created_event_class, type) and issubclass(
966
- created_event_class, CanInitAggregate
967
- ):
968
- # We just subclassed the event classes, so reassign this.
969
- created_event_class = getattr(cls, created_event_class.__name__)
970
- assert created_event_class
971
- cls._created_event_class = created_event_class
972
- else:
973
- msg = (
974
- f"{created_event_class} not subclass of {CanInitAggregate.__name__}"
975
- )
976
- raise TypeError(msg)
959
+ for name, value in tuple(cls.__dict__.items()):
960
+ if isinstance(value, type) and issubclass(value, CanInitAggregate):
961
+ created_event_classes[name] = value
977
962
 
978
963
  # Disallow using both '_created_event_class' and 'created_event_name'.
964
+ created_event_class: Type[CanInitAggregate] | None = cls.__dict__.get(
965
+ "_created_event_class"
966
+ )
979
967
  if created_event_class and created_event_name:
980
968
  msg = "Can't use both '_created_event_class' and 'created_event_name'"
981
969
  raise TypeError(msg)
982
970
 
971
+ # Identify or define the aggregate's "created" event class.
972
+
983
973
  # Is the init method decorated with a CommandMethodDecorator?
984
974
  if isinstance(cls.__dict__.get("__init__"), CommandMethodDecorator):
985
975
  init_decorator: CommandMethodDecorator = cls.__dict__["__init__"]
@@ -987,31 +977,20 @@ class MetaAggregate(type, Generic[TAggregate]):
987
977
  # Set the original method on the class (un-decorate __init__).
988
978
  cls.__init__ = init_decorator.decorated_method # type: ignore
989
979
 
990
- # Disallow using both 'created_event_name' and '_created_event_class'.
980
+ # Disallow using both 'created_event_name' and decorator on __init__.
991
981
  if created_event_name:
992
982
  msg = "Can't use both 'created_event_name' and decorator on __init__"
993
983
  raise TypeError(msg)
984
+ # Disallow using both '_created_event_class' and decorator on __init__.
994
985
  if created_event_class:
995
986
  msg = "Can't use both '_created_event_class' and decorator on __init__"
996
987
  raise TypeError(msg)
997
988
 
998
- # Does the decorator specify a "create" event class?
989
+ # Does the decorator specify a "created" event class?
999
990
  if init_decorator.given_event_cls:
1000
- created_event_class = getattr(
1001
- cls, init_decorator.given_event_cls.__name__
991
+ created_event_class = cast(
992
+ Type[CanInitAggregate], init_decorator.given_event_cls
1002
993
  )
1003
- if isinstance(created_event_class, type) and issubclass(
1004
- created_event_class, CanInitAggregate
1005
- ):
1006
- assert created_event_class
1007
- cls._created_event_class = created_event_class
1008
- else:
1009
- msg = (
1010
- f"{created_event_class} not subclass of "
1011
- f"{CanInitAggregate.__name__}"
1012
- )
1013
- raise TypeError(msg)
1014
-
1015
994
  # Does the decorator specify a "created" event name?
1016
995
  elif init_decorator.event_cls_name:
1017
996
  created_event_name = init_decorator.event_cls_name
@@ -1028,65 +1007,85 @@ class MetaAggregate(type, Generic[TAggregate]):
1028
1007
  _init_mentions_id.add(cls)
1029
1008
  break
1030
1009
 
1031
- # If no "created" event class has been specified, find or create one.
1032
- if created_event_class is None:
1033
- # Discover all the "created" event classes already defined.
1034
- created_event_classes: Dict[str, Type[AggregateCreated]] = {}
1035
- for name, value in tuple(cls.__dict__.items()):
1036
- if isinstance(value, type) and issubclass(value, AggregateCreated):
1037
- created_event_classes[name] = value
1038
-
1039
- # Is a "created" event class already defined that matches the name?
1040
- if created_event_name in created_event_classes:
1041
- cls._created_event_class = created_event_classes[created_event_name]
1042
-
1043
- # If there is only one class defined, and we have no name, use it.
1044
- elif len(created_event_classes) == 1 and not created_event_name:
1045
- cls._created_event_class = next(iter(created_event_classes.values()))
1046
-
1047
- # If there are no "created" event classes already defined, or a name is
1048
- # specified that hasn't matched, then define a "created" event class.
1049
- elif len(created_event_classes) == 0 or created_event_name:
1050
- # If no "created" event name has been specified, use default name.
1051
- if not created_event_name:
1052
- # This is safe because len(created_event_classes) == 0.
1053
- created_event_name = "Created"
1054
-
1055
- # Disallow init method from having variable params if
1056
- # we are using it to define a "created" event class.
1010
+ if created_event_class:
1011
+ # Check specified "created" event class can init aggregate.
1012
+ if not issubclass(created_event_class, CanInitAggregate):
1013
+ msg = (
1014
+ f"{created_event_class} not subclass of {CanInitAggregate.__name__}"
1015
+ )
1016
+ raise TypeError(msg)
1017
+
1018
+ for sub_class in created_event_classes.values():
1019
+ if issubclass(sub_class, created_event_class):
1020
+ # We just subclassed the created event class, so reassign it.
1021
+ created_event_class = sub_class
1022
+
1023
+ # Is a "created" event class already defined that matches the name?
1024
+ elif created_event_name and created_event_name in created_event_classes:
1025
+ created_event_class = created_event_classes[created_event_name]
1026
+
1027
+ # If there is only one class defined, then use it.
1028
+ elif len(created_event_classes) == 1 and not created_event_name:
1029
+ created_event_class = next(iter(created_event_classes.values()))
1030
+
1031
+ # If there are no "created" event classes already defined, or a name is
1032
+ # specified that hasn't matched, then define a "created" event class.
1033
+ elif len(created_event_classes) == 0 or created_event_name:
1034
+
1035
+ # Decide the base classes for the new "created" event class.
1036
+ if created_event_name and len(created_event_classes) == 1:
1037
+ base_created_event_cls = next(iter(created_event_classes.values()))
1038
+ else:
1039
+ for base_cls in cls.__mro__:
1040
+ if base_cls is cls:
1041
+ continue
1042
+ base_created_event_cls = base_cls.__dict__.get(
1043
+ "_created_event_class",
1044
+ base_cls.__dict__.get("Created"),
1045
+ )
1046
+ if base_created_event_cls:
1047
+ break
1048
+ else: # pragma: no cover
1049
+ msg = "Can't decide base class for new 'created' event class"
1050
+ raise TypeError(msg)
1051
+
1052
+ if not created_event_name:
1053
+ created_event_name = base_created_event_cls.__name__
1054
+
1055
+ # Disallow init method from having variable params if
1056
+ # we are using it to define a "created" event class.
1057
+ try:
1058
+ init_method = cls.__dict__["__init__"]
1059
+ except KeyError:
1060
+ init_method = None
1061
+ else:
1057
1062
  try:
1058
- init_method = cls.__dict__["__init__"]
1059
- except KeyError:
1060
- init_method = None
1061
- else:
1062
- try:
1063
- _check_no_variable_params(init_method)
1064
- except TypeError:
1065
- raise
1066
-
1067
- # Define a "created" event class for this aggregate.
1068
- if issubclass(cls.Created, base_event_cls):
1069
- # Don't subclass from base event class twice.
1070
- bases: Tuple[Type[CanMutateAggregate], ...] = (cls.Created,)
1071
- else:
1072
- bases = (cls.Created, base_event_cls)
1073
- event_cls = cls._define_event_class(
1063
+ _check_no_variable_params(init_method)
1064
+ except TypeError:
1065
+ raise
1066
+
1067
+ # Define a "created" event class for this aggregate.
1068
+ if issubclass(base_created_event_cls, base_event_cls):
1069
+ # Don't subclass from base event class twice.
1070
+ bases: Tuple[Type[CanMutateAggregate], ...] = (base_created_event_cls,)
1071
+ else:
1072
+ bases = (base_created_event_cls, base_event_cls)
1073
+ created_event_class = cast(
1074
+ Type[CanInitAggregate],
1075
+ cls._define_event_class(
1074
1076
  created_event_name,
1075
1077
  bases,
1076
1078
  init_method,
1077
- )
1078
-
1079
- # Set the event class as an attribute of the aggregate class.
1080
- setattr(cls, created_event_name, event_cls)
1081
-
1082
- # Remember which is the "created" event class.
1083
- cls._created_event_class = cast(Type[AggregateCreated], event_cls)
1079
+ ),
1080
+ )
1081
+ # Set the event class as an attribute of the aggregate class.
1082
+ setattr(cls, created_event_name, created_event_class)
1084
1083
 
1084
+ if created_event_class:
1085
+ cls._created_event_class = created_event_class
1086
+ else:
1085
1087
  # Prepare to disallow ambiguity of choice between created event classes.
1086
- else:
1087
- aggregate_has_many_created_event_classes[cls] = list(
1088
- created_event_classes
1089
- )
1088
+ aggregate_has_many_created_event_classes[cls] = list(created_event_classes)
1090
1089
 
1091
1090
  # Prepare the subsequent event classes.
1092
1091
  for attr_name, attr_value in tuple(cls.__dict__.items()):
@@ -730,6 +730,7 @@ class TestAggregateCreation(TestCase):
730
730
  order = Order("name")
731
731
  pending = order.collect_events()
732
732
  self.assertEqual(type(pending[0]).__name__, "Started")
733
+ self.assertTrue(isinstance(pending[0], Order.Created))
733
734
 
734
735
  def test_raises_when_given_created_event_name_conflicts_with_created_event_class(
735
736
  self,
@@ -1098,6 +1099,19 @@ class TestAggregateEventsAreSubclassed(TestCase):
1098
1099
  MySubclass.Ended.__qualname__,
1099
1100
  )
1100
1101
 
1102
+ self.assertTrue(
1103
+ MySubclass._created_event_class.__qualname__.endswith("MySubclass.Opened")
1104
+ )
1105
+
1106
+ class MySubSubClass(MySubclass):
1107
+ pass
1108
+
1109
+ self.assertTrue(
1110
+ MySubSubClass._created_event_class.__qualname__.endswith(
1111
+ "MySubSubClass.Opened"
1112
+ )
1113
+ )
1114
+
1101
1115
 
1102
1116
  class TestBankAccount(TestCase):
1103
1117
  def test_subclass_bank_account(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eventsourcing
3
- Version: 9.3.0a1
3
+ Version: 9.3.0b1
4
4
  Summary: Event sourcing in Python
5
5
  Home-page: https://github.com/pyeventsourcing/eventsourcing
6
6
  License: BSD 3-Clause
@@ -8,7 +8,7 @@ Keywords: event sourcing,event store,domain driven design,domain-driven design,d
8
8
  Author: John Bywater
9
9
  Author-email: john.bywater@appropriatesoftware.net
10
10
  Requires-Python: >=3.8,<4.0
11
- Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: Intended Audience :: Education
14
14
  Classifier: Intended Audience :: Science/Research
@@ -3,7 +3,7 @@ eventsourcing/application.py,sha256=ZTsk-qTieT13Jesf44Xh6htF8Y_CP753bmdoDOKSVW4,
3
3
  eventsourcing/cipher.py,sha256=NJcVfZdSlCER6xryM4zVoY3cmKstF-iSSniB4jmpaKg,3200
4
4
  eventsourcing/compressor.py,sha256=IdvrJUB9B2td871oifInv4lGXmHwYL9d69MbHHCr7uI,421
5
5
  eventsourcing/dispatch.py,sha256=yYSpT-jqc6l_wTdqEnfPJJfvsZN2Ta8g2anrVPWIcqQ,1412
6
- eventsourcing/domain.py,sha256=YpPUSiJBRL3QRz_49X5KMaKa0bybDbdeMXen_mlntwE,57442
6
+ eventsourcing/domain.py,sha256=rvm4Sv2MmLcha8_5wqJ13AjmqyWvuzkquYsexUaePIg,57264
7
7
  eventsourcing/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  eventsourcing/examples/aggregate1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  eventsourcing/examples/aggregate1/application.py,sha256=LPle9YoAu85EQFrp-lUk0I8DKuSdQOSUyJ__38JHSvE,766
@@ -114,7 +114,7 @@ eventsourcing/tests/docs_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
114
114
  eventsourcing/tests/docs_tests/test_docs.py,sha256=Yt--RMe_tcG9zERBJmaAVkZ0qgMWnlgbFzRPktRUVGk,10777
115
115
  eventsourcing/tests/domain.py,sha256=lHSlY6jIoSeqlcPSbrrozEPUJGvJ8bgPrznlmzTxn2w,3254
116
116
  eventsourcing/tests/domain_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
- eventsourcing/tests/domain_tests/test_aggregate.py,sha256=Ps1XCJo3nYr1vvOSQvhSNJwRPwbUC4CPz_Ripq8hJZ8,37851
117
+ eventsourcing/tests/domain_tests/test_aggregate.py,sha256=tH61bA69MzNF9VVt5USayWoB8tZ2lnLIaqyE5MTEgUI,38255
118
118
  eventsourcing/tests/domain_tests/test_aggregate_decorators.py,sha256=zky6jmqblM0GKgdhCJjYdSxtEE9MwRcemYaZhqxL1AE,50256
119
119
  eventsourcing/tests/domain_tests/test_domainevent.py,sha256=3EGLKnla1aWfKPzMfLCNmh7UtVAztk_ne_Oi0cP7jPU,2782
120
120
  eventsourcing/tests/interface_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -138,7 +138,7 @@ eventsourcing/tests/system_tests/test_system.py,sha256=xi-nCPTWeB5Rqasyn4-rP213F
138
138
  eventsourcing/tests/utils_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
139
  eventsourcing/tests/utils_tests/test_utils.py,sha256=8HcTk_0_lXyoT307fEmd2utwmOUS_joToUPGFeFnKW8,6486
140
140
  eventsourcing/utils.py,sha256=PIWDvoGiKCXsNbR5DirkoJ_svopg80SoH37bqxOcjkU,8247
141
- eventsourcing-9.3.0a1.dist-info/LICENSE,sha256=bSE_F-T6cQPmMY5LuJC27km_pGB1XCVuUFx1uY0Nueg,1512
142
- eventsourcing-9.3.0a1.dist-info/METADATA,sha256=pCAGpXV2lgzexep06p9k0Ca3IEQuDSFnopDhhNjb47A,9891
143
- eventsourcing-9.3.0a1.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
144
- eventsourcing-9.3.0a1.dist-info/RECORD,,
141
+ eventsourcing-9.3.0b1.dist-info/LICENSE,sha256=bSE_F-T6cQPmMY5LuJC27km_pGB1XCVuUFx1uY0Nueg,1512
142
+ eventsourcing-9.3.0b1.dist-info/METADATA,sha256=bNaX2a3mE4_9aGXlStw7M2EK_VijO5w8Z-GdTe4Rmmg,9890
143
+ eventsourcing-9.3.0b1.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
144
+ eventsourcing-9.3.0b1.dist-info/RECORD,,