1
- "Test autocomplete, coverage 57 %."
1
+ "Test autocomplete, coverage 87 %."
2
2
3
3
import unittest
4
+ from unittest .mock import Mock , patch
4
5
from <
E864
span class=pl-s1>test.support import requires
5
6
from tkinter import Tk , Text
7
+ import os
6
8
import __main__
7
9
8
10
import idlelib .autocomplete as ac
@@ -26,12 +28,14 @@ class AutoCompleteTest(unittest.TestCase):
26
28
def setUpClass (cls ):
27
29
requires ('gui' )
28
30
cls .root = Tk ()
31
+ cls .root .withdraw ()
29
32
cls .text = Text (cls .root )
30
33
cls .editor = DummyEditwin (cls .root , cls .text )
31
34
32
35
@classmethod
33
36
def tearDownClass (cls ):
34
37
del cls .editor , cls .text
38
+ cls .root .update_idletasks ()
35
39
cls .root .destroy ()
36
40
del cls .root
37
41
@@ -53,7 +57,7 @@ def test_remove_autocomplete_window(self):
53
57
self .assertIsNone (self .autocomplete .autocompletewindow )
54
58
55
59
def test_force_open_completions_event (self ):
56
- # Test that force_open_completions_event calls _open_completions
60
+ # Test that force_open_completions_event calls _open_completions.
57
61
o_cs = Func ()
58
62
self .autocomplete .open_completions = o_cs
59
63
self .autocomplete .force_open_completions_event ('event' )
@@ -66,16 +70,16 @@ def test_try_open_completions_event(self):
66
70
o_c_l = Func ()
67
71
autocomplete ._open_completions_later = o_c_l
68
72
69
- # _open_completions_later should not be called with no text in editor
73
+ # _open_completions_later should not be called with no text in editor.
70
74
trycompletions ('event' )
71
75
Equal (o_c_l .args , None )
72
76
73
- # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1)
77
+ # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1).
74
78
self .text .insert ('1.0' , 're.' )
75
79
trycompletions ('event' )
76
80
Equal (o_c_l .args , (False , False , False , 1 ))
77
81
78
- # _open_completions_later should be called with COMPLETE_FILES (2)
82
+ # _open_completions_later should be called with COMPLETE_FILES (2).
79
83
self .text .delete ('1.0' , 'end' )
80
84
self .text .insert ('1.0' , '"./Lib/' )
81
85
trycompletions ('event' )
@@ -86,7 +90,7 @@ def test_autocomplete_event(self):
86
90
autocomplete = self .autocomplete
87
91
88
92
# Test that the autocomplete event is ignored if user is pressing a
89
- # modifier key in addition to the tab key
93
+ # modifier key in addition to the tab key.
90
94
ev = Event (mc_state = True )
91
95
self .assertIsNone (autocomplete .autocomplete_event (ev ))
92
96
del ev .mc_state
@@ -96,15 +100,15 @@ def test_autocomplete_event(self):
96
100
self .assertIsNone (autocomplete .autocomplete_event (ev ))
97
101
self .text .delete ('1.0' , 'end' )
98
102
99
- # If autocomplete window is open, complete() method is called
103
+ # If autocomplete window is open, complete() method is called.
100
104
self .text .insert ('1.0' , 're.' )
101
- # This must call autocomplete._make_autocomplete_window()
105
+ # This must call autocomplete._make_autocomplete_window().
102
106
Equal (self .autocomplete .autocomplete_event (ev ), 'break' )
103
107
104
108
# If autocomplete window is not active or does not exist,
105
109
# open_completions is called. Return depends on its return.
106
110
autocomplete ._remove_autocomplete_window ()
107
- o_cs = Func () # .result = None
111
+ o_cs = Func () # .result = None.
108
112
autocomplete .open_completions = o_cs
109
113
Equal (self .autocomplete .autocomplete_event (ev ), None )
110
114
Equal (o_cs .args , (False , True , True ))
@@ -113,36 +117,130 @@ def test_autocomplete_event(self):
113
117
Equal (o_cs .args , (False , True , True ))
114
118
115
119
def test_open_completions_later (self ):
116
- # Test that autocomplete._delayed_completion_id is set
117
- pass
120
+ # Test that autocomplete._delayed_completion_id is set.
121
+ acp = self .autocomplete
122
+ acp ._delayed_completion_id = None
123
+ acp ._open_completions_later (False , False , False , ac .COMPLETE_ATTRIBUTES )
124
+ cb1 = acp ._delayed_completion_id
125
+ self .assertTrue (cb1 .startswith ('after' ))
126
+
127
+ # Test that cb1 is cancelled and cb2 is new.
128
+ acp ._open_completions_later (False , False , False , ac .COMPLETE_FILES )
129
+ self .assertNotIn (cb1 , self .root .tk .call ('after' , 'info' ))
130
+ cb2 = acp ._delayed_completion_id
131
+ self .assertTrue (cb2 .startswith ('after' ) and cb2 != cb1 )
132
+ self .text .after_cancel (cb2 )
118
133
119
134
def test_delayed_open_completions (self ):
120
- # Test that autocomplete._delayed_completion_id set to None and that
121
- # open_completions only called if insertion index is the same as
122
- # _delayed_completion_index
123
- pass
135
+ # Test that autocomplete._delayed_completion_id set to None
136
+ # and that open_completions is not called if the index is not
137
+ # equal to _delayed_completion_index.
138
+ acp = self .autocomplete
139
+ acp .open_completions = Func ()
140
+ acp ._delayed_completion_id = 'after'
141
+ acp ._delayed_completion_index = self .text .index ('insert+1c' )
142
+ acp ._delayed_open_completions (1 , 2 , 3 )
143
+ self .assertIsNone (acp ._delayed_completion_id )
144
+ self .assertEqual (acp .open_completions .called , 0 )
145
+
146
+ # Test that open_completions is called if indexes match.
147
+ acp ._delayed_completion_index = self .text .index ('insert' )
148
+ acp ._delayed_open_completions (1 , 2 , 3 , ac .COMPLETE_FILES )
149
+ self .assertEqual (acp .open_completions .args , (1 , 2 , 3 , 2 ))
124
150
125
151
def test_open_completions (self ):
126
152
# Test completions of files and attributes as well as non-completion
127
- # of errors
128
- pass
153
+ # of errors.
154
+ self .text .insert ('1.0' , 'pr' )
155
+ self .assertTrue (self .autocomplete .open_completions (False , True , True ))
156
+ self .text .delete ('1.0' , 'end' )
157
+
158
+ # Test files.
159
+ self .text .insert ('1.0' , '"t' )
160
+ #self.assertTrue(self.autocomplete.open_completions(False, True, True))
161
+ self .text .delete ('1.0' , 'end' )
162
+
163
+ # Test with blank will fail.
164
+ self .assertFalse (self .autocomplete .open_completions (False , True , True ))
165
+
166
+ # Test with only string quote will fail.
167
+ self .text .insert ('1.0' , '"' )
168
+ self .assertFalse (self .autocomplete .open_completions (False , True , True ))
169
+ self .text .delete ('1.0' , 'end' )
129
170
130
171
def test_fetch_completions (self ):
131
172
# Test that fetch_completions returns 2 lists:
132
173
# For attribute completion, a large list containing all variables, and
133
174
# a small list containing non-private variables.
134
175
# For file completion, a large list containing all files in the path,
135
- # and a small list containing files that do not start with '.'
176
+ # and a small list containing files that do not start with '.'.
177
+ autocomplete = self .autocomplete
136
178
small , large = self .autocomplete .fetch_completions (
137
179
'' , ac .COMPLETE_ATTRIBUTES )
138
- self .assertLess (len (small ), len (large ))
139
180
if __main__ .__file__ != ac .__file__ :
140
181
self .assertNotIn ('AutoComplete' , small ) # See issue 36405.
141
182
183
+ # Test attributes
184
+ s , b = autocomplete .fetch_completions ('' , ac .COMPLETE_ATTRIBUTES )
185
+ self .assertLess (len (small ), len (large ))
186
+ self .assertTrue (all (filter (lambda x : x .startswith ('_' ), s )))
187
+ self .assertTrue (any (filter (lambda x : x .startswith ('_' ), b )))
188
+
189
+ # Test smalll should respect to __all__.
190
+ with patch .dict ('__main__.__dict__' , {'__all__' : ['a' , 'b' ]}):
191
+ s , b = autocomplete .fetch_completions ('' , ac .COMPLETE_ATTRIBUTES )
192
+ self .assertEqual (s , ['a' , 'b' ])
193
+ self .assertIn ('__name__' , b ) # From __main__.__dict__
194
+ self .assertIn ('sum' , b ) # From __main__.__builtins__.__dict__
195
+
196
+ # Test attributes with name entity.
197
+ mock = Mock ()
198
+ mock ._private = Mock ()
199
+ with patch .dict ('__main__.__dict__' , {'foo' : mock }):
200
+ s , b = autocomplete .fetch_completions ('foo' , ac .COMPLETE_ATTRIBUTES )
201
+ self .assertNotIn ('_private' , s )
202
+ self .assertIn ('_private' , b )
203
+ self .assertEqual (s , [i for i in sorted (dir (mock )) if i [:1 ] != '_' ])
204
+ self .assertEqual (b , sorted (dir (mock )))
205
+
206
+ # Test files
207
+ def _listdir (path ):
208
+ # This will be patch and used in fetch_completions.
209
+ if path == '.' :
210
+ return ['foo' , 'bar' , '.hidden' ]
211
+ return ['monty' , 'python' , '.hidden' ]
212
+
213
+ with patch .object (os , 'listdir' , _listdir ):
214
+ s , b = autocomplete .fetch_completions ('' , ac .COMPLETE_FILES )
215
+ self .assertEqual (s , ['bar' , 'foo' ])
216
+ self .assertEqual (b , ['.hidden' , 'bar' , 'foo' ])
217
+
218
+ s , b = autocomplete .fetch_completions ('~' , ac .COMPLETE_FILES )
219
+ self .assertEqual (s , ['monty' , 'python' ])
220
+ self .assertEqual (b , ['.hidden' , 'monty' , 'python' ])
221
+
142
222
def test_get_entity (self ):
143
223
# Test that a name is in the namespace of sys.modules and
144
- # __main__.__dict__
145
- self .assertEqual (self .autocomplete .get_entity ('int' ), int )
224
+ # __main__.__dict__.
225
+ autocomplete = self .autocomplete
226
+ Equal = self .assertEqual
227
+
228
+ Equal (self .autocomplete .get_entity ('int' ), int )
229
+
230
+ # Test name from sys.modules.
231
+ mock = Mock ()
232
+ with patch .dict ('sys.modules' , {'tempfile' : mock }):
233
+ Equal (autocomplete .get_entity ('tempfile' ), mock )
234
+
235
+ # Test name from __main__.__dict__.
236
+ di = {'foo' : 10 , 'bar' : 20 }
237
+ with patch .dict ('__main__.__dict__' , {'d' : di }):
238
+ Equal (autocomplete .get_entity ('d' ), di )
239
+
240
+ # Test name not in namespace.
241
+ with patch .dict ('__main__.__dict__' , {}):
242
+ with self .assertRaises (NameError ):
243
+ autocomplete .get_entity ('not_exist' )
146
244
147
245
148
246
if __name__ == '__main__' :
0 commit comments