0
# Pretty Printer Registration
1
2
System for registering custom pretty printers for user-defined types and creating formatted function call representations. This enables extending prettyprinter to handle custom classes and data structures with specialized formatting logic.
3
4
## Capabilities
5
6
### Type Registration
7
8
Register custom pretty printers for specific types or predicate-based matching, enabling specialized formatting for user-defined classes and data structures.
9
10
```python { .api }
11
def register_pretty(type=None, predicate=None):
12
"""
13
Decorator that registers a function as the pretty printer for a type.
14
15
Parameters:
16
- type: Type to register for, or string 'module.ClassName' for deferred registration
17
- predicate: Function taking one argument returning bool for predicate-based matching
18
19
Notes:
20
- Exactly one of 'type' or 'predicate' must be provided
21
- Decorated function must accept (value, ctx) parameters
22
- Returns the original function unchanged
23
24
Usage:
25
@register_pretty(MyClass)
26
def pretty_my_class(value, ctx):
27
return pretty_call(ctx, MyClass, value.attr1, value.attr2)
28
"""
29
```
30
31
### Registration Status
32
33
Check whether a type has a registered pretty printer, useful for conditional formatting logic and debugging registration issues.
34
35
```python { .api }
36
def is_registered(type, *, check_superclasses=False, check_deferred=True,
37
register_deferred=True) -> bool:
38
"""
39
Check if a type has a registered pretty printer.
40
41
Parameters:
42
- type: Type to check for registration
43
- check_superclasses (bool): Check superclass types (default: False)
44
- check_deferred (bool): Check deferred registrations (default: True)
45
- register_deferred (bool): Register deferred printers when found (default: True)
46
47
Returns:
48
- bool: True if type has registered pretty printer
49
50
Raises:
51
- ValueError: If register_deferred=True when check_deferred=False
52
"""
53
```
54
55
### Function Call Formatting (Python 3.6+)
56
57
Create formatted function call representations with automatic argument handling and keyword argument preservation.
58
59
```python { .api }
60
def pretty_call(ctx, fn, *args, **kwargs):
61
"""
62
Create a Doc representing a function call with arguments.
63
64
Parameters:
65
- ctx (PrettyContext): Current pretty printing context
66
- fn: Callable to represent in the call
67
- args: Positional arguments for the call
68
- kwargs: Keyword arguments for the call
69
70
Returns:
71
- Doc: Document representing the formatted function call
72
73
Notes:
74
- Requires Python 3.6+ for keyword argument order preservation
75
- Automatically handles syntax highlighting and layout
76
- For Python 3.5 compatibility, use pretty_call_alt instead
77
"""
78
```
79
80
### Function Call Formatting (All Python Versions)
81
82
Create formatted function call representations with explicit argument specification, compatible with all Python versions.
83
84
```python { .api }
85
def pretty_call_alt(ctx, fn, args=(), kwargs=()):
86
"""
87
Create a Doc representing a function call with explicit arguments.
88
89
Parameters:
90
- ctx (PrettyContext): Current pretty printing context
91
- fn: Callable to represent in the call
92
- args (tuple): Tuple of positional arguments
93
- kwargs: OrderedDict, dict, or iterable of (key, value) pairs for keyword arguments
94
95
Returns:
96
- Doc: Document representing the formatted function call
97
98
Notes:
99
- Works on all Python versions including 3.5
100
- For consistent results on Python 3.5, use OrderedDict or list of tuples for kwargs
101
"""
102
```
103
104
## Usage Examples
105
106
### Basic Type Registration
107
108
```python
109
from prettyprinter import register_pretty, pretty_call
110
from collections import namedtuple
111
112
# Custom class example
113
class Person:
114
def __init__(self, name, age, email):
115
self.name = name
116
self.age = age
117
self.email = email
118
119
@register_pretty(Person)
120
def pretty_person(person, ctx):
121
return pretty_call(ctx, Person, person.name, person.age, person.email)
122
123
# Now Person instances are pretty printed as constructor calls
124
person = Person("Alice", 30, "alice@example.com")
125
pprint(person)
126
# Output: Person('Alice', 30, 'alice@example.com')
127
```
128
129
### Advanced Registration with Custom Logic
130
131
```python
132
from prettyprinter import register_pretty, pretty_call, comment
133
import datetime
134
135
class Task:
136
def __init__(self, title, priority=1, due_date=None, completed=False):
137
self.title = title
138
self.priority = priority
139
self.due_date = due_date
140
self.completed = completed
141
142
@register_pretty(Task)
143
def pretty_task(task, ctx):
144
# Show different representation based on completion status
145
if task.completed:
146
return comment(
147
pretty_call(ctx, Task, task.title,
148
priority=task.priority,
149
due_date=task.due_date,
150
completed=task.completed),
151
'COMPLETED'
152
)
153
else:
154
return pretty_call(ctx, Task, task.title,
155
priority=task.priority,
156
due_date=task.due_date)
157
158
# Usage
159
task1 = Task("Write documentation", priority=2,
160
due_date=datetime.date(2024, 1, 15))
161
task2 = Task("Review code", completed=True)
162
163
pprint([task1, task2])
164
```
165
166
### Predicate-Based Registration
167
168
```python
169
from prettyprinter import register_pretty
170
from collections.abc import Mapping
171
172
# Register pretty printer for all custom mapping types
173
@register_pretty(predicate=lambda obj: isinstance(obj, Mapping) and
174
type(obj).__name__.endswith('Dict'))
175
def pretty_custom_dicts(mapping, ctx):
176
return pretty_call(ctx, type(mapping), dict(mapping))
177
178
# This will handle CustomDict, OrderedDict, etc.
179
class CustomDict(dict):
180
pass
181
182
custom = CustomDict([('a', 1), ('b', 2)])
183
pprint(custom) # CustomDict({'a': 1, 'b': 2})
184
```
185
186
### Deferred Registration
187
188
```python
189
from prettyprinter import register_pretty
190
191
# Register for a type that might not be imported yet
192
@register_pretty('numpy.ndarray')
193
def pretty_numpy_array(arr, ctx):
194
# This registration is deferred until numpy.ndarray is actually encountered
195
return pretty_call(ctx, type(arr), arr.tolist())
196
197
# The registration becomes active when numpy arrays are first encountered
198
import numpy as np
199
arr = np.array([1, 2, 3, 4, 5])
200
pprint(arr) # Triggers registration and uses custom formatter
201
```
202
203
### Complex Object Hierarchies
204
205
```python
206
from prettyprinter import register_pretty, pretty_call
207
208
class Database:
209
def __init__(self, name, tables=None):
210
self.name = name
211
self.tables = tables or []
212
213
class Table:
214
def __init__(self, name, columns=None, rows=0):
215
self.name = name
216
self.columns = columns or []
217
self.rows = rows
218
219
@register_pretty(Database)
220
def pretty_database(db, ctx):
221
return pretty_call(ctx, Database, db.name, tables=db.tables)
222
223
@register_pretty(Table)
224
def pretty_table(table, ctx):
225
return pretty_call(ctx, Table, table.name,
226
columns=table.columns, rows=table.rows)
227
228
# Nested objects are automatically handled
229
db = Database("myapp", [
230
Table("users", ["id", "name", "email"], 1000),
231
Table("posts", ["id", "title", "content"], 5000)
232
])
233
234
pprint(db)
235
# Output shows nested structure with custom formatting for both types
236
```
237
238
### Checking Registration Status
239
240
```python
241
from prettyprinter import is_registered, register_pretty
242
243
class MyClass:
244
pass
245
246
# Check if registered
247
print(is_registered(MyClass)) # False
248
249
@register_pretty(MyClass)
250
def pretty_my_class(obj, ctx):
251
return "MyClass()"
252
253
# Now it's registered
254
print(is_registered(MyClass)) # True
255
256
# Check superclasses too
257
class MySubClass(MyClass):
258
pass
259
260
print(is_registered(MySubClass)) # False
261
print(is_registered(MySubClass, check_superclasses=True)) # True
262
```
263
264
### Using pretty_call_alt for Python 3.5 Compatibility
265
266
```python
267
from prettyprinter import register_pretty, pretty_call_alt
268
from collections import OrderedDict
269
270
@register_pretty(Person)
271
def pretty_person_alt(person, ctx):
272
# Use explicit args and kwargs for Python 3.5 compatibility
273
return pretty_call_alt(
274
ctx,
275
Person,
276
args=(person.name,),
277
kwargs=OrderedDict([
278
('age', person.age),
279
('email', person.email)
280
])
281
)
282
```