##// END OF EJS Templates
another pass on formatter lookup...
MinRK -
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 '__module__.__name__' string key for a type."""
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 fromatting callable for the type.
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 """ Look up all the registered formatters for a type.
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 fromatting callable for the type.
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 return self.type_printers[cls]
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 """ Pop a registered object for the given type.
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