database-wrapper 0.1.44__py3-none-any.whl → 0.1.72__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.
- database_wrapper/__init__.py +12 -1
- database_wrapper/abc.py +68 -0
- database_wrapper/config.py +3 -3
- database_wrapper/db_backend.py +131 -42
- database_wrapper/db_data_model.py +109 -60
- database_wrapper/db_wrapper.py +43 -123
- database_wrapper/db_wrapper_async.py +54 -118
- database_wrapper/db_wrapper_mixin.py +18 -44
- database_wrapper/serialization.py +82 -0
- database_wrapper/utils/__init__.py +0 -2
- database_wrapper/utils/dataclass_addons.py +1 -1
- {database_wrapper-0.1.44.dist-info → database_wrapper-0.1.72.dist-info}/METADATA +22 -20
- database_wrapper-0.1.72.dist-info/RECORD +17 -0
- {database_wrapper-0.1.44.dist-info → database_wrapper-0.1.72.dist-info}/WHEEL +1 -1
- database_wrapper/utils/timer.py +0 -297
- database_wrapper-0.1.44.dist-info/RECORD +0 -16
- {database_wrapper-0.1.44.dist-info → database_wrapper-0.1.72.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import json
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from decimal import Decimal
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Any, Type
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SerializeType(Enum):
|
|
11
|
+
DATETIME = "datetime"
|
|
12
|
+
JSON = "json"
|
|
13
|
+
ENUM = "enum"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def jsonEncoder(obj: Any) -> Any:
|
|
17
|
+
if isinstance(obj, Decimal):
|
|
18
|
+
return float(obj)
|
|
19
|
+
|
|
20
|
+
if isinstance(obj, datetime.date) or isinstance(obj, datetime.datetime):
|
|
21
|
+
return obj.strftime("%Y-%m-%dT%H:%M:%S")
|
|
22
|
+
|
|
23
|
+
if isinstance(obj, Enum):
|
|
24
|
+
return obj.value
|
|
25
|
+
|
|
26
|
+
if isinstance(obj, int) or isinstance(obj, float) or isinstance(obj, str):
|
|
27
|
+
return obj
|
|
28
|
+
|
|
29
|
+
return str(obj)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def serializeValue(value: Any, sType: SerializeType) -> Any:
|
|
33
|
+
if sType == SerializeType.DATETIME:
|
|
34
|
+
if not isinstance(value, datetime.datetime):
|
|
35
|
+
return value
|
|
36
|
+
|
|
37
|
+
return value.isoformat()
|
|
38
|
+
|
|
39
|
+
if sType == SerializeType.JSON:
|
|
40
|
+
return json.dumps(value, default=jsonEncoder)
|
|
41
|
+
|
|
42
|
+
if sType == SerializeType.ENUM:
|
|
43
|
+
return value.value
|
|
44
|
+
return value
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def deserializeValue(
|
|
48
|
+
value: Any,
|
|
49
|
+
sType: SerializeType,
|
|
50
|
+
enumClass: Type[Enum] | None = None,
|
|
51
|
+
) -> Any:
|
|
52
|
+
if sType == SerializeType.DATETIME:
|
|
53
|
+
if isinstance(value, datetime.datetime):
|
|
54
|
+
return value
|
|
55
|
+
|
|
56
|
+
if value and isinstance(value, str):
|
|
57
|
+
pattern = r"^\d+(\.\d+)?$"
|
|
58
|
+
if re.match(pattern, value):
|
|
59
|
+
return datetime.datetime.fromtimestamp(float(value))
|
|
60
|
+
|
|
61
|
+
return datetime.datetime.fromisoformat(value)
|
|
62
|
+
|
|
63
|
+
return datetime.datetime.now(datetime.UTC)
|
|
64
|
+
|
|
65
|
+
if sType == SerializeType.JSON:
|
|
66
|
+
if isinstance(value, dict) or isinstance(value, list) or value is None:
|
|
67
|
+
return value # type: ignore
|
|
68
|
+
|
|
69
|
+
return json.loads(value)
|
|
70
|
+
|
|
71
|
+
if sType == SerializeType.ENUM:
|
|
72
|
+
if enumClass is None:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
"enumClass (enum_class) must be provided when deserializing Enum"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if isinstance(value, Enum) or value is None:
|
|
78
|
+
return value
|
|
79
|
+
|
|
80
|
+
return enumClass(value)
|
|
81
|
+
|
|
82
|
+
return value
|
|
@@ -12,7 +12,7 @@ def ignore_unknown_kwargs() -> Callable[[AnyDataType], AnyDataType]:
|
|
|
12
12
|
originalInit = cls.__init__
|
|
13
13
|
|
|
14
14
|
# @wraps(originalInit)
|
|
15
|
-
def newInit(self: Any, *args: Any, **kwargs: Any):
|
|
15
|
+
def newInit(self: Any, *args: Any, **kwargs: Any) -> None:
|
|
16
16
|
# Filter out kwargs that are not properties of the class
|
|
17
17
|
valid_kwargs = {k: v for k, v in kwargs.items() if hasattr(self, k)}
|
|
18
18
|
originalInit(self, *args, **valid_kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: database_wrapper
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.72
|
|
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)
|
|
@@ -32,27 +32,29 @@ Classifier: Topic :: Software Development
|
|
|
32
32
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
33
33
|
Requires-Python: >=3.8
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
|
-
Provides-Extra: all
|
|
36
|
-
Requires-Dist: database-wrapper[mssql,mysql,pgsql,sqlite] ; extra == 'all'
|
|
37
|
-
Provides-Extra: dev
|
|
38
|
-
Requires-Dist: ast-comments >=1.1.2 ; extra == 'dev'
|
|
39
|
-
Requires-Dist: codespell >=2.2 ; extra == 'dev'
|
|
40
|
-
Requires-Dist: build >=1.2.1 ; extra == 'dev'
|
|
41
|
-
Requires-Dist: black >=24.1.0 ; extra == 'dev'
|
|
42
|
-
Requires-Dist: types-setuptools >=61.0.0 ; extra == 'dev'
|
|
43
|
-
Requires-Dist: types-pymssql >=2.1.0 ; extra == 'dev'
|
|
44
|
-
Requires-Dist: psycopg[binary] >=3.2.0 ; extra == 'dev'
|
|
45
|
-
Requires-Dist: psycopg[pool] >=3.2.0 ; extra == 'dev'
|
|
46
|
-
Requires-Dist: mysqlclient >=2.2.2 ; extra == 'dev'
|
|
47
|
-
Requires-Dist: pymssql >=2.2.10 ; extra == 'dev'
|
|
48
|
-
Provides-Extra: mssql
|
|
49
|
-
Requires-Dist: database-wrapper-mssql ==0.1.44 ; extra == 'mssql'
|
|
50
|
-
Provides-Extra: mysql
|
|
51
|
-
Requires-Dist: database-wrapper-mysql ==0.1.44 ; extra == 'mysql'
|
|
52
35
|
Provides-Extra: pgsql
|
|
53
|
-
Requires-Dist:
|
|
36
|
+
Requires-Dist: database_wrapper_pgsql==0.1.72; extra == "pgsql"
|
|
37
|
+
Provides-Extra: mysql
|
|
38
|
+
Requires-Dist: database_wrapper_mysql==0.1.72; extra == "mysql"
|
|
39
|
+
Provides-Extra: mssql
|
|
40
|
+
Requires-Dist: database_wrapper_mssql==0.1.72; extra == "mssql"
|
|
54
41
|
Provides-Extra: sqlite
|
|
55
|
-
Requires-Dist:
|
|
42
|
+
Requires-Dist: database_wrapper_sqlite==0.1.72; extra == "sqlite"
|
|
43
|
+
Provides-Extra: all
|
|
44
|
+
Requires-Dist: database_wrapper[mssql,mysql,pgsql,sqlite]; extra == "all"
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: ast-comments>=1.1.2; extra == "dev"
|
|
47
|
+
Requires-Dist: codespell>=2.2; extra == "dev"
|
|
48
|
+
Requires-Dist: build>=1.2.1; extra == "dev"
|
|
49
|
+
Requires-Dist: black>=24.1.0; extra == "dev"
|
|
50
|
+
Requires-Dist: mypy>=1.9.0; extra == "dev"
|
|
51
|
+
Requires-Dist: types-setuptools>=61.0.0; extra == "dev"
|
|
52
|
+
Requires-Dist: types-pymssql>=2.1.0; extra == "dev"
|
|
53
|
+
Requires-Dist: types-mysqlclient>=2.2.0; extra == "dev"
|
|
54
|
+
Requires-Dist: psycopg[binary]>=3.2.0; extra == "dev"
|
|
55
|
+
Requires-Dist: psycopg[pool]>=3.2.0; extra == "dev"
|
|
56
|
+
Requires-Dist: mysqlclient>=2.2.2; extra == "dev"
|
|
57
|
+
Requires-Dist: pymssql>=2.2.10; extra == "dev"
|
|
56
58
|
|
|
57
59
|
# database_wrapper
|
|
58
60
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
database_wrapper/__init__.py,sha256=p-HLz9_zByIUeAS1tVxS7ZieslsryHSLw_IKZphqB7w,1200
|
|
2
|
+
database_wrapper/abc.py,sha256=JiQo6Yfv7xALrrHeICJCSgmyP2gHrp16Ov83mPBTGbE,2058
|
|
3
|
+
database_wrapper/common.py,sha256=fsxe28o_4xCrotPbB274dmzQ9rOyes0sBtcHog-9RVc,258
|
|
4
|
+
database_wrapper/config.py,sha256=r8H8ElFt2aifHOvuRwdfRu09_dCjrQe_zNEMLwDZtyY,334
|
|
5
|
+
database_wrapper/db_backend.py,sha256=huueyQH_FW36qQIGx7dofFA2cTqwKZ2r7F2BTaF7K_o,7176
|
|
6
|
+
database_wrapper/db_data_model.py,sha256=boLYcSJZhSUMeeUd21iEERIo5K-oERPG_gBAdfNOKDQ,14077
|
|
7
|
+
database_wrapper/db_wrapper.py,sha256=vpRifOT7e9d6PmlXIQde-tZ4hEceSgzGFO2hwc4XsBI,14353
|
|
8
|
+
database_wrapper/db_wrapper_async.py,sha256=iUcvRZ1L3wNBt0MCx6tSYbtcuN7Kzgq37HkShqnOoXA,14739
|
|
9
|
+
database_wrapper/db_wrapper_mixin.py,sha256=GR6Zn-2GygzzSaFWPIqkiI6mZ8oWqKY_Sc-MeUp6SG8,9966
|
|
10
|
+
database_wrapper/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
database_wrapper/serialization.py,sha256=_yA1srkS6Vec3TMOAYpsCAbJFuB6nrblt8uJrY-7s0E,2046
|
|
12
|
+
database_wrapper/utils/__init__.py,sha256=uC8YaJqfyFIZIeNdTRTbZwcOUVhmnS5eyOG-9gMs70c,96
|
|
13
|
+
database_wrapper/utils/dataclass_addons.py,sha256=r8DD40tXA_DLMQJx62UqVaRe4Gr9BSOmChLRhxawet4,770
|
|
14
|
+
database_wrapper-0.1.72.dist-info/METADATA,sha256=bT8f7OJWnpD5I4CEntQMFaXFKUyxiHw4DeGOxABX9fA,3440
|
|
15
|
+
database_wrapper-0.1.72.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
16
|
+
database_wrapper-0.1.72.dist-info/top_level.txt,sha256=QcnS4ocJygxcKE5eoOqriuja306oVu-zJRn6yjRRhBw,17
|
|
17
|
+
database_wrapper-0.1.72.dist-info/RECORD,,
|
database_wrapper/utils/timer.py
DELETED
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import logging
|
|
3
|
-
|
|
4
|
-
from typing import Any, TypedDict
|
|
5
|
-
from contextlib import asynccontextmanager, contextmanager
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TimerProperties(TypedDict):
|
|
9
|
-
level: int
|
|
10
|
-
total: float
|
|
11
|
-
runtimes: dict[int, float]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class Timer:
|
|
15
|
-
name: str
|
|
16
|
-
|
|
17
|
-
startTimes: dict[str, float]
|
|
18
|
-
totalTimes: dict[str, TimerProperties]
|
|
19
|
-
|
|
20
|
-
timers: list[tuple[int, str]]
|
|
21
|
-
level: int
|
|
22
|
-
runIndex: int
|
|
23
|
-
|
|
24
|
-
def __init__(self, name: str):
|
|
25
|
-
self.name = name
|
|
26
|
-
|
|
27
|
-
self.startTimes = {}
|
|
28
|
-
self.totalTimes = {}
|
|
29
|
-
self.timers = []
|
|
30
|
-
self.level = 0
|
|
31
|
-
self.runIndex = 0
|
|
32
|
-
|
|
33
|
-
# * Class generator
|
|
34
|
-
@contextmanager
|
|
35
|
-
def enter(self, name: str):
|
|
36
|
-
self.level += 1
|
|
37
|
-
self.start(name=name)
|
|
38
|
-
|
|
39
|
-
try:
|
|
40
|
-
yield self
|
|
41
|
-
finally:
|
|
42
|
-
self.stop(name=name)
|
|
43
|
-
self.level -= 1
|
|
44
|
-
|
|
45
|
-
@asynccontextmanager
|
|
46
|
-
async def aenter(self, name: str):
|
|
47
|
-
self.level += 1
|
|
48
|
-
self.start(name=name)
|
|
49
|
-
|
|
50
|
-
try:
|
|
51
|
-
yield self
|
|
52
|
-
finally:
|
|
53
|
-
self.stop(name=name)
|
|
54
|
-
self.level -= 1
|
|
55
|
-
|
|
56
|
-
# * Class context manager
|
|
57
|
-
def __enter__(self) -> "Timer":
|
|
58
|
-
self.start()
|
|
59
|
-
return self
|
|
60
|
-
|
|
61
|
-
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
|
62
|
-
self.stop()
|
|
63
|
-
|
|
64
|
-
async def __aenter__(self) -> "Timer":
|
|
65
|
-
self.start()
|
|
66
|
-
return self
|
|
67
|
-
|
|
68
|
-
async def __aexit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
|
69
|
-
self.stop()
|
|
70
|
-
|
|
71
|
-
# * Start / stop
|
|
72
|
-
def start(self, name: str | None = None, skipAppend: bool = False):
|
|
73
|
-
if name is None:
|
|
74
|
-
name = self.name
|
|
75
|
-
|
|
76
|
-
if len(self.timers) > 0:
|
|
77
|
-
(
|
|
78
|
-
level,
|
|
79
|
-
prevTimerName,
|
|
80
|
-
) = self.timers[-1]
|
|
81
|
-
if prevTimerName != name and level != self.level:
|
|
82
|
-
self.stop(name=prevTimerName, skipRemove=True)
|
|
83
|
-
|
|
84
|
-
self.startTimes[name] = time.perf_counter()
|
|
85
|
-
|
|
86
|
-
if not skipAppend:
|
|
87
|
-
self.timers.append(
|
|
88
|
-
(
|
|
89
|
-
self.level,
|
|
90
|
-
name,
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
def stop(
|
|
95
|
-
self,
|
|
96
|
-
name: str | None = None,
|
|
97
|
-
skipRemove: bool = False,
|
|
98
|
-
):
|
|
99
|
-
if name is None:
|
|
100
|
-
name = self.name
|
|
101
|
-
endTime = time.perf_counter()
|
|
102
|
-
|
|
103
|
-
if not name in self.startTimes:
|
|
104
|
-
logging.getLogger().warning(f"Timer {name} stopped before it was started")
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
elapsed = endTime - self.startTimes[name]
|
|
108
|
-
if not name in self.totalTimes:
|
|
109
|
-
self.totalTimes[name] = TimerProperties(
|
|
110
|
-
level=self.level, total=0, runtimes={}
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
self.totalTimes[name]["runtimes"][self.runIndex] = elapsed
|
|
114
|
-
self.totalTimes[name]["total"] += elapsed
|
|
115
|
-
|
|
116
|
-
if not skipRemove:
|
|
117
|
-
# Remove current timer
|
|
118
|
-
self.timers.pop()
|
|
119
|
-
|
|
120
|
-
# Continue previous timer
|
|
121
|
-
if len(self.timers) > 0:
|
|
122
|
-
(
|
|
123
|
-
level,
|
|
124
|
-
prevTimerName,
|
|
125
|
-
) = self.timers[-1]
|
|
126
|
-
if prevTimerName != name and level != self.level:
|
|
127
|
-
self.start(name=prevTimerName, skipAppend=True)
|
|
128
|
-
|
|
129
|
-
# * Stats
|
|
130
|
-
def resetTimers(self):
|
|
131
|
-
"""Resets the current timer. Call this at the start of an iteration."""
|
|
132
|
-
self.startTimes = {}
|
|
133
|
-
self.totalTimes = {}
|
|
134
|
-
|
|
135
|
-
# * Output
|
|
136
|
-
def printTimerStatsTable(self, returnData: bool = False) -> str | None:
|
|
137
|
-
"""Prints the current timing information into a table."""
|
|
138
|
-
timerStats = "\n\n"
|
|
139
|
-
|
|
140
|
-
all_fn_names = [k for k in self.totalTimes.keys()]
|
|
141
|
-
if len(all_fn_names) == 0:
|
|
142
|
-
return
|
|
143
|
-
|
|
144
|
-
# Max width of level column
|
|
145
|
-
max_level_width = max([self.totalTimes[k].get("level") for k in all_fn_names])
|
|
146
|
-
if max_level_width % 2 == 1:
|
|
147
|
-
max_level_width += 1
|
|
148
|
-
max_level_width = max(max_level_width, 6)
|
|
149
|
-
|
|
150
|
-
# Max width of name column
|
|
151
|
-
max_name_width = max([len(k) for k in all_fn_names] + [4])
|
|
152
|
-
if max_name_width % 2 == 1:
|
|
153
|
-
max_name_width += 1
|
|
154
|
-
|
|
155
|
-
# Format string
|
|
156
|
-
format_str = (
|
|
157
|
-
"{:>%d} | {:>%d} | {:>10.4f} | {:>10.4f} | {:>10.4f} | {:>10.4f} | {:>5}"
|
|
158
|
-
% (
|
|
159
|
-
max_level_width,
|
|
160
|
-
max_name_width,
|
|
161
|
-
)
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
header = (
|
|
165
|
-
"{:>%d} | {:>%d} | {:^10} | {:^10} | {:^10} | {:^10} | {:^5}"
|
|
166
|
-
% (
|
|
167
|
-
max_level_width,
|
|
168
|
-
max_name_width,
|
|
169
|
-
)
|
|
170
|
-
).format(
|
|
171
|
-
"Level", "Name", "Total (ms)", "Min (ms)", "Max (ms)", "Avg (ms)", "Count"
|
|
172
|
-
)
|
|
173
|
-
timerStats += f"{header}\n"
|
|
174
|
-
|
|
175
|
-
sepIdx = header.find("|")
|
|
176
|
-
sepText = ("-" * sepIdx) + "+" + ("-" * (len(header) - sepIdx - 1))
|
|
177
|
-
timerStats += f"{sepText}\n"
|
|
178
|
-
|
|
179
|
-
for name in all_fn_names:
|
|
180
|
-
runtimes = self.totalTimes[name].get("runtimes", {}).values()
|
|
181
|
-
total_time = self.totalTimes[name].get("total", 0) * 1000
|
|
182
|
-
min_time = min(runtimes) * 1000 if runtimes else 0
|
|
183
|
-
max_time = max(runtimes) * 1000 if runtimes else 0
|
|
184
|
-
avg_time = (sum(runtimes) / len(runtimes)) * 1000 if runtimes else 0
|
|
185
|
-
run_count = len(runtimes)
|
|
186
|
-
|
|
187
|
-
timerStats += format_str.format(
|
|
188
|
-
self.totalTimes[name].get("level"),
|
|
189
|
-
name,
|
|
190
|
-
total_time,
|
|
191
|
-
min_time,
|
|
192
|
-
max_time,
|
|
193
|
-
avg_time,
|
|
194
|
-
run_count,
|
|
195
|
-
)
|
|
196
|
-
timerStats += "\n"
|
|
197
|
-
|
|
198
|
-
totals_format_str = (
|
|
199
|
-
"{:>%d} | {:>%d} | {:>10.4f} | {:>10.4} | {:>10.4} | {:>10.4} | {:>10.4}"
|
|
200
|
-
% (
|
|
201
|
-
max_level_width,
|
|
202
|
-
max_name_width,
|
|
203
|
-
)
|
|
204
|
-
)
|
|
205
|
-
timerStats += f"{sepText}\n"
|
|
206
|
-
timerStats += totals_format_str.format(
|
|
207
|
-
"",
|
|
208
|
-
"Total",
|
|
209
|
-
self.totalTime(self.totalTimes) * 1000,
|
|
210
|
-
"",
|
|
211
|
-
"",
|
|
212
|
-
"",
|
|
213
|
-
"",
|
|
214
|
-
)
|
|
215
|
-
timerStats += "\n\n"
|
|
216
|
-
|
|
217
|
-
if returnData:
|
|
218
|
-
return timerStats
|
|
219
|
-
|
|
220
|
-
logging.getLogger().debug(timerStats)
|
|
221
|
-
|
|
222
|
-
def printTimerStatsJSON(self, returnData: bool = False) -> str | None:
|
|
223
|
-
"""Prints the current timing information into a JSON string."""
|
|
224
|
-
pass
|
|
225
|
-
|
|
226
|
-
def printTimerStatsCSV(self, returnData: bool = False) -> str | None:
|
|
227
|
-
"""Prints the current timing information into a CSV string."""
|
|
228
|
-
all_fn_names = list(self.totalTimes.keys())
|
|
229
|
-
if not all_fn_names:
|
|
230
|
-
return
|
|
231
|
-
|
|
232
|
-
# Prepare header
|
|
233
|
-
header = all_fn_names + ["Total"]
|
|
234
|
-
|
|
235
|
-
# Get all runtime indices and find the maximum index
|
|
236
|
-
all_indices: set[int] = set()
|
|
237
|
-
for name in all_fn_names:
|
|
238
|
-
all_indices.update(self.totalTimes[name].get("runtimes", {}).keys())
|
|
239
|
-
max_index = max(all_indices) if all_indices else 0
|
|
240
|
-
|
|
241
|
-
# Prepare data rows
|
|
242
|
-
data_rows: "list[list[str]]" = []
|
|
243
|
-
for i in range(max_index + 1):
|
|
244
|
-
row: "list[str]" = []
|
|
245
|
-
row_total = 0
|
|
246
|
-
for name in all_fn_names:
|
|
247
|
-
runtime = self.totalTimes[name].get("runtimes", {}).get(i)
|
|
248
|
-
if runtime is not None:
|
|
249
|
-
value = runtime * 1000
|
|
250
|
-
row.append(f"{value:.4f}")
|
|
251
|
-
row_total += value
|
|
252
|
-
else:
|
|
253
|
-
row.append("")
|
|
254
|
-
row.append(f"{row_total:.4f}")
|
|
255
|
-
data_rows.append(row)
|
|
256
|
-
|
|
257
|
-
# Prepare total row
|
|
258
|
-
total_row: "list[str]" = []
|
|
259
|
-
grand_total = 0
|
|
260
|
-
for name in all_fn_names:
|
|
261
|
-
total = sum(self.totalTimes[name].get("runtimes", {}).values()) * 1000
|
|
262
|
-
total_row.append(f"{total:.4f}")
|
|
263
|
-
grand_total += total
|
|
264
|
-
total_row.append(f"{grand_total:.4f}")
|
|
265
|
-
|
|
266
|
-
# Combine all rows
|
|
267
|
-
all_rows = [header] + data_rows + [total_row]
|
|
268
|
-
|
|
269
|
-
# Convert to CSV string
|
|
270
|
-
output = "\n".join([",".join(str(cell) for cell in row) for row in all_rows])
|
|
271
|
-
|
|
272
|
-
if returnData:
|
|
273
|
-
return output
|
|
274
|
-
|
|
275
|
-
logging.getLogger().info(f"\n{output}")
|
|
276
|
-
|
|
277
|
-
def printTimerStats(
|
|
278
|
-
self,
|
|
279
|
-
outputFormat: str = "table",
|
|
280
|
-
returnData: bool = False,
|
|
281
|
-
) -> str | None:
|
|
282
|
-
"""
|
|
283
|
-
Prints the current timing information into a table.
|
|
284
|
-
|
|
285
|
-
outputFormat: str - choices: ["table", "json", "csv"]
|
|
286
|
-
"""
|
|
287
|
-
|
|
288
|
-
if outputFormat == "table":
|
|
289
|
-
return self.printTimerStatsTable(returnData=returnData)
|
|
290
|
-
elif outputFormat == "json":
|
|
291
|
-
return self.printTimerStatsJSON(returnData=returnData)
|
|
292
|
-
elif outputFormat == "csv":
|
|
293
|
-
return self.printTimerStatsCSV(returnData=returnData)
|
|
294
|
-
|
|
295
|
-
def totalTime(self, totalTimes: dict[str, TimerProperties]) -> float:
|
|
296
|
-
"""Returns the total amount accumulated across all functions in seconds."""
|
|
297
|
-
return sum([timer.get("total") for _name, timer in totalTimes.items()])
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
database_wrapper/__init__.py,sha256=amoShlhRpOhrFbGeKbdq47H5omcVRd4xWG-RUX7bdIk,830
|
|
2
|
-
database_wrapper/common.py,sha256=fsxe28o_4xCrotPbB274dmzQ9rOyes0sBtcHog-9RVc,258
|
|
3
|
-
database_wrapper/config.py,sha256=hFaefMZ_4XVacDd5n5tPNQVi_fEDbG3ZCB-awE9TPxc,334
|
|
4
|
-
database_wrapper/db_backend.py,sha256=CNfkx-UKVmrR8dSXT5SYpPU3whCL61gxljNVpvcIKXc,5068
|
|
5
|
-
database_wrapper/db_data_model.py,sha256=NV4wfbASIVoSLIXWlHAYxCpVN7-ADKfG6OtYEyTyd_w,12123
|
|
6
|
-
database_wrapper/db_wrapper.py,sha256=O5H7Q8xvvzN4p7KL_NnHflY-EZCfw9TM5mYBzRuJfZA,16488
|
|
7
|
-
database_wrapper/db_wrapper_async.py,sha256=4K-01_UtNxaRgN5qB3j1O2eBX2cOW0xi2ZJJimnqgYw,16714
|
|
8
|
-
database_wrapper/db_wrapper_mixin.py,sha256=-k8Gna_iGE5Gz1gRsVP8sOkUbwX3djjCWeM3ZkGKT7E,10570
|
|
9
|
-
database_wrapper/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
database_wrapper/utils/__init__.py,sha256=mnewmY38-837VAh4f42hvpMUBVUjOLoMtIfdZBxbkg0,134
|
|
11
|
-
database_wrapper/utils/dataclass_addons.py,sha256=5_ZAj8h-4RtimEM-b9lo6TXi4qYVTf7KIjTtu0jzAS4,762
|
|
12
|
-
database_wrapper/utils/timer.py,sha256=ZJpVMsQ7oHHgyuqMOxVee1fZD78kcDrP4c8gHug3xGU,8927
|
|
13
|
-
database_wrapper-0.1.44.dist-info/METADATA,sha256=8ceRUd7R_lUMgLpnzdq78fntrH9BUo2Z-PuiAn_WzNg,3370
|
|
14
|
-
database_wrapper-0.1.44.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
|
15
|
-
database_wrapper-0.1.44.dist-info/top_level.txt,sha256=QcnS4ocJygxcKE5eoOqriuja306oVu-zJRn6yjRRhBw,17
|
|
16
|
-
database_wrapper-0.1.44.dist-info/RECORD,,
|
|
File without changes
|