##// END OF EJS Templates
Miscellaneous Py 3 fixes
Thomas Kluyver -
Show More
@@ -1,790 +1,791 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Python advanced pretty printer. This pretty printer is intended to
3 Python advanced pretty printer. This pretty printer is intended to
4 replace the old `pprint` python module which does not allow developers
4 replace the old `pprint` python module which does not allow developers
5 to provide their own pretty print callbacks.
5 to provide their own pretty print callbacks.
6
6
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8
8
9
9
10 Example Usage
10 Example Usage
11 -------------
11 -------------
12
12
13 To directly print the representation of an object use `pprint`::
13 To directly print the representation of an object use `pprint`::
14
14
15 from pretty import pprint
15 from pretty import pprint
16 pprint(complex_object)
16 pprint(complex_object)
17
17
18 To get a string of the output use `pretty`::
18 To get a string of the output use `pretty`::
19
19
20 from pretty import pretty
20 from pretty import pretty
21 string = pretty(complex_object)
21 string = pretty(complex_object)
22
22
23
23
24 Extending
24 Extending
25 ---------
25 ---------
26
26
27 The pretty library allows developers to add pretty printing rules for their
27 The pretty library allows developers to add pretty printing rules for their
28 own objects. This process is straightforward. All you have to do is to
28 own objects. This process is straightforward. All you have to do is to
29 add a `_repr_pretty_` method to your object and call the methods on the
29 add a `_repr_pretty_` method to your object and call the methods on the
30 pretty printer passed::
30 pretty printer passed::
31
31
32 class MyObject(object):
32 class MyObject(object):
33
33
34 def _repr_pretty_(self, p, cycle):
34 def _repr_pretty_(self, p, cycle):
35 ...
35 ...
36
36
37 Depending on the python version you want to support you have two
37 Depending on the python version you want to support you have two
38 possibilities. The following list shows the python 2.5 version and the
38 possibilities. The following list shows the python 2.5 version and the
39 compatibility one.
39 compatibility one.
40
40
41
41
42 Here the example implementation of a `_repr_pretty_` method for a list
42 Here the example implementation of a `_repr_pretty_` method for a list
43 subclass for python 2.5 and higher (python 2.5 requires the with statement
43 subclass for python 2.5 and higher (python 2.5 requires the with statement
44 __future__ import)::
44 __future__ import)::
45
45
46 class MyList(list):
46 class MyList(list):
47
47
48 def _repr_pretty_(self, p, cycle):
48 def _repr_pretty_(self, p, cycle):
49 if cycle:
49 if cycle:
50 p.text('MyList(...)')
50 p.text('MyList(...)')
51 else:
51 else:
52 with p.group(8, 'MyList([', '])'):
52 with p.group(8, 'MyList([', '])'):
53 for idx, item in enumerate(self):
53 for idx, item in enumerate(self):
54 if idx:
54 if idx:
55 p.text(',')
55 p.text(',')
56 p.breakable()
56 p.breakable()
57 p.pretty(item)
57 p.pretty(item)
58
58
59 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
59 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
60 react to that or the result is an infinite loop. `p.text()` just adds
60 react to that or the result is an infinite loop. `p.text()` just adds
61 non breaking text to the output, `p.breakable()` either adds a whitespace
61 non breaking text to the output, `p.breakable()` either adds a whitespace
62 or breaks here. If you pass it an argument it's used instead of the
62 or breaks here. If you pass it an argument it's used instead of the
63 default space. `p.pretty` prettyprints another object using the pretty print
63 default space. `p.pretty` prettyprints another object using the pretty print
64 method.
64 method.
65
65
66 The first parameter to the `group` function specifies the extra indentation
66 The first parameter to the `group` function specifies the extra indentation
67 of the next line. In this example the next item will either be not
67 of the next line. In this example the next item will either be not
68 breaked (if the items are short enough) or aligned with the right edge of
68 breaked (if the items are short enough) or aligned with the right edge of
69 the opening bracked of `MyList`.
69 the opening bracked of `MyList`.
70
70
71 If you want to support python 2.4 and lower you can use this code::
71 If you want to support python 2.4 and lower you can use this code::
72
72
73 class MyList(list):
73 class MyList(list):
74
74
75 def _repr_pretty_(self, p, cycle):
75 def _repr_pretty_(self, p, cycle):
76 if cycle:
76 if cycle:
77 p.text('MyList(...)')
77 p.text('MyList(...)')
78 else:
78 else:
79 p.begin_group(8, 'MyList([')
79 p.begin_group(8, 'MyList([')
80 for idx, item in enumerate(self):
80 for idx, item in enumerate(self):
81 if idx:
81 if idx:
82 p.text(',')
82 p.text(',')
83 p.breakable()
83 p.breakable()
84 p.pretty(item)
84 p.pretty(item)
85 p.end_group(8, '])')
85 p.end_group(8, '])')
86
86
87 If you just want to indent something you can use the group function
87 If you just want to indent something you can use the group function
88 without open / close parameters. Under python 2.5 you can also use this
88 without open / close parameters. Under python 2.5 you can also use this
89 code::
89 code::
90
90
91 with p.indent(2):
91 with p.indent(2):
92 ...
92 ...
93
93
94 Or under python2.4 you might want to modify ``p.indentation`` by hand but
94 Or under python2.4 you might want to modify ``p.indentation`` by hand but
95 this is rather ugly.
95 this is rather ugly.
96
96
97 Inheritance diagram:
97 Inheritance diagram:
98
98
99 .. inheritance-diagram:: IPython.lib.pretty
99 .. inheritance-diagram:: IPython.lib.pretty
100 :parts: 3
100 :parts: 3
101
101
102 :copyright: 2007 by Armin Ronacher.
102 :copyright: 2007 by Armin Ronacher.
103 Portions (c) 2009 by Robert Kern.
103 Portions (c) 2009 by Robert Kern.
104 :license: BSD License.
104 :license: BSD License.
105 """
105 """
106 from __future__ import print_function
106 from __future__ import print_function
107 from contextlib import contextmanager
107 from contextlib import contextmanager
108 import sys
108 import sys
109 import types
109 import types
110 import re
110 import re
111 import datetime
111 import datetime
112 from io import StringIO
112 from io import StringIO
113 from collections import deque
113 from collections import deque
114
114
115
115
116 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
116 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
117 'for_type', 'for_type_by_name']
117 'for_type', 'for_type_by_name']
118
118
119
119
120 _re_pattern_type = type(re.compile(''))
120 _re_pattern_type = type(re.compile(''))
121
121
122
122
123 def pretty(obj, verbose=False, max_width=79, newline='\n'):
123 def pretty(obj, verbose=False, max_width=79, newline='\n'):
124 """
124 """
125 Pretty print the object's representation.
125 Pretty print the object's representation.
126 """
126 """
127 stream = StringIO()
127 stream = StringIO()
128 printer = RepresentationPrinter(stream, verbose, max_width, newline)
128 printer = RepresentationPrinter(stream, verbose, max_width, newline)
129 printer.pretty(obj)
129 printer.pretty(obj)
130 printer.flush()
130 printer.flush()
131 return stream.getvalue()
131 return stream.getvalue()
132
132
133
133
134 def pprint(obj, verbose=False, max_width=79, newline='\n'):
134 def pprint(obj, verbose=False, max_width=79, newline='\n'):
135 """
135 """
136 Like `pretty` but print to stdout.
136 Like `pretty` but print to stdout.
137 """
137 """
138 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
138 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
139 printer.pretty(obj)
139 printer.pretty(obj)
140 printer.flush()
140 printer.flush()
141 sys.stdout.write(newline)
141 sys.stdout.write(newline)
142 sys.stdout.flush()
142 sys.stdout.flush()
143
143
144 class _PrettyPrinterBase(object):
144 class _PrettyPrinterBase(object):
145
145
146 @contextmanager
146 @contextmanager
147 def indent(self, indent):
147 def indent(self, indent):
148 """with statement support for indenting/dedenting."""
148 """with statement support for indenting/dedenting."""
149 self.indentation += indent
149 self.indentation += indent
150 try:
150 try:
151 yield
151 yield
152 finally:
152 finally:
153 self.indentation -= indent
153 self.indentation -= indent
154
154
155 @contextmanager
155 @contextmanager
156 def group(self, indent=0, open='', close=''):
156 def group(self, indent=0, open='', close=''):
157 """like begin_group / end_group but for the with statement."""
157 """like begin_group / end_group but for the with statement."""
158 self.begin_group(indent, open)
158 self.begin_group(indent, open)
159 try:
159 try:
160 yield
160 yield
161 finally:
161 finally:
162 self.end_group(indent, close)
162 self.end_group(indent, close)
163
163
164 class PrettyPrinter(_PrettyPrinterBase):
164 class PrettyPrinter(_PrettyPrinterBase):
165 """
165 """
166 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
166 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
167 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
167 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
168 this printer knows nothing about the default pprinters or the `_repr_pretty_`
168 this printer knows nothing about the default pprinters or the `_repr_pretty_`
169 callback method.
169 callback method.
170 """
170 """
171
171
172 def __init__(self, output, max_width=79, newline='\n'):
172 def __init__(self, output, max_width=79, newline='\n'):
173 self.output = output
173 self.output = output
174 self.max_width = max_width
174 self.max_width = max_width
175 self.newline = newline
175 self.newline = newline
176 self.output_width = 0
176 self.output_width = 0
177 self.buffer_width = 0
177 self.buffer_width = 0
178 self.buffer = deque()
178 self.buffer = deque()
179
179
180 root_group = Group(0)
180 root_group = Group(0)
181 self.group_stack = [root_group]
181 self.group_stack = [root_group]
182 self.group_queue = GroupQueue(root_group)
182 self.group_queue = GroupQueue(root_group)
183 self.indentation = 0
183 self.indentation = 0
184
184
185 def _break_outer_groups(self):
185 def _break_outer_groups(self):
186 while self.max_width < self.output_width + self.buffer_width:
186 while self.max_width < self.output_width + self.buffer_width:
187 group = self.group_queue.deq()
187 group = self.group_queue.deq()
188 if not group:
188 if not group:
189 return
189 return
190 while group.breakables:
190 while group.breakables:
191 x = self.buffer.popleft()
191 x = self.buffer.popleft()
192 self.output_width = x.output(self.output, self.output_width)
192 self.output_width = x.output(self.output, self.output_width)
193 self.buffer_width -= x.width
193 self.buffer_width -= x.width
194 while self.buffer and isinstance(self.buffer[0], Text):
194 while self.buffer and isinstance(self.buffer[0], Text):
195 x = self.buffer.popleft()
195 x = self.buffer.popleft()
196 self.output_width = x.output(self.output, self.output_width)
196 self.output_width = x.output(self.output, self.output_width)
197 self.buffer_width -= x.width
197 self.buffer_width -= x.width
198
198
199 def text(self, obj):
199 def text(self, obj):
200 """Add literal text to the output."""
200 """Add literal text to the output."""
201 width = len(obj)
201 width = len(obj)
202 if self.buffer:
202 if self.buffer:
203 text = self.buffer[-1]
203 text = self.buffer[-1]
204 if not isinstance(text, Text):
204 if not isinstance(text, Text):
205 text = Text()
205 text = Text()
206 self.buffer.append(text)
206 self.buffer.append(text)
207 text.add(obj, width)
207 text.add(obj, width)
208 self.buffer_width += width
208 self.buffer_width += width
209 self._break_outer_groups()
209 self._break_outer_groups()
210 else:
210 else:
211 self.output.write(obj)
211 self.output.write(obj)
212 self.output_width += width
212 self.output_width += width
213
213
214 def breakable(self, sep=' '):
214 def breakable(self, sep=' '):
215 """
215 """
216 Add a breakable separator to the output. This does not mean that it
216 Add a breakable separator to the output. This does not mean that it
217 will automatically break here. If no breaking on this position takes
217 will automatically break here. If no breaking on this position takes
218 place the `sep` is inserted which default to one space.
218 place the `sep` is inserted which default to one space.
219 """
219 """
220 width = len(sep)
220 width = len(sep)
221 group = self.group_stack[-1]
221 group = self.group_stack[-1]
222 if group.want_break:
222 if group.want_break:
223 self.flush()
223 self.flush()
224 self.output.write(self.newline)
224 self.output.write(self.newline)
225 self.output.write(' ' * self.indentation)
225 self.output.write(' ' * self.indentation)
226 self.output_width = self.indentation
226 self.output_width = self.indentation
227 self.buffer_width = 0
227 self.buffer_width = 0
228 else:
228 else:
229 self.buffer.append(Breakable(sep, width, self))
229 self.buffer.append(Breakable(sep, width, self))
230 self.buffer_width += width
230 self.buffer_width += width
231 self._break_outer_groups()
231 self._break_outer_groups()
232
232
233 def break_(self):
233 def break_(self):
234 """
234 """
235 Explicitly insert a newline into the output, maintaining correct indentation.
235 Explicitly insert a newline into the output, maintaining correct indentation.
236 """
236 """
237 self.flush()
237 self.flush()
238 self.output.write(self.newline)
238 self.output.write(self.newline)
239 self.output.write(' ' * self.indentation)
239 self.output.write(' ' * self.indentation)
240 self.output_width = self.indentation
240 self.output_width = self.indentation
241 self.buffer_width = 0
241 self.buffer_width = 0
242
242
243
243
244 def begin_group(self, indent=0, open=''):
244 def begin_group(self, indent=0, open=''):
245 """
245 """
246 Begin a group. If you want support for python < 2.5 which doesn't has
246 Begin a group. If you want support for python < 2.5 which doesn't has
247 the with statement this is the preferred way:
247 the with statement this is the preferred way:
248
248
249 p.begin_group(1, '{')
249 p.begin_group(1, '{')
250 ...
250 ...
251 p.end_group(1, '}')
251 p.end_group(1, '}')
252
252
253 The python 2.5 expression would be this:
253 The python 2.5 expression would be this:
254
254
255 with p.group(1, '{', '}'):
255 with p.group(1, '{', '}'):
256 ...
256 ...
257
257
258 The first parameter specifies the indentation for the next line (usually
258 The first parameter specifies the indentation for the next line (usually
259 the width of the opening text), the second the opening text. All
259 the width of the opening text), the second the opening text. All
260 parameters are optional.
260 parameters are optional.
261 """
261 """
262 if open:
262 if open:
263 self.text(open)
263 self.text(open)
264 group = Group(self.group_stack[-1].depth + 1)
264 group = Group(self.group_stack[-1].depth + 1)
265 self.group_stack.append(group)
265 self.group_stack.append(group)
266 self.group_queue.enq(group)
266 self.group_queue.enq(group)
267 self.indentation += indent
267 self.indentation += indent
268
268
269 def end_group(self, dedent=0, close=''):
269 def end_group(self, dedent=0, close=''):
270 """End a group. See `begin_group` for more details."""
270 """End a group. See `begin_group` for more details."""
271 self.indentation -= dedent
271 self.indentation -= dedent
272 group = self.group_stack.pop()
272 group = self.group_stack.pop()
273 if not group.breakables:
273 if not group.breakables:
274 self.group_queue.remove(group)
274 self.group_queue.remove(group)
275 if close:
275 if close:
276 self.text(close)
276 self.text(close)
277
277
278 def flush(self):
278 def flush(self):
279 """Flush data that is left in the buffer."""
279 """Flush data that is left in the buffer."""
280 for data in self.buffer:
280 for data in self.buffer:
281 self.output_width += data.output(self.output, self.output_width)
281 self.output_width += data.output(self.output, self.output_width)
282 self.buffer.clear()
282 self.buffer.clear()
283 self.buffer_width = 0
283 self.buffer_width = 0
284
284
285
285
286 def _get_mro(obj_class):
286 def _get_mro(obj_class):
287 """ Get a reasonable method resolution order of a class and its superclasses
287 """ Get a reasonable method resolution order of a class and its superclasses
288 for both old-style and new-style classes.
288 for both old-style and new-style classes.
289 """
289 """
290 if not hasattr(obj_class, '__mro__'):
290 if not hasattr(obj_class, '__mro__'):
291 # Old-style class. Mix in object to make a fake new-style class.
291 # Old-style class. Mix in object to make a fake new-style class.
292 try:
292 try:
293 obj_class = type(obj_class.__name__, (obj_class, object), {})
293 obj_class = type(obj_class.__name__, (obj_class, object), {})
294 except TypeError:
294 except TypeError:
295 # Old-style extension type that does not descend from object.
295 # Old-style extension type that does not descend from object.
296 # FIXME: try to construct a more thorough MRO.
296 # FIXME: try to construct a more thorough MRO.
297 mro = [obj_class]
297 mro = [obj_class]
298 else:
298 else:
299 mro = obj_class.__mro__[1:-1]
299 mro = obj_class.__mro__[1:-1]
300 else:
300 else:
301 mro = obj_class.__mro__
301 mro = obj_class.__mro__
302 return mro
302 return mro
303
303
304
304
305 class RepresentationPrinter(PrettyPrinter):
305 class RepresentationPrinter(PrettyPrinter):
306 """
306 """
307 Special pretty printer that has a `pretty` method that calls the pretty
307 Special pretty printer that has a `pretty` method that calls the pretty
308 printer for a python object.
308 printer for a python object.
309
309
310 This class stores processing data on `self` so you must *never* use
310 This class stores processing data on `self` so you must *never* use
311 this class in a threaded environment. Always lock it or reinstanciate
311 this class in a threaded environment. Always lock it or reinstanciate
312 it.
312 it.
313
313
314 Instances also have a verbose flag callbacks can access to control their
314 Instances also have a verbose flag callbacks can access to control their
315 output. For example the default instance repr prints all attributes and
315 output. For example the default instance repr prints all attributes and
316 methods that are not prefixed by an underscore if the printer is in
316 methods that are not prefixed by an underscore if the printer is in
317 verbose mode.
317 verbose mode.
318 """
318 """
319
319
320 def __init__(self, output, verbose=False, max_width=79, newline='\n',
320 def __init__(self, output, verbose=False, max_width=79, newline='\n',
321 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
321 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
322
322
323 PrettyPrinter.__init__(self, output, max_width, newline)
323 PrettyPrinter.__init__(self, output, max_width, newline)
324 self.verbose = verbose
324 self.verbose = verbose
325 self.stack = []
325 self.stack = []
326 if singleton_pprinters is None:
326 if singleton_pprinters is None:
327 singleton_pprinters = _singleton_pprinters.copy()
327 singleton_pprinters = _singleton_pprinters.copy()
328 self.singleton_pprinters = singleton_pprinters
328 self.singleton_pprinters = singleton_pprinters
329 if type_pprinters is None:
329 if type_pprinters is None:
330 type_pprinters = _type_pprinters.copy()
330 type_pprinters = _type_pprinters.copy()
331 self.type_pprinters = type_pprinters
331 self.type_pprinters = type_pprinters
332 if deferred_pprinters is None:
332 if deferred_pprinters is None:
333 deferred_pprinters = _deferred_type_pprinters.copy()
333 deferred_pprinters = _deferred_type_pprinters.copy()
334 self.deferred_pprinters = deferred_pprinters
334 self.deferred_pprinters = deferred_pprinters
335
335
336 def pretty(self, obj):
336 def pretty(self, obj):
337 """Pretty print the given object."""
337 """Pretty print the given object."""
338 obj_id = id(obj)
338 obj_id = id(obj)
339 cycle = obj_id in self.stack
339 cycle = obj_id in self.stack
340 self.stack.append(obj_id)
340 self.stack.append(obj_id)
341 self.begin_group()
341 self.begin_group()
342 try:
342 try:
343 obj_class = getattr(obj, '__class__', None) or type(obj)
343 obj_class = getattr(obj, '__class__', None) or type(obj)
344 # First try to find registered singleton printers for the type.
344 # First try to find registered singleton printers for the type.
345 try:
345 try:
346 printer = self.singleton_pprinters[obj_id]
346 printer = self.singleton_pprinters[obj_id]
347 except (TypeError, KeyError):
347 except (TypeError, KeyError):
348 pass
348 pass
349 else:
349 else:
350 return printer(obj, self, cycle)
350 return printer(obj, self, cycle)
351 # Next walk the mro and check for either:
351 # Next walk the mro and check for either:
352 # 1) a registered printer
352 # 1) a registered printer
353 # 2) a _repr_pretty_ method
353 # 2) a _repr_pretty_ method
354 for cls in _get_mro(obj_class):
354 for cls in _get_mro(obj_class):
355 if cls in self.type_pprinters:
355 if cls in self.type_pprinters:
356 # printer registered in self.type_pprinters
356 # printer registered in self.type_pprinters
357 return self.type_pprinters[cls](obj, self, cycle)
357 return self.type_pprinters[cls](obj, self, cycle)
358 else:
358 else:
359 # deferred printer
359 # deferred printer
360 printer = self._in_deferred_types(cls)
360 printer = self._in_deferred_types(cls)
361 if printer is not None:
361 if printer is not None:
362 return printer(obj, self, cycle)
362 return printer(obj, self, cycle)
363 else:
363 else:
364 # Finally look for special method names.
364 # Finally look for special method names.
365 # Some objects automatically create any requested
365 # Some objects automatically create any requested
366 # attribute. Try to ignore most of them by checking for
366 # attribute. Try to ignore most of them by checking for
367 # callability.
367 # callability.
368 if '_repr_pretty_' in cls.__dict__:
368 if '_repr_pretty_' in cls.__dict__:
369 meth = cls._repr_pretty_
369 meth = cls._repr_pretty_
370 if callable(meth):
370 if callable(meth):
371 return meth(obj, self, cycle)
371 return meth(obj, self, cycle)
372 return _default_pprint(obj, self, cycle)
372 return _default_pprint(obj, self, cycle)
373 finally:
373 finally:
374 self.end_group()
374 self.end_group()
375 self.stack.pop()
375 self.stack.pop()
376
376
377 def _in_deferred_types(self, cls):
377 def _in_deferred_types(self, cls):
378 """
378 """
379 Check if the given class is specified in the deferred type registry.
379 Check if the given class is specified in the deferred type registry.
380
380
381 Returns the printer from the registry if it exists, and None if the
381 Returns the printer from the registry if it exists, and None if the
382 class is not in the registry. Successful matches will be moved to the
382 class is not in the registry. Successful matches will be moved to the
383 regular type registry for future use.
383 regular type registry for future use.
384 """
384 """
385 mod = getattr(cls, '__module__', None)
385 mod = getattr(cls, '__module__', None)
386 name = getattr(cls, '__name__', None)
386 name = getattr(cls, '__name__', None)
387 key = (mod, name)
387 key = (mod, name)
388 printer = None
388 printer = None
389 if key in self.deferred_pprinters:
389 if key in self.deferred_pprinters:
390 # Move the printer over to the regular registry.
390 # Move the printer over to the regular registry.
391 printer = self.deferred_pprinters.pop(key)
391 printer = self.deferred_pprinters.pop(key)
392 self.type_pprinters[cls] = printer
392 self.type_pprinters[cls] = printer
393 return printer
393 return printer
394
394
395
395
396 class Printable(object):
396 class Printable(object):
397
397
398 def output(self, stream, output_width):
398 def output(self, stream, output_width):
399 return output_width
399 return output_width
400
400
401
401
402 class Text(Printable):
402 class Text(Printable):
403
403
404 def __init__(self):
404 def __init__(self):
405 self.objs = []
405 self.objs = []
406 self.width = 0
406 self.width = 0
407
407
408 def output(self, stream, output_width):
408 def output(self, stream, output_width):
409 for obj in self.objs:
409 for obj in self.objs:
410 stream.write(obj)
410 stream.write(obj)
411 return output_width + self.width
411 return output_width + self.width
412
412
413 def add(self, obj, width):
413 def add(self, obj, width):
414 self.objs.append(obj)
414 self.objs.append(obj)
415 self.width += width
415 self.width += width
416
416
417
417
418 class Breakable(Printable):
418 class Breakable(Printable):
419
419
420 def __init__(self, seq, width, pretty):
420 def __init__(self, seq, width, pretty):
421 self.obj = seq
421 self.obj = seq
422 self.width = width
422 self.width = width
423 self.pretty = pretty
423 self.pretty = pretty
424 self.indentation = pretty.indentation
424 self.indentation = pretty.indentation
425 self.group = pretty.group_stack[-1]
425 self.group = pretty.group_stack[-1]
426 self.group.breakables.append(self)
426 self.group.breakables.append(self)
427
427
428 def output(self, stream, output_width):
428 def output(self, stream, output_width):
429 self.group.breakables.popleft()
429 self.group.breakables.popleft()
430 if self.group.want_break:
430 if self.group.want_break:
431 stream.write(self.pretty.newline)
431 stream.write(self.pretty.newline)
432 stream.write(' ' * self.indentation)
432 stream.write(' ' * self.indentation)
433 return self.indentation
433 return self.indentation
434 if not self.group.breakables:
434 if not self.group.breakables:
435 self.pretty.group_queue.remove(self.group)
435 self.pretty.group_queue.remove(self.group)
436 stream.write(self.obj)
436 stream.write(self.obj)
437 return output_width + self.width
437 return output_width + self.width
438
438
439
439
440 class Group(Printable):
440 class Group(Printable):
441
441
442 def __init__(self, depth):
442 def __init__(self, depth):
443 self.depth = depth
443 self.depth = depth
444 self.breakables = deque()
444 self.breakables = deque()
445 self.want_break = False
445 self.want_break = False
446
446
447
447
448 class GroupQueue(object):
448 class GroupQueue(object):
449
449
450 def __init__(self, *groups):
450 def __init__(self, *groups):
451 self.queue = []
451 self.queue = []
452 for group in groups:
452 for group in groups:
453 self.enq(group)
453 self.enq(group)
454
454
455 def enq(self, group):
455 def enq(self, group):
456 depth = group.depth
456 depth = group.depth
457 while depth > len(self.queue) - 1:
457 while depth > len(self.queue) - 1:
458 self.queue.append([])
458 self.queue.append([])
459 self.queue[depth].append(group)
459 self.queue[depth].append(group)
460
460
461 def deq(self):
461 def deq(self):
462 for stack in self.queue:
462 for stack in self.queue:
463 for idx, group in enumerate(reversed(stack)):
463 for idx, group in enumerate(reversed(stack)):
464 if group.breakables:
464 if group.breakables:
465 del stack[idx]
465 del stack[idx]
466 group.want_break = True
466 group.want_break = True
467 return group
467 return group
468 for group in stack:
468 for group in stack:
469 group.want_break = True
469 group.want_break = True
470 del stack[:]
470 del stack[:]
471
471
472 def remove(self, group):
472 def remove(self, group):
473 try:
473 try:
474 self.queue[group.depth].remove(group)
474 self.queue[group.depth].remove(group)
475 except ValueError:
475 except ValueError:
476 pass
476 pass
477
477
478 try:
478 try:
479 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
479 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
480 except AttributeError: # Python 3
480 except AttributeError: # Python 3
481 _baseclass_reprs = (object.__repr__,)
481 _baseclass_reprs = (object.__repr__,)
482
482
483
483
484 def _default_pprint(obj, p, cycle):
484 def _default_pprint(obj, p, cycle):
485 """
485 """
486 The default print function. Used if an object does not provide one and
486 The default print function. Used if an object does not provide one and
487 it's none of the builtin objects.
487 it's none of the builtin objects.
488 """
488 """
489 klass = getattr(obj, '__class__', None) or type(obj)
489 klass = getattr(obj, '__class__', None) or type(obj)
490 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
490 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
491 # A user-provided repr. Find newlines and replace them with p.break_()
491 # A user-provided repr. Find newlines and replace them with p.break_()
492 output = repr(obj)
492 output = repr(obj)
493 for idx,output_line in enumerate(output.splitlines()):
493 for idx,output_line in enumerate(output.splitlines()):
494 if idx:
494 if idx:
495 p.break_()
495 p.break_()
496 p.text(output_line)
496 p.text(output_line)
497 return
497 return
498 p.begin_group(1, '<')
498 p.begin_group(1, '<')
499 p.pretty(klass)
499 p.pretty(klass)
500 p.text(' at 0x%x' % id(obj))
500 p.text(' at 0x%x' % id(obj))
501 if cycle:
501 if cycle:
502 p.text(' ...')
502 p.text(' ...')
503 elif p.verbose:
503 elif p.verbose:
504 first = True
504 first = True
505 for key in dir(obj):
505 for key in dir(obj):
506 if not key.startswith('_'):
506 if not key.startswith('_'):
507 try:
507 try:
508 value = getattr(obj, key)
508 value = getattr(obj, key)
509 except AttributeError:
509 except AttributeError:
510 continue
510 continue
511 if isinstance(value, types.MethodType):
511 if isinstance(value, types.MethodType):
512 continue
512 continue
513 if not first:
513 if not first:
514 p.text(',')
514 p.text(',')
515 p.breakable()
515 p.breakable()
516 p.text(key)
516 p.text(key)
517 p.text('=')
517 p.text('=')
518 step = len(key) + 1
518 step = len(key) + 1
519 p.indentation += step
519 p.indentation += step
520 p.pretty(value)
520 p.pretty(value)
521 p.indentation -= step
521 p.indentation -= step
522 first = False
522 first = False
523 p.end_group(1, '>')
523 p.end_group(1, '>')
524
524
525
525
526 def _seq_pprinter_factory(start, end, basetype):
526 def _seq_pprinter_factory(start, end, basetype):
527 """
527 """
528 Factory that returns a pprint function useful for sequences. Used by
528 Factory that returns a pprint function useful for sequences. Used by
529 the default pprint for tuples, dicts, and lists.
529 the default pprint for tuples, dicts, and lists.
530 """
530 """
531 def inner(obj, p, cycle):
531 def inner(obj, p, cycle):
532 typ = type(obj)
532 typ = type(obj)
533 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
533 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
534 # If the subclass provides its own repr, use it instead.
534 # If the subclass provides its own repr, use it instead.
535 return p.text(typ.__repr__(obj))
535 return p.text(typ.__repr__(obj))
536
536
537 if cycle:
537 if cycle:
538 return p.text(start + '...' + end)
538 return p.text(start + '...' + end)
539 step = len(start)
539 step = len(start)
540 p.begin_group(step, start)
540 p.begin_group(step, start)
541 for idx, x in enumerate(obj):
541 for idx, x in enumerate(obj):
542 if idx:
542 if idx:
543 p.text(',')
543 p.text(',')
544 p.breakable()
544 p.breakable()
545 p.pretty(x)
545 p.pretty(x)
546 if len(obj) == 1 and type(obj) is tuple:
546 if len(obj) == 1 and type(obj) is tuple:
547 # Special case for 1-item tuples.
547 # Special case for 1-item tuples.
548 p.text(',')
548 p.text(',')
549 p.end_group(step, end)
549 p.end_group(step, end)
550 return inner
550 return inner
551
551
552
552
553 def _set_pprinter_factory(start, end, basetype):
553 def _set_pprinter_factory(start, end, basetype):
554 """
554 """
555 Factory that returns a pprint function useful for sets and frozensets.
555 Factory that returns a pprint function useful for sets and frozensets.
556 """
556 """
557 def inner(obj, p, cycle):
557 def inner(obj, p, cycle):
558 typ = type(obj)
558 typ = type(obj)
559 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
559 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
560 # If the subclass provides its own repr, use it instead.
560 # If the subclass provides its own repr, use it instead.
561 return p.text(typ.__repr__(obj))
561 return p.text(typ.__repr__(obj))
562
562
563 if cycle:
563 if cycle:
564 return p.text(start + '...' + end)
564 return p.text(start + '...' + end)
565 if len(obj) == 0:
565 if len(obj) == 0:
566 # Special case.
566 # Special case.
567 p.text(basetype.__name__ + '()')
567 p.text(basetype.__name__ + '()')
568 else:
568 else:
569 step = len(start)
569 step = len(start)
570 p.begin_group(step, start)
570 p.begin_group(step, start)
571 # Like dictionary keys, we will try to sort the items.
571 # Like dictionary keys, we will try to sort the items.
572 items = list(obj)
572 items = list(obj)
573 try:
573 try:
574 items.sort()
574 items.sort()
575 except Exception:
575 except Exception:
576 # Sometimes the items don't sort.
576 # Sometimes the items don't sort.
577 pass
577 pass
578 for idx, x in enumerate(items):
578 for idx, x in enumerate(items):
579 if idx:
579 if idx:
580 p.text(',')
580 p.text(',')
581 p.breakable()
581 p.breakable()
582 p.pretty(x)
582 p.pretty(x)
583 p.end_group(step, end)
583 p.end_group(step, end)
584 return inner
584 return inner
585
585
586
586
587 def _dict_pprinter_factory(start, end, basetype=None):
587 def _dict_pprinter_factory(start, end, basetype=None):
588 """
588 """
589 Factory that returns a pprint function used by the default pprint of
589 Factory that returns a pprint function used by the default pprint of
590 dicts and dict proxies.
590 dicts and dict proxies.
591 """
591 """
592 def inner(obj, p, cycle):
592 def inner(obj, p, cycle):
593 typ = type(obj)
593 typ = type(obj)
594 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
594 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
595 # If the subclass provides its own repr, use it instead.
595 # If the subclass provides its own repr, use it instead.
596 return p.text(typ.__repr__(obj))
596 return p.text(typ.__repr__(obj))
597
597
598 if cycle:
598 if cycle:
599 return p.text('{...}')
599 return p.text('{...}')
600 p.begin_group(1, start)
600 p.begin_group(1, start)
601 keys = obj.keys()
601 keys = obj.keys()
602 try:
602 try:
603 keys.sort()
603 keys.sort()
604 except Exception as e:
604 except Exception as e:
605 # Sometimes the keys don't sort.
605 # Sometimes the keys don't sort.
606 pass
606 pass
607 for idx, key in enumerate(keys):
607 for idx, key in enumerate(keys):
608 if idx:
608 if idx:
609 p.text(',')
609 p.text(',')
610 p.breakable()
610 p.breakable()
611 p.pretty(key)
611 p.pretty(key)
612 p.text(': ')
612 p.text(': ')
613 p.pretty(obj[key])
613 p.pretty(obj[key])
614 p.end_group(1, end)
614 p.end_group(1, end)
615 return inner
615 return inner
616
616
617
617
618 def _super_pprint(obj, p, cycle):
618 def _super_pprint(obj, p, cycle):
619 """The pprint for the super type."""
619 """The pprint for the super type."""
620 p.begin_group(8, '<super: ')
620 p.begin_group(8, '<super: ')
621 p.pretty(obj.__self_class__)
621 p.pretty(obj.__self_class__)
622 p.text(',')
622 p.text(',')
623 p.breakable()
623 p.breakable()
624 p.pretty(obj.__self__)
624 p.pretty(obj.__self__)
625 p.end_group(8, '>')
625 p.end_group(8, '>')
626
626
627
627
628 def _re_pattern_pprint(obj, p, cycle):
628 def _re_pattern_pprint(obj, p, cycle):
629 """The pprint function for regular expression patterns."""
629 """The pprint function for regular expression patterns."""
630 p.text('re.compile(')
630 p.text('re.compile(')
631 pattern = repr(obj.pattern)
631 pattern = repr(obj.pattern)
632 if pattern[:1] in 'uU':
632 if pattern[:1] in 'uU':
633 pattern = pattern[1:]
633 pattern = pattern[1:]
634 prefix = 'ur'
634 prefix = 'ur'
635 else:
635 else:
636 prefix = 'r'
636 prefix = 'r'
637 pattern = prefix + pattern.replace('\\\\', '\\')
637 pattern = prefix + pattern.replace('\\\\', '\\')
638 p.text(pattern)
638 p.text(pattern)
639 if obj.flags:
639 if obj.flags:
640 p.text(',')
640 p.text(',')
641 p.breakable()
641 p.breakable()
642 done_one = False
642 done_one = False
643 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
643 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
644 'UNICODE', 'VERBOSE', 'DEBUG'):
644 'UNICODE', 'VERBOSE', 'DEBUG'):
645 if obj.flags & getattr(re, flag):
645 if obj.flags & getattr(re, flag):
646 if done_one:
646 if done_one:
647 p.text('|')
647 p.text('|')
648 p.text('re.' + flag)
648 p.text('re.' + flag)
649 done_one = True
649 done_one = True
650 p.text(')')
650 p.text(')')
651
651
652
652
653 def _type_pprint(obj, p, cycle):
653 def _type_pprint(obj, p, cycle):
654 """The pprint for classes and types."""
654 """The pprint for classes and types."""
655 mod = getattr(obj, '__module__', None)
655 mod = getattr(obj, '__module__', None)
656 if mod is None:
656 if mod is None:
657 # Heap allocated types might not have the module attribute,
657 # Heap allocated types might not have the module attribute,
658 # and others may set it to None.
658 # and others may set it to None.
659 return p.text(obj.__name__)
659 return p.text(obj.__name__)
660
660
661 if mod in ('__builtin__', 'builtins', 'exceptions'):
661 if mod in ('__builtin__', 'builtins', 'exceptions'):
662 name = obj.__name__
662 name = obj.__name__
663 else:
663 else:
664 name = mod + '.' + obj.__name__
664 name = mod + '.' + obj.__name__
665 p.text(name)
665 p.text(name)
666
666
667
667
668 def _repr_pprint(obj, p, cycle):
668 def _repr_pprint(obj, p, cycle):
669 """A pprint that just redirects to the normal repr function."""
669 """A pprint that just redirects to the normal repr function."""
670 p.text(repr(obj))
670 p.text(repr(obj))
671
671
672
672
673 def _function_pprint(obj, p, cycle):
673 def _function_pprint(obj, p, cycle):
674 """Base pprint for all functions and builtin functions."""
674 """Base pprint for all functions and builtin functions."""
675 if obj.__module__ in ('__builtin__', 'builtins', 'exceptions') or not obj.__module__:
675 if obj.__module__ in ('__builtin__', 'builtins', 'exceptions') or not obj.__module__:
676 name = obj.__name__
676 name = obj.__name__
677 else:
677 else:
678 name = obj.__module__ + '.' + obj.__name__
678 name = obj.__module__ + '.' + obj.__name__
679 p.text('<function %s>' % name)
679 p.text('<function %s>' % name)
680
680
681
681
682 def _exception_pprint(obj, p, cycle):
682 def _exception_pprint(obj, p, cycle):
683 """Base pprint for all exceptions."""
683 """Base pprint for all exceptions."""
684 if obj.__class__.__module__ in ('exceptions', 'builtins'):
684 if obj.__class__.__module__ in ('exceptions', 'builtins'):
685 name = obj.__class__.__name__
685 name = obj.__class__.__name__
686 else:
686 else:
687 name = '%s.%s' % (
687 name = '%s.%s' % (
688 obj.__class__.__module__,
688 obj.__class__.__module__,
689 obj.__class__.__name__
689 obj.__class__.__name__
690 )
690 )
691 step = len(name) + 1
691 step = len(name) + 1
692 p.begin_group(step, name + '(')
692 p.begin_group(step, name + '(')
693 for idx, arg in enumerate(getattr(obj, 'args', ())):
693 for idx, arg in enumerate(getattr(obj, 'args', ())):
694 if idx:
694 if idx:
695 p.text(',')
695 p.text(',')
696 p.breakable()
696 p.breakable()
697 p.pretty(arg)
697 p.pretty(arg)
698 p.end_group(step, ')')
698 p.end_group(step, ')')
699
699
700
700
701 #: the exception base
701 #: the exception base
702 try:
702 try:
703 _exception_base = BaseException
703 _exception_base = BaseException
704 except NameError:
704 except NameError:
705 _exception_base = Exception
705 _exception_base = Exception
706
706
707
707
708 #: printers for builtin types
708 #: printers for builtin types
709 _type_pprinters = {
709 _type_pprinters = {
710 int: _repr_pprint,
710 int: _repr_pprint,
711 float: _repr_pprint,
711 float: _repr_pprint,
712 str: _repr_pprint,
712 str: _repr_pprint,
713 tuple: _seq_pprinter_factory('(', ')', tuple),
713 tuple: _seq_pprinter_factory('(', ')', tuple),
714 list: _seq_pprinter_factory('[', ']', list),
714 list: _seq_pprinter_factory('[', ']', list),
715 dict: _dict_pprinter_factory('{', '}', dict),
715 dict: _dict_pprinter_factory('{', '}', dict),
716
716
717 set: _set_pprinter_factory('{', '}', set),
717 set: _set_pprinter_factory('{', '}', set),
718 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
718 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
719 super: _super_pprint,
719 super: _super_pprint,
720 _re_pattern_type: _re_pattern_pprint,
720 _re_pattern_type: _re_pattern_pprint,
721 type: _type_pprint,
721 type: _type_pprint,
722 types.FunctionType: _function_pprint,
722 types.FunctionType: _function_pprint,
723 types.BuiltinFunctionType: _function_pprint,
723 types.BuiltinFunctionType: _function_pprint,
724 types.SliceType: _repr_pprint,
725 types.MethodType: _repr_pprint,
724 types.MethodType: _repr_pprint,
726
725
727 datetime.datetime: _repr_pprint,
726 datetime.datetime: _repr_pprint,
728 datetime.timedelta: _repr_pprint,
727 datetime.timedelta: _repr_pprint,
729 _exception_base: _exception_pprint
728 _exception_base: _exception_pprint
730 }
729 }
731
730
732 try:
731 try:
733 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
732 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
734 _type_pprinters[types.ClassType] = _type_pprint
733 _type_pprinters[types.ClassType] = _type_pprint
735 _type_pprinters[long] = _repr_pprint
734 _type_pprinters[types.SliceType] = _repr_pprint
736 _type_pprinters[unicode] = _repr_pprint
735 except AttributeError: # Python 3
737 except (AttributeError, NameError): # Python 3
736 _type_pprinters[slice] = _repr_pprint
738 _type_pprinters[bytes] = _repr_pprint
739
737
740 try:
738 try:
741 _type_pprinters[xrange] = _repr_pprint
739 _type_pprinters[xrange] = _repr_pprint
740 _type_pprinters[long] = _repr_pprint
741 _type_pprinters[unicode] = _repr_pprint
742 except NameError:
742 except NameError:
743 _type_pprinters[range] = _repr_pprint
743 _type_pprinters[range] = _repr_pprint
744 _type_pprinters[bytes] = _repr_pprint
744
745
745 #: printers for types specified by name
746 #: printers for types specified by name
746 _deferred_type_pprinters = {
747 _deferred_type_pprinters = {
747 }
748 }
748
749
749 def for_type(typ, func):
750 def for_type(typ, func):
750 """
751 """
751 Add a pretty printer for a given type.
752 Add a pretty printer for a given type.
752 """
753 """
753 oldfunc = _type_pprinters.get(typ, None)
754 oldfunc = _type_pprinters.get(typ, None)
754 if func is not None:
755 if func is not None:
755 # To support easy restoration of old pprinters, we need to ignore Nones.
756 # To support easy restoration of old pprinters, we need to ignore Nones.
756 _type_pprinters[typ] = func
757 _type_pprinters[typ] = func
757 return oldfunc
758 return oldfunc
758
759
759 def for_type_by_name(type_module, type_name, func):
760 def for_type_by_name(type_module, type_name, func):
760 """
761 """
761 Add a pretty printer for a type specified by the module and name of a type
762 Add a pretty printer for a type specified by the module and name of a type
762 rather than the type object itself.
763 rather than the type object itself.
763 """
764 """
764 key = (type_module, type_name)
765 key = (type_module, type_name)
765 oldfunc = _deferred_type_pprinters.get(key, None)
766 oldfunc = _deferred_type_pprinters.get(key, None)
766 if func is not None:
767 if func is not None:
767 # To support easy restoration of old pprinters, we need to ignore Nones.
768 # To support easy restoration of old pprinters, we need to ignore Nones.
768 _deferred_type_pprinters[key] = func
769 _deferred_type_pprinters[key] = func
769 return oldfunc
770 return oldfunc
770
771
771
772
772 #: printers for the default singletons
773 #: printers for the default singletons
773 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
774 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
774 NotImplemented]), _repr_pprint)
775 NotImplemented]), _repr_pprint)
775
776
776
777
777 if __name__ == '__main__':
778 if __name__ == '__main__':
778 from random import randrange
779 from random import randrange
779 class Foo(object):
780 class Foo(object):
780 def __init__(self):
781 def __init__(self):
781 self.foo = 1
782 self.foo = 1
782 self.bar = re.compile(r'\s+')
783 self.bar = re.compile(r'\s+')
783 self.blub = dict.fromkeys(range(30), randrange(1, 40))
784 self.blub = dict.fromkeys(range(30), randrange(1, 40))
784 self.hehe = 23424.234234
785 self.hehe = 23424.234234
785 self.list = ["blub", "blah", self]
786 self.list = ["blub", "blah", self]
786
787
787 def get_foo(self):
788 def get_foo(self):
788 print("foo")
789 print("foo")
789
790
790 pprint(Foo(), verbose=True)
791 pprint(Foo(), verbose=True)
@@ -1,186 +1,186 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for coloring text in ANSI terminals.
2 """Tools for coloring text in ANSI terminals.
3 """
3 """
4
4
5 #*****************************************************************************
5 #*****************************************************************************
6 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #*****************************************************************************
10 #*****************************************************************************
11
11
12 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
12 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
13
13
14 import os
14 import os
15
15
16 from IPython.utils.ipstruct import Struct
16 from IPython.utils.ipstruct import Struct
17
17
18 color_templates = (
18 color_templates = (
19 # Dark colors
19 # Dark colors
20 ("Black" , "0;30"),
20 ("Black" , "0;30"),
21 ("Red" , "0;31"),
21 ("Red" , "0;31"),
22 ("Green" , "0;32"),
22 ("Green" , "0;32"),
23 ("Brown" , "0;33"),
23 ("Brown" , "0;33"),
24 ("Blue" , "0;34"),
24 ("Blue" , "0;34"),
25 ("Purple" , "0;35"),
25 ("Purple" , "0;35"),
26 ("Cyan" , "0;36"),
26 ("Cyan" , "0;36"),
27 ("LightGray" , "0;37"),
27 ("LightGray" , "0;37"),
28 # Light colors
28 # Light colors
29 ("DarkGray" , "1;30"),
29 ("DarkGray" , "1;30"),
30 ("LightRed" , "1;31"),
30 ("LightRed" , "1;31"),
31 ("LightGreen" , "1;32"),
31 ("LightGreen" , "1;32"),
32 ("Yellow" , "1;33"),
32 ("Yellow" , "1;33"),
33 ("LightBlue" , "1;34"),
33 ("LightBlue" , "1;34"),
34 ("LightPurple" , "1;35"),
34 ("LightPurple" , "1;35"),
35 ("LightCyan" , "1;36"),
35 ("LightCyan" , "1;36"),
36 ("White" , "1;37"),
36 ("White" , "1;37"),
37 # Blinking colors. Probably should not be used in anything serious.
37 # Blinking colors. Probably should not be used in anything serious.
38 ("BlinkBlack" , "5;30"),
38 ("BlinkBlack" , "5;30"),
39 ("BlinkRed" , "5;31"),
39 ("BlinkRed" , "5;31"),
40 ("BlinkGreen" , "5;32"),
40 ("BlinkGreen" , "5;32"),
41 ("BlinkYellow" , "5;33"),
41 ("BlinkYellow" , "5;33"),
42 ("BlinkBlue" , "5;34"),
42 ("BlinkBlue" , "5;34"),
43 ("BlinkPurple" , "5;35"),
43 ("BlinkPurple" , "5;35"),
44 ("BlinkCyan" , "5;36"),
44 ("BlinkCyan" , "5;36"),
45 ("BlinkLightGray", "5;37"),
45 ("BlinkLightGray", "5;37"),
46 )
46 )
47
47
48 def make_color_table(in_class):
48 def make_color_table(in_class):
49 """Build a set of color attributes in a class.
49 """Build a set of color attributes in a class.
50
50
51 Helper function for building the *TermColors classes."""
51 Helper function for building the *TermColors classes."""
52
52
53 for name,value in color_templates:
53 for name,value in color_templates:
54 setattr(in_class,name,in_class._base % value)
54 setattr(in_class,name,in_class._base % value)
55
55
56 class TermColors:
56 class TermColors:
57 """Color escape sequences.
57 """Color escape sequences.
58
58
59 This class defines the escape sequences for all the standard (ANSI?)
59 This class defines the escape sequences for all the standard (ANSI?)
60 colors in terminals. Also defines a NoColor escape which is just the null
60 colors in terminals. Also defines a NoColor escape which is just the null
61 string, suitable for defining 'dummy' color schemes in terminals which get
61 string, suitable for defining 'dummy' color schemes in terminals which get
62 confused by color escapes.
62 confused by color escapes.
63
63
64 This class should be used as a mixin for building color schemes."""
64 This class should be used as a mixin for building color schemes."""
65
65
66 NoColor = '' # for color schemes in color-less terminals.
66 NoColor = '' # for color schemes in color-less terminals.
67 Normal = '\033[0m' # Reset normal coloring
67 Normal = '\033[0m' # Reset normal coloring
68 _base = '\033[%sm' # Template for all other colors
68 _base = '\033[%sm' # Template for all other colors
69
69
70 # Build the actual color table as a set of class attributes:
70 # Build the actual color table as a set of class attributes:
71 make_color_table(TermColors)
71 make_color_table(TermColors)
72
72
73 class InputTermColors:
73 class InputTermColors:
74 """Color escape sequences for input prompts.
74 """Color escape sequences for input prompts.
75
75
76 This class is similar to TermColors, but the escapes are wrapped in \001
76 This class is similar to TermColors, but the escapes are wrapped in \001
77 and \002 so that readline can properly know the length of each line and
77 and \002 so that readline can properly know the length of each line and
78 can wrap lines accordingly. Use this class for any colored text which
78 can wrap lines accordingly. Use this class for any colored text which
79 needs to be used in input prompts, such as in calls to raw_input().
79 needs to be used in input prompts, such as in calls to raw_input().
80
80
81 This class defines the escape sequences for all the standard (ANSI?)
81 This class defines the escape sequences for all the standard (ANSI?)
82 colors in terminals. Also defines a NoColor escape which is just the null
82 colors in terminals. Also defines a NoColor escape which is just the null
83 string, suitable for defining 'dummy' color schemes in terminals which get
83 string, suitable for defining 'dummy' color schemes in terminals which get
84 confused by color escapes.
84 confused by color escapes.
85
85
86 This class should be used as a mixin for building color schemes."""
86 This class should be used as a mixin for building color schemes."""
87
87
88 NoColor = '' # for color schemes in color-less terminals.
88 NoColor = '' # for color schemes in color-less terminals.
89
89
90 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
90 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
91 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
91 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
92 Normal = '\033[0m' # Reset normal coloring
92 Normal = '\033[0m' # Reset normal coloring
93 _base = '\033[%sm' # Template for all other colors
93 _base = '\033[%sm' # Template for all other colors
94 else:
94 else:
95 Normal = '\001\033[0m\002' # Reset normal coloring
95 Normal = '\001\033[0m\002' # Reset normal coloring
96 _base = '\001\033[%sm\002' # Template for all other colors
96 _base = '\001\033[%sm\002' # Template for all other colors
97
97
98 # Build the actual color table as a set of class attributes:
98 # Build the actual color table as a set of class attributes:
99 make_color_table(InputTermColors)
99 make_color_table(InputTermColors)
100
100
101 class NoColors:
101 class NoColors:
102 """This defines all the same names as the colour classes, but maps them to
102 """This defines all the same names as the colour classes, but maps them to
103 empty strings, so it can easily be substituted to turn off colours."""
103 empty strings, so it can easily be substituted to turn off colours."""
104 NoColor = ''
104 NoColor = ''
105 Normal = ''
105 Normal = ''
106
106
107 for name, value in color_templates:
107 for name, value in color_templates:
108 setattr(NoColors, name, '')
108 setattr(NoColors, name, '')
109
109
110 class ColorScheme:
110 class ColorScheme:
111 """Generic color scheme class. Just a name and a Struct."""
111 """Generic color scheme class. Just a name and a Struct."""
112 def __init__(self,__scheme_name_,colordict=None,**colormap):
112 def __init__(self,__scheme_name_,colordict=None,**colormap):
113 self.name = __scheme_name_
113 self.name = __scheme_name_
114 if colordict is None:
114 if colordict is None:
115 self.colors = Struct(**colormap)
115 self.colors = Struct(**colormap)
116 else:
116 else:
117 self.colors = Struct(colordict)
117 self.colors = Struct(colordict)
118
118
119 def copy(self,name=None):
119 def copy(self,name=None):
120 """Return a full copy of the object, optionally renaming it."""
120 """Return a full copy of the object, optionally renaming it."""
121 if name is None:
121 if name is None:
122 name = self.name
122 name = self.name
123 return ColorScheme(name, self.colors.dict())
123 return ColorScheme(name, self.colors.dict())
124
124
125 class ColorSchemeTable(dict):
125 class ColorSchemeTable(dict):
126 """General class to handle tables of color schemes.
126 """General class to handle tables of color schemes.
127
127
128 It's basically a dict of color schemes with a couple of shorthand
128 It's basically a dict of color schemes with a couple of shorthand
129 attributes and some convenient methods.
129 attributes and some convenient methods.
130
130
131 active_scheme_name -> obvious
131 active_scheme_name -> obvious
132 active_colors -> actual color table of the active scheme"""
132 active_colors -> actual color table of the active scheme"""
133
133
134 def __init__(self,scheme_list=None,default_scheme=''):
134 def __init__(self,scheme_list=None,default_scheme=''):
135 """Create a table of color schemes.
135 """Create a table of color schemes.
136
136
137 The table can be created empty and manually filled or it can be
137 The table can be created empty and manually filled or it can be
138 created with a list of valid color schemes AND the specification for
138 created with a list of valid color schemes AND the specification for
139 the default active scheme.
139 the default active scheme.
140 """
140 """
141
141
142 # create object attributes to be set later
142 # create object attributes to be set later
143 self.active_scheme_name = ''
143 self.active_scheme_name = ''
144 self.active_colors = None
144 self.active_colors = None
145
145
146 if scheme_list:
146 if scheme_list:
147 if default_scheme == '':
147 if default_scheme == '':
148 raise ValueError('you must specify the default color scheme')
148 raise ValueError('you must specify the default color scheme')
149 for scheme in scheme_list:
149 for scheme in scheme_list:
150 self.add_scheme(scheme)
150 self.add_scheme(scheme)
151 self.set_active_scheme(default_scheme)
151 self.set_active_scheme(default_scheme)
152
152
153 def copy(self):
153 def copy(self):
154 """Return full copy of object"""
154 """Return full copy of object"""
155 return ColorSchemeTable(self.values(),self.active_scheme_name)
155 return ColorSchemeTable(self.values(),self.active_scheme_name)
156
156
157 def add_scheme(self,new_scheme):
157 def add_scheme(self,new_scheme):
158 """Add a new color scheme to the table."""
158 """Add a new color scheme to the table."""
159 if not isinstance(new_scheme,ColorScheme):
159 if not isinstance(new_scheme,ColorScheme):
160 raise ValueError('ColorSchemeTable only accepts ColorScheme instances')
160 raise ValueError('ColorSchemeTable only accepts ColorScheme instances')
161 self[new_scheme.name] = new_scheme
161 self[new_scheme.name] = new_scheme
162
162
163 def set_active_scheme(self,scheme,case_sensitive=0):
163 def set_active_scheme(self,scheme,case_sensitive=0):
164 """Set the currently active scheme.
164 """Set the currently active scheme.
165
165
166 Names are by default compared in a case-insensitive way, but this can
166 Names are by default compared in a case-insensitive way, but this can
167 be changed by setting the parameter case_sensitive to true."""
167 be changed by setting the parameter case_sensitive to true."""
168
168
169 scheme_names = self.keys()
169 scheme_names = list(self.keys())
170 if case_sensitive:
170 if case_sensitive:
171 valid_schemes = scheme_names
171 valid_schemes = scheme_names
172 scheme_test = scheme
172 scheme_test = scheme
173 else:
173 else:
174 valid_schemes = [s.lower() for s in scheme_names]
174 valid_schemes = [s.lower() for s in scheme_names]
175 scheme_test = scheme.lower()
175 scheme_test = scheme.lower()
176 try:
176 try:
177 scheme_idx = valid_schemes.index(scheme_test)
177 scheme_idx = valid_schemes.index(scheme_test)
178 except ValueError:
178 except ValueError:
179 raise ValueError('Unrecognized color scheme: ' + scheme + \
179 raise ValueError('Unrecognized color scheme: ' + scheme + \
180 '\nValid schemes: '+str(scheme_names).replace("'', ",''))
180 '\nValid schemes: '+str(scheme_names).replace("'', ",''))
181 else:
181 else:
182 active = scheme_names[scheme_idx]
182 active = scheme_names[scheme_idx]
183 self.active_scheme_name = active
183 self.active_scheme_name = active
184 self.active_colors = self[active].colors
184 self.active_colors = self[active].colors
185 # Now allow using '' as an index for the current active scheme
185 # Now allow using '' as an index for the current active scheme
186 self[''] = self[active]
186 self[''] = self[active]
General Comments 0
You need to be logged in to leave comments. Login now