0
# Output Formatting
1
2
Handles formatted, colorized output with timestamps, process identification, and cross-platform terminal compatibility. The output formatting system provides consistent, readable output for multi-process applications with proper color support and formatting.
3
4
## Capabilities
5
6
### Printer Class
7
8
The Printer class handles formatted output with colors, timestamps, and process identification. It provides a consistent interface for displaying process output in a readable format.
9
10
```python { .api }
11
class Printer:
12
"""
13
Printer defines Honcho's user-visible output. A Printer instance receives
14
typed messages and prints them to its output in the Honcho format with
15
timestamps, process names, and optional coloring.
16
"""
17
18
def __init__(self, output=sys.stdout, time_format="%H:%M:%S", width=0, colour=True, prefix=True):
19
"""
20
Initialize printer with formatting options.
21
22
Parameters:
23
- output: file-like object for output (default: sys.stdout)
24
- time_format: str, strftime format for timestamps (default: "%H:%M:%S")
25
- width: int, minimum width for process names (default: 0, auto-calculated)
26
- colour: bool, whether to use ANSI color codes (default: True)
27
- prefix: bool, whether to show timestamp and process name prefix (default: True)
28
"""
29
30
def write(self, message):
31
"""
32
Write a formatted message to the output.
33
34
Parameters:
35
- message: Message namedtuple with type, data, time, name, and colour
36
37
Raises:
38
RuntimeError: if message type is not 'line'
39
"""
40
41
# Properties
42
output: 'TextIO'
43
time_format: str
44
width: int
45
colour: bool
46
prefix: bool
47
```
48
49
### Message Structure
50
51
Structured message format for process output with metadata for formatting.
52
53
```python { .api }
54
from collections import namedtuple
55
import datetime
56
57
Message = namedtuple("Message", "type data time name colour")
58
```
59
60
### Color Support
61
62
Functions for generating ANSI color codes and applying colors to strings with cross-platform compatibility.
63
64
```python { .api }
65
def get_colours():
66
"""
67
Generator that yields ANSI color codes cyclically for process identification.
68
69
Returns:
70
Generator yielding color code strings in rotation
71
"""
72
73
# ANSI color constants
74
ANSI_COLOURS = ['grey', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white']
75
76
# Color code variables (dynamically generated)
77
grey: str = '30'
78
red: str = '31'
79
green: str = '32'
80
yellow: str = '33'
81
blue: str = '34'
82
magenta: str = '35'
83
cyan: str = '36'
84
white: str = '37'
85
86
# Intense color variants
87
intense_grey: str = '30;1'
88
intense_red: str = '31;1'
89
intense_green: str = '32;1'
90
intense_yellow: str = '33;1'
91
intense_blue: str = '34;1'
92
intense_magenta: str = '35;1'
93
intense_cyan: str = '36;1'
94
intense_white: str = '37;1'
95
```
96
97
### Internal Color Functions
98
99
Utility functions for ANSI color code generation and string formatting.
100
101
```python { .api }
102
def _ansi(code):
103
"""
104
Generate ANSI escape sequence for given code.
105
106
Parameters:
107
- code: int or str, ANSI color code
108
109
Returns:
110
str: ANSI escape sequence
111
"""
112
113
def _colour_string(colour, s):
114
"""
115
Apply color to string using ANSI escape codes.
116
117
Parameters:
118
- colour: str, ANSI color code
119
- s: str, string to colorize
120
121
Returns:
122
str: colorized string with reset codes
123
"""
124
```
125
126
## Usage Examples
127
128
### Basic Printer Usage
129
130
```python
131
import sys
132
from datetime import datetime
133
from honcho.printer import Printer, Message
134
135
# Create printer with custom formatting
136
printer = Printer(
137
output=sys.stdout,
138
time_format="%H:%M:%S",
139
width=10,
140
colour=True,
141
prefix=True
142
)
143
144
# Create and write messages
145
message = Message(
146
type='line',
147
data='Application starting up...\n',
148
time=datetime.now(),
149
name='web',
150
colour='32' # Green
151
)
152
153
printer.write(message)
154
# Output: 14:23:45 web | Application starting up...
155
```
156
157
### Multi-Process Output
158
159
```python
160
import sys
161
from datetime import datetime
162
from honcho.printer import Printer, Message
163
from honcho.colour import get_colours
164
165
# Create printer for multi-process output
166
printer = Printer(sys.stdout, width=12)
167
colours = get_colours()
168
169
# Simulate output from multiple processes
170
processes = ['web', 'worker', 'scheduler', 'redis']
171
172
for i, process_name in enumerate(processes):
173
colour = next(colours)
174
175
message = Message(
176
type='line',
177
data=f'{process_name} process started successfully\n',
178
time=datetime.now(),
179
name=process_name,
180
colour=colour
181
)
182
183
printer.write(message)
184
185
# Output:
186
# 14:23:45 web | web process started successfully
187
# 14:23:45 worker | worker process started successfully
188
# 14:23:45 scheduler | scheduler process started successfully
189
# 14:23:45 redis | redis process started successfully
190
```
191
192
### Custom Output Formatting
193
194
```python
195
import sys
196
from datetime import datetime
197
from honcho.printer import Printer, Message
198
199
# Create printer with custom time format and no colors
200
printer = Printer(
201
output=sys.stdout,
202
time_format="%Y-%m-%d %H:%M:%S",
203
colour=False,
204
prefix=True
205
)
206
207
# Write system message
208
message = Message(
209
type='line',
210
data='System shutting down gracefully\n',
211
time=datetime.now(),
212
name='system',
213
colour=None
214
)
215
216
printer.write(message)
217
# Output: 2025-01-15 14:23:45 system | System shutting down gracefully
218
```
219
220
### No-Prefix Output
221
222
```python
223
import sys
224
from datetime import datetime
225
from honcho.printer import Printer, Message
226
227
# Create printer without prefixes (raw output)
228
printer = Printer(
229
output=sys.stdout,
230
prefix=False
231
)
232
233
# Write raw process output
234
message = Message(
235
type='line',
236
data='This is raw process output\nwith multiple lines\n',
237
time=datetime.now(),
238
name='app',
239
colour=None
240
)
241
242
printer.write(message)
243
# Output:
244
# This is raw process output
245
# with multiple lines
246
```
247
248
### File Output
249
250
```python
251
from datetime import datetime
252
from honcho.printer import Printer, Message
253
254
# Write to file instead of stdout
255
with open('process.log', 'w') as f:
256
printer = Printer(
257
output=f,
258
colour=False, # No colors in file output
259
time_format="%Y-%m-%d %H:%M:%S"
260
)
261
262
message = Message(
263
type='line',
264
data='Process completed successfully\n',
265
time=datetime.now(),
266
name='worker',
267
colour=None
268
)
269
270
printer.write(message)
271
```
272
273
### Error Handling
274
275
```python
276
import sys
277
from datetime import datetime
278
from honcho.printer import Printer, Message
279
280
printer = Printer(sys.stdout)
281
282
# Only 'line' type messages are supported
283
try:
284
invalid_message = Message(
285
type='invalid', # This will cause an error
286
data='Some data',
287
time=datetime.now(),
288
name='test',
289
colour=None
290
)
291
printer.write(invalid_message)
292
except RuntimeError as e:
293
print(f"Error: {e}")
294
# Error: Printer can only process messages of type "line"
295
```
296
297
## Platform Compatibility
298
299
The output formatting system includes special handling for Windows platforms:
300
301
```python { .api }
302
# Windows color support detection
303
ON_WINDOWS = 'win32' in str(sys.platform).lower()
304
305
# Automatic colorama initialization on Windows for ANSI support
306
try:
307
import colorama
308
colorama.init() # Enable ANSI colors on Windows
309
except ImportError:
310
# Fall back to no colors if colorama not available
311
pass
312
```
313
314
The printer automatically detects terminal capabilities and disables colors when output is redirected to files or non-TTY outputs.