nercone-modern 1.3.0__tar.gz → 1.5.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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nercone-modern
3
- Version: 1.3.0
4
- Summary: Modern Logging and Progress Bar Library
3
+ Version: 1.5.0
4
+ Summary: Modern CLI Library
5
5
  Author: Nercone
6
6
  Author-email: Nercone <nercone@diamondgotcat.net>
7
7
  License: MIT
@@ -16,7 +16,7 @@ Description-Content-Type: text/markdown
16
16
  <img width="1920" alt="Nercone Modern" src="https://github.com/user-attachments/assets/c92b0407-916f-46ec-9116-c3388b38c88c" />
17
17
 
18
18
  # nercone-modern
19
- Modern Logging and Progress Bar Library
19
+ Modern CLI Library
20
20
 
21
21
  ## Installation
22
22
 
@@ -38,28 +38,63 @@ pip3 install nercone-modern
38
38
 
39
39
  ## Usage
40
40
 
41
- **Import**
41
+ ### Import
42
42
 
43
43
  ```python
44
+ from nercone_modern.color import ModernColor
45
+ from nercone_modern.text import ModernText
44
46
  from nercone_modern.logging import ModernLogging
45
47
  from nercone_modern.progressbar import ModernProgressBar
46
48
  ```
47
49
 
48
- **Logging**
50
+ ### Color
51
+ ```python
52
+ from nercone_modern.color import ModernColor as Color
53
+ print(f"Build {Color.GREEN}Success{Color.RESET}")
54
+ ```
55
+
56
+ **Supported colors:**
57
+ - `CYAN`
58
+ - `MAGENTA`
59
+ - `YELLOW`
60
+ - `GREEN`
61
+ - `RED`
62
+ - `BLUE`
63
+ - `WHITE`
64
+ - `BLACK`
65
+ - `GRAY`
66
+ - `RESET`
67
+
68
+ ### Text
69
+ ```python
70
+ from nercone_modern.text import ModernText as Text
71
+ from nercone_modern.color import ModernColor as Color
72
+ print("Build" + Text("Success", color="green"))
73
+ print("Build" + Text("Failed", color=Color.RED))
74
+ ```
49
75
 
76
+ ### Logging
50
77
  ```python
78
+ from nercone_modern.logging import ModernLogging
51
79
  logger = ModernLogging("Main", display_level="DEBUG")
52
80
  logger.log("This is a test message", level="INFO")
53
81
  answer = logger.prompt("What's your name?", level="INFO")
54
82
  logger.log(f"Answer: {answer}", level="DEBUG")
55
83
  ```
56
84
 
57
- **Progress Bar**
85
+ **Supported levels:**
86
+ - `DEBUG`
87
+ - `INFO`
88
+ - `WARN`
89
+ - `ERROR`
90
+ - `CRITICAL`
58
91
 
92
+ ### Progress Bar
59
93
  ```python
94
+ from nercone_modern.progressbar import ModernProgressBar
60
95
  progress_bar = ModernProgressBar(total=100, process_name="Task 1", spinner_mode=True)
61
- progress_bar.start()
62
96
 
97
+ progress_bar.start()
63
98
  time.sleep(5)
64
99
 
65
100
  progress_bar.spinner(False)
@@ -2,7 +2,7 @@
2
2
  <img width="1920" alt="Nercone Modern" src="https://github.com/user-attachments/assets/c92b0407-916f-46ec-9116-c3388b38c88c" />
3
3
 
4
4
  # nercone-modern
5
- Modern Logging and Progress Bar Library
5
+ Modern CLI Library
6
6
 
7
7
  ## Installation
8
8
 
@@ -24,28 +24,63 @@ pip3 install nercone-modern
24
24
 
25
25
  ## Usage
26
26
 
27
- **Import**
27
+ ### Import
28
28
 
29
29
  ```python
30
+ from nercone_modern.color import ModernColor
31
+ from nercone_modern.text import ModernText
30
32
  from nercone_modern.logging import ModernLogging
