##// END OF EJS Templates
Changes to dir2 to remove duplicates fix: put limit_to__all__ default to 0 fix: the doctest to reflect the new limit_to__all__...
Tim Couper -
Show More
@@ -416,7 +416,7 b' class IPCompleter(Completer):'
416 When 0: nothing will be excluded.
416 When 0: nothing will be excluded.
417 """
417 """
418 )
418 )
419 limit_to__all__ = Enum((0,1), default_value=1, config=True,
419 limit_to__all__ = Enum((0,1), default_value=0, config=True,
420 help="""Instruct the completer to use __all__ for the completion
420 help="""Instruct the completer to use __all__ for the completion
421
421
422 Specifically, when completing on ``object.<tab>``.
422 Specifically, when completing on ``object.<tab>``.
@@ -3753,6 +3753,13 b' Defaulting color scheme to \'NoColor\'"""'
3753 Whether to merge completion results into a single list
3753 Whether to merge completion results into a single list
3754 If False, only the completion results from the first non-empty completer
3754 If False, only the completion results from the first non-empty completer
3755 will be returned.
3755 will be returned.
3756 IPCompleter.limit_to__all__=<Enum>
3757 Current: 0
3758 Choices: (0, 1)
3759 Instruct the completer to use __all__ for the completion
3760 Specifically, when completing on ``object.<tab>``.
3761 When 1: only those names in obj.__all__ will be included.
3762 When 0 [default]: the values in the __all__ attribute are ignored
3756 IPCompleter.greedy=<CBool>
3763 IPCompleter.greedy=<CBool>
3757 Current: False
3764 Current: False
3758 Activate greedy completion
3765 Activate greedy completion
@@ -19,7 +19,7 b''
19
19
20 def get_class_members(cls):
20 def get_class_members(cls):
21 ret = dir(cls)
21 ret = dir(cls)
22 if hasattr(cls,'__bases__'):
22 if hasattr(cls, '__bases__'):
23 try:
23 try:
24 bases = cls.__bases__
24 bases = cls.__bases__
25 except AttributeError:
25 except AttributeError:
@@ -46,49 +46,28 b' def dir2(obj):'
46
46
47 # Start building the attribute list via dir(), and then complete it
47 # Start building the attribute list via dir(), and then complete it
48 # with a few extra special-purpose calls.
48 # with a few extra special-purpose calls.
49 words = dir(obj)
50
49
51 if hasattr(obj,'__class__'):
50 words = set(dir(obj))
52 words.append('__class__')
53 words.extend(get_class_members(obj.__class__))
54 #if '__base__' in words: 1/0
55
51
56 # Some libraries (such as traits) may introduce duplicates, we want to
52 if hasattr(obj, '__class__'):
57 # track and clean this up if it happens
53 #words.add('__class__')
58 may_have_dupes = False
54 words |= set(get_class_members(obj.__class__))
59
55
60 # this is the 'dir' function for objects with Enthought's traits
61 if hasattr(obj, 'trait_names'):
62 try:
63 words.extend(obj.trait_names())
64 may_have_dupes = True
65 except TypeError:
66 # This will happen if `obj` is a class and not an instance.
67 pass
68 except AttributeError:
69 # `obj` lied to hasatter (e.g. Pyro), ignore
70 pass
71
72 # Support for PyCrust-style _getAttributeNames magic method.
73 if hasattr(obj, '_getAttributeNames'):
74 try:
75 words.extend(obj._getAttributeNames())
76 may_have_dupes = True
77 except TypeError:
78 # `obj` is a class and not an instance. Ignore
79 # this error.
80 pass
81 except AttributeError:
82 # `obj` lied to hasatter (e.g. Pyro), ignore
83 pass
84
56
85 if may_have_dupes:
57 # for objects with Enthought's traits, add trait_names() list
86 # eliminate possible duplicates, as some traits may also
58 # for PyCrust-style, add _getAttributeNames() magic method list
87 # appear as normal attributes in the dir() call.
59 for attr in ('trait_names', '_getAttributeNames'):
88 words = list(set(words))
60 if hasattr(obj, attr):
89 words.sort()
61 try:
62 func = getattr(obj, attr)
63 if callable(func):
64 words |= set(func())
65 except:
66 # TypeError: obj is class not instance
67 pass
90
68
91 # filter out non-string attributes which may be stuffed by dir() calls
69 # filter out non-string attributes which may be stuffed by dir() calls
92 # and poor coding in third-party modules
70 # and poor coding in third-party modules
93 return [w for w in words if isinstance(w, basestring)]
94
71
72 words = [w for w in words if isinstance(w, basestring)]
73 return sorted(words)
@@ -13,8 +13,8 b' def test_base():'
13 assert ('z' in res)
13 assert ('z' in res)
14 assert ('y' not in res)
14 assert ('y' not in res)
15 assert ('__class__' in res)
15 assert ('__class__' in res)
16 nt.assert_equal(res.count('x'), 2) # duplicates
16 nt.assert_equal(res.count('x'), 1)
17 nt.assert_equal(res.count('__class__'), 4) # duplicates
17 nt.assert_equal(res.count('__class__'), 1)
18
18
19 def test_SubClass():
19 def test_SubClass():
20
20
@@ -23,8 +23,8 b' def test_SubClass():'
23
23
24 res = dir2(SubClass())
24 res = dir2(SubClass())
25 assert ('y' in res)
25 assert ('y' in res)
26 nt.assert_equal(res.count('y'), 2) # duplicates,
26 nt.assert_equal(res.count('y'), 1)
27 nt.assert_equal(res.count('x'), 3) # duplicates, but fewer than above!
27 nt.assert_equal(res.count('x'), 1)
28
28
29
29
30 def test_SubClass_with_trait_names_method():
30 def test_SubClass_with_trait_names_method():
@@ -37,6 +37,7 b' def test_SubClass_with_trait_names_method():'
37 res = dir2(SubClass())
37 res = dir2(SubClass())
38 assert('trait_names' in res)
38 assert('trait_names' in res)
39 assert('umbrella' in res)
39 assert('umbrella' in res)
40 nt.assert_equal(res[-6:], ['t', 'trait_names','umbrella', 'x','y','z'])
40 nt.assert_equal(res.count('t'), 1)
41 nt.assert_equal(res.count('t'), 1)
41
42
42
43
General Comments 0
You need to be logged in to leave comments. Login now