jsghh-logger 0.2.0__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.
- jsghh_logger-0.2.0/PKG-INFO +5 -0
- jsghh_logger-0.2.0/pyproject.toml +10 -0
- jsghh_logger-0.2.0/setup.cfg +4 -0
- jsghh_logger-0.2.0/src/jsghh_logger.egg-info/PKG-INFO +5 -0
- jsghh_logger-0.2.0/src/jsghh_logger.egg-info/SOURCES.txt +7 -0
- jsghh_logger-0.2.0/src/jsghh_logger.egg-info/dependency_links.txt +1 -0
- jsghh_logger-0.2.0/src/jsghh_logger.egg-info/top_level.txt +1 -0
- jsghh_logger-0.2.0/src/logger/__init__.py +27 -0
- jsghh_logger-0.2.0/src/logger/core.py +214 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
logger
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from .core import logging_worker as _logging_worker
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
def init(
|
|
5
|
+
# ╔═Locations═╗
|
|
6
|
+
in_console: bool=True,
|
|
7
|
+
# ╔═Display═╗
|
|
8
|
+
color_mode: Literal["none","simple","extended","full","custom"]="simple",
|
|
9
|
+
format: Literal["none","simple","extended","full"]="simple",
|
|
10
|
+
show_timestamp: bool=False,
|
|
11
|
+
# ╔═Callstack═╗
|
|
12
|
+
show_full_stack: bool=False,
|
|
13
|
+
):
|
|
14
|
+
"""### Returns a LoggerV2 worker instance.
|
|
15
|
+
|
|
16
|
+
### example usage:
|
|
17
|
+
```
|
|
18
|
+
>>>l = logger.init(*ARGS)
|
|
19
|
+
>>>l.success("Logger initialized!")
|
|
20
|
+
```
|
|
21
|
+
prints `Logger initialized!` in the given style options."""
|
|
22
|
+
return _logging_worker(in_console=in_console,
|
|
23
|
+
color_mode=color_mode,
|
|
24
|
+
format=format,
|
|
25
|
+
show_timestamp=show_timestamp,
|
|
26
|
+
show_full_stack=show_full_stack
|
|
27
|
+
)
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Full logging module for easy debugging of code
|
|
3
|
+
|
|
4
|
+
Start a worker with `logger.init(*ARGS)`
|
|
5
|
+
"""
|
|
6
|
+
from typing import Literal
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
import sys,re
|
|
9
|
+
|
|
10
|
+
class logging_worker():
|
|
11
|
+
|
|
12
|
+
colorMap = {
|
|
13
|
+
"ansi": {
|
|
14
|
+
"info": "\033[94m",
|
|
15
|
+
"success": "\033[92m",
|
|
16
|
+
"warn": "\033[93m",
|
|
17
|
+
"error": "\033[91m",
|
|
18
|
+
"magenta": "\033[35m", # for caller
|
|
19
|
+
"gray": "\033[90m", # for timestamp
|
|
20
|
+
"startBold":"\033[1m",
|
|
21
|
+
"endBold": "\033[22m",
|
|
22
|
+
"reset": "\033[0m"
|
|
23
|
+
},
|
|
24
|
+
"html": { # BASE COLOR: #CCCCCC !!!
|
|
25
|
+
"info": "<span style=\'color:#3B8EEA\'>",
|
|
26
|
+
"success": "<span style=\'color:#23D18B\'>",
|
|
27
|
+
"warn": "<span style=\'color:#F5F543\'>",
|
|
28
|
+
"error": "<span style=\'color:#F14C4C\'>",
|
|
29
|
+
"magenta": "<span style=\'color:#BC3FBC\'>", # for caller
|
|
30
|
+
"gray": "<span style=\'color:#666666\'>", # for timestamp
|
|
31
|
+
"startBold":"<b>",
|
|
32
|
+
"endBold": "</b>",
|
|
33
|
+
"reset": "</span>"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def __init__(self,
|
|
38
|
+
# ╔═Locations═╗
|
|
39
|
+
in_console: bool=True,
|
|
40
|
+
# ╔═Display═╗
|
|
41
|
+
color_mode: Literal["none","simple","extended","full","custom"]="simple",
|
|
42
|
+
format: Literal["none","simple","extended","full"]="simple",
|
|
43
|
+
show_timestamp: bool=False,
|
|
44
|
+
# ╔═Callstack═╗
|
|
45
|
+
show_full_stack: bool=False,
|
|
46
|
+
):
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
self.useConsole = in_console
|
|
51
|
+
|
|
52
|
+
self.colorMode = color_mode
|
|
53
|
+
self.formatting = format
|
|
54
|
+
self.useFullCallStack = show_full_stack
|
|
55
|
+
|
|
56
|
+
self.showTimestamp = show_timestamp
|
|
57
|
+
|
|
58
|
+
self.PreviousStack = []
|
|
59
|
+
|
|
60
|
+
self.TimestampColored = self.colorMode in ("extended", "full")
|
|
61
|
+
self.TimestampBold = self.formatting in ("extended", "full")
|
|
62
|
+
|
|
63
|
+
self.SESSION=datetime.now().isoformat(sep="_",timespec='seconds').replace(":",".")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def log(self, msg:str):
|
|
67
|
+
self._write_message(stack=get_stack(), content=msg, level="info")
|
|
68
|
+
def info(self, msg:str):
|
|
69
|
+
self._write_message(stack=get_stack(), content=msg, level="info")
|
|
70
|
+
def success(self, msg:str):
|
|
71
|
+
self._write_message(stack=get_stack(), content=msg, level="success")
|
|
72
|
+
def warn(self, msg:str):
|
|
73
|
+
self._write_message(stack=get_stack(), content=msg, level="warn")
|
|
74
|
+
def error(self, msg:str):
|
|
75
|
+
self._write_message(stack=get_stack(), content=msg, level="error")
|
|
76
|
+
|
|
77
|
+
def _write_message(self, stack:list[tuple[str|int]], content:str, level:Literal["info","success","warn","error"]):
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# none format: (content)
|
|
81
|
+
# simple format: ("["+level+"] "+none_format)
|
|
82
|
+
# extended format: ("["+level+"/"+stack+"] "+none_format)
|
|
83
|
+
# full format: layered callstack form -> simple format inside
|
|
84
|
+
|
|
85
|
+
# none color mode: white text
|
|
86
|
+
# simple color mode: entire msg in level color
|
|
87
|
+
# extended color mode: level identifier in level color (if printed), else white
|
|
88
|
+
# full color mode: extended + caller in magenta (if printed), else white
|
|
89
|
+
|
|
90
|
+
# timestamp: prefix, bold from format extended+, gray from color mode extended+
|
|
91
|
+
|
|
92
|
+
# show_full_stack: if True, uses full callstack in human readable format
|
|
93
|
+
# if False, only uses highest element
|
|
94
|
+
if self.useConsole:
|
|
95
|
+
msg = self._make_message(stack=stack, content=content, level=level, mode="ansi")
|
|
96
|
+
msglines = msg.split("\n")
|
|
97
|
+
finmsglines = []
|
|
98
|
+
for i in msglines:
|
|
99
|
+
finmsglines.append(((
|
|
100
|
+
str(self.colorMap["ansi"].get("gray") if self.TimestampColored else "") # color if wanted
|
|
101
|
+
+ str(self.colorMap["ansi"].get("startBold") if self.TimestampBold else "") # bold if wanted
|
|
102
|
+
+ str(datetime.now().isoformat(sep="_",timespec='seconds').replace(":",".")) # current time
|
|
103
|
+
+ str(self.colorMap["ansi"].get("endBold") if self.TimestampBold else "") # end bold if needed
|
|
104
|
+
+ str(self.colorMap["ansi"].get("reset") if self.TimestampColored else "") # end color (important for html)
|
|
105
|
+
+ " "
|
|
106
|
+
) if self.showTimestamp==True else "")+i) # only if timestamp is enabled
|
|
107
|
+
|
|
108
|
+
print(
|
|
109
|
+
"\n".join(finmsglines)
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# ...
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
self.PreviousStack = stack if self.useFullCallStack else [stack[-1]]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _make_message(self, stack:list[tuple[str|int]], content:str, level:Literal["info","success","warn","error"], mode:Literal["ansi", "html"]):
|
|
119
|
+
a=(((
|
|
120
|
+
str(self.colorMap[mode].get(level) if self.colorMode=="simple" else "")
|
|
121
|
+
# =PREFIX=
|
|
122
|
+
+ (
|
|
123
|
+
f"{self.colorMap[mode].get(level) if self.colorMode in ("extended", "full") else ""}[{level.upper()}]{" "*(7-len(level))}{self.colorMap[mode].get("reset") if self.colorMode in ("extended", "full") else ""} " if self.formatting=="simple" else
|
|
124
|
+
f"[{self.colorMap[mode].get(level) if self.colorMode in ("extended", "full") else ""}{level.upper()}{self.colorMap[mode].get("reset") if self.colorMode=="full" else ""} | {self.colorMap[mode].get("magenta") if self.colorMode=="full" else ""}{self.format_stack(stack)}{self.colorMap[mode].get("reset") if self.colorMode in ("extended", "full") else ""}] " if self.formatting=="extended" else
|
|
125
|
+
""
|
|
126
|
+
)
|
|
127
|
+
# =MSG=
|
|
128
|
+
|
|
129
|
+
+ content
|
|
130
|
+
+ str(self.colorMap[mode].get("reset") if self.colorMode=="simple" else "")
|
|
131
|
+
) if self.formatting!="full" else (
|
|
132
|
+
((
|
|
133
|
+
" |"*min(len(self.format_stack(stack).split(" > ")), len(self.format_stack(self.PreviousStack).split(" > ")))+"\n"
|
|
134
|
+
) if self.format_stack(stack)!=self.format_stack(self.PreviousStack) else ""
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
+ ("".join([
|
|
138
|
+
(" |"*i+" "+self.colorMap[mode].get("magenta")+e+self.colorMap[mode].get("reset")+"\n")
|
|
139
|
+
for i,e in enumerate(self.format_stack(stack).split(" > "))
|
|
140
|
+
if e not in self.format_stack(self.PreviousStack).split(" > ")
|
|
141
|
+
]))
|
|
142
|
+
+ (f"{" |"*len(self.format_stack(stack).split(" > "))}{self.colorMap[mode].get(level) if self.colorMode in ("simple", "extended", "full") else ""}[{level.upper()}]{" "*(7-len(level))}{self.colorMap[mode].get("reset") if self.colorMode in ("extended", "full") else ""} {content}{self.colorMap[mode].get("reset") if self.colorMode=="simple" else ""}")
|
|
143
|
+
|
|
144
|
+
))
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
return a
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def format_stack(self, stack:list[tuple[str|int]]):
|
|
154
|
+
def format_frame(frame):
|
|
155
|
+
func, path, l = frame
|
|
156
|
+
module = "/".join(path.split("\\")[-2:]).removesuffix(".py")
|
|
157
|
+
func = re.sub(r"[<>]", "__", func)
|
|
158
|
+
return f"{module}.{func}"
|
|
159
|
+
# print(stack)
|
|
160
|
+
if self.useFullCallStack:
|
|
161
|
+
return " > ".join(format_frame(frame) for frame in stack)
|
|
162
|
+
return format_frame(stack[-1]) if stack else ""
|
|
163
|
+
|
|
164
|
+
NOISE = (
|
|
165
|
+
"runpy",
|
|
166
|
+
"debugpy",
|
|
167
|
+
"_pydevd",
|
|
168
|
+
"importlib",
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def get_stack() -> list[tuple[str|int]]:
|
|
172
|
+
frame = sys._getframe()
|
|
173
|
+
stack = []
|
|
174
|
+
|
|
175
|
+
while frame:
|
|
176
|
+
filename = frame.f_code.co_filename
|
|
177
|
+
func = frame.f_code.co_name
|
|
178
|
+
|
|
179
|
+
if not any(x in filename for x in NOISE):
|
|
180
|
+
stack.append((func, filename, frame.f_lineno))
|
|
181
|
+
|
|
182
|
+
frame = frame.f_back
|
|
183
|
+
out=[]
|
|
184
|
+
for i in reversed(stack[2:]):
|
|
185
|
+
out.append(i)
|
|
186
|
+
return out
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# l = logging_worker(
|
|
196
|
+
# in_console=True,
|
|
197
|
+
# color_mode="extended",
|
|
198
|
+
# format="extended",
|
|
199
|
+
# show_timestamp=True,
|
|
200
|
+
# show_full_stack=True
|
|
201
|
+
# )
|
|
202
|
+
|
|
203
|
+
# l._write_message(stack=get_stack(), content="test", level="error")
|
|
204
|
+
# l._write_message(stack=get_stack(), content="test2", level="success")
|
|
205
|
+
|
|
206
|
+
# def a():
|
|
207
|
+
# l._write_message(stack=get_stack(), content="test3", level="info")
|
|
208
|
+
# l._write_message(stack=get_stack(), content="test4", level="warn")
|
|
209
|
+
# def b():
|
|
210
|
+
# l._write_message(stack=get_stack(), content="test5", level="success")
|
|
211
|
+
# l._write_message(stack=get_stack(), content="test6", level="warn")
|
|
212
|
+
# b()
|
|
213
|
+
# l._write_message(stack=get_stack(), content="test67", level="info")
|
|
214
|
+
# a()
|