blob: 1f7a6ed3f639e06374fb2de956f8e222bd83d4b0 [file] [log] [blame]
Antoine Pitrou482e66a2010-08-04 15:43:16 +00001import unittest
Martin Panter40062a12015-11-28 22:38:24 +00002from unittest.mock import patch
Antoine Pitrou482e66a2010-08-04 15:43:16 +00003import builtins
4import rlcompleter
5
6class CompleteMe:
7 """ Trivial class used in testing rlcompleter.Completer. """
8 spam = 1
Serhiy Storchakaab824222015-09-27 13:43:50 +03009 _ham = 2
Antoine Pitrou482e66a2010-08-04 15:43:16 +000010
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
Georg Brandl50de5f52010-10-21 07:40:03 +000035 self.assertEqual(sorted(self.stdcompleter.global_matches('di')),
Antoine Pitrou482e66a2010-08-04 15:43:16 +000036 [x+'(' for x in dir(builtins) if x.startswith('di')])
Georg Brandl50de5f52010-10-21 07:40:03 +000037 self.assertEqual(sorted(self.stdcompleter.global_matches('st')),
Antoine Pitrou482e66a2010-08-04 15:43:16 +000038 [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'),
Rémi Lapeyrebd4a3f22020-06-30 15:48:15 +020043 ['CompleteMe()'])
Antoine Pitrou482e66a2010-08-04 15:43:16 +000044 self.assertEqual(self.completer.global_matches('eg'),
45 ['egg('])
46 # XXX: see issue5256
47 self.assertEqual(self.completer.global_matches('CompleteM'),
Rémi Lapeyrebd4a3f22020-06-30 15:48:15 +020048 ['CompleteMe()'])
Antoine Pitrou482e66a2010-08-04 15:43:16 +000049
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'), [])
Serhiy Storchakaab824222015-09-27 13:43:50 +030056 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)
Antoine Pitrou482e66a2010-08-04 15:43:16 +000061
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'), [])
Serhiy Storchakaab824222015-09-27 13:43:50 +030066 self.assertEqual(self.completer.attr_matches('CompleteMe.'),
Rémi Lapeyrebd4a3f22020-06-30 15:48:15 +020067 ['CompleteMe.mro()', 'CompleteMe.spam'])
Serhiy Storchakaab824222015-09-27 13:43:50 +030068 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)
Antoine Pitrou482e66a2010-08-04 15:43:16 +000075
Martin Panter40062a12015-11-28 22:38:24 +000076 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')])
Antoine Pitrou482e66a2010-08-04 15:43:16 +000082
Martin Panter06622ea2015-11-13 22:47:00 +000083 def test_excessive_getattr(self):
Miss Islington (bot)d20f1092021-07-29 05:07:00 -070084 """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).
Martin Panter06622ea2015-11-13 22:47:00 +000090 class Foo:
91 calls = 0
Miss Islington (bot)d20f1092021-07-29 05:07:00 -070092 bar = ''
93 def __getattribute__(self, name):
94 if name == 'bar':
95 self.calls += 1
96 return None
97 return super().__getattribute__(name)
98
Martin Panter06622ea2015-11-13 22:47:00 +000099 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
Miss Islington (bot)d20f1092021-07-29 05:07:00 -0700104 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
Martin Panter6fe39262015-11-13 23:54:02 +0000120 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
Yury Selivanov46f77852016-02-04 14:00:26 -0500128 @unittest.mock.patch('rlcompleter._readline_available', False)
Berker Peksagaaf61142015-07-28 00:06:31 +0300129 def test_complete(self):
130 completer = rlcompleter.Completer()
131 self.assertEqual(completer.complete('', 0), '\t')
Serhiy Storchaka8ace8e92015-09-27 13:26:03 +0300132 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:')
Antoine Pitrou482e66a2010-08-04 15:43:16 +0000141
Martin Pantered929102015-11-23 23:50:26 +0000142 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
Martin Panter745f6b32015-11-24 00:20:00 +0000153 # Space or colon added due to being a reserved keyword
154 self.assertEqual(completer.complete('assert', 0), 'assert ')
Martin Pantered929102015-11-23 23:50:26 +0000155 self.assertIsNone(completer.complete('assert', 1))
Martin Panter745f6b32015-11-24 00:20:00 +0000156 self.assertEqual(completer.complete('try', 0), 'try:')
Martin Pantered929102015-11-23 23:50:26 +0000157 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))
Rémi Lapeyrebd4a3f22020-06-30 15:48:15 +0200161 self.assertEqual(completer.complete('Ellipsis', 0), 'Ellipsis()')
Martin Pantered929102015-11-23 23:50:26 +0000162 self.assertIsNone(completer.complete('Ellipsis', 1))
163
Antoine Pitrou482e66a2010-08-04 15:43:16 +0000164if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500165 unittest.main()