1import unittest 2from unittest.mock import patch 3import builtins 4import rlcompleter 5 6class CompleteMe: 7 """ Trivial class used in testing rlcompleter.Completer. """ 8 spam = 1 9 _ham = 2 10 11 12class TestRlcompleter(unittest.TestCase): 13 def setUp(self): 14 self.stdcompleter = rlcompleter.Completer() 15 self.completer = rlcompleter.Completer(dict(spam=int, 16 egg=str, 17 CompleteMe=CompleteMe)) 18 19 # forces stdcompleter to bind builtins namespace 20 self.stdcompleter.complete('', 0) 21 22 def test_namespace(self): 23 class A(dict): 24 pass 25 class B(list): 26 pass 27 28 self.assertTrue(self.stdcompleter.use_main_ns) 29 self.assertFalse(self.completer.use_main_ns) 30 self.assertFalse(rlcompleter.Completer(A()).use_main_ns) 31 self.assertRaises(TypeError, rlcompleter.Completer, B((1,))) 32 33 def test_global_matches(self): 34 # test with builtins namespace 35 self.assertEqual(sorted(self.stdcompleter.global_matches('di')), 36 [x+'(' for x in dir(builtins) if x.startswith('di')]) 37 self.assertEqual(sorted(self.stdcompleter.global_matches('st')), 38 [x+'(' for x in dir(builtins) if x.startswith('st')]) 39 self.assertEqual(self.stdcompleter.global_matches('akaksajadhak'), []) 40 41 # test with a customized namespace 42 self.assertEqual(self.completer.global_matches('CompleteM'), 43 ['CompleteMe()']) 44 self.assertEqual(self.completer.global_matches('eg'), 45 ['egg(']) 46 # XXX: see issue5256 47 self.assertEqual(self.completer.global_matches('CompleteM'), 48 ['CompleteMe()']) 49 50 def test_attr_matches(self): 51 # test with builtins namespace 52 self.assertEqual(self.stdcompleter.attr_matches('str.s'), 53 ['str.{}('.format(x) for x in dir(str) 54 if x.startswith('s')]) 55 self.assertEqual(self.stdcompleter.attr_matches('tuple.foospamegg'), []) 56 expected = sorted({'None.%s%s' % (x, '(' if x != '__doc__' else '') 57 for x in dir(None)}) 58 self.assertEqual(self.stdcompleter.attr_matches('None.'), expected) 59 self.assertEqual(self.stdcompleter.attr_matches('None._'), expected) 60 self.assertEqual(self.stdcompleter.attr_matches('None.__'), expected) 61 62 # test with a customized namespace 63 self.assertEqual(self.completer.attr_matches('CompleteMe.sp'), 64 ['CompleteMe.spam']) 65 self.assertEqual(self.completer.attr_matches('Completeme.egg'), []) 66 self.assertEqual(self.completer.attr_matches('CompleteMe.'), 67 ['CompleteMe.mro()', 'CompleteMe.spam']) 68 self.assertEqual(self.completer.attr_matches('CompleteMe._'), 69 ['CompleteMe._ham']) 70 matches = self.completer.attr_matches('CompleteMe.__') 71 for x in matches: 72 self.assertTrue(x.startswith('CompleteMe.__'), x) 73 self.assertIn('CompleteMe.__name__', matches) 74 self.assertIn('CompleteMe.__new__(', matches) 75 76 with patch.object(CompleteMe, "me", CompleteMe, create=True): 77 self.assertEqual(self.completer.attr_matches('CompleteMe.me.me.sp'), 78 ['CompleteMe.me.me.spam']) 79 self.assertEqual(self.completer.attr_matches('egg.s'), 80 ['egg.{}('.format(x) for x in dir(str) 81 if x.startswith('s')]) 82 83 def test_excessive_getattr(self): 84 """Ensure getattr() is invoked no more than once per attribute""" 85 86 # note the special case for @property methods below; that is why 87 # we use __dir__ and __getattr__ in class Foo to create a "magic" 88 # class attribute 'bar'. This forces `getattr` to call __getattr__ 89 # (which is doesn't necessarily do). 90 class Foo: 91 calls = 0 92 bar = '' 93 def __getattribute__(self, name): 94 if name == 'bar': 95 self.calls += 1 96 return None 97 return super().__getattribute__(name) 98 99 f = Foo() 100 completer = rlcompleter.Completer(dict(f=f)) 101 self.assertEqual(completer.complete('f.b', 0), 'f.bar') 102 self.assertEqual(f.calls, 1) 103 104 def test_property_method_not_called(self): 105 class Foo: 106 _bar = 0 107 property_called = False 108 109 @property 110 def bar(self): 111 self.property_called = True 112 return self._bar 113 114 f = Foo() 115 completer = rlcompleter.Completer(dict(f=f)) 116 self.assertEqual(completer.complete('f.b', 0), 'f.bar') 117 self.assertFalse(f.property_called) 118 119 120 def test_uncreated_attr(self): 121 # Attributes like properties and slots should be completed even when 122 # they haven't been created on an instance 123 class Foo: 124 __slots__ = ("bar",) 125 completer = rlcompleter.Completer(dict(f=Foo())) 126 self.assertEqual(completer.complete('f.', 0), 'f.bar') 127 128 @unittest.mock.patch('rlcompleter._readline_available', False) 129 def test_complete(self): 130 completer = rlcompleter.Completer() 131 self.assertEqual(completer.complete('', 0), '\t') 132 self.assertEqual(completer.complete('a', 0), 'and ') 133 self.assertEqual(completer.complete('a', 1), 'as ') 134 self.assertEqual(completer.complete('as', 2), 'assert ') 135 self.assertEqual(completer.complete('an', 0), 'and ') 136 self.assertEqual(completer.complete('pa', 0), 'pass') 137 self.assertEqual(completer.complete('Fa', 0), 'False') 138 self.assertEqual(completer.complete('el', 0), 'elif ') 139 self.assertEqual(completer.complete('el', 1), 'else') 140 self.assertEqual(completer.complete('tr', 0), 'try:') 141 142 def test_duplicate_globals(self): 143 namespace = { 144 'False': None, # Keyword vs builtin vs namespace 145 'assert': None, # Keyword vs namespace 146 'try': lambda: None, # Keyword vs callable 147 'memoryview': None, # Callable builtin vs non-callable 148 'Ellipsis': lambda: None, # Non-callable builtin vs callable 149 } 150 completer = rlcompleter.Completer(namespace) 151 self.assertEqual(completer.complete('False', 0), 'False') 152 self.assertIsNone(completer.complete('False', 1)) # No duplicates 153 # Space or colon added due to being a reserved keyword 154 self.assertEqual(completer.complete('assert', 0), 'assert ') 155 self.assertIsNone(completer.complete('assert', 1)) 156 self.assertEqual(completer.complete('try', 0), 'try:') 157 self.assertIsNone(completer.complete('try', 1)) 158 # No opening bracket "(" because we overrode the built-in class 159 self.assertEqual(completer.complete('memoryview', 0), 'memoryview') 160 self.assertIsNone(completer.complete('memoryview', 1)) 161 self.assertEqual(completer.complete('Ellipsis', 0), 'Ellipsis()') 162 self.assertIsNone(completer.complete('Ellipsis', 1)) 163 164if __name__ == '__main__': 165 unittest.main() 166