31
33
  from nercone_modern.progressbar import ModernProgressBar
32
34
  ```
33
35
 
34
- **Logging**
36
+ ### Color
37
+ ```python
38
+ from nercone_modern.color import ModernColor as Color
39
+ print(f"Build {Color.GREEN}Success{Color.RESET}")
40
+ ```
41
+
42
+ **Supported colors:**
43
+ - `CYAN`
44
+ - `MAGENTA`
45
+ - `YELLOW`
46
+ - `GREEN`
47
+ - `RED`
48
+ - `BLUE`
49
+ - `WHITE`
50
+ - `BLACK`
51
+ - `GRAY`
52
+ - `RESET`
53
+
54
+ ### Text
55
+ ```python
56
+ from nercone_modern.text import ModernText as Text
57
+ from nercone_modern.color import ModernColor as Color
58
+ print("Build" + Text("Success", color="green"))
59
+ print("Build" + Text("Failed", color=Color.RED))
60
+ ```
35
61
 
62
+ ### Logging
36
63
  ```python
64
+ from nercone_modern.logging import ModernLogging
37
65
  logger = ModernLogging("Main", display_level="DEBUG")
38
66
  logger.log("This is a test message", level="INFO")
39
67
  answer = logger.prompt("What's your name?", level="INFO")
40
68
  logger.log(f"Answer: {answer}", level="DEBUG")
41
69
  ```
42
70
 
43
- **Progress Bar**
71
+ **Supported levels:**
72
+ - `DEBUG`
73
+ - `INFO`
74
+ - `WARN`
75
+ - `ERROR`
76
+ - `CRITICAL`
44
77
 
78
+ ### Progress Bar
45
79
  ```python
80
+ from nercone_modern.progressbar import ModernProgressBar
46
81
  progress_bar = ModernProgressBar(total=100, process_name="Task 1", spinner_mode=True)
47
- progress_bar.start()
48
82
 
83
+ progress_bar.start()
49
84
  time.sleep(5)
50
85
 
51
86
  progress_bar.spinner(False)
@@ -4,8 +4,8 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "nercone-modern"
7
- version = "1.3.0"
8
- description = "Modern Logging and Progress Bar Library"
7
+ version = "1.5.0"
8
+ description = "Modern CLI Library"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  authors = [
11
11
  { name = "Nercone", email = "nercone@diamondgotcat.net" }
@@ -0,0 +1,38 @@
1
+ class ModernColor:
2
+ def ansi_color_by_code(color_code: int | str = 0):
3
+ return f"\033[{color_code}m"
4
+
5
+ def ansi_color(color_name: str = "reset"):
6
+ if color_name == "reset":
7
+ return ModernColor.ansi_color_by_code(0)
8
+ elif color_name == "black":
9
+ return ModernColor.ansi_color_by_code(30)
10
+ elif color_name == "red":
11
+ return ModernColor.ansi_color_by_code(31)
12
+ elif color_name == "green":
13
+ return ModernColor.ansi_color_by_code(32)
14
+ elif color_name == "yellow":
15
+ return ModernColor.ansi_color_by_code(33)
16
+ elif color_name == "blue":
17
+ return ModernColor.ansi_color_by_code(34)
18
+ elif color_name == "magenta":
19
+ return ModernColor.ansi_color_by_code(35)
20
+ elif color_name == "cyan":
21
+ return ModernColor.ansi_color_by_code(36)
22
+ elif color_name == "white":
23
+ return ModernColor.ansi_color_by_code(37)
24
+ elif color_name in ("gray", "grey"):
25
+ return ModernColor.ansi_color_by_code(90)
26
+ else:
27
+ return ""
28
+
29
+ RESET = "\033[0m"
30
+ BLACK = "\033[30m"
31
+ RED = "\033[31m"
32
+ GREEN = "\033[32m"
33
+ YELLOW = "\033[33m"
34
+ BLUE = "\033[34m"
35
+ MAGENTA = "\033[35m"
36
+ CYAN = "\033[36m"
37
+ WHITE = "\033[37m"
38
+ GRAY = "\033[90m"
@@ -40,69 +40,68 @@ 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) -> 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
+ log_line = self.make(message=message, level_text=level_text, level_color=level_color)
67
+ print(log_line, end="")
68
+ _last_process = self.process_name
69
+ _last_level = normalize_level(level_text.strip().upper())
70
+ answer = ""
71
+ try:
72
+ answer = input()
73
+ except KeyboardInterrupt:
74
+ if ignore_kbdinterrupt:
75
+ print()
76
+ else:
77
+ raise
78
+ if self.filepath:
79
+ with open(self.filepath, "a") as f:
80
+ f.write(f"{log_line}{answer}\n")
81
+ return answer
82
+
83
+ def make(self, message: str = "", level_text: str = "INFO", level_color: str | None = None):
84
+ level_text = normalize_level(level_text.strip().upper())
83
85
  show_proc = (self.process_name != _last_process)
