log21 3.2.0__tar.gz → 3.3.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.
- {log21-3.2.0 → log21-3.3.0}/PKG-INFO +40 -9
- {log21-3.2.0 → log21-3.3.0}/README.md +39 -8
- {log21-3.2.0 → log21-3.3.0}/pyproject.toml +1 -1
- {log21-3.2.0 → log21-3.3.0}/src/log21/__init__.py +4 -2
- log21-3.3.0/src/log21/helper_types.py +126 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/_argparse.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/_module_helper.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/argparse.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/argumentify.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/colors.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/crash_reporter/__init__.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/crash_reporter/formatters.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/crash_reporter/reporters.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/file_handler.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/formatters.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/levels.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/logger.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/logging_window.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/manager.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/pprint.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/progress_bar.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/stream_handler.py +0 -0
- {log21-3.2.0 → log21-3.3.0}/src/log21/tree_print.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: log21
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: A simple logging package
|
|
5
5
|
Keywords: python,log,colorize,color,logging,Python3,CodeWriter21
|
|
6
6
|
Author: CodeWriter21(Mehrad Pooryoussof)
|
|
@@ -94,24 +94,55 @@ pip install git+https://github.com/MPCodeWriter21/log21
|
|
|
94
94
|
Changelog
|
|
95
95
|
---------
|
|
96
96
|
|
|
97
|
-
### v3.
|
|
97
|
+
### v3.3.0
|
|
98
98
|
|
|
99
|
-
Add `
|
|
100
|
-
|
|
99
|
+
Add `log21.helper_types` module.
|
|
100
|
+
|
|
101
|
+
This module contains a collection of useful types meant for using with argument parser
|
|
102
|
+
to parse CLI arguments to more usable formats.
|
|
103
|
+
|
|
104
|
+
+ `FileSize`: Can take `str` and `int` values. Will convert human inputs such as "121 KB",
|
|
105
|
+
"21MiB", or "4.56 GB" to bytes. Can also be used to represent bytes value in more
|
|
106
|
+
human-readable formats.
|
|
101
107
|
|
|
102
108
|
For even more control you can still define Logger, Handlers, and Formatters manually.
|
|
103
109
|
|
|
104
110
|
#### Example
|
|
105
111
|
|
|
106
112
|
```python
|
|
113
|
+
from pathlib import Path
|
|
114
|
+
|
|
107
115
|
import log21
|
|
116
|
+
from log21.helper_types import FileSize
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def main(path: Path, min_size: FileSize, max_size: FileSize, /):
|
|
120
|
+
log21.info(
|
|
121
|
+
"Files that are smaller than %s or bigger than %s will be ignored.",
|
|
122
|
+
args=(min_size, max_size),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
for file in path.iterdir():
|
|
126
|
+
if not file.is_file():
|
|
127
|
+
continue
|
|
128
|
+
if min_size <= (size := file.stat().st_size) <= max_size:
|
|
129
|
+
log21.print(
|
|
130
|
+
"`%s` is %s.",
|
|
131
|
+
args=(file, FileSize(size).humanize(binary=False, fmt="%.4f")),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if __name__ == "__main__":
|
|
136
|
+
log21.argumentify(main)
|
|
137
|
+
```
|
|
108
138
|
|
|
109
|
-
|
|
110
|
-
"My File Logger", show_level=False, show_time=True, file="myapp.log", file_mode="a",
|
|
111
|
-
file_encoding="utf-8"
|
|
112
|
-
)
|
|
139
|
+
Example usage and output:
|
|
113
140
|
|
|
114
|
-
|
|
141
|
+
```shell
|
|
142
|
+
$ uv run test.py . "1.23MiB" "0.5 GB"
|
|
143
|
+
[21:21:21] [INFO] Files that are smaller than 1.23 MiB or bigger than 476.84 MiB will be
|
|
144
|
+
ignored.
|
|
145
|
+
`myfile21.zip` is 35.1856 MB.
|
|
115
146
|
```
|
|
116
147
|
|
|
117
148
|
[Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
|
|
@@ -69,24 +69,55 @@ pip install git+https://github.com/MPCodeWriter21/log21
|
|
|
69
69
|
Changelog
|
|
70
70
|
---------
|
|
71
71
|
|
|
72
|
-
### v3.
|
|
72
|
+
### v3.3.0
|
|
73
73
|
|
|
74
|
-
Add `
|
|
75
|
-
|
|
74
|
+
Add `log21.helper_types` module.
|
|
75
|
+
|
|
76
|
+
This module contains a collection of useful types meant for using with argument parser
|
|
77
|
+
to parse CLI arguments to more usable formats.
|
|
78
|
+
|
|
79
|
+
+ `FileSize`: Can take `str` and `int` values. Will convert human inputs such as "121 KB",
|
|
80
|
+
"21MiB", or "4.56 GB" to bytes. Can also be used to represent bytes value in more
|
|
81
|
+
human-readable formats.
|
|
76
82
|
|
|
77
83
|
For even more control you can still define Logger, Handlers, and Formatters manually.
|
|
78
84
|
|
|
79
85
|
#### Example
|
|
80
86
|
|
|
81
87
|
```python
|
|
88
|
+
from pathlib import Path
|
|
89
|
+
|
|
82
90
|
import log21
|
|
91
|
+
from log21.helper_types import FileSize
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def main(path: Path, min_size: FileSize, max_size: FileSize, /):
|
|
95
|
+
log21.info(
|
|
96
|
+
"Files that are smaller than %s or bigger than %s will be ignored.",
|
|
97
|
+
args=(min_size, max_size),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
for file in path.iterdir():
|
|
101
|
+
if not file.is_file():
|
|
102
|
+
continue
|
|
103
|
+
if min_size <= (size := file.stat().st_size) <= max_size:
|
|
104
|
+
log21.print(
|
|
105
|
+
"`%s` is %s.",
|
|
106
|
+
args=(file, FileSize(size).humanize(binary=False, fmt="%.4f")),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == "__main__":
|
|
111
|
+
log21.argumentify(main)
|
|
112
|
+
```
|
|
83
113
|
|
|
84
|
-
|
|
85
|
-
"My File Logger", show_level=False, show_time=True, file="myapp.log", file_mode="a",
|
|
86
|
-
file_encoding="utf-8"
|
|
87
|
-
)
|
|
114
|
+
Example usage and output:
|
|
88
115
|
|
|
89
|
-
|
|
116
|
+
```shell
|
|
117
|
+
$ uv run test.py . "1.23MiB" "0.5 GB"
|
|
118
|
+
[21:21:21] [INFO] Files that are smaller than 1.23 MiB or bigger than 476.84 MiB will be
|
|
119
|
+
ignored.
|
|
120
|
+
`myfile21.zip` is 35.1856 MB.
|
|
90
121
|
```
|
|
91
122
|
|
|
92
123
|
[Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
|
|
@@ -10,6 +10,8 @@ from types import ModuleType as _ModuleType
|
|
|
10
10
|
from typing import (Type as _Type, Union as _Union, Literal as _Literal,
|
|
11
11
|
Mapping as _Mapping, Iterable as _Iterable, Optional as _Optional)
|
|
12
12
|
|
|
13
|
+
import log21.helper_types
|
|
14
|
+
|
|
13
15
|
from . import crash_reporter
|
|
14
16
|
from .colors import (Colors, get_color, get_colors, ansi_escape, closest_color,
|
|
15
17
|
get_color_name)
|
|
@@ -31,7 +33,7 @@ from .stream_handler import StreamHandler, ColorizingStreamHandler
|
|
|
31
33
|
# yapf: enable
|
|
32
34
|
|
|
33
35
|
__author__ = 'CodeWriter21 (Mehrad Pooryoussof)'
|
|
34
|
-
__version__ = '3.
|
|
36
|
+
__version__ = '3.3.0'
|
|
35
37
|
__github__ = 'https://GitHub.com/MPCodeWriter21/log21'
|
|
36
38
|
__all__ = [
|
|
37
39
|
'ColorizingStreamHandler', 'DecolorizingFileHandler', 'ColorizingFormatter',
|
|
@@ -44,7 +46,7 @@ __all__ = [
|
|
|
44
46
|
'log', 'basic_config', 'basicConfig', 'ProgressBar', 'LoggingWindow',
|
|
45
47
|
'LoggingWindowHandler', 'get_logging_window', 'crash_reporter', 'console_reporter',
|
|
46
48
|
'file_reporter', 'argumentify', 'ArgumentError', 'IncompatibleArgumentsError',
|
|
47
|
-
'RequiredArgumentError', 'TooFewArgumentsError'
|
|
49
|
+
'RequiredArgumentError', 'TooFewArgumentsError', 'FileHandler'
|
|
48
50
|
]
|
|
49
51
|
|
|
50
52
|
_manager = Manager()
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# log21.helper_types.py
|
|
2
|
+
# CodeWriter21
|
|
3
|
+
"""A collection of useful types meant for using with argument parser to parse CLI
|
|
4
|
+
arguments to more usable formats.
|
|
5
|
+
|
|
6
|
+
+ FileSize: Can take `str` and `int` values. Will convert human inputs such as "121 KB",
|
|
7
|
+
"21MiB", or "4.56 GB" to bytes. Can also be used to represent bytes value in more
|
|
8
|
+
human-readable formats.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# yapf: disable
|
|
12
|
+
|
|
13
|
+
import re as _re
|
|
14
|
+
from math import log as _log
|
|
15
|
+
from typing import Union as _Union, SupportsInt as _SupportsInt
|
|
16
|
+
|
|
17
|
+
# yapf: enable
|
|
18
|
+
|
|
19
|
+
__all__ = ["FileSize"]
|
|
20
|
+
|
|
21
|
+
POWERS = "KMGTPEZYRQ"
|
|
22
|
+
FILE_SIZE_PATTERN = _re.compile(rf"^([+-]?[0-9]+(?:\.[0-9]+)?)\s*(|[{POWERS}])(i?)B$")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FileSize:
|
|
26
|
+
|
|
27
|
+
def __init__(self, value: _Union[int, str]) -> None:
|
|
28
|
+
"""An interface for converting different inputs to file-size (bytes).
|
|
29
|
+
|
|
30
|
+
:param value: int value in bytes or a string such as "100 KB", "20MiB", or "1.23
|
|
31
|
+
GB"
|
|
32
|
+
:raises TypeError: If the value is not of type int or str
|
|
33
|
+
:raises ValueError: If the str value does not match the file-size pattern:
|
|
34
|
+
^([+-]?[0-9]+(?:\\.[0-9]+)?)\\s*(|[KMGTPEZYRQ])(i?)B$
|
|
35
|
+
"""
|
|
36
|
+
if isinstance(value, int):
|
|
37
|
+
self.bytes = value
|
|
38
|
+
elif isinstance(value, str):
|
|
39
|
+
match = FILE_SIZE_PATTERN.match(value)
|
|
40
|
+
if not match:
|
|
41
|
+
raise ValueError(f"Input does not match the file-size pattern: {value}")
|
|
42
|
+
val, prefix, binary = match.groups()
|
|
43
|
+
power = POWERS.index(prefix) + 1
|
|
44
|
+
assert power is not None
|
|
45
|
+
self.bytes = int(float(val) * (1024 if binary else 1000)**power)
|
|
46
|
+
else:
|
|
47
|
+
raise TypeError(f"Input to FileSize() can be int or str, not {type(value)}")
|
|
48
|
+
|
|
49
|
+
def humanize(
|
|
50
|
+
self,
|
|
51
|
+
binary: bool = False,
|
|
52
|
+
gnu: bool = False,
|
|
53
|
+
fmt: str = "%.2f",
|
|
54
|
+
) -> str:
|
|
55
|
+
"""Returns the size in a human readable way."""
|
|
56
|
+
base = 1024 if (gnu or binary) else 1000
|
|
57
|
+
abs_bytes = abs(self.bytes)
|
|
58
|
+
|
|
59
|
+
if abs_bytes == 1 and not gnu:
|
|
60
|
+
return f"{self.bytes} Byte"
|
|
61
|
+
|
|
62
|
+
if abs_bytes < base:
|
|
63
|
+
return f"{self.bytes}B" if gnu else f"{self.bytes} Bytes"
|
|
64
|
+
|
|
65
|
+
power = int(min(_log(abs_bytes, base), len(POWERS)))
|
|
66
|
+
result: str = fmt % (self.bytes / (base**power))
|
|
67
|
+
if gnu:
|
|
68
|
+
return result + POWERS[power - 1]
|
|
69
|
+
result += " " + POWERS[power - 1]
|
|
70
|
+
if binary:
|
|
71
|
+
result += "i"
|
|
72
|
+
result += "B"
|
|
73
|
+
return result
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def KB(self) -> float:
|
|
77
|
+
return self.bytes / 1000
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def MB(self) -> float:
|
|
81
|
+
return self.bytes / 1000_000
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def GB(self) -> float:
|
|
85
|
+
return self.bytes / 1000_000_000
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def KiB(self) -> float:
|
|
89
|
+
return self.bytes / 1024
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def MiB(self) -> float:
|
|
93
|
+
return self.bytes / 1048576
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def GiB(self) -> float:
|
|
97
|
+
return self.bytes / 1073741824
|
|
98
|
+
|
|
99
|
+
def __int__(self) -> int:
|
|
100
|
+
return self.bytes
|
|
101
|
+
|
|
102
|
+
def __eq__(self, value: object) -> bool:
|
|
103
|
+
if not isinstance(value, _SupportsInt):
|
|
104
|
+
return False
|
|
105
|
+
return self.bytes == int(value)
|
|
106
|
+
|
|
107
|
+
def __lt__(self, value: _SupportsInt) -> bool:
|
|
108
|
+
return self.bytes < int(value)
|
|
109
|
+
|
|
110
|
+
def __le__(self, value: _SupportsInt) -> bool:
|
|
111
|
+
return self.bytes <= int(value)
|
|
112
|
+
|
|
113
|
+
def __gt__(self, value: _SupportsInt) -> bool:
|
|
114
|
+
return int(value) < self.bytes
|
|
115
|
+
|
|
116
|
+
def __ge__(self, value: _SupportsInt) -> bool:
|
|
117
|
+
return int(value) <= self.bytes
|
|
118
|
+
|
|
119
|
+
def __add__(self, value: _SupportsInt) -> "FileSize":
|
|
120
|
+
return FileSize(self.bytes + int(value))
|
|
121
|
+
|
|
122
|
+
def __str__(self) -> str:
|
|
123
|
+
return self.humanize(binary=True)
|
|
124
|
+
|
|
125
|
+
def __repr__(self) -> str:
|
|
126
|
+
return f"<{self.__class__.__name__}: '{self!s}'>"
|
|
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
|