Skip to content

Commit 3ec294e

Browse files
committed
Replace colored-logs with Rich
1 parent ff350cd commit 3ec294e

4 files changed

Lines changed: 85 additions & 89 deletions

File tree

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Release 0.12.0 (unreleased)
1111
* Skip patches outside manifest dir (#942)
1212
* Make patch path in metadata platform independent (#937)
1313
* Fix extra newlines in patch for new files (#945)
14+
* Replace colored-logs with Rich
1415

1516
Release 0.11.0 (released 2026-01-03)
1617
====================================

dfetch/log.py

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,97 @@
11
"""Logging related items."""
22

33
import logging
4-
from typing import cast
4+
from typing import Any, Optional, cast
55

6-
import coloredlogs
7-
from colorama import Fore
6+
from rich.highlighter import NullHighlighter
7+
from rich.logging import RichHandler
88

99
from dfetch import __version__
1010

11+
# Configure root logger
12+
logging.basicConfig(
13+
level=logging.INFO,
14+
format="%(message)s",
15+
handlers=[
16+
RichHandler(
17+
show_time=False,
18+
show_path=False,
19+
show_level=False,
20+
markup=True,
21+
rich_tracebacks=True,
22+
highlighter=NullHighlighter(),
23+
)
24+
],
25+
)
26+
1127

1228
class DLogger(logging.Logger):
1329
"""Logging class extended with specific log items for dfetch."""
1430

1531
def print_info_line(self, name: str, info: str) -> None:
1632
"""Print a line of info."""
17-
self.info(f" {Fore.GREEN}{name:20s}:{Fore.BLUE} {info}")
33+
self.info(
34+
f" [bold][bright_green]{name:20s}:[/bright_green][blue] {info}[/blue][/bold]"
35+
)
1836

1937
def print_warning_line(self, name: str, info: str) -> None:
20-
"""Print a line of info."""
21-
self.info(f" {Fore.GREEN}{name:20s}:{Fore.YELLOW} {info}")
38+
"""Print a warning line: green name, yellow value."""
39+
self.warning(
40+
f" [bold][bright_green]{name:20s}:[/bright_green][bright_yellow] {info}[/bright_yellow][/bold]"
41+
)
2242

2343
def print_title(self) -> None:
2444
"""Print the DFetch tool title and version."""
25-
self.info(f"{Fore.BLUE}Dfetch ({__version__})")
45+
self.info(f"[bold blue]Dfetch ({__version__})[/bold blue]")
2646

2747
def print_info_field(self, field_name: str, field: str) -> None:
2848
"""Print a field with corresponding value."""
2949
self.print_info_line(field_name, field if field else "<none>")
3050

51+
def warning(self, msg: object, *args: Any, **kwargs: Any) -> None:
52+
"""Log warning."""
53+
super().warning(
54+
f"[bold bright_yellow]{msg}[/bold bright_yellow]", *args, **kwargs
55+
)
3156

32-
def setup_root(name: str) -> DLogger:
33-
"""Create the root logger."""
34-
logger = get_logger(name)
35-
36-
msg_format = "%(message)s"
37-
38-
level_style = {
39-
"critical": {"color": "magenta", "bright": True, "bold": True},
40-
"debug": {"color": "green", "bright": True, "bold": True},
41-
"error": {"color": "red", "bright": True, "bold": True},
42-
"info": {"color": 4, "bright": True, "bold": True},
43-
"notice": {"color": "magenta", "bright": True, "bold": True},
44-
"spam": {"color": "green", "faint": True},
45-
"success": {"color": "green", "bright": True, "bold": True},
46-
"verbose": {"color": "blue", "bright": True, "bold": True},
47-
"warning": {"color": "yellow", "bright": True, "bold": True},
48-
}
49-
50-
coloredlogs.install(fmt=msg_format, level_styles=level_style, level="INFO")
57+
def error(self, msg: object, *args: Any, **kwargs: Any) -> None:
58+
"""Log error."""
59+
super().error(f"[red]{msg}[/red]", *args, **kwargs)
5160

52-
return logger
5361

54-
55-
def increase_verbosity() -> None:
56-
"""Increase the verbosity of the logger."""
57-
coloredlogs.increase_verbosity()
62+
def setup_root(name: str) -> DLogger:
63+
"""Create the root logger."""
64+
logging.setLoggerClass(DLogger)
65+
logger = logging.getLogger(name)
66+
return cast(DLogger, logger)
67+
68+
69+
def increase_verbosity(logger: Optional[DLogger] = None) -> None:
70+
"""Increase the verbosity of a logger."""
71+
levels = [
72+
logging.CRITICAL,
73+
logging.ERROR,
74+
logging.WARNING,
75+
logging.INFO,
76+
logging.DEBUG,
77+
]
78+
logger_ = logger or logging.getLogger("dfetch")
79+
current_level = logger_.getEffectiveLevel() # <- check effective level
80+
try:
81+
idx = levels.index(current_level)
82+
# step to next more verbose level (lower number)
83+
new_level = levels[min(idx + 1, len(levels) - 1)]
84+
except ValueError:
85+
new_level = logging.DEBUG
86+
logger_.setLevel(new_level)
5887

5988

6089
def get_logger(name: str) -> DLogger:
6190
"""Get logger for a module."""
6291
logging.setLoggerClass(DLogger)
63-
return cast(DLogger, logging.getLogger(name))
92+
logger = logging.getLogger(name)
93+
logger.propagate = True
94+
return cast(DLogger, logger)
6495

6596

6697
def configure_external_logger(name: str, level: int = logging.INFO) -> None:

doc/legal.rst

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -77,34 +77,33 @@ We use `PyYAML`_ for parsing manifests (which are YAML). This uses the MIT licen
7777

7878
.. _`PyYAML`: https://pyyaml.org/
7979

80-
python-coloredlogs
81-
~~~~~~~~~~~~~~~~~~
82-
`Colored logs`_ is used for the colored text output.
80+
Rich
81+
~~~~
82+
`Rich`_ is used for the colored text output.
8383

8484
::
8585

86-
Copyright (c) 2020 Peter Odding
86+
Copyright (c) 2020 Will McGugan
8787

88-
Permission is hereby granted, free of charge, to any person obtaining
89-
a copy of this software and associated documentation files (the
90-
"Software"), to deal in the Software without restriction, including
91-
without limitation the rights to use, copy, modify, merge, publish,
92-
distribute, sublicense, and/or sell copies of the Software, and to
93-
permit persons to whom the Software is furnished to do so, subject to
94-
the following conditions:
88+
Permission is hereby granted, free of charge, to any person obtaining a copy
89+
of this software and associated documentation files (the "Software"), to deal
90+
in the Software without restriction, including without limitation the rights
91+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
92+
copies of the Software, and to permit persons to whom the Software is
93+
furnished to do so, subject to the following conditions:
9594

96-
The above copyright notice and this permission notice shall be
97-
included in all copies or substantial portions of the Software.
95+
The above copyright notice and this permission notice shall be included in all
96+
copies or substantial portions of the Software.
9897

99-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
100-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
101-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
102-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
103-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
104-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
105-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
98+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
99+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
100+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
101+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
102+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
103+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
104+
SOFTWARE.
106105

107-
.. _`Colored logs`: https://coloredlogs.readthedocs.io/en/latest/
106+
.. _`Rich`: https://rich.readthedocs.io/en/latest/
108107

109108
pykwalify
110109
~~~~~~~~~
@@ -137,41 +136,7 @@ pykwalify
137136

138137
.. _`pykwalify`: https://github.com/Grokzen/pykwalify
139138

140-
Colorama
141-
~~~~~~~~
142-
`colorama`_ is also used for the colored text output.
143-
144-
::
145-
146-
Copyright (c) 2010 Jonathan Hartley
147-
All rights reserved.
148-
149-
Redistribution and use in source and binary forms, with or without
150-
modification, are permitted provided that the following conditions are met:
151-
152-
* Redistributions of source code must retain the above copyright notice, this
153-
list of conditions and the following disclaimer.
154-
155-
* Redistributions in binary form must reproduce the above copyright notice,
156-
this list of conditions and the following disclaimer in the documentation
157-
and/or other materials provided with the distribution.
158-
159-
* Neither the name of the copyright holders, nor those of its contributors
160-
may be used to endorse or promote products derived from this software without
161-
specific prior written permission.
162-
163-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
164-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
165-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
166-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
167-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
168-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
169-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
170-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
171-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
172-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
173139

174-
.. _`colorama`: https://github.com/tartley/colorama
175140

176141

177142
Typing-extensions

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,9 @@ classifiers = [
4040
]
4141
dependencies = [
4242
"PyYAML==6.0.3",
43-
"coloredlogs==15.0.1",
4443
"strictyaml==1.7.3",
4544
"halo==0.0.31",
46-
"colorama==0.4.6",
45+
"rich==14.2.0",
4746
"typing-extensions==4.15.0",
4847
"tldextract==5.3.0",
4948
"sarif-om==1.0.4",

0 commit comments

Comments
 (0)