84
86
  show_level = show_proc or (level_text != _last_level)
85
87
 
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):
88
+ if not level_color:
89
+ if level_text == "DEBUG":
90
+ level_color = 'gray'
91
+ elif level_text == "INFO":
92
+ level_color = 'blue'
93
+ elif level_text == "WARN":
94
+ level_color = 'yellow'
95
+ elif level_text == "ERROR":
96
+ level_color = 'red'
97
+ elif level_text == "CRITICAL":
98
+ level_color = 'red'
99
+ else:
100
+ level_color = 'blue'
101
+
102
+ return self._make(message, level_text, level_color, show_proc, show_level)
103
+
104
+ def _make(self, message: str, level_text: str, level_color: str, show_proc: bool, show_level: bool):
106
105
  global _max_proc_width
107
106
  level_width = max(MAX_LOG_LEVEL_WIDTH, len(level_text))
108
107
 
@@ -110,9 +109,9 @@ class ModernLogging:
110
109
  proc_part = proc_part.ljust(_max_proc_width) if proc_part else " " * _max_proc_width
111
110
 
112
111
  if show_level:
113
- level_part = f"{self._color(color)}{level_text.ljust(level_width)} |{self._color('reset')}"
112
+ level_part = f"{self._color(level_color)}{level_text.ljust(level_width)} |{self._color('reset')}"
114
113
  else:
115
- level_part = (" " * level_width) + f"{self._color(color)} |{self._color('reset')}"
114
+ level_part = (" " * level_width) + f"{self._color(level_color)} |{self._color('reset')}"
116
115
 
117
116
  return f"{proc_part} {level_part} {str(message)}"
118
117
 
@@ -0,0 +1,24 @@
1
+ from typing import Union
2
+ from .color import ModernColor
3
+
4
+ class ModernText:
5
+ def __init__(self, content="", color: str = ModernColor.WHITE):
6
+ self.content = content
7
+ if not color.startswith("\033"):
8
+ color = getattr(ModernColor, color.upper(), ModernColor.WHITE)
9
+ self.color = color
10
+
11
+ def __add__(self, other: Union[str, "ModernText"]):
12
+ if isinstance(other, ModernText):
13
+ if self.color == other.color:
14
+ return ModernText(self.content + other.content, self.color)
15
+ else:
16
+ combined = f"{self.color}{self.content}{ModernColor.RESET}{other.color}{other.content}"
17
+ return ModernText(combined, ModernColor.RESET)
18
+ elif isinstance(other, str):
19
+ return ModernText(self.content + other, self.color)
20
+ else:
21
+ raise TypeError(f"Unsupported operand type(s) for +: 'ModernText' and '{type(other).__name__}'")
22
+
23
+ def __str__(self):
24
+ return f"{self.color}{self.content}{ModernColor.RESET}"