python-coloured-logger 1.0.1__tar.gz → 1.0.3__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.
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/PKG-INFO +9 -6
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/README.md +5 -5
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/pyproject.toml +16 -1
- python_coloured_logger-1.0.3/src/coloured_logger/__init__.py +10 -0
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/src/coloured_logger/formatter.py +11 -3
- python_coloured_logger-1.0.3/src/coloured_logger/py.typed +0 -0
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/src/python_coloured_logger.egg-info/PKG-INFO +9 -6
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/src/python_coloured_logger.egg-info/SOURCES.txt +1 -0
- python_coloured_logger-1.0.3/tests/test_formatter.py +217 -0
- python_coloured_logger-1.0.1/src/coloured_logger/__init__.py +0 -3
- python_coloured_logger-1.0.1/tests/test_formatter.py +0 -31
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/LICENSE +0 -0
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/setup.cfg +0 -0
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/src/python_coloured_logger.egg-info/dependency_links.txt +0 -0
- {python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/src/python_coloured_logger.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-coloured-logger
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Simple coloured logging for Flask and FastAPI apps
|
|
5
5
|
Author: Skulldorom
|
|
6
6
|
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Skulldorom/python-coloured-logger
|
|
8
|
+
Project-URL: Repository, https://github.com/Skulldorom/python-coloured-logger
|
|
9
|
+
Project-URL: Issues, https://github.com/Skulldorom/python-coloured-logger/issues
|
|
7
10
|
Keywords: logging,flask,fastapi,color
|
|
8
11
|
Classifier: Programming Language :: Python :: 3
|
|
9
12
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -60,10 +63,10 @@ logger.critical("System crash")
|
|
|
60
63
|
Example output:
|
|
61
64
|
|
|
62
65
|
```text
|
|
63
|
-
[2026
|
|
64
|
-
[2026
|
|
65
|
-
[2026
|
|
66
|
-
[2026
|
|
66
|
+
[20/06/2026] [INFO] Server started
|
|
67
|
+
[20/06/2026] [SUCCESS] Database connected
|
|
68
|
+
[20/06/2026] [WARNING] High memory usage
|
|
69
|
+
[20/06/2026] [ERROR] Request failed
|
|
67
70
|
```
|
|
68
71
|
|
|
69
72
|
---
|
|
@@ -172,7 +175,7 @@ FLASK_LOG_DATE_FORMAT=%H:%M:%S
|
|
|
172
175
|
|
|
173
176
|
## Requirements
|
|
174
177
|
|
|
175
|
-
- Python 3.
|
|
178
|
+
- Python 3.8+
|
|
176
179
|
- Flask (optional)
|
|
177
180
|
- FastAPI / Uvicorn (optional)
|
|
178
181
|
|
|
@@ -45,10 +45,10 @@ logger.critical("System crash")
|
|
|
45
45
|
Example output:
|
|
46
46
|
|
|
47
47
|
```text
|
|
48
|
-
[2026
|
|
49
|
-
[2026
|
|
50
|
-
[2026
|
|
51
|
-
[2026
|
|
48
|
+
[20/06/2026] [INFO] Server started
|
|
49
|
+
[20/06/2026] [SUCCESS] Database connected
|
|
50
|
+
[20/06/2026] [WARNING] High memory usage
|
|
51
|
+
[20/06/2026] [ERROR] Request failed
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
---
|
|
@@ -157,7 +157,7 @@ FLASK_LOG_DATE_FORMAT=%H:%M:%S
|
|
|
157
157
|
|
|
158
158
|
## Requirements
|
|
159
159
|
|
|
160
|
-
- Python 3.
|
|
160
|
+
- Python 3.8+
|
|
161
161
|
- Flask (optional)
|
|
162
162
|
- FastAPI / Uvicorn (optional)
|
|
163
163
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-coloured-logger"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.3"
|
|
8
8
|
description = "Simple coloured logging for Flask and FastAPI apps"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -18,8 +18,23 @@ classifiers = [
|
|
|
18
18
|
"Operating System :: OS Independent",
|
|
19
19
|
]
|
|
20
20
|
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://github.com/Skulldorom/python-coloured-logger"
|
|
23
|
+
Repository = "https://github.com/Skulldorom/python-coloured-logger"
|
|
24
|
+
Issues = "https://github.com/Skulldorom/python-coloured-logger/issues"
|
|
25
|
+
|
|
21
26
|
[tool.setuptools]
|
|
22
27
|
package-dir = { "" = "src" }
|
|
23
28
|
|
|
29
|
+
[tool.setuptools.package-data]
|
|
30
|
+
"coloured_logger" = ["py.typed"]
|
|
31
|
+
|
|
24
32
|
[tool.setuptools.packages.find]
|
|
25
33
|
where = ["src"]
|
|
34
|
+
|
|
35
|
+
[tool.mypy]
|
|
36
|
+
strict = true
|
|
37
|
+
python_version = "3.8"
|
|
38
|
+
files = ["src"]
|
|
39
|
+
warn_unused_ignores = true
|
|
40
|
+
warn_redundant_casts = true
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
from .formatter import ColouredFormatter, SUCCESS_LEVEL, get_logger, log, setup_logging
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("python-coloured-logger")
|
|
7
|
+
except PackageNotFoundError:
|
|
8
|
+
__version__ = "unknown"
|
|
9
|
+
|
|
10
|
+
__all__ = ["ColouredFormatter", "SUCCESS_LEVEL", "get_logger", "log", "setup_logging", "__version__"]
|
{python_coloured_logger-1.0.1 → python_coloured_logger-1.0.3}/src/coloured_logger/formatter.py
RENAMED
|
@@ -4,6 +4,8 @@ from typing import Optional, TextIO
|
|
|
4
4
|
|
|
5
5
|
SUCCESS_LEVEL = 25
|
|
6
6
|
|
|
7
|
+
_success_level_registered: bool = False
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
def _env_bool(name: str, default: bool) -> bool:
|
|
9
11
|
value = os.getenv(name)
|
|
@@ -23,7 +25,7 @@ def _resolve_use_color(use_color: Optional[bool]) -> bool:
|
|
|
23
25
|
def _resolve_datefmt(datefmt: Optional[str]) -> str:
|
|
24
26
|
if datefmt:
|
|
25
27
|
return datefmt
|
|
26
|
-
return os.getenv("FLASK_LOG_DATE_FORMAT") or os.getenv("COLOURED_LOGGER_DATE_FORMAT") or "%d/%
|
|
28
|
+
return os.getenv("FLASK_LOG_DATE_FORMAT") or os.getenv("COLOURED_LOGGER_DATE_FORMAT") or "%d/%m/%Y"
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
class ColouredFormatter(logging.Formatter):
|
|
@@ -60,6 +62,10 @@ class ColouredFormatter(logging.Formatter):
|
|
|
60
62
|
|
|
61
63
|
|
|
62
64
|
def _ensure_success_level() -> None:
|
|
65
|
+
global _success_level_registered
|
|
66
|
+
if _success_level_registered:
|
|
67
|
+
return
|
|
68
|
+
|
|
63
69
|
if logging.getLevelName(SUCCESS_LEVEL) != "SUCCESS":
|
|
64
70
|
logging.addLevelName(SUCCESS_LEVEL, "SUCCESS")
|
|
65
71
|
|
|
@@ -71,11 +77,12 @@ def _ensure_success_level() -> None:
|
|
|
71
77
|
self._log(SUCCESS_LEVEL, msg, args, **kwargs)
|
|
72
78
|
|
|
73
79
|
setattr(logging.Logger, "success", success)
|
|
80
|
+
_success_level_registered = True
|
|
74
81
|
|
|
75
82
|
|
|
76
83
|
def setup_logging(
|
|
77
84
|
logger_name: Optional[str] = None,
|
|
78
|
-
level: int = logging.
|
|
85
|
+
level: int = logging.NOTSET,
|
|
79
86
|
stream: Optional[TextIO] = None,
|
|
80
87
|
use_color: Optional[bool] = None,
|
|
81
88
|
datefmt: Optional[str] = None,
|
|
@@ -83,7 +90,8 @@ def setup_logging(
|
|
|
83
90
|
) -> logging.Logger:
|
|
84
91
|
_ensure_success_level()
|
|
85
92
|
logger = logging.getLogger(logger_name)
|
|
86
|
-
logger.
|
|
93
|
+
if level != logging.NOTSET or logger.level == logging.NOTSET:
|
|
94
|
+
logger.setLevel(level)
|
|
87
95
|
|
|
88
96
|
managed_handler_exists = any(
|
|
89
97
|
isinstance(handler, logging.StreamHandler) and isinstance(handler.formatter, ColouredFormatter)
|
|
File without changes
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-coloured-logger
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Simple coloured logging for Flask and FastAPI apps
|
|
5
5
|
Author: Skulldorom
|
|
6
6
|
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Skulldorom/python-coloured-logger
|
|
8
|
+
Project-URL: Repository, https://github.com/Skulldorom/python-coloured-logger
|
|
9
|
+
Project-URL: Issues, https://github.com/Skulldorom/python-coloured-logger/issues
|
|
7
10
|
Keywords: logging,flask,fastapi,color
|
|
8
11
|
Classifier: Programming Language :: Python :: 3
|
|
9
12
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -60,10 +63,10 @@ logger.critical("System crash")
|
|
|
60
63
|
Example output:
|
|
61
64
|
|
|
62
65
|
```text
|
|
63
|
-
[2026
|
|
64
|
-
[2026
|
|
65
|
-
[2026
|
|
66
|
-
[2026
|
|
66
|
+
[20/06/2026] [INFO] Server started
|
|
67
|
+
[20/06/2026] [SUCCESS] Database connected
|
|
68
|
+
[20/06/2026] [WARNING] High memory usage
|
|
69
|
+
[20/06/2026] [ERROR] Request failed
|
|
67
70
|
```
|
|
68
71
|
|
|
69
72
|
---
|
|
@@ -172,7 +175,7 @@ FLASK_LOG_DATE_FORMAT=%H:%M:%S
|
|
|
172
175
|
|
|
173
176
|
## Requirements
|
|
174
177
|
|
|
175
|
-
- Python 3.
|
|
178
|
+
- Python 3.8+
|
|
176
179
|
- Flask (optional)
|
|
177
180
|
- FastAPI / Uvicorn (optional)
|
|
178
181
|
|
|
@@ -3,6 +3,7 @@ README.md
|
|
|
3
3
|
pyproject.toml
|
|
4
4
|
src/coloured_logger/__init__.py
|
|
5
5
|
src/coloured_logger/formatter.py
|
|
6
|
+
src/coloured_logger/py.typed
|
|
6
7
|
src/python_coloured_logger.egg-info/PKG-INFO
|
|
7
8
|
src/python_coloured_logger.egg-info/SOURCES.txt
|
|
8
9
|
src/python_coloured_logger.egg-info/dependency_links.txt
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from coloured_logger import ColouredFormatter, SUCCESS_LEVEL, get_logger, setup_logging
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ColouredFormatterTests(unittest.TestCase):
|
|
10
|
+
@classmethod
|
|
11
|
+
def setUpClass(cls):
|
|
12
|
+
# Register the SUCCESS level name so direct formatter usage sees "SUCCESS"
|
|
13
|
+
if logging.getLevelName(SUCCESS_LEVEL) != "SUCCESS":
|
|
14
|
+
logging.addLevelName(SUCCESS_LEVEL, "SUCCESS")
|
|
15
|
+
|
|
16
|
+
def test_format_without_color(self):
|
|
17
|
+
formatter = ColouredFormatter(use_color=False, datefmt="%Y")
|
|
18
|
+
record = logging.LogRecord("test", logging.INFO, __file__, 1, "hello", (), None)
|
|
19
|
+
output = formatter.format(record)
|
|
20
|
+
self.assertIn("[INFO] hello", output)
|
|
21
|
+
self.assertNotIn("\033[", output)
|
|
22
|
+
|
|
23
|
+
def test_format_with_color(self):
|
|
24
|
+
formatter = ColouredFormatter(use_color=True, datefmt="%Y")
|
|
25
|
+
record = logging.LogRecord("test", logging.INFO, __file__, 1, "hello", (), None)
|
|
26
|
+
output = formatter.format(record)
|
|
27
|
+
self.assertIn("[INFO] hello", output)
|
|
28
|
+
self.assertIn("\033[", output)
|
|
29
|
+
|
|
30
|
+
def test_all_log_levels_have_colors(self):
|
|
31
|
+
levels = {
|
|
32
|
+
logging.DEBUG: "DEBUG",
|
|
33
|
+
logging.INFO: "INFO",
|
|
34
|
+
SUCCESS_LEVEL: "SUCCESS",
|
|
35
|
+
logging.WARNING: "WARNING",
|
|
36
|
+
logging.ERROR: "ERROR",
|
|
37
|
+
logging.CRITICAL: "CRITICAL",
|
|
38
|
+
}
|
|
39
|
+
for levelno, levelname in levels.items():
|
|
40
|
+
formatter = ColouredFormatter(use_color=True)
|
|
41
|
+
record = logging.LogRecord("test", levelno, __file__, 1, "msg", (), None)
|
|
42
|
+
output = formatter.format(record)
|
|
43
|
+
self.assertIn(f"[{levelname}] msg", output)
|
|
44
|
+
self.assertIn("\033[", output)
|
|
45
|
+
|
|
46
|
+
def test_unknown_level_returns_uncolored(self):
|
|
47
|
+
formatter = ColouredFormatter(use_color=True)
|
|
48
|
+
record = logging.LogRecord("test", 99, __file__, 1, "msg", (), None)
|
|
49
|
+
output = formatter.format(record)
|
|
50
|
+
self.assertIn("[Level 99] msg", output)
|
|
51
|
+
self.assertNotIn("\033[", output)
|
|
52
|
+
|
|
53
|
+
def test_default_date_format(self):
|
|
54
|
+
formatter = ColouredFormatter(use_color=False)
|
|
55
|
+
self.assertEqual(formatter.datefmt, "%d/%m/%Y")
|
|
56
|
+
|
|
57
|
+
def test_custom_date_format(self):
|
|
58
|
+
formatter = ColouredFormatter(datefmt="%H:%M", use_color=False)
|
|
59
|
+
self.assertEqual(formatter.datefmt, "%H:%M")
|
|
60
|
+
|
|
61
|
+
def test_default_message_format(self):
|
|
62
|
+
formatter = ColouredFormatter(use_color=False)
|
|
63
|
+
record = logging.LogRecord("test", logging.INFO, __file__, 1, "hello world", (), None)
|
|
64
|
+
output = formatter.format(record)
|
|
65
|
+
self.assertIn("[INFO] hello world", output)
|
|
66
|
+
self.assertNotIn("\033[", output)
|
|
67
|
+
|
|
68
|
+
def test_custom_message_format(self):
|
|
69
|
+
formatter = ColouredFormatter(fmt="%(levelname)s: %(message)s", use_color=False)
|
|
70
|
+
record = logging.LogRecord("test", logging.ERROR, __file__, 1, "oops", (), None)
|
|
71
|
+
output = formatter.format(record)
|
|
72
|
+
self.assertEqual(output, "ERROR: oops")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class SetupLoggingTests(unittest.TestCase):
|
|
76
|
+
def _make_stream_logger(self, **kwargs):
|
|
77
|
+
stream = io.StringIO()
|
|
78
|
+
logger = setup_logging(stream=stream, use_color=False, datefmt="%Y", **kwargs)
|
|
79
|
+
return logger, stream
|
|
80
|
+
|
|
81
|
+
def test_default_level_is_notset(self):
|
|
82
|
+
logger, _ = self._make_stream_logger(logger_name="test_notset")
|
|
83
|
+
self.assertEqual(logger.level, logging.NOTSET)
|
|
84
|
+
|
|
85
|
+
def test_custom_level(self):
|
|
86
|
+
logger, _ = self._make_stream_logger(logger_name="test_level_warn", level=logging.WARNING)
|
|
87
|
+
self.assertEqual(logger.level, logging.WARNING)
|
|
88
|
+
|
|
89
|
+
def test_default_level_does_not_override_existing_logger_level(self):
|
|
90
|
+
logger_name = "test_preserve_level"
|
|
91
|
+
original = logging.getLogger(logger_name)
|
|
92
|
+
original.setLevel(logging.ERROR)
|
|
93
|
+
|
|
94
|
+
logger, _ = self._make_stream_logger(logger_name=logger_name)
|
|
95
|
+
self.assertEqual(logger.level, logging.ERROR)
|
|
96
|
+
|
|
97
|
+
def test_handler_deduplication(self):
|
|
98
|
+
logger1 = setup_logging(logger_name="test_dedup", use_color=False)
|
|
99
|
+
count1 = len(logger1.handlers)
|
|
100
|
+
logger2 = setup_logging(logger_name="test_dedup", use_color=False)
|
|
101
|
+
count2 = len(logger2.handlers)
|
|
102
|
+
self.assertEqual(count1, count2)
|
|
103
|
+
self.assertGreaterEqual(count1, 1)
|
|
104
|
+
|
|
105
|
+
def test_success_level_output(self):
|
|
106
|
+
logger, stream = self._make_stream_logger(
|
|
107
|
+
logger_name="test_success", level=logging.DEBUG
|
|
108
|
+
)
|
|
109
|
+
logger.success("done")
|
|
110
|
+
value = stream.getvalue()
|
|
111
|
+
self.assertIn("[SUCCESS] done", value)
|
|
112
|
+
|
|
113
|
+
def test_debug_output(self):
|
|
114
|
+
logger, stream = self._make_stream_logger(
|
|
115
|
+
logger_name="test_debug", level=logging.DEBUG
|
|
116
|
+
)
|
|
117
|
+
logger.debug("trace")
|
|
118
|
+
self.assertIn("[DEBUG] trace", stream.getvalue())
|
|
119
|
+
|
|
120
|
+
def test_info_output(self):
|
|
121
|
+
logger, stream = self._make_stream_logger(
|
|
122
|
+
logger_name="test_info", level=logging.DEBUG
|
|
123
|
+
)
|
|
124
|
+
logger.info("running")
|
|
125
|
+
self.assertIn("[INFO] running", stream.getvalue())
|
|
126
|
+
|
|
127
|
+
def test_warning_output(self):
|
|
128
|
+
logger, stream = self._make_stream_logger(
|
|
129
|
+
logger_name="test_warn", level=logging.DEBUG
|
|
130
|
+
)
|
|
131
|
+
logger.warning("caution")
|
|
132
|
+
self.assertIn("[WARNING] caution", stream.getvalue())
|
|
133
|
+
|
|
134
|
+
def test_error_output(self):
|
|
135
|
+
logger, stream = self._make_stream_logger(
|
|
136
|
+
logger_name="test_err", level=logging.DEBUG
|
|
137
|
+
)
|
|
138
|
+
logger.error("fail")
|
|
139
|
+
self.assertIn("[ERROR] fail", stream.getvalue())
|
|
140
|
+
|
|
141
|
+
def test_critical_output(self):
|
|
142
|
+
logger, stream = self._make_stream_logger(
|
|
143
|
+
logger_name="test_crit", level=logging.DEBUG
|
|
144
|
+
)
|
|
145
|
+
logger.critical("boom")
|
|
146
|
+
self.assertIn("[CRITICAL] boom", stream.getvalue())
|
|
147
|
+
|
|
148
|
+
def test_respects_level_filtering(self):
|
|
149
|
+
logger, stream = self._make_stream_logger(
|
|
150
|
+
logger_name="test_filter", level=logging.WARNING
|
|
151
|
+
)
|
|
152
|
+
logger.info("should not appear")
|
|
153
|
+
logger.warning("should appear")
|
|
154
|
+
value = stream.getvalue()
|
|
155
|
+
self.assertNotIn("should not appear", value)
|
|
156
|
+
self.assertIn("should appear", value)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class GetLoggerTests(unittest.TestCase):
|
|
160
|
+
def test_get_logger_returns_logger(self):
|
|
161
|
+
logger = get_logger("test_gl", use_color=False)
|
|
162
|
+
self.assertIsInstance(logger, logging.Logger)
|
|
163
|
+
self.assertEqual(logger.name, "test_gl")
|
|
164
|
+
|
|
165
|
+
def test_get_logger_default_level(self):
|
|
166
|
+
logger = get_logger("test_gl_default", use_color=False)
|
|
167
|
+
self.assertEqual(logger.level, logging.NOTSET)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class EnvironmentVariableTests(unittest.TestCase):
|
|
171
|
+
def setUp(self):
|
|
172
|
+
self._saved = {}
|
|
173
|
+
for var in (
|
|
174
|
+
"COLOURED_LOGGER_COLOR",
|
|
175
|
+
"FLASK_LOG_COLOR",
|
|
176
|
+
"COLOURED_LOGGER_DATE_FORMAT",
|
|
177
|
+
"FLASK_LOG_DATE_FORMAT",
|
|
178
|
+
):
|
|
179
|
+
self._saved[var] = os.environ.pop(var, None)
|
|
180
|
+
|
|
181
|
+
def tearDown(self):
|
|
182
|
+
for var, value in self._saved.items():
|
|
183
|
+
if value is not None:
|
|
184
|
+
os.environ[var] = value
|
|
185
|
+
elif var in os.environ:
|
|
186
|
+
del os.environ[var]
|
|
187
|
+
|
|
188
|
+
def test_colour_env_var_true(self):
|
|
189
|
+
os.environ["COLOURED_LOGGER_COLOR"] = "true"
|
|
190
|
+
formatter = ColouredFormatter()
|
|
191
|
+
self.assertTrue(formatter.use_color)
|
|
192
|
+
|
|
193
|
+
def test_colour_env_var_false(self):
|
|
194
|
+
os.environ["COLOURED_LOGGER_COLOR"] = "false"
|
|
195
|
+
formatter = ColouredFormatter()
|
|
196
|
+
self.assertFalse(formatter.use_color)
|
|
197
|
+
|
|
198
|
+
def test_flask_color_overrides_coloured_logger_color(self):
|
|
199
|
+
os.environ["COLOURED_LOGGER_COLOR"] = "true"
|
|
200
|
+
os.environ["FLASK_LOG_COLOR"] = "false"
|
|
201
|
+
formatter = ColouredFormatter()
|
|
202
|
+
self.assertFalse(formatter.use_color)
|
|
203
|
+
|
|
204
|
+
def test_date_format_env_var(self):
|
|
205
|
+
os.environ["COLOURED_LOGGER_DATE_FORMAT"] = "%H:%M"
|
|
206
|
+
formatter = ColouredFormatter(use_color=False)
|
|
207
|
+
self.assertEqual(formatter.datefmt, "%H:%M")
|
|
208
|
+
|
|
209
|
+
def test_flask_date_format_overrides_coloured_date_format(self):
|
|
210
|
+
os.environ["COLOURED_LOGGER_DATE_FORMAT"] = "%H:%M"
|
|
211
|
+
os.environ["FLASK_LOG_DATE_FORMAT"] = "%Y"
|
|
212
|
+
formatter = ColouredFormatter(use_color=False)
|
|
213
|
+
self.assertEqual(formatter.datefmt, "%Y")
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
if __name__ == "__main__":
|
|
217
|
+
unittest.main()
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import io
|
|
2
|
-
import logging
|
|
3
|
-
import unittest
|
|
4
|
-
|
|
5
|
-
from coloured_logger import ColouredFormatter, setup_logging
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class FormatterTests(unittest.TestCase):
|
|
9
|
-
def test_formatter_without_color(self):
|
|
10
|
-
formatter = ColouredFormatter(use_color=False, datefmt="%Y")
|
|
11
|
-
record = logging.LogRecord("test", logging.INFO, __file__, 1, "hello", (), None)
|
|
12
|
-
output = formatter.format(record)
|
|
13
|
-
self.assertIn("[INFO] hello", output)
|
|
14
|
-
self.assertNotIn("\033[", output)
|
|
15
|
-
|
|
16
|
-
def test_logger_adds_success_level_output(self):
|
|
17
|
-
stream = io.StringIO()
|
|
18
|
-
logger = setup_logging(
|
|
19
|
-
logger_name="coloured_logger_test",
|
|
20
|
-
level=logging.DEBUG,
|
|
21
|
-
stream=stream,
|
|
22
|
-
use_color=False,
|
|
23
|
-
datefmt="%Y",
|
|
24
|
-
)
|
|
25
|
-
logger.success("done")
|
|
26
|
-
value = stream.getvalue()
|
|
27
|
-
self.assertIn("[SUCCESS] done", value)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if __name__ == "__main__":
|
|
31
|
-
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|