spanlogger 1.0.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rowsvips
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: spanlogger
3
+ Version: 1.0.0
4
+ Summary: Professional colored terminal logger with timestamps, symbols, and title bar support.
5
+ Author: rowsvips
6
+ License: MIT
7
+ Project-URL: Homepage, https://vmshops.mysellauth.com
8
+ Keywords: logger,terminal,colored,console,logging,ansi,cli
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: System :: Logging
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Dynamic: license-file
27
+
28
+ # spanlogger
29
+
30
+ Professional colored terminal logger for Python by **rowsvips**.
31
+
32
+ Zero dependencies. Thread-safe. Windows & Linux compatible.
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install spanlogger
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ from spanlogger import Logger, Colors
44
+
45
+ log = Logger(title="MyApp", show_time=True)
46
+
47
+ log.info("Application started")
48
+ log.success("Connected to server")
49
+ log.warning("Rate limit approaching")
50
+ log.error("Connection failed")
51
+ log.money("Payment received [$50.00]")
52
+ log.debug("Internal state: ok")
53
+ log.captcha("Captcha detected on session_abc****")
54
+ log.custom("Special event", symbol="★", color=Colors.BRIGHT_YELLOW)
55
+ ```
56
+
57
+ ## Output
58
+
59
+ ```
60
+ 07:23 AM [¥] Application started
61
+ 07:23 AM [+] Connected to server
62
+ 07:23 AM [!] Rate limit approaching
63
+ 07:23 AM [-] Connection failed
64
+ 07:23 AM [$] Payment received [$50.00]
65
+ 07:23 AM [~] Internal state: ok
66
+ 07:23 AM [¥] Captcha detected on session_abc****
67
+ 07:23 AM [★] Special event
68
+ ```
69
+
70
+ ## Title Bar
71
+
72
+ ```python
73
+ log.print_title_bar(
74
+ "MyApp v1.0",
75
+ "@rowsvips",
76
+ "vmshops.mysellauth.com",
77
+ stats={"Success": 10, "Failed": 2}
78
+ )
79
+ ```
80
+
81
+ ```
82
+ ────────────────────────────────────────────────────────────────────────────────
83
+ MyApp v1.0 | @rowsvips | vmshops.mysellauth.com | Success: 10 - Failed: 2
84
+ ────────────────────────────────────────────────────────────────────────────────
85
+ ```
86
+
87
+ ## Console Window Title
88
+
89
+ ```python
90
+ log.set_title("MyApp v1.0", "@rowsvips")
91
+ log.set_title_stats(Success=10, Failed=2, Captcha=5)
92
+ ```
93
+
94
+ ## Counter System
95
+
96
+ ```python
97
+ log.increment("success")
98
+ log.increment("failed", 3)
99
+
100
+ print(log.get_count("success"))
101
+ print(log.get_all_counts())
102
+
103
+ log.reset_counts()
104
+ ```
105
+
106
+ ## Contextual Helpers
107
+
108
+ ```python
109
+ log.redeemed("code_abc****", "session_123****", "[AT: 2.5s | Type: Premium]")
110
+ log.failed("Process Task", "Error: session expired")
111
+ log.added("Account", "user_xyz****", "session_123****")
112
+ log.removed("Session", "session_old****")
113
+ log.thread_sleep(5, "Before retry")
114
+ ```
115
+
116
+ ## Custom Symbols & Colors
117
+
118
+ ```python
119
+ log.custom("Diamond", symbol="♦", color=Colors.BRIGHT_MAGENTA)
120
+ log.custom("Heart", symbol="♥", color=Colors.BRIGHT_RED)
121
+ log.custom("Arrow", symbol="→", color=Colors.BRIGHT_CYAN)
122
+ ```
123
+
124
+ ## Inline Colored Text
125
+
126
+ ```python
127
+ token = Logger.colorize("session_abc****", Colors.BRIGHT_CYAN)
128
+ log.info(f"Processing on {token}")
129
+
130
+ log.info(f"Status: {Logger.bold('ACTIVE')}")
131
+ ```
132
+
133
+ ## Utilities
134
+
135
+ ```python
136
+ log.separator()
137
+ log.separator(char="=", length=40, color=Colors.CYAN)
138
+
139
+ log.blank()
140
+ log.clear()
141
+
142
+ log.banner("All Done!", color=Colors.BRIGHT_GREEN, width=50)
143
+ ```
144
+
145
+ ## Options
146
+
147
+ | Parameter | Default | Description |
148
+ |---|---|---|
149
+ | `title` | `"Application"` | Application title |
150
+ | `show_time` | `True` | Show timestamps |
151
+ | `time_format` | `"%I:%M %p"` | Time format (12h AM/PM) |
152
+ | `title_separator` | `" \| "` | Separator for title parts |
153
+ | `title_color` | `Colors.CYAN` | Title bar color |
154
+ | `time_color` | `Colors.BRIGHT_BLACK` | Timestamp color |
155
+ | `bracket_style` | `"square"` | Bracket style: square, round, angle, curly |
156
+ | `log_file` | `None` | Optional file path to save logs |
157
+
158
+ ## Log File
159
+
160
+ ```python
161
+ log = Logger(log_file="app.log")
162
+ log.info("This goes to terminal AND file")
163
+ ```
164
+
165
+ ## Log Levels
166
+
167
+ | Method | Symbol | Color |
168
+ |---|---|---|
169
+ | `info()` | `[¥]` | Cyan |
170
+ | `success()` | `[+]` | Green |
171
+ | `warning()` | `[!]` | Yellow |
172
+ | `error()` | `[-]` | Red |
173
+ | `money()` | `[$]` | Bright Green |
174
+ | `input_log()` | `[>]` | Magenta |
175
+ | `debug()` | `[~]` | Gray |
176
+ | `captcha()` | `[¥]` | Yellow |
177
+ | `custom()` | Custom | Custom |
178
+
179
+ ## Default Instance
180
+
181
+ ```python
182
+ from spanlogger import log
183
+
184
+ log.info("Quick access without creating an instance")
185
+ ```
186
+
187
+ ## License
188
+
189
+ MIT - by rowsvips | vmshops.mysellauth.com
@@ -0,0 +1,162 @@
1
+ # spanlogger
2
+
3
+ Professional colored terminal logger for Python by **rowsvips**.
4
+
5
+ Zero dependencies. Thread-safe. Windows & Linux compatible.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install spanlogger
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```python
16
+ from spanlogger import Logger, Colors
17
+
18
+ log = Logger(title="MyApp", show_time=True)
19
+
20
+ log.info("Application started")
21
+ log.success("Connected to server")
22
+ log.warning("Rate limit approaching")
23
+ log.error("Connection failed")
24
+ log.money("Payment received [$50.00]")
25
+ log.debug("Internal state: ok")
26
+ log.captcha("Captcha detected on session_abc****")
27
+ log.custom("Special event", symbol="★", color=Colors.BRIGHT_YELLOW)
28
+ ```
29
+
30
+ ## Output
31
+
32
+ ```
33
+ 07:23 AM [¥] Application started
34
+ 07:23 AM [+] Connected to server
35
+ 07:23 AM [!] Rate limit approaching
36
+ 07:23 AM [-] Connection failed
37
+ 07:23 AM [$] Payment received [$50.00]
38
+ 07:23 AM [~] Internal state: ok
39
+ 07:23 AM [¥] Captcha detected on session_abc****
40
+ 07:23 AM [★] Special event
41
+ ```
42
+
43
+ ## Title Bar
44
+
45
+ ```python
46
+ log.print_title_bar(
47
+ "MyApp v1.0",
48
+ "@rowsvips",
49
+ "vmshops.mysellauth.com",
50
+ stats={"Success": 10, "Failed": 2}
51
+ )
52
+ ```
53
+
54
+ ```
55
+ ────────────────────────────────────────────────────────────────────────────────
56
+ MyApp v1.0 | @rowsvips | vmshops.mysellauth.com | Success: 10 - Failed: 2
57
+ ────────────────────────────────────────────────────────────────────────────────
58
+ ```
59
+
60
+ ## Console Window Title
61
+
62
+ ```python
63
+ log.set_title("MyApp v1.0", "@rowsvips")
64
+ log.set_title_stats(Success=10, Failed=2, Captcha=5)
65
+ ```
66
+
67
+ ## Counter System
68
+
69
+ ```python
70
+ log.increment("success")
71
+ log.increment("failed", 3)
72
+
73
+ print(log.get_count("success"))
74
+ print(log.get_all_counts())
75
+
76
+ log.reset_counts()
77
+ ```
78
+
79
+ ## Contextual Helpers
80
+
81
+ ```python
82
+ log.redeemed("code_abc****", "session_123****", "[AT: 2.5s | Type: Premium]")
83
+ log.failed("Process Task", "Error: session expired")
84
+ log.added("Account", "user_xyz****", "session_123****")
85
+ log.removed("Session", "session_old****")
86
+ log.thread_sleep(5, "Before retry")
87
+ ```
88
+
89
+ ## Custom Symbols & Colors
90
+
91
+ ```python
92
+ log.custom("Diamond", symbol="♦", color=Colors.BRIGHT_MAGENTA)
93
+ log.custom("Heart", symbol="♥", color=Colors.BRIGHT_RED)
94
+ log.custom("Arrow", symbol="→", color=Colors.BRIGHT_CYAN)
95
+ ```
96
+
97
+ ## Inline Colored Text
98
+
99
+ ```python
100
+ token = Logger.colorize("session_abc****", Colors.BRIGHT_CYAN)
101
+ log.info(f"Processing on {token}")
102
+
103
+ log.info(f"Status: {Logger.bold('ACTIVE')}")
104
+ ```
105
+
106
+ ## Utilities
107
+
108
+ ```python
109
+ log.separator()
110
+ log.separator(char="=", length=40, color=Colors.CYAN)
111
+
112
+ log.blank()
113
+ log.clear()
114
+
115
+ log.banner("All Done!", color=Colors.BRIGHT_GREEN, width=50)
116
+ ```
117
+
118
+ ## Options
119
+
120
+ | Parameter | Default | Description |
121
+ |---|---|---|
122
+ | `title` | `"Application"` | Application title |
123
+ | `show_time` | `True` | Show timestamps |
124
+ | `time_format` | `"%I:%M %p"` | Time format (12h AM/PM) |
125
+ | `title_separator` | `" \| "` | Separator for title parts |
126
+ | `title_color` | `Colors.CYAN` | Title bar color |
127
+ | `time_color` | `Colors.BRIGHT_BLACK` | Timestamp color |
128
+ | `bracket_style` | `"square"` | Bracket style: square, round, angle, curly |
129
+ | `log_file` | `None` | Optional file path to save logs |
130
+
131
+ ## Log File
132
+
133
+ ```python
134
+ log = Logger(log_file="app.log")
135
+ log.info("This goes to terminal AND file")
136
+ ```
137
+
138
+ ## Log Levels
139
+
140
+ | Method | Symbol | Color |
141
+ |---|---|---|
142
+ | `info()` | `[¥]` | Cyan |
143
+ | `success()` | `[+]` | Green |
144
+ | `warning()` | `[!]` | Yellow |
145
+ | `error()` | `[-]` | Red |
146
+ | `money()` | `[$]` | Bright Green |
147
+ | `input_log()` | `[>]` | Magenta |
148
+ | `debug()` | `[~]` | Gray |
149
+ | `captcha()` | `[¥]` | Yellow |
150
+ | `custom()` | Custom | Custom |
151
+
152
+ ## Default Instance
153
+
154
+ ```python
155
+ from spanlogger import log
156
+
157
+ log.info("Quick access without creating an instance")
158
+ ```
159
+
160
+ ## License
161
+
162
+ MIT - by rowsvips | vmshops.mysellauth.com
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "spanlogger"
7
+ version = "1.0.0"
8
+ description = "Professional colored terminal logger with timestamps, symbols, and title bar support."
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.8"
12
+ authors = [
13
+ {name = "rowsvips"}
14
+ ]
15
+ keywords = ["logger", "terminal", "colored", "console", "logging", "ansi", "cli"]
16
+ classifiers = [
17
+ "Development Status :: 5 - Production/Stable",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Programming Language :: Python :: 3.14",
29
+ "Topic :: Software Development :: Libraries :: Python Modules",
30
+ "Topic :: System :: Logging",
31
+ ]
32
+
33
+ [project.urls]
34
+ Homepage = "https://vmshops.mysellauth.com"
35
+
36
+ [tool.setuptools.packages.find]
37
+ include = ["spanlogger*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ from .logger import Logger, Colors, LogLevel, log
2
+
3
+ __all__ = ["Logger", "Colors", "LogLevel", "log"]
4
+ __version__ = "1.0.0"
5
+ __author__ = "rowsvips"
@@ -0,0 +1,335 @@
1
+ import io
2
+ import os
3
+ import sys
4
+ import threading
5
+ from datetime import datetime
6
+ from enum import Enum
7
+ from typing import Optional
8
+
9
+
10
+ class Colors:
11
+ RESET = "\033[0m"
12
+ BOLD = "\033[1m"
13
+ DIM = "\033[2m"
14
+ UNDERLINE = "\033[4m"
15
+
16
+ BLACK = "\033[30m"
17
+ RED = "\033[31m"
18
+ GREEN = "\033[32m"
19
+ YELLOW = "\033[33m"
20
+ BLUE = "\033[34m"
21
+ MAGENTA = "\033[35m"
22
+ CYAN = "\033[36m"
23
+ WHITE = "\033[37m"
24
+
25
+ BRIGHT_BLACK = "\033[90m"
26
+ BRIGHT_RED = "\033[91m"
27
+ BRIGHT_GREEN = "\033[92m"
28
+ BRIGHT_YELLOW = "\033[93m"
29
+ BRIGHT_BLUE = "\033[94m"
30
+ BRIGHT_MAGENTA = "\033[95m"
31
+ BRIGHT_CYAN = "\033[96m"
32
+ BRIGHT_WHITE = "\033[97m"
33
+
34
+ BG_BLACK = "\033[40m"
35
+ BG_RED = "\033[41m"
36
+ BG_GREEN = "\033[42m"
37
+ BG_YELLOW = "\033[43m"
38
+ BG_BLUE = "\033[44m"
39
+ BG_MAGENTA = "\033[45m"
40
+ BG_CYAN = "\033[46m"
41
+ BG_WHITE = "\033[47m"
42
+
43
+ BG_BRIGHT_BLACK = "\033[100m"
44
+ BG_BRIGHT_RED = "\033[101m"
45
+ BG_BRIGHT_GREEN = "\033[102m"
46
+ BG_BRIGHT_YELLOW = "\033[103m"
47
+ BG_BRIGHT_BLUE = "\033[104m"
48
+ BG_BRIGHT_MAGENTA = "\033[105m"
49
+ BG_BRIGHT_CYAN = "\033[106m"
50
+ BG_BRIGHT_WHITE = "\033[107m"
51
+
52
+
53
+ class LogLevel(Enum):
54
+ INFO = ("¥", Colors.CYAN, Colors.BRIGHT_CYAN)
55
+ SUCCESS = ("+", Colors.GREEN, Colors.BRIGHT_GREEN)
56
+ WARNING = ("!", Colors.YELLOW, Colors.BRIGHT_YELLOW)
57
+ ERROR = ("-", Colors.RED, Colors.BRIGHT_RED)
58
+ MONEY = ("$", Colors.BRIGHT_GREEN, Colors.BRIGHT_GREEN)
59
+ INPUT = (">", Colors.MAGENTA, Colors.BRIGHT_MAGENTA)
60
+ DEBUG = ("~", Colors.BRIGHT_BLACK, Colors.BRIGHT_BLACK)
61
+ CAPTCHA = ("¥", Colors.YELLOW, Colors.BRIGHT_YELLOW)
62
+ CUSTOM = ("*", Colors.BRIGHT_WHITE, Colors.BRIGHT_WHITE)
63
+
64
+ def __init__(self, symbol: str, bracket_color: str, message_color: str):
65
+ self.symbol = symbol
66
+ self.bracket_color = bracket_color
67
+ self.message_color = message_color
68
+
69
+
70
+ class Logger:
71
+ _lock = threading.Lock()
72
+
73
+ def __init__(
74
+ self,
75
+ title: str = "Application",
76
+ show_time: bool = True,
77
+ time_format: str = "%I:%M %p",
78
+ title_separator: str = " | ",
79
+ title_color: str = Colors.CYAN,
80
+ time_color: str = Colors.BRIGHT_BLACK,
81
+ bracket_style: str = "square",
82
+ log_file: Optional[str] = None,
83
+ ):
84
+ self.title = title
85
+ self.show_time = show_time
86
+ self.time_format = time_format
87
+ self.title_separator = title_separator
88
+ self.title_color = title_color
89
+ self.time_color = time_color
90
+ self.bracket_style = bracket_style
91
+ self.log_file = log_file
92
+ self._counters: dict[str, int] = {}
93
+ self._title_stats: dict[str, str] = {}
94
+ self._title_parts: list[str] = []
95
+
96
+ if os.name == "nt":
97
+ self._enable_windows_ansi()
98
+
99
+ self._brackets = {
100
+ "square": ("[", "]"),
101
+ "round": ("(", ")"),
102
+ "angle": ("<", ">"),
103
+ "curly": ("{", "}"),
104
+ }
105
+
106
+ @staticmethod
107
+ def _enable_windows_ansi():
108
+ try:
109
+ import ctypes
110
+ kernel32 = ctypes.windll.kernel32
111
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
112
+ except Exception:
113
+ pass
114
+
115
+ try:
116
+ if sys.stdout.encoding and sys.stdout.encoding.lower() != "utf-8":
117
+ sys.stdout = io.TextIOWrapper(
118
+ sys.stdout.buffer, encoding="utf-8", errors="replace", line_buffering=True
119
+ )
120
+ if sys.stderr.encoding and sys.stderr.encoding.lower() != "utf-8":
121
+ sys.stderr = io.TextIOWrapper(
122
+ sys.stderr.buffer, encoding="utf-8", errors="replace", line_buffering=True
123
+ )
124
+ except Exception:
125
+ pass
126
+
127
+ def _get_brackets(self) -> tuple[str, str]:
128
+ return self._brackets.get(self.bracket_style, ("[", "]"))
129
+
130
+ def _get_timestamp(self) -> str:
131
+ if not self.show_time:
132
+ return ""
133
+ now = datetime.now().strftime(self.time_format)
134
+ return f"{self.time_color}{now}{Colors.RESET}"
135
+
136
+ def _format_message(self, level: LogLevel, message: str, extra_color: Optional[str] = None) -> str:
137
+ lb, rb = self._get_brackets()
138
+ color = extra_color or level.message_color
139
+
140
+ time_str = self._get_timestamp()
141
+ time_part = f"{time_str} " if time_str else ""
142
+
143
+ symbol_part = (
144
+ f"{level.bracket_color}{lb}"
145
+ f"{Colors.BOLD}{level.message_color}{level.symbol}"
146
+ f"{Colors.RESET}{level.bracket_color}{rb}{Colors.RESET}"
147
+ )
148
+
149
+ msg_part = f"{color}{message}{Colors.RESET}"
150
+
151
+ return f"{time_part}{symbol_part} {msg_part}"
152
+
153
+ def _write(self, formatted: str, raw_message: str = ""):
154
+ with self._lock:
155
+ sys.stdout.write(formatted + "\n")
156
+ sys.stdout.flush()
157
+
158
+ if self.log_file and raw_message:
159
+ try:
160
+ with open(self.log_file, "a", encoding="utf-8") as f:
161
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
162
+ f.write(f"[{timestamp}] {raw_message}\n")
163
+ except Exception:
164
+ pass
165
+
166
+ def info(self, message: str):
167
+ formatted = self._format_message(LogLevel.INFO, message)
168
+ self._write(formatted, f"[INFO] {message}")
169
+
170
+ def success(self, message: str):
171
+ formatted = self._format_message(LogLevel.SUCCESS, message)
172
+ self._write(formatted, f"[SUCCESS] {message}")
173
+
174
+ def warning(self, message: str):
175
+ formatted = self._format_message(LogLevel.WARNING, message)
176
+ self._write(formatted, f"[WARNING] {message}")
177
+
178
+ def error(self, message: str):
179
+ formatted = self._format_message(LogLevel.ERROR, message)
180
+ self._write(formatted, f"[ERROR] {message}")
181
+
182
+ def money(self, message: str):
183
+ formatted = self._format_message(LogLevel.MONEY, message)
184
+ self._write(formatted, f"[MONEY] {message}")
185
+
186
+ def input_log(self, message: str):
187
+ formatted = self._format_message(LogLevel.INPUT, message)
188
+ self._write(formatted, f"[INPUT] {message}")
189
+
190
+ def debug(self, message: str):
191
+ formatted = self._format_message(LogLevel.DEBUG, message)
192
+ self._write(formatted, f"[DEBUG] {message}")
193
+
194
+ def captcha(self, message: str):
195
+ formatted = self._format_message(LogLevel.CAPTCHA, message)
196
+ self._write(formatted, f"[CAPTCHA] {message}")
197
+
198
+ def custom(self, message: str, symbol: str = "*", color: str = Colors.BRIGHT_WHITE):
199
+ lb, rb = self._get_brackets()
200
+ time_str = self._get_timestamp()
201
+ time_part = f"{time_str} " if time_str else ""
202
+
203
+ symbol_part = (
204
+ f"{color}{lb}"
205
+ f"{Colors.BOLD}{color}{symbol}"
206
+ f"{Colors.RESET}{color}{rb}{Colors.RESET}"
207
+ )
208
+ msg_part = f"{color}{message}{Colors.RESET}"
209
+ formatted = f"{time_part}{symbol_part} {msg_part}"
210
+ self._write(formatted, f"[CUSTOM] {message}")
211
+
212
+ def set_title(self, *parts: str):
213
+ self._title_parts = list(parts)
214
+ self._refresh_title()
215
+
216
+ def set_title_stats(self, **stats: any):
217
+ for key, value in stats.items():
218
+ self._title_stats[key] = str(value)
219
+ self._refresh_title()
220
+
221
+ def _refresh_title(self):
222
+ parts = list(self._title_parts)
223
+
224
+ if self._title_stats:
225
+ stats_str = " - ".join(
226
+ f"{k}: {v}" for k, v in self._title_stats.items()
227
+ )
228
+ parts.append(stats_str)
229
+
230
+ full_title = self.title_separator.join(parts)
231
+
232
+ sys.stdout.write(f"\033]0;{full_title}\007")
233
+ sys.stdout.flush()
234
+
235
+ def print_title_bar(self, *parts: str, stats: Optional[dict] = None):
236
+ all_parts = list(parts)
237
+
238
+ if stats:
239
+ stats_parts = []
240
+ for k, v in stats.items():
241
+ stats_parts.append(f"{k}: {v}")
242
+ stats_str = " - ".join(stats_parts)
243
+ all_parts.append(stats_str)
244
+
245
+ separator = f"{Colors.BRIGHT_BLACK}{self.title_separator}{Colors.RESET}"
246
+ colored_parts = [f"{self.title_color}{p}{Colors.RESET}" for p in all_parts]
247
+ bar = separator.join(colored_parts)
248
+
249
+ with self._lock:
250
+ sys.stdout.write(f"{Colors.BRIGHT_BLACK}{'─' * 80}{Colors.RESET}\n")
251
+ sys.stdout.write(f" {bar}\n")
252
+ sys.stdout.write(f"{Colors.BRIGHT_BLACK}{'─' * 80}{Colors.RESET}\n")
253
+ sys.stdout.flush()
254
+
255
+ def increment(self, key: str, amount: int = 1) -> int:
256
+ with self._lock:
257
+ self._counters[key] = self._counters.get(key, 0) + amount
258
+ return self._counters[key]
259
+
260
+ def get_count(self, key: str) -> int:
261
+ return self._counters.get(key, 0)
262
+
263
+ def get_all_counts(self) -> dict[str, int]:
264
+ return dict(self._counters)
265
+
266
+ def reset_counts(self):
267
+ with self._lock:
268
+ self._counters.clear()
269
+
270
+ def separator(self, char: str = "─", length: int = 60, color: str = Colors.BRIGHT_BLACK):
271
+ line = f"{color}{char * length}{Colors.RESET}"
272
+ self._write(line)
273
+
274
+ def blank(self):
275
+ self._write("")
276
+
277
+ def banner(self, text: str, color: str = Colors.CYAN, width: int = 60):
278
+ border = f"{color}{'═' * width}{Colors.RESET}"
279
+ padded = text.center(width)
280
+ banner_text = f"{color}{padded}{Colors.RESET}"
281
+ with self._lock:
282
+ sys.stdout.write(f"{border}\n{banner_text}\n{border}\n")
283
+ sys.stdout.flush()
284
+
285
+ def clear(self):
286
+ os.system("cls" if os.name == "nt" else "clear")
287
+
288
+ @staticmethod
289
+ def colorize(text: str, color: str) -> str:
290
+ return f"{color}{text}{Colors.RESET}"
291
+
292
+ @staticmethod
293
+ def bold(text: str) -> str:
294
+ return f"{Colors.BOLD}{text}{Colors.RESET}"
295
+
296
+ @staticmethod
297
+ def dim(text: str) -> str:
298
+ return f"{Colors.DIM}{text}{Colors.RESET}"
299
+
300
+ def redeemed(self, promo: str, token: str, details: str = ""):
301
+ msg = f"Redeemed {Colors.BRIGHT_GREEN}{promo}{Colors.RESET}"
302
+ msg += f" {Colors.CYAN}On{Colors.RESET} {Colors.BRIGHT_CYAN}{token}{Colors.RESET}"
303
+ if details:
304
+ msg += f" {Colors.BRIGHT_BLACK}{details}{Colors.RESET}"
305
+ formatted = self._format_message(LogLevel.MONEY, msg)
306
+ self._write(formatted, f"[REDEEMED] {promo} on {token} {details}")
307
+
308
+ def failed(self, action: str, reason: str = ""):
309
+ msg = f"Failed to {Colors.BRIGHT_RED}{action}{Colors.RESET}"
310
+ if reason:
311
+ msg += f", {Colors.YELLOW}{reason}{Colors.RESET}"
312
+ formatted = self._format_message(LogLevel.ERROR, msg)
313
+ self._write(formatted, f"[FAILED] {action} - {reason}")
314
+
315
+ def added(self, item_type: str, item: str, target: str = ""):
316
+ msg = f"Added {Colors.BRIGHT_GREEN}{item_type}{Colors.RESET} {Colors.GREEN}{item}{Colors.RESET}"
317
+ if target:
318
+ msg += f" {Colors.CYAN}To{Colors.RESET} {Colors.BRIGHT_CYAN}{target}{Colors.RESET}"
319
+ formatted = self._format_message(LogLevel.SUCCESS, msg)
320
+ self._write(formatted, f"[ADDED] {item_type} {item} to {target}")
321
+
322
+ def removed(self, item_type: str, item: str):
323
+ msg = f"Removed {Colors.YELLOW}{item_type}{Colors.RESET}: {Colors.BRIGHT_YELLOW}{item}{Colors.RESET}"
324
+ formatted = self._format_message(LogLevel.WARNING, msg)
325
+ self._write(formatted, f"[REMOVED] {item_type} {item}")
326
+
327
+ def thread_sleep(self, seconds: int, reason: str = ""):
328
+ msg = f"Thread Sleeping for {Colors.BRIGHT_CYAN}{seconds}s{Colors.RESET}"
329
+ if reason:
330
+ msg += f" {Colors.BRIGHT_BLACK}{reason}{Colors.RESET}"
331
+ formatted = self._format_message(LogLevel.INPUT, msg)
332
+ self._write(formatted, f"[SLEEP] {seconds}s {reason}")
333
+
334
+
335
+ log = Logger()
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: spanlogger
3
+ Version: 1.0.0
4
+ Summary: Professional colored terminal logger with timestamps, symbols, and title bar support.
5
+ Author: rowsvips
6
+ License: MIT
7
+ Project-URL: Homepage, https://vmshops.mysellauth.com
8
+ Keywords: logger,terminal,colored,console,logging,ansi,cli
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: System :: Logging
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Dynamic: license-file
27
+
28
+ # spanlogger
29
+
30
+ Professional colored terminal logger for Python by **rowsvips**.
31
+
32
+ Zero dependencies. Thread-safe. Windows & Linux compatible.
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install spanlogger
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ from spanlogger import Logger, Colors
44
+
45
+ log = Logger(title="MyApp", show_time=True)
46
+
47
+ log.info("Application started")
48
+ log.success("Connected to server")
49
+ log.warning("Rate limit approaching")
50
+ log.error("Connection failed")
51
+ log.money("Payment received [$50.00]")
52
+ log.debug("Internal state: ok")
53
+ log.captcha("Captcha detected on session_abc****")
54
+ log.custom("Special event", symbol="★", color=Colors.BRIGHT_YELLOW)
55
+ ```
56
+
57
+ ## Output
58
+
59
+ ```
60
+ 07:23 AM [¥] Application started
61
+ 07:23 AM [+] Connected to server
62
+ 07:23 AM [!] Rate limit approaching
63
+ 07:23 AM [-] Connection failed
64
+ 07:23 AM [$] Payment received [$50.00]
65
+ 07:23 AM [~] Internal state: ok
66
+ 07:23 AM [¥] Captcha detected on session_abc****
67
+ 07:23 AM [★] Special event
68
+ ```
69
+
70
+ ## Title Bar
71
+
72
+ ```python
73
+ log.print_title_bar(
74
+ "MyApp v1.0",
75
+ "@rowsvips",
76
+ "vmshops.mysellauth.com",
77
+ stats={"Success": 10, "Failed": 2}
78
+ )
79
+ ```
80
+
81
+ ```
82
+ ────────────────────────────────────────────────────────────────────────────────
83
+ MyApp v1.0 | @rowsvips | vmshops.mysellauth.com | Success: 10 - Failed: 2
84
+ ────────────────────────────────────────────────────────────────────────────────
85
+ ```
86
+
87
+ ## Console Window Title
88
+
89
+ ```python
90
+ log.set_title("MyApp v1.0", "@rowsvips")
91
+ log.set_title_stats(Success=10, Failed=2, Captcha=5)
92
+ ```
93
+
94
+ ## Counter System
95
+
96
+ ```python
97
+ log.increment("success")
98
+ log.increment("failed", 3)
99
+
100
+ print(log.get_count("success"))
101
+ print(log.get_all_counts())
102
+
103
+ log.reset_counts()
104
+ ```
105
+
106
+ ## Contextual Helpers
107
+
108
+ ```python
109
+ log.redeemed("code_abc****", "session_123****", "[AT: 2.5s | Type: Premium]")
110
+ log.failed("Process Task", "Error: session expired")
111
+ log.added("Account", "user_xyz****", "session_123****")
112
+ log.removed("Session", "session_old****")
113
+ log.thread_sleep(5, "Before retry")
114
+ ```
115
+
116
+ ## Custom Symbols & Colors
117
+
118
+ ```python
119
+ log.custom("Diamond", symbol="♦", color=Colors.BRIGHT_MAGENTA)
120
+ log.custom("Heart", symbol="♥", color=Colors.BRIGHT_RED)
121
+ log.custom("Arrow", symbol="→", color=Colors.BRIGHT_CYAN)
122
+ ```
123
+
124
+ ## Inline Colored Text
125
+
126
+ ```python
127
+ token = Logger.colorize("session_abc****", Colors.BRIGHT_CYAN)
128
+ log.info(f"Processing on {token}")
129
+
130
+ log.info(f"Status: {Logger.bold('ACTIVE')}")
131
+ ```
132
+
133
+ ## Utilities
134
+
135
+ ```python
136
+ log.separator()
137
+ log.separator(char="=", length=40, color=Colors.CYAN)
138
+
139
+ log.blank()
140
+ log.clear()
141
+
142
+ log.banner("All Done!", color=Colors.BRIGHT_GREEN, width=50)
143
+ ```
144
+
145
+ ## Options
146
+
147
+ | Parameter | Default | Description |
148
+ |---|---|---|
149
+ | `title` | `"Application"` | Application title |
150
+ | `show_time` | `True` | Show timestamps |
151
+ | `time_format` | `"%I:%M %p"` | Time format (12h AM/PM) |
152
+ | `title_separator` | `" \| "` | Separator for title parts |
153
+ | `title_color` | `Colors.CYAN` | Title bar color |
154
+ | `time_color` | `Colors.BRIGHT_BLACK` | Timestamp color |
155
+ | `bracket_style` | `"square"` | Bracket style: square, round, angle, curly |
156
+ | `log_file` | `None` | Optional file path to save logs |
157
+
158
+ ## Log File
159
+
160
+ ```python
161
+ log = Logger(log_file="app.log")
162
+ log.info("This goes to terminal AND file")
163
+ ```
164
+
165
+ ## Log Levels
166
+
167
+ | Method | Symbol | Color |
168
+ |---|---|---|
169
+ | `info()` | `[¥]` | Cyan |
170
+ | `success()` | `[+]` | Green |
171
+ | `warning()` | `[!]` | Yellow |
172
+ | `error()` | `[-]` | Red |
173
+ | `money()` | `[$]` | Bright Green |
174
+ | `input_log()` | `[>]` | Magenta |
175
+ | `debug()` | `[~]` | Gray |
176
+ | `captcha()` | `[¥]` | Yellow |
177
+ | `custom()` | Custom | Custom |
178
+
179
+ ## Default Instance
180
+
181
+ ```python
182
+ from spanlogger import log
183
+
184
+ log.info("Quick access without creating an instance")
185
+ ```
186
+
187
+ ## License
188
+
189
+ MIT - by rowsvips | vmshops.mysellauth.com
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ spanlogger/__init__.py
5
+ spanlogger/logger.py
6
+ spanlogger.egg-info/PKG-INFO
7
+ spanlogger.egg-info/SOURCES.txt
8
+ spanlogger.egg-info/dependency_links.txt
9
+ spanlogger.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ spanlogger