logger-36 2023.4__py3-none-any.whl → 2023.6__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.
- logger_36/main.py +74 -47
- logger_36/test.py +50 -0
- logger_36/version.py +1 -1
- {logger_36-2023.4.dist-info → logger_36-2023.6.dist-info}/METADATA +1 -1
- logger_36-2023.6.dist-info/RECORD +8 -0
- logger_36-2023.4.dist-info/RECORD +0 -7
- {logger_36-2023.4.dist-info → logger_36-2023.6.dist-info}/WHEEL +0 -0
- {logger_36-2023.4.dist-info → logger_36-2023.6.dist-info}/top_level.txt +0 -0
logger_36/main.py
CHANGED
@@ -46,29 +46,27 @@ try:
|
|
46
46
|
from psutil import Process as process_t
|
47
47
|
|
48
48
|
_PROCESS = process_t()
|
49
|
-
|
50
|
-
|
51
|
-
def UsedMemoryInGb() -> float:
|
52
|
-
""""""
|
53
|
-
return round(_GIGA_SCALING * _PROCESS.memory_info().rss, 1)
|
54
|
-
|
49
|
+
_MEGA_SCALING = 1.0 / (1024.0**2)
|
50
|
+
_GIGA_SCALING = _MEGA_SCALING / 1024.0
|
55
51
|
except ModuleNotFoundError:
|
56
52
|
_PROCESS = None
|
57
|
-
|
58
|
-
def UsedMemoryInGb() -> float:
|
59
|
-
""""""
|
60
|
-
return 0.0
|
53
|
+
_MEGA_SCALING = _GIGA_SCALING = 0.0
|
61
54
|
|
62
55
|
|
63
56
|
# This module is certainly imported early. Therefore, the current time should be close enough to the real start time.
|
64
57
|
_START_TIME = time.time()
|
65
58
|
|
59
|
+
_TERMINAL_WIDTH = 1000
|
60
|
+
_TAB_SIZE = 5
|
66
61
|
|
62
|
+
_WHERE_SEPARATOR = "@"
|
63
|
+
# Tab size is set by console_t so that the dash is aligned for all log levels (might not work for file handlers though)
|
67
64
|
_MESSAGE_FORMAT = (
|
68
|
-
"%(asctime)s[%(levelname)s]\t- "
|
69
|
-
"%(message)s
|
70
|
-
"%(module)s:%(funcName)s:%(lineno)d"
|
65
|
+
f"%(asctime)s[%(levelname)s]\t- "
|
66
|
+
f"%(message)s {_WHERE_SEPARATOR} "
|
67
|
+
f"%(module)s:%(funcName)s:%(lineno)d"
|
71
68
|
)
|
69
|
+
_NEXT_LINE_PROLOGUE = "\n" + (27 + _TAB_SIZE) * " "
|
72
70
|
_DATE_FORMAT = "%Y-%m-%d@%H:%M:%S"
|
73
71
|
|
74
72
|
_SYSTEM_DETAILS = (
|
@@ -93,15 +91,52 @@ _SYSTEM_DETAILS = {_dtl.capitalize(): getattr(pltf, _dtl)() for _dtl in _SYSTEM_
|
|
93
91
|
_MAX_DETAIL_NAME_LENGTH = max(map(len, _SYSTEM_DETAILS.keys()))
|
94
92
|
|
95
93
|
|
96
|
-
#
|
97
|
-
|
94
|
+
# Alternative implementations: using logging.Filter or logging.LoggerAdapter
|
95
|
+
|
96
|
+
|
98
97
|
class _handler_extension:
|
99
|
-
|
100
|
-
|
98
|
+
__slots__ = ("formatter", "show_memory_usage")
|
99
|
+
formatter: lggg.Formatter
|
100
|
+
show_memory_usage: bool
|
101
101
|
|
102
102
|
def __init__(self) -> None:
|
103
103
|
""""""
|
104
104
|
self.formatter = lggg.Formatter(fmt=_MESSAGE_FORMAT, datefmt=_DATE_FORMAT)
|
105
|
+
self.show_memory_usage = False
|
106
|
+
|
107
|
+
def FormattedMessage(
|
108
|
+
self, record: lggg.LogRecord, /
|
109
|
+
) -> tuple[str, list[str] | None]:
|
110
|
+
"""
|
111
|
+
Note: "message" is not yet an attribute of record (it will be set by format()); Use "msg" instead.
|
112
|
+
"""
|
113
|
+
if not isinstance(record.msg, str):
|
114
|
+
record.msg = str(record.msg)
|
115
|
+
if "\n" in record.msg:
|
116
|
+
original_message = record.msg
|
117
|
+
lines = original_message.splitlines()
|
118
|
+
record.msg = lines[0]
|
119
|
+
else:
|
120
|
+
original_message = lines = None
|
121
|
+
|
122
|
+
formatted = self.formatter.format(record)
|
123
|
+
|
124
|
+
# Revert the record message to its original value for subsequent handlers
|
125
|
+
if original_message is not None:
|
126
|
+
record.msg = original_message
|
127
|
+
|
128
|
+
return formatted, lines
|
129
|
+
|
130
|
+
def MemoryUsage(self) -> str:
|
131
|
+
""""""
|
132
|
+
if self.show_memory_usage:
|
133
|
+
usage = _PROCESS.memory_info().rss
|
134
|
+
if usage > _GIGA_SCALING:
|
135
|
+
return f" :{round(_GIGA_SCALING * usage, 1)}GB"
|
136
|
+
else:
|
137
|
+
return f" :{round(_MEGA_SCALING * usage, 1)}MB"
|
138
|
+
|
139
|
+
return ""
|
105
140
|
|
106
141
|
|
107
142
|
class console_handler_t(lggg.Handler, _handler_extension):
|
@@ -116,7 +151,7 @@ class console_handler_t(lggg.Handler, _handler_extension):
|
|
116
151
|
_ACTUAL: ClassVar[str] = r" Actual=[^.]+\."
|
117
152
|
_EXPECTED: ClassVar[str] = r" Expected([!<>]=|: )[^.]+\."
|
118
153
|
|
119
|
-
console: console_t
|
154
|
+
console: console_t
|
120
155
|
|
121
156
|
def __init__(self, /, *, level=lggg.NOTSET) -> None:
|
122
157
|
""""""
|
@@ -125,33 +160,28 @@ class console_handler_t(lggg.Handler, _handler_extension):
|
|
125
160
|
|
126
161
|
self.setFormatter(self.formatter)
|
127
162
|
self.console = console_t(
|
128
|
-
record=True, force_terminal=True, width=
|
163
|
+
record=True, force_terminal=True, width=_TERMINAL_WIDTH, tab_size=_TAB_SIZE
|
129
164
|
)
|
130
165
|
|
131
166
|
def emit(self, record: lggg.LogRecord, /) -> None:
|
132
167
|
""""""
|
133
168
|
cls = self.__class__
|
134
169
|
|
135
|
-
formatted = self.
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
highlighted.append(f" +{ElapsedTime()}{memory_usage}\n", style="green")
|
144
|
-
highlighted.append(" " + "\n ".join(lines[1:]))
|
145
|
-
else:
|
146
|
-
highlighted = text_t(formatted)
|
147
|
-
highlighted.append(f" +{ElapsedTime()}{memory_usage}", style="green")
|
170
|
+
formatted, lines = self.FormattedMessage(record)
|
171
|
+
|
172
|
+
highlighted = text_t(formatted)
|
173
|
+
highlighted.append(f" +{ElapsedTime()}{self.MemoryUsage()}", style="green")
|
174
|
+
if lines is not None:
|
175
|
+
highlighted.append(
|
176
|
+
_NEXT_LINE_PROLOGUE + _NEXT_LINE_PROLOGUE.join(lines[1:])
|
177
|
+
)
|
148
178
|
|
149
179
|
highlighted.stylize("dodger_blue2", end=19)
|
150
180
|
highlighted.highlight_words(
|
151
181
|
(f"[{record.levelname}]",), style=cls._LEVEL_COLOR[record.levelno]
|
152
182
|
)
|
153
183
|
highlighted.highlight_regex(
|
154
|
-
f"
|
184
|
+
f"{_WHERE_SEPARATOR} {record.module}:{record.funcName}:{record.lineno}",
|
155
185
|
style=cls._GRAY_STYLE,
|
156
186
|
)
|
157
187
|
highlighted.highlight_regex(cls._ACTUAL, style="red")
|
@@ -161,26 +191,23 @@ class console_handler_t(lggg.Handler, _handler_extension):
|
|
161
191
|
|
162
192
|
|
163
193
|
class file_handler_t(lggg.FileHandler, _handler_extension):
|
164
|
-
def __init__(self, file: str, *args, **kwargs) -> None:
|
194
|
+
def __init__(self, file: str | path_t, *args, **kwargs) -> None:
|
165
195
|
""""""
|
166
|
-
lggg.FileHandler.__init__(self, file, *args, **kwargs)
|
196
|
+
lggg.FileHandler.__init__(self, str(file), *args, **kwargs)
|
167
197
|
_handler_extension.__init__(self)
|
168
198
|
|
169
199
|
self.setFormatter(self.formatter)
|
170
200
|
|
171
201
|
def emit(self, record: lggg.LogRecord, /) -> None:
|
172
202
|
""""""
|
173
|
-
formatted = self.
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
if "\n" in formatted:
|
179
|
-
lines = formatted.splitlines()
|
180
|
-
next_lines = "\n ".join(lines[1:])
|
181
|
-
message = f"{lines[0]} +{ElapsedTime()}{memory_usage}\n {next_lines}"
|
203
|
+
formatted, lines = self.FormattedMessage(record)
|
204
|
+
formatted = formatted.replace("\t", (9 - record.levelname.__len__()) * " ")
|
205
|
+
|
206
|
+
if lines is None:
|
207
|
+
message = f"{formatted} +{ElapsedTime()}{self.MemoryUsage()}"
|
182
208
|
else:
|
183
|
-
|
209
|
+
next_lines = _NEXT_LINE_PROLOGUE.join(lines[1:])
|
210
|
+
message = f"{formatted} +{ElapsedTime()}{self.MemoryUsage()}{_NEXT_LINE_PROLOGUE}{next_lines}"
|
184
211
|
|
185
212
|
print(message, file=self.stream)
|
186
213
|
self.stream.flush()
|
@@ -213,7 +240,7 @@ def AddFileHandler(file: Union[str, path_t], /) -> None:
|
|
213
240
|
def SaveLOGasHTML(file: Union[str, path_t], /) -> None:
|
214
241
|
""""""
|
215
242
|
if file.exists():
|
216
|
-
|
243
|
+
print(f'Cannot save logging record as HTML: File "{file}" already exists')
|
217
244
|
|
218
245
|
console = None
|
219
246
|
found = False
|
@@ -225,7 +252,7 @@ def SaveLOGasHTML(file: Union[str, path_t], /) -> None:
|
|
225
252
|
with open(file, "w") as accessor:
|
226
253
|
accessor.write(console.export_html())
|
227
254
|
|
228
|
-
|
255
|
+
print("Cannot save logging record as HTML: No handler has a RICH console")
|
229
256
|
|
230
257
|
|
231
258
|
def WhereFunction(function: Any, /) -> str:
|
logger_36/test.py
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright CNRS/Inria/UCA
|
2
|
+
# Contributor(s): Eric Debreuve (since 2023)
|
3
|
+
#
|
4
|
+
# eric.debreuve@cnrs.fr
|
5
|
+
#
|
6
|
+
# This software is governed by the CeCILL license under French law and
|
7
|
+
# abiding by the rules of distribution of free software. You can use,
|
8
|
+
# modify and/ or redistribute the software under the terms of the CeCILL
|
9
|
+
# license as circulated by CEA, CNRS and INRIA at the following URL
|
10
|
+
# "http://www.cecill.info".
|
11
|
+
#
|
12
|
+
# As a counterpart to the access to the source code and rights to copy,
|
13
|
+
# modify and redistribute granted by the license, users are provided only
|
14
|
+
# with a limited warranty and the software's author, the holder of the
|
15
|
+
# economic rights, and the successive licensors have only limited
|
16
|
+
# liability.
|
17
|
+
#
|
18
|
+
# In this respect, the user's attention is drawn to the risks associated
|
19
|
+
# with loading, using, modifying and/or developing or reproducing the
|
20
|
+
# software by the user in light of its specific status of free software,
|
21
|
+
# that may mean that it is complicated to manipulate, and that also
|
22
|
+
# therefore means that it is reserved for developers and experienced
|
23
|
+
# professionals having in-depth computer knowledge. Users are therefore
|
24
|
+
# encouraged to load and test the software's suitability as regards their
|
25
|
+
# requirements in conditions enabling the security of their systems and/or
|
26
|
+
# data to be ensured and, more generally, to use and operate it in the
|
27
|
+
# same conditions as regards security.
|
28
|
+
#
|
29
|
+
# The fact that you are presently reading this means that you have had
|
30
|
+
# knowledge of the CeCILL license and that you accept its terms.
|
31
|
+
|
32
|
+
from pathlib import Path as path_t
|
33
|
+
from tempfile import TemporaryDirectory
|
34
|
+
|
35
|
+
from logger_36 import LOGGER, AddFileHandler
|
36
|
+
|
37
|
+
|
38
|
+
with TemporaryDirectory() as tmp_folder:
|
39
|
+
tmp_folder = path_t(tmp_folder)
|
40
|
+
tmp_file = tmp_folder / "log.txt"
|
41
|
+
|
42
|
+
AddFileHandler(tmp_file)
|
43
|
+
|
44
|
+
for level in ("debug", "info", "warning", "error", "critical"):
|
45
|
+
LogMessage = getattr(LOGGER, level)
|
46
|
+
LogMessage(f"{level.capitalize()} message")
|
47
|
+
LogMessage(f"Multi-line\n{level.capitalize()}\nmessage")
|
48
|
+
|
49
|
+
content = open(tmp_file, "r").read()
|
50
|
+
print(f"\n{content}")
|
logger_36/version.py
CHANGED
@@ -0,0 +1,8 @@
|
|
1
|
+
logger_36/__init__.py,sha256=hoDitcbdJeHgQYTpkAnfYepCxUxkP6lbxPbHkHas3AU,1739
|
2
|
+
logger_36/main.py,sha256=gMML8vC0QmYItGvzrFIQxYohHMTANVdji5Y3FgW2GJQ,10257
|
3
|
+
logger_36/test.py,sha256=8bh0i-HZaZVImf66M0F-0R-T_PI6gYlPxO44KbCjI5s,2118
|
4
|
+
logger_36/version.py,sha256=r36L0uTNUpNnKoBVQqEARtyQO1bzYXBVu9Z2Af_Lnjg,1575
|
5
|
+
logger_36-2023.6.dist-info/METADATA,sha256=aosgF4UGoXIRGGc5XodWc0CKGtciMbpqpIlG0TaviBs,4241
|
6
|
+
logger_36-2023.6.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
7
|
+
logger_36-2023.6.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
|
8
|
+
logger_36-2023.6.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
logger_36/__init__.py,sha256=hoDitcbdJeHgQYTpkAnfYepCxUxkP6lbxPbHkHas3AU,1739
|
2
|
-
logger_36/main.py,sha256=3B9rupYmD9uetFeHzb_dk8l_7sx51-in1-yYbV3abpg,9227
|
3
|
-
logger_36/version.py,sha256=mwuHINlUSknBMxwdd964m2zq-4spq-ceuSw63CAiS0A,1575
|
4
|
-
logger_36-2023.4.dist-info/METADATA,sha256=tUdw-rpD5BJ3194-Uh337d3MccZwVFJ9F3Mf08BaTJU,4241
|
5
|
-
logger_36-2023.4.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
6
|
-
logger_36-2023.4.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
|
7
|
-
logger_36-2023.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|