database-wrapper 0.1.86__tar.gz → 0.2.2__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.
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/PKG-INFO +5 -5
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/config.py +3 -3
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/db_backend.py +41 -40
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/db_data_model.py +102 -102
- database_wrapper-0.2.2/database_wrapper/db_wrapper.py +476 -0
- database_wrapper-0.2.2/database_wrapper/db_wrapper_async.py +482 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/db_wrapper_mixin.py +72 -72
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/serialization.py +15 -17
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/utils/dataclass_addons.py +5 -5
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper.egg-info/PKG-INFO +5 -5
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper.egg-info/requires.txt +4 -4
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/pyproject.toml +5 -5
- database_wrapper-0.1.86/database_wrapper/db_wrapper.py +0 -456
- database_wrapper-0.1.86/database_wrapper/db_wrapper_async.py +0 -470
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/README.md +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/__init__.py +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/abc.py +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/common.py +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/py.typed +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper/utils/__init__.py +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper.egg-info/SOURCES.txt +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper.egg-info/dependency_links.txt +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/database_wrapper.egg-info/top_level.txt +0 -0
- {database_wrapper-0.1.86 → database_wrapper-0.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: database_wrapper
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A Different Approach to Database Wrappers in Python
|
|
5
5
|
Author-email: Gints Murans <gm@gm.lv>
|
|
6
6
|
License: GNU General Public License v3.0 (GPL-3.0)
|
|
@@ -33,13 +33,13 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
33
33
|
Requires-Python: >=3.8
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
Provides-Extra: pgsql
|
|
36
|
-
Requires-Dist: database_wrapper_pgsql==0.
|
|
36
|
+
Requires-Dist: database_wrapper_pgsql==0.2.2; extra == "pgsql"
|
|
37
37
|
Provides-Extra: mysql
|
|
38
|
-
Requires-Dist: database_wrapper_mysql==0.
|
|
38
|
+
Requires-Dist: database_wrapper_mysql==0.2.2; extra == "mysql"
|
|
39
39
|
Provides-Extra: mssql
|
|
40
|
-
Requires-Dist: database_wrapper_mssql==0.
|
|
40
|
+
Requires-Dist: database_wrapper_mssql==0.2.2; extra == "mssql"
|
|
41
41
|
Provides-Extra: sqlite
|
|
42
|
-
Requires-Dist: database_wrapper_sqlite==0.
|
|
42
|
+
Requires-Dist: database_wrapper_sqlite==0.2.2; extra == "sqlite"
|
|
43
43
|
Provides-Extra: all
|
|
44
44
|
Requires-Dist: database_wrapper[mssql,mysql,pgsql,sqlite]; extra == "all"
|
|
45
45
|
Provides-Extra: dev
|
|
@@ -3,7 +3,7 @@ from typing import Any
|
|
|
3
3
|
CONFIG: dict[str, Any] = {
|
|
4
4
|
# These are supposed to be set automatically by a git pre-compile script
|
|
5
5
|
# They are one git commit hash behind, if used automatically
|
|
6
|
-
"git_commit_hash": "
|
|
7
|
-
"git_commit_date": "
|
|
8
|
-
"app_version": "0.
|
|
6
|
+
"git_commit_hash": "c2bc2271cb75bcb46a0114013afa9b34dcb71aa6",
|
|
7
|
+
"git_commit_date": "16.05.2025 21:56",
|
|
8
|
+
"app_version": "0.2.2",
|
|
9
9
|
}
|
|
@@ -10,20 +10,20 @@ class DatabaseBackend:
|
|
|
10
10
|
config: Any
|
|
11
11
|
""" Database configuration """
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
connection_timeout: int
|
|
14
14
|
""" Connection timeout """
|
|
15
15
|
|
|
16
16
|
name: str
|
|
17
17
|
""" Instance name """
|
|
18
18
|
|
|
19
19
|
# TODO: This should be made to increase exponentially
|
|
20
|
-
|
|
20
|
+
slow_down_timeout: int
|
|
21
21
|
""" How long to wait before trying to reconnect """
|
|
22
22
|
|
|
23
23
|
pool: Any
|
|
24
24
|
""" Connection pool """
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
pool_async: Any
|
|
27
27
|
""" Async connection pool """
|
|
28
28
|
|
|
29
29
|
connection: Any
|
|
@@ -32,19 +32,19 @@ class DatabaseBackend:
|
|
|
32
32
|
cursor: Any
|
|
33
33
|
""" Cursor to database """
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
context_connection: ContextVar[Any | None]
|
|
36
36
|
""" Connection used in context manager """
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
context_connection_async: ContextVar[Any | None]
|
|
39
39
|
""" Connection used in async context manager """
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
logger_name: str
|
|
42
42
|
""" Logger name """
|
|
43
43
|
|
|
44
44
|
logger: logging.Logger
|
|
45
45
|
""" Logger """
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
shutdown_requested: Event
|
|
48
48
|
"""
|
|
49
49
|
Event to signal shutdown
|
|
50
50
|
Used to stop database pool from creating new connections
|
|
@@ -56,16 +56,16 @@ class DatabaseBackend:
|
|
|
56
56
|
|
|
57
57
|
def __init__(
|
|
58
58
|
self,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
db_config: Any,
|
|
60
|
+
connection_timeout: int = 5,
|
|
61
|
+
instance_name: str = "database_backend",
|
|
62
|
+
slow_down_timeout: int = 5,
|
|
63
63
|
) -> None:
|
|
64
64
|
"""
|
|
65
65
|
Main concept here is that in init we do not connect to database,
|
|
66
66
|
so that class instances can be safely made regardless of connection statuss.
|
|
67
67
|
|
|
68
|
-
Remember to call open() or
|
|
68
|
+
Remember to call open() or open_pool() before using this class.
|
|
69
69
|
Close will be called automatically when class is destroyed.
|
|
70
70
|
|
|
71
71
|
Contexts are not implemented here, but in child classes should be used
|
|
@@ -75,23 +75,24 @@ class DatabaseBackend:
|
|
|
75
75
|
if not upon destroying the class, an error will be raised that method was not awaited.
|
|
76
76
|
"""
|
|
77
77
|
|
|
78
|
-
self.config =
|
|
79
|
-
self.
|
|
80
|
-
self.name =
|
|
81
|
-
self.
|
|
78
|
+
self.config = db_config
|
|
79
|
+
self.connection_timeout = connection_timeout
|
|
80
|
+
self.name = instance_name
|
|
81
|
+
self.slow_down_timeout = slow_down_timeout
|
|
82
82
|
|
|
83
|
-
self.
|
|
84
|
-
self.logger = logging.getLogger(self.
|
|
83
|
+
self.logger_name = f"{__name__}.{self.__class__.__name__}.{self.name}"
|
|
84
|
+
self.logger = logging.getLogger(self.logger_name)
|
|
85
85
|
|
|
86
86
|
self.pool = None
|
|
87
|
-
self.
|
|
87
|
+
self.pool_async = None
|
|
88
88
|
|
|
89
89
|
self.connection = None
|
|
90
90
|
self.cursor = None
|
|
91
|
-
self.
|
|
92
|
-
self.
|
|
93
|
-
self.
|
|
94
|
-
f"db_connection_{self.name}_async",
|
|
91
|
+
self.shutdown_requested = Event()
|
|
92
|
+
self.context_connection = ContextVar(f"db_connection_{self.name}", default=None)
|
|
93
|
+
self.context_connection_async = ContextVar(
|
|
94
|
+
f"db_connection_{self.name}_async",
|
|
95
|
+
default=None,
|
|
95
96
|
)
|
|
96
97
|
|
|
97
98
|
def __del__(self) -> None:
|
|
@@ -100,14 +101,14 @@ class DatabaseBackend:
|
|
|
100
101
|
|
|
101
102
|
# Clean up connections
|
|
102
103
|
self.close()
|
|
103
|
-
self.
|
|
104
|
+
self.close_pool()
|
|
104
105
|
|
|
105
106
|
# Clean just in case
|
|
106
107
|
del self.connection
|
|
107
108
|
del self.cursor
|
|
108
109
|
|
|
109
110
|
del self.pool
|
|
110
|
-
del self.
|
|
111
|
+
del self.pool_async
|
|
111
112
|
|
|
112
113
|
###############
|
|
113
114
|
### Context ###
|
|
@@ -133,11 +134,11 @@ class DatabaseBackend:
|
|
|
133
134
|
### Connection ###
|
|
134
135
|
##################
|
|
135
136
|
|
|
136
|
-
def
|
|
137
|
+
def open_pool(self) -> Any:
|
|
137
138
|
"""Open connection pool"""
|
|
138
139
|
...
|
|
139
140
|
|
|
140
|
-
def
|
|
141
|
+
def close_pool(self) -> Any:
|
|
141
142
|
"""Close connection pool"""
|
|
142
143
|
...
|
|
143
144
|
|
|
@@ -157,7 +158,7 @@ class DatabaseBackend:
|
|
|
157
158
|
self.connection.close()
|
|
158
159
|
self.connection = None
|
|
159
160
|
|
|
160
|
-
def
|
|
161
|
+
def new_connection(self) -> Any:
|
|
161
162
|
"""
|
|
162
163
|
Create new connection
|
|
163
164
|
|
|
@@ -168,7 +169,7 @@ class DatabaseBackend:
|
|
|
168
169
|
"""
|
|
169
170
|
raise Exception("Not implemented")
|
|
170
171
|
|
|
171
|
-
def
|
|
172
|
+
def return_connection(self, connection: Any) -> Any:
|
|
172
173
|
"""
|
|
173
174
|
Return connection to pool
|
|
174
175
|
|
|
@@ -190,7 +191,7 @@ class DatabaseBackend:
|
|
|
190
191
|
"""
|
|
191
192
|
raise Exception("Not implemented")
|
|
192
193
|
|
|
193
|
-
def
|
|
194
|
+
def has_connection(self) -> bool:
|
|
194
195
|
"""
|
|
195
196
|
Check if connection is alive/set.
|
|
196
197
|
|
|
@@ -199,7 +200,7 @@ class DatabaseBackend:
|
|
|
199
200
|
"""
|
|
200
201
|
return self.connection is not None
|
|
201
202
|
|
|
202
|
-
def
|
|
203
|
+
def has_cursor(self) -> bool:
|
|
203
204
|
"""
|
|
204
205
|
Check if cursor is alive/set.
|
|
205
206
|
|
|
@@ -212,14 +213,14 @@ class DatabaseBackend:
|
|
|
212
213
|
### Helpers ###
|
|
213
214
|
###############
|
|
214
215
|
|
|
215
|
-
def
|
|
216
|
+
def fix_socket_timeouts(self, fd: Any) -> None:
|
|
216
217
|
# Lets do some socket magic
|
|
217
218
|
s = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
|
|
218
219
|
# Enable sending of keep-alive messages
|
|
219
220
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
220
221
|
# Time the connection needs to remain idle before start sending
|
|
221
222
|
# keepalive probes
|
|
222
|
-
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, self.
|
|
223
|
+
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, self.connection_timeout)
|
|
223
224
|
# Time between individual keepalive probes
|
|
224
225
|
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 1)
|
|
225
226
|
# The maximum number of keepalive probes should send before dropping
|
|
@@ -228,27 +229,27 @@ class DatabaseBackend:
|
|
|
228
229
|
# To set timeout for an RTO you must set TCP_USER_TIMEOUT timeout
|
|
229
230
|
# (in milliseconds) for socket.
|
|
230
231
|
s.setsockopt(
|
|
231
|
-
socket.IPPROTO_TCP, socket.TCP_USER_TIMEOUT, self.
|
|
232
|
+
socket.IPPROTO_TCP, socket.TCP_USER_TIMEOUT, self.connection_timeout * 1000
|
|
232
233
|
)
|
|
233
234
|
|
|
234
235
|
####################
|
|
235
236
|
### Transactions ###
|
|
236
237
|
####################
|
|
237
238
|
|
|
238
|
-
def
|
|
239
|
+
def begin_transaction(self) -> Any:
|
|
239
240
|
"""Start transaction"""
|
|
240
241
|
raise Exception("Not implemented")
|
|
241
242
|
|
|
242
|
-
def
|
|
243
|
+
def commit_transaction(self) -> Any:
|
|
243
244
|
"""Commit transaction"""
|
|
244
245
|
raise Exception("Not implemented")
|
|
245
246
|
|
|
246
|
-
def
|
|
247
|
+
def rollback_transaction(self) -> Any:
|
|
247
248
|
"""Rollback transaction"""
|
|
248
249
|
raise Exception("Not implemented")
|
|
249
250
|
|
|
250
251
|
# @contextmanager
|
|
251
|
-
def transaction(self,
|
|
252
|
+
def transaction(self, db_conn: Any = None) -> Any:
|
|
252
253
|
"""
|
|
253
254
|
Transaction context manager
|
|
254
255
|
|
|
@@ -261,11 +262,11 @@ class DatabaseBackend:
|
|
|
261
262
|
### Data ###
|
|
262
263
|
############
|
|
263
264
|
|
|
264
|
-
def
|
|
265
|
+
def last_insert_id(self) -> int:
|
|
265
266
|
"""Get last inserted row id generated by auto increment"""
|
|
266
267
|
raise Exception("Not implemented")
|
|
267
268
|
|
|
268
|
-
def
|
|
269
|
+
def affected_rows(self) -> int:
|
|
269
270
|
"""Get affected rows count"""
|
|
270
271
|
raise Exception("Not implemented")
|
|
271
272
|
|