##// 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 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 215 module = getattr(typ, '__module__', None)
213 216 name = getattr(typ, '__name__', None)
214 217 return (module, name)
@@ -218,6 +221,7 b' def _get_type(obj):'
218 221 """Return the type of an instance (old and new-style)"""
219 222 return getattr(obj, '__class__', None) or type(obj)
220 223
224 _raise_key_error = object()
221 225
222 226 class BaseFormatter(Configurable):
223 227 """A base formatter class that is configurable.
@@ -283,6 +287,15 b' class BaseFormatter(Configurable):'
283 287 else:
284 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 299 def lookup(self, obj):
287 300 """Look up the formatter for a given instance.
288 301
@@ -293,7 +306,7 b' class BaseFormatter(Configurable):'
293 306 Returns
294 307 -------
295 308 f : callable
296 The registered fromatting callable for the type.
309 The registered formatting callable for the type.
297 310
298 311 Raises
299 312 ------
@@ -307,7 +320,7 b' class BaseFormatter(Configurable):'
307 320 return self.lookup_by_type(_get_type(obj))
308 321
309 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 325 Parameters
313 326 ----------
@@ -316,12 +329,23 b' class BaseFormatter(Configurable):'
316 329 Returns
317 330 -------
318 331 f : callable
319 The registered fromatting callable for the type.
332 The registered formatting callable for the type.
320 333
321 334 Raises
322 335 ------
323 336 KeyError if the type has not been registered.
324 337 """
338 if isinstance(typ, string_types):
339 typ_key = tuple(typ.rsplit('.',1))
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:
325 349 for cls in pretty._get_mro(typ):
326 350 if cls in self.type_printers or self._in_deferred_types(cls):
327 351 return self.type_printers[cls]
@@ -398,17 +422,23 b' class BaseFormatter(Configurable):'
398 422 """
399 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 430 if func is not None:
403 431 self.deferred_printers[key] = func
404 432 return oldfunc
405 433
406 def pop(self, typ):
407 """ Pop a registered object for the given type.
434 def pop(self, typ, default=_raise_key_error):
435 """Pop a formatter for the given type.
408 436
409 437 Parameters
410 438 ----------
411 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 443 Returns
414 444 -------
@@ -417,8 +447,9 b' class BaseFormatter(Configurable):'
417 447
418 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 453 if isinstance(typ, string_types):
423 454 typ_key = tuple(typ.rsplit('.',1))
424 455 if typ_key not in self.deferred_printers:
@@ -429,14 +460,16 b' class BaseFormatter(Configurable):'
429 460 old = self.type_printers.pop(cls)
430 461 break
431 462 else:
432 raise KeyError("No registered value for {0!r}".format(typ_key))
463 old = default
433 464 else:
434 465 old = self.deferred_printers.pop(typ_key)
435 466 else:
436 467 if typ in self.type_printers:
437 468 old = self.type_printers.pop(typ)
438 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 473 return old
441 474
442 475 def _in_deferred_types(self, cls):
@@ -173,22 +173,13 b' def select_figure_format(shell, fmt):'
173 173 png_formatter = shell.display_formatter.formatters['image/png']
174 174
175 175 if fmt == 'png':
176 try:
177 svg_formatter.pop(Figure)
178 except KeyError:
179 pass
176 svg_formatter.pop(Figure, None)
180 177 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
181 178 elif fmt in ('png2x', 'retina'):
182 try:
183 svg_formatter.pop(Figure)
184 except KeyError:
185 pass
179 svg_formatter.pop(Figure, None)
186 180 png_formatter.for_type(Figure, retina_figure)
187 181 elif fmt == 'svg':
188 try:
189 svg_formatter.pop(Figure)
190 except KeyError:
191 pass
182 png_formatter.pop(Figure, None)
192 183 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
193 184 else:
194 185 raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt)
@@ -169,22 +169,44 b' def test_lookup_by_type_string():'
169 169 nt.assert_in(_mod_name_key(C), f.deferred_printers)
170 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 177 nt.assert_is(f.lookup_by_type(C), foo_printer)
173 178 # should move from deferred to imported dict
174 179 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
175 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 196 def test_pop():
178 197 f = PlainTextFormatter()
179 198 f.for_type(C, foo_printer)
180 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 203 with nt.assert_raises(KeyError):
183 204 f.lookup_by_type(C)
184 205 with nt.assert_raises(KeyError):
185 206 f.pop(C)
186 207 with nt.assert_raises(KeyError):
187 208 f.pop(A)
209 nt.assert_is(f.pop(A, None), None)
188 210
189 211 def test_pop_string():
190 212 f = PlainTextFormatter()
@@ -201,10 +223,12 b' def test_pop_string():'
201 223 f.pop(type_str)
202 224
203 225 f.for_type(C, foo_printer)
204 f.pop(type_str)
226 nt.assert_is(f.pop(type_str, None), foo_printer)
205 227 with nt.assert_raises(KeyError):
206 228 f.lookup_by_type(C)
207 229 with nt.assert_raises(KeyError):
208 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