Show More
@@ -208,7 +208,10 b' class FormatterABC(with_metaclass(abc.ABCMeta, object)):' | |||||
208 |
|
208 | |||
209 |
|
209 | |||
210 | def _mod_name_key(typ): |
|
210 | def _mod_name_key(typ): | |
211 |
"""Return a |
|
211 | """Return a (__module__, __name__) tuple for a type. | |
|
212 | ||||
|
213 | Used as key in Formatter.deferred_printers. | |||
|
214 | """ | |||
212 | module = getattr(typ, '__module__', None) |
|
215 | module = getattr(typ, '__module__', None) | |
213 | name = getattr(typ, '__name__', None) |
|
216 | name = getattr(typ, '__name__', None) | |
214 | return (module, name) |
|
217 | return (module, name) | |
@@ -218,6 +221,7 b' def _get_type(obj):' | |||||
218 | """Return the type of an instance (old and new-style)""" |
|
221 | """Return the type of an instance (old and new-style)""" | |
219 | return getattr(obj, '__class__', None) or type(obj) |
|
222 | return getattr(obj, '__class__', None) or type(obj) | |
220 |
|
223 | |||
|
224 | _raise_key_error = object() | |||
221 |
|
225 | |||
222 | class BaseFormatter(Configurable): |
|
226 | class BaseFormatter(Configurable): | |
223 | """A base formatter class that is configurable. |
|
227 | """A base formatter class that is configurable. | |
@@ -283,6 +287,15 b' class BaseFormatter(Configurable):' | |||||
283 | else: |
|
287 | else: | |
284 | return None |
|
288 | return None | |
285 |
|
289 | |||
|
290 | def __contains__(self, typ): | |||
|
291 | """map in to lookup_by_type""" | |||
|
292 | try: | |||
|
293 | self.lookup_by_type(typ) | |||
|
294 | except KeyError: | |||
|
295 | return False | |||
|
296 | else: | |||
|
297 | return True | |||
|
298 | ||||
286 | def lookup(self, obj): |
|
299 | def lookup(self, obj): | |
287 | """Look up the formatter for a given instance. |
|
300 | """Look up the formatter for a given instance. | |
288 |
|
301 | |||
@@ -293,7 +306,7 b' class BaseFormatter(Configurable):' | |||||
293 | Returns |
|
306 | Returns | |
294 | ------- |
|
307 | ------- | |
295 | f : callable |
|
308 | f : callable | |
296 |
The registered f |
|
309 | The registered formatting callable for the type. | |
297 |
|
310 | |||
298 | Raises |
|
311 | Raises | |
299 | ------ |
|
312 | ------ | |
@@ -307,7 +320,7 b' class BaseFormatter(Configurable):' | |||||
307 | return self.lookup_by_type(_get_type(obj)) |
|
320 | return self.lookup_by_type(_get_type(obj)) | |
308 |
|
321 | |||
309 | def lookup_by_type(self, typ): |
|
322 | def lookup_by_type(self, typ): | |
310 |
""" |
|
323 | """Look up the registered formatter for a type. | |
311 |
|
324 | |||
312 | Parameters |
|
325 | Parameters | |
313 | ---------- |
|
326 | ---------- | |
@@ -316,15 +329,26 b' class BaseFormatter(Configurable):' | |||||
316 | Returns |
|
329 | Returns | |
317 | ------- |
|
330 | ------- | |
318 | f : callable |
|
331 | f : callable | |
319 |
The registered f |
|
332 | The registered formatting callable for the type. | |
320 |
|
333 | |||
321 | Raises |
|
334 | Raises | |
322 | ------ |
|
335 | ------ | |
323 | KeyError if the type has not been registered. |
|
336 | KeyError if the type has not been registered. | |
324 | """ |
|
337 | """ | |
325 | for cls in pretty._get_mro(typ): |
|
338 | if isinstance(typ, string_types): | |
326 | if cls in self.type_printers or self._in_deferred_types(cls): |
|
339 | typ_key = tuple(typ.rsplit('.',1)) | |
327 |
|
|
340 | if typ_key not in self.deferred_printers: | |
|
341 | # We may have it cached in the type map. We will have to | |||
|
342 | # iterate over all of the types to check. | |||
|
343 | for cls in self.type_printers: | |||
|
344 | if _mod_name_key(cls) == typ_key: | |||
|
345 | return self.type_printers[cls] | |||
|
346 | else: | |||
|
347 | return self.deferred_printers[typ_key] | |||
|
348 | else: | |||
|
349 | for cls in pretty._get_mro(typ): | |||
|
350 | if cls in self.type_printers or self._in_deferred_types(cls): | |||
|
351 | return self.type_printers[cls] | |||
328 |
|
352 | |||
329 | # If we have reached here, the lookup failed. |
|
353 | # If we have reached here, the lookup failed. | |
330 | raise KeyError("No registered printer for {0!r}".format(typ)) |
|
354 | raise KeyError("No registered printer for {0!r}".format(typ)) | |
@@ -398,17 +422,23 b' class BaseFormatter(Configurable):' | |||||
398 | """ |
|
422 | """ | |
399 | key = (type_module, type_name) |
|
423 | key = (type_module, type_name) | |
400 |
|
424 | |||
401 | oldfunc = self.deferred_printers.get(key, None) |
|
425 | try: | |
|
426 | oldfunc = self.lookup_by_type("%s.%s" % key) | |||
|
427 | except KeyError: | |||
|
428 | oldfunc = None | |||
|
429 | ||||
402 | if func is not None: |
|
430 | if func is not None: | |
403 | self.deferred_printers[key] = func |
|
431 | self.deferred_printers[key] = func | |
404 | return oldfunc |
|
432 | return oldfunc | |
405 |
|
433 | |||
406 | def pop(self, typ): |
|
434 | def pop(self, typ, default=_raise_key_error): | |
407 |
""" |
|
435 | """Pop a formatter for the given type. | |
408 |
|
436 | |||
409 | Parameters |
|
437 | Parameters | |
410 | ---------- |
|
438 | ---------- | |
411 | typ : type or '__module__.__name__' string for a type |
|
439 | typ : type or '__module__.__name__' string for a type | |
|
440 | default : object | |||
|
441 | value to be returned if no formatter is registered for typ. | |||
412 |
|
442 | |||
413 | Returns |
|
443 | Returns | |
414 | ------- |
|
444 | ------- | |
@@ -417,8 +447,9 b' class BaseFormatter(Configurable):' | |||||
417 |
|
447 | |||
418 | Raises |
|
448 | Raises | |
419 | ------ |
|
449 | ------ | |
420 | KeyError if the type is not registered. |
|
450 | KeyError if the type is not registered and default is not specified. | |
421 | """ |
|
451 | """ | |
|
452 | ||||
422 | if isinstance(typ, string_types): |
|
453 | if isinstance(typ, string_types): | |
423 | typ_key = tuple(typ.rsplit('.',1)) |
|
454 | typ_key = tuple(typ.rsplit('.',1)) | |
424 | if typ_key not in self.deferred_printers: |
|
455 | if typ_key not in self.deferred_printers: | |
@@ -429,14 +460,16 b' class BaseFormatter(Configurable):' | |||||
429 | old = self.type_printers.pop(cls) |
|
460 | old = self.type_printers.pop(cls) | |
430 | break |
|
461 | break | |
431 | else: |
|
462 | else: | |
432 | raise KeyError("No registered value for {0!r}".format(typ_key)) |
|
463 | old = default | |
433 | else: |
|
464 | else: | |
434 | old = self.deferred_printers.pop(typ_key) |
|
465 | old = self.deferred_printers.pop(typ_key) | |
435 | else: |
|
466 | else: | |
436 | if typ in self.type_printers: |
|
467 | if typ in self.type_printers: | |
437 | old = self.type_printers.pop(typ) |
|
468 | old = self.type_printers.pop(typ) | |
438 | else: |
|
469 | else: | |
439 | old = self.deferred_printers.pop(_mod_name_key(typ)) |
|
470 | old = self.deferred_printers.pop(_mod_name_key(typ), default) | |
|
471 | if old is _raise_key_error: | |||
|
472 | raise KeyError("No registered value for {0!r}".format(typ)) | |||
440 | return old |
|
473 | return old | |
441 |
|
474 | |||
442 | def _in_deferred_types(self, cls): |
|
475 | def _in_deferred_types(self, cls): |
@@ -173,22 +173,13 b' def select_figure_format(shell, fmt):' | |||||
173 | png_formatter = shell.display_formatter.formatters['image/png'] |
|
173 | png_formatter = shell.display_formatter.formatters['image/png'] | |
174 |
|
174 | |||
175 | if fmt == 'png': |
|
175 | if fmt == 'png': | |
176 | try: |
|
176 | svg_formatter.pop(Figure, None) | |
177 | svg_formatter.pop(Figure) |
|
|||
178 | except KeyError: |
|
|||
179 | pass |
|
|||
180 | png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png')) |
|
177 | png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png')) | |
181 | elif fmt in ('png2x', 'retina'): |
|
178 | elif fmt in ('png2x', 'retina'): | |
182 | try: |
|
179 | svg_formatter.pop(Figure, None) | |
183 | svg_formatter.pop(Figure) |
|
|||
184 | except KeyError: |
|
|||
185 | pass |
|
|||
186 | png_formatter.for_type(Figure, retina_figure) |
|
180 | png_formatter.for_type(Figure, retina_figure) | |
187 | elif fmt == 'svg': |
|
181 | elif fmt == 'svg': | |
188 | try: |
|
182 | png_formatter.pop(Figure, None) | |
189 | svg_formatter.pop(Figure) |
|
|||
190 | except KeyError: |
|
|||
191 | pass |
|
|||
192 | svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg')) |
|
183 | svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg')) | |
193 | else: |
|
184 | else: | |
194 | raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt) |
|
185 | raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt) |
@@ -169,22 +169,44 b' def test_lookup_by_type_string():' | |||||
169 | nt.assert_in(_mod_name_key(C), f.deferred_printers) |
|
169 | nt.assert_in(_mod_name_key(C), f.deferred_printers) | |
170 | nt.assert_not_in(C, f.type_printers) |
|
170 | nt.assert_not_in(C, f.type_printers) | |
171 |
|
171 | |||
|
172 | nt.assert_is(f.lookup_by_type(type_str), foo_printer) | |||
|
173 | # lookup by string doesn't cause import | |||
|
174 | nt.assert_in(_mod_name_key(C), f.deferred_printers) | |||
|
175 | nt.assert_not_in(C, f.type_printers) | |||
|
176 | ||||
172 | nt.assert_is(f.lookup_by_type(C), foo_printer) |
|
177 | nt.assert_is(f.lookup_by_type(C), foo_printer) | |
173 | # should move from deferred to imported dict |
|
178 | # should move from deferred to imported dict | |
174 | nt.assert_not_in(_mod_name_key(C), f.deferred_printers) |
|
179 | nt.assert_not_in(_mod_name_key(C), f.deferred_printers) | |
175 | nt.assert_in(C, f.type_printers) |
|
180 | nt.assert_in(C, f.type_printers) | |
176 |
|
181 | |||
|
182 | def test_in_formatter(): | |||
|
183 | f = PlainTextFormatter() | |||
|
184 | f.for_type(C, foo_printer) | |||
|
185 | type_str = '%s.%s' % (C.__module__, 'C') | |||
|
186 | nt.assert_in(C, f) | |||
|
187 | nt.assert_in(type_str, f) | |||
|
188 | ||||
|
189 | def test_string_in_formatter(): | |||
|
190 | f = PlainTextFormatter() | |||
|
191 | type_str = '%s.%s' % (C.__module__, 'C') | |||
|
192 | f.for_type(type_str, foo_printer) | |||
|
193 | nt.assert_in(type_str, f) | |||
|
194 | nt.assert_in(C, f) | |||
|
195 | ||||
177 | def test_pop(): |
|
196 | def test_pop(): | |
178 | f = PlainTextFormatter() |
|
197 | f = PlainTextFormatter() | |
179 | f.for_type(C, foo_printer) |
|
198 | f.for_type(C, foo_printer) | |
180 | nt.assert_is(f.lookup_by_type(C), foo_printer) |
|
199 | nt.assert_is(f.lookup_by_type(C), foo_printer) | |
181 | f.pop(C) |
|
200 | nt.assert_is(f.pop(C, None), foo_printer) | |
|
201 | f.for_type(C, foo_printer) | |||
|
202 | nt.assert_is(f.pop(C), foo_printer) | |||
182 | with nt.assert_raises(KeyError): |
|
203 | with nt.assert_raises(KeyError): | |
183 | f.lookup_by_type(C) |
|
204 | f.lookup_by_type(C) | |
184 | with nt.assert_raises(KeyError): |
|
205 | with nt.assert_raises(KeyError): | |
185 | f.pop(C) |
|
206 | f.pop(C) | |
186 | with nt.assert_raises(KeyError): |
|
207 | with nt.assert_raises(KeyError): | |
187 | f.pop(A) |
|
208 | f.pop(A) | |
|
209 | nt.assert_is(f.pop(A, None), None) | |||
188 |
|
210 | |||
189 | def test_pop_string(): |
|
211 | def test_pop_string(): | |
190 | f = PlainTextFormatter() |
|
212 | f = PlainTextFormatter() | |
@@ -201,10 +223,12 b' def test_pop_string():' | |||||
201 | f.pop(type_str) |
|
223 | f.pop(type_str) | |
202 |
|
224 | |||
203 | f.for_type(C, foo_printer) |
|
225 | f.for_type(C, foo_printer) | |
204 | f.pop(type_str) |
|
226 | nt.assert_is(f.pop(type_str, None), foo_printer) | |
205 | with nt.assert_raises(KeyError): |
|
227 | with nt.assert_raises(KeyError): | |
206 | f.lookup_by_type(C) |
|
228 | f.lookup_by_type(C) | |
207 | with nt.assert_raises(KeyError): |
|
229 | with nt.assert_raises(KeyError): | |
208 | f.pop(type_str) |
|
230 | f.pop(type_str) | |
|
231 | nt.assert_is(f.pop(type_str, None), None) | |||
|
232 | ||||
209 |
|
233 | |||
210 |
|
234 |
General Comments 0
You need to be logged in to leave comments.
Login now