forked from pycontribs/enrich
/
handler.py
152 lines (137 loc) · 5.88 KB
/
handler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""
Implements enriched RichHandler
Based on:
https://github.com/willmcgugan/rich/blob/master/rich/_log_render.py
"""
from datetime import datetime
from typing import Any, Iterable, Optional
from rich.style import Style
# from rich.style import Style
from rich.logging import RichHandler as OriginalRichHandler
from rich.text import Text, TextType, Span
from enrich.config import STYLES, NO_COLOR
from enrich.console import get_console, Console
from rich.console import ConsoleRenderable
# from datetime import datetime
# from typing import Any, Iterable, Optional
# from rich.logging import RichHandler as OriginalRichHandler
# from rich.text import Text, TextType, Span
COLOR = (not NO_COLOR)
class RichHandler(OriginalRichHandler):
"""Enriched handler that does not wrap."""
def __init__(self, *args: Any, **kwargs: Any) -> None:
if 'console' not in kwargs:
kwargs['console'] = get_console(
redirect=False,
width=9999,
markup=True
)
super().__init__(*args, **kwargs)
# RichHandler constructor does not allow custom renderer
# https://github.com/willmcgugan/rich/issues/438
self._log_render = FluidLogRender(
show_time=kwargs.get("show_time", True),
show_level=kwargs.get("show_level", True),
show_path=kwargs.get("show_path", True),
) # type: ignore
# class RichHandler(OriginalRichHandler):
# """Enriched handler that does not wrap."""
# def __init__(self, *args: Any, **kwargs: Any) -> None:
# super().__init__(*args, **kwargs)
# # RichHandler constructor does not allow custom renderer
# # https://github.com/willmcgugan/rich/issues/438
# self._log_render = FluidLogRender(
# show_time=kwargs.get("show_time", False),
# show_level=kwargs.get("show_level", True),
# show_path=kwargs.get("show_path", False),
# ) # type: ignore
class FluidLogRender: # pylint: disable=too-few-public-methods
"""Renders log by not using columns and avoiding any wrapping."""
def __init__(
self,
show_time: bool = True,
show_level: bool = True,
show_path: bool = True,
time_format: str = "%Y-%m-%d %H:%M:%S",
link_path: Optional[bool] = False,
) -> None:
self.show_time = show_time
self.show_level = show_level
self.show_path = show_path
self.time_format = time_format
self.link_path = link_path
self._last_time: Optional[str] = None
def __call__( # pylint: disable=too-many-arguments
self,
console: Console, # type: ignore
renderables: Iterable[ConsoleRenderable],
log_time: Optional[datetime] = None,
time_format: str = '%Y-%m-%d %H:%M:%S',
level: TextType = "",
path: Optional[str] = None,
line_no: Optional[int] = None,
link_path: Optional[str] = None,
) -> Text:
result = Text()
if self.show_time:
log_time = datetime.now() if log_time is None else log_time
log_time_display = log_time.strftime(
time_format or self.time_format
)
d, t = log_time_display.split(' ')
result += Text("[", style=STYLES.get('log.brace', ''))
result += Text(f'{d} ', style=STYLES.get('logging.date', ''))
result += Text(t, style=STYLES.get('logging.time', ''))
result += Text("]", style=STYLES.get('log.brace', ''))
# result += Text(log_time_display, style=STYLES['logging.time'])
self._last_time = log_time_display
if self.show_level:
if isinstance(level, Text):
lstr = level.plain.rstrip(' ')
if COLOR:
style = level.spans[0].style
else:
style = Style.null()
level.spans = [Span(0, len(lstr), style)]
ltext = Text('[', style=STYLES.get('log.brace', ''))
ltext.append(Text(f'{lstr}', style=style))
ltext.append(Text(']', style=STYLES.get('log.brace', '')))
# ltext = Text(f'[{lstr}]', style=style)
elif isinstance(level, str):
lstr = level.rstrip(' ')
style = f"logging.level.{str(lstr)}" if COLOR else Style.null()
ltext = Text('[', style=STYLES.get('log.brace', ''))
ltext = Text(f"{lstr}", style=style) # f"logging.level.{str(lstr)}")
ltext.append(Text(']', style=STYLES.get('log.brace', '')))
else:
raise TypeError('Unexpected type for level')
result += ltext
if self.show_path and path:
path_text = Text("[", style=STYLES.get('log.brace', ''))
# path_text.append( /)
path_text.append(
path.rstrip('.py'),
style=STYLES.get('log.path', ''),
# style=STYLES.get('log.path', Style(color='black')),
# style=(
# f"link file://{link_path}" + " underline"
# if link_path else ""
# # + STYLES["repr.url"]
# )
)
if line_no:
path_text.append(Text(":", style=STYLES.get('log.colon', '')))
path_text.append(
f"{line_no}",
style=STYLES.get('log.linenumber', ''),
# style=(
# f"link file://{link_path}#{line_no}"
# if link_path else ""
# ),
)
path_text.append("]", style=STYLES.get('log.brace', ''))
result += path_text
result += Text(' - ', style=STYLES.get('repr.dash', ''))
for elem in renderables:
result += elem
return result