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