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.
- {nercone_modern-1.3.0 → nercone_modern-1.5.0}/PKG-INFO +42 -7
- {nercone_modern-1.3.0 → nercone_modern-1.5.0}/README.md +40 -5
- {nercone_modern-1.3.0 → nercone_modern-1.5.0}/pyproject.toml +2 -2
- nercone_modern-1.5.0/src/nercone_modern/color.py +38 -0
- {nercone_modern-1.3.0 → nercone_modern-1.5.0}/src/nercone_modern/logging.py +50 -51
- nercone_modern-1.5.0/src/nercone_modern/text.py +24 -0
- {nercone_modern-1.3.0 → nercone_modern-1.5.0}/src/nercone_modern/__init__.py +0 -0
- {nercone_modern-1.3.0 → nercone_modern-1.5.0}/src/nercone_modern/__main__.py +0 -0
- {nercone_modern-1.3.0 → nercone_modern-1.5.0}/src/nercone_modern/progressbar.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: nercone-modern
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary: Modern
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
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.
|
|
8
|
-
description = "Modern
|
|
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 = "",
|
|
51
|
-
if not is_higher_priority(
|
|
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
|
-
|
|
56
|
-
|
|
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 = "",
|
|
78
|
-
if not is_higher_priority(
|
|
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
|
-
|
|
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
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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(
|
|
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(
|
|
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}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|