Show More
@@ -246,11 +246,13 class Config(dict): | |||||
246 | c = Config() |
|
246 | c = Config() | |
247 | dict.__setitem__(self, key, c) |
|
247 | dict.__setitem__(self, key, c) | |
248 | return c |
|
248 | return c | |
249 | else: |
|
249 | elif not key.startswith('_'): | |
250 | # undefined, create lazy value, used for container methods |
|
250 | # undefined, create lazy value, used for container methods | |
251 | v = LazyConfigValue() |
|
251 | v = LazyConfigValue() | |
252 | dict.__setitem__(self, key, v) |
|
252 | dict.__setitem__(self, key, v) | |
253 | return v |
|
253 | return v | |
|
254 | else: | |||
|
255 | raise KeyError | |||
254 |
|
256 | |||
255 | def __setitem__(self, key, value): |
|
257 | def __setitem__(self, key, value): | |
256 | if _is_section_key(key): |
|
258 | if _is_section_key(key): |
@@ -369,6 +369,14 class TestConfig(TestCase): | |||||
369 | assert isinstance(foo, LazyConfigValue) |
|
369 | assert isinstance(foo, LazyConfigValue) | |
370 | self.assertIn('foo', cfg) |
|
370 | self.assertIn('foo', cfg) | |
371 |
|
371 | |||
|
372 | def test_getattr_private_missing(self): | |||
|
373 | cfg = Config() | |||
|
374 | self.assertNotIn('_repr_html_', cfg) | |||
|
375 | with self.assertRaises(AttributeError): | |||
|
376 | _ = cfg._repr_html_ | |||
|
377 | self.assertNotIn('_repr_html_', cfg) | |||
|
378 | self.assertEqual(len(cfg), 0) | |||
|
379 | ||||
372 | def test_getitem_not_section(self): |
|
380 | def test_getitem_not_section(self): | |
373 | cfg = Config() |
|
381 | cfg = Config() | |
374 | self.assertNotIn('foo', cfg) |
|
382 | self.assertNotIn('foo', cfg) |
@@ -25,7 +25,9 Authors: | |||||
25 |
|
25 | |||
26 | # Stdlib imports |
|
26 | # Stdlib imports | |
27 | import abc |
|
27 | import abc | |
|
28 | import inspect | |||
28 | import sys |
|
29 | import sys | |
|
30 | import types | |||
29 | import warnings |
|
31 | import warnings | |
30 |
|
32 | |||
31 | from IPython.external.decorator import decorator |
|
33 | from IPython.external.decorator import decorator | |
@@ -52,6 +54,32 else: | |||||
52 | # The main DisplayFormatter class |
|
54 | # The main DisplayFormatter class | |
53 | #----------------------------------------------------------------------------- |
|
55 | #----------------------------------------------------------------------------- | |
54 |
|
56 | |||
|
57 | ||||
|
58 | def _valid_formatter(f): | |||
|
59 | """Return whether an object is a valid formatter | |||
|
60 | ||||
|
61 | Cases checked: | |||
|
62 | ||||
|
63 | - bound methods OK | |||
|
64 | - unbound methods NO | |||
|
65 | - callable with zero args OK | |||
|
66 | """ | |||
|
67 | if isinstance(f, type(str.find)): | |||
|
68 | # unbound methods on compiled classes have type method_descriptor | |||
|
69 | return False | |||
|
70 | elif isinstance(f, types.BuiltinFunctionType): | |||
|
71 | # bound methods on compiled classes have type builtin_function | |||
|
72 | return True | |||
|
73 | elif callable(f): | |||
|
74 | # anything that works with zero args should be okay | |||
|
75 | try: | |||
|
76 | inspect.getcallargs(f) | |||
|
77 | except TypeError: | |||
|
78 | return False | |||
|
79 | else: | |||
|
80 | return True | |||
|
81 | return False | |||
|
82 | ||||
55 | class DisplayFormatter(Configurable): |
|
83 | class DisplayFormatter(Configurable): | |
56 |
|
84 | |||
57 | # When set to true only the default plain text formatter will be used. |
|
85 | # When set to true only the default plain text formatter will be used. | |
@@ -312,7 +340,8 class BaseFormatter(Configurable): | |||||
312 | return printer(obj) |
|
340 | return printer(obj) | |
313 | # Finally look for special method names |
|
341 | # Finally look for special method names | |
314 | method = pretty._safe_getattr(obj, self.print_method, None) |
|
342 | method = pretty._safe_getattr(obj, self.print_method, None) | |
315 | if method is not None: |
|
343 | # print_method must be a bound method: | |
|
344 | if _valid_formatter(method): | |||
316 | return method() |
|
345 | return method() | |
317 | return None |
|
346 | return None | |
318 | else: |
|
347 | else: |
@@ -8,6 +8,7 except: | |||||
8 | numpy = None |
|
8 | numpy = None | |
9 | import nose.tools as nt |
|
9 | import nose.tools as nt | |
10 |
|
10 | |||
|
11 | from IPython.config import Config | |||
11 | from IPython.core.formatters import ( |
|
12 | from IPython.core.formatters import ( | |
12 | PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key |
|
13 | PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key | |
13 | ) |
|
14 | ) | |
@@ -289,3 +290,33 def test_pdf_formatter(): | |||||
289 | pdf = MakePDF() |
|
290 | pdf = MakePDF() | |
290 | f = PDFFormatter() |
|
291 | f = PDFFormatter() | |
291 | nt.assert_equal(f(pdf), 'PDF') |
|
292 | nt.assert_equal(f(pdf), 'PDF') | |
|
293 | ||||
|
294 | def test_print_method_bound(): | |||
|
295 | f = HTMLFormatter() | |||
|
296 | class MyHTML(object): | |||
|
297 | def _repr_html_(self): | |||
|
298 | return "hello" | |||
|
299 | ||||
|
300 | with capture_output() as captured: | |||
|
301 | result = f(MyHTML) | |||
|
302 | nt.assert_is(result, None) | |||
|
303 | nt.assert_not_in("FormatterWarning", captured.stderr) | |||
|
304 | ||||
|
305 | with capture_output() as captured: | |||
|
306 | result = f(MyHTML()) | |||
|
307 | nt.assert_equal(result, "hello") | |||
|
308 | nt.assert_equal(captured.stderr, "") | |||
|
309 | ||||
|
310 | def test_format_config(): | |||
|
311 | """config objects don't pretend to support fancy reprs with lazy attrs""" | |||
|
312 | f = HTMLFormatter() | |||
|
313 | cfg = Config() | |||
|
314 | with capture_output() as captured: | |||
|
315 | result = f(cfg) | |||
|
316 | nt.assert_is(result, None) | |||
|
317 | nt.assert_equal(captured.stderr, "") | |||
|
318 | ||||
|
319 | with capture_output() as captured: | |||
|
320 | result = f(Config) | |||
|
321 | nt.assert_is(result, None) | |||
|
322 | nt.assert_equal(captured.stderr, "") |
General Comments 0
You need to be logged in to leave comments.
Login now