database-wrapper 0.1.85__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.85 → database_wrapper-0.2.2}/PKG-INFO +5 -5
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/config.py +3 -3
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/db_backend.py +57 -38
- {database_wrapper-0.1.85 → 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.85 → database_wrapper-0.2.2}/database_wrapper/db_wrapper_mixin.py +72 -72
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/serialization.py +15 -17
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/utils/dataclass_addons.py +5 -5
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper.egg-info/PKG-INFO +5 -5
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper.egg-info/requires.txt +4 -4
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/pyproject.toml +5 -5
- database_wrapper-0.1.85/database_wrapper/db_wrapper.py +0 -456
- database_wrapper-0.1.85/database_wrapper/db_wrapper_async.py +0 -470
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/README.md +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/__init__.py +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/abc.py +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/common.py +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/py.typed +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper/utils/__init__.py +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper.egg-info/SOURCES.txt +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper.egg-info/dependency_links.txt +0 -0
- {database_wrapper-0.1.85 → database_wrapper-0.2.2}/database_wrapper.egg-info/top_level.txt +0 -0
- {database_wrapper-0.1.85 → 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,18 +191,36 @@ class DatabaseBackend:
|
|
|
190
191
|
"""
|
|
191
192
|
raise Exception("Not implemented")
|
|
192
193
|
|
|
194
|
+
def has_connection(self) -> bool:
|
|
195
|
+
"""
|
|
196
|
+
Check if connection is alive/set.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
bool: Connection status
|
|
200
|
+
"""
|
|
201
|
+
return self.connection is not None
|
|
202
|
+
|
|
203
|
+
def has_cursor(self) -> bool:
|
|
204
|
+
"""
|
|
205
|
+
Check if cursor is alive/set.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
bool: Cursor status
|
|
209
|
+
"""
|
|
210
|
+
return self.cursor is not None
|
|
211
|
+
|
|
193
212
|
###############
|
|
194
213
|
### Helpers ###
|
|
195
214
|
###############
|
|
196
215
|
|
|
197
|
-
def
|
|
216
|
+
def fix_socket_timeouts(self, fd: Any) -> None:
|
|
198
217
|
# Lets do some socket magic
|
|
199
218
|
s = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
|
|
200
219
|
# Enable sending of keep-alive messages
|
|
201
220
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
202
221
|
# Time the connection needs to remain idle before start sending
|
|
203
222
|
# keepalive probes
|
|
204
|
-
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, self.
|
|
223
|
+
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, self.connection_timeout)
|
|
205
224
|
# Time between individual keepalive probes
|
|
206
225
|
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 1)
|
|
207
226
|
# The maximum number of keepalive probes should send before dropping
|
|
@@ -210,27 +229,27 @@ class DatabaseBackend:
|
|
|
210
229
|
# To set timeout for an RTO you must set TCP_USER_TIMEOUT timeout
|
|
211
230
|
# (in milliseconds) for socket.
|
|
212
231
|
s.setsockopt(
|
|
213
|
-
socket.IPPROTO_TCP, socket.TCP_USER_TIMEOUT, self.
|
|
232
|
+
socket.IPPROTO_TCP, socket.TCP_USER_TIMEOUT, self.connection_timeout * 1000
|
|
214
233
|
)
|
|
215
234
|
|
|
216
235
|
####################
|
|
217
236
|
### Transactions ###
|
|
218
237
|
####################
|
|
219
238
|
|
|
220
|
-
def
|
|
239
|
+
def begin_transaction(self) -> Any:
|
|
221
240
|
"""Start transaction"""
|
|
222
241
|
raise Exception("Not implemented")
|
|
223
242
|
|
|
224
|
-
def
|
|
243
|
+
def commit_transaction(self) -> Any:
|
|
225
244
|
"""Commit transaction"""
|
|
226
245
|
raise Exception("Not implemented")
|
|
227
246
|
|
|
228
|
-
def
|
|
247
|
+
def rollback_transaction(self) -> Any:
|
|
229
248
|
"""Rollback transaction"""
|
|
230
249
|
raise Exception("Not implemented")
|
|
231
250
|
|
|
232
251
|
# @contextmanager
|
|
233
|
-
def transaction(self,
|
|
252
|
+
def transaction(self, db_conn: Any = None) -> Any:
|
|
234
253
|
"""
|
|
235
254
|
Transaction context manager
|
|
236
255
|
|
|
@@ -243,11 +262,11 @@ class DatabaseBackend:
|
|
|
243
262
|
### Data ###
|
|
244
263
|
############
|
|
245
264
|
|
|
246
|
-
def
|
|
265
|
+
def last_insert_id(self) -> int:
|
|
247
266
|
"""Get last inserted row id generated by auto increment"""
|
|
248
267
|
raise Exception("Not implemented")
|
|
249
268
|
|
|
250
|
-
def
|
|
269
|
+
def affected_rows(self) -> int:
|
|
251
270
|
"""Get affected rows count"""
|
|
252
271
|
raise Exception("Not implemented")
|
|
253
272
|
|