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.

@@ -5,19 +5,19 @@ import sys
5
5
  import traceback
6
6
  import warnings
7
7
  from concurrent.futures import ThreadPoolExecutor
8
- from datetime import datetime
9
8
  from decimal import Decimal
10
9
  from threading import Event, get_ident
11
10
  from time import sleep
12
11
  from timeit import timeit
13
- from typing import Any, ClassVar
12
+ from typing import TYPE_CHECKING, Any, ClassVar
14
13
  from unittest import TestCase
15
14
  from uuid import UUID, uuid4
16
15
 
17
16
  from eventsourcing.application import AggregateNotFoundError, Application
18
- from eventsourcing.domain import Aggregate
17
+ from eventsourcing.domain import Aggregate, datetime_now_with_tzinfo
19
18
  from eventsourcing.persistence import (
20
19
  InfrastructureFactory,
20
+ InfrastructureFactoryError,
21
21
  IntegrityError,
22
22
  JSONTranscoder,
23
23
  Transcoding,
@@ -25,7 +25,10 @@ from eventsourcing.persistence import (
25
25
  from eventsourcing.tests.domain import BankAccount, EmailAddress
26
26
  from eventsourcing.utils import EnvType, get_topic
27
27
 
28
- TIMEIT_FACTOR = int(os.environ.get("TEST_TIMEIT_FACTOR", default=10))
28
+ if TYPE_CHECKING:
29
+ from datetime import datetime
30
+
31
+ TIMEIT_FACTOR = int(os.environ.get("TEST_TIMEIT_FACTOR", default="10"))
29
32
 
30
33
 
31
34
  class ExampleApplicationTestCase(TestCase):
@@ -163,7 +166,7 @@ class ExampleApplicationTestCase(TestCase):
163
166
  def print_time(self, test_label: str, duration: float) -> None:
164
167
  cls = type(self)
165
168
  if cls not in self.started_ats:
166
- self.started_ats[cls] = datetime.now()
169
+ self.started_ats[cls] = datetime_now_with_tzinfo()
167
170
  print(f"{cls.__name__: <29} timeit number: {cls.timeit_number}")
168
171
  self.counts[cls] = 1
169
172
  else:
@@ -178,7 +181,7 @@ class ExampleApplicationTestCase(TestCase):
178
181
  )
179
182
 
180
183
  if self.counts[cls] == 3:
181
- cls_duration = datetime.now() - cls.started_ats[cls]
184
+ cls_duration = datetime_now_with_tzinfo() - cls.started_ats[cls]
182
185
  print(f"{cls.__name__: <29} timeit duration: {cls_duration}")
183
186
  sys.stdout.flush()
184
187
 
@@ -263,7 +266,7 @@ class ApplicationTestCase(TestCase):
263
266
  self.assertIsInstance(app.factory, InfrastructureFactory)
264
267
 
265
268
  # Check exceptions.
266
- with self.assertRaises(AssertionError) as cm:
269
+ with self.assertRaises(InfrastructureFactoryError) as cm:
267
270
  Application(env={"PERSISTENCE_MODULE": "eventsourcing.application"})
268
271
  self.assertEqual(
269
272
  cm.exception.args[0],
@@ -271,14 +274,15 @@ class ApplicationTestCase(TestCase):
271
274
  "'eventsourcing.application', expected 1.",
272
275
  )
273
276
 
274
- with self.assertRaises(AssertionError) as cm:
277
+ with self.assertRaises(InfrastructureFactoryError) as cm:
275
278
  Application(
276
279
  env={"PERSISTENCE_MODULE": "eventsourcing.application:Application"}
277
280
  )
278
281
  self.assertEqual(
282
+ "Topic 'eventsourcing.application:Application' didn't "
283
+ "resolve to a persistence module or infrastructure factory class: "
284
+ "<class 'eventsourcing.application.Application'>",
279
285
  cm.exception.args[0],
280
- "Not an infrastructure factory class or module: "
281
- "eventsourcing.application:Application",
282
286
  )
283
287
 
284
288
  def test_save_returns_recording_event(self) -> None:
@@ -14,9 +14,7 @@ class EmailAddress:
14
14
 
15
15
 
16
16
  class BankAccount(Aggregate):
17
- """
18
- Aggregate root for bank accounts.
19
- """
17
+ """Aggregate root for bank accounts."""
20
18
 
21
19
  def __init__(self, full_name: str, email_address: EmailAddress):
22
20
  self.full_name = full_name
@@ -27,9 +25,7 @@ class BankAccount(Aggregate):
27
25
 
28
26
  @classmethod
29
27
  def open(cls, full_name: str, email_address: str) -> BankAccount:
30
- """
31
- Creates new bank account object.
32
- """
28
+ """Creates new bank account object."""
33
29
  return cls._create(
34
30
  cls.Opened,
35
31
  id=uuid4(),
@@ -42,9 +38,7 @@ class BankAccount(Aggregate):
42
38
  email_address: str
43
39
 
44
40
  def append_transaction(self, amount: Decimal) -> None:
45
- """
46
- Appends given amount as transaction on account.
47
- """
41
+ """Appends given amount as transaction on account."""
48
42
  self.check_account_is_not_closed()
49
43
  self.check_has_sufficient_funds(amount)
50
44
  self.trigger_event(
@@ -62,23 +56,18 @@ class BankAccount(Aggregate):
62
56
 
63
57
  @dataclass(frozen=True)
64
58
  class TransactionAppended(AggregateEvent):
65
- """
66
- Domain event for when transaction
59
+ """Domain event for when transaction
67
60
  is appended to bank account.
68
61
  """
69
62
 
70
63
  amount: Decimal
71
64
 
72
65
  def apply(self, aggregate: Aggregate) -> None:
73
- """
74
- Increments the account balance.
75
- """
76
- cast(BankAccount, aggregate).balance += self.amount
66
+ """Increments the account balance."""
67
+ cast("BankAccount", aggregate).balance += self.amount
77
68
 
78
69
  def set_overdraft_limit(self, overdraft_limit: Decimal) -> None:
79
- """
80
- Sets the overdraft limit.
81
- """
70
+ """Sets the overdraft limit."""
82
71
  # Check the limit is not a negative value.
83
72
  assert overdraft_limit >= Decimal("0.00")
84
73
  self.check_account_is_not_closed()
@@ -88,38 +77,29 @@ class BankAccount(Aggregate):
88
77
  )
89
78
 
90
79
  class OverdraftLimitSet(AggregateEvent):
91
- """
92
- Domain event for when overdraft
80
+ """Domain event for when overdraft
93
81
  limit is set.
94
82
  """
95
83
 
96
84
  overdraft_limit: Decimal
97
85
 
98
86
  def apply(self, aggregate: Aggregate) -> None:
99
- cast(BankAccount, aggregate).overdraft_limit = self.overdraft_limit
87
+ cast("BankAccount", aggregate).overdraft_limit = self.overdraft_limit
100
88
 
101
89
  def close(self) -> None:
102
- """
103
- Closes the bank account.
104
- """
90
+ """Closes the bank account."""
105
91
  self.trigger_event(self.Closed)
106
92
 
107
93
  class Closed(AggregateEvent):
108
- """
109
- Domain event for when account is closed.
110
- """
94
+ """Domain event for when account is closed."""
111
95
 
112
96
  def apply(self, aggregate: Aggregate) -> None:
113
- cast(BankAccount, aggregate).is_closed = True
97
+ cast("BankAccount", aggregate).is_closed = True
114
98
 
115
99
 
116
100
  class AccountClosedError(Exception):
117
- """
118
- Raised when attempting to operate a closed account.
119
- """
101
+ """Raised when attempting to operate a closed account."""
120
102
 
121
103
 
122
104
  class InsufficientFundsError(Exception):
123
- """
124
- Raised when attempting to go past overdraft limit.
125
- """
105
+ """Raised when attempting to go past overdraft limit."""
@@ -1,11 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
- import os
4
3
  import traceback
5
4
  import zlib
6
5
  from abc import ABC, abstractmethod
7
6
  from concurrent.futures import ThreadPoolExecutor
8
- from datetime import datetime
7
+ from pathlib import Path
9
8
  from tempfile import NamedTemporaryFile
10
9
  from threading import Event, Thread, get_ident
11
10
  from time import sleep
@@ -18,7 +17,7 @@ from typing_extensions import TypeVar
18
17
 
19
18
  from eventsourcing.cipher import AESCipher
20
19
  from eventsourcing.compressor import ZlibCompressor
21
- from eventsourcing.domain import DomainEvent
20
+ from eventsourcing.domain import DomainEvent, datetime_now_with_tzinfo
22
21
  from eventsourcing.persistence import (
23
22
  AggregateRecorder,
24
23
  ApplicationRecorder,
@@ -476,7 +475,7 @@ class ApplicationRecorderTestCase(TestCase, ABC, Generic[_TApplicationRecorder])
476
475
  )
477
476
  for i in range(num_events_per_write)
478
477
  ]
479
- started = datetime.now()
478
+ started = datetime_now_with_tzinfo()
480
479
  # print(f"Thread {thread_num} write beginning #{count + 1}")
481
480
  try:
482
481
  recorder.insert_events(stored_events)
@@ -484,16 +483,15 @@ class ApplicationRecorderTestCase(TestCase, ABC, Generic[_TApplicationRecorder])
484
483
  except Exception as e: # pragma: no cover
485
484
  if errors:
486
485
  return
487
- ended = datetime.now()
486
+ ended = datetime_now_with_tzinfo()
488
487
  duration = (ended - started).total_seconds()
489
488
  print(f"Error after starting {duration}", e)
490
489
  errors.append(e)
491
490
  else:
492
- ended = datetime.now()
491
+ ended = datetime_now_with_tzinfo()
493
492
  duration = (ended - started).total_seconds()
494
493
  counts[thread_id] += 1
495
- if duration > durations[thread_id]:
496
- durations[thread_id] = duration
494
+ durations[thread_id] = max(durations[thread_id], duration)
497
495
  sleep(writer_sleep)
498
496
 
499
497
  stop_reading = Event()
@@ -584,7 +582,7 @@ class ApplicationRecorderTestCase(TestCase, ABC, Generic[_TApplicationRecorder])
584
582
 
585
583
  # Run.
586
584
  with ThreadPoolExecutor(max_workers=num_workers) as executor:
587
- started = datetime.now()
585
+ started = datetime_now_with_tzinfo()
588
586
  futures = []
589
587
  for _ in range(num_jobs):
590
588
  future = executor.submit(insert_events)
@@ -593,7 +591,7 @@ class ApplicationRecorderTestCase(TestCase, ABC, Generic[_TApplicationRecorder])
593
591
  future.result()
594
592
 
595
593
  self.assertFalse(errors_happened.is_set(), "There were errors (see above)")
596
- ended = datetime.now()
594
+ ended = datetime_now_with_tzinfo()
597
595
  rate = num_jobs * num_events_per_job / (ended - started).total_seconds()
598
596
  print(f"Rate: {rate:.0f} inserts per second")
599
597
 
@@ -1099,7 +1097,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase, Generic[_TInfrastrutureFactor
1099
1097
 
1100
1098
  def setUp(self) -> None:
1101
1099
  self.factory = cast(
1102
- _TInfrastrutureFactory, InfrastructureFactory.construct(self.env)
1100
+ "_TInfrastrutureFactory", InfrastructureFactory.construct(self.env)
1103
1101
  )
1104
1102
  self.assertIsInstance(self.factory, self.expected_factory_class())
1105
1103
  self.transcoder = JSONTranscoder()
@@ -1279,14 +1277,17 @@ class InfrastructureFactoryTestCase(ABC, TestCase, Generic[_TInfrastrutureFactor
1279
1277
 
1280
1278
  def tmpfile_uris() -> Iterator[str]:
1281
1279
  tmp_files = []
1282
- ram_disk_path = "/Volumes/RAM DISK/"
1283
- prefix = None
1284
- if os.path.exists(ram_disk_path):
1285
- prefix = ram_disk_path
1280
+ ram_disk_path = Path("/Volumes/RAM DISK/")
1281
+ prefix: str | None = None
1282
+ if ram_disk_path.exists():
1283
+ prefix = str(ram_disk_path)
1286
1284
  while True:
1287
- tmp_file = NamedTemporaryFile(prefix=prefix, suffix="_eventsourcing_test.db")
1288
- tmp_files.append(tmp_file)
1289
- yield "file:" + tmp_file.name
1285
+ with NamedTemporaryFile(
1286
+ prefix=prefix,
1287
+ suffix="_eventsourcing_test.db",
1288
+ ) as tmp_file:
1289
+ tmp_files.append(tmp_file)
1290
+ yield "file:" + tmp_file.name
1290
1291
 
1291
1292
 
1292
1293
  class CustomType1:
@@ -1329,6 +1330,8 @@ class MyList(list[_T]):
1329
1330
 
1330
1331
 
1331
1332
  class MyStr(str):
1333
+ __slots__ = ()
1334
+
1332
1335
  def __repr__(self) -> str:
1333
1336
  return f"{type(self).__name__}({super().__repr__()})"
1334
1337
 
eventsourcing/utils.py CHANGED
@@ -16,9 +16,7 @@ if TYPE_CHECKING:
16
16
 
17
17
 
18
18
  class TopicError(Exception):
19
- """
20
- Raised when topic doesn't resolve.
21
- """
19
+ """Raised when topic doesn't resolve."""
22
20
 
23
21
 
24
22
  SupportsTopic = Union[type, Callable[..., Any], ModuleType]
@@ -29,8 +27,7 @@ _topic_cache_lock = Lock()
29
27
 
30
28
 
31
29
  def get_topic(obj: SupportsTopic, /) -> str:
32
- """
33
- Returns a "topic string" that locates the given class
30
+ """Returns a "topic string" that locates the given class
34
31
  in its module. The string is formed by joining the
35
32
  module name and the class qualname separated by the
36
33
  colon character.
@@ -45,8 +42,7 @@ def get_topic(obj: SupportsTopic, /) -> str:
45
42
 
46
43
 
47
44
  def resolve_topic(topic: str) -> Any:
48
- """
49
- Returns an object located by the given topic.
45
+ """Returns an object located by the given topic.
50
46
 
51
47
  This function can be (is) used to locate domain
52
48
  event classes and aggregate classes from the
@@ -101,8 +97,7 @@ def resolve_topic(topic: str) -> Any:
101
97
 
102
98
 
103
99
  def register_topic(topic: str, obj: SupportsTopic) -> None:
104
- """
105
- Registers a topic with an object, so the object will be
100
+ """Registers a topic with an object, so the object will be
106
101
  returned whenever the topic is resolved.
107
102
 
108
103
  This function can be used to cache the topic of a class, so
@@ -134,8 +129,7 @@ def retry(
134
129
  wait: float = 0,
135
130
  stall: float = 0,
136
131
  ) -> Callable[[Any], Any]:
137
- """
138
- Retry decorator.
132
+ """Retry decorator.
139
133
 
140
134
  :param exc: List of exceptions that will cause the call to be retried if raised.
141
135
  :param max_attempts: Maximum number of attempts to try.
@@ -145,9 +139,9 @@ def retry(
145
139
  """
146
140
 
147
141
  @no_type_check
148
- def _retry(func):
142
+ def _retry(func: Callable) -> Callable:
149
143
  @wraps(func)
150
- def retry_decorator(*args, **kwargs):
144
+ def retry_decorator(*args: Any, **kwargs: Any) -> Any:
151
145
  if stall:
152
146
  sleep(stall)
153
147
  attempts = 0
@@ -236,16 +230,16 @@ class Environment(dict[str, str]):
236
230
  self.name = name
237
231
 
238
232
  @overload # type: ignore[override]
239
- def get(self, __key: str) -> str | None: ... # pragma: no cover
233
+ def get(self, __key: str, /) -> str | None: ... # pragma: no cover
240
234
 
241
235
  @overload
242
- def get(self, __key: str, __default: str) -> str: ... # pragma: no cover
236
+ def get(self, __key: str, /, __default: str) -> str: ... # pragma: no cover
243
237
 
244
238
  @overload
245
- def get(self, __key: str, __default: T) -> str | T: ... # pragma: no cover
239
+ def get(self, __key: str, /, __default: T) -> str | T: ... # pragma: no cover
246
240
 
247
241
  def get( # pyright: ignore [reportIncompatibleMethodOverride]
248
- self, __key: str, __default: str | T | None = None
242
+ self, __key: str, /, __default: str | T | None = None
249
243
  ) -> str | T | None:
250
244
  for _key in self.create_keys(__key):
251
245
  value = super().get(_key, None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: eventsourcing
3
- Version: 9.4.0b2
3
+ Version: 9.4.0b3
4
4
  Summary: Event sourcing in Python
5
5
  License: BSD 3-Clause
6
6
  Keywords: event sourcing,event store,domain driven design,domain-driven design,ddd,cqrs,cqs
@@ -0,0 +1,26 @@
1
+ eventsourcing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ eventsourcing/application.py,sha256=K3M9_Rh2jaYzBDPMvmyemLXHQ4GsGfGsxmMfUeVSqXw,35507
3
+ eventsourcing/cipher.py,sha256=ulTBtX5K9ejRAkdUaUbdIaj4H7anYwDOi7JxOolj2uo,3295
4
+ eventsourcing/compressor.py,sha256=qEYWvsUXFLyhKgfuv-HGNJ6VF4sRw4z0IxbNW9ukOfc,385
5
+ eventsourcing/cryptography.py,sha256=aFZLlJxxSb5seVbh94-T8FA_RIGOe-VFu5SJrbOnwUU,2969
6
+ eventsourcing/dispatch.py,sha256=j03cIVPziq6LFEgJxvQMMIPlixuZ4bB8ynXXdd_Tj8Q,2740
7
+ eventsourcing/domain.py,sha256=Vk7MvA7GsY3krFBcotIxuMoDxYkBPP-EMnEIOj-JTU8,60062
8
+ eventsourcing/interface.py,sha256=-VLoqcd9a0PXpD_Bv0LjCiG21xLREG6tXK6phgtShOw,5035
9
+ eventsourcing/persistence.py,sha256=y_1o3LNi9tkOTqkvjgsGF4un4XPXEgxzt0Iwhk7UzEI,46340
10
+ eventsourcing/popo.py,sha256=xZD6mig7bVwAoHe-UdraXvuu2iL5a8b2b41cEcBHlBU,9642
11
+ eventsourcing/postgres.py,sha256=lcbLvHCiUCYyHeIn4Fh7RHEjrbdmIrZC9XwfTOH4t4Q,37544
12
+ eventsourcing/projection.py,sha256=-vhjyOr08D42TGJX9ISeGx8H3sOuyKlIajPGek4aUtM,9775
13
+ eventsourcing/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ eventsourcing/sqlite.py,sha256=_9ENoxEY7hqHGhOS4HBgElibBXyHI2vJ5nUVAQuffD0,22016
15
+ eventsourcing/system.py,sha256=3mbxQRFLg8wQ8ulThd6y0CKBjtmo6lR3gZf9ZFITNCI,46888
16
+ eventsourcing/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ eventsourcing/tests/application.py,sha256=pAn9Cugp_1rjOtj_nruGhh7PxdrQWibDlrnOAlOKXwo,20614
18
+ eventsourcing/tests/domain.py,sha256=yN-F6gMRumeX6nIXIcZGxAR3RrUslzmEMM8JksnkI8Q,3227
19
+ eventsourcing/tests/persistence.py,sha256=DVSKySk86iRW-QKGgs-4ca1C956N1LoGhYEXXesBF6k,58648
20
+ eventsourcing/tests/postgres_utils.py,sha256=0ywklGp6cXZ5PmV8ANVkwSHsZZCl5zTmOk7iG-RmrCE,1548
21
+ eventsourcing/utils.py,sha256=pOnczXzaE5q7UbQbPmgcpWaP660fsmfiDJs6Gmo8QCM,8558
22
+ eventsourcing-9.4.0b3.dist-info/AUTHORS,sha256=8aHOM4UbNZcKlD-cHpFRcM6RWyCqtwtxRev6DeUgVRs,137
23
+ eventsourcing-9.4.0b3.dist-info/LICENSE,sha256=CQEQzcZO8AWXL5i3hIo4yVKrYjh2FBz6hCM7kpXWpw4,1512
24
+ eventsourcing-9.4.0b3.dist-info/METADATA,sha256=EZrHitWWM3yUoXD38I2u0SSNsDutr9zNg8AfFXno8mQ,9796
25
+ eventsourcing-9.4.0b3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
26
+ eventsourcing-9.4.0b3.dist-info/RECORD,,
@@ -1,26 +0,0 @@
1
- eventsourcing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- eventsourcing/application.py,sha256=lVgKXCeGA36CsUW7qgkkABX0mCUBvUH-QGQFtOYwmUw,35796
3
- eventsourcing/cipher.py,sha256=R6bvq7Zcsd7NvV1o8WghdBcnqu0IDkOxlfxUSk1txeQ,3320
4
- eventsourcing/compressor.py,sha256=IdvrJUB9B2td871oifInv4lGXmHwYL9d69MbHHCr7uI,421
5
- eventsourcing/cryptography.py,sha256=ZsQFyeyMZysADqKy38ECV71j6EMMSbo3VQO7oRnC1h0,2994
6
- eventsourcing/dispatch.py,sha256=3eVnGCagnn_CENSnTKonMt2kZ1eoHm8abdK7YRVONbU,2736
7
- eventsourcing/domain.py,sha256=WwDwo-IxYrC3fEXu_5E2x-Vk4s1Ye9IaZSQLcUGhQqw,59889
8
- eventsourcing/interface.py,sha256=uCoV9ARAu229SGwp169yeSLbB8wDLKDwWcnQdvOXOQM,5141
9
- eventsourcing/persistence.py,sha256=6q4d7oYjSb8TQHwd30iqMYBJ1tIK6RacA2nfOEhmGvE,47015
10
- eventsourcing/popo.py,sha256=xBUnnPuQ_wdF0ErU9AApRPwlkB0CJePMbWCz6qn3U1M,9654
11
- eventsourcing/postgres.py,sha256=hHYpzvZc7nANXE1uQZ3gA-XKk5X9rB6nJ_zouOkpidk,37537
12
- eventsourcing/projection.py,sha256=Dh5vdMhrvuljpr4cZyEUho6n_rGvkWHh5VlBesbNrYM,9963
13
- eventsourcing/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- eventsourcing/sqlite.py,sha256=UVgG0JCmYr7xN8HHnoiMPpZtZ3d5NTfB-iq0MlZGax4,22051
15
- eventsourcing/system.py,sha256=tyqGaGUE6CUGPWUZf27_26-Zl3PLsm3vK017Wxn7IM0,47279
16
- eventsourcing/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- eventsourcing/tests/application.py,sha256=ItYpHuFn7gNnGxYFmLQBAaEsDRVRZK7GVJmeU_XslA4,20372
18
- eventsourcing/tests/domain.py,sha256=LkvGFYFc6jJR0PYjO2hAGPw0TNW8vUzdTuR8K5xDEQ0,3385
19
- eventsourcing/tests/persistence.py,sha256=DePUevT4uYNTcIzVZoO6uzyyrUI2sOK6CSioiJRcD6I,58518
20
- eventsourcing/tests/postgres_utils.py,sha256=0ywklGp6cXZ5PmV8ANVkwSHsZZCl5zTmOk7iG-RmrCE,1548
21
- eventsourcing/utils.py,sha256=1mG24CXb4oRaumB6NMaH3QqxtHEiWTiJEWzFDRBf6nc,8537
22
- eventsourcing-9.4.0b2.dist-info/AUTHORS,sha256=8aHOM4UbNZcKlD-cHpFRcM6RWyCqtwtxRev6DeUgVRs,137
23
- eventsourcing-9.4.0b2.dist-info/LICENSE,sha256=CQEQzcZO8AWXL5i3hIo4yVKrYjh2FBz6hCM7kpXWpw4,1512
24
- eventsourcing-9.4.0b2.dist-info/METADATA,sha256=NEvxuyvdFg5vqJNNKScZNztuEomgftsm-jB3IP0j49Q,9796
25
- eventsourcing-9.4.0b2.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
26
- eventsourcing-9.4.0b2.dist-info/RECORD,,