Show More
@@ -40,38 +40,21 b' else:' | |||||
40 | #----------------------------------------------------------------------------- |
|
40 | #----------------------------------------------------------------------------- | |
41 |
|
41 | |||
42 |
|
42 | |||
43 | def _valid_formatter(f): |
|
43 | def _safe_get_formatter_method(obj, name): | |
44 | """Return whether an object is a valid formatter |
|
44 | """Safely get a formatter method | |
45 |
|
||||
46 | Cases checked: |
|
|||
47 |
|
45 | |||
48 | - bound methods OK |
|
46 | - Classes cannot have formatter methods, only instance | |
49 | - unbound methods NO |
|
47 | - protect against proxy objects that claim to have everything | |
50 | - callable with zero args OK |
|
|||
51 | """ |
|
48 | """ | |
52 | if f is None: |
|
49 | if inspect.isclass(obj): | |
53 | return False |
|
50 | # repr methods only make sense on instances, not classes | |
54 | elif isinstance(f, type(str.find)): |
|
51 | return None | |
55 | # unbound methods on compiled classes have type method_descriptor |
|
|||
56 | return False |
|
|||
57 | elif isinstance(f, types.BuiltinFunctionType): |
|
|||
58 | # bound methods on compiled classes have type builtin_function |
|
|||
59 | return True |
|
|||
60 | elif callable(f): |
|
|||
61 | # anything that works with zero args should be okay |
|
|||
62 | try: |
|
|||
63 | inspect.getcallargs(f) |
|
|||
64 | except Exception: |
|
|||
65 | return False |
|
|||
66 | else: |
|
|||
67 | return True |
|
|||
68 | return False |
|
|||
69 |
|
||||
70 | def _safe_get_formatter_method(obj, name): |
|
|||
71 | """Safely get a formatter method""" |
|
|||
72 | method = pretty._safe_getattr(obj, name, None) |
|
52 | method = pretty._safe_getattr(obj, name, None) | |
73 | # formatter methods must be bound |
|
53 | if callable(method): | |
74 | if _valid_formatter(method): |
|
54 | # obj claims to have repr method... | |
|
55 | if callable(pretty._safe_getattr(obj, '_ipython_canary_method_should_not_exist_', None)): | |||
|
56 | # ...but don't trust proxy objects that claim to have everything | |||
|
57 | return None | |||
75 | return method |
|
58 | return method | |
76 |
|
59 | |||
77 |
|
60 |
@@ -314,7 +314,6 b' def test_print_method_bound():' | |||||
314 | class MyHTML(object): |
|
314 | class MyHTML(object): | |
315 | def _repr_html_(self): |
|
315 | def _repr_html_(self): | |
316 | return "hello" |
|
316 | return "hello" | |
317 |
|
||||
318 | with capture_output() as captured: |
|
317 | with capture_output() as captured: | |
319 | result = f(MyHTML) |
|
318 | result = f(MyHTML) | |
320 | nt.assert_is(result, None) |
|
319 | nt.assert_is(result, None) | |
@@ -325,6 +324,44 b' def test_print_method_bound():' | |||||
325 | nt.assert_equal(result, "hello") |
|
324 | nt.assert_equal(result, "hello") | |
326 | nt.assert_equal(captured.stderr, "") |
|
325 | nt.assert_equal(captured.stderr, "") | |
327 |
|
326 | |||
|
327 | def test_print_method_weird(): | |||
|
328 | ||||
|
329 | class TextMagicHat(object): | |||
|
330 | def __getattr__(self, key): | |||
|
331 | return key | |||
|
332 | ||||
|
333 | f = HTMLFormatter() | |||
|
334 | ||||
|
335 | text_hat = TextMagicHat() | |||
|
336 | nt.assert_equal(text_hat._repr_html_, '_repr_html_') | |||
|
337 | with capture_output() as captured: | |||
|
338 | result = f(text_hat) | |||
|
339 | ||||
|
340 | nt.assert_is(result, None) | |||
|
341 | nt.assert_not_in("FormatterWarning", captured.stderr) | |||
|
342 | ||||
|
343 | class CallableMagicHat(object): | |||
|
344 | def __getattr__(self, key): | |||
|
345 | return lambda : key | |||
|
346 | ||||
|
347 | call_hat = CallableMagicHat() | |||
|
348 | with capture_output() as captured: | |||
|
349 | result = f(call_hat) | |||
|
350 | ||||
|
351 | nt.assert_equal(result, None) | |||
|
352 | ||||
|
353 | class BadReprArgs(object): | |||
|
354 | def _repr_html_(self, extra, args): | |||
|
355 | return "html" | |||
|
356 | ||||
|
357 | bad = BadReprArgs() | |||
|
358 | with capture_output() as captured: | |||
|
359 | result = f(bad) | |||
|
360 | ||||
|
361 | nt.assert_is(result, None) | |||
|
362 | nt.assert_not_in("FormatterWarning", captured.stderr) | |||
|
363 | ||||
|
364 | ||||
328 | def test_format_config(): |
|
365 | def test_format_config(): | |
329 | """config objects don't pretend to support fancy reprs with lazy attrs""" |
|
366 | """config objects don't pretend to support fancy reprs with lazy attrs""" | |
330 | f = HTMLFormatter() |
|
367 | f = HTMLFormatter() |
General Comments 0
You need to be logged in to leave comments.
Login now