custom-python-logger 2.0.1__tar.gz → 2.0.2__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.
- {custom_python_logger-2.0.1/custom_python_logger.egg-info → custom_python_logger-2.0.2}/PKG-INFO +1 -1
- custom_python_logger-2.0.2/custom_python_logger/consts.py +16 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger/logger.py +81 -63
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2/custom_python_logger.egg-info}/PKG-INFO +1 -1
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger.egg-info/SOURCES.txt +1 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/setup.py +1 -1
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/LICENSE +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/MANIFEST.in +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/README.md +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger/__init__.py +1 -1
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger/usage_example.py +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger.egg-info/dependency_links.txt +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger.egg-info/requires.txt +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger.egg-info/top_level.txt +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/pyproject.toml +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/requirements.txt +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/setup.cfg +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/tests/test_logger.py +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/tests/test_logger_pytest.py +0 -0
- {custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/tests/test_usage_example_pytest.py +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
LOG_COLORS = {
|
|
4
|
+
"DEBUG": "white",
|
|
5
|
+
"INFO": "green",
|
|
6
|
+
"WARNING": "yellow",
|
|
7
|
+
"STEP": "blue",
|
|
8
|
+
"ERROR": "red,bold",
|
|
9
|
+
"EXCEPTION": "light_red,bold",
|
|
10
|
+
"CRITICAL": "red,bg_white",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CustomLoggerLevel(Enum):
|
|
15
|
+
EXCEPTION = 45
|
|
16
|
+
STEP = 25
|
|
@@ -2,20 +2,39 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
4
|
import time
|
|
5
|
-
from logging import Logger
|
|
5
|
+
from logging import Logger
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Any, Callable, Optional
|
|
8
8
|
|
|
9
9
|
import yaml
|
|
10
10
|
from colorlog import ColoredFormatter
|
|
11
11
|
|
|
12
|
+
from custom_python_logger.consts import LOG_COLORS, CustomLoggerLevel
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
|
|
15
|
+
def json_pretty_format(
|
|
16
|
+
data: Any, indent: int = 4, sort_keys: bool = True, default: Callable = None
|
|
17
|
+
) -> str:
|
|
18
|
+
return json.dumps(data, indent=indent, sort_keys=sort_keys, default=default)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def yaml_pretty_format(
|
|
22
|
+
data: Any, indent: int = 4, sort_keys: bool = False, allow_unicode=True
|
|
23
|
+
) -> str:
|
|
24
|
+
return yaml.dump(
|
|
25
|
+
data, sort_keys=sort_keys, indent=indent, allow_unicode=allow_unicode
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_project_path_by_file(markers: Optional[list[str]] = None) -> Path:
|
|
30
|
+
if not markers:
|
|
31
|
+
markers = ["pyproject.toml", "setup.py", ".git", "requirements.txt", ".gitignore", ".github", ".gitlab"]
|
|
14
32
|
path = Path(__file__).resolve()
|
|
15
33
|
for parent in path.parents:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
for marker in markers:
|
|
35
|
+
if (parent / marker).exists():
|
|
36
|
+
return parent
|
|
37
|
+
raise RuntimeError(f'Project root with one of the markers: "{markers}" not found.')
|
|
19
38
|
|
|
20
39
|
|
|
21
40
|
def print_before_logger(project_name: str) -> None:
|
|
@@ -30,16 +49,55 @@ def print_before_logger(project_name: str) -> None:
|
|
|
30
49
|
|
|
31
50
|
class CustomLoggerAdapter(logging.LoggerAdapter):
|
|
32
51
|
def exception(self, msg: str, *args, **kwargs):
|
|
33
|
-
|
|
34
|
-
logging.addLevelName(level_no, "EXCEPTION")
|
|
52
|
+
logging.addLevelName(CustomLoggerLevel.EXCEPTION.value, "EXCEPTION")
|
|
35
53
|
kwargs.setdefault("stacklevel", 2)
|
|
36
|
-
self.log(
|
|
54
|
+
self.log(CustomLoggerLevel.EXCEPTION.value, msg, *args, exc_info=True, **kwargs)
|
|
37
55
|
|
|
38
56
|
def step(self, msg: str, *args, **kwargs):
|
|
39
|
-
|
|
40
|
-
logging.addLevelName(level_no, "STEP")
|
|
57
|
+
logging.addLevelName(CustomLoggerLevel.STEP.value, "STEP")
|
|
41
58
|
kwargs.setdefault("stacklevel", 2)
|
|
42
|
-
self.log(
|
|
59
|
+
self.log(CustomLoggerLevel.STEP.value, msg, *args, exc_info=False, **kwargs)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def clear_existing_handlers(logger: Logger) -> None:
|
|
63
|
+
for handler in logger.handlers[:]:
|
|
64
|
+
logger.removeHandler(handler)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def add_file_handler_if_specified(
|
|
68
|
+
logger: Logger,
|
|
69
|
+
log_file: bool,
|
|
70
|
+
log_file_path: Optional[str],
|
|
71
|
+
log_format: str,
|
|
72
|
+
) -> None:
|
|
73
|
+
if log_file and log_file_path is not None:
|
|
74
|
+
log_file_formatter = logging.Formatter(log_format)
|
|
75
|
+
|
|
76
|
+
# Create directory if it doesn't exist
|
|
77
|
+
log_dir = os.path.dirname(log_file_path)
|
|
78
|
+
if log_dir and not os.path.exists(log_dir):
|
|
79
|
+
os.makedirs(log_dir)
|
|
80
|
+
|
|
81
|
+
file_handler = logging.FileHandler(log_file_path)
|
|
82
|
+
|
|
83
|
+
file_handler.setFormatter(log_file_formatter)
|
|
84
|
+
logger.addHandler(file_handler)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def add_console_handler_if_specified(
|
|
88
|
+
logger: Logger,
|
|
89
|
+
console_output: bool,
|
|
90
|
+
log_format: str
|
|
91
|
+
):
|
|
92
|
+
if console_output:
|
|
93
|
+
log_console_formatter = ColoredFormatter(
|
|
94
|
+
"%(log_color)s " + log_format,
|
|
95
|
+
log_colors=LOG_COLORS,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
console_handler = logging.StreamHandler()
|
|
99
|
+
console_handler.setFormatter(log_console_formatter)
|
|
100
|
+
logger.addHandler(console_handler)
|
|
43
101
|
|
|
44
102
|
|
|
45
103
|
def configure_logging(
|
|
@@ -67,43 +125,20 @@ def configure_logging(
|
|
|
67
125
|
root_logger = logging.getLogger()
|
|
68
126
|
root_logger.setLevel(log_level)
|
|
69
127
|
|
|
70
|
-
|
|
71
|
-
for handler in root_logger.handlers[:]:
|
|
72
|
-
root_logger.removeHandler(handler)
|
|
128
|
+
clear_existing_handlers(logger=root_logger)
|
|
73
129
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if log_dir and not os.path.exists(log_dir):
|
|
81
|
-
os.makedirs(log_dir)
|
|
82
|
-
|
|
83
|
-
file_handler = logging.FileHandler(log_file_path)
|
|
84
|
-
|
|
85
|
-
file_handler.setFormatter(log_file_formatter)
|
|
86
|
-
root_logger.addHandler(file_handler)
|
|
87
|
-
|
|
88
|
-
# Add console handler if specified
|
|
89
|
-
if console_output:
|
|
90
|
-
# log_console_formatter = logging.Formatter('%(log_color)s ' + log_format)
|
|
91
|
-
log_console_formatter = ColoredFormatter(
|
|
92
|
-
"%(log_color)s " + log_format,
|
|
93
|
-
log_colors={
|
|
94
|
-
"DEBUG": "white",
|
|
95
|
-
"INFO": "green",
|
|
96
|
-
"WARNING": "yellow",
|
|
97
|
-
"STEP": "blue",
|
|
98
|
-
"ERROR": "red,bold",
|
|
99
|
-
"EXCEPTION": "light_red,bold",
|
|
100
|
-
"CRITICAL": "red,bg_white",
|
|
101
|
-
},
|
|
102
|
-
)
|
|
130
|
+
add_file_handler_if_specified(
|
|
131
|
+
logger=root_logger,
|
|
132
|
+
log_file=log_file,
|
|
133
|
+
log_file_path=log_file_path,
|
|
134
|
+
log_format=log_format,
|
|
135
|
+
)
|
|
103
136
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
137
|
+
add_console_handler_if_specified(
|
|
138
|
+
logger=root_logger,
|
|
139
|
+
console_output=console_output,
|
|
140
|
+
log_format=log_format,
|
|
141
|
+
)
|
|
107
142
|
|
|
108
143
|
|
|
109
144
|
def build_logger(
|
|
@@ -128,12 +163,9 @@ def build_logger(
|
|
|
128
163
|
log_file_path: Path to log file (if None, no file logging)
|
|
129
164
|
console_output: Whether to output logs to console
|
|
130
165
|
utc: Whether to use UTC time for log timestamps
|
|
131
|
-
|
|
132
166
|
Returns:
|
|
133
167
|
Configured logger
|
|
134
168
|
"""
|
|
135
|
-
print_before_logger(project_name=project_name)
|
|
136
|
-
|
|
137
169
|
if not log_file_path:
|
|
138
170
|
log_file_path = f"{get_project_path_by_file()}/logs/{project_name}.log"
|
|
139
171
|
log_file_path = log_file_path.lower().replace(" ", "_")
|
|
@@ -157,17 +189,3 @@ def build_logger(
|
|
|
157
189
|
|
|
158
190
|
def get_logger(name: str, extra: Optional[dict] = None) -> CustomLoggerAdapter:
|
|
159
191
|
return CustomLoggerAdapter(logging.getLogger(name), extra=extra)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
def json_pretty_format(
|
|
163
|
-
data: Any, indent: int = 4, sort_keys: bool = True, default: Callable = None
|
|
164
|
-
) -> str:
|
|
165
|
-
return json.dumps(data, indent=indent, sort_keys=sort_keys, default=default)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def yaml_pretty_format(
|
|
169
|
-
data: Any, indent: int = 4, sort_keys: bool = False, allow_unicode=True
|
|
170
|
-
) -> str:
|
|
171
|
-
return yaml.dump(
|
|
172
|
-
data, sort_keys=sort_keys, indent=indent, allow_unicode=allow_unicode
|
|
173
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger/usage_example.py
RENAMED
|
File without changes
|
|
File without changes
|
{custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/custom_python_logger.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{custom_python_logger-2.0.1 → custom_python_logger-2.0.2}/tests/test_usage_example_pytest.py
RENAMED
|
File without changes
|