kisa-utils 0.37.12__py3-none-any.whl → 0.37.13__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.
- kisa_utils/db.py +71 -7
- {kisa_utils-0.37.12.dist-info → kisa_utils-0.37.13.dist-info}/METADATA +1 -1
- {kisa_utils-0.37.12.dist-info → kisa_utils-0.37.13.dist-info}/RECORD +5 -5
- {kisa_utils-0.37.12.dist-info → kisa_utils-0.37.13.dist-info}/WHEEL +1 -1
- {kisa_utils-0.37.12.dist-info → kisa_utils-0.37.13.dist-info}/top_level.txt +0 -0
kisa_utils/db.py
CHANGED
|
@@ -6,6 +6,7 @@ from typing import Generator, Any, Callable
|
|
|
6
6
|
import inspect
|
|
7
7
|
import traceback
|
|
8
8
|
import re
|
|
9
|
+
from threading import get_native_id as getCurrentThreadId, Lock
|
|
9
10
|
|
|
10
11
|
from . import storage
|
|
11
12
|
from . import codes
|
|
@@ -52,6 +53,8 @@ TRIGGERS:dict = {
|
|
|
52
53
|
|
|
53
54
|
JSON_SEPARATOR = '::'
|
|
54
55
|
|
|
56
|
+
RAM_DB_PATHS:list[str] = [':memory:', ':ram:',':RAM:']
|
|
57
|
+
|
|
55
58
|
# *********************************************************************
|
|
56
59
|
def _getNumberOfArgsAndKwargs(function:Callable) -> tuple[int]:
|
|
57
60
|
'''
|
|
@@ -69,6 +72,39 @@ def _getNumberOfArgsAndKwargs(function:Callable) -> tuple[int]:
|
|
|
69
72
|
return nArgs, nKwargs
|
|
70
73
|
|
|
71
74
|
class Api:
|
|
75
|
+
__lock = Lock()
|
|
76
|
+
__openDatabases:dict = {
|
|
77
|
+
# path:str -> {
|
|
78
|
+
# threadId:int -> instance:Api,
|
|
79
|
+
# ...
|
|
80
|
+
# }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# make this class a singleton
|
|
84
|
+
def __new__(cls, *args, **kwargs) -> 'Api':
|
|
85
|
+
path = ''
|
|
86
|
+
if args: path=args[0]
|
|
87
|
+
else: path = kwargs.get(path, RAM_DB_PATHS[0])
|
|
88
|
+
|
|
89
|
+
if path not in RAM_DB_PATHS:
|
|
90
|
+
threadId = getCurrentThreadId()
|
|
91
|
+
with Api.__lock:
|
|
92
|
+
if path not in Api.__openDatabases:
|
|
93
|
+
Api.__openDatabases[path] = {}
|
|
94
|
+
|
|
95
|
+
if threadId in Api.__openDatabases[path]:
|
|
96
|
+
instance = Api.__openDatabases[path][threadId]
|
|
97
|
+
# print(f'using existing db handle: {threadId} {path}')
|
|
98
|
+
else:
|
|
99
|
+
instance = super().__new__(cls)
|
|
100
|
+
# print(f'new db handle: {threadId} {path}')
|
|
101
|
+
Api.__openDatabases[path][threadId] = instance
|
|
102
|
+
else:
|
|
103
|
+
instance = super().__new__(cls)
|
|
104
|
+
|
|
105
|
+
return instance
|
|
106
|
+
|
|
107
|
+
|
|
72
108
|
def __checkContext(method):
|
|
73
109
|
'''
|
|
74
110
|
this decorator will be used to enforce the calling of Api class instances
|
|
@@ -162,6 +198,9 @@ class Api:
|
|
|
162
198
|
useWALMode(bool): if set to `True`, WAL mode will be used for the underlying sqlite3 database
|
|
163
199
|
returnKISAResponse(bool|None): if not set, `kisa_utils.db.RETURN_KISA_RESPONSES` will be used. if set to `True`, all public methods that dont return `None` will return KISA Response objects
|
|
164
200
|
'''
|
|
201
|
+
if getattr(self, "_dbInitializedInThread", False):
|
|
202
|
+
return
|
|
203
|
+
self._dbInitializedInThread = True
|
|
165
204
|
|
|
166
205
|
self._in_with_statement = False
|
|
167
206
|
self.isOpen = False
|
|
@@ -172,7 +211,9 @@ class Api:
|
|
|
172
211
|
self.__withContextCount = 0
|
|
173
212
|
self.__returnKISAResponse = RETURN_KISA_RESPONSES if None==returnKISAResponse else returnKISAResponse
|
|
174
213
|
|
|
175
|
-
|
|
214
|
+
self._path = path
|
|
215
|
+
|
|
216
|
+
if path not in RAM_DB_PATHS:
|
|
176
217
|
while path.endswith('/'): path = path[:-1]
|
|
177
218
|
if not path.endswith(f'.{__EXT__}') and not os.path.isfile(path):
|
|
178
219
|
path += f'.{__EXT__}'
|
|
@@ -700,13 +741,19 @@ class Api:
|
|
|
700
741
|
+ 1d = insert single row
|
|
701
742
|
+ 2d = insert multple row
|
|
702
743
|
'''
|
|
703
|
-
|
|
704
|
-
|
|
744
|
+
reply = {'status':False, 'log':'', 'affectedRows':0}
|
|
745
|
+
|
|
746
|
+
try:
|
|
747
|
+
self.cursor.execute(f'select * from {table}')
|
|
748
|
+
column_value_placeholders = ['?' for description in self.cursor.description]
|
|
749
|
+
except Exception as e:
|
|
750
|
+
if self.__transactionMode: self.__transactionData['insert']['failed'] += 1
|
|
751
|
+
reply['log'] = str(e)
|
|
752
|
+
return reply if not self.__returnKISAResponse else Error(reply['log'])
|
|
705
753
|
|
|
706
754
|
if not isinstance(data, (list, tuple)):
|
|
707
755
|
data = [data]
|
|
708
756
|
|
|
709
|
-
reply = {'status':False, 'log':'', 'affectedRows':0}
|
|
710
757
|
try:
|
|
711
758
|
data = self.__encodeIncomingData(data)
|
|
712
759
|
if isinstance(data[0],(list,tuple)):
|
|
@@ -979,10 +1026,15 @@ class Api:
|
|
|
979
1026
|
return reply if not self.__returnKISAResponse else Ok()
|
|
980
1027
|
|
|
981
1028
|
# @__checkContext
|
|
982
|
-
def close(self) ->
|
|
1029
|
+
def close(self) -> bool:
|
|
983
1030
|
'''
|
|
984
1031
|
close the sqlite connection
|
|
985
1032
|
'''
|
|
1033
|
+
|
|
1034
|
+
if self.__withContextCount > 0:
|
|
1035
|
+
return False
|
|
1036
|
+
|
|
1037
|
+
# print('>>>closed DB<<<<', self._path)
|
|
986
1038
|
if self.isOpen:
|
|
987
1039
|
# self.db.execute('pragma optimize;')
|
|
988
1040
|
if self.__transactionMode:
|
|
@@ -995,12 +1047,24 @@ class Api:
|
|
|
995
1047
|
# self.db, self.cursor = None,None
|
|
996
1048
|
self.isOpen = False
|
|
997
1049
|
|
|
1050
|
+
return True
|
|
1051
|
+
|
|
998
1052
|
# @__checkContext
|
|
999
1053
|
def release(self) -> None:
|
|
1000
1054
|
'''
|
|
1001
1055
|
close the sqlite3 connection
|
|
1002
1056
|
'''
|
|
1003
|
-
|
|
1057
|
+
|
|
1058
|
+
path = self._path
|
|
1059
|
+
|
|
1060
|
+
if not self.close():
|
|
1061
|
+
return
|
|
1062
|
+
|
|
1063
|
+
if path in RAM_DB_PATHS: return
|
|
1064
|
+
|
|
1065
|
+
threadId = getCurrentThreadId()
|
|
1066
|
+
with Api.__lock:
|
|
1067
|
+
del Api.__openDatabases[path][threadId]
|
|
1004
1068
|
|
|
1005
1069
|
# methods to add context to the handle
|
|
1006
1070
|
def __enter__(self) -> 'Api':
|
|
@@ -1059,7 +1123,7 @@ def transaction(*dbArgs, **dbKwargs) -> dict|Response:
|
|
|
1059
1123
|
|
|
1060
1124
|
'''
|
|
1061
1125
|
|
|
1062
|
-
returnKISAResponse = dbKwargs.get('returnKISAResponse',
|
|
1126
|
+
returnKISAResponse = dbKwargs.get('returnKISAResponse',RETURN_KISA_RESPONSES)
|
|
1063
1127
|
|
|
1064
1128
|
def handler(func) -> dict:
|
|
1065
1129
|
def wrapper(*args, **kwargs) -> dict:
|
|
@@ -3,7 +3,7 @@ kisa_utils/cache.py,sha256=4Ue5G3QhHSQAmIfQKYgWKWjNL4rA4wLLd_RdBLb2ABY,7345
|
|
|
3
3
|
kisa_utils/codes.py,sha256=PV_S53Skggf4XetOdYoIKtEmM8cpN5wZwUlxje70WZY,904
|
|
4
4
|
kisa_utils/config.py,sha256=NfluzGKTh66qfNtC-Ae0zNb1XzMTgU2Me9Vi82R9c1E,2285
|
|
5
5
|
kisa_utils/dates.py,sha256=kcNqoY_iguG9hSzABMIBqeL3MGz3n4MRIXuW4OxRHLs,12662
|
|
6
|
-
kisa_utils/db.py,sha256=
|
|
6
|
+
kisa_utils/db.py,sha256=8WwJs2a1h2hdPc2U65effJ5MYLVadaeGNLR2iPqd6FA,46391
|
|
7
7
|
kisa_utils/encryption.py,sha256=nFzNpzWV_D9uSEq4FsgCnlS7FQtqWP9fvM_81rsfcLo,4218
|
|
8
8
|
kisa_utils/enqueue.py,sha256=VIliaMvw4MUdOqts0dXdZCYNxs-QrOVjIRAR3scGrRM,11786
|
|
9
9
|
kisa_utils/figures.py,sha256=pYIpQzu1OXRSsY1d98GhgPifnIRmgl-r7S32ai-Ms0c,3731
|
|
@@ -23,7 +23,7 @@ kisa_utils/servers/flask.py,sha256=o76cJKlQ3L8EOVdHUF092qwoAZMzgttuLt0mMhtCsGI,4
|
|
|
23
23
|
kisa_utils/structures/__init__.py,sha256=JBU1j3A42jQ62ALKnsS1Hav9YXcYwjDw1wQJtohXPbU,83
|
|
24
24
|
kisa_utils/structures/utils.py,sha256=l56NQiPVcFijpuLqt2n9ZwnVKT4XzK6oknRVallRzwQ,2573
|
|
25
25
|
kisa_utils/structures/validator.py,sha256=Y4UmB4TH7N-GkK22EV1WOsPWjTeqxVWLTentl1keZD4,4053
|
|
26
|
-
kisa_utils-0.37.
|
|
27
|
-
kisa_utils-0.37.
|
|
28
|
-
kisa_utils-0.37.
|
|
29
|
-
kisa_utils-0.37.
|
|
26
|
+
kisa_utils-0.37.13.dist-info/METADATA,sha256=CVP00b5I9CF2mKMRXXv0XaGaHPqp741ggky_7256efo,478
|
|
27
|
+
kisa_utils-0.37.13.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
28
|
+
kisa_utils-0.37.13.dist-info/top_level.txt,sha256=URxY4sRuqmirOxWtztpVmPoGQdksEMYO6hmYsEDGz2Y,75
|
|
29
|
+
kisa_utils-0.37.13.dist-info/RECORD,,
|
|
File without changes
|