nercone-modern 1.4.5__py3-none-any.whl → 1.6.0__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.
@@ -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("This is a Prompt. Let's try it: ")
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")
nercone_modern/logging.py CHANGED
@@ -40,69 +40,126 @@ def is_higher_priority(level_a: str, level_b: str) -> bool:
40
40
  raise ValueError(f"Unknown log level: {level_a} or {level_b}")
41
41
 
42
42
  class ModernLogging:
43
- def __init__(self, process_name: str, display_level: str = "INFO"):
43
+ def __init__(self, process_name: str = "App", display_level: str = "INFO", filepath: str | None = None):
44
44
  self.process_name = process_name
45
45
  self.display_level = display_level
46
-
46
+ self.filepath = filepath
47
47
  global _max_proc_width
48
48
  _max_proc_width = max(_max_proc_width, len(process_name))
49
49
 
50
- def log(self, message: str = "", level: str = "INFO"):
51
- if not is_higher_priority(level, self.display_level):
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
52
  return
53
-
54
53
  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
-
54
+ log_line = self.make(message=message, level_text=level_text, level_color=level_color)
55
+ print(log_line)
74
56
  _last_process = self.process_name
75
- _last_level = level_text
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")
76
61
 
77
- def prompt(self, message: str = "", level: str = "INFO") -> str:
78
- if not is_higher_priority(level, self.display_level):
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):
79
64
  return
80
-
81
65
  global _last_process, _last_level
82
- level_text = normalize_level(level.strip().upper())
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())
83
143
  show_proc = (self.process_name != _last_process)
84
144
  show_level = show_proc or (level_text != _last_level)
85
145
 
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):
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):
106
163
  global _max_proc_width
107
164
  level_width = max(MAX_LOG_LEVEL_WIDTH, len(level_text))
108
165
 
@@ -110,9 +167,9 @@ class ModernLogging:
110
167
  proc_part = proc_part.ljust(_max_proc_width) if proc_part else " " * _max_proc_width
111
168
 
112
169
  if show_level:
113
- level_part = f"{self._color(color)}{level_text.ljust(level_width)} |{self._color('reset')}"
170
+ level_part = f"{self._color(level_color)}{level_text.ljust(level_width)} |{self._color('reset')}"
114
171
  else:
115
- level_part = (" " * level_width) + f"{self._color(color)} |{self._color('reset')}"
172
+ level_part = (" " * level_width) + f"{self._color(level_color)} |{self._color('reset')}"
116
173
 
117
174
  return f"{proc_part} {level_part} {str(message)}"
118
175
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nercone-modern
3
- Version: 1.4.5
3
+ Version: 1.6.0
4
4
  Summary: Modern CLI Library
5
5
  Author: Nercone
6
6
  Author-email: Nercone <nercone@diamondgotcat.net>
@@ -0,0 +1,9 @@
1
+ nercone_modern/__init__.py,sha256=ArF3T8FdWIhwGcL4MfYcHqMse3n5gjuyzbLNlcqRcxs,443
2
+ nercone_modern/__main__.py,sha256=7UUBJ71GmMkwOmEbsgMr8LCD2dYo0v5OvBDFkTca39E,2056
3
+ nercone_modern/color.py,sha256=sy7f0Fe07PZWNfM1AOt7HeuhF7uGK2_IuZHEckwgxc4,1328
4
+ nercone_modern/logging.py,sha256=17CcLMKydwgfw7HIs1Ds7bKBbLxXQ677DJ_OO0u73W0,8182
5
+ nercone_modern/progressbar.py,sha256=bzlGg0dSj88eli2lM0cI4xTw2FNJqlJb352jdtJbsWQ,8088
6
+ nercone_modern/text.py,sha256=eGxGQOJ3b-783ocLibkG62cOcYD4HLG_3diA52tU8jI,1031
7
+ nercone_modern-1.6.0.dist-info/WHEEL,sha256=DpNsHFUm_gffZe1FgzmqwuqiuPC6Y-uBCzibcJcdupM,78
8
+ nercone_modern-1.6.0.dist-info/METADATA,sha256=76eB0XA8rWk80YAx2lDdB3aoHrmVOAobj5_DfcOmrRM,2472
9
+ nercone_modern-1.6.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.7
2
+ Generator: uv 0.9.8
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,9 +0,0 @@
1
- nercone_modern/__init__.py,sha256=ArF3T8FdWIhwGcL4MfYcHqMse3n5gjuyzbLNlcqRcxs,443
2
- nercone_modern/__main__.py,sha256=wKQnrGpTKemaaMv1oow_KKQFfPqxzhkz4KAhWBjVcYg,1957
3
- nercone_modern/color.py,sha256=sy7f0Fe07PZWNfM1AOt7HeuhF7uGK2_IuZHEckwgxc4,1328
4
- nercone_modern/logging.py,sha256=p9biozctXNQmesChmn8ozCUKwBSC_5mdelCgbuZ3q0M,4945
5
- nercone_modern/progressbar.py,sha256=bzlGg0dSj88eli2lM0cI4xTw2FNJqlJb352jdtJbsWQ,8088
6
- nercone_modern/text.py,sha256=eGxGQOJ3b-783ocLibkG62cOcYD4HLG_3diA52tU8jI,1031
7
- nercone_modern-1.4.5.dist-info/WHEEL,sha256=5w2T7AS2mz1-rW9CNagNYWRCaB0iQqBMYLwKdlgiR4Q,78
8
- nercone_modern-1.4.5.dist-info/METADATA,sha256=jZPhPnjGBngxi4j_NgDVtFeiZKaedAmJcaPhXTn7CWY,2472
9
- nercone_modern-1.4.5.dist-info/RECORD,,