Show More
@@ -71,7 +71,7 b' from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol' | |||||
71 | from IPython.utils import generics |
|
71 | from IPython.utils import generics | |
72 | from IPython.utils import io |
|
72 | from IPython.utils import io | |
73 | from IPython.utils.decorators import undoc |
|
73 | from IPython.utils.decorators import undoc | |
74 |
from IPython.utils.dir2 import dir2, |
|
74 | from IPython.utils.dir2 import dir2, get_real_method | |
75 | from IPython.utils.process import arg_split |
|
75 | from IPython.utils.process import arg_split | |
76 | from IPython.utils.py3compat import builtin_mod, string_types, PY3 |
|
76 | from IPython.utils.py3compat import builtin_mod, string_types, PY3 | |
77 | from traitlets import CBool, Enum |
|
77 | from traitlets import CBool, Enum | |
@@ -472,19 +472,6 b' def _safe_isinstance(obj, module, class_name):' | |||||
472 | return (module in sys.modules and |
|
472 | return (module in sys.modules and | |
473 | isinstance(obj, getattr(__import__(module), class_name))) |
|
473 | isinstance(obj, getattr(__import__(module), class_name))) | |
474 |
|
474 | |||
475 | def _safe_really_hasattr(obj, name): |
|
|||
476 | """Checks that an object genuinely has a given attribute. |
|
|||
477 |
|
||||
478 | Some objects claim to have any attribute that's requested, to act as a lazy |
|
|||
479 | proxy for something else. We want to catch these cases and ignore their |
|
|||
480 | claim to have the attribute we're interested in. |
|
|||
481 | """ |
|
|||
482 | if safe_hasattr(obj, '_ipy_proxy_check_dont_define_this_'): |
|
|||
483 | # If it claims this exists, don't trust it |
|
|||
484 | return False |
|
|||
485 |
|
||||
486 | return safe_hasattr(obj, name) |
|
|||
487 |
|
||||
488 |
|
475 | |||
489 | def back_unicode_name_matches(text): |
|
476 | def back_unicode_name_matches(text): | |
490 | u"""Match unicode characters back to unicode name |
|
477 | u"""Match unicode characters back to unicode name | |
@@ -937,8 +924,9 b' class IPCompleter(Completer):' | |||||
937 | def get_keys(obj): |
|
924 | def get_keys(obj): | |
938 | # Objects can define their own completions by defining an |
|
925 | # Objects can define their own completions by defining an | |
939 | # _ipy_key_completions_() method. |
|
926 | # _ipy_key_completions_() method. | |
940 |
|
|
927 | method = get_real_method(obj, '_ipython_key_completions_') | |
941 | return obj._ipython_key_completions_() |
|
928 | if method is not None: | |
|
929 | return method() | |||
942 |
|
930 | |||
943 | # Special case some common in-memory dict-like types |
|
931 | # Special case some common in-memory dict-like types | |
944 | if isinstance(obj, dict) or\ |
|
932 | if isinstance(obj, dict) or\ |
@@ -13,7 +13,6 b' import sys' | |||||
13 | import io as _io |
|
13 | import io as _io | |
14 | import tokenize |
|
14 | import tokenize | |
15 |
|
15 | |||
16 | from IPython.core.formatters import _safe_get_formatter_method |
|
|||
17 | from traitlets.config.configurable import Configurable |
|
16 | from traitlets.config.configurable import Configurable | |
18 | from IPython.utils import io |
|
17 | from IPython.utils import io | |
19 | from IPython.utils.py3compat import builtin_mod, cast_unicode_py2 |
|
18 | from IPython.utils.py3compat import builtin_mod, cast_unicode_py2 |
@@ -22,6 +22,7 b' from decorator import decorator' | |||||
22 | from traitlets.config.configurable import Configurable |
|
22 | from traitlets.config.configurable import Configurable | |
23 | from IPython.core.getipython import get_ipython |
|
23 | from IPython.core.getipython import get_ipython | |
24 | from IPython.utils.sentinel import Sentinel |
|
24 | from IPython.utils.sentinel import Sentinel | |
|
25 | from IPython.utils.dir2 import get_real_method | |||
25 | from IPython.lib import pretty |
|
26 | from IPython.lib import pretty | |
26 | from traitlets import ( |
|
27 | from traitlets import ( | |
27 | Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List, |
|
28 | Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List, | |
@@ -32,29 +33,6 b' from IPython.utils.py3compat import (' | |||||
32 | ) |
|
33 | ) | |
33 |
|
34 | |||
34 |
|
35 | |||
35 | #----------------------------------------------------------------------------- |
|
|||
36 | # The main DisplayFormatter class |
|
|||
37 | #----------------------------------------------------------------------------- |
|
|||
38 |
|
||||
39 |
|
||||
40 | def _safe_get_formatter_method(obj, name): |
|
|||
41 | """Safely get a formatter method |
|
|||
42 |
|
||||
43 | - Classes cannot have formatter methods, only instance |
|
|||
44 | - protect against proxy objects that claim to have everything |
|
|||
45 | """ |
|
|||
46 | if inspect.isclass(obj): |
|
|||
47 | # repr methods only make sense on instances, not classes |
|
|||
48 | return None |
|
|||
49 | method = pretty._safe_getattr(obj, name, None) |
|
|||
50 | if callable(method): |
|
|||
51 | # obj claims to have repr method... |
|
|||
52 | if callable(pretty._safe_getattr(obj, '_ipython_canary_method_should_not_exist_', None)): |
|
|||
53 | # ...but don't trust proxy objects that claim to have everything |
|
|||
54 | return None |
|
|||
55 | return method |
|
|||
56 |
|
||||
57 |
|
||||
58 | class DisplayFormatter(Configurable): |
|
36 | class DisplayFormatter(Configurable): | |
59 |
|
37 | |||
60 | # When set to true only the default plain text formatter will be used. |
|
38 | # When set to true only the default plain text formatter will be used. | |
@@ -338,7 +316,7 b' class BaseFormatter(Configurable):' | |||||
338 | else: |
|
316 | else: | |
339 | return printer(obj) |
|
317 | return printer(obj) | |
340 | # Finally look for special method names |
|
318 | # Finally look for special method names | |
341 |
method = |
|
319 | method = get_real_method(obj, self.print_method) | |
342 | if method is not None: |
|
320 | if method is not None: | |
343 | return method() |
|
321 | return method() | |
344 | return None |
|
322 | return None | |
@@ -904,7 +882,7 b' class IPythonDisplayFormatter(BaseFormatter):' | |||||
904 | printer(obj) |
|
882 | printer(obj) | |
905 | return True |
|
883 | return True | |
906 | # Finally look for special method names |
|
884 | # Finally look for special method names | |
907 |
method = |
|
885 | method = get_real_method(obj, self.print_method) | |
908 | if method is not None: |
|
886 | if method is not None: | |
909 | method() |
|
887 | method() | |
910 | return True |
|
888 | return True |
@@ -2,21 +2,11 b'' | |||||
2 | """A fancy version of Python's builtin :func:`dir` function. |
|
2 | """A fancy version of Python's builtin :func:`dir` function. | |
3 | """ |
|
3 | """ | |
4 |
|
4 | |||
5 | #----------------------------------------------------------------------------- |
|
5 | # Copyright (c) IPython Development Team. | |
6 | # Copyright (C) 2008-2011 The IPython Development Team |
|
6 | # Distributed under the terms of the Modified BSD License. | |
7 | # |
|
|||
8 | # Distributed under the terms of the BSD License. The full license is in |
|
|||
9 | # the file COPYING, distributed as part of this software. |
|
|||
10 | #----------------------------------------------------------------------------- |
|
|||
11 |
|
||||
12 | #----------------------------------------------------------------------------- |
|
|||
13 | # Imports |
|
|||
14 | #----------------------------------------------------------------------------- |
|
|||
15 | from .py3compat import string_types |
|
|||
16 |
|
7 | |||
17 | #----------------------------------------------------------------------------- |
|
8 | import inspect | |
18 | # Code |
|
9 | from .py3compat import string_types | |
19 | #----------------------------------------------------------------------------- |
|
|||
20 |
|
10 | |||
21 |
|
11 | |||
22 | def safe_hasattr(obj, attr): |
|
12 | def safe_hasattr(obj, attr): | |
@@ -56,3 +46,36 b' def dir2(obj):' | |||||
56 |
|
46 | |||
57 | words = [w for w in words if isinstance(w, string_types)] |
|
47 | words = [w for w in words if isinstance(w, string_types)] | |
58 | return sorted(words) |
|
48 | return sorted(words) | |
|
49 | ||||
|
50 | ||||
|
51 | def get_real_method(obj, name): | |||
|
52 | """Like getattr, but with a few extra sanity checks: | |||
|
53 | ||||
|
54 | - If obj is a class, ignore its methods | |||
|
55 | - Check if obj is a proxy that claims to have all attributes | |||
|
56 | - Catch attribute access failing with any exception | |||
|
57 | - Check that the attribute is a callable object | |||
|
58 | ||||
|
59 | Returns the method or None. | |||
|
60 | """ | |||
|
61 | if inspect.isclass(obj): | |||
|
62 | return None | |||
|
63 | ||||
|
64 | try: | |||
|
65 | canary = getattr(obj, '_ipython_canary_method_should_not_exist_', None) | |||
|
66 | except Exception: | |||
|
67 | return None | |||
|
68 | ||||
|
69 | if canary is not None: | |||
|
70 | # It claimed to have an attribute it should never have | |||
|
71 | return None | |||
|
72 | ||||
|
73 | try: | |||
|
74 | m = getattr(obj, name, None) | |||
|
75 | except Exception: | |||
|
76 | return None | |||
|
77 | ||||
|
78 | if callable(m): | |||
|
79 | return m | |||
|
80 | ||||
|
81 | return None |
General Comments 0
You need to be logged in to leave comments.
Login now