nercone-modern 1.4.5__tar.gz → 1.6.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.
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/PKG-INFO +1 -1
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/pyproject.toml +1 -1
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/src/nercone_modern/__main__.py +4 -1
- nercone_modern-1.6.0/src/nercone_modern/logging.py +201 -0
- nercone_modern-1.4.5/src/nercone_modern/logging.py +0 -144
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/README.md +0 -0
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/src/nercone_modern/__init__.py +0 -0
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/src/nercone_modern/color.py +0 -0
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/src/nercone_modern/progressbar.py +0 -0
- {nercone_modern-1.4.5 → nercone_modern-1.6.0}/src/nercone_modern/text.py +0 -0
|
@@ -22,8 +22,11 @@ try:
|
|
|
22
22
|
logger1.log("This is a warning message", "WARNING")
|
|
23
23
|
logger1.log("This is a error message", "ERROR")
|
|
24
24
|
logger1.log("This is a critical error message", "CRITICAL")
|
|
25
|
-
prompt_result = logger1.prompt("
|
|
25
|
+
prompt_result = logger1.prompt("Continue demo?", choices=["Y", "n"])
|
|
26
26
|
logger1.log(f"Answer is: {prompt_result}", "INFO")
|
|
27
|
+
if prompt_result == "n":
|
|
28
|
+
print("Exiting demo. See you!")
|
|
29
|
+
raise SystemExit(0)
|
|
27
30
|
|
|
28
31
|
progress_bar1 = ModernProgressBar(total=100, process_name="Task 1", spinner_mode=False)
|
|
29
32
|
progress_bar1.setMessage("WAITING")
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# -- nercone-modern --------------------------------------------- #
|
|
4
|
+
# logging.py on nercone-modern #
|
|
5
|
+
# Made by DiamondGotCat, Licensed under MIT License #
|
|
6
|
+
# Copyright (c) 2025 DiamondGotCat #
|
|
7
|
+
# ---------------------------------------------- DiamondGotCat -- #
|
|
8
|
+
|
|
9
|
+
ModernLoggingLevels = ["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL"]
|
|
10
|
+
MAX_LOG_LEVEL_WIDTH = max(len(level) for level in ModernLoggingLevels)
|
|
11
|
+
LEVEL_ALIASES = {
|
|
12
|
+
"D": "DEBUG",
|
|
13
|
+
"DEBUG": "DEBUG",
|
|
14
|
+
"I": "INFO",
|
|
15
|
+
"INFO": "INFO",
|
|
16
|
+
"INFORMATION": "INFO",
|
|
17
|
+
"W": "WARN",
|
|
18
|
+
"WARN": "WARN",
|
|
19
|
+
"WARNING": "WARN",
|
|
20
|
+
"E": "ERROR",
|
|
21
|
+
"ERROR": "ERROR",
|
|
22
|
+
"C": "CRITICAL",
|
|
23
|
+
"CRITICAL": "CRITICAL"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
_last_process = None
|
|
27
|
+
_last_level = None
|
|
28
|
+
_max_proc_width = 0
|
|
29
|
+
|
|
30
|
+
def normalize_level(level: str) -> str:
|
|
31
|
+
level = level.strip().upper()
|
|
32
|
+
return LEVEL_ALIASES.get(level, level)
|
|
33
|
+
|
|
34
|
+
def is_higher_priority(level_a: str, level_b: str) -> bool:
|
|
35
|
+
a = normalize_level(level_a)
|
|
36
|
+
b = normalize_level(level_b)
|
|
37
|
+
try:
|
|
38
|
+
return ModernLoggingLevels.index(a) >= ModernLoggingLevels.index(b)
|
|
39
|
+
except ValueError:
|
|
40
|
+
raise ValueError(f"Unknown log level: {level_a} or {level_b}")
|
|
41
|
+
|
|
42
|
+
class ModernLogging:
|
|
43
|
+
def __init__(self, process_name: str = "App", display_level: str = "INFO", filepath: str | None = None):
|
|
44
|
+
self.process_name = process_name
|
|
45
|
+
self.display_level = display_level
|
|
46
|
+
self.filepath = filepath
|
|
47
|
+
global _max_proc_width
|
|
48
|
+
_max_proc_width = max(_max_proc_width, len(process_name))
|
|
49
|
+
|
|
50
|
+
def log(self, message: str = "", level_text: str = "INFO", level_color: str | None = None):
|
|
51
|
+
if not is_higher_priority(level_text, self.display_level):
|
|
52
|
+
return
|
|
53
|
+
global _last_process, _last_level
|
|
54
|
+
log_line = self.make(message=message, level_text=level_text, level_color=level_color)
|
|
55
|
+
print(log_line)
|
|
56
|
+
_last_process = self.process_name
|
|
57
|
+
_last_level = normalize_level(level_text.strip().upper())
|
|
58
|
+
if self.filepath:
|
|
59
|
+
with open(self.filepath, "a") as f:
|
|
60
|
+
f.write(f"{log_line}\n")
|
|
61
|
+
|
|
62
|
+
def prompt(self, message: str = "", level_text: str = "INFO", level_color: str | None = None, ignore_kbdinterrupt: bool = True, default: str | None = None, choices: list[str] | None = None, show_choices: bool = True) -> str:
|
|
63
|
+
if not is_higher_priority(level_text, self.display_level):
|
|
64
|
+
return
|
|
65
|
+
global _last_process, _last_level
|
|
66
|
+
if default:
|
|
67
|
+
message += f" ({default})"
|
|
68
|
+
if choices and show_choices:
|
|
69
|
+
message += f" [{'/'.join(choices)}]"
|
|
70
|
+
if not message.endswith(" "):
|
|
71
|
+
message += " "
|
|
72
|
+
log_line = self.make(message=message, level_text=level_text, level_color=level_color)
|
|
73
|
+
print(log_line, end="")
|
|
74
|
+
_last_process = self.process_name
|
|
75
|
+
_last_level = normalize_level(level_text.strip().upper())
|
|
76
|
+
answer = ""
|
|
77
|
+
try:
|
|
78
|
+
answer = input()
|
|
79
|
+
except KeyboardInterrupt:
|
|
80
|
+
if ignore_kbdinterrupt:
|
|
81
|
+
print()
|
|
82
|
+
else:
|
|
83
|
+
raise
|
|
84
|
+
if answer.strip() == "" and default is not None:
|
|
85
|
+
if choices:
|
|
86
|
+
selected_default = self._select_choice(default, choices)
|
|
87
|
+
if selected_default is not None:
|
|
88
|
+
answer = default
|
|
89
|
+
else:
|
|
90
|
+
answer = default
|
|
91
|
+
if self.filepath:
|
|
92
|
+
with open(self.filepath, "a") as f:
|
|
93
|
+
f.write(f"{log_line}{answer}\n")
|
|
94
|
+
if choices:
|
|
95
|
+
selected = self._select_choice(answer, choices)
|
|
96
|
+
if selected is not None:
|
|
97
|
+
return selected
|
|
98
|
+
else:
|
|
99
|
+
while True:
|
|
100
|
+
log_line = self.make(message=f"Invalid selection. Please select from: {'/'.join(choices)}", level_text=level_text, level_color=level_color)
|
|
101
|
+
print(log_line, end="")
|
|
102
|
+
if self.filepath:
|
|
103
|
+
with open(self.filepath, "a") as f:
|
|
104
|
+
f.write(f"{log_line}{answer}\n")
|
|
105
|
+
log_line = self.make(message=message, level_text=level_text, level_color=level_color)
|
|
106
|
+
print(log_line, end="")
|
|
107
|
+
try:
|
|
108
|
+
answer = input()
|
|
109
|
+
except KeyboardInterrupt:
|
|
110
|
+
if ignore_kbdinterrupt:
|
|
111
|
+
print()
|
|
112
|
+
else:
|
|
113
|
+
raise
|
|
114
|
+
if self.filepath:
|
|
115
|
+
with open(self.filepath, "a") as f:
|
|
116
|
+
f.write(f"{log_line}{answer}\n")
|
|
117
|
+
if answer.strip() == "" and default is not None:
|
|
118
|
+
if choices:
|
|
119
|
+
selected_default = self._select_choice(default, choices)
|
|
120
|
+
if selected_default is not None:
|
|
121
|
+
return default
|
|
122
|
+
else:
|
|
123
|
+
return default
|
|
124
|
+
selected = self._select_choice(answer, choices)
|
|
125
|
+
if selected is not None:
|
|
126
|
+
return selected
|
|
127
|
+
|
|
128
|
+
def _select_choice(self, answer: str, choices: list[str]) -> str | None:
|
|
129
|
+
if answer in choices:
|
|
130
|
+
return answer
|
|
131
|
+
stripped = answer.strip()
|
|
132
|
+
if stripped in choices:
|
|
133
|
+
return stripped
|
|
134
|
+
lower_map = {c.lower(): c for c in choices}
|
|
135
|
+
if answer.lower() in lower_map:
|
|
136
|
+
return lower_map[answer.lower()]
|
|
137
|
+
if stripped.lower() in lower_map:
|
|
138
|
+
return lower_map[stripped.lower()]
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
def make(self, message: str = "", level_text: str = "INFO", level_color: str | None = None):
|
|
142
|
+
level_text = normalize_level(level_text.strip().upper())
|
|
143
|
+
show_proc = (self.process_name != _last_process)
|
|
144
|
+
show_level = show_proc or (level_text != _last_level)
|
|
145
|
+
|
|
146
|
+
if not level_color:
|
|
147
|
+
if level_text == "DEBUG":
|
|
148
|
+
level_color = 'gray'
|
|
149
|
+
elif level_text == "INFO":
|
|
150
|
+
level_color = 'blue'
|
|
151
|
+
elif level_text == "WARN":
|
|
152
|
+
level_color = 'yellow'
|
|
153
|
+
elif level_text == "ERROR":
|
|
154
|
+
level_color = 'red'
|
|
155
|
+
elif level_text == "CRITICAL":
|
|
156
|
+
level_color = 'red'
|
|
157
|
+
else:
|
|
158
|
+
level_color = 'blue'
|
|
159
|
+
|
|
160
|
+
return self._make(message, level_text, level_color, show_proc, show_level)
|
|
161
|
+
|
|
162
|
+
def _make(self, message: str, level_text: str, level_color: str, show_proc: bool, show_level: bool):
|
|
163
|
+
global _max_proc_width
|
|
164
|
+
level_width = max(MAX_LOG_LEVEL_WIDTH, len(level_text))
|
|
165
|
+
|
|
166
|
+
proc_part = self.process_name if show_proc else ""
|
|
167
|
+
proc_part = proc_part.ljust(_max_proc_width) if proc_part else " " * _max_proc_width
|
|
168
|
+
|
|
169
|
+
if show_level:
|
|
170
|
+
level_part = f"{self._color(level_color)}{level_text.ljust(level_width)} |{self._color('reset')}"
|
|
171
|
+
else:
|
|
172
|
+
level_part = (" " * level_width) + f"{self._color(level_color)} |{self._color('reset')}"
|
|
173
|
+
|
|
174
|
+
return f"{proc_part} {level_part} {str(message)}"
|
|
175
|
+
|
|
176
|
+
def _color(self, color_name: str = "reset"):
|
|
177
|
+
if color_name == "cyan":
|
|
178
|
+
return self._color_by_code(36)
|
|
179
|
+
elif color_name == "magenta":
|
|
180
|
+
return self._color_by_code(35)
|
|
181
|
+
elif color_name == "yellow":
|
|
182
|
+
return self._color_by_code(33)
|
|
183
|
+
elif color_name == "green":
|
|
184
|
+
return self._color_by_code(32)
|
|
185
|
+
elif color_name == "red":
|
|
186
|
+
return self._color_by_code(31)
|
|
187
|
+
elif color_name == "blue":
|
|
188
|
+
return self._color_by_code(34)
|
|
189
|
+
elif color_name == "white":
|
|
190
|
+
return self._color_by_code(37)
|
|
191
|
+
elif color_name == "black":
|
|
192
|
+
return self._color_by_code(30)
|
|
193
|
+
elif color_name in ("gray", "grey"):
|
|
194
|
+
return self._color_by_code(90)
|
|
195
|
+
elif color_name == "reset":
|
|
196
|
+
return self._color_by_code(0)
|
|
197
|
+
else:
|
|
198
|
+
return ""
|
|
199
|
+
|
|
200
|
+
def _color_by_code(self, color_code: int | str = 0):
|
|
201
|
+
return f"\033[{color_code}m"
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
# -- nercone-modern --------------------------------------------- #
|
|
4
|
-
# logging.py on nercone-modern #
|
|
5
|
-
# Made by DiamondGotCat, Licensed under MIT License #
|
|
6
|
-
# Copyright (c) 2025 DiamondGotCat #
|
|
7
|
-
# ---------------------------------------------- DiamondGotCat -- #
|
|
8
|
-
|
|
9
|
-
ModernLoggingLevels = ["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL"]
|
|
10
|
-
MAX_LOG_LEVEL_WIDTH = max(len(level) for level in ModernLoggingLevels)
|
|
11
|
-
LEVEL_ALIASES = {
|
|
12
|
-
"D": "DEBUG",
|
|
13
|
-
"DEBUG": "DEBUG",
|
|
14
|
-
"I": "INFO",
|
|
15
|
-
"INFO": "INFO",
|
|
16
|
-
"INFORMATION": "INFO",
|
|
17
|
-
"W": "WARN",
|
|
18
|
-
"WARN": "WARN",
|
|
19
|
-
"WARNING": "WARN",
|
|
20
|
-
"E": "ERROR",
|
|
21
|
-
"ERROR": "ERROR",
|
|
22
|
-
"C": "CRITICAL",
|
|
23
|
-
"CRITICAL": "CRITICAL"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
_last_process = None
|
|
27
|
-
_last_level = None
|
|
28
|
-
_max_proc_width = 0
|
|
29
|
-
|
|
30
|
-
def normalize_level(level: str) -> str:
|
|
31
|
-
level = level.strip().upper()
|
|
32
|
-
return LEVEL_ALIASES.get(level, level)
|
|
33
|
-
|
|
34
|
-
def is_higher_priority(level_a: str, level_b: str) -> bool:
|
|
35
|
-
a = normalize_level(level_a)
|
|
36
|
-
b = normalize_level(level_b)
|
|
37
|
-
try:
|
|
38
|
-
return ModernLoggingLevels.index(a) >= ModernLoggingLevels.index(b)
|
|
39
|
-
except ValueError:
|
|
40
|
-
raise ValueError(f"Unknown log level: {level_a} or {level_b}")
|
|
41
|
-
|
|
42
|
-
class ModernLogging:
|
|
43
|
-
def __init__(self, process_name: str, display_level: str = "INFO"):
|
|
44
|
-
self.process_name = process_name
|
|
45
|
-
self.display_level = display_level
|
|
46
|
-
|
|
47
|
-
global _max_proc_width
|
|
48
|
-
_max_proc_width = max(_max_proc_width, len(process_name))
|
|
49
|
-
|
|
50
|
-
def log(self, message: str = "", level: str = "INFO"):
|
|
51
|
-
if not is_higher_priority(level, self.display_level):
|
|
52
|
-
return
|
|
53
|
-
|
|
54
|
-
global _last_process, _last_level
|
|
55
|
-
level_text = normalize_level(level.strip().upper())
|
|
56
|
-
show_proc = (self.process_name != _last_process)
|
|
57
|
-
show_level = show_proc or (level_text != _last_level)
|
|
58
|
-
|
|
59
|
-
if level_text == "DEBUG":
|
|
60
|
-
color = 'gray'
|
|
61
|
-
elif level_text == "INFO":
|
|
62
|
-
color = 'blue'
|
|
63
|
-
elif level_text == "WARN":
|
|
64
|
-
color = 'yellow'
|
|
65
|
-
elif level_text == "ERROR":
|
|
66
|
-
color = 'red'
|
|
67
|
-
elif level_text == "CRITICAL":
|
|
68
|
-
color = 'red'
|
|
69
|
-
else:
|
|
70
|
-
color = 'blue'
|
|
71
|
-
|
|
72
|
-
print(self._make(message, level_text, color, show_proc, show_level))
|
|
73
|
-
|
|
74
|
-
_last_process = self.process_name
|
|
75
|
-
_last_level = level_text
|
|
76
|
-
|
|
77
|
-
def prompt(self, message: str = "", level: str = "INFO") -> str:
|
|
78
|
-
if not is_higher_priority(level, self.display_level):
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
global _last_process, _last_level
|
|
82
|
-
level_text = normalize_level(level.strip().upper())
|
|
83
|
-
show_proc = (self.process_name != _last_process)
|
|
84
|
-
show_level = show_proc or (level_text != _last_level)
|
|
85
|
-
|
|
86
|
-
if level_text == "DEBUG":
|
|
87
|
-
color = 'gray'
|
|
88
|
-
elif level_text == "INFO":
|
|
89
|
-
color = 'blue'
|
|
90
|
-
elif level_text == "WARN":
|
|
91
|
-
color = 'yellow'
|
|
92
|
-
elif level_text == "ERROR":
|
|
93
|
-
color = 'red'
|
|
94
|
-
elif level_text == "CRITICAL":
|
|
95
|
-
color = 'red'
|
|
96
|
-
else:
|
|
97
|
-
color = 'blue'
|
|
98
|
-
|
|
99
|
-
print(self._make(message, level_text, color, show_proc, show_level), end="")
|
|
100
|
-
|
|
101
|
-
_last_process = self.process_name
|
|
102
|
-
_last_level = level_text
|
|
103
|
-
return input()
|
|
104
|
-
|
|
105
|
-
def _make(self, message: str, level_text: str, color: str, show_proc: bool, show_level: bool):
|
|
106
|
-
global _max_proc_width
|
|
107
|
-
level_width = max(MAX_LOG_LEVEL_WIDTH, len(level_text))
|
|
108
|
-
|
|
109
|
-
proc_part = self.process_name if show_proc else ""
|
|
110
|
-
proc_part = proc_part.ljust(_max_proc_width) if proc_part else " " * _max_proc_width
|
|
111
|
-
|
|
112
|
-
if show_level:
|
|
113
|
-
level_part = f"{self._color(color)}{level_text.ljust(level_width)} |{self._color('reset')}"
|
|
114
|
-
else:
|
|
115
|
-
level_part = (" " * level_width) + f"{self._color(color)} |{self._color('reset')}"
|
|
116
|
-
|
|
117
|
-
return f"{proc_part} {level_part} {str(message)}"
|
|
118
|
-
|
|
119
|
-
def _color(self, color_name: str = "reset"):
|
|
120
|
-
if color_name == "cyan":
|
|
121
|
-
return self._color_by_code(36)
|
|
122
|
-
elif color_name == "magenta":
|
|
123
|
-
return self._color_by_code(35)
|
|
124
|
-
elif color_name == "yellow":
|
|
125
|
-
return self._color_by_code(33)
|
|
126
|
-
elif color_name == "green":
|
|
127
|
-
return self._color_by_code(32)
|
|
128
|
-
elif color_name == "red":
|
|
129
|
-
return self._color_by_code(31)
|
|
130
|
-
elif color_name == "blue":
|
|
131
|
-
return self._color_by_code(34)
|
|
132
|
-
elif color_name == "white":
|
|
133
|
-
return self._color_by_code(37)
|
|
134
|
-
elif color_name == "black":
|
|
135
|
-
return self._color_by_code(30)
|
|
136
|
-
elif color_name in ("gray", "grey"):
|
|
137
|
-
return self._color_by_code(90)
|
|
138
|
-
elif color_name == "reset":
|
|
139
|
-
return self._color_by_code(0)
|
|
140
|
-
else:
|
|
141
|
-
return ""
|
|
142
|
-
|
|
143
|
-
def _color_by_code(self, color_code: int | str = 0):
|
|
144
|
-
return f"\033[{color_code}m"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|