Skip to content

Commit cabda54

Browse files
committed
Add padding to levelname in terminal logs
It makes it easier to follow logs when the message part is aligned and the level does not affect where the text starts. The colouring method has been refactored at the same time to reduce the duplication around adding styles.
1 parent 2ba131e commit cabda54

2 files changed

Lines changed: 30 additions & 30 deletions

File tree

‎src/blueapi/log.py‎

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -139,34 +139,25 @@ class IBMColorBlindSafeColors(enum.Enum):
139139
class ColorFormatter(logging.Formatter):
140140
"""Colors level_name of log using IBM color blind safe palette."""
141141

142-
def color_level_name(self, level_name: str, level_no: int) -> str:
142+
def _level_colour(self, level_no: int) -> tuple[int, int, int] | None:
143143
match level_no:
144144
case logging.DEBUG:
145-
return click.style(
146-
str(level_name), fg=IBMColorBlindSafeColors.ultramarine.value
147-
)
145+
return IBMColorBlindSafeColors.ultramarine.value
148146
case logging.INFO:
149-
return click.style(
150-
str(level_name), fg=IBMColorBlindSafeColors.indigo.value
151-
)
147+
return IBMColorBlindSafeColors.indigo.value
152148
case logging.WARNING:
153-
return click.style(
154-
str(level_name), fg=IBMColorBlindSafeColors.gold.value
155-
)
149+
return IBMColorBlindSafeColors.gold.value
156150
case logging.ERROR:
157-
return click.style(
158-
str(level_name), fg=IBMColorBlindSafeColors.magenta.value
159-
)
151+
return IBMColorBlindSafeColors.magenta.value
160152
case logging.CRITICAL:
161-
return click.style(
162-
str(level_name), fg=IBMColorBlindSafeColors.orange.value
163-
)
164-
return level_name
153+
return IBMColorBlindSafeColors.orange.value
154+
case _:
155+
return None
165156

166157
def formatMessage(self, record: logging.LogRecord) -> str: # noqa: N802
167158
# Copy record to avoid modifying for other handlers etc.
168159
recordcopy = copy(record)
169-
recordcopy.levelname = self.color_level_name(
170-
recordcopy.levelname, recordcopy.levelno
160+
recordcopy.levelname = click.style(
161+
f"{recordcopy.levelname:>8}", fg=self._level_colour(recordcopy.levelno)
171162
)
172163
return super().formatMessage(recordcopy)

‎tests/unit_tests/test_log.py‎

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -142,43 +142,52 @@ def foo_record():
142142

143143

144144
class TestColorFormatter:
145+
def _update_record(self, record: logging.LogRecord, level: int):
146+
record.levelno = level
147+
record.levelname = logging.getLevelName(level)
148+
145149
def test_debug(self, color_formatter, foo_record):
146-
foo_record.levelno = logging.DEBUG
150+
self._update_record(foo_record, logging.DEBUG)
147151

148152
assert (
149153
color_formatter.format(foo_record)
150-
== "\x1b[38;2;100;143;255mINFO\x1b[0m foo"
154+
== "\x1b[38;2;100;143;255m DEBUG\x1b[0m foo"
151155
)
152156

153157
def test_info(self, color_formatter, foo_record):
154-
foo_record.levelno = logging.INFO
158+
self._update_record(foo_record, logging.INFO)
155159

156160
assert (
157-
color_formatter.format(foo_record) == "\x1b[38;2;120;94;240mINFO\x1b[0m foo"
161+
color_formatter.format(foo_record)
162+
== "\x1b[38;2;120;94;240m INFO\x1b[0m foo"
158163
)
159164

160165
def test_warning(self, color_formatter, foo_record):
161-
foo_record.levelno = logging.WARNING
166+
self._update_record(foo_record, logging.WARNING)
162167

163168
assert (
164-
color_formatter.format(foo_record) == "\x1b[38;2;255;176;0mINFO\x1b[0m foo"
169+
color_formatter.format(foo_record)
170+
== "\x1b[38;2;255;176;0m WARNING\x1b[0m foo"
165171
)
166172

167173
def test_error(self, color_formatter, foo_record):
168-
foo_record.levelno = logging.ERROR
174+
self._update_record(foo_record, logging.ERROR)
169175

170176
assert (
171-
color_formatter.format(foo_record) == "\x1b[38;2;220;38;127mINFO\x1b[0m foo"
177+
color_formatter.format(foo_record)
178+
== "\x1b[38;2;220;38;127m ERROR\x1b[0m foo"
172179
)
173180

174181
def test_critical(self, color_formatter, foo_record):
175-
foo_record.levelno = logging.CRITICAL
182+
self._update_record(foo_record, logging.CRITICAL)
176183

177184
assert (
178-
color_formatter.format(foo_record) == "\x1b[38;2;254;97;0mINFO\x1b[0m foo"
185+
color_formatter.format(foo_record)
186+
== "\x1b[38;2;254;97;0mCRITICAL\x1b[0m foo"
179187
)
180188

181189
def test_other(self, color_formatter, foo_record):
182190
foo_record.levelno = -1
191+
foo_record.levelname = "UNKNOWN"
183192

184-
assert color_formatter.format(foo_record) == "INFO foo"
193+
assert color_formatter.format(foo_record) == " UNKNOWN\x1b[0m foo"

0 commit comments

Comments
 (0)