##// END OF EJS Templates
Consolidate code to check for method in IPython.utils.dir2
Thomas Kluyver -
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, safe_hasattr
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 if _safe_really_hasattr(obj, '_ipython_key_completions_'):
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 = _safe_get_formatter_method(obj, self.print_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 = _safe_get_formatter_method(obj, self.print_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