##// END OF EJS Templates
add lookup logic based on apptools.type_registry...
MinRK -
Show More
@@ -1,681 +1,758 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Display formatters.
2 """Display formatters.
3
3
4 Inheritance diagram:
4 Inheritance diagram:
5
5
6 .. inheritance-diagram:: IPython.core.formatters
6 .. inheritance-diagram:: IPython.core.formatters
7 :parts: 3
7 :parts: 3
8
8
9 Authors:
9 Authors:
10
10
11 * Robert Kern
11 * Robert Kern
12 * Brian Granger
12 * Brian Granger
13 """
13 """
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2010-2011, IPython Development Team.
15 # Copyright (C) 2010-2011, IPython Development Team.
16 #
16 #
17 # Distributed under the terms of the Modified BSD License.
17 # Distributed under the terms of the Modified BSD License.
18 #
18 #
19 # The full license is in the file COPYING.txt, distributed with this software.
19 # The full license is in the file COPYING.txt, distributed with this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 # Stdlib imports
26 # Stdlib imports
27 import abc
27 import abc
28 import sys
28 import sys
29 import warnings
29 import warnings
30
30
31 # Our own imports
31 # Our own imports
32 from IPython.config.configurable import Configurable
32 from IPython.config.configurable import Configurable
33 from IPython.lib import pretty
33 from IPython.lib import pretty
34 from IPython.utils.traitlets import (
34 from IPython.utils.traitlets import (
35 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
35 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
36 )
36 )
37 from IPython.utils.py3compat import unicode_to_str, with_metaclass, PY3
37 from IPython.utils.py3compat import (
38 unicode_to_str, with_metaclass, PY3, string_types,
39 )
38
40
39 if PY3:
41 if PY3:
40 from io import StringIO
42 from io import StringIO
41 else:
43 else:
42 from StringIO import StringIO
44 from StringIO import StringIO
43
45
44
46
45 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
46 # The main DisplayFormatter class
48 # The main DisplayFormatter class
47 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
48
50
49 _current = object()
50
51 class DisplayFormatter(Configurable):
51 class DisplayFormatter(Configurable):
52
52
53 # When set to true only the default plain text formatter will be used.
53 # When set to true only the default plain text formatter will be used.
54 plain_text_only = Bool(False, config=True)
54 plain_text_only = Bool(False, config=True)
55 def _plain_text_only_changed(self, name, old, new):
55 def _plain_text_only_changed(self, name, old, new):
56 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
56 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
57
57
58 Use DisplayFormatter.active_types = ['text/plain']
58 Use DisplayFormatter.active_types = ['text/plain']
59 for the same effect.
59 for the same effect.
60 """, DeprecationWarning)
60 """, DeprecationWarning)
61 if new:
61 if new:
62 self.active_types = ['text/plain']
62 self.active_types = ['text/plain']
63 else:
63 else:
64 self.active_types = self.format_types
64 self.active_types = self.format_types
65
65
66 active_types = List(Unicode, config=True,
66 active_types = List(Unicode, config=True,
67 help="""List of currently active mime-types to display.
67 help="""List of currently active mime-types to display.
68 You can use this to set a white-list for formats to display.
68 You can use this to set a white-list for formats to display.
69
69
70 Most users will not need to change this value.
70 Most users will not need to change this value.
71 """)
71 """)
72 def _active_types_default(self):
72 def _active_types_default(self):
73 return self.format_types
73 return self.format_types
74
74
75 def _active_types_changed(self, name, old, new):
75 def _active_types_changed(self, name, old, new):
76 for key, formatter in self.formatters.items():
76 for key, formatter in self.formatters.items():
77 if key in new:
77 if key in new:
78 formatter.enabled = True
78 formatter.enabled = True
79 else:
79 else:
80 formatter.enabled = False
80 formatter.enabled = False
81
81
82 # A dict of formatter whose keys are format types (MIME types) and whose
82 # A dict of formatter whose keys are format types (MIME types) and whose
83 # values are subclasses of BaseFormatter.
83 # values are subclasses of BaseFormatter.
84 formatters = Dict()
84 formatters = Dict()
85 def _formatters_default(self):
85 def _formatters_default(self):
86 """Activate the default formatters."""
86 """Activate the default formatters."""
87 formatter_classes = [
87 formatter_classes = [
88 PlainTextFormatter,
88 PlainTextFormatter,
89 HTMLFormatter,
89 HTMLFormatter,
90 SVGFormatter,
90 SVGFormatter,
91 PNGFormatter,
91 PNGFormatter,
92 JPEGFormatter,
92 JPEGFormatter,
93 LatexFormatter,
93 LatexFormatter,
94 JSONFormatter,
94 JSONFormatter,
95 JavascriptFormatter
95 JavascriptFormatter
96 ]
96 ]
97 d = {}
97 d = {}
98 for cls in formatter_classes:
98 for cls in formatter_classes:
99 f = cls(parent=self)
99 f = cls(parent=self)
100 d[f.format_type] = f
100 d[f.format_type] = f
101 return d
101 return d
102
102
103 def format(self, obj, include=None, exclude=None):
103 def format(self, obj, include=None, exclude=None):
104 """Return a format data dict for an object.
104 """Return a format data dict for an object.
105
105
106 By default all format types will be computed.
106 By default all format types will be computed.
107
107
108 The following MIME types are currently implemented:
108 The following MIME types are currently implemented:
109
109
110 * text/plain
110 * text/plain
111 * text/html
111 * text/html
112 * text/latex
112 * text/latex
113 * application/json
113 * application/json
114 * application/javascript
114 * application/javascript
115 * image/png
115 * image/png
116 * image/jpeg
116 * image/jpeg
117 * image/svg+xml
117 * image/svg+xml
118
118
119 Parameters
119 Parameters
120 ----------
120 ----------
121 obj : object
121 obj : object
122 The Python object whose format data will be computed.
122 The Python object whose format data will be computed.
123 include : list or tuple, optional
123 include : list or tuple, optional
124 A list of format type strings (MIME types) to include in the
124 A list of format type strings (MIME types) to include in the
125 format data dict. If this is set *only* the format types included
125 format data dict. If this is set *only* the format types included
126 in this list will be computed.
126 in this list will be computed.
127 exclude : list or tuple, optional
127 exclude : list or tuple, optional
128 A list of format type string (MIME types) to exclude in the format
128 A list of format type string (MIME types) to exclude in the format
129 data dict. If this is set all format types will be computed,
129 data dict. If this is set all format types will be computed,
130 except for those included in this argument.
130 except for those included in this argument.
131
131
132 Returns
132 Returns
133 -------
133 -------
134 (format_dict, metadata_dict) : tuple of two dicts
134 (format_dict, metadata_dict) : tuple of two dicts
135
135
136 format_dict is a dictionary of key/value pairs, one of each format that was
136 format_dict is a dictionary of key/value pairs, one of each format that was
137 generated for the object. The keys are the format types, which
137 generated for the object. The keys are the format types, which
138 will usually be MIME type strings and the values and JSON'able
138 will usually be MIME type strings and the values and JSON'able
139 data structure containing the raw data for the representation in
139 data structure containing the raw data for the representation in
140 that format.
140 that format.
141
141
142 metadata_dict is a dictionary of metadata about each mime-type output.
142 metadata_dict is a dictionary of metadata about each mime-type output.
143 Its keys will be a strict subset of the keys in format_dict.
143 Its keys will be a strict subset of the keys in format_dict.
144 """
144 """
145 format_dict = {}
145 format_dict = {}
146 md_dict = {}
146 md_dict = {}
147
147
148 for format_type, formatter in self.formatters.items():
148 for format_type, formatter in self.formatters.items():
149 if include and format_type not in include:
149 if include and format_type not in include:
150 continue
150 continue
151 if exclude and format_type in exclude:
151 if exclude and format_type in exclude:
152 continue
152 continue
153
153
154 md = None
154 md = None
155 try:
155 try:
156 data = formatter(obj)
156 data = formatter(obj)
157 except:
157 except:
158 # FIXME: log the exception
158 # FIXME: log the exception
159 raise
159 raise
160
160
161 # formatters can return raw data or (data, metadata)
161 # formatters can return raw data or (data, metadata)
162 if isinstance(data, tuple) and len(data) == 2:
162 if isinstance(data, tuple) and len(data) == 2:
163 data, md = data
163 data, md = data
164
164
165 if data is not None:
165 if data is not None:
166 format_dict[format_type] = data
166 format_dict[format_type] = data
167 if md is not None:
167 if md is not None:
168 md_dict[format_type] = md
168 md_dict[format_type] = md
169
169
170 return format_dict, md_dict
170 return format_dict, md_dict
171
171
172 @property
172 @property
173 def format_types(self):
173 def format_types(self):
174 """Return the format types (MIME types) of the active formatters."""
174 """Return the format types (MIME types) of the active formatters."""
175 return list(self.formatters.keys())
175 return list(self.formatters.keys())
176
176
177
177
178 #-----------------------------------------------------------------------------
178 #-----------------------------------------------------------------------------
179 # Formatters for specific format types (text, html, svg, etc.)
179 # Formatters for specific format types (text, html, svg, etc.)
180 #-----------------------------------------------------------------------------
180 #-----------------------------------------------------------------------------
181
181
182
182
183 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
183 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
184 """ Abstract base class for Formatters.
184 """ Abstract base class for Formatters.
185
185
186 A formatter is a callable class that is responsible for computing the
186 A formatter is a callable class that is responsible for computing the
187 raw format data for a particular format type (MIME type). For example,
187 raw format data for a particular format type (MIME type). For example,
188 an HTML formatter would have a format type of `text/html` and would return
188 an HTML formatter would have a format type of `text/html` and would return
189 the HTML representation of the object when called.
189 the HTML representation of the object when called.
190 """
190 """
191
191
192 # The format type of the data returned, usually a MIME type.
192 # The format type of the data returned, usually a MIME type.
193 format_type = 'text/plain'
193 format_type = 'text/plain'
194
194
195 # Is the formatter enabled...
195 # Is the formatter enabled...
196 enabled = True
196 enabled = True
197
197
198 @abc.abstractmethod
198 @abc.abstractmethod
199 def __call__(self, obj):
199 def __call__(self, obj):
200 """Return a JSON'able representation of the object.
200 """Return a JSON'able representation of the object.
201
201
202 If the object cannot be formatted by this formatter, then return None
202 If the object cannot be formatted by this formatter, then return None
203 """
203 """
204 try:
204 try:
205 return repr(obj)
205 return repr(obj)
206 except Exception:
206 except Exception:
207 return None
207 return None
208
208
209
209
210 def _mod_name_key(typ):
211 """Return a '__module__.__name__' string key for a type."""
212 module = getattr(typ, '__module__', None)
213 name = getattr(typ, '__name__', None)
214 return (module, name)
215
216
217 def _get_type(obj):
218 """Return the type of an instance (old and new-style)"""
219 return getattr(obj, '__class__', None) or type(obj)
220
221
210 class BaseFormatter(Configurable):
222 class BaseFormatter(Configurable):
211 """A base formatter class that is configurable.
223 """A base formatter class that is configurable.
212
224
213 This formatter should usually be used as the base class of all formatters.
225 This formatter should usually be used as the base class of all formatters.
214 It is a traited :class:`Configurable` class and includes an extensible
226 It is a traited :class:`Configurable` class and includes an extensible
215 API for users to determine how their objects are formatted. The following
227 API for users to determine how their objects are formatted. The following
216 logic is used to find a function to format an given object.
228 logic is used to find a function to format an given object.
217
229
218 1. The object is introspected to see if it has a method with the name
230 1. The object is introspected to see if it has a method with the name
219 :attr:`print_method`. If is does, that object is passed to that method
231 :attr:`print_method`. If is does, that object is passed to that method
220 for formatting.
232 for formatting.
221 2. If no print method is found, three internal dictionaries are consulted
233 2. If no print method is found, three internal dictionaries are consulted
222 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
234 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
223 and :attr:`deferred_printers`.
235 and :attr:`deferred_printers`.
224
236
225 Users should use these dictionaries to register functions that will be
237 Users should use these dictionaries to register functions that will be
226 used to compute the format data for their objects (if those objects don't
238 used to compute the format data for their objects (if those objects don't
227 have the special print methods). The easiest way of using these
239 have the special print methods). The easiest way of using these
228 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
240 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
229 methods.
241 methods.
230
242
231 If no function/callable is found to compute the format data, ``None`` is
243 If no function/callable is found to compute the format data, ``None`` is
232 returned and this format type is not used.
244 returned and this format type is not used.
233 """
245 """
234
246
235 format_type = Unicode('text/plain')
247 format_type = Unicode('text/plain')
236
248
237 enabled = Bool(True, config=True)
249 enabled = Bool(True, config=True)
238
250
239 print_method = ObjectName('__repr__')
251 print_method = ObjectName('__repr__')
240
252
241 # The singleton printers.
253 # The singleton printers.
242 # Maps the IDs of the builtin singleton objects to the format functions.
254 # Maps the IDs of the builtin singleton objects to the format functions.
243 singleton_printers = Dict(config=True)
255 singleton_printers = Dict(config=True)
244 def _singleton_printers_default(self):
245 return {}
246
256
247 # The type-specific printers.
257 # The type-specific printers.
248 # Map type objects to the format functions.
258 # Map type objects to the format functions.
249 type_printers = Dict(config=True)
259 type_printers = Dict(config=True)
250 def _type_printers_default(self):
251 return {}
252
260
253 # The deferred-import type-specific printers.
261 # The deferred-import type-specific printers.
254 # Map (modulename, classname) pairs to the format functions.
262 # Map (modulename, classname) pairs to the format functions.
255 deferred_printers = Dict(config=True)
263 deferred_printers = Dict(config=True)
256 def _deferred_printers_default(self):
257 return {}
258
264
259 def __call__(self, obj):
265 def __call__(self, obj):
260 """Compute the format for an object."""
266 """Compute the format for an object."""
261 if self.enabled:
267 if self.enabled:
262 obj_id = id(obj)
263 try:
268 try:
264 obj_class = getattr(obj, '__class__', None) or type(obj)
269 # lookup registered printer
265 # First try to find registered singleton printers for the type.
266 try:
270 try:
267 printer = self.singleton_printers[obj_id]
271 printer = self.lookup(obj)
268 except (TypeError, KeyError):
272 except KeyError:
269 pass
273 pass
270 else:
274 else:
271 return printer(obj)
275 return printer(obj)
272 # Next look for type_printers.
276 # Finally look for special method names
273 for cls in pretty._get_mro(obj_class):
277 method = pretty._safe_getattr(obj, self.print_method, None)
274 if cls in self.type_printers:
278 if method is not None:
275 return self.type_printers[cls](obj)
279 return method()
276 else:
277 printer = self._in_deferred_types(cls)
278 if printer is not None:
279 return printer(obj)
280 # Finally look for special method names.
281 if hasattr(obj_class, self.print_method):
282 printer = getattr(obj_class, self.print_method)
283 return printer(obj)
284 return None
280 return None
285 except Exception:
281 except Exception:
286 pass
282 pass
287 else:
283 else:
288 return None
284 return None
289
285
290 def for_type(self, typ, func=_current):
286 def lookup(self, obj):
287 """Look up the formatter for a given instance.
288
289 Parameters
290 ----------
291 obj : object instance
292
293 Returns
294 -------
295 f : callable
296 The registered fromatting callable for the type.
297
298 Raises
299 ------
300 KeyError if the type has not been registered.
301 """
302 # look for singleton first
303 obj_id = id(obj)
304 if obj_id in self.singleton_printers:
305 return self.singleton_printers[obj_id]
306 # then lookup by type
307 return self.lookup_by_type(_get_type(obj))
308
309 def lookup_by_type(self, typ):
310 """ Look up all the registered formatters for a type.
311
312 Parameters
313 ----------
314 typ : type
315
316 Returns
317 -------
318 f : callable
319 The registered fromatting callable for the type.
320
321 Raises
322 ------
323 KeyError if the type has not been registered.
324 """
325 for cls in pretty._get_mro(typ):
326 if cls in self.type_printers or self._in_deferred_types(cls):
327 return self.type_printers[cls]
328
329 # If we have reached here, the lookup failed.
330 raise KeyError("No registered printer for {0!r}".format(typ))
331
332 def for_type(self, typ, func=None):
291 """Add a format function for a given type.
333 """Add a format function for a given type.
292
334
293 Parameters
335 Parameters
294 -----------
336 -----------
295 typ : class
337 typ : class
296 The class of the object that will be formatted using `func`.
338 The class of the object that will be formatted using `func`.
297 func : callable
339 func : callable
298 A callable for computing the format data.
340 A callable for computing the format data.
299 `func` will be called with the object to be formatted,
341 `func` will be called with the object to be formatted,
300 and will return the raw data in this formatter's format.
342 and will return the raw data in this formatter's format.
301 Subclasses may use a different call signature for the
343 Subclasses may use a different call signature for the
302 `func` argument.
344 `func` argument.
303
345
304 If None is given, the current formatter for the type, if any,
346 If `func` is None or not specified, there will be no change,
305 will be cleared.
306
307 If `func` is not specified, there will be no change,
308 only returning the current value.
347 only returning the current value.
309
348
310 Returns
349 Returns
311 -------
350 -------
312 oldfunc : callable
351 oldfunc : callable
313 The currently registered callable.
352 The currently registered callable.
314 If you are registering a new formatter,
353 If you are registering a new formatter,
315 this will be the previous value (to enable restoring later).
354 this will be the previous value (to enable restoring later).
316 """
355 """
317 oldfunc = self.type_printers.get(typ, None)
356 # if string given, interpret as 'pkg.module.class_name'
318 if func is None:
357 if isinstance(typ, string_types):
319 self.type_printers.pop(typ, None)
358 type_module, type_name = typ.rsplit('.', 1)
320 elif func is not _current:
359 return self.for_type_by_name(type_module, type_name, func)
360
361 try:
362 oldfunc = self.lookup_by_type(typ)
363 except KeyError:
364 oldfunc = None
365
366 if func is not None:
321 self.type_printers[typ] = func
367 self.type_printers[typ] = func
368
322 return oldfunc
369 return oldfunc
323
370
324 def for_type_by_name(self, type_module, type_name, func=_current):
371 def for_type_by_name(self, type_module, type_name, func=None):
325 """Add a format function for a type specified by the full dotted
372 """Add a format function for a type specified by the full dotted
326 module and name of the type, rather than the type of the object.
373 module and name of the type, rather than the type of the object.
327
374
328 Parameters
375 Parameters
329 ----------
376 ----------
330 type_module : str
377 type_module : str
331 The full dotted name of the module the type is defined in, like
378 The full dotted name of the module the type is defined in, like
332 ``numpy``.
379 ``numpy``.
333 type_name : str
380 type_name : str
334 The name of the type (the class name), like ``dtype``
381 The name of the type (the class name), like ``dtype``
335 func : callable
382 func : callable
336 A callable for computing the format data.
383 A callable for computing the format data.
337 `func` will be called with the object to be formatted,
384 `func` will be called with the object to be formatted,
338 and will return the raw data in this formatter's format.
385 and will return the raw data in this formatter's format.
339 Subclasses may use a different call signature for the
386 Subclasses may use a different call signature for the
340 `func` argument.
387 `func` argument.
341
388
342 If None is given, the current formatter for the type, if any,
389 If `func` is None or unspecified, there will be no change,
343 will be cleared.
344
345 If `func` is not specified, there will be no change,
346 only returning the current value.
390 only returning the current value.
347
391
348 Returns
392 Returns
349 -------
393 -------
350 oldfunc : callable
394 oldfunc : callable
351 The currently registered callable.
395 The currently registered callable.
352 If you are registering a new formatter,
396 If you are registering a new formatter,
353 this will be the previous value (to enable restoring later).
397 this will be the previous value (to enable restoring later).
354 """
398 """
355 key = (type_module, type_name)
399 key = (type_module, type_name)
400
356 oldfunc = self.deferred_printers.get(key, None)
401 oldfunc = self.deferred_printers.get(key, None)
357 if func is None:
402 if func is not None:
358 self.deferred_printers.pop(key, None)
359 elif func is not _current:
360 self.deferred_printers[key] = func
403 self.deferred_printers[key] = func
361 return oldfunc
404 return oldfunc
362
405
406 def pop(self, typ):
407 """ Pop a registered object for the given type.
408
409 Parameters
410 ----------
411 typ : type or '__module__.__name__' string for a type
412
413 Returns
414 -------
415 obj : object
416 The last registered object for the type.
417
418 Raises
419 ------
420 KeyError if the type is not registered.
421 """
422 if isinstance(typ, string_types):
423 typ_key = tuple(typ.rsplit('.',1))
424 if typ_key not in self.deferred_printers:
425 # We may have it cached in the type map. We will have to
426 # iterate over all of the types to check.
427 for cls in self.type_printers:
428 if _mod_name_key(cls) == typ_key:
429 old = self.type_printers.pop(cls)
430 break
431 else:
432 raise KeyError("No registered value for {0!r}".format(typ_key))
433 else:
434 old = self.deferred_printers.pop(typ)
435 else:
436 if typ in self.type_printers:
437 old = self.type_printers.pop(typ)
438 else:
439 old = self.deferred_printers.pop(_mod_name_key(typ))
440 return old
441
363 def _in_deferred_types(self, cls):
442 def _in_deferred_types(self, cls):
364 """
443 """
365 Check if the given class is specified in the deferred type registry.
444 Check if the given class is specified in the deferred type registry.
366
445
367 Returns the printer from the registry if it exists, and None if the
446 Successful matches will be moved to the regular type registry for future use.
368 class is not in the registry. Successful matches will be moved to the
369 regular type registry for future use.
370 """
447 """
371 mod = getattr(cls, '__module__', None)
448 mod = getattr(cls, '__module__', None)
372 name = getattr(cls, '__name__', None)
449 name = getattr(cls, '__name__', None)
373 key = (mod, name)
450 key = (mod, name)
374 printer = None
375 if key in self.deferred_printers:
451 if key in self.deferred_printers:
376 # Move the printer over to the regular registry.
452 # Move the printer over to the regular registry.
377 printer = self.deferred_printers.pop(key)
453 printer = self.deferred_printers.pop(key)
378 self.type_printers[cls] = printer
454 self.type_printers[cls] = printer
379 return printer
455 return True
456 return False
380
457
381
458
382 class PlainTextFormatter(BaseFormatter):
459 class PlainTextFormatter(BaseFormatter):
383 """The default pretty-printer.
460 """The default pretty-printer.
384
461
385 This uses :mod:`IPython.lib.pretty` to compute the format data of
462 This uses :mod:`IPython.lib.pretty` to compute the format data of
386 the object. If the object cannot be pretty printed, :func:`repr` is used.
463 the object. If the object cannot be pretty printed, :func:`repr` is used.
387 See the documentation of :mod:`IPython.lib.pretty` for details on
464 See the documentation of :mod:`IPython.lib.pretty` for details on
388 how to write pretty printers. Here is a simple example::
465 how to write pretty printers. Here is a simple example::
389
466
390 def dtype_pprinter(obj, p, cycle):
467 def dtype_pprinter(obj, p, cycle):
391 if cycle:
468 if cycle:
392 return p.text('dtype(...)')
469 return p.text('dtype(...)')
393 if hasattr(obj, 'fields'):
470 if hasattr(obj, 'fields'):
394 if obj.fields is None:
471 if obj.fields is None:
395 p.text(repr(obj))
472 p.text(repr(obj))
396 else:
473 else:
397 p.begin_group(7, 'dtype([')
474 p.begin_group(7, 'dtype([')
398 for i, field in enumerate(obj.descr):
475 for i, field in enumerate(obj.descr):
399 if i > 0:
476 if i > 0:
400 p.text(',')
477 p.text(',')
401 p.breakable()
478 p.breakable()
402 p.pretty(field)
479 p.pretty(field)
403 p.end_group(7, '])')
480 p.end_group(7, '])')
404 """
481 """
405
482
406 # The format type of data returned.
483 # The format type of data returned.
407 format_type = Unicode('text/plain')
484 format_type = Unicode('text/plain')
408
485
409 # This subclass ignores this attribute as it always need to return
486 # This subclass ignores this attribute as it always need to return
410 # something.
487 # something.
411 enabled = Bool(True, config=False)
488 enabled = Bool(True, config=False)
412
489
413 # Look for a _repr_pretty_ methods to use for pretty printing.
490 # Look for a _repr_pretty_ methods to use for pretty printing.
414 print_method = ObjectName('_repr_pretty_')
491 print_method = ObjectName('_repr_pretty_')
415
492
416 # Whether to pretty-print or not.
493 # Whether to pretty-print or not.
417 pprint = Bool(True, config=True)
494 pprint = Bool(True, config=True)
418
495
419 # Whether to be verbose or not.
496 # Whether to be verbose or not.
420 verbose = Bool(False, config=True)
497 verbose = Bool(False, config=True)
421
498
422 # The maximum width.
499 # The maximum width.
423 max_width = Integer(79, config=True)
500 max_width = Integer(79, config=True)
424
501
425 # The newline character.
502 # The newline character.
426 newline = Unicode('\n', config=True)
503 newline = Unicode('\n', config=True)
427
504
428 # format-string for pprinting floats
505 # format-string for pprinting floats
429 float_format = Unicode('%r')
506 float_format = Unicode('%r')
430 # setter for float precision, either int or direct format-string
507 # setter for float precision, either int or direct format-string
431 float_precision = CUnicode('', config=True)
508 float_precision = CUnicode('', config=True)
432
509
433 def _float_precision_changed(self, name, old, new):
510 def _float_precision_changed(self, name, old, new):
434 """float_precision changed, set float_format accordingly.
511 """float_precision changed, set float_format accordingly.
435
512
436 float_precision can be set by int or str.
513 float_precision can be set by int or str.
437 This will set float_format, after interpreting input.
514 This will set float_format, after interpreting input.
438 If numpy has been imported, numpy print precision will also be set.
515 If numpy has been imported, numpy print precision will also be set.
439
516
440 integer `n` sets format to '%.nf', otherwise, format set directly.
517 integer `n` sets format to '%.nf', otherwise, format set directly.
441
518
442 An empty string returns to defaults (repr for float, 8 for numpy).
519 An empty string returns to defaults (repr for float, 8 for numpy).
443
520
444 This parameter can be set via the '%precision' magic.
521 This parameter can be set via the '%precision' magic.
445 """
522 """
446
523
447 if '%' in new:
524 if '%' in new:
448 # got explicit format string
525 # got explicit format string
449 fmt = new
526 fmt = new
450 try:
527 try:
451 fmt%3.14159
528 fmt%3.14159
452 except Exception:
529 except Exception:
453 raise ValueError("Precision must be int or format string, not %r"%new)
530 raise ValueError("Precision must be int or format string, not %r"%new)
454 elif new:
531 elif new:
455 # otherwise, should be an int
532 # otherwise, should be an int
456 try:
533 try:
457 i = int(new)
534 i = int(new)
458 assert i >= 0
535 assert i >= 0
459 except ValueError:
536 except ValueError:
460 raise ValueError("Precision must be int or format string, not %r"%new)
537 raise ValueError("Precision must be int or format string, not %r"%new)
461 except AssertionError:
538 except AssertionError:
462 raise ValueError("int precision must be non-negative, not %r"%i)
539 raise ValueError("int precision must be non-negative, not %r"%i)
463
540
464 fmt = '%%.%if'%i
541 fmt = '%%.%if'%i
465 if 'numpy' in sys.modules:
542 if 'numpy' in sys.modules:
466 # set numpy precision if it has been imported
543 # set numpy precision if it has been imported
467 import numpy
544 import numpy
468 numpy.set_printoptions(precision=i)
545 numpy.set_printoptions(precision=i)
469 else:
546 else:
470 # default back to repr
547 # default back to repr
471 fmt = '%r'
548 fmt = '%r'
472 if 'numpy' in sys.modules:
549 if 'numpy' in sys.modules:
473 import numpy
550 import numpy
474 # numpy default is 8
551 # numpy default is 8
475 numpy.set_printoptions(precision=8)
552 numpy.set_printoptions(precision=8)
476 self.float_format = fmt
553 self.float_format = fmt
477
554
478 # Use the default pretty printers from IPython.lib.pretty.
555 # Use the default pretty printers from IPython.lib.pretty.
479 def _singleton_printers_default(self):
556 def _singleton_printers_default(self):
480 return pretty._singleton_pprinters.copy()
557 return pretty._singleton_pprinters.copy()
481
558
482 def _type_printers_default(self):
559 def _type_printers_default(self):
483 d = pretty._type_pprinters.copy()
560 d = pretty._type_pprinters.copy()
484 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
561 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
485 return d
562 return d
486
563
487 def _deferred_printers_default(self):
564 def _deferred_printers_default(self):
488 return pretty._deferred_type_pprinters.copy()
565 return pretty._deferred_type_pprinters.copy()
489
566
490 #### FormatterABC interface ####
567 #### FormatterABC interface ####
491
568
492 def __call__(self, obj):
569 def __call__(self, obj):
493 """Compute the pretty representation of the object."""
570 """Compute the pretty representation of the object."""
494 if not self.pprint:
571 if not self.pprint:
495 return pretty._safe_repr(obj)
572 return pretty._safe_repr(obj)
496 else:
573 else:
497 # This uses use StringIO, as cStringIO doesn't handle unicode.
574 # This uses use StringIO, as cStringIO doesn't handle unicode.
498 stream = StringIO()
575 stream = StringIO()
499 # self.newline.encode() is a quick fix for issue gh-597. We need to
576 # self.newline.encode() is a quick fix for issue gh-597. We need to
500 # ensure that stream does not get a mix of unicode and bytestrings,
577 # ensure that stream does not get a mix of unicode and bytestrings,
501 # or it will cause trouble.
578 # or it will cause trouble.
502 printer = pretty.RepresentationPrinter(stream, self.verbose,
579 printer = pretty.RepresentationPrinter(stream, self.verbose,
503 self.max_width, unicode_to_str(self.newline),
580 self.max_width, unicode_to_str(self.newline),
504 singleton_pprinters=self.singleton_printers,
581 singleton_pprinters=self.singleton_printers,
505 type_pprinters=self.type_printers,
582 type_pprinters=self.type_printers,
506 deferred_pprinters=self.deferred_printers)
583 deferred_pprinters=self.deferred_printers)
507 printer.pretty(obj)
584 printer.pretty(obj)
508 printer.flush()
585 printer.flush()
509 return stream.getvalue()
586 return stream.getvalue()
510
587
511
588
512 class HTMLFormatter(BaseFormatter):
589 class HTMLFormatter(BaseFormatter):
513 """An HTML formatter.
590 """An HTML formatter.
514
591
515 To define the callables that compute the HTML representation of your
592 To define the callables that compute the HTML representation of your
516 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
593 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
517 or :meth:`for_type_by_name` methods to register functions that handle
594 or :meth:`for_type_by_name` methods to register functions that handle
518 this.
595 this.
519
596
520 The return value of this formatter should be a valid HTML snippet that
597 The return value of this formatter should be a valid HTML snippet that
521 could be injected into an existing DOM. It should *not* include the
598 could be injected into an existing DOM. It should *not* include the
522 ```<html>`` or ```<body>`` tags.
599 ```<html>`` or ```<body>`` tags.
523 """
600 """
524 format_type = Unicode('text/html')
601 format_type = Unicode('text/html')
525
602
526 print_method = ObjectName('_repr_html_')
603 print_method = ObjectName('_repr_html_')
527
604
528
605
529 class SVGFormatter(BaseFormatter):
606 class SVGFormatter(BaseFormatter):
530 """An SVG formatter.
607 """An SVG formatter.
531
608
532 To define the callables that compute the SVG representation of your
609 To define the callables that compute the SVG representation of your
533 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
610 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
534 or :meth:`for_type_by_name` methods to register functions that handle
611 or :meth:`for_type_by_name` methods to register functions that handle
535 this.
612 this.
536
613
537 The return value of this formatter should be valid SVG enclosed in
614 The return value of this formatter should be valid SVG enclosed in
538 ```<svg>``` tags, that could be injected into an existing DOM. It should
615 ```<svg>``` tags, that could be injected into an existing DOM. It should
539 *not* include the ```<html>`` or ```<body>`` tags.
616 *not* include the ```<html>`` or ```<body>`` tags.
540 """
617 """
541 format_type = Unicode('image/svg+xml')
618 format_type = Unicode('image/svg+xml')
542
619
543 print_method = ObjectName('_repr_svg_')
620 print_method = ObjectName('_repr_svg_')
544
621
545
622
546 class PNGFormatter(BaseFormatter):
623 class PNGFormatter(BaseFormatter):
547 """A PNG formatter.
624 """A PNG formatter.
548
625
549 To define the callables that compute the PNG representation of your
626 To define the callables that compute the PNG representation of your
550 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
627 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
551 or :meth:`for_type_by_name` methods to register functions that handle
628 or :meth:`for_type_by_name` methods to register functions that handle
552 this.
629 this.
553
630
554 The return value of this formatter should be raw PNG data, *not*
631 The return value of this formatter should be raw PNG data, *not*
555 base64 encoded.
632 base64 encoded.
556 """
633 """
557 format_type = Unicode('image/png')
634 format_type = Unicode('image/png')
558
635
559 print_method = ObjectName('_repr_png_')
636 print_method = ObjectName('_repr_png_')
560
637
561
638
562 class JPEGFormatter(BaseFormatter):
639 class JPEGFormatter(BaseFormatter):
563 """A JPEG formatter.
640 """A JPEG formatter.
564
641
565 To define the callables that compute the JPEG representation of your
642 To define the callables that compute the JPEG representation of your
566 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
643 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
567 or :meth:`for_type_by_name` methods to register functions that handle
644 or :meth:`for_type_by_name` methods to register functions that handle
568 this.
645 this.
569
646
570 The return value of this formatter should be raw JPEG data, *not*
647 The return value of this formatter should be raw JPEG data, *not*
571 base64 encoded.
648 base64 encoded.
572 """
649 """
573 format_type = Unicode('image/jpeg')
650 format_type = Unicode('image/jpeg')
574
651
575 print_method = ObjectName('_repr_jpeg_')
652 print_method = ObjectName('_repr_jpeg_')
576
653
577
654
578 class LatexFormatter(BaseFormatter):
655 class LatexFormatter(BaseFormatter):
579 """A LaTeX formatter.
656 """A LaTeX formatter.
580
657
581 To define the callables that compute the LaTeX representation of your
658 To define the callables that compute the LaTeX representation of your
582 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
659 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
583 or :meth:`for_type_by_name` methods to register functions that handle
660 or :meth:`for_type_by_name` methods to register functions that handle
584 this.
661 this.
585
662
586 The return value of this formatter should be a valid LaTeX equation,
663 The return value of this formatter should be a valid LaTeX equation,
587 enclosed in either ```$```, ```$$``` or another LaTeX equation
664 enclosed in either ```$```, ```$$``` or another LaTeX equation
588 environment.
665 environment.
589 """
666 """
590 format_type = Unicode('text/latex')
667 format_type = Unicode('text/latex')
591
668
592 print_method = ObjectName('_repr_latex_')
669 print_method = ObjectName('_repr_latex_')
593
670
594
671
595 class JSONFormatter(BaseFormatter):
672 class JSONFormatter(BaseFormatter):
596 """A JSON string formatter.
673 """A JSON string formatter.
597
674
598 To define the callables that compute the JSON string representation of
675 To define the callables that compute the JSON string representation of
599 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
676 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
600 or :meth:`for_type_by_name` methods to register functions that handle
677 or :meth:`for_type_by_name` methods to register functions that handle
601 this.
678 this.
602
679
603 The return value of this formatter should be a valid JSON string.
680 The return value of this formatter should be a valid JSON string.
604 """
681 """
605 format_type = Unicode('application/json')
682 format_type = Unicode('application/json')
606
683
607 print_method = ObjectName('_repr_json_')
684 print_method = ObjectName('_repr_json_')
608
685
609
686
610 class JavascriptFormatter(BaseFormatter):
687 class JavascriptFormatter(BaseFormatter):
611 """A Javascript formatter.
688 """A Javascript formatter.
612
689
613 To define the callables that compute the Javascript representation of
690 To define the callables that compute the Javascript representation of
614 your objects, define a :meth:`_repr_javascript_` method or use the
691 your objects, define a :meth:`_repr_javascript_` method or use the
615 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
692 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
616 that handle this.
693 that handle this.
617
694
618 The return value of this formatter should be valid Javascript code and
695 The return value of this formatter should be valid Javascript code and
619 should *not* be enclosed in ```<script>``` tags.
696 should *not* be enclosed in ```<script>``` tags.
620 """
697 """
621 format_type = Unicode('application/javascript')
698 format_type = Unicode('application/javascript')
622
699
623 print_method = ObjectName('_repr_javascript_')
700 print_method = ObjectName('_repr_javascript_')
624
701
625 FormatterABC.register(BaseFormatter)
702 FormatterABC.register(BaseFormatter)
626 FormatterABC.register(PlainTextFormatter)
703 FormatterABC.register(PlainTextFormatter)
627 FormatterABC.register(HTMLFormatter)
704 FormatterABC.register(HTMLFormatter)
628 FormatterABC.register(SVGFormatter)
705 FormatterABC.register(SVGFormatter)
629 FormatterABC.register(PNGFormatter)
706 FormatterABC.register(PNGFormatter)
630 FormatterABC.register(JPEGFormatter)
707 FormatterABC.register(JPEGFormatter)
631 FormatterABC.register(LatexFormatter)
708 FormatterABC.register(LatexFormatter)
632 FormatterABC.register(JSONFormatter)
709 FormatterABC.register(JSONFormatter)
633 FormatterABC.register(JavascriptFormatter)
710 FormatterABC.register(JavascriptFormatter)
634
711
635
712
636 def format_display_data(obj, include=None, exclude=None):
713 def format_display_data(obj, include=None, exclude=None):
637 """Return a format data dict for an object.
714 """Return a format data dict for an object.
638
715
639 By default all format types will be computed.
716 By default all format types will be computed.
640
717
641 The following MIME types are currently implemented:
718 The following MIME types are currently implemented:
642
719
643 * text/plain
720 * text/plain
644 * text/html
721 * text/html
645 * text/latex
722 * text/latex
646 * application/json
723 * application/json
647 * application/javascript
724 * application/javascript
648 * image/png
725 * image/png
649 * image/jpeg
726 * image/jpeg
650 * image/svg+xml
727 * image/svg+xml
651
728
652 Parameters
729 Parameters
653 ----------
730 ----------
654 obj : object
731 obj : object
655 The Python object whose format data will be computed.
732 The Python object whose format data will be computed.
656
733
657 Returns
734 Returns
658 -------
735 -------
659 format_dict : dict
736 format_dict : dict
660 A dictionary of key/value pairs, one or each format that was
737 A dictionary of key/value pairs, one or each format that was
661 generated for the object. The keys are the format types, which
738 generated for the object. The keys are the format types, which
662 will usually be MIME type strings and the values and JSON'able
739 will usually be MIME type strings and the values and JSON'able
663 data structure containing the raw data for the representation in
740 data structure containing the raw data for the representation in
664 that format.
741 that format.
665 include : list or tuple, optional
742 include : list or tuple, optional
666 A list of format type strings (MIME types) to include in the
743 A list of format type strings (MIME types) to include in the
667 format data dict. If this is set *only* the format types included
744 format data dict. If this is set *only* the format types included
668 in this list will be computed.
745 in this list will be computed.
669 exclude : list or tuple, optional
746 exclude : list or tuple, optional
670 A list of format type string (MIME types) to exclue in the format
747 A list of format type string (MIME types) to exclue in the format
671 data dict. If this is set all format types will be computed,
748 data dict. If this is set all format types will be computed,
672 except for those included in this argument.
749 except for those included in this argument.
673 """
750 """
674 from IPython.core.interactiveshell import InteractiveShell
751 from IPython.core.interactiveshell import InteractiveShell
675
752
676 InteractiveShell.instance().display_formatter.format(
753 InteractiveShell.instance().display_formatter.format(
677 obj,
754 obj,
678 include,
755 include,
679 exclude
756 exclude
680 )
757 )
681
758
@@ -1,134 +1,153 b''
1 """Tests for the Formatters.
1 """Tests for the Formatters.
2 """
2 """
3
3
4 from math import pi
4 from math import pi
5
5
6 try:
6 try:
7 import numpy
7 import numpy
8 except:
8 except:
9 numpy = None
9 numpy = None
10 import nose.tools as nt
10 import nose.tools as nt
11
11
12 from IPython.core.formatters import PlainTextFormatter
12 from IPython.core.formatters import PlainTextFormatter, _mod_name_key
13
13
14 class A(object):
14 class A(object):
15 def __repr__(self):
15 def __repr__(self):
16 return 'A()'
16 return 'A()'
17
17
18 class B(A):
18 class B(A):
19 def __repr__(self):
19 def __repr__(self):
20 return 'B()'
20 return 'B()'
21
21
22 class C:
23 pass
24
22 class BadPretty(object):
25 class BadPretty(object):
23 _repr_pretty_ = None
26 _repr_pretty_ = None
24
27
25 class GoodPretty(object):
28 class GoodPretty(object):
26 def _repr_pretty_(self, pp, cycle):
29 def _repr_pretty_(self, pp, cycle):
27 pp.text('foo')
30 pp.text('foo')
28
31
29 def __repr__(self):
32 def __repr__(self):
30 return 'GoodPretty()'
33 return 'GoodPretty()'
31
34
32 def foo_printer(obj, pp, cycle):
35 def foo_printer(obj, pp, cycle):
33 pp.text('foo')
36 pp.text('foo')
34
37
35 def test_pretty():
38 def test_pretty():
36 f = PlainTextFormatter()
39 f = PlainTextFormatter()
37 f.for_type(A, foo_printer)
40 f.for_type(A, foo_printer)
38 nt.assert_equal(f(A()), 'foo')
41 nt.assert_equal(f(A()), 'foo')
39 nt.assert_equal(f(B()), 'foo')
42 nt.assert_equal(f(B()), 'foo')
40 nt.assert_equal(f(GoodPretty()), 'foo')
43 nt.assert_equal(f(GoodPretty()), 'foo')
41 # Just don't raise an exception for the following:
44 # Just don't raise an exception for the following:
42 f(BadPretty())
45 f(BadPretty())
43
46
44 f.pprint = False
47 f.pprint = False
45 nt.assert_equal(f(A()), 'A()')
48 nt.assert_equal(f(A()), 'A()')
46 nt.assert_equal(f(B()), 'B()')
49 nt.assert_equal(f(B()), 'B()')
47 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
50 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
48
51
49
52
50 def test_deferred():
53 def test_deferred():
51 f = PlainTextFormatter()
54 f = PlainTextFormatter()
52
55
53 def test_precision():
56 def test_precision():
54 """test various values for float_precision."""
57 """test various values for float_precision."""
55 f = PlainTextFormatter()
58 f = PlainTextFormatter()
56 nt.assert_equal(f(pi), repr(pi))
59 nt.assert_equal(f(pi), repr(pi))
57 f.float_precision = 0
60 f.float_precision = 0
58 if numpy:
61 if numpy:
59 po = numpy.get_printoptions()
62 po = numpy.get_printoptions()
60 nt.assert_equal(po['precision'], 0)
63 nt.assert_equal(po['precision'], 0)
61 nt.assert_equal(f(pi), '3')
64 nt.assert_equal(f(pi), '3')
62 f.float_precision = 2
65 f.float_precision = 2
63 if numpy:
66 if numpy:
64 po = numpy.get_printoptions()
67 po = numpy.get_printoptions()
65 nt.assert_equal(po['precision'], 2)
68 nt.assert_equal(po['precision'], 2)
66 nt.assert_equal(f(pi), '3.14')
69 nt.assert_equal(f(pi), '3.14')
67 f.float_precision = '%g'
70 f.float_precision = '%g'
68 if numpy:
71 if numpy:
69 po = numpy.get_printoptions()
72 po = numpy.get_printoptions()
70 nt.assert_equal(po['precision'], 2)
73 nt.assert_equal(po['precision'], 2)
71 nt.assert_equal(f(pi), '3.14159')
74 nt.assert_equal(f(pi), '3.14159')
72 f.float_precision = '%e'
75 f.float_precision = '%e'
73 nt.assert_equal(f(pi), '3.141593e+00')
76 nt.assert_equal(f(pi), '3.141593e+00')
74 f.float_precision = ''
77 f.float_precision = ''
75 if numpy:
78 if numpy:
76 po = numpy.get_printoptions()
79 po = numpy.get_printoptions()
77 nt.assert_equal(po['precision'], 8)
80 nt.assert_equal(po['precision'], 8)
78 nt.assert_equal(f(pi), repr(pi))
81 nt.assert_equal(f(pi), repr(pi))
79
82
80 def test_bad_precision():
83 def test_bad_precision():
81 """test various invalid values for float_precision."""
84 """test various invalid values for float_precision."""
82 f = PlainTextFormatter()
85 f = PlainTextFormatter()
83 def set_fp(p):
86 def set_fp(p):
84 f.float_precision=p
87 f.float_precision=p
85 nt.assert_raises(ValueError, set_fp, '%')
88 nt.assert_raises(ValueError, set_fp, '%')
86 nt.assert_raises(ValueError, set_fp, '%.3f%i')
89 nt.assert_raises(ValueError, set_fp, '%.3f%i')
87 nt.assert_raises(ValueError, set_fp, 'foo')
90 nt.assert_raises(ValueError, set_fp, 'foo')
88 nt.assert_raises(ValueError, set_fp, -1)
91 nt.assert_raises(ValueError, set_fp, -1)
89
92
90
93
91 def test_for_type():
94 def test_for_type():
92 f = PlainTextFormatter()
95 f = PlainTextFormatter()
93 class C():
94 pass
95
96 def foo(c, p, cycle):
97 p.text('C')
98
96
99 # initial return is None
97 # initial return is None
100 assert f.for_type(C, foo) is None
98 assert f.for_type(C, foo_printer) is None
101 # no func queries
99 # no func queries
102 assert f.for_type(C) is foo
100 assert f.for_type(C) is foo_printer
103 # shouldn't change anything
101 # shouldn't change anything
104 assert f.for_type(C) is foo
102 assert f.for_type(C) is foo_printer
105 # None should clear and return foo
103 # None should do the same
106 assert f.for_type(C, None) is foo
104 assert f.for_type(C, None) is foo_printer
107 # verify clear
105 assert f.for_type(C, None) is foo_printer
108 assert C not in f.type_printers
109 assert f.for_type(C) is None
110
106
111
107
112 def test_for_type_by_name():
108 def test_for_type_string():
113 f = PlainTextFormatter()
109 f = PlainTextFormatter()
114 class C():
115 pass
116
110
117 mod = C.__module__
111 mod = C.__module__
118
112
119 def foo(c, p, cycle):
113 type_str = '%s.%s' % (C.__module__, 'C')
120 p.text('C')
121
114
122 # initial return is None
115 # initial return is None
123 assert f.for_type_by_name(mod, 'C', foo) is None
116 assert f.for_type(type_str, foo_printer) is None
124 # no func queries
117 # no func queries
125 assert f.for_type_by_name(mod, 'C') is foo
118 assert f.for_type(type_str) is foo_printer
119 assert _mod_name_key(C) in f.deferred_printers
120 assert f.for_type(C) is foo_printer
121 assert _mod_name_key(C) not in f.deferred_printers
122 assert C in f.type_printers
123
124
125 def test_for_type_by_name():
126 f = PlainTextFormatter()
127
128 mod = C.__module__
129
130 # initial return is None
131 assert f.for_type_by_name(mod, 'C', foo_printer) is None
132 # no func queries
133 assert f.for_type_by_name(mod, 'C') is foo_printer
126 # shouldn't change anything
134 # shouldn't change anything
127 assert f.for_type_by_name(mod, 'C') is foo
135 assert f.for_type_by_name(mod, 'C') is foo_printer
128 # None should clear and return foo
136 # None should do the same
129 assert f.for_type_by_name(mod, 'C', None) is foo
137 assert f.for_type_by_name(mod, 'C', None) is foo_printer
130 # verify clear
138 assert f.for_type_by_name(mod, 'C', None) is foo_printer
131 assert (mod, 'C') not in f.deferred_printers
139
132 assert f.for_type_by_name(mod, 'C') is None
140
141 def test_lookup():
142 f = PlainTextFormatter()
133
143
144 mod = C.__module__
145 c = C()
146
147 type_str = '%s.%s' % (C.__module__, 'C')
148
149 # initial return is None
150 assert f.for_type(type_str, foo_printer) is None
151 # no func queries
152 assert f.lookup(c) is foo_printer
134
153
General Comments 0
You need to be logged in to leave comments. Login now