log21 2.7.1__tar.gz → 2.8.1__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.
- {log21-2.7.1 → log21-2.8.1}/LICENSE.txt +1 -1
- {log21-2.7.1 → log21-2.8.1}/PKG-INFO +9 -6
- {log21-2.7.1 → log21-2.8.1}/README.md +7 -4
- {log21-2.7.1 → log21-2.8.1}/pyproject.toml +9 -3
- {log21-2.7.1 → log21-2.8.1}/src/log21/Argparse.py +4 -2
- {log21-2.7.1 → log21-2.8.1}/src/log21/Logger.py +126 -40
- {log21-2.7.1 → log21-2.8.1}/src/log21/StreamHandler.py +1 -1
- {log21-2.7.1 → log21-2.8.1}/src/log21/__init__.py +17 -17
- {log21-2.7.1 → log21-2.8.1}/src/log21.egg-info/PKG-INFO +9 -6
- {log21-2.7.1 → log21-2.8.1}/setup.cfg +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/Argumentify.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/Colors.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/CrashReporter/Formatters.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/CrashReporter/Reporters.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/CrashReporter/__init__.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/FileHandler.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/Formatters.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/Levels.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/LoggingWindow.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/Manager.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/PPrint.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/ProgressBar.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21/TreePrint.py +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21.egg-info/SOURCES.txt +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21.egg-info/dependency_links.txt +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21.egg-info/requires.txt +0 -0
- {log21-2.7.1 → log21-2.8.1}/src/log21.egg-info/top_level.txt +0 -0
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright [2021-
|
|
189
|
+
Copyright [2021-2024] [CodeWriter21]
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: log21
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.1
|
|
4
4
|
Summary: A simple logging package that helps you log colorized messages in Windows console.
|
|
5
5
|
Author-email: "CodeWriter21(Mehrad Pooryoussof)" <CodeWriter21@gmail.com>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Classifier: Operating System :: Unix
|
|
17
17
|
Classifier: Operating System :: Microsoft :: Windows
|
|
18
18
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
19
|
-
Requires-Python: >=3.
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE.txt
|
|
22
22
|
Requires-Dist: webcolors
|
|
@@ -49,7 +49,7 @@ Features
|
|
|
49
49
|
modifications. It can also decolorize the output if you want to log into a file.
|
|
50
50
|
+ Pretty printing : Have you ever wanted to colorize the output of the pprint module? log21's pretty printer can do
|
|
51
51
|
that.
|
|
52
|
-
+ Tree printing : You can pass a dict or list to log21.tree_print function and it will print it in a tree-like
|
|
52
|
+
+ Tree printing : You can pass a dict or list to `log21.tree_print` function and it will print it in a tree-like
|
|
53
53
|
structure. It's also colorized XD.
|
|
54
54
|
+ ProgressBar : log21's progress bar can be used to show progress of a process in a beautiful way.
|
|
55
55
|
+ LoggingWindow : Helps you to log messages and debug your code in a window other than the console.
|
|
@@ -92,9 +92,12 @@ pip install git+https://github.com/MPCodeWriter21/log21
|
|
|
92
92
|
Changes
|
|
93
93
|
-------
|
|
94
94
|
|
|
95
|
-
### 2.
|
|
95
|
+
### 2.8.1
|
|
96
96
|
|
|
97
|
-
+
|
|
97
|
+
+ Fixed Carriage Return Handling.
|
|
98
|
+
+ Fixed setting level using `log21.basic_config`
|
|
99
|
+
+ Added more configuration for developer tools to the `pyproject.toml` file.
|
|
100
|
+
+ Added pre-commit.
|
|
98
101
|
|
|
99
102
|
[Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
|
|
100
103
|
|
|
@@ -233,7 +236,7 @@ for character in text:
|
|
|
233
236
|
|
|
234
237
|
window.error(colored_text)
|
|
235
238
|
|
|
236
|
-
# See more examples in
|
|
239
|
+
# See more examples in
|
|
237
240
|
# https://github.com/MPCodeWriter21/log21/blob/066efc1e72542531012d36974bbf6cd4c5941378/log21/LoggingWindow.py#L155
|
|
238
241
|
# and
|
|
239
242
|
# https://github.com/MPCodeWriter21/log21/blob/066efc1e72542531012d36974bbf6cd4c5941378/log21/__init__.py#L144
|
|
@@ -18,7 +18,7 @@ Features
|
|
|
18
18
|
modifications. It can also decolorize the output if you want to log into a file.
|
|
19
19
|
+ Pretty printing : Have you ever wanted to colorize the output of the pprint module? log21's pretty printer can do
|
|
20
20
|
that.
|
|
21
|
-
+ Tree printing : You can pass a dict or list to log21.tree_print function and it will print it in a tree-like
|
|
21
|
+
+ Tree printing : You can pass a dict or list to `log21.tree_print` function and it will print it in a tree-like
|
|
22
22
|
structure. It's also colorized XD.
|
|
23
23
|
+ ProgressBar : log21's progress bar can be used to show progress of a process in a beautiful way.
|
|
24
24
|
+ LoggingWindow : Helps you to log messages and debug your code in a window other than the console.
|
|
@@ -61,9 +61,12 @@ pip install git+https://github.com/MPCodeWriter21/log21
|
|
|
61
61
|
Changes
|
|
62
62
|
-------
|
|
63
63
|
|
|
64
|
-
### 2.
|
|
64
|
+
### 2.8.1
|
|
65
65
|
|
|
66
|
-
+
|
|
66
|
+
+ Fixed Carriage Return Handling.
|
|
67
|
+
+ Fixed setting level using `log21.basic_config`
|
|
68
|
+
+ Added more configuration for developer tools to the `pyproject.toml` file.
|
|
69
|
+
+ Added pre-commit.
|
|
67
70
|
|
|
68
71
|
[Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
|
|
69
72
|
|
|
@@ -202,7 +205,7 @@ for character in text:
|
|
|
202
205
|
|
|
203
206
|
window.error(colored_text)
|
|
204
207
|
|
|
205
|
-
# See more examples in
|
|
208
|
+
# See more examples in
|
|
206
209
|
# https://github.com/MPCodeWriter21/log21/blob/066efc1e72542531012d36974bbf6cd4c5941378/log21/LoggingWindow.py#L155
|
|
207
210
|
# and
|
|
208
211
|
# https://github.com/MPCodeWriter21/log21/blob/066efc1e72542531012d36974bbf6cd4c5941378/log21/__init__.py#L144
|
|
@@ -9,7 +9,7 @@ authors = [
|
|
|
9
9
|
]
|
|
10
10
|
description = "A simple logging package that helps you log colorized messages in Windows console."
|
|
11
11
|
readme = {file = "README.md", content-type = "text/markdown"}
|
|
12
|
-
requires-python = ">=3.
|
|
12
|
+
requires-python = ">=3.8"
|
|
13
13
|
keywords = ['python', 'log', 'colorize', 'color', 'logging', 'Python3', 'CodeWriter21']
|
|
14
14
|
license = {text = "Apache License 2.0"}
|
|
15
15
|
classifiers = [
|
|
@@ -26,7 +26,7 @@ dependencies = [
|
|
|
26
26
|
"webcolors",
|
|
27
27
|
"docstring-parser"
|
|
28
28
|
]
|
|
29
|
-
version = "2.
|
|
29
|
+
version = "2.8.1"
|
|
30
30
|
|
|
31
31
|
[tool.setuptools.packages.find]
|
|
32
32
|
where = ["src"]
|
|
@@ -43,9 +43,9 @@ dev = ["yapf", "isort", "docformatter", "pylint", "json5", "pytest"]
|
|
|
43
43
|
max-line-length = 88
|
|
44
44
|
|
|
45
45
|
disable = [
|
|
46
|
-
"protected-access",
|
|
47
46
|
"too-few-public-methods",
|
|
48
47
|
"too-many-arguments",
|
|
48
|
+
"protected-access",
|
|
49
49
|
"too-many-locals",
|
|
50
50
|
"fixme",
|
|
51
51
|
]
|
|
@@ -62,4 +62,10 @@ dedent_closing_brackets = true
|
|
|
62
62
|
[tool.isort]
|
|
63
63
|
line_length = 88
|
|
64
64
|
combine_as_imports = true
|
|
65
|
+
length_sort = true
|
|
65
66
|
order_by_type = true
|
|
67
|
+
|
|
68
|
+
[tool.docformatter]
|
|
69
|
+
recursive = true
|
|
70
|
+
wrap-summaries = 88
|
|
71
|
+
wrap-descriptions = 88
|
|
@@ -572,7 +572,8 @@ class _ActionsContainer(_argparse._ActionsContainer):
|
|
|
572
572
|
# Handle `Required` as a type (e.g. `Required[int]`)
|
|
573
573
|
elif (hasattr(_typing, 'Required') and hasattr(_typing, '_GenericAlias')
|
|
574
574
|
and isinstance(func_type, _typing._GenericAlias) # type: ignore
|
|
575
|
-
and func_type.__origin__ is _typing.Required
|
|
575
|
+
and func_type.__origin__ is _typing.Required
|
|
576
|
+
):
|
|
576
577
|
func_type = func_type.__args__[0]
|
|
577
578
|
action.required = True
|
|
578
579
|
|
|
@@ -754,7 +755,8 @@ class ColorizingArgumentParser(_argparse.ArgumentParser, _ActionsContainer):
|
|
|
754
755
|
return self.formatter_class(prog=self.prog)
|
|
755
756
|
|
|
756
757
|
def _get_value(self, action, arg_string):
|
|
757
|
-
"""Override _get_value to add support for types such as Union and
|
|
758
|
+
"""Override _get_value to add support for types such as Union and
|
|
759
|
+
Literal."""
|
|
758
760
|
|
|
759
761
|
func_type = self._registry_get('type', action.type, action.type)
|
|
760
762
|
if not callable(func_type) and not isinstance(func_type, tuple):
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# log21.Logger.py
|
|
2
2
|
# CodeWriter21
|
|
3
3
|
|
|
4
|
+
import re as _re
|
|
4
5
|
import logging as _logging
|
|
5
|
-
from
|
|
6
|
-
|
|
6
|
+
from types import MethodType as _MethodType
|
|
7
|
+
from typing import (Union as _Union, Literal as _Literal, Mapping,
|
|
8
|
+
Callable as _Callable, Optional as _Optional, Sequence as _Sequence)
|
|
7
9
|
from getpass import getpass as _getpass
|
|
8
10
|
from logging import raiseExceptions as _raiseExceptions
|
|
9
11
|
|
|
@@ -51,11 +53,10 @@ class Logger(_logging.Logger):
|
|
|
51
53
|
def log(self, level: int, *msg, args: tuple = (), end='\n', **kwargs):
|
|
52
54
|
"""Log 'msg % args' with the integer severity 'level'.
|
|
53
55
|
|
|
54
|
-
To pass exception information, use the keyword argument exc_info
|
|
55
|
-
|
|
56
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
57
|
+
value, e.g.
|
|
56
58
|
|
|
57
|
-
logger.log(level, "We have a %s", args=("mysterious problem",),
|
|
58
|
-
exc_info=1)
|
|
59
|
+
logger.log(level, "We have a %s", args=("mysterious problem",), exc_info=1)
|
|
59
60
|
"""
|
|
60
61
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
61
62
|
if not isinstance(level, int):
|
|
@@ -68,11 +69,10 @@ class Logger(_logging.Logger):
|
|
|
68
69
|
def debug(self, *msg, args: tuple = (), end='\n', **kwargs):
|
|
69
70
|
"""Log 'msg % args' with severity 'DEBUG'.
|
|
70
71
|
|
|
71
|
-
To pass exception information, use the keyword argument exc_info
|
|
72
|
-
|
|
72
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
73
|
+
value, e.g.
|
|
73
74
|
|
|
74
|
-
logger.debug("Houston, we have a %s", args=("thorny problem",),
|
|
75
|
-
exc_info=1)
|
|
75
|
+
logger.debug("Houston, we have a %s", args=("thorny problem",), exc_info=1)
|
|
76
76
|
"""
|
|
77
77
|
if self.isEnabledFor(DEBUG):
|
|
78
78
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
@@ -81,11 +81,10 @@ class Logger(_logging.Logger):
|
|
|
81
81
|
def info(self, *msg, args: tuple = (), end='\n', **kwargs):
|
|
82
82
|
"""Log 'msg % args' with severity 'INFO'.
|
|
83
83
|
|
|
84
|
-
To pass exception information, use the keyword argument exc_info
|
|
85
|
-
|
|
84
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
85
|
+
value, e.g.
|
|
86
86
|
|
|
87
|
-
logger.info("Houston, we have an %s", args=("interesting
|
|
88
|
-
problem",), exc_info=1)
|
|
87
|
+
logger.info("Houston, we have an %s", args=("interesting problem",), exc_info=1)
|
|
89
88
|
"""
|
|
90
89
|
if self.isEnabledFor(INFO):
|
|
91
90
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
@@ -94,11 +93,10 @@ class Logger(_logging.Logger):
|
|
|
94
93
|
def warning(self, *msg, args: tuple = (), end='\n', **kwargs):
|
|
95
94
|
"""Log 'msg % args' with severity 'WARNING'.
|
|
96
95
|
|
|
97
|
-
To pass exception information, use the keyword argument exc_info
|
|
98
|
-
|
|
96
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
97
|
+
value, e.g.
|
|
99
98
|
|
|
100
|
-
logger.warning("Houston, we have a %s", args=("bit of a
|
|
101
|
-
problem",), exc_info=1)
|
|
99
|
+
logger.warning("Houston, we have a %s", args=("bit of a problem",), exc_info=1)
|
|
102
100
|
"""
|
|
103
101
|
if self.isEnabledFor(WARNING):
|
|
104
102
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
@@ -109,11 +107,10 @@ class Logger(_logging.Logger):
|
|
|
109
107
|
def write(self, *msg, args: tuple = (), end='', **kwargs):
|
|
110
108
|
"""Log 'msg % args' with severity 'WARNING'.
|
|
111
109
|
|
|
112
|
-
To pass exception information, use the keyword argument exc_info
|
|
113
|
-
|
|
110
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
111
|
+
value, e.g.
|
|
114
112
|
|
|
115
|
-
logger.write("Houston, we have a %s", args=("bit of a
|
|
116
|
-
problem",), exc_info=1)
|
|
113
|
+
logger.write("Houston, we have a %s", args=("bit of a problem",), exc_info=1)
|
|
117
114
|
"""
|
|
118
115
|
if self.isEnabledFor(WARNING):
|
|
119
116
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
@@ -122,29 +119,26 @@ class Logger(_logging.Logger):
|
|
|
122
119
|
def error(self, *msg, args: tuple = (), end='\n', **kwargs):
|
|
123
120
|
"""Log 'msg % args' with severity 'ERROR'.
|
|
124
121
|
|
|
125
|
-
To pass exception information, use the keyword argument exc_info
|
|
126
|
-
|
|
122
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
123
|
+
value, e.g.
|
|
127
124
|
|
|
128
|
-
logger.error("Houston, we have a %s", args=("major problem",),
|
|
129
|
-
exc_info=1)
|
|
125
|
+
logger.error("Houston, we have a %s", args=("major problem",), exc_info=1)
|
|
130
126
|
"""
|
|
131
127
|
if self.isEnabledFor(ERROR):
|
|
132
128
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
133
129
|
self._log(ERROR, msg, args, **kwargs)
|
|
134
130
|
|
|
135
131
|
def exception(self, *msg, args: tuple = (), exc_info=True, **kwargs):
|
|
136
|
-
"""Convenience method for logging an ERROR with exception
|
|
137
|
-
information."""
|
|
132
|
+
"""Convenience method for logging an ERROR with exception information."""
|
|
138
133
|
self.error(*msg, args=args, exc_info=exc_info, **kwargs)
|
|
139
134
|
|
|
140
135
|
def critical(self, *msg, args: tuple = (), end='\n', **kwargs):
|
|
141
136
|
"""Log 'msg % args' with severity 'CRITICAL'.
|
|
142
137
|
|
|
143
|
-
To pass exception information, use the keyword argument exc_info
|
|
144
|
-
|
|
138
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
139
|
+
value, e.g.
|
|
145
140
|
|
|
146
|
-
logger.critical("Houston, we have a %s", args=("major
|
|
147
|
-
disaster",), exc_info=1)
|
|
141
|
+
logger.critical("Houston, we have a %s", args=("major disaster",), exc_info=1)
|
|
148
142
|
"""
|
|
149
143
|
if self.isEnabledFor(CRITICAL):
|
|
150
144
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
@@ -155,11 +149,10 @@ class Logger(_logging.Logger):
|
|
|
155
149
|
def print(self, *msg, args: tuple = (), end='\n', **kwargs):
|
|
156
150
|
"""Log 'msg % args'.
|
|
157
151
|
|
|
158
|
-
To pass exception information, use the keyword argument exc_info
|
|
159
|
-
|
|
152
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
153
|
+
value, e.g.
|
|
160
154
|
|
|
161
|
-
logger.print("Houston, we have a %s", args=("major disaster",),
|
|
162
|
-
exc_info=1)
|
|
155
|
+
logger.print("Houston, we have a %s", args=("major disaster",), exc_info=1)
|
|
163
156
|
"""
|
|
164
157
|
msg = ' '.join([str(m) for m in msg]) + end
|
|
165
158
|
self._log(PRINT, msg, args, **kwargs)
|
|
@@ -167,8 +160,8 @@ class Logger(_logging.Logger):
|
|
|
167
160
|
def input(self, *msg, args: tuple = (), end='', **kwargs):
|
|
168
161
|
"""Log 'msg % args'.
|
|
169
162
|
|
|
170
|
-
To pass exception information, use the keyword argument exc_info
|
|
171
|
-
|
|
163
|
+
To pass exception information, use the keyword argument exc_info with a true
|
|
164
|
+
value, e.g.
|
|
172
165
|
|
|
173
166
|
age = logger.input("Enter your age: ")
|
|
174
167
|
"""
|
|
@@ -192,7 +185,10 @@ class Logger(_logging.Logger):
|
|
|
192
185
|
|
|
193
186
|
@property
|
|
194
187
|
def progress_bar(self):
|
|
195
|
-
"""Return a progress bar instance.
|
|
188
|
+
"""Return a progress bar instance.
|
|
189
|
+
|
|
190
|
+
If not exists, create a new one.
|
|
191
|
+
"""
|
|
196
192
|
if not self._progress_bar:
|
|
197
193
|
# avoid circular import; pylint: disable=import-outside-toplevel
|
|
198
194
|
from log21.ProgressBar import ProgressBar
|
|
@@ -211,4 +207,94 @@ class Logger(_logging.Logger):
|
|
|
211
207
|
"""
|
|
212
208
|
for handler in self.handlers:
|
|
213
209
|
if isinstance(getattr(handler, 'clear_line', None), _Callable):
|
|
214
|
-
handler.clear_line(length)
|
|
210
|
+
handler.clear_line(length) # type: ignore
|
|
211
|
+
|
|
212
|
+
def add_level(
|
|
213
|
+
self,
|
|
214
|
+
level: int,
|
|
215
|
+
name: str,
|
|
216
|
+
errors: _Literal["raise", "ignore", "handle", "force"] = "raise"
|
|
217
|
+
) -> str:
|
|
218
|
+
"""Adds a new method to the logger with a specific level and name.
|
|
219
|
+
|
|
220
|
+
:param level: The level of the new method.
|
|
221
|
+
:param name: The name of the new method.
|
|
222
|
+
:param errors: The action to take if the level already exists.
|
|
223
|
+
+ ``raise`` (default): Raise an exception if anything goes wrong.
|
|
224
|
+
+ ``ignore``: Do nothing.
|
|
225
|
+
+ ``handle``: Handle the situation if a method with the same ``name``
|
|
226
|
+
already exists. Adds a number to the name to avoid the conflict.
|
|
227
|
+
+ ``force``: Add the new level with the specified level even if a
|
|
228
|
+
method with the same ``name`` already exists.
|
|
229
|
+
:raises TypeError: If ``level`` is not an integer.
|
|
230
|
+
:raises TypeError: If ``name`` is not a string.
|
|
231
|
+
:raises ValueError: If ``errors`` is not one of "raise", "ignore", "handle",
|
|
232
|
+
or "force".
|
|
233
|
+
:raises ValueError: If ``name`` starts with a number.
|
|
234
|
+
:raises ValueError: If ``name`` is not a valid identifier.
|
|
235
|
+
:raises AttributeError: If ``errors`` is "raise" and a method with the
|
|
236
|
+
same ``name`` already exists.
|
|
237
|
+
:return: The name of the new method.
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
def raise_(error: BaseException):
|
|
241
|
+
if errors == 'ignore':
|
|
242
|
+
return
|
|
243
|
+
raise error
|
|
244
|
+
|
|
245
|
+
if not isinstance(level, int):
|
|
246
|
+
raise_(TypeError('level must be an integer'))
|
|
247
|
+
if not isinstance(name, str):
|
|
248
|
+
raise_(TypeError('name must be a string'))
|
|
249
|
+
if errors not in ('raise', 'ignore', 'handle', 'force'):
|
|
250
|
+
raise_(
|
|
251
|
+
ValueError(
|
|
252
|
+
'errors must be one of "raise", "ignore", "handle", "force"'
|
|
253
|
+
)
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
name = _re.sub(r'\s', '_', name)
|
|
257
|
+
if _re.match(r'[0-9].*', name):
|
|
258
|
+
raise_(ValueError(f'level name cannot start with a number: "{name}"'))
|
|
259
|
+
if not _re.fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]*', name):
|
|
260
|
+
raise_(ValueError(f'level name must be a valid identifier: "{name}"'))
|
|
261
|
+
|
|
262
|
+
if hasattr(self, name):
|
|
263
|
+
if errors == 'raise':
|
|
264
|
+
raise AttributeError(f'level "{name}" already exists')
|
|
265
|
+
if errors == 'ignore':
|
|
266
|
+
return name
|
|
267
|
+
if errors == 'handle':
|
|
268
|
+
return self.add_level(level, _add_one(name), errors)
|
|
269
|
+
|
|
270
|
+
def log_for_level(self, *msg, args: tuple = (), end='\n', **kwargs):
|
|
271
|
+
self.log(level, *msg, args=args, end=end, **kwargs)
|
|
272
|
+
|
|
273
|
+
setattr(self, name, _MethodType(log_for_level, self))
|
|
274
|
+
return name
|
|
275
|
+
|
|
276
|
+
def add_levels(
|
|
277
|
+
self,
|
|
278
|
+
level_names: Mapping[int, str],
|
|
279
|
+
errors: _Literal["raise", "ignore", "handle", "force"] = "raise"
|
|
280
|
+
) -> None:
|
|
281
|
+
"""Adds new methods to the logger with specific levels and names.
|
|
282
|
+
|
|
283
|
+
:param level_names: A mapping of levels to names.
|
|
284
|
+
:param errors: The action to take if the level already exists
|
|
285
|
+
:return:
|
|
286
|
+
"""
|
|
287
|
+
for level, name in level_names.items():
|
|
288
|
+
self.add_level(level, name, errors)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def _add_one(name: str) -> str:
|
|
292
|
+
"""Add one to the end of a string.
|
|
293
|
+
|
|
294
|
+
:param name: The string to add one to.
|
|
295
|
+
:return: The string with one added to the end.
|
|
296
|
+
"""
|
|
297
|
+
match = _re.match(r'([\S]+)_([0-9]+)', name)
|
|
298
|
+
if not match:
|
|
299
|
+
return name + '_1'
|
|
300
|
+
return f'{match.group(1)}{int(match.group(2)) + 1}'
|
|
@@ -53,7 +53,7 @@ class StreamHandler(_StreamHandler):
|
|
|
53
53
|
msg = _hex_escape.sub(
|
|
54
54
|
'', _ansi_escape.sub('', record.msg.strip(' \t\n\x0b\x0c'))
|
|
55
55
|
)
|
|
56
|
-
if '\r'
|
|
56
|
+
if '\r' == msg[:1]:
|
|
57
57
|
file_descriptor = getattr(self.stream, 'fileno', None)
|
|
58
58
|
if file_descriptor:
|
|
59
59
|
file_descriptor = file_descriptor()
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# log21.__init__.py
|
|
2
2
|
# CodeWriter21
|
|
3
3
|
|
|
4
|
-
import io as _io
|
|
5
4
|
import os as _os
|
|
6
5
|
import logging as _logging
|
|
7
6
|
from typing import (Type as _Type, Tuple as _Tuple, Union as _Union,
|
|
@@ -24,18 +23,17 @@ from log21.ProgressBar import ProgressBar
|
|
|
24
23
|
from log21.LoggingWindow import LoggingWindow, LoggingWindowHandler
|
|
25
24
|
from log21.StreamHandler import StreamHandler, ColorizingStreamHandler
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
__github__ = "Https://GitHub.com/MPCodeWriter21/log21"
|
|
26
|
+
__author__ = 'CodeWriter21 (Mehrad Pooryoussof)'
|
|
27
|
+
__github__ = 'Https://GitHub.com/MPCodeWriter21/log21'
|
|
30
28
|
__all__ = [
|
|
31
29
|
'ColorizingStreamHandler', 'DecolorizingFileHandler', 'ColorizingFormatter',
|
|
32
30
|
'DecolorizingFormatter', 'get_logger', 'Logger', 'Colors', 'get_color',
|
|
33
31
|
'get_colors', 'CRITICAL', 'FATAL', 'ERROR', 'WARNING', 'WARN', 'INFO', 'DEBUG',
|
|
34
32
|
'NOTSET', 'INPUT', 'StreamHandler', 'ColorizingArgumentParser', 'PrettyPrinter',
|
|
35
33
|
'pformat', 'pprint', 'pretty_print', 'tree_format', 'TreePrint', 'Manager',
|
|
36
|
-
'get_color_name', 'closest_color', 'ansi_escape', '
|
|
37
|
-
'
|
|
38
|
-
'
|
|
34
|
+
'get_color_name', 'closest_color', 'ansi_escape', '__author__', '__github__',
|
|
35
|
+
'debug', 'info', 'warning', 'warn', 'error', 'critical', 'fatal', 'exception',
|
|
36
|
+
'log', 'basic_config', 'basicConfig', 'ProgressBar', 'progress_bar',
|
|
39
37
|
'LoggingWindow', 'LoggingWindowHandler', 'get_logging_window', 'CrashReporter',
|
|
40
38
|
'console_reporter', 'file_reporter', 'argumentify'
|
|
41
39
|
]
|
|
@@ -47,7 +45,7 @@ _logging.setLoggerClass(Logger)
|
|
|
47
45
|
def _prepare_formatter(
|
|
48
46
|
fmt: _Optional[str] = None,
|
|
49
47
|
style: str = '%',
|
|
50
|
-
datefmt: str =
|
|
48
|
+
datefmt: str = '%H:%M:%S',
|
|
51
49
|
show_level: bool = True,
|
|
52
50
|
show_time: bool = True,
|
|
53
51
|
colorize_time_and_level: bool = True,
|
|
@@ -58,11 +56,11 @@ def _prepare_formatter(
|
|
|
58
56
|
# Prepares a formatting if the fmt was None
|
|
59
57
|
if not fmt:
|
|
60
58
|
style = '%'
|
|
61
|
-
fmt =
|
|
59
|
+
fmt = '%(message)s'
|
|
62
60
|
if show_level:
|
|
63
|
-
fmt =
|
|
61
|
+
fmt = '[%(levelname)s] ' + fmt
|
|
64
62
|
if show_time:
|
|
65
|
-
fmt =
|
|
63
|
+
fmt = '[%(asctime)s] ' + fmt
|
|
66
64
|
fmt = '\r' + fmt
|
|
67
65
|
|
|
68
66
|
if level_colors and not issubclass(formatter_class, ColorizingFormatter):
|
|
@@ -102,7 +100,7 @@ def get_logger(
|
|
|
102
100
|
show_level: bool = True,
|
|
103
101
|
colorize_time_and_level: bool = True,
|
|
104
102
|
fmt: _Optional[str] = None,
|
|
105
|
-
datefmt: str =
|
|
103
|
+
datefmt: str = '%H:%M:%S',
|
|
106
104
|
style: str = '%',
|
|
107
105
|
handle_carriage_return: bool = True,
|
|
108
106
|
handle_new_line: bool = True,
|
|
@@ -181,6 +179,8 @@ def get_logger(
|
|
|
181
179
|
)
|
|
182
180
|
handler.setFormatter(formatter)
|
|
183
181
|
logger.addHandler(handler)
|
|
182
|
+
if level_names:
|
|
183
|
+
logger.add_levels(level_names, errors='ignore')
|
|
184
184
|
_manager.addLogger(name, logger)
|
|
185
185
|
|
|
186
186
|
if file:
|
|
@@ -208,7 +208,7 @@ def get_logging_window(
|
|
|
208
208
|
show_level: bool = True,
|
|
209
209
|
colorize_time_and_level: bool = True,
|
|
210
210
|
fmt: _Optional[str] = None,
|
|
211
|
-
datefmt: str =
|
|
211
|
+
datefmt: str = '%H:%M:%S',
|
|
212
212
|
style: str = '%',
|
|
213
213
|
handle_carriage_return: bool = True,
|
|
214
214
|
handle_new_line: bool = True,
|
|
@@ -420,7 +420,7 @@ def basic_config(
|
|
|
420
420
|
stream=None,
|
|
421
421
|
filename=None,
|
|
422
422
|
filemode: str = 'a',
|
|
423
|
-
date_format: str =
|
|
423
|
+
date_format: str = '%H:%M:%S',
|
|
424
424
|
style: str = '%',
|
|
425
425
|
format_: _Optional[str] = None,
|
|
426
426
|
level: _Optional[_Union[int, str]] = None
|
|
@@ -516,8 +516,8 @@ def basic_config(
|
|
|
516
516
|
if handler.formatter is None:
|
|
517
517
|
handler.setFormatter(formatter)
|
|
518
518
|
root.addHandler(handler)
|
|
519
|
-
|
|
520
|
-
|
|
519
|
+
if level is not None:
|
|
520
|
+
root.setLevel(level)
|
|
521
521
|
|
|
522
522
|
|
|
523
523
|
basicConfig = basic_config
|
|
@@ -628,4 +628,4 @@ def progress_bar(
|
|
|
628
628
|
|
|
629
629
|
console_reporter = CrashReporter.ConsoleReporter()
|
|
630
630
|
|
|
631
|
-
file_reporter = CrashReporter.FileReporter(file='crash_report.log')
|
|
631
|
+
file_reporter = CrashReporter.FileReporter(file='.crash_report.log')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: log21
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.1
|
|
4
4
|
Summary: A simple logging package that helps you log colorized messages in Windows console.
|
|
5
5
|
Author-email: "CodeWriter21(Mehrad Pooryoussof)" <CodeWriter21@gmail.com>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Classifier: Operating System :: Unix
|
|
17
17
|
Classifier: Operating System :: Microsoft :: Windows
|
|
18
18
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
19
|
-
Requires-Python: >=3.
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE.txt
|
|
22
22
|
Requires-Dist: webcolors
|
|
@@ -49,7 +49,7 @@ Features
|
|
|
49
49
|
modifications. It can also decolorize the output if you want to log into a file.
|
|
50
50
|
+ Pretty printing : Have you ever wanted to colorize the output of the pprint module? log21's pretty printer can do
|
|
51
51
|
that.
|
|
52
|
-
+ Tree printing : You can pass a dict or list to log21.tree_print function and it will print it in a tree-like
|
|
52
|
+
+ Tree printing : You can pass a dict or list to `log21.tree_print` function and it will print it in a tree-like
|
|
53
53
|
structure. It's also colorized XD.
|
|
54
54
|
+ ProgressBar : log21's progress bar can be used to show progress of a process in a beautiful way.
|
|
55
55
|
+ LoggingWindow : Helps you to log messages and debug your code in a window other than the console.
|
|
@@ -92,9 +92,12 @@ pip install git+https://github.com/MPCodeWriter21/log21
|
|
|
92
92
|
Changes
|
|
93
93
|
-------
|
|
94
94
|
|
|
95
|
-
### 2.
|
|
95
|
+
### 2.8.1
|
|
96
96
|
|
|
97
|
-
+
|
|
97
|
+
+ Fixed Carriage Return Handling.
|
|
98
|
+
+ Fixed setting level using `log21.basic_config`
|
|
99
|
+
+ Added more configuration for developer tools to the `pyproject.toml` file.
|
|
100
|
+
+ Added pre-commit.
|
|
98
101
|
|
|
99
102
|
[Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
|
|
100
103
|
|
|
@@ -233,7 +236,7 @@ for character in text:
|
|
|
233
236
|
|
|
234
237
|
window.error(colored_text)
|
|
235
238
|
|
|
236
|
-
# See more examples in
|
|
239
|
+
# See more examples in
|
|
237
240
|
# https://github.com/MPCodeWriter21/log21/blob/066efc1e72542531012d36974bbf6cd4c5941378/log21/LoggingWindow.py#L155
|
|
238
241
|
# and
|
|
239
242
|
# https://github.com/MPCodeWriter21/log21/blob/066efc1e72542531012d36974bbf6cd4c5941378/log21/__init__.py#L144
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|