eventsourcing 9.3.5__py3-none-any.whl → 9.4.0__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.

@@ -1,16 +1,17 @@
1
1
  import psycopg
2
+ from psycopg.sql import SQL, Identifier
2
3
 
3
4
  from eventsourcing.persistence import PersistenceError
4
5
  from eventsourcing.postgres import PostgresDatastore
5
6
 
6
7
 
7
8
  def pg_close_all_connections(
8
- name="eventsourcing",
9
- host="127.0.0.1",
10
- port="5432",
11
- user="postgres",
12
- password="postgres", # noqa: S107
13
- ):
9
+ name: str = "eventsourcing",
10
+ host: str = "127.0.0.1",
11
+ port: str = "5432",
12
+ user: str = "postgres",
13
+ password: str = "postgres", # noqa: S107
14
+ ) -> None:
14
15
  try:
15
16
  # For local development... probably.
16
17
  pg_conn = psycopg.connect(
@@ -40,11 +41,13 @@ def pg_close_all_connections(
40
41
  """
41
42
  pg_conn_cursor = pg_conn.cursor()
42
43
  pg_conn_cursor.execute(close_all_connections)
43
- return close_all_connections, pg_conn_cursor
44
44
 
45
45
 
46
- def drop_postgres_table(datastore: PostgresDatastore, table_name):
47
- statement = f"DROP TABLE {table_name}"
46
+ def drop_postgres_table(datastore: PostgresDatastore, table_name: str) -> None:
47
+ statement = SQL("DROP TABLE {0}.{1}").format(
48
+ Identifier(datastore.schema), Identifier(table_name)
49
+ )
50
+ # print(f"Dropping table {datastore.schema}.{table_name}")
48
51
  try:
49
52
  with datastore.transaction(commit=True) as curs:
50
53
  curs.execute(statement, prepare=False)
eventsourcing/utils.py CHANGED
@@ -2,60 +2,47 @@ from __future__ import annotations
2
2
 
3
3
  import importlib
4
4
  import sys
5
+ from collections.abc import Iterator, Mapping
5
6
  from functools import wraps
6
7
  from inspect import isfunction
7
8
  from random import random
8
9
  from threading import Lock
9
10
  from time import sleep
10
- from typing import (
11
- TYPE_CHECKING,
12
- Any,
13
- Callable,
14
- Dict,
15
- Iterator,
16
- List,
17
- Mapping,
18
- Sequence,
19
- Type,
20
- TypeVar,
21
- no_type_check,
22
- overload,
23
- )
24
-
25
- if TYPE_CHECKING: # pragma: nocover
11
+ from types import ModuleType
12
+ from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union, no_type_check, overload
13
+
14
+ if TYPE_CHECKING:
26
15
  from types import FunctionType, WrapperDescriptorType
27
16
 
28
17
 
29
18
  class TopicError(Exception):
30
- """
31
- Raised when topic doesn't resolve.
32
- """
19
+ """Raised when topic doesn't resolve."""
33
20
 
34
21
 
35
- _type_cache: Dict[type, str] = {}
36
- _topic_cache: Dict[str, Any] = {}
22
+ SupportsTopic = Union[type, Callable[..., Any], ModuleType]
23
+
24
+ _type_cache: dict[SupportsTopic, str] = {}
25
+ _topic_cache: dict[str, SupportsTopic] = {}
37
26
  _topic_cache_lock = Lock()
38
27
 
39
28
 
40
- def get_topic(cls: type) -> str:
41
- """
42
- Returns a "topic string" that locates the given class
29
+ def get_topic(obj: SupportsTopic, /) -> str:
30
+ """Returns a "topic string" that locates the given class
43
31
  in its module. The string is formed by joining the
44
32
  module name and the class qualname separated by the
45
33
  colon character.
46
34
  """
47
35
  try:
48
- return _type_cache[cls]
36
+ return _type_cache[obj]
49
37
  except KeyError:
50
- topic = f"{cls.__module__}:{cls.__qualname__}"
51
- register_topic(topic, cls)
52
- _type_cache[cls] = topic
38
+ topic = f"{obj.__module__}:{obj.__qualname__}"
39
+ register_topic(topic, obj)
40
+ _type_cache[obj] = topic
53
41
  return topic
54
42
 
55
43
 
56
44
  def resolve_topic(topic: str) -> Any:
57
- """
58
- Returns an object located by the given topic.
45
+ """Returns an object located by the given topic.
59
46
 
60
47
  This function can be (is) used to locate domain
61
48
  event classes and aggregate classes from the
@@ -109,9 +96,8 @@ def resolve_topic(topic: str) -> Any:
109
96
  return obj
110
97
 
111
98
 
112
- def register_topic(topic: str, obj: Any) -> None:
113
- """
114
- Registers a topic with an object, so the object will be
99
+ def register_topic(topic: str, obj: SupportsTopic) -> None:
100
+ """Registers a topic with an object, so the object will be
115
101
  returned whenever the topic is resolved.
116
102
 
117
103
  This function can be used to cache the topic of a class, so
@@ -138,13 +124,12 @@ def clear_topic_cache() -> None:
138
124
 
139
125
 
140
126
  def retry(
141
- exc: Type[Exception] | Sequence[Type[Exception]] = Exception,
127
+ exc: type[Exception] | tuple[type[Exception], ...] = Exception,
142
128
  max_attempts: int = 1,
143
129
  wait: float = 0,
144
130
  stall: float = 0,
145
131
  ) -> Callable[[Any], Any]:
146
- """
147
- Retry decorator.
132
+ """Retry decorator.
148
133
 
149
134
  :param exc: List of exceptions that will cause the call to be retried if raised.
150
135
  :param max_attempts: Maximum number of attempts to try.
@@ -154,9 +139,9 @@ def retry(
154
139
  """
155
140
 
156
141
  @no_type_check
157
- def _retry(func):
142
+ def _retry(func: Callable) -> Callable:
158
143
  @wraps(func)
159
- def retry_decorator(*args, **kwargs):
144
+ def retry_decorator(*args: Any, **kwargs: Any) -> Any:
160
145
  if stall:
161
146
  sleep(stall)
162
147
  attempts = 0
@@ -223,11 +208,13 @@ def strtobool(val: str) -> bool:
223
208
  raise ValueError(msg)
224
209
 
225
210
 
226
- def reversed_keys(d: Dict[Any, Any]) -> Iterator[Any]:
211
+ def reversed_keys(d: dict[Any, Any]) -> Iterator[Any]:
227
212
  return reversed(d.keys())
228
213
 
229
214
 
230
- def get_method_name(method: FunctionType | WrapperDescriptorType) -> str:
215
+ def get_method_name(
216
+ method: Callable[..., Any] | FunctionType | WrapperDescriptorType,
217
+ ) -> str:
231
218
  if sys.version_info >= (3, 10): # pragma: no cover
232
219
  return method.__qualname__
233
220
  return method.__name__ # pragma: no cover
@@ -237,25 +224,30 @@ EnvType = Mapping[str, str]
237
224
  T = TypeVar("T")
238
225
 
239
226
 
240
- class Environment(Dict[str, str]):
227
+ class Environment(dict[str, str]):
241
228
  def __init__(self, name: str = "", env: EnvType | None = None):
242
229
  super().__init__(env or {})
243
230
  self.name = name
244
231
 
232
+ @overload # type: ignore[override]
233
+ def get(self, __key: str, /) -> str | None: ... # pragma: no cover
234
+
245
235
  @overload
246
- def get(self, key: str) -> str | None: ... # pragma: no cover
236
+ def get(self, __key: str, /, __default: str) -> str: ... # pragma: no cover
247
237
 
248
238
  @overload
249
- def get(self, key: str, default: str | T) -> str | T: ... # pragma: no cover
239
+ def get(self, __key: str, /, __default: T) -> str | T: ... # pragma: no cover
250
240
 
251
- def get(self, key: str, default: str | T | None = None) -> str | T | None:
252
- for _key in self.create_keys(key):
241
+ def get( # pyright: ignore [reportIncompatibleMethodOverride]
242
+ self, __key: str, /, __default: str | T | None = None
243
+ ) -> str | T | None:
244
+ for _key in self.create_keys(__key):
253
245
  value = super().get(_key, None)
254
246
  if value is not None:
255
247
  return value
256
- return default
248
+ return __default
257
249
 
258
- def create_keys(self, key: str) -> List[str]:
250
+ def create_keys(self, key: str) -> list[str]:
259
251
  keys = []
260
252
  if self.name:
261
253
  keys.append(self.name.upper() + "_" + key)
@@ -1,6 +1,6 @@
1
1
  BSD 3-Clause License
2
2
 
3
- Copyright (c) 2023, John Bywater
3
+ Copyright (c) 2025, John Bywater
4
4
  All rights reserved.
5
5
 
6
6
  Redistribution and use in source and binary forms, with or without
@@ -1,13 +1,12 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: eventsourcing
3
- Version: 9.3.5
3
+ Version: 9.4.0
4
4
  Summary: Event sourcing in Python
5
- Home-page: https://github.com/pyeventsourcing/eventsourcing
6
5
  License: BSD 3-Clause
7
6
  Keywords: event sourcing,event store,domain driven design,domain-driven design,ddd,cqrs,cqs
8
7
  Author: John Bywater
9
8
  Author-email: john.bywater@appropriatesoftware.net
10
- Requires-Python: >=3.8,<4.0
9
+ Requires-Python: >=3.9, !=2.7.*, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*, !=3.7.*, !=3.8.*
11
10
  Classifier: Development Status :: 5 - Production/Stable
12
11
  Classifier: Intended Audience :: Developers
13
12
  Classifier: Intended Audience :: Education
@@ -17,23 +16,24 @@ Classifier: License :: Other/Proprietary License
17
16
  Classifier: Operating System :: OS Independent
18
17
  Classifier: Programming Language :: Python
19
18
  Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.8
21
- Classifier: Programming Language :: Python :: 3.9
22
19
  Classifier: Programming Language :: Python :: 3.10
23
20
  Classifier: Programming Language :: Python :: 3.11
24
21
  Classifier: Programming Language :: Python :: 3.12
25
22
  Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.9
26
24
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
25
  Provides-Extra: crypto
26
+ Provides-Extra: cryptography
28
27
  Provides-Extra: postgres
29
- Requires-Dist: backports.zoneinfo ; python_version < "3.9"
30
- Requires-Dist: psycopg[c,pool] (<=3.2.99999) ; extra == "postgres"
31
- Requires-Dist: pycryptodome (>=3.21,<3.22) ; extra == "crypto"
28
+ Requires-Dist: cryptography (>=44.0,<44.1) ; extra == "cryptography"
29
+ Requires-Dist: psycopg[pool] (<=3.2.99999) ; extra == "postgres"
30
+ Requires-Dist: pycryptodome (>=3.22,<3.23) ; extra == "crypto"
32
31
  Requires-Dist: typing_extensions
32
+ Project-URL: Homepage, https://github.com/pyeventsourcing/eventsourcing
33
33
  Project-URL: Repository, https://github.com/pyeventsourcing/eventsourcing
34
34
  Description-Content-Type: text/markdown
35
35
 
36
- [![Build Status](https://github.com/pyeventsourcing/eventsourcing/actions/workflows/runtests.yaml/badge.svg?branch=main)](https://github.com/pyeventsourcing/eventsourcing/tree/main)
36
+ [![Build Status](https://github.com/pyeventsourcing/eventsourcing/actions/workflows/runtests.yaml/badge.svg?branch=9.4)](https://github.com/pyeventsourcing/eventsourcing)
37
37
  [![Coverage Status](https://coveralls.io/repos/github/pyeventsourcing/eventsourcing/badge.svg?branch=main)](https://coveralls.io/github/pyeventsourcing/eventsourcing?branch=main)
38
38
  [![Documentation Status](https://readthedocs.org/projects/eventsourcing/badge/?version=stable)](https://eventsourcing.readthedocs.io/en/stable/)
39
39
  [![Latest Release](https://badge.fury.io/py/eventsourcing.svg)](https://pypi.org/project/eventsourcing/)
@@ -43,7 +43,10 @@ Description-Content-Type: text/markdown
43
43
 
44
44
  # Event Sourcing in Python
45
45
 
46
- A library for event sourcing in Python.
46
+ This project is a comprehensive Python library for implementing event sourcing, a design pattern where all
47
+ changes to application state are stored as a sequence of events. This library provides a solid foundation
48
+ for building event-sourced applications in Python, with a focus on reliability, performance, and developer
49
+ experience. Please [read the docs](https://eventsourcing.readthedocs.io/). See also [extension projects](https://github.com/pyeventsourcing).
47
50
 
48
51
  *"totally amazing and a pleasure to use"*
49
52
 
@@ -51,8 +54,6 @@ A library for event sourcing in Python.
51
54
 
52
55
  *"a huge help and time saver"*
53
56
 
54
- Please [read the docs](https://eventsourcing.readthedocs.io/). See also [extension projects](https://github.com/pyeventsourcing).
55
-
56
57
 
57
58
  ## Installation
58
59
 
@@ -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=bIELG5g8O4KhBBJMa9A0YeUe9EIuHul4LvCvGBuUhls,62962
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=LGEsfAN_cUOL6xX0NT4gxVcu2Btma95WLqtYcEzdPSA,37757
12
+ eventsourcing/projection.py,sha256=2qkagy2o1sts22LqndYZzsDV7AJK28oGkPrFH1ECnYM,15069
13
+ eventsourcing/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ eventsourcing/sqlite.py,sha256=1DRQgDE1S7lz7Mnz9QH6WZ4luMjI9tof1YpH5qrK9u8,22076
15
+ eventsourcing/system.py,sha256=WCfuSc45A9A1fFO7zpDum_ddh4pU7x-vEcpVZ_ycAyE,44358
16
+ eventsourcing/tests/__init__.py,sha256=FtOyuj-L-oSisYeByTIrnUw-XzsctSbq76XmjPy5fMc,102
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=jy_aMQwRGKQKohw8Ji7oBf1aFIdcHLHiSrHxH6yHvzw,58654
20
+ eventsourcing/tests/postgres_utils.py,sha256=0ywklGp6cXZ5PmV8ANVkwSHsZZCl5zTmOk7iG-RmrCE,1548
21
+ eventsourcing/utils.py,sha256=pOnczXzaE5q7UbQbPmgcpWaP660fsmfiDJs6Gmo8QCM,8558
22
+ eventsourcing-9.4.0.dist-info/AUTHORS,sha256=8aHOM4UbNZcKlD-cHpFRcM6RWyCqtwtxRev6DeUgVRs,137
23
+ eventsourcing-9.4.0.dist-info/LICENSE,sha256=CQEQzcZO8AWXL5i3hIo4yVKrYjh2FBz6hCM7kpXWpw4,1512
24
+ eventsourcing-9.4.0.dist-info/METADATA,sha256=NOe7UGOwfegOvMY0n4DOfcOGVEof3hxeJVTLbZpZnX8,10098
25
+ eventsourcing-9.4.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
26
+ eventsourcing-9.4.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,24 +0,0 @@
1
- eventsourcing/__init__.py,sha256=st2H3shrhTk5rqoUeZHUW8XD9iOX9tGGtQFWr2HGYmo,26
2
- eventsourcing/application.py,sha256=AwTpzqByZT4b6tS6HIFQkH3m9Xx2tchBN-j7jAq63wc,35868
3
- eventsourcing/cipher.py,sha256=NJcVfZdSlCER6xryM4zVoY3cmKstF-iSSniB4jmpaKg,3200
4
- eventsourcing/compressor.py,sha256=IdvrJUB9B2td871oifInv4lGXmHwYL9d69MbHHCr7uI,421
5
- eventsourcing/dispatch.py,sha256=yYSpT-jqc6l_wTdqEnfPJJfvsZN2Ta8g2anrVPWIcqQ,1412
6
- eventsourcing/domain.py,sha256=rvm4Sv2MmLcha8_5wqJ13AjmqyWvuzkquYsexUaePIg,57264
7
- eventsourcing/interface.py,sha256=KzDWLeIkREf-TAFl5AFHtKJwJFA-IthqMKClFkUFqdc,4676
8
- eventsourcing/persistence.py,sha256=TJseAtsWwdC33XLvcoyHdgwTv6s6KsvQS8XLKIq472s,37672
9
- eventsourcing/popo.py,sha256=AApSGneHuXa8yHOWdDfsFTMVDI-9ivEpuKTX1BSOXr8,6547
10
- eventsourcing/postgres.py,sha256=NatfdA-YQQPB1qWsQg23Uhyy6R-hcGNOJHJ1bKmFuKQ,29772
11
- eventsourcing/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- eventsourcing/sqlite.py,sha256=jz7SZk26Gcsjw88KL1xnr4-1tStTW16f1NR6TjMsZnQ,18466
13
- eventsourcing/system.py,sha256=tRn-KpSxcrpJ3x8BtpD9hxYSvk8IHBIPSfTMKPLVT60,46307
14
- eventsourcing/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- eventsourcing/tests/application.py,sha256=wBanhWzAZvL3fYxCFe5cloN-Up7uLw6KcdRQ2dhKVAg,17586
16
- eventsourcing/tests/domain.py,sha256=lHSlY6jIoSeqlcPSbrrozEPUJGvJ8bgPrznlmzTxn2w,3254
17
- eventsourcing/tests/persistence.py,sha256=giLWEZDdViXY8_SHCJerJ0sYVbJUP3UkLKaEbel9sqs,45777
18
- eventsourcing/tests/postgres_utils.py,sha256=xymcGYasUXeZTBenkHz-ykD8HtrFjVM1Z7-qRrH6OQk,1364
19
- eventsourcing/utils.py,sha256=PIWDvoGiKCXsNbR5DirkoJ_svopg80SoH37bqxOcjkU,8247
20
- eventsourcing-9.3.5.dist-info/AUTHORS,sha256=8aHOM4UbNZcKlD-cHpFRcM6RWyCqtwtxRev6DeUgVRs,137
21
- eventsourcing-9.3.5.dist-info/LICENSE,sha256=bSE_F-T6cQPmMY5LuJC27km_pGB1XCVuUFx1uY0Nueg,1512
22
- eventsourcing-9.3.5.dist-info/METADATA,sha256=yLNXm5rtENkOWB7kK63T2ohN1w7FuraebWFlk-Nxfho,9734
23
- eventsourcing-9.3.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
24
- eventsourcing-9.3.5.dist-info/RECORD,,