1from collections import namedtuple
2
3Message = namedtuple("Message", "type data time name color")
4
5
6class Printer:
7 """
8 Printer is where Poncho's user-visible output is defined. A Printer
9 instance receives typed messages and prints them to its output (usually
10 STDOUT) in the Poncho format.
11 """
12
13 def __init__(
14 self,
15 print_func,
16 time_format="%H:%M:%S",
17 width=0,
18 color=True,
19 prefix=True,
20 ):
21 self.print_func = print_func
22 self.time_format = time_format
23 self.width = width
24 self.color = color
25 self.prefix = prefix
26
27 def write(self, message):
28 if message.type != "line":
29 raise RuntimeError('Printer can only process messages of type "line"')
30
31 name = message.name if message.name is not None else ""
32 name = name.ljust(self.width)
33 if name:
34 name += " "
35
36 # When encountering data that cannot be interpreted as UTF-8 encoded
37 # Unicode, Printer will replace the unrecognisable bytes with the
38 # Unicode replacement character (U+FFFD).
39 if isinstance(message.data, bytes):
40 string = message.data.decode("utf-8", "replace")
41 else:
42 string = message.data
43
44 for line in string.splitlines():
45 prefix = ""
46 if self.prefix:
47 time_formatted = message.time.strftime(self.time_format)
48 prefix = f"{time_formatted} {name}| "
49 if self.color and message.color:
50 prefix = _color_string(message.color, prefix)
51
52 self.print_func(prefix + line)
53
54
55def _color_string(color, s):
56 def _ansi(code):
57 return f"\033[{code}m"
58
59 return f"{_ansi(0)}{_ansi(color)}{s}{_ansi(0)}"