sqlalchemy-events-lib 0.2.0__tar.gz → 0.3.0__tar.gz
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.
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/PKG-INFO +6 -7
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/README.md +5 -6
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/pyproject.toml +1 -1
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/__init__.py +1 -1
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/core.py +53 -18
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/decorators.py +4 -0
- sqlalchemy_events_lib-0.3.0/src/sqlalchemy_events/default_logger.py +25 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/discovery.py +6 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/handlers.py +3 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events_lib.egg-info/PKG-INFO +6 -7
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events_lib.egg-info/SOURCES.txt +1 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/tests/conftest.py +0 -1
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/LICENSE +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/setup.cfg +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/callbacks_strategies/__init__.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/callbacks_strategies/base.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/callbacks_strategies/postgres_callback.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/events.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/exceptions.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/init_triggers_strategies/__init__.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/init_triggers_strategies/base.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/init_triggers_strategies/postgres_init_triggers.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/registry.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/types.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/utils.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events_lib.egg-info/dependency_links.txt +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events_lib.egg-info/requires.txt +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events_lib.egg-info/top_level.txt +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/tests/test_autodiscover.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/tests/test_is_created_triggers.py +0 -0
- {sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/tests/test_models.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlalchemy-events-lib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Event-driven extension for SQLAlchemy that enables listening to database CUD events. This library allows you to react to database changes in real time using a clean, declarative API.
|
|
5
5
|
Author-email: Alexey Kostarev <normjkeeewm@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -110,13 +110,11 @@ main.py
|
|
|
110
110
|
```python
|
|
111
111
|
import asyncio
|
|
112
112
|
from sqlalchemy_events import SQLAlchemyEvents
|
|
113
|
-
from models import Base
|
|
114
113
|
from session import engine
|
|
115
114
|
|
|
116
115
|
|
|
117
116
|
async def main():
|
|
118
117
|
SQLAlchemyEvents(
|
|
119
|
-
base=Base,
|
|
120
118
|
engine=engine,
|
|
121
119
|
autodiscover_paths=['services']
|
|
122
120
|
)
|
|
@@ -133,22 +131,23 @@ if __name__ == '__main__':
|
|
|
133
131
|
The SQLAlchemyEvents class accepts the following parameters:
|
|
134
132
|
```python
|
|
135
133
|
SQLAlchemyEvents(
|
|
136
|
-
base,
|
|
137
134
|
engine,
|
|
138
135
|
autodiscover_paths,
|
|
139
|
-
logger=None
|
|
136
|
+
logger=None,
|
|
137
|
+
verbose=True
|
|
140
138
|
)
|
|
141
139
|
```
|
|
142
140
|
|
|
143
141
|
Parameters:
|
|
144
|
-
* **base** - SQLAlchemy declarative base class used to discover mapped models.
|
|
145
142
|
* **engine** - SQLAlchemy Engine or AsyncEngine instance.
|
|
146
143
|
* **autodiscover_paths** - List of Python module paths where event handlers are defined.
|
|
147
144
|
These modules are automatically imported so that decorators such as
|
|
148
|
-
`@sa_insert_handler`, `@sa_update_handler`, `@sa_delete_handler` are executed.
|
|
145
|
+
`@sa_insert_handler`, `@sa_update_handler`, `@sa_delete_handler` are executed.
|
|
149
146
|
**Example:**
|
|
150
147
|
`autodiscover_paths=["services", "app.handlers"]`
|
|
151
148
|
|
|
149
|
+
* **verbose** - Enables detailed logging output. When set to True, the library will log additional informational and warning messages to help with debugging and configuration.
|
|
150
|
+
|
|
152
151
|
### Important:
|
|
153
152
|
|
|
154
153
|
All modules containing event handlers must be imported through autodiscover
|
|
@@ -88,13 +88,11 @@ main.py
|
|
|
88
88
|
```python
|
|
89
89
|
import asyncio
|
|
90
90
|
from sqlalchemy_events import SQLAlchemyEvents
|
|
91
|
-
from models import Base
|
|
92
91
|
from session import engine
|
|
93
92
|
|
|
94
93
|
|
|
95
94
|
async def main():
|
|
96
95
|
SQLAlchemyEvents(
|
|
97
|
-
base=Base,
|
|
98
96
|
engine=engine,
|
|
99
97
|
autodiscover_paths=['services']
|
|
100
98
|
)
|
|
@@ -111,22 +109,23 @@ if __name__ == '__main__':
|
|
|
111
109
|
The SQLAlchemyEvents class accepts the following parameters:
|
|
112
110
|
```python
|
|
113
111
|
SQLAlchemyEvents(
|
|
114
|
-
base,
|
|
115
112
|
engine,
|
|
116
113
|
autodiscover_paths,
|
|
117
|
-
logger=None
|
|
114
|
+
logger=None,
|
|
115
|
+
verbose=True
|
|
118
116
|
)
|
|
119
117
|
```
|
|
120
118
|
|
|
121
119
|
Parameters:
|
|
122
|
-
* **base** - SQLAlchemy declarative base class used to discover mapped models.
|
|
123
120
|
* **engine** - SQLAlchemy Engine or AsyncEngine instance.
|
|
124
121
|
* **autodiscover_paths** - List of Python module paths where event handlers are defined.
|
|
125
122
|
These modules are automatically imported so that decorators such as
|
|
126
|
-
`@sa_insert_handler`, `@sa_update_handler`, `@sa_delete_handler` are executed.
|
|
123
|
+
`@sa_insert_handler`, `@sa_update_handler`, `@sa_delete_handler` are executed.
|
|
127
124
|
**Example:**
|
|
128
125
|
`autodiscover_paths=["services", "app.handlers"]`
|
|
129
126
|
|
|
127
|
+
* **verbose** - Enables detailed logging output. When set to True, the library will log additional informational and warning messages to help with debugging and configuration.
|
|
128
|
+
|
|
130
129
|
### Important:
|
|
131
130
|
|
|
132
131
|
All modules containing event handlers must be imported through autodiscover
|
|
@@ -10,7 +10,7 @@ where = ["src"]
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "sqlalchemy-events-lib"
|
|
13
|
-
version = "0.
|
|
13
|
+
version = "0.3.0"
|
|
14
14
|
description = "Event-driven extension for SQLAlchemy that enables listening to database CUD events. This library allows you to react to database changes in real time using a clean, declarative API."
|
|
15
15
|
requires-python = ">=3.12"
|
|
16
16
|
authors = [
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
|
+
from collections import defaultdict
|
|
3
4
|
from pathlib import Path
|
|
4
|
-
from typing import Optional,
|
|
5
|
+
from typing import Optional, Union
|
|
5
6
|
import inspect
|
|
6
7
|
|
|
7
8
|
from sqlalchemy import Engine
|
|
8
9
|
from sqlalchemy.ext.asyncio import AsyncEngine
|
|
9
10
|
from sqlalchemy.orm import DeclarativeBase
|
|
10
11
|
|
|
12
|
+
from .default_logger import DefaultLogger
|
|
11
13
|
from .discovery import autodiscover
|
|
12
14
|
from .events import SaEventStrategy, sa_events_strategy
|
|
13
15
|
from .registry import get_event_handlers
|
|
16
|
+
from .types import Handler
|
|
14
17
|
from .utils import dialect_resolver
|
|
15
18
|
|
|
16
19
|
|
|
@@ -18,19 +21,35 @@ class SQLAlchemyEvents:
|
|
|
18
21
|
|
|
19
22
|
def __init__(
|
|
20
23
|
self,
|
|
21
|
-
base: Type[DeclarativeBase],
|
|
22
24
|
engine: Union[AsyncEngine, Engine],
|
|
23
|
-
autodiscover_paths: list[str],
|
|
24
|
-
logger: Optional[logging.Logger] = None
|
|
25
|
+
autodiscover_paths: list[str | Path],
|
|
26
|
+
logger: Optional[logging.Logger] = None,
|
|
27
|
+
verbose: bool = True
|
|
25
28
|
) -> None:
|
|
26
|
-
self.base = base
|
|
27
29
|
self.engine = engine
|
|
28
30
|
self.autodiscover_paths = autodiscover_paths
|
|
29
|
-
self.logger = logger
|
|
31
|
+
self.logger = logger or DefaultLogger() if verbose else None
|
|
32
|
+
self.verbose = verbose
|
|
30
33
|
asyncio.create_task(self.__init())
|
|
31
34
|
|
|
32
35
|
async def __init(self) -> None:
|
|
33
|
-
if not
|
|
36
|
+
if not isinstance(self.engine, (AsyncEngine, Engine)):
|
|
37
|
+
raise RuntimeError(
|
|
38
|
+
'[SQLAlchemyEvents] \'engine\' must be an instance of '
|
|
39
|
+
'sqlalchemy.Engine or sqlalchemy.ext.asyncio.AsyncEngine.'
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if not self.autodiscover_paths:
|
|
43
|
+
if self.verbose:
|
|
44
|
+
self.logger.warning(
|
|
45
|
+
'[SQLAlchemyEvents] No autodiscover paths specified. '
|
|
46
|
+
'Please provide at least one module path (e.g., \'app.handlers\') '
|
|
47
|
+
'in \'autodiscover_paths\' during initialization.'
|
|
48
|
+
)
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
handlers = await self.__find_handlers()
|
|
52
|
+
if not handlers:
|
|
34
53
|
return
|
|
35
54
|
|
|
36
55
|
dialect = dialect_resolver(self.engine)
|
|
@@ -38,13 +57,13 @@ class SQLAlchemyEvents:
|
|
|
38
57
|
if not event_strategy:
|
|
39
58
|
raise RuntimeError(f'[SQLAlchemyEvents] Unsupported database {dialect}. '
|
|
40
59
|
f'This library supports only {', '.join(sa_events_strategy.keys())}')
|
|
41
|
-
await self.__start_listen(event_strategy)
|
|
60
|
+
await self.__start_listen(event_strategy, handlers)
|
|
42
61
|
|
|
43
62
|
async def __find_handlers(self):
|
|
44
63
|
autodiscover(self.autodiscover_paths)
|
|
45
64
|
handlers = get_event_handlers()
|
|
46
65
|
if not handlers:
|
|
47
|
-
if self.
|
|
66
|
+
if self.verbose:
|
|
48
67
|
self.logger.info('[SQLAlchemyEvents] No handlers found')
|
|
49
68
|
return
|
|
50
69
|
res_handlers = []
|
|
@@ -53,6 +72,7 @@ class SQLAlchemyEvents:
|
|
|
53
72
|
|
|
54
73
|
filtered_handlers = []
|
|
55
74
|
handler_paths = set()
|
|
75
|
+
handlers_qty = defaultdict(int)
|
|
56
76
|
for handler in res_handlers:
|
|
57
77
|
file_path = inspect.getsourcefile(handler.func) or inspect.getfile(handler.func)
|
|
58
78
|
|
|
@@ -64,13 +84,28 @@ class SQLAlchemyEvents:
|
|
|
64
84
|
|
|
65
85
|
handler_paths.add(handler_path)
|
|
66
86
|
filtered_handlers.append(handler)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
handlers_qty[f'{file_func.parent.name}/{file_name}'] += 1
|
|
88
|
+
|
|
89
|
+
if self.verbose:
|
|
90
|
+
for path, qty in handlers_qty.items():
|
|
91
|
+
self.logger.info(f'[SQLAlchemyEvents] Registered {qty} {'handler' if qty == 1 else 'handlers'} '
|
|
92
|
+
f'from \'{path}\'')
|
|
70
93
|
|
|
71
94
|
return filtered_handlers
|
|
72
95
|
|
|
73
|
-
async def __start_listen(self, event_strategy: SaEventStrategy):
|
|
96
|
+
async def __start_listen(self, event_strategy: SaEventStrategy, handlers: list[Handler]):
|
|
97
|
+
base = None
|
|
98
|
+
try:
|
|
99
|
+
model = handlers[0].args['model']
|
|
100
|
+
for cls in model.__mro__:
|
|
101
|
+
if issubclass(cls, DeclarativeBase) and cls is not DeclarativeBase:
|
|
102
|
+
base = cls
|
|
103
|
+
|
|
104
|
+
if not base:
|
|
105
|
+
raise Exception
|
|
106
|
+
except Exception:
|
|
107
|
+
raise RuntimeError('[SQLAlchemyEvents] No Base found in Registered handlers')
|
|
108
|
+
|
|
74
109
|
if isinstance(self.engine, AsyncEngine):
|
|
75
110
|
async with self.engine.connect() as conn:
|
|
76
111
|
raw_conn = await conn.get_raw_connection()
|
|
@@ -80,11 +115,11 @@ class SQLAlchemyEvents:
|
|
|
80
115
|
raise RuntimeError('[SQLAlchemyEvents] Driver does not support LISTEN/NOTIFY')
|
|
81
116
|
|
|
82
117
|
await event_strategy.init_triggers(
|
|
83
|
-
model_list=
|
|
118
|
+
model_list=base.__subclasses__(),
|
|
84
119
|
conn=conn,
|
|
85
120
|
logger=self.logger
|
|
86
121
|
)
|
|
87
|
-
if self.
|
|
122
|
+
if self.verbose:
|
|
88
123
|
self.logger.info('[SQLAlchemyEvents] Start listening')
|
|
89
124
|
await driver_conn.add_listener('sqlalchemy_events', event_strategy.callback.handle)
|
|
90
125
|
return
|
|
@@ -103,11 +138,11 @@ class SQLAlchemyEvents:
|
|
|
103
138
|
if not asyncio.iscoroutine(result):
|
|
104
139
|
raise RuntimeError(sync_engine_error)
|
|
105
140
|
await event_strategy.init_triggers(
|
|
106
|
-
model_list=
|
|
141
|
+
model_list=base.__subclasses__(),
|
|
107
142
|
conn=conn,
|
|
108
143
|
logger=self.logger
|
|
109
144
|
)
|
|
110
|
-
if self.
|
|
145
|
+
if self.verbose:
|
|
111
146
|
self.logger.info('[SQLAlchemyEvents] Start listening')
|
|
112
147
|
await result
|
|
113
148
|
|
|
@@ -120,6 +155,6 @@ class SQLAlchemyEvents:
|
|
|
120
155
|
try:
|
|
121
156
|
await driver_conn.wait_for_notify()
|
|
122
157
|
except Exception as e:
|
|
123
|
-
if self.
|
|
158
|
+
if self.verbose:
|
|
124
159
|
self.logger.error(f'[SQLAlchemyEvents] listener crashed: {e}')
|
|
125
160
|
await asyncio.sleep(1)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DefaultLogger:
|
|
5
|
+
def __init__(self) -> None:
|
|
6
|
+
self.__logger = logging.getLogger()
|
|
7
|
+
self.__logger.setLevel(logging.INFO)
|
|
8
|
+
|
|
9
|
+
if not self.__logger.handlers:
|
|
10
|
+
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
|
|
11
|
+
console_handler = logging.StreamHandler()
|
|
12
|
+
console_handler.setFormatter(formatter)
|
|
13
|
+
self.__logger.addHandler(console_handler)
|
|
14
|
+
|
|
15
|
+
def info(self, message: str) -> None:
|
|
16
|
+
self.__logger.info(message)
|
|
17
|
+
|
|
18
|
+
def error(self, message: str, exc_info: bool = True) -> None:
|
|
19
|
+
self.__logger.error(message, exc_info=exc_info)
|
|
20
|
+
|
|
21
|
+
def warning(self, message: str) -> None:
|
|
22
|
+
self.__logger.warning(message)
|
|
23
|
+
|
|
24
|
+
def debug(self, message: str) -> None:
|
|
25
|
+
self.__logger.debug(message)
|
{sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/discovery.py
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
import pkgutil
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from types import ModuleType
|
|
4
5
|
from typing import Iterable, List
|
|
5
6
|
|
|
@@ -8,6 +9,11 @@ def autodiscover(paths: Iterable[str]) -> List[ModuleType]:
|
|
|
8
9
|
modules: List[ModuleType] = []
|
|
9
10
|
|
|
10
11
|
for path in paths:
|
|
12
|
+
if isinstance(path, Path):
|
|
13
|
+
path = str(path)
|
|
14
|
+
path = path.replace('\\', '.')
|
|
15
|
+
|
|
16
|
+
path = path.strip('/').replace('/', '.').lstrip('.')
|
|
11
17
|
module = importlib.import_module(path)
|
|
12
18
|
modules.append(module)
|
|
13
19
|
|
{sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/handlers.py
RENAMED
|
@@ -10,6 +10,9 @@ from .types import Handler
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def __inner(func: Callable, sa_event: SaEvent, model: Type[DeclarativeBase]):
|
|
13
|
+
if not isinstance(model, type) or not issubclass(model, DeclarativeBase):
|
|
14
|
+
raise RuntimeError('Model must inherit from DeclarativeBase')
|
|
15
|
+
|
|
13
16
|
event_handlers = get_event_handlers()
|
|
14
17
|
trig_name = f'sa_{model.__tablename__}_{sa_event.lower()}_notify'
|
|
15
18
|
func_path = inspect.getsourcefile(func) or inspect.getfile(func)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlalchemy-events-lib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Event-driven extension for SQLAlchemy that enables listening to database CUD events. This library allows you to react to database changes in real time using a clean, declarative API.
|
|
5
5
|
Author-email: Alexey Kostarev <normjkeeewm@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -110,13 +110,11 @@ main.py
|
|
|
110
110
|
```python
|
|
111
111
|
import asyncio
|
|
112
112
|
from sqlalchemy_events import SQLAlchemyEvents
|
|
113
|
-
from models import Base
|
|
114
113
|
from session import engine
|
|
115
114
|
|
|
116
115
|
|
|
117
116
|
async def main():
|
|
118
117
|
SQLAlchemyEvents(
|
|
119
|
-
base=Base,
|
|
120
118
|
engine=engine,
|
|
121
119
|
autodiscover_paths=['services']
|
|
122
120
|
)
|
|
@@ -133,22 +131,23 @@ if __name__ == '__main__':
|
|
|
133
131
|
The SQLAlchemyEvents class accepts the following parameters:
|
|
134
132
|
```python
|
|
135
133
|
SQLAlchemyEvents(
|
|
136
|
-
base,
|
|
137
134
|
engine,
|
|
138
135
|
autodiscover_paths,
|
|
139
|
-
logger=None
|
|
136
|
+
logger=None,
|
|
137
|
+
verbose=True
|
|
140
138
|
)
|
|
141
139
|
```
|
|
142
140
|
|
|
143
141
|
Parameters:
|
|
144
|
-
* **base** - SQLAlchemy declarative base class used to discover mapped models.
|
|
145
142
|
* **engine** - SQLAlchemy Engine or AsyncEngine instance.
|
|
146
143
|
* **autodiscover_paths** - List of Python module paths where event handlers are defined.
|
|
147
144
|
These modules are automatically imported so that decorators such as
|
|
148
|
-
`@sa_insert_handler`, `@sa_update_handler`, `@sa_delete_handler` are executed.
|
|
145
|
+
`@sa_insert_handler`, `@sa_update_handler`, `@sa_delete_handler` are executed.
|
|
149
146
|
**Example:**
|
|
150
147
|
`autodiscover_paths=["services", "app.handlers"]`
|
|
151
148
|
|
|
149
|
+
* **verbose** - Enables detailed logging output. When set to True, the library will log additional informational and warning messages to help with debugging and configuration.
|
|
150
|
+
|
|
152
151
|
### Important:
|
|
153
152
|
|
|
154
153
|
All modules containing event handlers must be imported through autodiscover
|
|
@@ -4,6 +4,7 @@ pyproject.toml
|
|
|
4
4
|
src/sqlalchemy_events/__init__.py
|
|
5
5
|
src/sqlalchemy_events/core.py
|
|
6
6
|
src/sqlalchemy_events/decorators.py
|
|
7
|
+
src/sqlalchemy_events/default_logger.py
|
|
7
8
|
src/sqlalchemy_events/discovery.py
|
|
8
9
|
src/sqlalchemy_events/events.py
|
|
9
10
|
src/sqlalchemy_events/exceptions.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/sqlalchemy_events/registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sqlalchemy_events_lib-0.2.0 → sqlalchemy_events_lib-0.3.0}/src/tests/test_is_created_triggers.py
RENAMED
|
File without changes
|
|
File without changes
|