blob: e59ddf93cead70f747e43c4c43540945c958ced1 [file] [log] [blame]
Bram Moolenaar53901442018-07-25 22:02:36 +02001" Test for python 3 commands.
Bram Moolenaara58883b2017-01-29 21:31:09 +01002
Bram Moolenaarb46fecd2019-06-15 17:58:09 +02003source check.vim
4CheckFeature python3
Bram Moolenaarab589462020-07-06 21:03:06 +02005source shared.vim
Bram Moolenaara58883b2017-01-29 21:31:09 +01006
Bram Moolenaar423a85a2020-08-29 12:57:16 +02007func Create_vim_list()
8 return [1]
9endfunction
10
Yegappan Lakshmanan038be272025-03-26 18:46:21 +010011func Create_vim_tuple()
12 return ('a', 'b')
13endfunction
14
Bram Moolenaar423a85a2020-08-29 12:57:16 +020015func Create_vim_dict()
16 return {'a': 1}
17endfunction
18
Zdenek Dohnaledd7a472021-10-06 19:39:16 +010019let s:system_error_pat = 'Vim(py3):SystemError: \(<built-in function eval> returned NULL without setting an \(error\|exception\)\|error return without exception set\)'
Bram Moolenaar423a85a2020-08-29 12:57:16 +020020
Bram Moolenaareffb0cd2020-07-03 21:17:34 +020021" This function should be called first. This sets up python functions used by
22" the other tests.
23func Test_AAA_python3_setup()
24 py3 << trim EOF
25 import vim
26 import sys
27 import re
28
Zdenek Dohnal288bf262023-08-11 23:32:23 +020029 py33_type_error_pattern = re.compile(r'^__call__\(\) takes (\d+) positional argument but (\d+) were given$')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +020030 py37_exception_repr = re.compile(r'([^\(\),])(\)+)$')
Zdenek Dohnal288bf262023-08-11 23:32:23 +020031 py39_type_error_pattern = re.compile(r'\w+\.([^(]+\(\) takes)')
32 py310_type_error_pattern = re.compile(r'takes (\d+) positional argument but (\d+) were given')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +020033
34 def emsg(ei):
35 return ei[0].__name__ + ':' + repr(ei[1].args)
36
37 def ee(expr, g=globals(), l=locals()):
38 cb = vim.current.buffer
39 try:
40 try:
41 exec(expr, g, l)
42 except Exception as e:
43 if sys.version_info >= (3, 3) and e.__class__ is AttributeError and str(e).find('has no attribute')>=0 and not str(e).startswith("'vim."):
44 msg = repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1])))
45 elif sys.version_info >= (3, 3) and e.__class__ is ImportError and str(e).find('No module named \'') >= 0:
46 msg = repr((e.__class__, ImportError(str(e).replace("'", ''))))
47 elif sys.version_info >= (3, 6) and e.__class__ is ModuleNotFoundError:
48 # Python 3.6 gives ModuleNotFoundError, change it to an ImportError
49 msg = repr((ImportError, ImportError(str(e).replace("'", ''))))
50 elif sys.version_info >= (3, 3) and e.__class__ is TypeError:
51 m = py33_type_error_pattern.search(str(e))
52 if m:
53 msg = '__call__() takes exactly {0} positional argument ({1} given)'.format(m.group(1), m.group(2))
54 msg = repr((e.__class__, TypeError(msg)))
55 else:
56 msg = repr((e.__class__, e))
57 # Messages changed with Python 3.6, change new to old.
58 newmsg1 = """'argument must be str, bytes or bytearray, not None'"""
59 oldmsg1 = '''"Can't convert 'NoneType' object to str implicitly"'''
60 if msg.find(newmsg1) > -1:
61 msg = msg.replace(newmsg1, oldmsg1)
62 newmsg2 = """'argument must be str, bytes or bytearray, not int'"""
63 oldmsg2 = '''"Can't convert 'int' object to str implicitly"'''
64 if msg.find(newmsg2) > -1:
65 msg = msg.replace(newmsg2, oldmsg2)
Bram Moolenaar68a48ee2020-10-27 19:59:10 +010066 # Python 3.9 reports errors like "vim.command() takes ..." instead of "command() takes ..."
67 msg = py39_type_error_pattern.sub(r'\1', msg)
K.Takata1be7e212021-11-16 13:08:56 +000068 msg = py310_type_error_pattern.sub(r'takes exactly \1 positional argument (\2 given)', msg)
Bram Moolenaareffb0cd2020-07-03 21:17:34 +020069 elif sys.version_info >= (3, 5) and e.__class__ is ValueError and str(e) == 'embedded null byte':
70 msg = repr((TypeError, TypeError('expected bytes with no null')))
71 else:
72 msg = repr((e.__class__, e))
73 # Some Python versions say can't, others cannot.
74 if msg.find('can\'t') > -1:
75 msg = msg.replace('can\'t', 'cannot')
76 # Some Python versions use single quote, some double quote
77 if msg.find('"cannot ') > -1:
78 msg = msg.replace('"cannot ', '\'cannot ')
79 if msg.find(' attributes"') > -1:
80 msg = msg.replace(' attributes"', ' attributes\'')
81 if sys.version_info >= (3, 7):
82 msg = py37_exception_repr.sub(r'\1,\2', msg)
83 cb.append(expr + ':' + msg)
84 else:
85 cb.append(expr + ':NOT FAILED')
86 except Exception as e:
87 msg = repr((e.__class__, e))
88 if sys.version_info >= (3, 7):
89 msg = py37_exception_repr.sub(r'\1,\2', msg)
90 cb.append(expr + '::' + msg)
91 EOF
92endfunc
93
Bram Moolenaara58883b2017-01-29 21:31:09 +010094func Test_py3do()
Bram Moolenaara58883b2017-01-29 21:31:09 +010095 new
zeertzjqe99f0682024-01-29 19:32:39 +010096
97 " Check deleting lines does not trigger an ml_get error.
Bram Moolenaara58883b2017-01-29 21:31:09 +010098 call setline(1, ['one', 'two', 'three'])
99 py3do vim.command("%d_")
zeertzjqe99f0682024-01-29 19:32:39 +0100100 call assert_equal([''], getline(1, '$'))
101
102 call setline(1, ['one', 'two', 'three'])
103 py3do vim.command("1,2d_")
104 call assert_equal(['three'], getline(1, '$'))
105
106 call setline(1, ['one', 'two', 'three'])
107 py3do vim.command("2,3d_"); return "REPLACED"
108 call assert_equal(['REPLACED'], getline(1, '$'))
109
110 call setline(1, ['one', 'two', 'three'])
111 2,3py3do vim.command("1,2d_"); return "REPLACED"
112 call assert_equal(['three'], getline(1, '$'))
113
Bram Moolenaara58883b2017-01-29 21:31:09 +0100114 bwipe!
115
116 " Check switching to another buffer does not trigger an ml_get error.
117 new
118 let wincount = winnr('$')
119 call setline(1, ['one', 'two', 'three'])
120 py3do vim.command("new")
121 call assert_equal(wincount + 1, winnr('$'))
122 bwipe!
123 bwipe!
Bram Moolenaarab589462020-07-06 21:03:06 +0200124
125 " Try modifying a buffer with 'nomodifiable' set
126 set nomodifiable
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200127 call assert_fails('py3do toupper(line)', 'E21:')
Bram Moolenaarab589462020-07-06 21:03:06 +0200128 set modifiable
129
130 " Invalid command
131 call AssertException(['py3do non_existing_cmd'],
132 \ "Vim(py3do):NameError: name 'non_existing_cmd' is not defined")
133 call AssertException(["py3do raise Exception('test')"],
134 \ 'Vim(py3do):Exception: test')
135 call AssertException(["py3do {lambda}"],
136 \ 'Vim(py3do):SyntaxError: invalid syntax')
Bram Moolenaara58883b2017-01-29 21:31:09 +0100137endfunc
Bram Moolenaar53901442018-07-25 22:02:36 +0200138
139func Test_set_cursor()
140 " Check that setting the cursor position works.
Bram Moolenaar53901442018-07-25 22:02:36 +0200141 new
142 call setline(1, ['first line', 'second line'])
143 normal gg
144 py3do vim.current.window.cursor = (1, 5)
145 call assert_equal([1, 6], [line('.'), col('.')])
146
147 " Check that movement after setting cursor position keeps current column.
148 normal j
149 call assert_equal([2, 6], [line('.'), col('.')])
150endfunc
Bram Moolenaar9123c0b2018-12-22 18:59:06 +0100151
152func Test_vim_function()
153 " Check creating vim.Function object
Bram Moolenaar9123c0b2018-12-22 18:59:06 +0100154
155 func s:foo()
156 return matchstr(expand('<sfile>'), '<SNR>\zs\d\+_foo$')
157 endfunc
158 let name = '<SNR>' . s:foo()
159
160 try
161 py3 f = vim.bindeval('function("s:foo")')
162 call assert_equal(name, py3eval('f.name'))
163 catch
164 call assert_false(v:exception)
165 endtry
166
167 try
168 py3 f = vim.Function(b'\x80\xfdR' + vim.eval('s:foo()').encode())
Bram Moolenaar3f4f3d82019-09-04 20:05:59 +0200169 call assert_equal(name, 'f.name'->py3eval())
Bram Moolenaar9123c0b2018-12-22 18:59:06 +0100170 catch
171 call assert_false(v:exception)
172 endtry
173
Bram Moolenaarab589462020-07-06 21:03:06 +0200174 " Non-existing function attribute
175 call AssertException(["let x = py3eval('f.abc')"],
176 \ "Vim(let):AttributeError: 'vim.function' object has no attribute 'abc'")
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200177
Bram Moolenaar9123c0b2018-12-22 18:59:06 +0100178 py3 del f
179 delfunc s:foo
180endfunc
Bram Moolenaar14816ad2019-02-18 22:04:56 +0100181
182func Test_skipped_python3_command_does_not_affect_pyxversion()
183 set pyxversion=0
184 if 0
185 python3 import vim
186 endif
187 call assert_equal(0, &pyxversion) " This assertion would have failed with Vim 8.0.0251. (pyxversion was introduced in 8.0.0251.)
188endfunc
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100189
190func _SetUpHiddenBuffer()
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100191 new
192 edit hidden
193 setlocal bufhidden=hide
194
195 enew
196 let lnum = 0
197 while lnum < 10
198 call append( 1, string( lnum ) )
199 let lnum = lnum + 1
200 endwhile
201 normal G
202
203 call assert_equal( line( '.' ), 11 )
204endfunc
205
Bram Moolenaarbfd36032019-03-30 12:33:13 +0100206func _CleanUpHiddenBuffer()
207 bwipe! hidden
208 bwipe!
209endfunc
210
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100211func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_Clear()
212 call _SetUpHiddenBuffer()
213 py3 vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][:] = None
214 call assert_equal( line( '.' ), 11 )
Bram Moolenaarbfd36032019-03-30 12:33:13 +0100215 call _CleanUpHiddenBuffer()
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100216endfunc
217
218func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_List()
219 call _SetUpHiddenBuffer()
220 py3 vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][:] = [ 'test' ]
221 call assert_equal( line( '.' ), 11 )
Bram Moolenaarbfd36032019-03-30 12:33:13 +0100222 call _CleanUpHiddenBuffer()
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100223endfunc
224
225func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_Str()
226 call _SetUpHiddenBuffer()
227 py3 vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][0] = 'test'
228 call assert_equal( line( '.' ), 11 )
Bram Moolenaarbfd36032019-03-30 12:33:13 +0100229 call _CleanUpHiddenBuffer()
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100230endfunc
231
232func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_ClearLine()
233 call _SetUpHiddenBuffer()
234 py3 vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][0] = None
235 call assert_equal( line( '.' ), 11 )
Bram Moolenaarbfd36032019-03-30 12:33:13 +0100236 call _CleanUpHiddenBuffer()
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100237endfunc
238
239func _SetUpVisibleBuffer()
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100240 new
241 let lnum = 0
242 while lnum < 10
243 call append( 1, string( lnum ) )
244 let lnum = lnum + 1
245 endwhile
246 normal G
247 call assert_equal( line( '.' ), 11 )
248endfunc
249
250func Test_Write_To_Current_Buffer_Fixes_Cursor_Clear()
251 call _SetUpVisibleBuffer()
252
253 py3 vim.current.buffer[:] = None
254 call assert_equal( line( '.' ), 1 )
255
256 bwipe!
257endfunc
258
259func Test_Write_To_Current_Buffer_Fixes_Cursor_List()
260 call _SetUpVisibleBuffer()
261
262 py3 vim.current.buffer[:] = [ 'test' ]
263 call assert_equal( line( '.' ), 1 )
264
265 bwipe!
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200266endfunc
Bram Moolenaar63dbfd32019-03-23 17:41:59 +0100267
268func Test_Write_To_Current_Buffer_Fixes_Cursor_Str()
269 call _SetUpVisibleBuffer()
270
271 py3 vim.current.buffer[-1] = None
272 call assert_equal( line( '.' ), 10 )
273
274 bwipe!
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200275endfunc
Bram Moolenaar7f3a2842019-05-18 15:02:25 +0200276
277func Test_Catch_Exception_Message()
278 try
279 py3 raise RuntimeError( 'TEST' )
280 catch /.*/
281 call assert_match( '^Vim(.*):RuntimeError: TEST$', v:exception )
282 endtry
283endfunc
Bram Moolenaar556684f2019-12-31 21:59:01 +0100284
285func Test_unicode()
286 " this crashed Vim once
Bram Moolenaar2466aea2020-01-01 17:09:11 +0100287 if &tenc != ''
288 throw "Skipped: 'termencoding' is not empty"
289 endif
Bram Moolenaar4b7cdca2020-01-01 16:18:38 +0100290
Bram Moolenaar556684f2019-12-31 21:59:01 +0100291 set encoding=utf32
292 py3 print('hello')
Bram Moolenaar4b7cdca2020-01-01 16:18:38 +0100293
Bram Moolenaar955f4e62020-01-01 17:44:56 +0100294 if !has('win32')
295 set encoding=debug
296 py3 print('hello')
Bram Moolenaar4b7cdca2020-01-01 16:18:38 +0100297
Bram Moolenaar7fc47852020-01-02 16:38:07 +0100298 set encoding=euc-tw
299 py3 print('hello')
300 endif
Bram Moolenaar4b7cdca2020-01-01 16:18:38 +0100301
Bram Moolenaar556684f2019-12-31 21:59:01 +0100302 set encoding=utf8
303endfunc
Bram Moolenaar904edab2020-01-19 13:57:54 +0100304
Bram Moolenaar026270c2020-02-23 15:10:16 +0100305" Test vim.eval() with various types.
zeertzjq50732c72024-11-09 18:30:10 +0100306func Test_python3_vim_eval()
Bram Moolenaar026270c2020-02-23 15:10:16 +0100307 call assert_equal("\n8", execute('py3 print(vim.eval("3+5"))'))
Bram Moolenaar73e28dc2022-09-17 21:08:33 +0100308 call assert_equal("\n3.140000", execute('py3 print(vim.eval("1.01+2.13"))'))
309 call assert_equal("\n0.000000", execute('py3 print(vim.eval("0.0/(1.0/0.0)"))'))
310 call assert_equal("\n0.000000", execute('py3 print(vim.eval("0.0/(1.0/0.0)"))'))
311 call assert_equal("\n-0.000000", execute('py3 print(vim.eval("0.0/(-1.0/0.0)"))'))
312 " Commented out: output of infinity and nan depend on platforms.
313 " call assert_equal("\ninf", execute('py3 print(vim.eval("1.0/0.0"))'))
314 " call assert_equal("\n-inf", execute('py3 print(vim.eval("-1.0/0.0"))'))
315 " call assert_equal("\n-nan", execute('py3 print(vim.eval("0.0/0.0"))'))
Bram Moolenaar026270c2020-02-23 15:10:16 +0100316 call assert_equal("\nabc", execute('py3 print(vim.eval("\"abc\""))'))
317 call assert_equal("\n['1', '2']", execute('py3 print(vim.eval("[1, 2]"))'))
318 call assert_equal("\n{'1': '2'}", execute('py3 print(vim.eval("{1:2}"))'))
319 call assert_equal("\nTrue", execute('py3 print(vim.eval("v:true"))'))
320 call assert_equal("\nFalse", execute('py3 print(vim.eval("v:false"))'))
321 call assert_equal("\nNone", execute('py3 print(vim.eval("v:null"))'))
322 call assert_equal("\nNone", execute('py3 print(vim.eval("v:none"))'))
323 call assert_equal("\nb'\\xab\\x12'", execute('py3 print(vim.eval("0zab12"))'))
324
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200325 call assert_fails('py3 vim.eval("1+")', 'E15: Invalid expression')
Bram Moolenaar026270c2020-02-23 15:10:16 +0100326endfunc
327
Bram Moolenaar904edab2020-01-19 13:57:54 +0100328" Test range objects, see :help python-range
Bram Moolenaar50985eb2020-01-27 22:09:39 +0100329func Test_python3_range()
Bram Moolenaar904edab2020-01-19 13:57:54 +0100330 new
331 py3 b = vim.current.buffer
332
333 call setline(1, range(1, 6))
334 py3 r = b.range(2, 4)
335 call assert_equal(6, py3eval('len(b)'))
336 call assert_equal(3, py3eval('len(r)'))
337 call assert_equal('3', py3eval('b[2]'))
338 call assert_equal('4', py3eval('r[2]'))
339
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200340 call assert_fails('py3 r[3] = "x"', ['Traceback', 'IndexError: line number out of range'])
341 call assert_fails('py3 x = r[3]', ['Traceback', 'IndexError: line number out of range'])
342 call assert_fails('py3 r["a"] = "x"', ['Traceback', 'TypeError: index must be int or slice, not str'])
343 call assert_fails('py3 x = r["a"]', ['Traceback', 'TypeError: index must be int or slice, not str'])
Bram Moolenaar904edab2020-01-19 13:57:54 +0100344
345 py3 del r[:]
346 call assert_equal(['1', '5', '6'], getline(1, '$'))
347
348 %d | call setline(1, range(1, 6))
349 py3 r = b.range(2, 5)
350 py3 del r[2]
351 call assert_equal(['1', '2', '3', '5', '6'], getline(1, '$'))
352
353 %d | call setline(1, range(1, 6))
354 py3 r = b.range(2, 4)
355 py3 vim.command("%d,%dnorm Ax" % (r.start + 1, r.end + 1))
356 call assert_equal(['1', '2x', '3x', '4x', '5', '6'], getline(1, '$'))
357
358 %d | call setline(1, range(1, 4))
359 py3 r = b.range(2, 3)
360 py3 r.append(['a', 'b'])
361 call assert_equal(['1', '2', '3', 'a', 'b', '4'], getline(1, '$'))
362 py3 r.append(['c', 'd'], 0)
363 call assert_equal(['1', 'c', 'd', '2', '3', 'a', 'b', '4'], getline(1, '$'))
364
365 %d | call setline(1, range(1, 5))
366 py3 r = b.range(2, 4)
367 py3 r.append('a')
368 call assert_equal(['1', '2', '3', '4', 'a', '5'], getline(1, '$'))
369 py3 r.append('b', 1)
370 call assert_equal(['1', '2', 'b', '3', '4', 'a', '5'], getline(1, '$'))
371
372 bwipe!
373endfunc
Bram Moolenaar1363a302020-04-12 13:50:26 +0200374
375" Test for resetting options with local values to global values
376func Test_python3_opt_reset_local_to_global()
377 new
378
379 py3 curbuf = vim.current.buffer
380 py3 curwin = vim.current.window
381
382 " List of buffer-local options. Each list item has [option name, global
383 " value, buffer-local value, buffer-local value after reset] to use in the
384 " test.
385 let bopts = [
386 \ ['autoread', 1, 0, -1],
387 \ ['equalprg', 'geprg', 'leprg', ''],
388 \ ['keywordprg', 'gkprg', 'lkprg', ''],
389 \ ['path', 'gpath', 'lpath', ''],
390 \ ['backupcopy', 'yes', 'no', ''],
391 \ ['tags', 'gtags', 'ltags', ''],
392 \ ['tagcase', 'ignore', 'match', ''],
393 \ ['define', 'gdef', 'ldef', ''],
394 \ ['include', 'ginc', 'linc', ''],
395 \ ['dict', 'gdict', 'ldict', ''],
396 \ ['thesaurus', 'gtsr', 'ltsr', ''],
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +0000397 \ ['thesaurusfunc', 'Gtsrfu', 'Ltsrfu', ''],
Bram Moolenaar1363a302020-04-12 13:50:26 +0200398 \ ['formatprg', 'gfprg', 'lfprg', ''],
399 \ ['errorformat', '%f:%l:%m', '%s-%l-%m', ''],
400 \ ['grepprg', 'ggprg', 'lgprg', ''],
401 \ ['makeprg', 'gmprg', 'lmprg', ''],
Bram Moolenaar1363a302020-04-12 13:50:26 +0200402 \ ['cryptmethod', 'blowfish2', 'zip', ''],
403 \ ['lispwords', 'abc', 'xyz', ''],
404 \ ['makeencoding', 'utf-8', 'latin1', ''],
405 \ ['undolevels', 100, 200, -123456]]
Bram Moolenaarddf53122022-05-27 20:23:20 +0100406 if has('balloon_eval')
407 call add(bopts, ['balloonexpr', 'gbexpr', 'lbexpr', ''])
408 endif
Bram Moolenaar1363a302020-04-12 13:50:26 +0200409
410 " Set the global and buffer-local option values and then clear the
411 " buffer-local option value.
412 for opt in bopts
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +0200413 py3 << trim END
414 pyopt = vim.bindeval("opt")
415 vim.options[pyopt[0]] = pyopt[1]
416 curbuf.options[pyopt[0]] = pyopt[2]
417 END
Bram Moolenaar1363a302020-04-12 13:50:26 +0200418 exe "call assert_equal(opt[2], &" .. opt[0] .. ")"
419 exe "call assert_equal(opt[1], &g:" .. opt[0] .. ")"
420 exe "call assert_equal(opt[2], &l:" .. opt[0] .. ")"
421 py3 del curbuf.options[pyopt[0]]
422 exe "call assert_equal(opt[1], &" .. opt[0] .. ")"
423 exe "call assert_equal(opt[1], &g:" .. opt[0] .. ")"
424 exe "call assert_equal(opt[3], &l:" .. opt[0] .. ")"
425 exe "set " .. opt[0] .. "&"
426 endfor
427
428 " Set the global and window-local option values and then clear the
429 " window-local option value.
430 let wopts = [
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +0000431 \ ['fillchars', 'fold:>', 'fold:+', ''],
432 \ ['listchars', 'tab:>>', 'tab:--', ''],
Bram Moolenaar1363a302020-04-12 13:50:26 +0200433 \ ['scrolloff', 5, 10, -1],
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +0000434 \ ['showbreak', '>>', '++', ''],
Bram Moolenaar1363a302020-04-12 13:50:26 +0200435 \ ['sidescrolloff', 6, 12, -1],
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +0000436 \ ['statusline', '%<%f', '%<%F', ''],
437 \ ['virtualedit', 'block', 'insert', '']]
Bram Moolenaar1363a302020-04-12 13:50:26 +0200438 for opt in wopts
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +0200439 py3 << trim
440 pyopt = vim.bindeval("opt")
441 vim.options[pyopt[0]] = pyopt[1]
442 curwin.options[pyopt[0]] = pyopt[2]
443 .
Bram Moolenaar1363a302020-04-12 13:50:26 +0200444 exe "call assert_equal(opt[2], &" .. opt[0] .. ")"
445 exe "call assert_equal(opt[1], &g:" .. opt[0] .. ")"
446 exe "call assert_equal(opt[2], &l:" .. opt[0] .. ")"
447 py3 del curwin.options[pyopt[0]]
448 exe "call assert_equal(opt[1], &" .. opt[0] .. ")"
449 exe "call assert_equal(opt[1], &g:" .. opt[0] .. ")"
450 exe "call assert_equal(opt[3], &l:" .. opt[0] .. ")"
451 exe "set " .. opt[0] .. "&"
452 endfor
453
454 close!
455endfunc
456
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +0200457" Test for various heredoc syntax
458func Test_python3_heredoc()
459 python3 << END
460s='A'
461END
462 python3 <<
463s+='B'
464.
465 python3 << trim END
466 s+='C'
467 END
468 python3 << trim
469 s+='D'
470 .
Bram Moolenaar6ab09532020-05-01 14:10:13 +0200471 python3 << trim eof
472 s+='E'
473 eof
zeertzjq449c2e52025-02-03 18:56:16 +0100474 python3 << trimm
475s+='F'
476trimm
477 call assert_equal('ABCDEF', pyxeval('s'))
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +0200478endfunc
479
Bram Moolenaarab589462020-07-06 21:03:06 +0200480" Test for the buffer range object
481func Test_python3_range2()
482 new
483 call setline(1, ['one', 'two', 'three'])
484 py3 b = vim.current.buffer
485 py3 r = b.range(1, 3)
486 call assert_equal(0, py3eval('r.start'))
487 call assert_equal(2, py3eval('r.end'))
488 call assert_equal('one', py3eval('r[0]'))
489 call assert_equal('one', py3eval('r[-3]'))
490 call AssertException(["let x = py3eval('r[-4]')"],
491 \ 'Vim(let):IndexError: line number out of range')
492 call assert_equal(['two', 'three'], py3eval('r[1:]'))
493 py3 r[0] = 'green'
494 call assert_equal(['green', 'two', 'three'], getline(1, '$'))
495 py3 r[0:2] = ['red', 'blue']
496 call assert_equal(['red', 'blue', 'three'], getline(1, '$'))
497
498 " try different invalid start/end index for the range slice
499 %d
500 call setline(1, ['one', 'two', 'three'])
501 py3 r[-10:1] = ["a"]
502 py3 r[10:12] = ["b"]
503 py3 r[-10:-9] = ["c"]
504 py3 r[1:0] = ["d"]
505 call assert_equal(['c', 'd', 'a', 'two', 'three', 'b'], getline(1, '$'))
506
Bram Moolenaarbb790dc2020-07-07 20:12:54 +0200507 " The following code used to trigger an ml_get error
508 %d
509 let x = py3eval('r[:]')
Bram Moolenaarab589462020-07-06 21:03:06 +0200510
511 " Non-existing range attribute
512 call AssertException(["let x = py3eval('r.abc')"],
513 \ "Vim(let):AttributeError: 'vim.range' object has no attribute 'abc'")
514
515 close!
516endfunc
517
518" Test for the python tabpage object
519func Test_python3_tabpage()
520 tabnew
521 py3 t = vim.tabpages[1]
522 py3 wl = t.windows
523 tabclose
524 " Accessing a closed tabpage
525 call AssertException(["let n = py3eval('t.number')"],
526 \ 'Vim(let):vim.error: attempt to refer to deleted tab page')
527 call AssertException(["let n = py3eval('len(wl)')"],
528 \ 'Vim(let):vim.error: attempt to refer to deleted tab page')
529 call AssertException(["py3 w = wl[0]"],
530 \ 'Vim(py3):vim.error: attempt to refer to deleted tab page')
531 call AssertException(["py3 vim.current.tabpage = t"],
532 \ 'Vim(py3):vim.error: attempt to refer to deleted tab page')
533 call assert_match('<tabpage object (deleted)', py3eval('repr(t)'))
534 %bw!
535endfunc
536
537" Test for the python window object
538func Test_python3_window()
539 " Test for setting the window height
540 10new
541 py3 vim.current.window.height = 5
542 call assert_equal(5, winheight(0))
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200543 py3 vim.current.window.height = 3.2
544 call assert_equal(3, winheight(0))
Bram Moolenaarab589462020-07-06 21:03:06 +0200545
546 " Test for setting the window width
547 10vnew
548 py3 vim.current.window.width = 6
549 call assert_equal(6, winwidth(0))
550
551 " Try accessing a closed window
552 py3 w = vim.current.window
553 py3 wopts = w.options
554 close
555 " Access the attributes of a closed window
556 call AssertException(["let n = py3eval('w.number')"],
557 \ 'Vim(let):vim.error: attempt to refer to deleted window')
558 call AssertException(["py3 w.height = 5"],
559 \ 'Vim(py3):vim.error: attempt to refer to deleted window')
560 call AssertException(["py3 vim.current.window = w"],
561 \ 'Vim(py3):vim.error: attempt to refer to deleted window')
562 " Try to set one of the options of the closed window
Bram Moolenaarbb790dc2020-07-07 20:12:54 +0200563 " The following caused ASAN failure
564 call AssertException(["py3 wopts['list'] = False"],
565 \ 'Vim(py3):vim.error: attempt to refer to deleted window')
Bram Moolenaarab589462020-07-06 21:03:06 +0200566 call assert_match('<window object (deleted)', py3eval("repr(w)"))
567 %bw!
568endfunc
569
Bram Moolenaar6c87bbb2022-12-10 11:17:11 +0000570" This was causing trouble because "curbuf" was not matching curwin->w_buffer
571func Test_python3_window_set_height()
572 enew!
573 call setline(1, ['aaa', 'bbb', 'ccc'])
574 call cursor(2, 1)
575 set foldmethod=expr
576 new
577 wincmd w
578 python3 vim.windows[0].height = 5
579 call assert_equal(5, winheight(1))
580
581 call feedkeys('j', 'xt')
582 call assert_equal(3, getpos('.')[1])
583
584 bwipe!
585 bwipe!
586endfunc
587
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200588" Test for the python List object
589func Test_python3_list()
Bram Moolenaarab589462020-07-06 21:03:06 +0200590 " Try to convert a null List
591 call AssertException(["py3 t = vim.eval('test_null_list()')"],
Bram Moolenaar07761a32020-12-22 12:50:10 +0100592 \ s:system_error_pat)
Bram Moolenaarab589462020-07-06 21:03:06 +0200593
594 " Try to convert a List with a null List item
595 call AssertException(["py3 t = vim.eval('[test_null_list()]')"],
Bram Moolenaar07761a32020-12-22 12:50:10 +0100596 \ s:system_error_pat)
Bram Moolenaarab589462020-07-06 21:03:06 +0200597
Bram Moolenaar64ffa9b2020-11-04 12:23:06 +0100598 " Try to bind a null List variable (works because an empty list is used)
Bram Moolenaarab589462020-07-06 21:03:06 +0200599 let cmds =<< trim END
600 let l = test_null_list()
601 py3 ll = vim.bindeval('l')
602 END
Bram Moolenaar64ffa9b2020-11-04 12:23:06 +0100603 call AssertException(cmds, '')
Bram Moolenaarab589462020-07-06 21:03:06 +0200604
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200605 let l = []
606 py3 l = vim.bindeval('l')
607 py3 f = vim.bindeval('function("strlen")')
608 " Extending List directly with different types
609 py3 l += [1, "as'd", [1, 2, f, {'a': 1}]]
610 call assert_equal([1, "as'd", [1, 2, function("strlen"), {'a': 1}]], l)
611 call assert_equal([1, 2, function("strlen"), {'a': 1}], l[-1])
612 call assert_fails('echo l[-4]', 'E684:')
613
614 " List assignment
615 py3 l[0] = 0
616 call assert_equal([0, "as'd", [1, 2, function("strlen"), {'a': 1}]], l)
617 py3 l[-2] = f
618 call assert_equal([0, function("strlen"), [1, 2, function("strlen"), {'a': 1}]], l)
Bram Moolenaarab589462020-07-06 21:03:06 +0200619
620 " appending to a list
621 let l = [1, 2]
622 py3 ll = vim.bindeval('l')
623 py3 ll[2] = 8
624 call assert_equal([1, 2, 8], l)
625
Bram Moolenaar21578272021-02-21 19:12:47 +0100626 " iterating over list from Python
627 py3 print([x for x in vim.Function("getline")(1, 2)])
628
Bram Moolenaarab589462020-07-06 21:03:06 +0200629 " Using dict as an index
630 call AssertException(['py3 ll[{}] = 10'],
631 \ 'Vim(py3):TypeError: index must be int or slice, not dict')
632endfunc
633
Yegappan Lakshmanan038be272025-03-26 18:46:21 +0100634" Test for the python Tuple object
635func Test_python3_tuple()
636 " Try to convert a null tuple
637 call AssertException(["py3 l = vim.eval('test_null_tuple()')"],
638 \ s:system_error_pat)
639
640 " Try to convert a Tuple with a null Tuple item
641 call AssertException(["py3 t = vim.eval('(test_null_tuple(),)')"],
642 \ s:system_error_pat)
643
644 " Try to convert a List with a null Tuple item
645 call AssertException(["py3 t = vim.eval('[test_null_tuple()]')"],
646 \ s:system_error_pat)
647
648 " Try to convert a Tuple with a null List item
649 call AssertException(["py3 t = vim.eval('(test_null_list(),)')"],
650 \ s:system_error_pat)
651
652 " Try to bind a null Tuple variable (works because an empty tuple is used)
653 let cmds =<< trim END
654 let t = test_null_tuple()
655 py3 tt = vim.bindeval('t')
656 END
657 call AssertException(cmds, '')
658
659 " Creating a tuple using different iterators
660 py3 t1 = vim.Tuple(['abc', 20, 1.2, (4, 5)])
661 call assert_equal(('abc', 20, 1.2, (4, 5)), py3eval('t1'))
662 py3 t2 = vim.Tuple('abc')
663 call assert_equal(('a', 'b', 'c'), py3eval('t2'))
664 py3 t3 = vim.Tuple({'color': 'red', 'model': 'ford'})
665 call assert_equal(('color', 'model'), py3eval('t3'))
666 py3 t4 = vim.Tuple()
667 call assert_equal((), py3eval('t4'))
668 py3 t5 = vim.Tuple(x**2 for x in range(5))
669 call assert_equal((0, 1, 4, 9, 16), py3eval('t5'))
670 py3 t6 = vim.Tuple(('abc', 20, 1.2, (4, 5)))
671 call assert_equal(('abc', 20, 1.2, (4, 5)), py3eval('t6'))
672
673 " Convert between Vim tuple/list and python tuple/list
674 py3 t = vim.Tuple(vim.bindeval("('a', ('b',), ['c'], {'s': 'd'})"))
675 call assert_equal(('a', ('b',), ['c'], {'s': 'd'}), py3eval('t'))
676 call assert_equal(['a', ('b',), ['c'], {'s': 'd'}], py3eval('list(t)'))
677 call assert_equal(('a', ('b',), ['c'], {'s': 'd'}), py3eval('tuple(t)'))
678
679 py3 l = vim.List(vim.bindeval("['e', ('f',), ['g'], {'s': 'h'}]"))
680 call assert_equal(('e', ('f',), ['g'], {'s': 'h'}), py3eval('tuple(l)'))
681
682 " Tuple assignment
683 py3 tt = vim.bindeval('("a", "b")')
684 call AssertException(['py3 tt[0] = 10'],
685 \ "Vim(py3):TypeError: 'vim.tuple' object does not support item assignment")
686 py3 tt = vim.bindeval('("a", "b")')
687 call AssertException(['py3 tt[0:1] = (10, 20)'],
688 \ "Vim(py3):TypeError: 'vim.tuple' object does not support item assignment")
689
690 " iterating over tuple from Python
691 py3 print([x for x in vim.bindeval("('a', 'b')")])
692
693 " modifying a list item within a tuple
694 let t = ('a', ['b', 'c'], 'd')
695 py3 vim.bindeval('t')[1][1] = 'x'
696 call assert_equal(('a', ['b', 'x'], 'd'), t)
697
698 " length of a tuple
699 let t = ()
700 py3 p_t = vim.bindeval('t')
701 call assert_equal(0, py3eval('len(p_t)'))
702 let t = ('a', )
703 py3 p_t = vim.bindeval('t')
704 call assert_equal(1, py3eval('len(p_t)'))
705 let t = ('a', 'b', 'c')
706 py3 p_t = vim.bindeval('t')
707 call assert_equal(3, py3eval('len(p_t)'))
708
709 " membership test
710 let t = ('a', 'b', 'c')
711 py3 p_t = vim.bindeval('t')
712 call assert_true(py3eval("b'c' in p_t"))
713 call assert_true(py3eval("b'd' not in p_t"))
714
715 py3 x = vim.eval('("a", (2), [3], {})')
716 call assert_equal(('a', '2', ['3'], {}), py3eval('x'))
717
718 " Using a keyword argument for a tuple
719 call AssertException(['py3 x = vim.Tuple(a=1)'],
720 \ 'Vim(py3):TypeError: tuple constructor does not accept keyword arguments')
721
722 " Using dict as an index
723 call AssertException(['py3 x = tt[{}]'],
724 \ 'Vim(py3):TypeError: index must be int or slice, not dict')
725 call AssertException(['py3 x = tt["abc"]'],
726 \ 'Vim(py3):TypeError: index must be int or slice, not str')
727
728 call AssertException(['py3 del tt.locked'],
729 \ 'Vim(py3):AttributeError: cannot delete vim.Tuple attributes')
730
731 call AssertException(['py3 tt.foobar = 1'],
732 \ 'Vim(py3):AttributeError: cannot set attribute foobar')
733endfunc
734
Bram Moolenaarab589462020-07-06 21:03:06 +0200735" Test for the python Dict object
736func Test_python3_dict()
737 " Try to convert a null Dict
738 call AssertException(["py3 t = vim.eval('test_null_dict()')"],
Bram Moolenaar07761a32020-12-22 12:50:10 +0100739 \ s:system_error_pat)
Bram Moolenaarab589462020-07-06 21:03:06 +0200740
741 " Try to convert a Dict with a null List value
742 call AssertException(["py3 t = vim.eval(\"{'a' : test_null_list()}\")"],
Bram Moolenaar07761a32020-12-22 12:50:10 +0100743 \ s:system_error_pat)
Bram Moolenaarab589462020-07-06 21:03:06 +0200744
745 " Try to convert a Dict with a null string key
746 py3 t = vim.eval("{test_null_string() : 10}")
747 call assert_fails("let d = py3eval('t')", 'E859:')
748
749 " Dict length
750 let d = {'a' : 10, 'b' : 20}
751 py3 d = vim.bindeval('d')
752 call assert_equal(2, py3eval('len(d)'))
753
Dominique Pelle923dce22021-11-21 11:36:04 +0000754 " Deleting a non-existing key
Bram Moolenaarab589462020-07-06 21:03:06 +0200755 call AssertException(["py3 del d['c']"], "Vim(py3):KeyError: 'c'")
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200756endfunc
757
758" Extending Dictionary directly with different types
759func Test_python3_dict_extend()
760 let d = {}
761 func d.f()
762 return 1
763 endfunc
764
765 py3 f = vim.bindeval('function("strlen")')
766 py3 << trim EOF
767 d = vim.bindeval('d')
768 d['1'] = 'asd'
769 d.update() # Must not do anything, including throwing errors
770 d.update(b = [1, 2, f])
771 d.update((('-1', {'a': 1}),))
772 d.update({'0': -1})
773 dk = d.keys()
774 dv = d.values()
775 di = d.items()
776 dk.sort(key=repr)
777 dv.sort(key=repr)
778 di.sort(key=repr)
779 EOF
780
Bram Moolenaarab589462020-07-06 21:03:06 +0200781 " Try extending a locked dictionary
782 lockvar d
783 call AssertException(["py3 d.update({'b' : 20})"],
784 \ 'Vim(py3):vim.error: dictionary is locked')
785 unlockvar d
786
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200787 call assert_equal(1, py3eval("d['f'](self={})"))
788 call assert_equal("[b'-1', b'0', b'1', b'b', b'f']", py3eval('repr(dk)'))
789 call assert_equal("[-1, <vim.Function '1'>, <vim.dictionary object at >, <vim.list object at >, b'asd']", substitute(py3eval('repr(dv)'),'0x\x\+','','g'))
790 call assert_equal("[(b'-1', <vim.dictionary object at >), (b'0', -1), (b'1', b'asd'), (b'b', <vim.list object at >), (b'f', <vim.Function '1'>)]", substitute(py3eval('repr(di)'),'0x\x\+','','g'))
791 call assert_equal(['0', '1', 'b', 'f', '-1'], keys(d))
792 call assert_equal("[-1, 'asd', [1, 2, function('strlen')], function('1'), {'a': 1}]", string(values(d)))
793 py3 del dk
794 py3 del di
795 py3 del dv
796endfunc
797
798func Test_python3_list_del_items()
799 " removing items with del
800 let l = [0, function("strlen"), [1, 2, function("strlen"), {'a': 1}]]
801 py3 l = vim.bindeval('l')
802 py3 del l[2]
803 call assert_equal("[0, function('strlen')]", string(l))
804
805 let l = range(8)
806 py3 l = vim.bindeval('l')
807 py3 del l[:3]
808 py3 del l[1:]
809 call assert_equal([3], l)
810
811 " removing items out of range: silently skip items that don't exist
812
813 " The following two ranges delete nothing as they match empty list:
814 let l = [0, 1, 2, 3]
815 py3 l = vim.bindeval('l')
816 py3 del l[2:1]
817 call assert_equal([0, 1, 2, 3], l)
818 py3 del l[2:2]
819 call assert_equal([0, 1, 2, 3], l)
820 py3 del l[2:3]
821 call assert_equal([0, 1, 3], l)
822
823 let l = [0, 1, 2, 3]
824 py3 l = vim.bindeval('l')
825 py3 del l[2:4]
826 call assert_equal([0, 1], l)
827
828 let l = [0, 1, 2, 3]
829 py3 l = vim.bindeval('l')
830 py3 del l[2:5]
831 call assert_equal([0, 1], l)
832
833 let l = [0, 1, 2, 3]
834 py3 l = vim.bindeval('l')
835 py3 del l[2:6]
836 call assert_equal([0, 1], l)
837
838 " The following two ranges delete nothing as they match empty list:
839 let l = [0, 1, 2, 3]
840 py3 l = vim.bindeval('l')
841 py3 del l[-1:2]
842 call assert_equal([0, 1, 2, 3], l)
843 py3 del l[-2:2]
844 call assert_equal([0, 1, 2, 3], l)
845 py3 del l[-3:2]
846 call assert_equal([0, 2, 3], l)
847
848 let l = [0, 1, 2, 3]
849 py3 l = vim.bindeval('l')
850 py3 del l[-4:2]
851 call assert_equal([2, 3], l)
852
853 let l = [0, 1, 2, 3]
854 py3 l = vim.bindeval('l')
855 py3 del l[-5:2]
856 call assert_equal([2, 3], l)
857
858 let l = [0, 1, 2, 3]
859 py3 l = vim.bindeval('l')
860 py3 del l[-6:2]
861 call assert_equal([2, 3], l)
862
863 let l = [0, 1, 2, 3]
864 py3 l = vim.bindeval('l')
865 py3 del l[::2]
866 call assert_equal([1, 3], l)
867
868 let l = [0, 1, 2, 3]
869 py3 l = vim.bindeval('l')
870 py3 del l[3:0:-2]
871 call assert_equal([0, 2], l)
872
873 let l = [0, 1, 2, 3]
874 py3 l = vim.bindeval('l')
875 py3 del l[2:4:-2]
876 let l = [0, 1, 2, 3]
877endfunc
878
879func Test_python3_dict_del_items()
880 let d = eval("{'0' : -1, '1' : 'asd', 'b' : [1, 2, function('strlen')], 'f' : function('min'), '-1' : {'a': 1}}")
881 py3 d = vim.bindeval('d')
882 py3 del d['-1']
883 py3 del d['f']
884 call assert_equal([1, 2, function('strlen')], py3eval('d.get(''b'', 1)'))
885 call assert_equal([1, 2, function('strlen')], py3eval('d.pop(''b'')'))
886 call assert_equal(1, py3eval('d.get(''b'', 1)'))
887 call assert_equal('asd', py3eval('d.pop(''1'', 2)'))
888 call assert_equal(2, py3eval('d.pop(''1'', 2)'))
889 call assert_equal('True', py3eval('repr(d.has_key(''0''))'))
890 call assert_equal('False', py3eval('repr(d.has_key(''1''))'))
891 call assert_equal('True', py3eval('repr(''0'' in d)'))
892 call assert_equal('False', py3eval('repr(''1'' in d)'))
893 call assert_equal("[b'0']", py3eval('repr(list(iter(d)))'))
894 call assert_equal({'0' : -1}, d)
895 call assert_equal("(b'0', -1)", py3eval('repr(d.popitem())'))
896 call assert_equal('None', py3eval('repr(d.get(''0''))'))
897 call assert_equal('[]', py3eval('repr(list(iter(d)))'))
898endfunc
899
900" Slice assignment to a list
901func Test_python3_slice_assignment()
902 let l = [0, 1, 2, 3]
903 py3 l = vim.bindeval('l')
904 py3 l[0:0] = ['a']
905 call assert_equal(['a', 0, 1, 2, 3], l)
906
907 let l = [0, 1, 2, 3]
908 py3 l = vim.bindeval('l')
909 py3 l[1:2] = ['b']
910 call assert_equal([0, 'b', 2, 3], l)
911
912 let l = [0, 1, 2, 3]
913 py3 l = vim.bindeval('l')
914 py3 l[2:4] = ['c']
915 call assert_equal([0, 1, 'c'], l)
916
917 let l = [0, 1, 2, 3]
918 py3 l = vim.bindeval('l')
919 py3 l[4:4] = ['d']
920 call assert_equal([0, 1, 2, 3, 'd'], l)
921
922 let l = [0, 1, 2, 3]
923 py3 l = vim.bindeval('l')
924 py3 l[-1:2] = ['e']
925 call assert_equal([0, 1, 2, 'e', 3], l)
926
927 let l = [0, 1, 2, 3]
928 py3 l = vim.bindeval('l')
929 py3 l[-10:2] = ['f']
930 call assert_equal(['f', 2, 3], l)
931
932 let l = [0, 1, 2, 3]
933 py3 l = vim.bindeval('l')
934 py3 l[2:-10] = ['g']
935 call assert_equal([0, 1, 'g', 2, 3], l)
936
937 let l = []
938 py3 l = vim.bindeval('l')
939 py3 l[0:0] = ['h']
940 call assert_equal(['h'], l)
941
942 let l = range(8)
943 py3 l = vim.bindeval('l')
944 py3 l[2:6:2] = [10, 20]
945 call assert_equal([0, 1, 10, 3, 20, 5, 6, 7], l)
946
947 let l = range(8)
948 py3 l = vim.bindeval('l')
949 py3 l[6:2:-2] = [10, 20]
950 call assert_equal([0, 1, 2, 3, 20, 5, 10, 7], l)
951
952 let l = range(8)
953 py3 l = vim.bindeval('l')
954 py3 l[6:2] = ()
955 call assert_equal([0, 1, 2, 3, 4, 5, 6, 7], l)
956
957 let l = range(8)
958 py3 l = vim.bindeval('l')
959 py3 l[6:2:1] = ()
960 call assert_equal([0, 1, 2, 3, 4, 5, 6, 7], l)
961
962 let l = range(8)
963 py3 l = vim.bindeval('l')
964 py3 l[2:2:1] = ()
965 call assert_equal([0, 1, 2, 3, 4, 5, 6, 7], l)
Bram Moolenaar0ab55d62020-07-07 20:50:39 +0200966
967 call AssertException(["py3 x = l[10:11:0]"],
968 \ "Vim(py3):ValueError: slice step cannot be zero")
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200969endfunc
970
971" Locked variables
972func Test_python3_lockedvar()
973 new
974 py3 cb = vim.current.buffer
975 let l = [0, 1, 2, 3]
976 py3 l = vim.bindeval('l')
977 lockvar! l
978 py3 << trim EOF
979 try:
980 l[2]='i'
981 except vim.error:
982 cb.append('l[2] threw vim.error: ' + emsg(sys.exc_info()))
983 EOF
984 call assert_equal(['', "l[2] threw vim.error: error:('list is locked',)"],
985 \ getline(1, '$'))
Bram Moolenaarab589462020-07-06 21:03:06 +0200986
987 " Try to concatenate a locked list
988 call AssertException(['py3 l += [4, 5]'], 'Vim(py3):vim.error: list is locked')
989
Bram Moolenaareffb0cd2020-07-03 21:17:34 +0200990 call assert_equal([0, 1, 2, 3], l)
991 unlockvar! l
992 close!
993endfunc
994
995" Test for calling a function
996func Test_python3_function_call()
997 func New(...)
998 return ['NewStart'] + a:000 + ['NewEnd']
999 endfunc
1000
1001 func DictNew(...) dict
1002 return ['DictNewStart'] + a:000 + ['DictNewEnd', self]
1003 endfunc
1004
1005 new
1006 let l = [function('New'), function('DictNew')]
1007 py3 l = vim.bindeval('l')
1008 py3 l.extend(list(l[0](1, 2, 3)))
1009 call assert_equal([function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd'], l)
1010 py3 l.extend(list(l[1](1, 2, 3, self={'a': 'b'})))
1011 call assert_equal([function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}], l)
1012 py3 l += [[l[0].name]]
1013 call assert_equal([function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}, ['New']], l)
1014 py3 ee('l[1](1, 2, 3)')
1015 call assert_equal("l[1](1, 2, 3):(<class 'vim.error'>, error('Vim:E725: Calling dict function without Dictionary: DictNew',))", getline(2))
1016 %d
1017 py3 f = l[0]
1018 delfunction New
1019 py3 ee('f(1, 2, 3)')
1020 call assert_equal("f(1, 2, 3):(<class 'vim.error'>, error('Vim:E117: Unknown function: New',))", getline(2))
1021 close!
1022 delfunction DictNew
1023endfunc
1024
1025func Test_python3_float()
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001026 let l = [0.0]
1027 py3 l = vim.bindeval('l')
1028 py3 l.extend([0.0])
1029 call assert_equal([0.0, 0.0], l)
1030endfunc
1031
1032" Test for Dict key errors
1033func Test_python3_dict_key_error()
1034 let messages = []
1035 py3 << trim EOF
1036 import sys
1037 d = vim.bindeval('{}')
1038 m = vim.bindeval('messages')
1039 def em(expr, g=globals(), l=locals()):
1040 try:
1041 exec(expr, g, l)
1042 except Exception as e:
1043 if sys.version_info >= (3, 5) and e.__class__ is ValueError and str(e) == 'embedded null byte':
1044 m.extend([TypeError.__name__])
1045 else:
1046 m.extend([e.__class__.__name__])
1047
1048 em('d["abc1"]')
1049 em('d["abc1"]="\\0"')
1050 em('d["abc1"]=vim')
1051 em('d[""]=1')
1052 em('d["a\\0b"]=1')
1053 em('d[b"a\\0b"]=1')
1054 em('d.pop("abc1")')
1055 em('d.popitem()')
1056 del em
1057 del m
1058 EOF
1059
1060 call assert_equal(['KeyError', 'TypeError', 'TypeError', 'ValueError',
1061 \ 'TypeError', 'TypeError', 'KeyError', 'KeyError'], messages)
1062 unlet messages
1063endfunc
1064
1065" Test for locked and scope attributes
1066func Test_python3_lock_scope_attr()
1067 let d = {} | let dl = {} | lockvar dl
1068 let res = []
1069 for s in split("d dl v: g:")
1070 let name = tr(s, ':', 's')
1071 execute 'py3 ' .. name .. ' = vim.bindeval("' .. s .. '")'
1072 call add(res, s .. ' : ' .. join(map(['locked', 'scope'],
1073 \ 'v:val .. ":" .. py3eval(name .. "." .. v:val)'), ';'))
1074 endfor
1075 call assert_equal(['d : locked:0;scope:0', 'dl : locked:1;scope:0',
1076 \ 'v: : locked:2;scope:1', 'g: : locked:0;scope:2'], res)
1077
1078 silent! let d.abc2 = 1
1079 silent! let dl.abc3 = 1
1080 py3 d.locked = True
1081 py3 dl.locked = False
1082 silent! let d.def = 1
1083 silent! let dl.def = 1
1084 call assert_equal({'abc2': 1}, d)
1085 call assert_equal({'def': 1}, dl)
1086 unlet d dl
1087
1088 let l = [] | let ll = [] | lockvar ll
1089 let res = []
1090 for s in split("l ll")
1091 let name = tr(s, ':', 's')
1092 execute 'py3 ' .. name .. '=vim.bindeval("' .. s .. '")'
1093 call add(res, s .. ' : locked:' .. py3eval(name .. '.locked'))
1094 endfor
1095 call assert_equal(['l : locked:0', 'll : locked:1'], res)
1096
1097 silent! call extend(l, [0])
1098 silent! call extend(ll, [0])
1099 py3 l.locked = True
1100 py3 ll.locked = False
1101 silent! call extend(l, [1])
1102 silent! call extend(ll, [1])
1103 call assert_equal([0], l)
1104 call assert_equal([1], ll)
1105 unlet l ll
Bram Moolenaarab589462020-07-06 21:03:06 +02001106
1107 " Try changing an attribute of a fixed list
1108 py3 a = vim.bindeval('v:argv')
1109 call AssertException(['py3 a.locked = 0'],
1110 \ 'Vim(py3):TypeError: cannot modify fixed list')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001111endfunc
1112
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001113" Test for locking/unlocking a tuple
1114func Test_tuple_lock()
1115 let t = (1, 2, 3)
1116 py3 t = vim.bindeval('t')
1117 py3 t.locked = True
1118 call assert_equal(1, islocked('t'))
1119 py3 t.locked = False
1120 call assert_equal(0, islocked('t'))
1121endfunc
1122
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001123" Test for py3eval()
1124func Test_python3_pyeval()
1125 let l = py3eval('[0, 1, 2]')
1126 call assert_equal([0, 1, 2], l)
1127
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001128 let t = py3eval('("a", "b", "c")')
1129 call assert_equal(("a", "b", "c"), t)
1130
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001131 let d = py3eval('{"a": "b", "c": 1, "d": ["e"]}')
1132 call assert_equal([['a', 'b'], ['c', 1], ['d', ['e']]], sort(items(d)))
1133
1134 let v:errmsg = ''
1135 call assert_equal(v:none, py3eval('None'))
1136 call assert_equal('', v:errmsg)
1137
Bram Moolenaarab589462020-07-06 21:03:06 +02001138 py3 v = vim.eval('test_null_function()')
1139 call assert_equal(v:none, py3eval('v'))
1140
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01001141 call assert_equal(0.0, py3eval('0.0'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001142
Bram Moolenaarab589462020-07-06 21:03:06 +02001143 " Evaluate an invalid values
1144 call AssertException(['let v = py3eval(''"\0"'')'], 'E859:')
1145 call AssertException(['let v = py3eval(''{"\0" : 1}'')'], 'E859:')
1146 call AssertException(['let v = py3eval("undefined_name")'],
1147 \ "Vim(let):NameError: name 'undefined_name' is not defined")
1148 call AssertException(['let v = py3eval("vim")'], 'E859:')
1149endfunc
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001150
Ben Jacksonea19e782024-11-06 21:50:05 +01001151" Test for py3eval with locals
1152func Test_python3_pyeval_locals()
1153 let str = 'a string'
1154 let num = 0xbadb33f
1155 let d = {'a': 1, 'b': 2, 'c': str}
1156 let l = [ str, num, d ]
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001157 let t = ( str, num, d )
Ben Jacksonea19e782024-11-06 21:50:05 +01001158
1159 let locals = #{
1160 \ s: str,
1161 \ n: num,
1162 \ d: d,
1163 \ l: l,
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001164 \ t: t,
Ben Jacksonea19e782024-11-06 21:50:05 +01001165 \ }
1166
1167 " check basics
1168 call assert_equal('a string', py3eval('s', locals))
1169 call assert_equal(0xbadb33f, py3eval('n', locals))
1170 call assert_equal(d, py3eval('d', locals))
1171 call assert_equal(l, py3eval('l', locals))
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001172 call assert_equal(t, py3eval('t', locals))
Ben Jacksonea19e782024-11-06 21:50:05 +01001173 call assert_equal('a,b,c', py3eval('b",".join(l)', {'l': ['a', 'b', 'c']}))
1174 call assert_equal('hello', 's'->py3eval({'s': 'hello'}))
1175 call assert_equal('a,b,c', 'b",".join(l)'->py3eval({'l': ['a', 'b', 'c']}))
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001176 call assert_equal('a-b-c', 'b"-".join(t)'->py3eval({'t': ('a', 'b', 'c')}))
Ben Jacksonea19e782024-11-06 21:50:05 +01001177
1178 py3 << trim EOF
1179 def __UpdateDict(d, upd):
1180 d.update(upd)
1181 return d
1182
1183 def __ExtendList(l, *args):
1184 l.extend(*args)
1185 return l
1186 EOF
1187
1188 " check assign to dict member works like bindeval
1189 call assert_equal(3, py3eval('__UpdateDict( d, {"c": 3} )["c"]', locals))
1190 call assert_equal(3, d['c'])
1191
1192 " check append lo list
1193 call assert_equal(4, py3eval('len(__ExtendList(l, ["new item"]))', locals))
1194 call assert_equal("new item", l[-1])
1195
1196 " check calling a function
1197 let StrLen = function('strlen')
1198 call assert_equal(3, py3eval('f("abc")', {'f': StrLen}))
1199endfunc
1200
Bram Moolenaarab589462020-07-06 21:03:06 +02001201" Test for vim.bindeval()
1202func Test_python3_vim_bindeval()
1203 " Float
1204 let f = 3.14
1205 py3 f = vim.bindeval('f')
1206 call assert_equal(3.14, py3eval('f'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001207
Bram Moolenaarab589462020-07-06 21:03:06 +02001208 " Blob
1209 let b = 0z12
1210 py3 b = vim.bindeval('b')
1211 call assert_equal("\x12", py3eval('b'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001212
Bram Moolenaarab589462020-07-06 21:03:06 +02001213 " Bool
1214 call assert_equal(1, py3eval("vim.bindeval('v:true')"))
1215 call assert_equal(0, py3eval("vim.bindeval('v:false')"))
1216 call assert_equal(v:none, py3eval("vim.bindeval('v:null')"))
1217 call assert_equal(v:none, py3eval("vim.bindeval('v:none')"))
Bram Moolenaar0ab55d62020-07-07 20:50:39 +02001218
1219 " channel/job
Dominique Pelle56c9fd02021-05-19 00:16:14 +02001220 if has('channel')
1221 call assert_equal(v:none, py3eval("vim.bindeval('test_null_channel()')"))
1222 endif
1223 if has('job')
1224 call assert_equal(v:none, py3eval("vim.bindeval('test_null_job()')"))
1225 endif
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001226endfunc
1227
1228" threading
1229" Running py3do command (Test_pydo) before this test, stops the python thread
1230" from running. So this test should be run before the pydo test
Bram Moolenaarab589462020-07-06 21:03:06 +02001231func Test_aaa_python3_threading()
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001232 let l = [0]
1233 py3 l = vim.bindeval('l')
1234 py3 << trim EOF
1235 import threading
1236 import time
1237
1238 class T(threading.Thread):
1239 def __init__(self):
1240 threading.Thread.__init__(self)
1241 self.t = 0
1242 self.running = True
1243
1244 def run(self):
1245 while self.running:
1246 self.t += 1
1247 time.sleep(0.1)
1248
1249 t = T()
1250 del T
1251 t.start()
1252 EOF
1253
1254 sleep 1
1255 py3 t.running = False
1256 py3 t.join()
1257
1258 " Check if the background thread is working. Count should be 10, but on a
1259 " busy system (AppVeyor) it can be much lower.
1260 py3 l[0] = t.t > 4
1261 py3 del time
1262 py3 del threading
1263 py3 del t
1264 call assert_equal([1], l)
1265endfunc
1266
1267" settrace
1268func Test_python3_settrace()
1269 let l = []
1270 py3 l = vim.bindeval('l')
1271 py3 << trim EOF
1272 import sys
1273
1274 def traceit(frame, event, arg):
1275 global l
1276 if event == "line":
1277 l += [frame.f_lineno]
1278 return traceit
1279
1280 def trace_main():
1281 for i in range(5):
1282 pass
1283 EOF
1284 py3 sys.settrace(traceit)
1285 py3 trace_main()
1286 py3 sys.settrace(None)
1287 py3 del traceit
1288 py3 del trace_main
1289 call assert_equal([1, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 1], l)
1290endfunc
1291
1292" Slice
1293func Test_python3_list_slice()
1294 py3 ll = vim.bindeval('[0, 1, 2, 3, 4, 5]')
1295 py3 l = ll[:4]
1296 call assert_equal([0, 1, 2, 3], py3eval('l'))
1297 py3 l = ll[2:]
1298 call assert_equal([2, 3, 4, 5], py3eval('l'))
1299 py3 l = ll[:-4]
1300 call assert_equal([0, 1], py3eval('l'))
1301 py3 l = ll[-2:]
1302 call assert_equal([4, 5], py3eval('l'))
1303 py3 l = ll[2:4]
1304 call assert_equal([2, 3], py3eval('l'))
1305 py3 l = ll[4:2]
1306 call assert_equal([], py3eval('l'))
1307 py3 l = ll[-4:-2]
1308 call assert_equal([2, 3], py3eval('l'))
1309 py3 l = ll[-2:-4]
1310 call assert_equal([], py3eval('l'))
1311 py3 l = ll[:]
1312 call assert_equal([0, 1, 2, 3, 4, 5], py3eval('l'))
1313 py3 l = ll[0:6]
1314 call assert_equal([0, 1, 2, 3, 4, 5], py3eval('l'))
1315 py3 l = ll[-10:10]
1316 call assert_equal([0, 1, 2, 3, 4, 5], py3eval('l'))
1317 py3 l = ll[4:2:-1]
1318 call assert_equal([4, 3], py3eval('l'))
1319 py3 l = ll[::2]
1320 call assert_equal([0, 2, 4], py3eval('l'))
1321 py3 l = ll[4:2:1]
1322 call assert_equal([], py3eval('l'))
Bram Moolenaarab589462020-07-06 21:03:06 +02001323
1324 " Error case: Use an invalid index
1325 call AssertException(['py3 ll[-10] = 5'], 'Vim(py3):vim.error: internal error:')
1326
1327 " Use a step value of 0
1328 call AssertException(['py3 ll[0:3:0] = [1, 2, 3]'],
1329 \ 'Vim(py3):ValueError: slice step cannot be zero')
1330
1331 " Error case: Invalid slice type
1332 call AssertException(["py3 x = ll['abc']"],
1333 \ "Vim(py3):TypeError: index must be int or slice, not str")
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001334 py3 del l
Bram Moolenaarab589462020-07-06 21:03:06 +02001335
1336 " Error case: List with a null list item
1337 let l = [test_null_list()]
1338 py3 ll = vim.bindeval('l')
1339 call AssertException(["py3 x = ll[:]"],
Bram Moolenaar07761a32020-12-22 12:50:10 +01001340 \ s:system_error_pat)
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001341endfunc
1342
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001343" Slice
1344func Test_python3_tuple_slice()
1345 py3 tt = vim.bindeval('(0, 1, 2, 3, 4, 5)')
1346 py3 t = tt[:4]
1347 call assert_equal((0, 1, 2, 3), py3eval('t'))
1348 py3 t = tt[2:]
1349 call assert_equal((2, 3, 4, 5), py3eval('t'))
1350 py3 t = tt[:-4]
1351 call assert_equal((0, 1), py3eval('t'))
1352 py3 t = tt[-2:]
1353 call assert_equal((4, 5), py3eval('t'))
1354 py3 t = tt[2:4]
1355 call assert_equal((2, 3), py3eval('t'))
1356 py3 t = tt[4:2]
1357 call assert_equal((), py3eval('t'))
1358 py3 t = tt[-4:-2]
1359 call assert_equal((2, 3), py3eval('t'))
1360 py3 t = tt[-2:-4]
1361 call assert_equal((), py3eval('t'))
1362 py3 t = tt[:]
1363 call assert_equal((0, 1, 2, 3, 4, 5), py3eval('t'))
1364 py3 t = tt[0:6]
1365 call assert_equal((0, 1, 2, 3, 4, 5), py3eval('t'))
1366 py3 t = tt[-10:10]
1367 call assert_equal((0, 1, 2, 3, 4, 5), py3eval('t'))
1368 py3 t = tt[4:2:-1]
1369 call assert_equal((4, 3), py3eval('t'))
1370 py3 t = tt[::2]
1371 call assert_equal((0, 2, 4), py3eval('t'))
1372 py3 t = tt[4:2:1]
1373 call assert_equal((), py3eval('t'))
1374
1375 " Error case: Use an invalid index
1376 call AssertException(['py3 x = tt[-10]'], 'Vim(py3):IndexError: tuple index out of range')
1377
1378 " Use a step value of 0
1379 call AssertException(['py3 x = tt[0:3:0]'],
1380 \ 'Vim(py3):ValueError: slice step cannot be zero')
1381
1382 " Error case: Invalid slice type
1383 call AssertException(["py3 x = tt['abc']"],
1384 \ "Vim(py3):TypeError: index must be int or slice, not str")
1385
1386 " Error case: List with a null tuple item
1387 let t = (test_null_tuple(),)
1388 py3 tt = vim.bindeval('t')
1389 call AssertException(["py3 x = tt[:]"], s:system_error_pat)
1390endfunc
1391
1392func Test_python3_pytuple_to_vimtuple()
1393 let t = py3eval("('a', 'b')")
1394 call assert_equal(('a', 'b'), t)
1395 let t = py3eval("()")
1396 call assert_equal((), t)
1397 let t = py3eval("('x',)")
1398 call assert_equal(('x',), t)
1399 let t = py3eval("((1, 2), (), (3, 4))")
1400 call assert_equal(((1, 2), (), (3, 4)), t)
1401 let t = py3eval("((1, 2), {'a': 10}, [5, 6])")
1402 call assert_equal(((1, 2), {'a': 10}, [5, 6]), t)
1403
1404 " Invalid python tuple
1405 py3 << trim END
1406 class FailingIter(object):
1407 def __iter__(self):
1408 raise NotImplementedError('iter')
1409 END
1410 call assert_fails('call py3eval("(1, FailingIter, 2)")',
1411 \ 'E859: Failed to convert returned python object to a Vim value')
1412
1413 py3 del FailingIter
1414endfunc
1415
1416" Test for tuple garbage collection
1417func Test_python3_tuple_garbage_collect()
1418 let t = (1, (2, 3), [4, 5], {'a': 6})
1419 py3 py_t = vim.bindeval('t')
1420 let save_testing = v:testing
1421 let v:testing = 1
1422 call test_garbagecollect_now()
1423 let v:testing = save_testing
1424
1425 let new_t = py3eval('py_t')
1426 call assert_equal((1, (2, 3), [4, 5], {'a': 6}), new_t)
1427endfunc
1428
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001429" Vars
1430func Test_python3_vars()
1431 let g:foo = 'bac'
1432 let w:abc3 = 'def'
1433 let b:baz = 'bar'
1434 let t:bar = 'jkl'
1435 try
1436 throw "Abc"
1437 catch /Abc/
1438 call assert_equal('Abc', py3eval('vim.vvars[''exception'']'))
1439 endtry
1440 call assert_equal('bac', py3eval('vim.vars[''foo'']'))
1441 call assert_equal('def', py3eval('vim.current.window.vars[''abc3'']'))
1442 call assert_equal('bar', py3eval('vim.current.buffer.vars[''baz'']'))
1443 call assert_equal('jkl', py3eval('vim.current.tabpage.vars[''bar'']'))
1444endfunc
1445
1446" Options
1447" paste: boolean, global
1448" previewheight number, global
1449" operatorfunc: string, global
1450" number: boolean, window-local
1451" numberwidth: number, window-local
1452" colorcolumn: string, window-local
1453" statusline: string, window-local/global
1454" autoindent: boolean, buffer-local
1455" shiftwidth: number, buffer-local
1456" omnifunc: string, buffer-local
1457" preserveindent: boolean, buffer-local/global
1458" path: string, buffer-local/global
1459func Test_python3_opts()
1460 let g:res = []
1461 let g:bufs = [bufnr('%')]
1462 new
1463 let g:bufs += [bufnr('%')]
1464 vnew
1465 let g:bufs += [bufnr('%')]
1466 wincmd j
1467 vnew
1468 let g:bufs += [bufnr('%')]
1469 wincmd l
1470
1471 func RecVars(opt)
1472 let gval = string(eval('&g:' .. a:opt))
1473 let wvals = join(map(range(1, 4),
1474 \ 'v:val .. ":" .. string(getwinvar(v:val, "&" .. a:opt))'))
1475 let bvals = join(map(copy(g:bufs),
1476 \ 'v:val .. ":" .. string(getbufvar(v:val, "&" .. a:opt))'))
1477 call add(g:res, ' G: ' .. gval)
1478 call add(g:res, ' W: ' .. wvals)
1479 call add(g:res, ' B: ' .. wvals)
1480 endfunc
1481
1482 py3 << trim EOF
1483 def e(s, g=globals(), l=locals()):
1484 try:
1485 exec(s, g, l)
1486 except Exception as e:
1487 vim.command('return ' + repr(e.__class__.__name__))
1488
1489 def ev(s, g=globals(), l=locals()):
1490 try:
1491 return eval(s, g, l)
1492 except Exception as e:
1493 vim.command('let exc=' + repr(e.__class__.__name__))
1494 return 0
1495 EOF
1496
1497 func E(s)
1498 python3 e(vim.eval('a:s'))
1499 endfunc
1500
1501 func Ev(s)
1502 let r = py3eval('ev(vim.eval("a:s"))')
1503 if exists('exc')
1504 throw exc
1505 endif
1506 return r
1507 endfunc
1508
1509 py3 gopts1 = vim.options
1510 py3 wopts1 = vim.windows[2].options
1511 py3 wopts2 = vim.windows[0].options
1512 py3 wopts3 = vim.windows[1].options
1513 py3 bopts1 = vim.buffers[vim.bindeval("g:bufs")[2]].options
1514 py3 bopts2 = vim.buffers[vim.bindeval("g:bufs")[1]].options
1515 py3 bopts3 = vim.buffers[vim.bindeval("g:bufs")[0]].options
1516 call add(g:res, 'wopts iters equal: ' ..
1517 \ py3eval('list(wopts1) == list(wopts2)'))
1518 call add(g:res, 'bopts iters equal: ' ..
1519 \ py3eval('list(bopts1) == list(bopts2)'))
1520 py3 gset = set(iter(gopts1))
1521 py3 wset = set(iter(wopts1))
1522 py3 bset = set(iter(bopts1))
1523
1524 set path=.,..,,
1525 let lst = []
1526 let lst += [['paste', 1, 0, 1, 2, 1, 1, 0]]
1527 let lst += [['previewheight', 5, 1, 6, 'a', 0, 1, 0]]
1528 let lst += [['operatorfunc', 'A', 'B', 'C', 2, 0, 1, 0]]
1529 let lst += [['number', 0, 1, 1, 0, 1, 0, 1]]
1530 let lst += [['numberwidth', 2, 3, 5, -100, 0, 0, 1]]
1531 let lst += [['colorcolumn', '+1', '+2', '+3', 'abc4', 0, 0, 1]]
1532 let lst += [['statusline', '1', '2', '4', 0, 0, 1, 1]]
1533 let lst += [['autoindent', 0, 1, 1, 2, 1, 0, 2]]
1534 let lst += [['shiftwidth', 0, 2, 1, 3, 0, 0, 2]]
1535 let lst += [['omnifunc', 'A', 'B', 'C', 1, 0, 0, 2]]
1536 let lst += [['preserveindent', 0, 1, 1, 2, 1, 1, 2]]
1537 let lst += [['path', '.,,', ',,', '.', 0, 0, 1, 2]]
1538 for [oname, oval1, oval2, oval3, invval, bool, global, local] in lst
1539 py3 oname = vim.eval('oname')
1540 py3 oval1 = vim.bindeval('oval1')
1541 py3 oval2 = vim.bindeval('oval2')
1542 py3 oval3 = vim.bindeval('oval3')
1543 if invval is 0 || invval is 1
1544 py3 invval = bool(vim.bindeval('invval'))
1545 else
1546 py3 invval = vim.bindeval('invval')
1547 endif
1548 if bool
1549 py3 oval1 = bool(oval1)
1550 py3 oval2 = bool(oval2)
1551 py3 oval3 = bool(oval3)
1552 endif
1553 call add(g:res, '>>> ' .. oname)
1554 call add(g:res, ' g/w/b:' .. py3eval('oname in gset') .. '/' ..
1555 \ py3eval('oname in wset') .. '/' .. py3eval('oname in bset'))
1556 call add(g:res, ' g/w/b (in):' .. py3eval('oname in gopts1') .. '/' ..
1557 \ py3eval('oname in wopts1') .. '/' .. py3eval('oname in bopts1'))
1558 for v in ['gopts1', 'wopts1', 'bopts1']
1559 try
1560 call add(g:res, ' p/' .. v .. ': ' .. Ev('repr(' .. v .. '[''' .. oname .. '''])'))
1561 catch
1562 call add(g:res, ' p/' .. v .. '! ' .. v:exception)
1563 endtry
1564 let r = E(v .. '[''' .. oname .. ''']=invval')
1565 if r isnot 0
1566 call add(g:res, ' inv: ' .. string(invval) .. '! ' .. r)
1567 endif
1568 for vv in (v is# 'gopts1' ? [v] : [v, v[:-2] .. '2', v[:-2] .. '3'])
1569 let val = substitute(vv, '^.opts', 'oval', '')
1570 let r = E(vv .. '[''' .. oname .. ''']=' .. val)
1571 if r isnot 0
1572 call add(g:res, ' ' .. vv .. '! ' .. r)
1573 endif
1574 endfor
1575 endfor
1576 call RecVars(oname)
1577 for v in ['wopts3', 'bopts3']
1578 let r = E('del ' .. v .. '["' .. oname .. '"]')
1579 if r isnot 0
1580 call add(g:res, ' del ' .. v .. '! ' .. r)
1581 endif
1582 endfor
1583 call RecVars(oname)
1584 endfor
1585 delfunction RecVars
1586 delfunction E
1587 delfunction Ev
1588 py3 del ev
1589 py3 del e
1590 only
1591 for buf in g:bufs[1:]
1592 execute 'bwipeout!' buf
1593 endfor
1594 py3 del gopts1
1595 py3 del wopts1
1596 py3 del wopts2
1597 py3 del wopts3
1598 py3 del bopts1
1599 py3 del bopts2
1600 py3 del bopts3
1601 py3 del oval1
1602 py3 del oval2
1603 py3 del oval3
1604 py3 del oname
1605 py3 del invval
1606
1607 let expected =<< trim END
1608 wopts iters equal: 1
1609 bopts iters equal: 1
1610 >>> paste
1611 g/w/b:1/0/0
1612 g/w/b (in):1/0/0
1613 p/gopts1: False
1614 p/wopts1! KeyError
1615 inv: 2! KeyError
1616 wopts1! KeyError
1617 wopts2! KeyError
1618 wopts3! KeyError
1619 p/bopts1! KeyError
1620 inv: 2! KeyError
1621 bopts1! KeyError
1622 bopts2! KeyError
1623 bopts3! KeyError
1624 G: 1
1625 W: 1:1 2:1 3:1 4:1
1626 B: 1:1 2:1 3:1 4:1
1627 del wopts3! KeyError
1628 del bopts3! KeyError
1629 G: 1
1630 W: 1:1 2:1 3:1 4:1
1631 B: 1:1 2:1 3:1 4:1
1632 >>> previewheight
1633 g/w/b:1/0/0
1634 g/w/b (in):1/0/0
1635 p/gopts1: 12
1636 inv: 'a'! TypeError
1637 p/wopts1! KeyError
1638 inv: 'a'! KeyError
1639 wopts1! KeyError
1640 wopts2! KeyError
1641 wopts3! KeyError
1642 p/bopts1! KeyError
1643 inv: 'a'! KeyError
1644 bopts1! KeyError
1645 bopts2! KeyError
1646 bopts3! KeyError
1647 G: 5
1648 W: 1:5 2:5 3:5 4:5
1649 B: 1:5 2:5 3:5 4:5
1650 del wopts3! KeyError
1651 del bopts3! KeyError
1652 G: 5
1653 W: 1:5 2:5 3:5 4:5
1654 B: 1:5 2:5 3:5 4:5
1655 >>> operatorfunc
1656 g/w/b:1/0/0
1657 g/w/b (in):1/0/0
1658 p/gopts1: b''
1659 inv: 2! TypeError
1660 p/wopts1! KeyError
1661 inv: 2! KeyError
1662 wopts1! KeyError
1663 wopts2! KeyError
1664 wopts3! KeyError
1665 p/bopts1! KeyError
1666 inv: 2! KeyError
1667 bopts1! KeyError
1668 bopts2! KeyError
1669 bopts3! KeyError
1670 G: 'A'
1671 W: 1:'A' 2:'A' 3:'A' 4:'A'
1672 B: 1:'A' 2:'A' 3:'A' 4:'A'
1673 del wopts3! KeyError
1674 del bopts3! KeyError
1675 G: 'A'
1676 W: 1:'A' 2:'A' 3:'A' 4:'A'
1677 B: 1:'A' 2:'A' 3:'A' 4:'A'
1678 >>> number
1679 g/w/b:0/1/0
1680 g/w/b (in):0/1/0
1681 p/gopts1! KeyError
1682 inv: 0! KeyError
1683 gopts1! KeyError
1684 p/wopts1: False
1685 p/bopts1! KeyError
1686 inv: 0! KeyError
1687 bopts1! KeyError
1688 bopts2! KeyError
1689 bopts3! KeyError
1690 G: 0
1691 W: 1:1 2:1 3:0 4:0
1692 B: 1:1 2:1 3:0 4:0
1693 del wopts3! ValueError
1694 del bopts3! KeyError
1695 G: 0
1696 W: 1:1 2:1 3:0 4:0
1697 B: 1:1 2:1 3:0 4:0
1698 >>> numberwidth
1699 g/w/b:0/1/0
1700 g/w/b (in):0/1/0
1701 p/gopts1! KeyError
1702 inv: -100! KeyError
1703 gopts1! KeyError
1704 p/wopts1: 4
1705 inv: -100! error
1706 p/bopts1! KeyError
1707 inv: -100! KeyError
1708 bopts1! KeyError
1709 bopts2! KeyError
1710 bopts3! KeyError
1711 G: 4
1712 W: 1:3 2:5 3:2 4:4
1713 B: 1:3 2:5 3:2 4:4
1714 del wopts3! ValueError
1715 del bopts3! KeyError
1716 G: 4
1717 W: 1:3 2:5 3:2 4:4
1718 B: 1:3 2:5 3:2 4:4
1719 >>> colorcolumn
1720 g/w/b:0/1/0
1721 g/w/b (in):0/1/0
1722 p/gopts1! KeyError
1723 inv: 'abc4'! KeyError
1724 gopts1! KeyError
1725 p/wopts1: b''
1726 inv: 'abc4'! error
1727 p/bopts1! KeyError
1728 inv: 'abc4'! KeyError
1729 bopts1! KeyError
1730 bopts2! KeyError
1731 bopts3! KeyError
1732 G: ''
1733 W: 1:'+2' 2:'+3' 3:'+1' 4:''
1734 B: 1:'+2' 2:'+3' 3:'+1' 4:''
1735 del wopts3! ValueError
1736 del bopts3! KeyError
1737 G: ''
1738 W: 1:'+2' 2:'+3' 3:'+1' 4:''
1739 B: 1:'+2' 2:'+3' 3:'+1' 4:''
1740 >>> statusline
1741 g/w/b:1/1/0
1742 g/w/b (in):1/1/0
1743 p/gopts1: b''
1744 inv: 0! TypeError
1745 p/wopts1: None
1746 inv: 0! TypeError
1747 p/bopts1! KeyError
1748 inv: 0! KeyError
1749 bopts1! KeyError
1750 bopts2! KeyError
1751 bopts3! KeyError
1752 G: '1'
1753 W: 1:'2' 2:'4' 3:'1' 4:'1'
1754 B: 1:'2' 2:'4' 3:'1' 4:'1'
1755 del bopts3! KeyError
1756 G: '1'
1757 W: 1:'2' 2:'1' 3:'1' 4:'1'
1758 B: 1:'2' 2:'1' 3:'1' 4:'1'
1759 >>> autoindent
1760 g/w/b:0/0/1
1761 g/w/b (in):0/0/1
1762 p/gopts1! KeyError
1763 inv: 2! KeyError
1764 gopts1! KeyError
1765 p/wopts1! KeyError
1766 inv: 2! KeyError
1767 wopts1! KeyError
1768 wopts2! KeyError
1769 wopts3! KeyError
1770 p/bopts1: False
1771 G: 0
1772 W: 1:0 2:1 3:0 4:1
1773 B: 1:0 2:1 3:0 4:1
1774 del wopts3! KeyError
1775 del bopts3! ValueError
1776 G: 0
1777 W: 1:0 2:1 3:0 4:1
1778 B: 1:0 2:1 3:0 4:1
1779 >>> shiftwidth
1780 g/w/b:0/0/1
1781 g/w/b (in):0/0/1
1782 p/gopts1! KeyError
1783 inv: 3! KeyError
1784 gopts1! KeyError
1785 p/wopts1! KeyError
1786 inv: 3! KeyError
1787 wopts1! KeyError
1788 wopts2! KeyError
1789 wopts3! KeyError
1790 p/bopts1: 8
1791 G: 8
1792 W: 1:0 2:2 3:8 4:1
1793 B: 1:0 2:2 3:8 4:1
1794 del wopts3! KeyError
1795 del bopts3! ValueError
1796 G: 8
1797 W: 1:0 2:2 3:8 4:1
1798 B: 1:0 2:2 3:8 4:1
1799 >>> omnifunc
1800 g/w/b:0/0/1
1801 g/w/b (in):0/0/1
1802 p/gopts1! KeyError
1803 inv: 1! KeyError
1804 gopts1! KeyError
1805 p/wopts1! KeyError
1806 inv: 1! KeyError
1807 wopts1! KeyError
1808 wopts2! KeyError
1809 wopts3! KeyError
1810 p/bopts1: b''
1811 inv: 1! TypeError
1812 G: ''
1813 W: 1:'A' 2:'B' 3:'' 4:'C'
1814 B: 1:'A' 2:'B' 3:'' 4:'C'
1815 del wopts3! KeyError
1816 del bopts3! ValueError
1817 G: ''
1818 W: 1:'A' 2:'B' 3:'' 4:'C'
1819 B: 1:'A' 2:'B' 3:'' 4:'C'
1820 >>> preserveindent
1821 g/w/b:0/0/1
1822 g/w/b (in):0/0/1
1823 p/gopts1! KeyError
1824 inv: 2! KeyError
1825 gopts1! KeyError
1826 p/wopts1! KeyError
1827 inv: 2! KeyError
1828 wopts1! KeyError
1829 wopts2! KeyError
1830 wopts3! KeyError
1831 p/bopts1: False
1832 G: 0
1833 W: 1:0 2:1 3:0 4:1
1834 B: 1:0 2:1 3:0 4:1
1835 del wopts3! KeyError
1836 del bopts3! ValueError
1837 G: 0
1838 W: 1:0 2:1 3:0 4:1
1839 B: 1:0 2:1 3:0 4:1
1840 >>> path
1841 g/w/b:1/0/1
1842 g/w/b (in):1/0/1
1843 p/gopts1: b'.,..,,'
1844 inv: 0! TypeError
1845 p/wopts1! KeyError
1846 inv: 0! KeyError
1847 wopts1! KeyError
1848 wopts2! KeyError
1849 wopts3! KeyError
1850 p/bopts1: None
1851 inv: 0! TypeError
1852 G: '.,,'
1853 W: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
1854 B: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
1855 del wopts3! KeyError
1856 G: '.,,'
1857 W: 1:'.,,' 2:',,' 3:'.,,' 4:'.,,'
1858 B: 1:'.,,' 2:',,' 3:'.,,' 4:'.,,'
1859 END
1860
1861 call assert_equal(expected, g:res)
1862 unlet g:res
Bram Moolenaarab589462020-07-06 21:03:06 +02001863
1864 call assert_equal(0, py3eval("'' in vim.options"))
1865
1866 " use an empty key to index vim.options
1867 call AssertException(["let v = py3eval(\"vim.options['']\")"],
1868 \ 'Vim(let):ValueError: empty keys are not allowed')
1869 call AssertException(["py3 vim.current.window.options[''] = 0"],
1870 \ 'Vim(py3):ValueError: empty keys are not allowed')
1871 call AssertException(["py3 vim.current.window.options[{}] = 0"],
1872 \ 'Vim(py3):TypeError: expected bytes() or str() instance, but got dict')
1873
1874 " set one of the number options to a very large number
1875 let cmd = ["py3 vim.options['previewheight'] = 9999999999999999"]
1876 call AssertException(cmd, "Vim(py3):OverflowError:")
1877
1878 " unset a global-local string option
1879 call AssertException(["py3 del vim.options['errorformat']"],
1880 \ 'Vim(py3):ValueError: unable to unset global option errorformat')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001881endfunc
1882
1883" Test for vim.buffer object
1884func Test_python3_buffer()
1885 new
1886 call setline(1, "Hello\nWorld")
1887 call assert_fails("let x = py3eval('vim.current.buffer[0]')", 'E859:')
1888 %bw!
1889
1890 edit Xfile1
1891 let bnr1 = bufnr()
1892 py3 cb = vim.current.buffer
1893 vnew Xfile2
1894 let bnr2 = bufnr()
1895 call setline(1, ['First line', 'Second line', 'Third line'])
1896 py3 b = vim.current.buffer
1897 wincmd w
1898
Bram Moolenaarab589462020-07-06 21:03:06 +02001899 " Test for getting lines from the buffer using a slice
1900 call assert_equal(['First line'], py3eval('b[-10:1]'))
1901 call assert_equal(['Third line'], py3eval('b[2:10]'))
1902 call assert_equal([], py3eval('b[2:0]'))
1903 call assert_equal([], py3eval('b[10:12]'))
1904 call assert_equal([], py3eval('b[-10:-8]'))
Bram Moolenaar0ab55d62020-07-07 20:50:39 +02001905 call AssertException(["py3 x = b[0:3:0]"],
1906 \ 'Vim(py3):ValueError: slice step cannot be zero')
1907 call AssertException(["py3 b[0:3:0] = 'abc'"],
1908 \ 'Vim(py3):ValueError: slice step cannot be zero')
1909 call AssertException(["py3 x = b[{}]"],
1910 \ 'Vim(py3):TypeError: index must be int or slice, not dict')
1911 call AssertException(["py3 b[{}] = 'abc'"],
1912 \ 'Vim(py3):TypeError: index must be int or slice, not dict')
1913
1914 " Test for getting lines using a range
1915 call AssertException(["py3 x = b.range(0,3)[0:2:0]"],
1916 \ "Vim(py3):ValueError: slice step cannot be zero")
1917 call AssertException(["py3 b.range(0,3)[0:2:0] = 'abc'"],
1918 \ "Vim(py3):ValueError: slice step cannot be zero")
Bram Moolenaarab589462020-07-06 21:03:06 +02001919
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001920 " Tests BufferAppend and BufferItem
1921 py3 cb.append(b[0])
1922 call assert_equal(['First line'], getbufline(bnr1, 2))
1923 %d
1924
Bram Moolenaarab589462020-07-06 21:03:06 +02001925 " Try to append using out-of-range line number
1926 call AssertException(["py3 b.append('abc', 10)"],
1927 \ 'Vim(py3):IndexError: line number out of range')
1928
1929 " Append a non-string item
1930 call AssertException(["py3 b.append([22])"],
1931 \ 'Vim(py3):TypeError: expected bytes() or str() instance, but got int')
1932
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02001933 " Tests BufferSlice and BufferAssSlice
1934 py3 cb.append('abc5') # Will be overwritten
1935 py3 cb[-1:] = b[:-2]
1936 call assert_equal(['First line'], getbufline(bnr1, 2))
1937 %d
1938
1939 " Test BufferLength and BufferAssSlice
1940 py3 cb.append('def') # Will not be overwritten
1941 py3 cb[len(cb):] = b[:]
1942 call assert_equal(['def', 'First line', 'Second line', 'Third line'],
1943 \ getbufline(bnr1, 2, '$'))
1944 %d
1945
1946 " Test BufferAssItem and BufferMark
1947 call setbufline(bnr1, 1, ['one', 'two', 'three'])
1948 call cursor(1, 3)
1949 normal ma
1950 py3 cb.append('ghi') # Will be overwritten
1951 py3 cb[-1] = repr((len(cb) - cb.mark('a')[0], cb.mark('a')[1]))
1952 call assert_equal(['(3, 2)'], getbufline(bnr1, 4))
1953 %d
1954
1955 " Test BufferRepr
1956 py3 cb.append(repr(cb) + repr(b))
1957 call assert_equal(['<buffer Xfile1><buffer Xfile2>'], getbufline(bnr1, 2))
1958 %d
1959
1960 " Modify foreign buffer
1961 py3 << trim EOF
1962 b.append('foo')
1963 b[0]='bar'
1964 b[0:0]=['baz']
1965 vim.command('call append("$", getbufline(%i, 1, "$"))' % b.number)
1966 EOF
1967 call assert_equal(['baz', 'bar', 'Second line', 'Third line', 'foo'],
1968 \ getbufline(bnr2, 1, '$'))
1969 %d
1970
1971 " Test assigning to name property
1972 augroup BUFS
1973 autocmd BufFilePost * python3 cb.append(vim.eval('expand("<abuf>")') + ':BufFilePost:' + vim.eval('bufnr("%")'))
1974 autocmd BufFilePre * python3 cb.append(vim.eval('expand("<abuf>")') + ':BufFilePre:' + vim.eval('bufnr("%")'))
1975 augroup END
1976 py3 << trim EOF
1977 import os
1978 old_name = cb.name
1979 cb.name = 'foo'
1980 cb.append(cb.name[-11:].replace(os.path.sep, '/'))
1981 b.name = 'bar'
1982 cb.append(b.name[-11:].replace(os.path.sep, '/'))
1983 cb.name = old_name
1984 cb.append(cb.name[-14:].replace(os.path.sep, '/'))
1985 del old_name
1986 EOF
1987 call assert_equal([bnr1 .. ':BufFilePre:' .. bnr1,
1988 \ bnr1 .. ':BufFilePost:' .. bnr1,
1989 \ 'testdir/foo',
1990 \ bnr2 .. ':BufFilePre:' .. bnr2,
1991 \ bnr2 .. ':BufFilePost:' .. bnr2,
1992 \ 'testdir/bar',
1993 \ bnr1 .. ':BufFilePre:' .. bnr1,
1994 \ bnr1 .. ':BufFilePost:' .. bnr1,
1995 \ 'testdir/Xfile1'], getbufline(bnr1, 2, '$'))
1996 %d
1997
1998 " Test CheckBuffer
1999 py3 << trim EOF
2000 for _b in vim.buffers:
2001 if _b is not cb:
2002 vim.command('bwipeout! ' + str(_b.number))
2003 del _b
2004 cb.append('valid: b:%s, cb:%s' % (repr(b.valid), repr(cb.valid)))
2005 EOF
2006 call assert_equal('valid: b:False, cb:True', getline(2))
2007 %d
2008
2009 py3 << trim EOF
2010 for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc6")'):
2011 try:
2012 exec(expr)
2013 except vim.error:
2014 pass
2015 else:
2016 # Usually a SEGV here
2017 # Should not happen in any case
2018 cb.append('No exception for ' + expr)
2019 vim.command('cd .')
2020 del b
2021 EOF
2022 call assert_equal([''], getline(1, '$'))
2023
Bram Moolenaarab589462020-07-06 21:03:06 +02002024 " Delete all the lines in a buffer
2025 call setline(1, ['a', 'b', 'c'])
2026 py3 vim.current.buffer[:] = []
2027 call assert_equal([''], getline(1, '$'))
2028
Bram Moolenaar0ab55d62020-07-07 20:50:39 +02002029 " Test for buffer marks
2030 call assert_equal(v:none, py3eval("vim.current.buffer.mark('r')"))
2031
Bram Moolenaarab589462020-07-06 21:03:06 +02002032 " Test for modifying a 'nomodifiable' buffer
2033 setlocal nomodifiable
2034 call AssertException(["py3 vim.current.buffer[0] = 'abc'"],
2035 \ "Vim(py3):vim.error: Vim:E21: Cannot make changes, 'modifiable' is off")
2036 call AssertException(["py3 vim.current.buffer[0] = None"],
2037 \ "Vim(py3):vim.error: Vim:E21: Cannot make changes, 'modifiable' is off")
2038 call AssertException(["py3 vim.current.buffer[:] = None"],
2039 \ "Vim(py3):vim.error: Vim:E21: Cannot make changes, 'modifiable' is off")
2040 call AssertException(["py3 vim.current.buffer[:] = []"],
2041 \ "Vim(py3):vim.error: Vim:E21: Cannot make changes, 'modifiable' is off")
2042 call AssertException(["py3 vim.current.buffer.append('abc')"],
2043 \ "Vim(py3):vim.error: Vim:E21: Cannot make changes, 'modifiable' is off")
2044 call AssertException(["py3 vim.current.buffer.append([])"],
2045 \ "Vim(py3):vim.error: Vim:E21: Cannot make changes, 'modifiable' is off")
2046 setlocal modifiable
2047
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002048 augroup BUFS
2049 autocmd!
2050 augroup END
2051 augroup! BUFS
2052 %bw!
Bram Moolenaarab589462020-07-06 21:03:06 +02002053
2054 " Range object for a deleted buffer
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002055 new Xp3buffile
Bram Moolenaarab589462020-07-06 21:03:06 +02002056 call setline(1, ['one', 'two', 'three'])
2057 py3 b = vim.current.buffer
2058 py3 r = vim.current.buffer.range(0, 2)
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002059 call assert_equal('<range Xp3buffile (0:2)>', py3eval('repr(r)'))
Bram Moolenaarab589462020-07-06 21:03:06 +02002060 %bw!
2061 call AssertException(['py3 r[:] = []'],
2062 \ 'Vim(py3):vim.error: attempt to refer to deleted buffer')
2063 call assert_match('<buffer object (deleted)', py3eval('repr(b)'))
2064 call assert_match('<range object (for deleted buffer)', py3eval('repr(r)'))
2065 call AssertException(["let n = py3eval('len(r)')"],
2066 \ 'Vim(let):vim.error: attempt to refer to deleted buffer')
2067 call AssertException(["py3 r.append('abc')"],
2068 \ 'Vim(py3):vim.error: attempt to refer to deleted buffer')
2069
2070 " object for a deleted buffer
2071 call AssertException(["py3 b[0] = 'one'"],
2072 \ 'Vim(py3):vim.error: attempt to refer to deleted buffer')
2073 call AssertException(["py3 b.append('one')"],
2074 \ 'Vim(py3):vim.error: attempt to refer to deleted buffer')
2075 call AssertException(["let n = py3eval('len(b)')"],
2076 \ 'Vim(let):vim.error: attempt to refer to deleted buffer')
2077 call AssertException(["py3 pos = b.mark('a')"],
2078 \ 'Vim(py3):vim.error: attempt to refer to deleted buffer')
2079 call AssertException(["py3 vim.current.buffer = b"],
2080 \ 'Vim(py3):vim.error: attempt to refer to deleted buffer')
2081 call AssertException(["py3 rn = b.range(0, 2)"],
2082 \ 'Vim(py3):vim.error: attempt to refer to deleted buffer')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002083endfunc
2084
2085" Test vim.buffers object
2086func Test_python3_buffers()
2087 %bw!
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002088 edit Xp3buffile
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002089 py3 cb = vim.current.buffer
2090 set hidden
2091 edit a
2092 buffer #
2093 edit b
2094 buffer #
2095 edit c
2096 buffer #
2097 py3 << trim EOF
2098 # Check GCing iterator that was not fully exhausted
2099 i = iter(vim.buffers)
2100 cb.append('i:' + str(next(i)))
2101 # and also check creating more than one iterator at a time
2102 i2 = iter(vim.buffers)
2103 cb.append('i2:' + str(next(i2)))
2104 cb.append('i:' + str(next(i)))
2105 # The following should trigger GC and not cause any problems
2106 del i
2107 del i2
2108 i3 = iter(vim.buffers)
2109 cb.append('i3:' + str(next(i3)))
2110 del i3
2111 EOF
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002112 call assert_equal(['i:<buffer Xp3buffile>',
2113 \ 'i2:<buffer Xp3buffile>', 'i:<buffer a>', 'i3:<buffer Xp3buffile>'],
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002114 \ getline(2, '$'))
2115 %d
2116
2117 py3 << trim EOF
2118 prevnum = 0
2119 for b in vim.buffers:
2120 # Check buffer order
2121 if prevnum >= b.number:
2122 cb.append('!!! Buffer numbers not in strictly ascending order')
2123 # Check indexing: vim.buffers[number].number == number
2124 cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + \
2125 '=' + repr(b))
2126 prevnum = b.number
2127 del prevnum
2128
2129 cb.append(str(len(vim.buffers)))
2130 EOF
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002131 call assert_equal([bufnr('Xp3buffile') .. ':<buffer Xp3buffile>=<buffer Xp3buffile>',
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002132 \ bufnr('a') .. ':<buffer a>=<buffer a>',
2133 \ bufnr('b') .. ':<buffer b>=<buffer b>',
2134 \ bufnr('c') .. ':<buffer c>=<buffer c>', '4'], getline(2, '$'))
2135 %d
2136
2137 py3 << trim EOF
2138 bnums = list(map(lambda b: b.number, vim.buffers))[1:]
2139
2140 # Test wiping out buffer with existing iterator
2141 i4 = iter(vim.buffers)
2142 cb.append('i4:' + str(next(i4)))
2143 vim.command('bwipeout! ' + str(bnums.pop(0)))
2144 try:
2145 next(i4)
2146 except vim.error:
2147 pass
2148 else:
2149 cb.append('!!!! No vim.error')
2150 i4 = iter(vim.buffers)
2151 vim.command('bwipeout! ' + str(bnums.pop(-1)))
2152 vim.command('bwipeout! ' + str(bnums.pop(-1)))
2153 cb.append('i4:' + str(next(i4)))
2154 try:
2155 next(i4)
2156 except StopIteration:
2157 cb.append('StopIteration')
2158 del i4
2159 del bnums
2160 EOF
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002161 call assert_equal(['i4:<buffer Xp3buffile>',
2162 \ 'i4:<buffer Xp3buffile>', 'StopIteration'], getline(2, '$'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002163 %bw!
2164endfunc
2165
2166" Test vim.{tabpage,window}list and vim.{tabpage,window} objects
2167func Test_python3_tabpage_window()
2168 %bw
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002169 edit Xp3buffile
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002170 py3 cb = vim.current.buffer
2171 tabnew 0
2172 tabnew 1
2173 vnew a.1
2174 tabnew 2
2175 vnew a.2
2176 vnew b.2
2177 vnew c.2
2178
2179 py3 << trim EOF
2180 cb.append('Number of tabs: ' + str(len(vim.tabpages)))
2181 cb.append('Current tab pages:')
2182 def W(w):
2183 if '(unknown)' in repr(w):
2184 return '<window object (unknown)>'
2185 else:
2186 return repr(w)
2187
2188 def Cursor(w, start=len(cb)):
2189 if w.buffer is cb:
2190 return repr((start - w.cursor[0], w.cursor[1]))
2191 else:
2192 return repr(w.cursor)
2193
2194 for t in vim.tabpages:
2195 cb.append(' ' + repr(t) + '(' + str(t.number) + ')' + ': ' + \
2196 str(len(t.windows)) + ' windows, current is ' + W(t.window))
2197 cb.append(' Windows:')
2198 for w in t.windows:
2199 cb.append(' ' + W(w) + '(' + str(w.number) + ')' + \
2200 ': displays buffer ' + repr(w.buffer) + \
2201 '; cursor is at ' + Cursor(w))
2202 # Other values depend on the size of the terminal, so they are checked
2203 # partly:
2204 for attr in ('height', 'row', 'width', 'col'):
2205 try:
2206 aval = getattr(w, attr)
2207 if type(aval) is not int:
2208 raise TypeError
2209 if aval < 0:
2210 raise ValueError
2211 except Exception as e:
2212 cb.append('!!!!!! Error while getting attribute ' + attr + \
2213 ': ' + e.__class__.__name__)
2214 del aval
2215 del attr
2216 w.cursor = (len(w.buffer), 0)
2217 del W
2218 del Cursor
2219 cb.append('Number of windows in current tab page: ' + \
2220 str(len(vim.windows)))
2221 if list(vim.windows) != list(vim.current.tabpage.windows):
2222 cb.append('!!!!!! Windows differ')
2223 EOF
2224
2225 let expected =<< trim END
2226 Number of tabs: 4
2227 Current tab pages:
2228 <tabpage 0>(1): 1 windows, current is <window object (unknown)>
2229 Windows:
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002230 <window object (unknown)>(1): displays buffer <buffer Xp3buffile>; cursor is at (2, 0)
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002231 <tabpage 1>(2): 1 windows, current is <window object (unknown)>
2232 Windows:
2233 <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
2234 <tabpage 2>(3): 2 windows, current is <window object (unknown)>
2235 Windows:
2236 <window object (unknown)>(1): displays buffer <buffer a.1>; cursor is at (1, 0)
2237 <window object (unknown)>(2): displays buffer <buffer 1>; cursor is at (1, 0)
2238 <tabpage 3>(4): 4 windows, current is <window 0>
2239 Windows:
2240 <window 0>(1): displays buffer <buffer c.2>; cursor is at (1, 0)
2241 <window 1>(2): displays buffer <buffer b.2>; cursor is at (1, 0)
2242 <window 2>(3): displays buffer <buffer a.2>; cursor is at (1, 0)
2243 <window 3>(4): displays buffer <buffer 2>; cursor is at (1, 0)
2244 Number of windows in current tab page: 4
2245 END
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002246 call assert_equal(expected, getbufline(bufnr('Xp3buffile'), 2, '$'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002247 %bw!
2248endfunc
2249
2250" Test vim.current
2251func Test_python3_vim_current()
2252 %bw
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002253 edit Xpy3cfile
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002254 py3 cb = vim.current.buffer
2255 tabnew 0
2256 tabnew 1
2257 vnew a.1
2258 tabnew 2
2259 vnew a.2
2260 vnew b.2
2261 vnew c.2
2262
2263 py3 << trim EOF
2264 def H(o):
2265 return repr(o)
2266 cb.append('Current tab page: ' + repr(vim.current.tabpage))
2267 cb.append('Current window: ' + repr(vim.current.window) + ': ' + \
2268 H(vim.current.window) + ' is ' + H(vim.current.tabpage.window))
2269 cb.append('Current buffer: ' + repr(vim.current.buffer) + ': ' + \
2270 H(vim.current.buffer) + ' is ' + H(vim.current.window.buffer)+ \
2271 ' is ' + H(vim.current.tabpage.window.buffer))
2272 del H
2273 EOF
2274 let expected =<< trim END
2275 Current tab page: <tabpage 3>
2276 Current window: <window 0>: <window 0> is <window 0>
2277 Current buffer: <buffer c.2>: <buffer c.2> is <buffer c.2> is <buffer c.2>
2278 END
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002279 call assert_equal(expected, getbufline(bufnr('Xpy3cfile'), 2, '$'))
2280 call deletebufline(bufnr('Xpy3cfile'), 1, '$')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002281
2282 " Assigning: fails
2283 py3 << trim EOF
2284 try:
2285 vim.current.window = vim.tabpages[0].window
2286 except ValueError:
2287 cb.append('ValueError at assigning foreign tab window')
2288
2289 for attr in ('window', 'tabpage', 'buffer'):
2290 try:
2291 setattr(vim.current, attr, None)
2292 except TypeError:
2293 cb.append('Type error at assigning None to vim.current.' + attr)
2294 del attr
2295 EOF
2296
2297 let expected =<< trim END
2298 ValueError at assigning foreign tab window
2299 Type error at assigning None to vim.current.window
2300 Type error at assigning None to vim.current.tabpage
2301 Type error at assigning None to vim.current.buffer
2302 END
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002303 call assert_equal(expected, getbufline(bufnr('Xpy3cfile'), 2, '$'))
2304 call deletebufline(bufnr('Xpy3cfile'), 1, '$')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002305
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002306 call setbufline(bufnr('Xpy3cfile'), 1, 'python interface')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002307 py3 << trim EOF
2308 # Assigning: success
2309 vim.current.tabpage = vim.tabpages[-2]
2310 vim.current.buffer = cb
2311 vim.current.window = vim.windows[0]
2312 vim.current.window.cursor = (len(vim.current.buffer), 0)
2313 cb.append('Current tab page: ' + repr(vim.current.tabpage))
2314 cb.append('Current window: ' + repr(vim.current.window))
2315 cb.append('Current buffer: ' + repr(vim.current.buffer))
2316 cb.append('Current line: ' + repr(vim.current.line))
2317 EOF
2318
2319 let expected =<< trim END
2320 Current tab page: <tabpage 2>
2321 Current window: <window 0>
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002322 Current buffer: <buffer Xpy3cfile>
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002323 Current line: 'python interface'
2324 END
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002325 call assert_equal(expected, getbufline(bufnr('Xpy3cfile'), 2, '$'))
Bram Moolenaarab589462020-07-06 21:03:06 +02002326 py3 vim.current.line = 'one line'
2327 call assert_equal('one line', getline('.'))
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002328 call deletebufline(bufnr('Xpy3cfile'), 1, '$')
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002329
2330 py3 << trim EOF
2331 ws = list(vim.windows)
2332 ts = list(vim.tabpages)
2333 for b in vim.buffers:
2334 if b is not cb:
2335 vim.command('bwipeout! ' + str(b.number))
2336 del b
2337 cb.append('w.valid: ' + repr([w.valid for w in ws]))
2338 cb.append('t.valid: ' + repr([t.valid for t in ts]))
2339 del w
2340 del t
2341 del ts
2342 del ws
2343 EOF
2344 let expected =<< trim END
2345 w.valid: [True, False]
2346 t.valid: [True, False, True, False]
2347 END
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002348 call assert_equal(expected, getbufline(bufnr('Xpy3cfile'), 2, '$'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002349 %bw!
2350endfunc
2351
2352" Test types
2353func Test_python3_types()
2354 %d
2355 py3 cb = vim.current.buffer
2356 py3 << trim EOF
2357 for expr, attr in (
2358 ('vim.vars', 'Dictionary'),
2359 ('vim.options', 'Options'),
2360 ('vim.bindeval("{}")', 'Dictionary'),
2361 ('vim.bindeval("[]")', 'List'),
2362 ('vim.bindeval("function(\'tr\')")', 'Function'),
2363 ('vim.current.buffer', 'Buffer'),
2364 ('vim.current.range', 'Range'),
2365 ('vim.current.window', 'Window'),
2366 ('vim.current.tabpage', 'TabPage'),
2367 ):
2368 cb.append(expr + ':' + attr + ':' + \
2369 repr(type(eval(expr)) is getattr(vim, attr)))
2370 del expr
2371 del attr
2372 EOF
2373 let expected =<< trim END
2374 vim.vars:Dictionary:True
2375 vim.options:Options:True
2376 vim.bindeval("{}"):Dictionary:True
2377 vim.bindeval("[]"):List:True
2378 vim.bindeval("function('tr')"):Function:True
2379 vim.current.buffer:Buffer:True
2380 vim.current.range:Range:True
2381 vim.current.window:Window:True
2382 vim.current.tabpage:TabPage:True
2383 END
2384 call assert_equal(expected, getline(2, '$'))
2385endfunc
2386
2387" Test __dir__() method
2388func Test_python3_dir_method()
2389 %d
2390 py3 cb = vim.current.buffer
2391 py3 << trim EOF
2392 for name, o in (
2393 ('current', vim.current),
2394 ('buffer', vim.current.buffer),
2395 ('window', vim.current.window),
2396 ('tabpage', vim.current.tabpage),
2397 ('range', vim.current.range),
2398 ('dictionary', vim.bindeval('{}')),
2399 ('list', vim.bindeval('[]')),
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01002400 ('tuple', vim.bindeval('()')),
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002401 ('function', vim.bindeval('function("tr")')),
2402 ('output', sys.stdout),
2403 ):
2404 cb.append(name + ':' + ','.join(dir(o)))
2405 del name
2406 del o
2407 EOF
2408 let expected =<< trim END
2409 current:__dir__,buffer,line,range,tabpage,window
2410 buffer:__dir__,append,mark,name,number,options,range,valid,vars
2411 window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars,width
2412 tabpage:__dir__,number,valid,vars,window,windows
2413 range:__dir__,append,end,start
2414 dictionary:__dir__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
2415 list:__dir__,extend,locked
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01002416 tuple:__dir__,locked
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002417 function:__dir__,args,auto_rebind,self,softspace
2418 output:__dir__,close,closed,flush,isatty,readable,seekable,softspace,writable,write,writelines
2419 END
2420 call assert_equal(expected, getline(2, '$'))
2421endfunc
2422
2423" Test vim.*.__new__
2424func Test_python3_new()
2425 call assert_equal({}, py3eval('vim.Dictionary({})'))
2426 call assert_equal({'a': 1}, py3eval('vim.Dictionary(a=1)'))
2427 call assert_equal({'a': 1}, py3eval('vim.Dictionary(((''a'', 1),))'))
2428 call assert_equal([], py3eval('vim.List()'))
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01002429 call assert_equal((), py3eval('vim.Tuple()'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002430 call assert_equal(['a', 'b', 'c', '7'], py3eval('vim.List(iter(''abc7''))'))
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01002431 call assert_equal(('a', 'b', 'c', '7'), py3eval('vim.Tuple(iter(''abc7''))'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002432 call assert_equal(function('tr'), py3eval('vim.Function(''tr'')'))
2433 call assert_equal(function('tr', [123, 3, 4]),
2434 \ py3eval('vim.Function(''tr'', args=[123, 3, 4])'))
2435 call assert_equal(function('tr'), py3eval('vim.Function(''tr'', args=[])'))
2436 call assert_equal(function('tr', {}),
2437 \ py3eval('vim.Function(''tr'', self={})'))
2438 call assert_equal(function('tr', [123, 3, 4], {}),
2439 \ py3eval('vim.Function(''tr'', args=[123, 3, 4], self={})'))
2440 call assert_equal(function('tr'),
2441 \ py3eval('vim.Function(''tr'', auto_rebind=False)'))
2442 call assert_equal(function('tr', [123, 3, 4]),
2443 \ py3eval('vim.Function(''tr'', args=[123, 3, 4], auto_rebind=False)'))
2444 call assert_equal(function('tr'),
2445 \ py3eval('vim.Function(''tr'', args=[], auto_rebind=False)'))
2446 call assert_equal(function('tr', {}),
2447 \ py3eval('vim.Function(''tr'', self={}, auto_rebind=False)'))
2448 call assert_equal(function('tr', [123, 3, 4], {}),
2449 \ py3eval('vim.Function(''tr'', args=[123, 3, 4], self={}, auto_rebind=False)'))
2450endfunc
2451
2452" Test vim.Function
2453func Test_python3_vim_func()
Bram Moolenaarab589462020-07-06 21:03:06 +02002454 func Args(...)
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002455 return a:000
2456 endfunc
2457
Bram Moolenaarab589462020-07-06 21:03:06 +02002458 func SelfArgs(...) dict
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002459 return [a:000, self]
2460 endfunc
2461
2462 " The following four lines should not crash
2463 let Pt = function('tr', [[]], {'l': []})
2464 py3 Pt = vim.bindeval('Pt')
2465 unlet Pt
2466 py3 del Pt
2467
Bram Moolenaarab589462020-07-06 21:03:06 +02002468 call assert_equal(3, py3eval('vim.strwidth("a\tb")'))
2469
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002470 %bw!
2471 py3 cb = vim.current.buffer
2472 py3 << trim EOF
2473 def ecall(out_prefix, func, *args, **kwargs):
2474 line = out_prefix + ': '
2475 try:
2476 ret = func(*args, **kwargs)
2477 except Exception:
2478 line += '!exception: ' + emsg(sys.exc_info())
2479 else:
2480 line += '!result: ' + str(vim.Function('string')(ret), 'utf-8')
2481 cb.append(line)
2482 a = vim.Function('Args')
2483 pa1 = vim.Function('Args', args=['abcArgsPA1'])
2484 pa2 = vim.Function('Args', args=[])
2485 pa3 = vim.Function('Args', args=['abcArgsPA3'], self={'abcSelfPA3': 'abcSelfPA3Val'})
2486 pa4 = vim.Function('Args', self={'abcSelfPA4': 'abcSelfPA4Val'})
2487 cb.append('a: ' + repr(a))
2488 cb.append('pa1: ' + repr(pa1))
2489 cb.append('pa2: ' + repr(pa2))
2490 cb.append('pa3: ' + repr(pa3))
2491 cb.append('pa4: ' + repr(pa4))
2492 sa = vim.Function('SelfArgs')
2493 psa1 = vim.Function('SelfArgs', args=['abcArgsPSA1'])
2494 psa2 = vim.Function('SelfArgs', args=[])
2495 psa3 = vim.Function('SelfArgs', args=['abcArgsPSA3'], self={'abcSelfPSA3': 'abcSelfPSA3Val'})
2496 psa4 = vim.Function('SelfArgs', self={'abcSelfPSA4': 'abcSelfPSA4Val'})
2497 psa5 = vim.Function('SelfArgs', self={'abcSelfPSA5': 'abcSelfPSA5Val'}, auto_rebind=0)
2498 psa6 = vim.Function('SelfArgs', args=['abcArgsPSA6'], self={'abcSelfPSA6': 'abcSelfPSA6Val'}, auto_rebind=())
2499 psa7 = vim.Function('SelfArgs', args=['abcArgsPSA7'], auto_rebind=[])
2500 psa8 = vim.Function('SelfArgs', auto_rebind=False)
2501 psa9 = vim.Function('SelfArgs', self={'abcSelfPSA9': 'abcSelfPSA9Val'}, auto_rebind=True)
2502 psaA = vim.Function('SelfArgs', args=['abcArgsPSAA'], self={'abcSelfPSAA': 'abcSelfPSAAVal'}, auto_rebind=1)
2503 psaB = vim.Function('SelfArgs', args=['abcArgsPSAB'], auto_rebind={'abcARPSAB': 'abcARPSABVal'})
2504 psaC = vim.Function('SelfArgs', auto_rebind=['abcARPSAC'])
2505 cb.append('sa: ' + repr(sa))
2506 cb.append('psa1: ' + repr(psa1))
2507 cb.append('psa2: ' + repr(psa2))
2508 cb.append('psa3: ' + repr(psa3))
2509 cb.append('psa4: ' + repr(psa4))
2510 cb.append('psa5: ' + repr(psa5))
2511 cb.append('psa6: ' + repr(psa6))
2512 cb.append('psa7: ' + repr(psa7))
2513 cb.append('psa8: ' + repr(psa8))
2514 cb.append('psa9: ' + repr(psa9))
2515 cb.append('psaA: ' + repr(psaA))
2516 cb.append('psaB: ' + repr(psaB))
2517 cb.append('psaC: ' + repr(psaC))
2518
2519 psar = vim.Function('SelfArgs', args=[{'abcArgsPSAr': 'abcArgsPSArVal'}], self={'abcSelfPSAr': 'abcSelfPSArVal'})
2520 psar.args[0]['abcArgsPSAr2'] = [psar.self, psar.args[0]]
2521 psar.self['rec'] = psar
2522 psar.self['self'] = psar.self
2523 psar.self['args'] = psar.args
2524
2525 try:
2526 cb.append('psar: ' + repr(psar))
2527 except Exception:
2528 cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
2529 EOF
2530
2531 let expected =<< trim END
2532 a: <vim.Function 'Args'>
2533 pa1: <vim.Function 'Args', args=['abcArgsPA1']>
2534 pa2: <vim.Function 'Args'>
2535 pa3: <vim.Function 'Args', args=['abcArgsPA3'], self={'abcSelfPA3': 'abcSelfPA3Val'}>
2536 pa4: <vim.Function 'Args', self={'abcSelfPA4': 'abcSelfPA4Val'}>
2537 sa: <vim.Function 'SelfArgs'>
2538 psa1: <vim.Function 'SelfArgs', args=['abcArgsPSA1']>
2539 psa2: <vim.Function 'SelfArgs'>
2540 psa3: <vim.Function 'SelfArgs', args=['abcArgsPSA3'], self={'abcSelfPSA3': 'abcSelfPSA3Val'}>
2541 psa4: <vim.Function 'SelfArgs', self={'abcSelfPSA4': 'abcSelfPSA4Val'}>
2542 psa5: <vim.Function 'SelfArgs', self={'abcSelfPSA5': 'abcSelfPSA5Val'}>
2543 psa6: <vim.Function 'SelfArgs', args=['abcArgsPSA6'], self={'abcSelfPSA6': 'abcSelfPSA6Val'}>
2544 psa7: <vim.Function 'SelfArgs', args=['abcArgsPSA7']>
2545 psa8: <vim.Function 'SelfArgs'>
2546 psa9: <vim.Function 'SelfArgs', self={'abcSelfPSA9': 'abcSelfPSA9Val'}, auto_rebind=True>
2547 psaA: <vim.Function 'SelfArgs', args=['abcArgsPSAA'], self={'abcSelfPSAA': 'abcSelfPSAAVal'}, auto_rebind=True>
2548 psaB: <vim.Function 'SelfArgs', args=['abcArgsPSAB']>
2549 psaC: <vim.Function 'SelfArgs'>
2550 psar: <vim.Function 'SelfArgs', args=[{'abcArgsPSAr2': [{'rec': function('SelfArgs', [{...}], {...}), 'self': {...}, 'abcSelfPSAr': 'abcSelfPSArVal', 'args': [{...}]}, {...}], 'abcArgsPSAr': 'abcArgsPSArVal'}], self={'rec': function('SelfArgs', [{'abcArgsPSAr2': [{...}, {...}], 'abcArgsPSAr': 'abcArgsPSArVal'}], {...}), 'self': {...}, 'abcSelfPSAr': 'abcSelfPSArVal', 'args': [{'abcArgsPSAr2': [{...}, {...}], 'abcArgsPSAr': 'abcArgsPSArVal'}]}>
2551 END
2552 call assert_equal(expected, getline(2, '$'))
2553 %d
2554
2555 call assert_equal(function('Args'), py3eval('a'))
2556 call assert_equal(function('Args', ['abcArgsPA1']), py3eval('pa1'))
2557 call assert_equal(function('Args'), py3eval('pa2'))
2558 call assert_equal(function('Args', ['abcArgsPA3'], {'abcSelfPA3': 'abcSelfPA3Val'}), py3eval('pa3'))
2559 call assert_equal(function('Args', {'abcSelfPA4': 'abcSelfPA4Val'}), py3eval('pa4'))
2560 call assert_equal(function('SelfArgs'), py3eval('sa'))
2561 call assert_equal(function('SelfArgs', ['abcArgsPSA1']), py3eval('psa1'))
2562 call assert_equal(function('SelfArgs'), py3eval('psa2'))
2563 call assert_equal(function('SelfArgs', ['abcArgsPSA3'], {'abcSelfPSA3': 'abcSelfPSA3Val'}), py3eval('psa3'))
2564 call assert_equal(function('SelfArgs', {'abcSelfPSA4': 'abcSelfPSA4Val'}), py3eval('psa4'))
2565 call assert_equal(function('SelfArgs', {'abcSelfPSA5': 'abcSelfPSA5Val'}), py3eval('psa5'))
2566 call assert_equal(function('SelfArgs', ['abcArgsPSA6'], {'abcSelfPSA6': 'abcSelfPSA6Val'}), py3eval('psa6'))
2567 call assert_equal(function('SelfArgs', ['abcArgsPSA7']), py3eval('psa7'))
2568 call assert_equal(function('SelfArgs'), py3eval('psa8'))
2569 call assert_equal(function('SelfArgs', {'abcSelfPSA9': 'abcSelfPSA9Val'}), py3eval('psa9'))
2570 call assert_equal(function('SelfArgs', ['abcArgsPSAA'], {'abcSelfPSAA': 'abcSelfPSAAVal'}), py3eval('psaA'))
2571 call assert_equal(function('SelfArgs', ['abcArgsPSAB']), py3eval('psaB'))
2572 call assert_equal(function('SelfArgs'), py3eval('psaC'))
2573
2574 let res = []
2575 for v in ['sa', 'psa1', 'psa2', 'psa3', 'psa4', 'psa5', 'psa6', 'psa7',
2576 \ 'psa8', 'psa9', 'psaA', 'psaB', 'psaC']
2577 let d = {'f': py3eval(v)}
2578 call add(res, 'd.' .. v .. '(): ' .. string(d.f()))
2579 endfor
2580
2581 let expected =<< trim END
2582 d.sa(): [[], {'f': function('SelfArgs')}]
2583 d.psa1(): [['abcArgsPSA1'], {'f': function('SelfArgs', ['abcArgsPSA1'])}]
2584 d.psa2(): [[], {'f': function('SelfArgs')}]
2585 d.psa3(): [['abcArgsPSA3'], {'abcSelfPSA3': 'abcSelfPSA3Val'}]
2586 d.psa4(): [[], {'abcSelfPSA4': 'abcSelfPSA4Val'}]
2587 d.psa5(): [[], {'abcSelfPSA5': 'abcSelfPSA5Val'}]
2588 d.psa6(): [['abcArgsPSA6'], {'abcSelfPSA6': 'abcSelfPSA6Val'}]
2589 d.psa7(): [['abcArgsPSA7'], {'f': function('SelfArgs', ['abcArgsPSA7'])}]
2590 d.psa8(): [[], {'f': function('SelfArgs')}]
2591 d.psa9(): [[], {'f': function('SelfArgs', {'abcSelfPSA9': 'abcSelfPSA9Val'})}]
2592 d.psaA(): [['abcArgsPSAA'], {'f': function('SelfArgs', ['abcArgsPSAA'], {'abcSelfPSAA': 'abcSelfPSAAVal'})}]
2593 d.psaB(): [['abcArgsPSAB'], {'f': function('SelfArgs', ['abcArgsPSAB'])}]
2594 d.psaC(): [[], {'f': function('SelfArgs')}]
2595 END
2596 call assert_equal(expected, res)
2597
2598 py3 ecall('a()', a, )
2599 py3 ecall('pa1()', pa1, )
2600 py3 ecall('pa2()', pa2, )
2601 py3 ecall('pa3()', pa3, )
2602 py3 ecall('pa4()', pa4, )
2603 py3 ecall('sa()', sa, )
2604 py3 ecall('psa1()', psa1, )
2605 py3 ecall('psa2()', psa2, )
2606 py3 ecall('psa3()', psa3, )
2607 py3 ecall('psa4()', psa4, )
2608
2609 py3 ecall('a(42, 43)', a, 42, 43)
2610 py3 ecall('pa1(42, 43)', pa1, 42, 43)
2611 py3 ecall('pa2(42, 43)', pa2, 42, 43)
2612 py3 ecall('pa3(42, 43)', pa3, 42, 43)
2613 py3 ecall('pa4(42, 43)', pa4, 42, 43)
2614 py3 ecall('sa(42, 43)', sa, 42, 43)
2615 py3 ecall('psa1(42, 43)', psa1, 42, 43)
2616 py3 ecall('psa2(42, 43)', psa2, 42, 43)
2617 py3 ecall('psa3(42, 43)', psa3, 42, 43)
2618 py3 ecall('psa4(42, 43)', psa4, 42, 43)
2619
2620 py3 ecall('a(42, self={"20": 1})', a, 42, self={'20': 1})
2621 py3 ecall('pa1(42, self={"20": 1})', pa1, 42, self={'20': 1})
2622 py3 ecall('pa2(42, self={"20": 1})', pa2, 42, self={'20': 1})
2623 py3 ecall('pa3(42, self={"20": 1})', pa3, 42, self={'20': 1})
2624 py3 ecall('pa4(42, self={"20": 1})', pa4, 42, self={'20': 1})
2625 py3 ecall('sa(42, self={"20": 1})', sa, 42, self={'20': 1})
2626 py3 ecall('psa1(42, self={"20": 1})', psa1, 42, self={'20': 1})
2627 py3 ecall('psa2(42, self={"20": 1})', psa2, 42, self={'20': 1})
2628 py3 ecall('psa3(42, self={"20": 1})', psa3, 42, self={'20': 1})
2629 py3 ecall('psa4(42, self={"20": 1})', psa4, 42, self={'20': 1})
2630
2631 py3 ecall('a(self={"20": 1})', a, self={'20': 1})
2632 py3 ecall('pa1(self={"20": 1})', pa1, self={'20': 1})
2633 py3 ecall('pa2(self={"20": 1})', pa2, self={'20': 1})
2634 py3 ecall('pa3(self={"20": 1})', pa3, self={'20': 1})
2635 py3 ecall('pa4(self={"20": 1})', pa4, self={'20': 1})
2636 py3 ecall('sa(self={"20": 1})', sa, self={'20': 1})
2637 py3 ecall('psa1(self={"20": 1})', psa1, self={'20': 1})
2638 py3 ecall('psa2(self={"20": 1})', psa2, self={'20': 1})
2639 py3 ecall('psa3(self={"20": 1})', psa3, self={'20': 1})
2640 py3 ecall('psa4(self={"20": 1})', psa4, self={'20': 1})
2641
2642 py3 << trim EOF
2643 def s(v):
2644 if v is None:
2645 return repr(v)
2646 else:
2647 return str(vim.Function('string')(v), 'utf-8')
2648
2649 cb.append('a.args: ' + s(a.args))
2650 cb.append('pa1.args: ' + s(pa1.args))
2651 cb.append('pa2.args: ' + s(pa2.args))
2652 cb.append('pa3.args: ' + s(pa3.args))
2653 cb.append('pa4.args: ' + s(pa4.args))
2654 cb.append('sa.args: ' + s(sa.args))
2655 cb.append('psa1.args: ' + s(psa1.args))
2656 cb.append('psa2.args: ' + s(psa2.args))
2657 cb.append('psa3.args: ' + s(psa3.args))
2658 cb.append('psa4.args: ' + s(psa4.args))
2659
2660 cb.append('a.self: ' + s(a.self))
2661 cb.append('pa1.self: ' + s(pa1.self))
2662 cb.append('pa2.self: ' + s(pa2.self))
2663 cb.append('pa3.self: ' + s(pa3.self))
2664 cb.append('pa4.self: ' + s(pa4.self))
2665 cb.append('sa.self: ' + s(sa.self))
2666 cb.append('psa1.self: ' + s(psa1.self))
2667 cb.append('psa2.self: ' + s(psa2.self))
2668 cb.append('psa3.self: ' + s(psa3.self))
2669 cb.append('psa4.self: ' + s(psa4.self))
2670
2671 cb.append('a.name: ' + s(a.name))
2672 cb.append('pa1.name: ' + s(pa1.name))
2673 cb.append('pa2.name: ' + s(pa2.name))
2674 cb.append('pa3.name: ' + s(pa3.name))
2675 cb.append('pa4.name: ' + s(pa4.name))
2676 cb.append('sa.name: ' + s(sa.name))
2677 cb.append('psa1.name: ' + s(psa1.name))
2678 cb.append('psa2.name: ' + s(psa2.name))
2679 cb.append('psa3.name: ' + s(psa3.name))
2680 cb.append('psa4.name: ' + s(psa4.name))
2681
2682 cb.append('a.auto_rebind: ' + s(a.auto_rebind))
2683 cb.append('pa1.auto_rebind: ' + s(pa1.auto_rebind))
2684 cb.append('pa2.auto_rebind: ' + s(pa2.auto_rebind))
2685 cb.append('pa3.auto_rebind: ' + s(pa3.auto_rebind))
2686 cb.append('pa4.auto_rebind: ' + s(pa4.auto_rebind))
2687 cb.append('sa.auto_rebind: ' + s(sa.auto_rebind))
2688 cb.append('psa1.auto_rebind: ' + s(psa1.auto_rebind))
2689 cb.append('psa2.auto_rebind: ' + s(psa2.auto_rebind))
2690 cb.append('psa3.auto_rebind: ' + s(psa3.auto_rebind))
2691 cb.append('psa4.auto_rebind: ' + s(psa4.auto_rebind))
2692 cb.append('psa5.auto_rebind: ' + s(psa5.auto_rebind))
2693 cb.append('psa6.auto_rebind: ' + s(psa6.auto_rebind))
2694 cb.append('psa7.auto_rebind: ' + s(psa7.auto_rebind))
2695 cb.append('psa8.auto_rebind: ' + s(psa8.auto_rebind))
2696 cb.append('psa9.auto_rebind: ' + s(psa9.auto_rebind))
2697 cb.append('psaA.auto_rebind: ' + s(psaA.auto_rebind))
2698 cb.append('psaB.auto_rebind: ' + s(psaB.auto_rebind))
2699 cb.append('psaC.auto_rebind: ' + s(psaC.auto_rebind))
2700
2701 del s
2702
2703 del a
2704 del pa1
2705 del pa2
2706 del pa3
2707 del pa4
2708 del sa
2709 del psa1
2710 del psa2
2711 del psa3
2712 del psa4
2713 del psa5
2714 del psa6
2715 del psa7
2716 del psa8
2717 del psa9
2718 del psaA
2719 del psaB
2720 del psaC
2721 del psar
2722
2723 del ecall
2724 EOF
2725
2726 let expected =<< trim END
2727 a(): !result: []
2728 pa1(): !result: ['abcArgsPA1']
2729 pa2(): !result: []
2730 pa3(): !result: ['abcArgsPA3']
2731 pa4(): !result: []
2732 sa(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
2733 psa1(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
2734 psa2(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
2735 psa3(): !result: [['abcArgsPSA3'], {'abcSelfPSA3': 'abcSelfPSA3Val'}]
2736 psa4(): !result: [[], {'abcSelfPSA4': 'abcSelfPSA4Val'}]
2737 a(42, 43): !result: [42, 43]
2738 pa1(42, 43): !result: ['abcArgsPA1', 42, 43]
2739 pa2(42, 43): !result: [42, 43]
2740 pa3(42, 43): !result: ['abcArgsPA3', 42, 43]
2741 pa4(42, 43): !result: [42, 43]
2742 sa(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
2743 psa1(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
2744 psa2(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
2745 psa3(42, 43): !result: [['abcArgsPSA3', 42, 43], {'abcSelfPSA3': 'abcSelfPSA3Val'}]
2746 psa4(42, 43): !result: [[42, 43], {'abcSelfPSA4': 'abcSelfPSA4Val'}]
2747 a(42, self={"20": 1}): !result: [42]
2748 pa1(42, self={"20": 1}): !result: ['abcArgsPA1', 42]
2749 pa2(42, self={"20": 1}): !result: [42]
2750 pa3(42, self={"20": 1}): !result: ['abcArgsPA3', 42]
2751 pa4(42, self={"20": 1}): !result: [42]
2752 sa(42, self={"20": 1}): !result: [[42], {'20': 1}]
2753 psa1(42, self={"20": 1}): !result: [['abcArgsPSA1', 42], {'20': 1}]
2754 psa2(42, self={"20": 1}): !result: [[42], {'20': 1}]
2755 psa3(42, self={"20": 1}): !result: [['abcArgsPSA3', 42], {'20': 1}]
2756 psa4(42, self={"20": 1}): !result: [[42], {'20': 1}]
2757 a(self={"20": 1}): !result: []
2758 pa1(self={"20": 1}): !result: ['abcArgsPA1']
2759 pa2(self={"20": 1}): !result: []
2760 pa3(self={"20": 1}): !result: ['abcArgsPA3']
2761 pa4(self={"20": 1}): !result: []
2762 sa(self={"20": 1}): !result: [[], {'20': 1}]
2763 psa1(self={"20": 1}): !result: [['abcArgsPSA1'], {'20': 1}]
2764 psa2(self={"20": 1}): !result: [[], {'20': 1}]
2765 psa3(self={"20": 1}): !result: [['abcArgsPSA3'], {'20': 1}]
2766 psa4(self={"20": 1}): !result: [[], {'20': 1}]
2767 a.args: None
2768 pa1.args: ['abcArgsPA1']
2769 pa2.args: None
2770 pa3.args: ['abcArgsPA3']
2771 pa4.args: None
2772 sa.args: None
2773 psa1.args: ['abcArgsPSA1']
2774 psa2.args: None
2775 psa3.args: ['abcArgsPSA3']
2776 psa4.args: None
2777 a.self: None
2778 pa1.self: None
2779 pa2.self: None
2780 pa3.self: {'abcSelfPA3': 'abcSelfPA3Val'}
2781 pa4.self: {'abcSelfPA4': 'abcSelfPA4Val'}
2782 sa.self: None
2783 psa1.self: None
2784 psa2.self: None
2785 psa3.self: {'abcSelfPSA3': 'abcSelfPSA3Val'}
2786 psa4.self: {'abcSelfPSA4': 'abcSelfPSA4Val'}
2787 a.name: 'Args'
2788 pa1.name: 'Args'
2789 pa2.name: 'Args'
2790 pa3.name: 'Args'
2791 pa4.name: 'Args'
2792 sa.name: 'SelfArgs'
2793 psa1.name: 'SelfArgs'
2794 psa2.name: 'SelfArgs'
2795 psa3.name: 'SelfArgs'
2796 psa4.name: 'SelfArgs'
2797 a.auto_rebind: 1
2798 pa1.auto_rebind: 1
2799 pa2.auto_rebind: 1
2800 pa3.auto_rebind: 0
2801 pa4.auto_rebind: 0
2802 sa.auto_rebind: 1
2803 psa1.auto_rebind: 1
2804 psa2.auto_rebind: 1
2805 psa3.auto_rebind: 0
2806 psa4.auto_rebind: 0
2807 psa5.auto_rebind: 0
2808 psa6.auto_rebind: 0
2809 psa7.auto_rebind: 1
2810 psa8.auto_rebind: 1
2811 psa9.auto_rebind: 1
2812 psaA.auto_rebind: 1
2813 psaB.auto_rebind: 1
2814 psaC.auto_rebind: 1
2815 END
2816 call assert_equal(expected, getline(2, '$'))
2817 %bw!
2818endfunc
2819
2820" Test stdout/stderr
2821func Test_python3_stdin_stderr()
2822 let caught_writeerr = 0
2823 let caught_writelineerr = 0
2824 redir => messages
2825 py3 sys.stdout.write('abc8') ; sys.stdout.write('def')
2826 try
2827 py3 sys.stderr.write('abc9') ; sys.stderr.write('def')
2828 catch /abc9def/
2829 let caught_writeerr = 1
2830 endtry
2831 py3 sys.stdout.writelines(iter('abcA'))
2832 try
2833 py3 sys.stderr.writelines(iter('abcB'))
2834 catch /abcB/
2835 let caught_writelineerr = 1
2836 endtry
2837 redir END
2838 call assert_equal("\nabc8def\nabcA", messages)
2839 call assert_equal(1, caught_writeerr)
2840 call assert_equal(1, caught_writelineerr)
2841endfunc
2842
2843" Test subclassing
2844func Test_python3_subclass()
2845 new
2846 func Put(...)
2847 return a:000
2848 endfunc
2849
2850 py3 << trim EOF
2851 class DupDict(vim.Dictionary):
2852 def __setitem__(self, key, value):
2853 super(DupDict, self).__setitem__(key, value)
2854 super(DupDict, self).__setitem__('dup_' + key, value)
2855 dd = DupDict()
2856 dd['a'] = 'b'
2857
2858 class DupList(vim.List):
2859 def __getitem__(self, idx):
2860 return [super(DupList, self).__getitem__(idx)] * 2
2861
2862 dl = DupList()
2863 dl2 = DupList(iter('abcC'))
2864 dl.extend(dl2[0])
2865
2866 class DupFun(vim.Function):
2867 def __call__(self, arg):
2868 return super(DupFun, self).__call__(arg, arg)
2869
2870 df = DupFun('Put')
2871 EOF
2872
2873 call assert_equal(['a', 'dup_a'], sort(keys(py3eval('dd'))))
2874 call assert_equal(['a', 'a'], py3eval('dl'))
2875 call assert_equal(['a', 'b', 'c', 'C'], py3eval('dl2'))
2876 call assert_equal([2, 2], py3eval('df(2)'))
2877 call assert_equal(1, py3eval('dl') is# py3eval('dl'))
2878 call assert_equal(1, py3eval('dd') is# py3eval('dd'))
2879 call assert_equal(function('Put'), py3eval('df'))
2880 delfunction Put
2881 py3 << trim EOF
2882 del DupDict
2883 del DupList
2884 del DupFun
2885 del dd
2886 del dl
2887 del dl2
2888 del df
2889 EOF
2890 close!
2891endfunc
2892
2893" Test chdir
2894func Test_python3_chdir()
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002895 new Xp3cdfile
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002896 py3 cb = vim.current.buffer
2897 py3 << trim EOF
2898 import os
2899 fnamemodify = vim.Function('fnamemodify')
2900 cb.append(str(fnamemodify('.', ':p:h:t')))
2901 cb.append(vim.eval('@%'))
2902 os.chdir('..')
2903 path = fnamemodify('.', ':p:h:t')
Bram Moolenaar7d697962020-08-31 21:30:32 +02002904 if path != b'src' and path != b'src2':
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002905 # Running tests from a shadow directory, so move up another level
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002906 # This will result in @% looking like shadow/testdir/Xp3cdfile, hence the
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002907 # slicing to remove the leading path and path separator
2908 os.chdir('..')
2909 cb.append(str(fnamemodify('.', ':p:h:t')))
2910 cb.append(vim.eval('@%')[len(path)+1:].replace(os.path.sep, '/'))
2911 os.chdir(path)
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002912 else:
Bram Moolenaar7d697962020-08-31 21:30:32 +02002913 # Also accept running from src2/testdir/ for MS-Windows CI.
2914 cb.append(str(fnamemodify('.', ':p:h:t').replace(b'src2', b'src')))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002915 cb.append(vim.eval('@%').replace(os.path.sep, '/'))
2916 del path
2917 os.chdir('testdir')
2918 cb.append(str(fnamemodify('.', ':p:h:t')))
2919 cb.append(vim.eval('@%'))
2920 del fnamemodify
2921 EOF
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002922 call assert_equal(["b'testdir'", 'Xp3cdfile', "b'src'", 'testdir/Xp3cdfile',
2923 \"b'testdir'", 'Xp3cdfile'], getline(2, '$'))
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002924 close!
Bram Moolenaar0ab55d62020-07-07 20:50:39 +02002925 call AssertException(["py3 vim.chdir(None)"], "Vim(py3):TypeError:")
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002926endfunc
2927
2928" Test errors
2929func Test_python3_errors()
2930 func F() dict
2931 endfunc
2932
2933 func D()
2934 endfunc
2935
2936 new
2937 py3 cb = vim.current.buffer
2938
2939 py3 << trim EOF
K.Takata1be7e212021-11-16 13:08:56 +00002940 import os
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02002941 d = vim.Dictionary()
2942 ned = vim.Dictionary(foo='bar', baz='abcD')
2943 dl = vim.Dictionary(a=1)
2944 dl.locked = True
2945 l = vim.List()
2946 ll = vim.List('abcE')
2947 ll.locked = True
2948 nel = vim.List('abcO')
2949 f = vim.Function('string')
2950 fd = vim.Function('F')
2951 fdel = vim.Function('D')
2952 vim.command('delfunction D')
2953
2954 def subexpr_test(expr, name, subexprs):
2955 cb.append('>>> Testing %s using %s' % (name, expr))
2956 for subexpr in subexprs:
2957 ee(expr % subexpr)
2958 cb.append('<<< Finished')
2959
2960 def stringtochars_test(expr):
2961 return subexpr_test(expr, 'StringToChars', (
2962 '1', # Fail type checks
2963 'b"\\0"', # Fail PyString_AsStringAndSize(object, , NULL) check
2964 '"\\0"', # Fail PyString_AsStringAndSize(bytes, , NULL) check
2965 ))
2966
2967 class Mapping(object):
2968 def __init__(self, d):
2969 self.d = d
2970
2971 def __getitem__(self, key):
2972 return self.d[key]
2973
2974 def keys(self):
2975 return self.d.keys()
2976
2977 def items(self):
2978 return self.d.items()
2979
2980 def convertfrompyobject_test(expr, recurse=True):
2981 # pydict_to_tv
2982 stringtochars_test(expr % '{%s : 1}')
2983 if recurse:
2984 convertfrompyobject_test(expr % '{"abcF" : %s}', False)
2985 # pymap_to_tv
2986 stringtochars_test(expr % 'Mapping({%s : 1})')
2987 if recurse:
2988 convertfrompyobject_test(expr % 'Mapping({"abcG" : %s})', False)
2989 # pyseq_to_tv
2990 iter_test(expr)
2991 return subexpr_test(expr, 'ConvertFromPyObject', (
2992 'None', # Not conversible
2993 '{b"": 1}', # Empty key not allowed
2994 '{"": 1}', # Same, but with unicode object
2995 'FailingMapping()', #
2996 'FailingMappingKey()', #
2997 'FailingNumber()', #
2998 ))
2999
3000 def convertfrompymapping_test(expr):
3001 convertfrompyobject_test(expr)
3002 return subexpr_test(expr, 'ConvertFromPyMapping', (
3003 '[]',
3004 ))
3005
3006 def iter_test(expr):
3007 return subexpr_test(expr, '*Iter*', (
3008 'FailingIter()',
3009 'FailingIterNext()',
3010 ))
3011
3012 def number_test(expr, natural=False, unsigned=False):
3013 if natural:
3014 unsigned = True
3015 return subexpr_test(expr, 'NumberToLong', (
3016 '[]',
3017 'None',
3018 ) + (('-1',) if unsigned else ())
3019 + (('0',) if natural else ()))
3020
3021 class FailingTrue(object):
3022 def __bool__(self):
3023 raise NotImplementedError('bool')
3024
3025 class FailingIter(object):
3026 def __iter__(self):
3027 raise NotImplementedError('iter')
3028
3029 class FailingIterNext(object):
3030 def __iter__(self):
3031 return self
3032
3033 def __next__(self):
3034 raise NotImplementedError('next')
3035
3036 class FailingIterNextN(object):
3037 def __init__(self, n):
3038 self.n = n
3039
3040 def __iter__(self):
3041 return self
3042
3043 def __next__(self):
3044 if self.n:
3045 self.n -= 1
3046 return 1
3047 else:
3048 raise NotImplementedError('next N')
3049
3050 class FailingMappingKey(object):
3051 def __getitem__(self, item):
3052 raise NotImplementedError('getitem:mappingkey')
3053
3054 def keys(self):
3055 return list("abcH")
3056
3057 class FailingMapping(object):
3058 def __getitem__(self):
3059 raise NotImplementedError('getitem:mapping')
3060
3061 def keys(self):
3062 raise NotImplementedError('keys')
3063
3064 class FailingList(list):
3065 def __getitem__(self, idx):
3066 if i == 2:
3067 raise NotImplementedError('getitem:list')
3068 else:
3069 return super(FailingList, self).__getitem__(idx)
3070
3071 class NoArgsCall(object):
3072 def __call__(self):
3073 pass
3074
3075 class FailingCall(object):
3076 def __call__(self, path):
3077 raise NotImplementedError('call')
3078
3079 class FailingNumber(object):
3080 def __int__(self):
3081 raise NotImplementedError('int')
3082
3083 cb.append("> Output")
3084 cb.append(">> OutputSetattr")
3085 ee('del sys.stdout.softspace')
3086 number_test('sys.stdout.softspace = %s', unsigned=True)
3087 number_test('sys.stderr.softspace = %s', unsigned=True)
3088 ee('assert sys.stdout.isatty()==False')
3089 ee('assert sys.stdout.seekable()==False')
3090 ee('sys.stdout.close()')
3091 ee('sys.stdout.flush()')
3092 ee('assert sys.stderr.isatty()==False')
3093 ee('assert sys.stderr.seekable()==False')
3094 ee('sys.stderr.close()')
3095 ee('sys.stderr.flush()')
3096 ee('sys.stdout.attr = None')
3097 cb.append(">> OutputWrite")
3098 ee('assert sys.stdout.writable()==True')
3099 ee('assert sys.stdout.readable()==False')
3100 ee('assert sys.stderr.writable()==True')
3101 ee('assert sys.stderr.readable()==False')
3102 ee('assert sys.stdout.closed()==False')
3103 ee('assert sys.stderr.closed()==False')
3104 ee('assert sys.stdout.errors=="strict"')
3105 ee('assert sys.stderr.errors=="strict"')
3106 ee('assert sys.stdout.encoding==sys.stderr.encoding')
3107 ee('sys.stdout.write(None)')
3108 cb.append(">> OutputWriteLines")
3109 ee('sys.stdout.writelines(None)')
3110 ee('sys.stdout.writelines([1])')
3111 iter_test('sys.stdout.writelines(%s)')
3112 cb.append("> VimCommand")
3113 stringtochars_test('vim.command(%s)')
3114 ee('vim.command("", 2)')
3115 #! Not checked: vim->python exceptions translating: checked later
3116 cb.append("> VimToPython")
3117 #! Not checked: everything: needs errors in internal python functions
3118 cb.append("> VimEval")
3119 stringtochars_test('vim.eval(%s)')
3120 ee('vim.eval("", FailingTrue())')
3121 #! Not checked: everything: needs errors in internal python functions
3122 cb.append("> VimEvalPy")
3123 stringtochars_test('vim.bindeval(%s)')
3124 ee('vim.eval("", 2)')
3125 #! Not checked: vim->python exceptions translating: checked later
3126 cb.append("> VimStrwidth")
3127 stringtochars_test('vim.strwidth(%s)')
3128 cb.append("> VimForeachRTP")
3129 ee('vim.foreach_rtp(None)')
3130 ee('vim.foreach_rtp(NoArgsCall())')
3131 ee('vim.foreach_rtp(FailingCall())')
3132 ee('vim.foreach_rtp(int, 2)')
3133 cb.append('> import')
3134 old_rtp = vim.options['rtp']
3135 vim.options['rtp'] = os.getcwd().replace('\\', '\\\\').replace(',', '\\,')
3136 ee('import xxx_no_such_module_xxx')
3137 ee('import failing_import')
3138 ee('import failing')
3139 vim.options['rtp'] = old_rtp
3140 del old_rtp
3141 cb.append("> Options")
3142 cb.append(">> OptionsItem")
3143 ee('vim.options["abcQ"]')
3144 ee('vim.options[""]')
3145 stringtochars_test('vim.options[%s]')
3146 cb.append(">> OptionsContains")
3147 stringtochars_test('%s in vim.options')
3148 cb.append("> Dictionary")
3149 cb.append(">> DictionaryConstructor")
3150 ee('vim.Dictionary("abcI")')
3151 ##! Not checked: py_dict_alloc failure
3152 cb.append(">> DictionarySetattr")
3153 ee('del d.locked')
3154 ee('d.locked = FailingTrue()')
3155 ee('vim.vvars.locked = False')
3156 ee('d.scope = True')
3157 ee('d.xxx = True')
3158 cb.append(">> _DictionaryItem")
3159 ee('d.get("a", 2, 3)')
3160 stringtochars_test('d.get(%s)')
3161 ee('d.pop("a")')
3162 ee('dl.pop("a")')
3163 cb.append(">> DictionaryContains")
3164 ee('"" in d')
3165 ee('0 in d')
3166 cb.append(">> DictionaryIterNext")
3167 ee('for i in ned: ned["a"] = 1')
3168 del i
3169 cb.append(">> DictionaryAssItem")
3170 ee('dl["b"] = 1')
3171 stringtochars_test('d[%s] = 1')
3172 convertfrompyobject_test('d["a"] = %s')
3173 cb.append(">> DictionaryUpdate")
3174 cb.append(">>> kwargs")
3175 cb.append(">>> iter")
3176 ee('d.update(FailingMapping())')
3177 ee('d.update([FailingIterNext()])')
3178 ee('d.update([FailingIterNextN(1)])')
3179 iter_test('d.update(%s)')
3180 convertfrompyobject_test('d.update(%s)')
3181 stringtochars_test('d.update(((%s, 0),))')
3182 convertfrompyobject_test('d.update((("a", %s),))')
3183 cb.append(">> DictionaryPopItem")
3184 ee('d.popitem(1, 2)')
3185 cb.append(">> DictionaryHasKey")
3186 ee('d.has_key()')
3187 cb.append("> List")
3188 cb.append(">> ListConstructor")
3189 ee('vim.List(1, 2)')
3190 ee('vim.List(a=1)')
3191 iter_test('vim.List(%s)')
3192 convertfrompyobject_test('vim.List([%s])')
3193 cb.append(">> ListItem")
3194 ee('l[1000]')
3195 cb.append(">> ListAssItem")
3196 ee('ll[1] = 2')
3197 ee('l[1000] = 3')
3198 cb.append(">> ListAssSlice")
3199 ee('ll[1:100] = "abcJ"')
3200 iter_test('l[:] = %s')
3201 ee('nel[1:10:2] = "abcK"')
3202 cb.append(repr(tuple(nel)))
3203 ee('nel[1:10:2] = "a"')
3204 cb.append(repr(tuple(nel)))
3205 ee('nel[1:1:-1] = "a"')
3206 cb.append(repr(tuple(nel)))
3207 ee('nel[:] = FailingIterNextN(2)')
3208 cb.append(repr(tuple(nel)))
3209 convertfrompyobject_test('l[:] = [%s]')
3210 cb.append(">> ListConcatInPlace")
3211 iter_test('l.extend(%s)')
3212 convertfrompyobject_test('l.extend([%s])')
3213 cb.append(">> ListSetattr")
3214 ee('del l.locked')
3215 ee('l.locked = FailingTrue()')
3216 ee('l.xxx = True')
3217 cb.append("> Function")
3218 cb.append(">> FunctionConstructor")
3219 cb.append(">>> FunctionConstructor")
3220 ee('vim.Function("123")')
3221 ee('vim.Function("xxx_non_existent_function_xxx")')
3222 ee('vim.Function("xxx#non#existent#function#xxx")')
3223 ee('vim.Function("xxx_non_existent_function_xxx2", args=[])')
3224 ee('vim.Function("xxx_non_existent_function_xxx3", self={})')
3225 ee('vim.Function("xxx_non_existent_function_xxx4", args=[], self={})')
3226 cb.append(">>> FunctionNew")
3227 ee('vim.Function("tr", self="abcFuncSelf")')
3228 ee('vim.Function("tr", args=427423)')
3229 ee('vim.Function("tr", self="abcFuncSelf2", args="abcFuncArgs2")')
3230 ee('vim.Function(self="abcFuncSelf2", args="abcFuncArgs2")')
3231 ee('vim.Function("tr", "", self="abcFuncSelf2", args="abcFuncArgs2")')
3232 ee('vim.Function("tr", "")')
3233 cb.append(">> FunctionCall")
3234 convertfrompyobject_test('f(%s)')
3235 convertfrompymapping_test('fd(self=%s)')
3236 cb.append("> TabPage")
3237 cb.append(">> TabPageAttr")
3238 ee('vim.current.tabpage.xxx')
3239 cb.append("> TabList")
3240 cb.append(">> TabListItem")
3241 ee('vim.tabpages[1000]')
3242 cb.append("> Window")
3243 cb.append(">> WindowAttr")
3244 ee('vim.current.window.xxx')
3245 cb.append(">> WindowSetattr")
3246 ee('vim.current.window.buffer = 0')
3247 ee('vim.current.window.cursor = (100000000, 100000000)')
3248 ee('vim.current.window.cursor = True')
3249 number_test('vim.current.window.height = %s', unsigned=True)
3250 number_test('vim.current.window.width = %s', unsigned=True)
3251 ee('vim.current.window.xxxxxx = True')
3252 cb.append("> WinList")
3253 cb.append(">> WinListItem")
3254 ee('vim.windows[1000]')
3255 cb.append("> Buffer")
3256 cb.append(">> StringToLine (indirect)")
3257 ee('vim.current.buffer[0] = "\\na"')
3258 ee('vim.current.buffer[0] = b"\\na"')
3259 cb.append(">> SetBufferLine (indirect)")
3260 ee('vim.current.buffer[0] = True')
3261 cb.append(">> SetBufferLineList (indirect)")
3262 ee('vim.current.buffer[:] = True')
3263 ee('vim.current.buffer[:] = ["\\na", "bc"]')
3264 cb.append(">> InsertBufferLines (indirect)")
3265 ee('vim.current.buffer.append(None)')
3266 ee('vim.current.buffer.append(["\\na", "bc"])')
3267 ee('vim.current.buffer.append("\\nbc")')
3268 cb.append(">> RBItem")
3269 ee('vim.current.buffer[100000000]')
3270 cb.append(">> RBAsItem")
3271 ee('vim.current.buffer[100000000] = ""')
3272 cb.append(">> BufferAttr")
3273 ee('vim.current.buffer.xxx')
3274 cb.append(">> BufferSetattr")
3275 ee('vim.current.buffer.name = True')
3276 ee('vim.current.buffer.xxx = True')
3277 cb.append(">> BufferMark")
3278 ee('vim.current.buffer.mark(0)')
3279 ee('vim.current.buffer.mark("abcM")')
3280 ee('vim.current.buffer.mark("!")')
3281 cb.append(">> BufferRange")
3282 ee('vim.current.buffer.range(1, 2, 3)')
3283 cb.append("> BufMap")
3284 cb.append(">> BufMapItem")
3285 ee('vim.buffers[100000000]')
3286 number_test('vim.buffers[%s]', natural=True)
3287 cb.append("> Current")
3288 cb.append(">> CurrentGetattr")
3289 ee('vim.current.xxx')
3290 cb.append(">> CurrentSetattr")
3291 ee('vim.current.line = True')
3292 ee('vim.current.buffer = True')
3293 ee('vim.current.window = True')
3294 ee('vim.current.tabpage = True')
3295 ee('vim.current.xxx = True')
3296 del d
3297 del ned
3298 del dl
3299 del l
3300 del ll
3301 del nel
3302 del f
3303 del fd
3304 del fdel
3305 del subexpr_test
3306 del stringtochars_test
3307 del Mapping
3308 del convertfrompyobject_test
3309 del convertfrompymapping_test
3310 del iter_test
3311 del number_test
3312 del FailingTrue
3313 del FailingIter
3314 del FailingIterNext
3315 del FailingIterNextN
3316 del FailingMapping
3317 del FailingMappingKey
3318 del FailingList
3319 del NoArgsCall
3320 del FailingCall
3321 del FailingNumber
3322 EOF
3323 delfunction F
3324
3325 let expected =<< trim END
3326 > Output
3327 >> OutputSetattr
3328 del sys.stdout.softspace:(<class 'AttributeError'>, AttributeError('cannot delete OutputObject attributes',))
3329 >>> Testing NumberToLong using sys.stdout.softspace = %s
3330 sys.stdout.softspace = []:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got list',))
3331 sys.stdout.softspace = None:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got NoneType',))
3332 sys.stdout.softspace = -1:(<class 'ValueError'>, ValueError('number must be greater or equal to zero',))
3333 <<< Finished
3334 >>> Testing NumberToLong using sys.stderr.softspace = %s
3335 sys.stderr.softspace = []:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got list',))
3336 sys.stderr.softspace = None:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got NoneType',))
3337 sys.stderr.softspace = -1:(<class 'ValueError'>, ValueError('number must be greater or equal to zero',))
3338 <<< Finished
3339 assert sys.stdout.isatty()==False:NOT FAILED
3340 assert sys.stdout.seekable()==False:NOT FAILED
3341 sys.stdout.close():NOT FAILED
3342 sys.stdout.flush():NOT FAILED
3343 assert sys.stderr.isatty()==False:NOT FAILED
3344 assert sys.stderr.seekable()==False:NOT FAILED
3345 sys.stderr.close():NOT FAILED
3346 sys.stderr.flush():NOT FAILED
3347 sys.stdout.attr = None:(<class 'AttributeError'>, AttributeError('invalid attribute: attr',))
3348 >> OutputWrite
3349 assert sys.stdout.writable()==True:NOT FAILED
3350 assert sys.stdout.readable()==False:NOT FAILED
3351 assert sys.stderr.writable()==True:NOT FAILED
3352 assert sys.stderr.readable()==False:NOT FAILED
3353 assert sys.stdout.closed()==False:NOT FAILED
3354 assert sys.stderr.closed()==False:NOT FAILED
3355 assert sys.stdout.errors=="strict":NOT FAILED
3356 assert sys.stderr.errors=="strict":NOT FAILED
3357 assert sys.stdout.encoding==sys.stderr.encoding:NOT FAILED
3358 sys.stdout.write(None):(<class 'TypeError'>, TypeError("Can't convert 'NoneType' object to str implicitly",))
3359 >> OutputWriteLines
3360 sys.stdout.writelines(None):(<class 'TypeError'>, TypeError("'NoneType' object is not iterable",))
3361 sys.stdout.writelines([1]):(<class 'TypeError'>, TypeError("Can't convert 'int' object to str implicitly",))
3362 >>> Testing *Iter* using sys.stdout.writelines(%s)
3363 sys.stdout.writelines(FailingIter()):(<class 'NotImplementedError'>, NotImplementedError('iter',))
3364 sys.stdout.writelines(FailingIterNext()):(<class 'NotImplementedError'>, NotImplementedError('next',))
3365 <<< Finished
3366 > VimCommand
3367 >>> Testing StringToChars using vim.command(%s)
3368 vim.command(1):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3369 vim.command(b"\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3370 vim.command("\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3371 <<< Finished
3372 vim.command("", 2):(<class 'TypeError'>, TypeError('command() takes exactly one argument (2 given)',))
3373 > VimToPython
3374 > VimEval
3375 >>> Testing StringToChars using vim.eval(%s)
3376 vim.eval(1):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3377 vim.eval(b"\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3378 vim.eval("\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3379 <<< Finished
3380 vim.eval("", FailingTrue()):(<class 'TypeError'>, TypeError('function takes exactly 1 argument (2 given)',))
3381 > VimEvalPy
3382 >>> Testing StringToChars using vim.bindeval(%s)
3383 vim.bindeval(1):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3384 vim.bindeval(b"\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3385 vim.bindeval("\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3386 <<< Finished
3387 vim.eval("", 2):(<class 'TypeError'>, TypeError('function takes exactly 1 argument (2 given)',))
3388 > VimStrwidth
3389 >>> Testing StringToChars using vim.strwidth(%s)
3390 vim.strwidth(1):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3391 vim.strwidth(b"\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3392 vim.strwidth("\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3393 <<< Finished
3394 > VimForeachRTP
3395 vim.foreach_rtp(None):(<class 'TypeError'>, TypeError("'NoneType' object is not callable",))
3396 vim.foreach_rtp(NoArgsCall()):(<class 'TypeError'>, TypeError('__call__() takes exactly 1 positional argument (2 given)',))
3397 vim.foreach_rtp(FailingCall()):(<class 'NotImplementedError'>, NotImplementedError('call',))
3398 vim.foreach_rtp(int, 2):(<class 'TypeError'>, TypeError('foreach_rtp() takes exactly one argument (2 given)',))
3399 > import
3400 import xxx_no_such_module_xxx:(<class 'ImportError'>, ImportError('No module named xxx_no_such_module_xxx',))
3401 import failing_import:(<class 'ImportError'>, ImportError())
3402 import failing:(<class 'NotImplementedError'>, NotImplementedError())
3403 > Options
3404 >> OptionsItem
3405 vim.options["abcQ"]:(<class 'KeyError'>, KeyError('abcQ',))
3406 vim.options[""]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3407 >>> Testing StringToChars using vim.options[%s]
3408 vim.options[1]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3409 vim.options[b"\0"]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3410 vim.options["\0"]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3411 <<< Finished
3412 >> OptionsContains
3413 >>> Testing StringToChars using %s in vim.options
3414 1 in vim.options:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3415 b"\0" in vim.options:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3416 "\0" in vim.options:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3417 <<< Finished
3418 > Dictionary
3419 >> DictionaryConstructor
3420 vim.Dictionary("abcI"):(<class 'ValueError'>, ValueError('expected sequence element of size 2, but got sequence of size 1',))
3421 >> DictionarySetattr
3422 del d.locked:(<class 'AttributeError'>, AttributeError('cannot delete vim.Dictionary attributes',))
3423 d.locked = FailingTrue():(<class 'NotImplementedError'>, NotImplementedError('bool',))
3424 vim.vvars.locked = False:(<class 'TypeError'>, TypeError('cannot modify fixed dictionary',))
3425 d.scope = True:(<class 'AttributeError'>, AttributeError('cannot set attribute scope',))
3426 d.xxx = True:(<class 'AttributeError'>, AttributeError('cannot set attribute xxx',))
3427 >> _DictionaryItem
3428 d.get("a", 2, 3):(<class 'TypeError'>, TypeError('function takes at most 2 arguments (3 given)',))
3429 >>> Testing StringToChars using d.get(%s)
3430 d.get(1):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3431 d.get(b"\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3432 d.get("\0"):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3433 <<< Finished
3434 d.pop("a"):(<class 'KeyError'>, KeyError('a',))
3435 dl.pop("a"):(<class 'vim.error'>, error('dictionary is locked',))
3436 >> DictionaryContains
3437 "" in d:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3438 0 in d:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3439 >> DictionaryIterNext
3440 for i in ned: ned["a"] = 1:(<class 'RuntimeError'>, RuntimeError('hashtab changed during iteration',))
3441 >> DictionaryAssItem
3442 dl["b"] = 1:(<class 'vim.error'>, error('dictionary is locked',))
3443 >>> Testing StringToChars using d[%s] = 1
3444 d[1] = 1:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3445 d[b"\0"] = 1:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3446 d["\0"] = 1:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3447 <<< Finished
3448 >>> Testing StringToChars using d["a"] = {%s : 1}
3449 d["a"] = {1 : 1}:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3450 d["a"] = {b"\0" : 1}:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3451 d["a"] = {"\0" : 1}:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3452 <<< Finished
3453 >>> Testing StringToChars using d["a"] = {"abcF" : {%s : 1}}
3454 d["a"] = {"abcF" : {1 : 1}}:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3455 d["a"] = {"abcF" : {b"\0" : 1}}:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3456 d["a"] = {"abcF" : {"\0" : 1}}:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3457 <<< Finished
3458 >>> Testing StringToChars using d["a"] = {"abcF" : Mapping({%s : 1})}
3459 d["a"] = {"abcF" : Mapping({1 : 1})}:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3460 d["a"] = {"abcF" : Mapping({b"\0" : 1})}:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3461 d["a"] = {"abcF" : Mapping({"\0" : 1})}:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3462 <<< Finished
3463 >>> Testing *Iter* using d["a"] = {"abcF" : %s}
3464 d["a"] = {"abcF" : FailingIter()}:(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3465 d["a"] = {"abcF" : FailingIterNext()}:(<class 'NotImplementedError'>, NotImplementedError('next',))
3466 <<< Finished
3467 >>> Testing ConvertFromPyObject using d["a"] = {"abcF" : %s}
3468 d["a"] = {"abcF" : None}:NOT FAILED
3469 d["a"] = {"abcF" : {b"": 1}}:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3470 d["a"] = {"abcF" : {"": 1}}:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3471 d["a"] = {"abcF" : FailingMapping()}:(<class 'NotImplementedError'>, NotImplementedError('keys',))
3472 d["a"] = {"abcF" : FailingMappingKey()}:(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3473 d["a"] = {"abcF" : FailingNumber()}:(<class 'NotImplementedError'>, NotImplementedError('int',))
3474 <<< Finished
3475 >>> Testing StringToChars using d["a"] = Mapping({%s : 1})
3476 d["a"] = Mapping({1 : 1}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3477 d["a"] = Mapping({b"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3478 d["a"] = Mapping({"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3479 <<< Finished
3480 >>> Testing StringToChars using d["a"] = Mapping({"abcG" : {%s : 1}})
3481 d["a"] = Mapping({"abcG" : {1 : 1}}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3482 d["a"] = Mapping({"abcG" : {b"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3483 d["a"] = Mapping({"abcG" : {"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3484 <<< Finished
3485 >>> Testing StringToChars using d["a"] = Mapping({"abcG" : Mapping({%s : 1})})
3486 d["a"] = Mapping({"abcG" : Mapping({1 : 1})}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3487 d["a"] = Mapping({"abcG" : Mapping({b"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3488 d["a"] = Mapping({"abcG" : Mapping({"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3489 <<< Finished
3490 >>> Testing *Iter* using d["a"] = Mapping({"abcG" : %s})
3491 d["a"] = Mapping({"abcG" : FailingIter()}):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3492 d["a"] = Mapping({"abcG" : FailingIterNext()}):(<class 'NotImplementedError'>, NotImplementedError('next',))
3493 <<< Finished
3494 >>> Testing ConvertFromPyObject using d["a"] = Mapping({"abcG" : %s})
3495 d["a"] = Mapping({"abcG" : None}):NOT FAILED
3496 d["a"] = Mapping({"abcG" : {b"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3497 d["a"] = Mapping({"abcG" : {"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3498 d["a"] = Mapping({"abcG" : FailingMapping()}):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3499 d["a"] = Mapping({"abcG" : FailingMappingKey()}):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3500 d["a"] = Mapping({"abcG" : FailingNumber()}):(<class 'NotImplementedError'>, NotImplementedError('int',))
3501 <<< Finished
3502 >>> Testing *Iter* using d["a"] = %s
3503 d["a"] = FailingIter():(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3504 d["a"] = FailingIterNext():(<class 'NotImplementedError'>, NotImplementedError('next',))
3505 <<< Finished
3506 >>> Testing ConvertFromPyObject using d["a"] = %s
3507 d["a"] = None:NOT FAILED
3508 d["a"] = {b"": 1}:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3509 d["a"] = {"": 1}:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3510 d["a"] = FailingMapping():(<class 'NotImplementedError'>, NotImplementedError('keys',))
3511 d["a"] = FailingMappingKey():(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3512 d["a"] = FailingNumber():(<class 'NotImplementedError'>, NotImplementedError('int',))
3513 <<< Finished
3514 >> DictionaryUpdate
3515 >>> kwargs
3516 >>> iter
3517 d.update(FailingMapping()):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3518 d.update([FailingIterNext()]):(<class 'NotImplementedError'>, NotImplementedError('next',))
3519 d.update([FailingIterNextN(1)]):(<class 'NotImplementedError'>, NotImplementedError('next N',))
3520 >>> Testing *Iter* using d.update(%s)
3521 d.update(FailingIter()):(<class 'NotImplementedError'>, NotImplementedError('iter',))
3522 d.update(FailingIterNext()):(<class 'NotImplementedError'>, NotImplementedError('next',))
3523 <<< Finished
3524 >>> Testing StringToChars using d.update({%s : 1})
3525 d.update({1 : 1}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3526 d.update({b"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3527 d.update({"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3528 <<< Finished
3529 >>> Testing StringToChars using d.update({"abcF" : {%s : 1}})
3530 d.update({"abcF" : {1 : 1}}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3531 d.update({"abcF" : {b"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3532 d.update({"abcF" : {"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3533 <<< Finished
3534 >>> Testing StringToChars using d.update({"abcF" : Mapping({%s : 1})})
3535 d.update({"abcF" : Mapping({1 : 1})}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3536 d.update({"abcF" : Mapping({b"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3537 d.update({"abcF" : Mapping({"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3538 <<< Finished
3539 >>> Testing *Iter* using d.update({"abcF" : %s})
3540 d.update({"abcF" : FailingIter()}):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3541 d.update({"abcF" : FailingIterNext()}):(<class 'NotImplementedError'>, NotImplementedError('next',))
3542 <<< Finished
3543 >>> Testing ConvertFromPyObject using d.update({"abcF" : %s})
3544 d.update({"abcF" : None}):NOT FAILED
3545 d.update({"abcF" : {b"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3546 d.update({"abcF" : {"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3547 d.update({"abcF" : FailingMapping()}):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3548 d.update({"abcF" : FailingMappingKey()}):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3549 d.update({"abcF" : FailingNumber()}):(<class 'NotImplementedError'>, NotImplementedError('int',))
3550 <<< Finished
3551 >>> Testing StringToChars using d.update(Mapping({%s : 1}))
3552 d.update(Mapping({1 : 1})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3553 d.update(Mapping({b"\0" : 1})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3554 d.update(Mapping({"\0" : 1})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3555 <<< Finished
3556 >>> Testing StringToChars using d.update(Mapping({"abcG" : {%s : 1}}))
3557 d.update(Mapping({"abcG" : {1 : 1}})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3558 d.update(Mapping({"abcG" : {b"\0" : 1}})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3559 d.update(Mapping({"abcG" : {"\0" : 1}})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3560 <<< Finished
3561 >>> Testing StringToChars using d.update(Mapping({"abcG" : Mapping({%s : 1})}))
3562 d.update(Mapping({"abcG" : Mapping({1 : 1})})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3563 d.update(Mapping({"abcG" : Mapping({b"\0" : 1})})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3564 d.update(Mapping({"abcG" : Mapping({"\0" : 1})})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3565 <<< Finished
3566 >>> Testing *Iter* using d.update(Mapping({"abcG" : %s}))
3567 d.update(Mapping({"abcG" : FailingIter()})):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3568 d.update(Mapping({"abcG" : FailingIterNext()})):(<class 'NotImplementedError'>, NotImplementedError('next',))
3569 <<< Finished
3570 >>> Testing ConvertFromPyObject using d.update(Mapping({"abcG" : %s}))
3571 d.update(Mapping({"abcG" : None})):NOT FAILED
3572 d.update(Mapping({"abcG" : {b"": 1}})):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3573 d.update(Mapping({"abcG" : {"": 1}})):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3574 d.update(Mapping({"abcG" : FailingMapping()})):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3575 d.update(Mapping({"abcG" : FailingMappingKey()})):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3576 d.update(Mapping({"abcG" : FailingNumber()})):(<class 'NotImplementedError'>, NotImplementedError('int',))
3577 <<< Finished
3578 >>> Testing *Iter* using d.update(%s)
3579 d.update(FailingIter()):(<class 'NotImplementedError'>, NotImplementedError('iter',))
3580 d.update(FailingIterNext()):(<class 'NotImplementedError'>, NotImplementedError('next',))
3581 <<< Finished
3582 >>> Testing ConvertFromPyObject using d.update(%s)
3583 d.update(None):(<class 'TypeError'>, TypeError("'NoneType' object is not iterable",))
3584 d.update({b"": 1}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3585 d.update({"": 1}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3586 d.update(FailingMapping()):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3587 d.update(FailingMappingKey()):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3588 d.update(FailingNumber()):(<class 'TypeError'>, TypeError("'FailingNumber' object is not iterable",))
3589 <<< Finished
3590 >>> Testing StringToChars using d.update(((%s, 0),))
3591 d.update(((1, 0),)):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3592 d.update(((b"\0", 0),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3593 d.update((("\0", 0),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3594 <<< Finished
3595 >>> Testing StringToChars using d.update((("a", {%s : 1}),))
3596 d.update((("a", {1 : 1}),)):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3597 d.update((("a", {b"\0" : 1}),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3598 d.update((("a", {"\0" : 1}),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3599 <<< Finished
3600 >>> Testing StringToChars using d.update((("a", {"abcF" : {%s : 1}}),))
3601 d.update((("a", {"abcF" : {1 : 1}}),)):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3602 d.update((("a", {"abcF" : {b"\0" : 1}}),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3603 d.update((("a", {"abcF" : {"\0" : 1}}),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3604 <<< Finished
3605 >>> Testing StringToChars using d.update((("a", {"abcF" : Mapping({%s : 1})}),))
3606 d.update((("a", {"abcF" : Mapping({1 : 1})}),)):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3607 d.update((("a", {"abcF" : Mapping({b"\0" : 1})}),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3608 d.update((("a", {"abcF" : Mapping({"\0" : 1})}),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3609 <<< Finished
3610 >>> Testing *Iter* using d.update((("a", {"abcF" : %s}),))
3611 d.update((("a", {"abcF" : FailingIter()}),)):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3612 d.update((("a", {"abcF" : FailingIterNext()}),)):(<class 'NotImplementedError'>, NotImplementedError('next',))
3613 <<< Finished
3614 >>> Testing ConvertFromPyObject using d.update((("a", {"abcF" : %s}),))
3615 d.update((("a", {"abcF" : None}),)):(<class 'vim.error'>, error("failed to add key 'a' to dictionary",))
3616 d.update((("a", {"abcF" : {b"": 1}}),)):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3617 d.update((("a", {"abcF" : {"": 1}}),)):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3618 d.update((("a", {"abcF" : FailingMapping()}),)):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3619 d.update((("a", {"abcF" : FailingMappingKey()}),)):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3620 d.update((("a", {"abcF" : FailingNumber()}),)):(<class 'NotImplementedError'>, NotImplementedError('int',))
3621 <<< Finished
3622 >>> Testing StringToChars using d.update((("a", Mapping({%s : 1})),))
3623 d.update((("a", Mapping({1 : 1})),)):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3624 d.update((("a", Mapping({b"\0" : 1})),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3625 d.update((("a", Mapping({"\0" : 1})),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3626 <<< Finished
3627 >>> Testing StringToChars using d.update((("a", Mapping({"abcG" : {%s : 1}})),))
3628 d.update((("a", Mapping({"abcG" : {1 : 1}})),)):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3629 d.update((("a", Mapping({"abcG" : {b"\0" : 1}})),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3630 d.update((("a", Mapping({"abcG" : {"\0" : 1}})),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3631 <<< Finished
3632 >>> Testing StringToChars using d.update((("a", Mapping({"abcG" : Mapping({%s : 1})})),))
3633 d.update((("a", Mapping({"abcG" : Mapping({1 : 1})})),)):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3634 d.update((("a", Mapping({"abcG" : Mapping({b"\0" : 1})})),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3635 d.update((("a", Mapping({"abcG" : Mapping({"\0" : 1})})),)):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3636 <<< Finished
3637 >>> Testing *Iter* using d.update((("a", Mapping({"abcG" : %s})),))
3638 d.update((("a", Mapping({"abcG" : FailingIter()})),)):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3639 d.update((("a", Mapping({"abcG" : FailingIterNext()})),)):(<class 'NotImplementedError'>, NotImplementedError('next',))
3640 <<< Finished
3641 >>> Testing ConvertFromPyObject using d.update((("a", Mapping({"abcG" : %s})),))
3642 d.update((("a", Mapping({"abcG" : None})),)):(<class 'vim.error'>, error("failed to add key 'a' to dictionary",))
3643 d.update((("a", Mapping({"abcG" : {b"": 1}})),)):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3644 d.update((("a", Mapping({"abcG" : {"": 1}})),)):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3645 d.update((("a", Mapping({"abcG" : FailingMapping()})),)):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3646 d.update((("a", Mapping({"abcG" : FailingMappingKey()})),)):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3647 d.update((("a", Mapping({"abcG" : FailingNumber()})),)):(<class 'NotImplementedError'>, NotImplementedError('int',))
3648 <<< Finished
3649 >>> Testing *Iter* using d.update((("a", %s),))
3650 d.update((("a", FailingIter()),)):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3651 d.update((("a", FailingIterNext()),)):(<class 'NotImplementedError'>, NotImplementedError('next',))
3652 <<< Finished
3653 >>> Testing ConvertFromPyObject using d.update((("a", %s),))
3654 d.update((("a", None),)):(<class 'vim.error'>, error("failed to add key 'a' to dictionary",))
3655 d.update((("a", {b"": 1}),)):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3656 d.update((("a", {"": 1}),)):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3657 d.update((("a", FailingMapping()),)):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3658 d.update((("a", FailingMappingKey()),)):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3659 d.update((("a", FailingNumber()),)):(<class 'NotImplementedError'>, NotImplementedError('int',))
3660 <<< Finished
3661 >> DictionaryPopItem
3662 d.popitem(1, 2):(<class 'TypeError'>, TypeError('popitem() takes no arguments (2 given)',))
3663 >> DictionaryHasKey
3664 d.has_key():(<class 'TypeError'>, TypeError('has_key() takes exactly one argument (0 given)',))
3665 > List
3666 >> ListConstructor
3667 vim.List(1, 2):(<class 'TypeError'>, TypeError('function takes at most 1 argument (2 given)',))
3668 vim.List(a=1):(<class 'TypeError'>, TypeError('list constructor does not accept keyword arguments',))
3669 >>> Testing *Iter* using vim.List(%s)
3670 vim.List(FailingIter()):(<class 'NotImplementedError'>, NotImplementedError('iter',))
3671 vim.List(FailingIterNext()):(<class 'NotImplementedError'>, NotImplementedError('next',))
3672 <<< Finished
3673 >>> Testing StringToChars using vim.List([{%s : 1}])
3674 vim.List([{1 : 1}]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3675 vim.List([{b"\0" : 1}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3676 vim.List([{"\0" : 1}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3677 <<< Finished
3678 >>> Testing StringToChars using vim.List([{"abcF" : {%s : 1}}])
3679 vim.List([{"abcF" : {1 : 1}}]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3680 vim.List([{"abcF" : {b"\0" : 1}}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3681 vim.List([{"abcF" : {"\0" : 1}}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3682 <<< Finished
3683 >>> Testing StringToChars using vim.List([{"abcF" : Mapping({%s : 1})}])
3684 vim.List([{"abcF" : Mapping({1 : 1})}]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3685 vim.List([{"abcF" : Mapping({b"\0" : 1})}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3686 vim.List([{"abcF" : Mapping({"\0" : 1})}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3687 <<< Finished
3688 >>> Testing *Iter* using vim.List([{"abcF" : %s}])
3689 vim.List([{"abcF" : FailingIter()}]):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3690 vim.List([{"abcF" : FailingIterNext()}]):(<class 'NotImplementedError'>, NotImplementedError('next',))
3691 <<< Finished
3692 >>> Testing ConvertFromPyObject using vim.List([{"abcF" : %s}])
3693 vim.List([{"abcF" : None}]):NOT FAILED
3694 vim.List([{"abcF" : {b"": 1}}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3695 vim.List([{"abcF" : {"": 1}}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3696 vim.List([{"abcF" : FailingMapping()}]):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3697 vim.List([{"abcF" : FailingMappingKey()}]):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3698 vim.List([{"abcF" : FailingNumber()}]):(<class 'NotImplementedError'>, NotImplementedError('int',))
3699 <<< Finished
3700 >>> Testing StringToChars using vim.List([Mapping({%s : 1})])
3701 vim.List([Mapping({1 : 1})]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3702 vim.List([Mapping({b"\0" : 1})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3703 vim.List([Mapping({"\0" : 1})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3704 <<< Finished
3705 >>> Testing StringToChars using vim.List([Mapping({"abcG" : {%s : 1}})])
3706 vim.List([Mapping({"abcG" : {1 : 1}})]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3707 vim.List([Mapping({"abcG" : {b"\0" : 1}})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3708 vim.List([Mapping({"abcG" : {"\0" : 1}})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3709 <<< Finished
3710 >>> Testing StringToChars using vim.List([Mapping({"abcG" : Mapping({%s : 1})})])
3711 vim.List([Mapping({"abcG" : Mapping({1 : 1})})]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3712 vim.List([Mapping({"abcG" : Mapping({b"\0" : 1})})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3713 vim.List([Mapping({"abcG" : Mapping({"\0" : 1})})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3714 <<< Finished
3715 >>> Testing *Iter* using vim.List([Mapping({"abcG" : %s})])
3716 vim.List([Mapping({"abcG" : FailingIter()})]):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3717 vim.List([Mapping({"abcG" : FailingIterNext()})]):(<class 'NotImplementedError'>, NotImplementedError('next',))
3718 <<< Finished
3719 >>> Testing ConvertFromPyObject using vim.List([Mapping({"abcG" : %s})])
3720 vim.List([Mapping({"abcG" : None})]):NOT FAILED
3721 vim.List([Mapping({"abcG" : {b"": 1}})]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3722 vim.List([Mapping({"abcG" : {"": 1}})]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3723 vim.List([Mapping({"abcG" : FailingMapping()})]):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3724 vim.List([Mapping({"abcG" : FailingMappingKey()})]):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3725 vim.List([Mapping({"abcG" : FailingNumber()})]):(<class 'NotImplementedError'>, NotImplementedError('int',))
3726 <<< Finished
3727 >>> Testing *Iter* using vim.List([%s])
3728 vim.List([FailingIter()]):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3729 vim.List([FailingIterNext()]):(<class 'NotImplementedError'>, NotImplementedError('next',))
3730 <<< Finished
3731 >>> Testing ConvertFromPyObject using vim.List([%s])
3732 vim.List([None]):NOT FAILED
3733 vim.List([{b"": 1}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3734 vim.List([{"": 1}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3735 vim.List([FailingMapping()]):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3736 vim.List([FailingMappingKey()]):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3737 vim.List([FailingNumber()]):(<class 'NotImplementedError'>, NotImplementedError('int',))
3738 <<< Finished
3739 >> ListItem
3740 l[1000]:(<class 'IndexError'>, IndexError('list index out of range',))
3741 >> ListAssItem
3742 ll[1] = 2:(<class 'vim.error'>, error('list is locked',))
3743 l[1000] = 3:(<class 'IndexError'>, IndexError('list index out of range',))
3744 >> ListAssSlice
3745 ll[1:100] = "abcJ":(<class 'vim.error'>, error('list is locked',))
3746 >>> Testing *Iter* using l[:] = %s
3747 l[:] = FailingIter():(<class 'NotImplementedError'>, NotImplementedError('iter',))
3748 l[:] = FailingIterNext():(<class 'NotImplementedError'>, NotImplementedError('next',))
3749 <<< Finished
3750 nel[1:10:2] = "abcK":(<class 'ValueError'>, ValueError('attempt to assign sequence of size greater than 2 to extended slice',))
3751 (b'a', b'b', b'c', b'O')
3752 nel[1:10:2] = "a":(<class 'ValueError'>, ValueError('attempt to assign sequence of size 1 to extended slice of size 2',))
3753 (b'a', b'b', b'c', b'O')
3754 nel[1:1:-1] = "a":(<class 'ValueError'>, ValueError('attempt to assign sequence of size greater than 0 to extended slice',))
3755 (b'a', b'b', b'c', b'O')
3756 nel[:] = FailingIterNextN(2):(<class 'NotImplementedError'>, NotImplementedError('next N',))
3757 (b'a', b'b', b'c', b'O')
3758 >>> Testing StringToChars using l[:] = [{%s : 1}]
3759 l[:] = [{1 : 1}]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3760 l[:] = [{b"\0" : 1}]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3761 l[:] = [{"\0" : 1}]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3762 <<< Finished
3763 >>> Testing StringToChars using l[:] = [{"abcF" : {%s : 1}}]
3764 l[:] = [{"abcF" : {1 : 1}}]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3765 l[:] = [{"abcF" : {b"\0" : 1}}]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3766 l[:] = [{"abcF" : {"\0" : 1}}]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3767 <<< Finished
3768 >>> Testing StringToChars using l[:] = [{"abcF" : Mapping({%s : 1})}]
3769 l[:] = [{"abcF" : Mapping({1 : 1})}]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3770 l[:] = [{"abcF" : Mapping({b"\0" : 1})}]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3771 l[:] = [{"abcF" : Mapping({"\0" : 1})}]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3772 <<< Finished
3773 >>> Testing *Iter* using l[:] = [{"abcF" : %s}]
3774 l[:] = [{"abcF" : FailingIter()}]:(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3775 l[:] = [{"abcF" : FailingIterNext()}]:(<class 'NotImplementedError'>, NotImplementedError('next',))
3776 <<< Finished
3777 >>> Testing ConvertFromPyObject using l[:] = [{"abcF" : %s}]
3778 l[:] = [{"abcF" : None}]:NOT FAILED
3779 l[:] = [{"abcF" : {b"": 1}}]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3780 l[:] = [{"abcF" : {"": 1}}]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3781 l[:] = [{"abcF" : FailingMapping()}]:(<class 'NotImplementedError'>, NotImplementedError('keys',))
3782 l[:] = [{"abcF" : FailingMappingKey()}]:(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3783 l[:] = [{"abcF" : FailingNumber()}]:(<class 'NotImplementedError'>, NotImplementedError('int',))
3784 <<< Finished
3785 >>> Testing StringToChars using l[:] = [Mapping({%s : 1})]
3786 l[:] = [Mapping({1 : 1})]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3787 l[:] = [Mapping({b"\0" : 1})]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3788 l[:] = [Mapping({"\0" : 1})]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3789 <<< Finished
3790 >>> Testing StringToChars using l[:] = [Mapping({"abcG" : {%s : 1}})]
3791 l[:] = [Mapping({"abcG" : {1 : 1}})]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3792 l[:] = [Mapping({"abcG" : {b"\0" : 1}})]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3793 l[:] = [Mapping({"abcG" : {"\0" : 1}})]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3794 <<< Finished
3795 >>> Testing StringToChars using l[:] = [Mapping({"abcG" : Mapping({%s : 1})})]
3796 l[:] = [Mapping({"abcG" : Mapping({1 : 1})})]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3797 l[:] = [Mapping({"abcG" : Mapping({b"\0" : 1})})]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3798 l[:] = [Mapping({"abcG" : Mapping({"\0" : 1})})]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
3799 <<< Finished
3800 >>> Testing *Iter* using l[:] = [Mapping({"abcG" : %s})]
3801 l[:] = [Mapping({"abcG" : FailingIter()})]:(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3802 l[:] = [Mapping({"abcG" : FailingIterNext()})]:(<class 'NotImplementedError'>, NotImplementedError('next',))
3803 <<< Finished
3804 >>> Testing ConvertFromPyObject using l[:] = [Mapping({"abcG" : %s})]
3805 l[:] = [Mapping({"abcG" : None})]:NOT FAILED
3806 l[:] = [Mapping({"abcG" : {b"": 1}})]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3807 l[:] = [Mapping({"abcG" : {"": 1}})]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3808 l[:] = [Mapping({"abcG" : FailingMapping()})]:(<class 'NotImplementedError'>, NotImplementedError('keys',))
3809 l[:] = [Mapping({"abcG" : FailingMappingKey()})]:(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3810 l[:] = [Mapping({"abcG" : FailingNumber()})]:(<class 'NotImplementedError'>, NotImplementedError('int',))
3811 <<< Finished
3812 >>> Testing *Iter* using l[:] = [%s]
3813 l[:] = [FailingIter()]:(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3814 l[:] = [FailingIterNext()]:(<class 'NotImplementedError'>, NotImplementedError('next',))
3815 <<< Finished
3816 >>> Testing ConvertFromPyObject using l[:] = [%s]
3817 l[:] = [None]:NOT FAILED
3818 l[:] = [{b"": 1}]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3819 l[:] = [{"": 1}]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3820 l[:] = [FailingMapping()]:(<class 'NotImplementedError'>, NotImplementedError('keys',))
3821 l[:] = [FailingMappingKey()]:(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3822 l[:] = [FailingNumber()]:(<class 'NotImplementedError'>, NotImplementedError('int',))
3823 <<< Finished
3824 >> ListConcatInPlace
3825 >>> Testing *Iter* using l.extend(%s)
3826 l.extend(FailingIter()):(<class 'NotImplementedError'>, NotImplementedError('iter',))
3827 l.extend(FailingIterNext()):(<class 'NotImplementedError'>, NotImplementedError('next',))
3828 <<< Finished
3829 >>> Testing StringToChars using l.extend([{%s : 1}])
3830 l.extend([{1 : 1}]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3831 l.extend([{b"\0" : 1}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3832 l.extend([{"\0" : 1}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3833 <<< Finished
3834 >>> Testing StringToChars using l.extend([{"abcF" : {%s : 1}}])
3835 l.extend([{"abcF" : {1 : 1}}]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3836 l.extend([{"abcF" : {b"\0" : 1}}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3837 l.extend([{"abcF" : {"\0" : 1}}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3838 <<< Finished
3839 >>> Testing StringToChars using l.extend([{"abcF" : Mapping({%s : 1})}])
3840 l.extend([{"abcF" : Mapping({1 : 1})}]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3841 l.extend([{"abcF" : Mapping({b"\0" : 1})}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3842 l.extend([{"abcF" : Mapping({"\0" : 1})}]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3843 <<< Finished
3844 >>> Testing *Iter* using l.extend([{"abcF" : %s}])
3845 l.extend([{"abcF" : FailingIter()}]):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3846 l.extend([{"abcF" : FailingIterNext()}]):(<class 'NotImplementedError'>, NotImplementedError('next',))
3847 <<< Finished
3848 >>> Testing ConvertFromPyObject using l.extend([{"abcF" : %s}])
3849 l.extend([{"abcF" : None}]):NOT FAILED
3850 l.extend([{"abcF" : {b"": 1}}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3851 l.extend([{"abcF" : {"": 1}}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3852 l.extend([{"abcF" : FailingMapping()}]):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3853 l.extend([{"abcF" : FailingMappingKey()}]):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3854 l.extend([{"abcF" : FailingNumber()}]):(<class 'NotImplementedError'>, NotImplementedError('int',))
3855 <<< Finished
3856 >>> Testing StringToChars using l.extend([Mapping({%s : 1})])
3857 l.extend([Mapping({1 : 1})]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3858 l.extend([Mapping({b"\0" : 1})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3859 l.extend([Mapping({"\0" : 1})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3860 <<< Finished
3861 >>> Testing StringToChars using l.extend([Mapping({"abcG" : {%s : 1}})])
3862 l.extend([Mapping({"abcG" : {1 : 1}})]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3863 l.extend([Mapping({"abcG" : {b"\0" : 1}})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3864 l.extend([Mapping({"abcG" : {"\0" : 1}})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3865 <<< Finished
3866 >>> Testing StringToChars using l.extend([Mapping({"abcG" : Mapping({%s : 1})})])
3867 l.extend([Mapping({"abcG" : Mapping({1 : 1})})]):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3868 l.extend([Mapping({"abcG" : Mapping({b"\0" : 1})})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3869 l.extend([Mapping({"abcG" : Mapping({"\0" : 1})})]):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3870 <<< Finished
3871 >>> Testing *Iter* using l.extend([Mapping({"abcG" : %s})])
3872 l.extend([Mapping({"abcG" : FailingIter()})]):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3873 l.extend([Mapping({"abcG" : FailingIterNext()})]):(<class 'NotImplementedError'>, NotImplementedError('next',))
3874 <<< Finished
3875 >>> Testing ConvertFromPyObject using l.extend([Mapping({"abcG" : %s})])
3876 l.extend([Mapping({"abcG" : None})]):NOT FAILED
3877 l.extend([Mapping({"abcG" : {b"": 1}})]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3878 l.extend([Mapping({"abcG" : {"": 1}})]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3879 l.extend([Mapping({"abcG" : FailingMapping()})]):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3880 l.extend([Mapping({"abcG" : FailingMappingKey()})]):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3881 l.extend([Mapping({"abcG" : FailingNumber()})]):(<class 'NotImplementedError'>, NotImplementedError('int',))
3882 <<< Finished
3883 >>> Testing *Iter* using l.extend([%s])
3884 l.extend([FailingIter()]):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3885 l.extend([FailingIterNext()]):(<class 'NotImplementedError'>, NotImplementedError('next',))
3886 <<< Finished
3887 >>> Testing ConvertFromPyObject using l.extend([%s])
3888 l.extend([None]):NOT FAILED
3889 l.extend([{b"": 1}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3890 l.extend([{"": 1}]):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3891 l.extend([FailingMapping()]):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3892 l.extend([FailingMappingKey()]):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3893 l.extend([FailingNumber()]):(<class 'NotImplementedError'>, NotImplementedError('int',))
3894 <<< Finished
3895 >> ListSetattr
3896 del l.locked:(<class 'AttributeError'>, AttributeError('cannot delete vim.List attributes',))
3897 l.locked = FailingTrue():(<class 'NotImplementedError'>, NotImplementedError('bool',))
3898 l.xxx = True:(<class 'AttributeError'>, AttributeError('cannot set attribute xxx',))
3899 > Function
3900 >> FunctionConstructor
3901 >>> FunctionConstructor
3902 vim.Function("123"):(<class 'ValueError'>, ValueError('unnamed function 123 does not exist',))
3903 vim.Function("xxx_non_existent_function_xxx"):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx does not exist',))
3904 vim.Function("xxx#non#existent#function#xxx"):NOT FAILED
3905 vim.Function("xxx_non_existent_function_xxx2", args=[]):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx2 does not exist',))
3906 vim.Function("xxx_non_existent_function_xxx3", self={}):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx3 does not exist',))
3907 vim.Function("xxx_non_existent_function_xxx4", args=[], self={}):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx4 does not exist',))
3908 >>> FunctionNew
3909 vim.Function("tr", self="abcFuncSelf"):(<class 'AttributeError'>, AttributeError('keys',))
3910 vim.Function("tr", args=427423):(<class 'TypeError'>, TypeError('unable to convert int to a Vim list',))
3911 vim.Function("tr", self="abcFuncSelf2", args="abcFuncArgs2"):(<class 'AttributeError'>, AttributeError('keys',))
3912 vim.Function(self="abcFuncSelf2", args="abcFuncArgs2"):(<class 'AttributeError'>, AttributeError('keys',))
3913 vim.Function("tr", "", self="abcFuncSelf2", args="abcFuncArgs2"):(<class 'AttributeError'>, AttributeError('keys',))
3914 vim.Function("tr", ""):(<class 'TypeError'>, TypeError('function takes exactly 1 argument (2 given)',))
3915 >> FunctionCall
3916 >>> Testing StringToChars using f({%s : 1})
3917 f({1 : 1}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3918 f({b"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3919 f({"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3920 <<< Finished
3921 >>> Testing StringToChars using f({"abcF" : {%s : 1}})
3922 f({"abcF" : {1 : 1}}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3923 f({"abcF" : {b"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3924 f({"abcF" : {"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3925 <<< Finished
3926 >>> Testing StringToChars using f({"abcF" : Mapping({%s : 1})})
3927 f({"abcF" : Mapping({1 : 1})}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3928 f({"abcF" : Mapping({b"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3929 f({"abcF" : Mapping({"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3930 <<< Finished
3931 >>> Testing *Iter* using f({"abcF" : %s})
3932 f({"abcF" : FailingIter()}):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3933 f({"abcF" : FailingIterNext()}):(<class 'NotImplementedError'>, NotImplementedError('next',))
3934 <<< Finished
3935 >>> Testing ConvertFromPyObject using f({"abcF" : %s})
3936 f({"abcF" : None}):NOT FAILED
3937 f({"abcF" : {b"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3938 f({"abcF" : {"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3939 f({"abcF" : FailingMapping()}):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3940 f({"abcF" : FailingMappingKey()}):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3941 f({"abcF" : FailingNumber()}):(<class 'NotImplementedError'>, NotImplementedError('int',))
3942 <<< Finished
3943 >>> Testing StringToChars using f(Mapping({%s : 1}))
3944 f(Mapping({1 : 1})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3945 f(Mapping({b"\0" : 1})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3946 f(Mapping({"\0" : 1})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3947 <<< Finished
3948 >>> Testing StringToChars using f(Mapping({"abcG" : {%s : 1}}))
3949 f(Mapping({"abcG" : {1 : 1}})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3950 f(Mapping({"abcG" : {b"\0" : 1}})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3951 f(Mapping({"abcG" : {"\0" : 1}})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3952 <<< Finished
3953 >>> Testing StringToChars using f(Mapping({"abcG" : Mapping({%s : 1})}))
3954 f(Mapping({"abcG" : Mapping({1 : 1})})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3955 f(Mapping({"abcG" : Mapping({b"\0" : 1})})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3956 f(Mapping({"abcG" : Mapping({"\0" : 1})})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3957 <<< Finished
3958 >>> Testing *Iter* using f(Mapping({"abcG" : %s}))
3959 f(Mapping({"abcG" : FailingIter()})):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3960 f(Mapping({"abcG" : FailingIterNext()})):(<class 'NotImplementedError'>, NotImplementedError('next',))
3961 <<< Finished
3962 >>> Testing ConvertFromPyObject using f(Mapping({"abcG" : %s}))
3963 f(Mapping({"abcG" : None})):NOT FAILED
3964 f(Mapping({"abcG" : {b"": 1}})):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3965 f(Mapping({"abcG" : {"": 1}})):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3966 f(Mapping({"abcG" : FailingMapping()})):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3967 f(Mapping({"abcG" : FailingMappingKey()})):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3968 f(Mapping({"abcG" : FailingNumber()})):(<class 'NotImplementedError'>, NotImplementedError('int',))
3969 <<< Finished
3970 >>> Testing *Iter* using f(%s)
3971 f(FailingIter()):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3972 f(FailingIterNext()):(<class 'NotImplementedError'>, NotImplementedError('next',))
3973 <<< Finished
3974 >>> Testing ConvertFromPyObject using f(%s)
3975 f(None):NOT FAILED
3976 f({b"": 1}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3977 f({"": 1}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
3978 f(FailingMapping()):(<class 'NotImplementedError'>, NotImplementedError('keys',))
3979 f(FailingMappingKey()):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
3980 f(FailingNumber()):(<class 'NotImplementedError'>, NotImplementedError('int',))
3981 <<< Finished
3982 >>> Testing StringToChars using fd(self={%s : 1})
3983 fd(self={1 : 1}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3984 fd(self={b"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3985 fd(self={"\0" : 1}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3986 <<< Finished
3987 >>> Testing StringToChars using fd(self={"abcF" : {%s : 1}})
3988 fd(self={"abcF" : {1 : 1}}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3989 fd(self={"abcF" : {b"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3990 fd(self={"abcF" : {"\0" : 1}}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3991 <<< Finished
3992 >>> Testing StringToChars using fd(self={"abcF" : Mapping({%s : 1})})
3993 fd(self={"abcF" : Mapping({1 : 1})}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
3994 fd(self={"abcF" : Mapping({b"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3995 fd(self={"abcF" : Mapping({"\0" : 1})}):(<class 'TypeError'>, TypeError('expected bytes with no null',))
3996 <<< Finished
3997 >>> Testing *Iter* using fd(self={"abcF" : %s})
3998 fd(self={"abcF" : FailingIter()}):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
3999 fd(self={"abcF" : FailingIterNext()}):(<class 'NotImplementedError'>, NotImplementedError('next',))
4000 <<< Finished
4001 >>> Testing ConvertFromPyObject using fd(self={"abcF" : %s})
4002 fd(self={"abcF" : None}):NOT FAILED
4003 fd(self={"abcF" : {b"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
4004 fd(self={"abcF" : {"": 1}}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
4005 fd(self={"abcF" : FailingMapping()}):(<class 'NotImplementedError'>, NotImplementedError('keys',))
4006 fd(self={"abcF" : FailingMappingKey()}):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
4007 fd(self={"abcF" : FailingNumber()}):(<class 'NotImplementedError'>, NotImplementedError('int',))
4008 <<< Finished
4009 >>> Testing StringToChars using fd(self=Mapping({%s : 1}))
4010 fd(self=Mapping({1 : 1})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
4011 fd(self=Mapping({b"\0" : 1})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
4012 fd(self=Mapping({"\0" : 1})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
4013 <<< Finished
4014 >>> Testing StringToChars using fd(self=Mapping({"abcG" : {%s : 1}}))
4015 fd(self=Mapping({"abcG" : {1 : 1}})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
4016 fd(self=Mapping({"abcG" : {b"\0" : 1}})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
4017 fd(self=Mapping({"abcG" : {"\0" : 1}})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
4018 <<< Finished
4019 >>> Testing StringToChars using fd(self=Mapping({"abcG" : Mapping({%s : 1})}))
4020 fd(self=Mapping({"abcG" : Mapping({1 : 1})})):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
4021 fd(self=Mapping({"abcG" : Mapping({b"\0" : 1})})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
4022 fd(self=Mapping({"abcG" : Mapping({"\0" : 1})})):(<class 'TypeError'>, TypeError('expected bytes with no null',))
4023 <<< Finished
4024 >>> Testing *Iter* using fd(self=Mapping({"abcG" : %s}))
4025 fd(self=Mapping({"abcG" : FailingIter()})):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim structure',))
4026 fd(self=Mapping({"abcG" : FailingIterNext()})):(<class 'NotImplementedError'>, NotImplementedError('next',))
4027 <<< Finished
4028 >>> Testing ConvertFromPyObject using fd(self=Mapping({"abcG" : %s}))
4029 fd(self=Mapping({"abcG" : None})):NOT FAILED
4030 fd(self=Mapping({"abcG" : {b"": 1}})):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
4031 fd(self=Mapping({"abcG" : {"": 1}})):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
4032 fd(self=Mapping({"abcG" : FailingMapping()})):(<class 'NotImplementedError'>, NotImplementedError('keys',))
4033 fd(self=Mapping({"abcG" : FailingMappingKey()})):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
4034 fd(self=Mapping({"abcG" : FailingNumber()})):(<class 'NotImplementedError'>, NotImplementedError('int',))
4035 <<< Finished
4036 >>> Testing *Iter* using fd(self=%s)
4037 fd(self=FailingIter()):(<class 'TypeError'>, TypeError('unable to convert FailingIter to a Vim dictionary',))
4038 fd(self=FailingIterNext()):(<class 'TypeError'>, TypeError('unable to convert FailingIterNext to a Vim dictionary',))
4039 <<< Finished
4040 >>> Testing ConvertFromPyObject using fd(self=%s)
4041 fd(self=None):(<class 'TypeError'>, TypeError('unable to convert NoneType to a Vim dictionary',))
4042 fd(self={b"": 1}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
4043 fd(self={"": 1}):(<class 'ValueError'>, ValueError('empty keys are not allowed',))
4044 fd(self=FailingMapping()):(<class 'NotImplementedError'>, NotImplementedError('keys',))
4045 fd(self=FailingMappingKey()):(<class 'NotImplementedError'>, NotImplementedError('getitem:mappingkey',))
4046 fd(self=FailingNumber()):(<class 'TypeError'>, TypeError('unable to convert FailingNumber to a Vim dictionary',))
4047 <<< Finished
4048 >>> Testing ConvertFromPyMapping using fd(self=%s)
4049 fd(self=[]):(<class 'AttributeError'>, AttributeError('keys',))
4050 <<< Finished
4051 > TabPage
4052 >> TabPageAttr
4053 vim.current.tabpage.xxx:(<class 'AttributeError'>, AttributeError("'vim.tabpage' object has no attribute 'xxx'",))
4054 > TabList
4055 >> TabListItem
4056 vim.tabpages[1000]:(<class 'IndexError'>, IndexError('no such tab page',))
4057 > Window
4058 >> WindowAttr
4059 vim.current.window.xxx:(<class 'AttributeError'>, AttributeError("'vim.window' object has no attribute 'xxx'",))
4060 >> WindowSetattr
4061 vim.current.window.buffer = 0:(<class 'TypeError'>, TypeError('readonly attribute: buffer',))
4062 vim.current.window.cursor = (100000000, 100000000):(<class 'vim.error'>, error('cursor position outside buffer',))
4063 vim.current.window.cursor = True:(<class 'TypeError'>, TypeError('argument must be 2-item sequence, not bool',))
4064 >>> Testing NumberToLong using vim.current.window.height = %s
4065 vim.current.window.height = []:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got list',))
4066 vim.current.window.height = None:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got NoneType',))
4067 vim.current.window.height = -1:(<class 'ValueError'>, ValueError('number must be greater or equal to zero',))
4068 <<< Finished
4069 >>> Testing NumberToLong using vim.current.window.width = %s
4070 vim.current.window.width = []:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got list',))
4071 vim.current.window.width = None:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got NoneType',))
4072 vim.current.window.width = -1:(<class 'ValueError'>, ValueError('number must be greater or equal to zero',))
4073 <<< Finished
4074 vim.current.window.xxxxxx = True:(<class 'AttributeError'>, AttributeError('xxxxxx',))
4075 > WinList
4076 >> WinListItem
4077 vim.windows[1000]:(<class 'IndexError'>, IndexError('no such window',))
4078 > Buffer
4079 >> StringToLine (indirect)
4080 vim.current.buffer[0] = "\na":(<class 'vim.error'>, error('string cannot contain newlines',))
4081 vim.current.buffer[0] = b"\na":(<class 'vim.error'>, error('string cannot contain newlines',))
4082 >> SetBufferLine (indirect)
4083 vim.current.buffer[0] = True:(<class 'TypeError'>, TypeError('bad argument type for built-in operation',))
4084 >> SetBufferLineList (indirect)
4085 vim.current.buffer[:] = True:(<class 'TypeError'>, TypeError('bad argument type for built-in operation',))
4086 vim.current.buffer[:] = ["\na", "bc"]:(<class 'vim.error'>, error('string cannot contain newlines',))
4087 >> InsertBufferLines (indirect)
4088 vim.current.buffer.append(None):(<class 'TypeError'>, TypeError('bad argument type for built-in operation',))
4089 vim.current.buffer.append(["\na", "bc"]):(<class 'vim.error'>, error('string cannot contain newlines',))
4090 vim.current.buffer.append("\nbc"):(<class 'vim.error'>, error('string cannot contain newlines',))
4091 >> RBItem
4092 vim.current.buffer[100000000]:(<class 'IndexError'>, IndexError('line number out of range',))
4093 >> RBAsItem
4094 vim.current.buffer[100000000] = "":(<class 'IndexError'>, IndexError('line number out of range',))
4095 >> BufferAttr
4096 vim.current.buffer.xxx:(<class 'AttributeError'>, AttributeError("'vim.buffer' object has no attribute 'xxx'",))
4097 >> BufferSetattr
4098 vim.current.buffer.name = True:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got bool',))
4099 vim.current.buffer.xxx = True:(<class 'AttributeError'>, AttributeError('xxx',))
4100 >> BufferMark
4101 vim.current.buffer.mark(0):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
4102 vim.current.buffer.mark("abcM"):(<class 'ValueError'>, ValueError('mark name must be a single character',))
4103 vim.current.buffer.mark("!"):(<class 'vim.error'>, error('invalid mark name',))
4104 >> BufferRange
4105 vim.current.buffer.range(1, 2, 3):(<class 'TypeError'>, TypeError('function takes exactly 2 arguments (3 given)',))
4106 > BufMap
4107 >> BufMapItem
4108 vim.buffers[100000000]:(<class 'KeyError'>, KeyError(100000000,))
4109 >>> Testing NumberToLong using vim.buffers[%s]
4110 vim.buffers[[]]:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got list',))
4111 vim.buffers[None]:(<class 'TypeError'>, TypeError('expected int() or something supporting coercing to int(), but got NoneType',))
4112 vim.buffers[-1]:(<class 'ValueError'>, ValueError('number must be greater than zero',))
4113 vim.buffers[0]:(<class 'ValueError'>, ValueError('number must be greater than zero',))
4114 <<< Finished
4115 > Current
4116 >> CurrentGetattr
4117 vim.current.xxx:(<class 'AttributeError'>, AttributeError("'vim.currentdata' object has no attribute 'xxx'",))
4118 >> CurrentSetattr
4119 vim.current.line = True:(<class 'TypeError'>, TypeError('bad argument type for built-in operation',))
4120 vim.current.buffer = True:(<class 'TypeError'>, TypeError('expected vim.Buffer object, but got bool',))
4121 vim.current.window = True:(<class 'TypeError'>, TypeError('expected vim.Window object, but got bool',))
4122 vim.current.tabpage = True:(<class 'TypeError'>, TypeError('expected vim.TabPage object, but got bool',))
4123 vim.current.xxx = True:(<class 'AttributeError'>, AttributeError('xxx',))
4124 END
4125
Bram Moolenaar68a48ee2020-10-27 19:59:10 +01004126 let actual = getline(2, '$')
4127 let n_expected = len(expected)
4128 let n_actual = len(actual)
4129 call assert_equal(n_expected, n_actual, 'number of lines to compare')
4130
4131 " Compare line by line so the errors are easier to understand. Missing lines
4132 " are compared with an empty string.
4133 for i in range(n_expected > n_actual ? n_expected : n_actual)
4134 call assert_equal(i >= n_expected ? '' : expected[i], i >= n_actual ? '' : actual[i])
4135 endfor
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02004136 close!
4137endfunc
4138
4139" Test import
4140func Test_python3_import()
4141 new
4142 py3 cb = vim.current.buffer
4143
4144 py3 << trim EOF
4145 sys.path.insert(0, os.path.join(os.getcwd(), 'python_before'))
4146 sys.path.append(os.path.join(os.getcwd(), 'python_after'))
4147 vim.options['rtp'] = os.getcwd().replace(',', '\\,').replace('\\', '\\\\')
4148 l = []
4149 def callback(path):
4150 l.append(os.path.relpath(path))
4151 vim.foreach_rtp(callback)
4152 cb.append(repr(l))
4153 del l
4154 def callback(path):
4155 return os.path.relpath(path)
4156 cb.append(repr(vim.foreach_rtp(callback)))
4157 del callback
4158 from module import dir as d
4159 from modulex import ddir
4160 cb.append(d + ',' + ddir)
4161 import before
4162 cb.append(before.dir)
4163 import after
4164 cb.append(after.dir)
4165 import topmodule as tm
4166 import topmodule.submodule as tms
4167 import topmodule.submodule.subsubmodule.subsubsubmodule as tmsss
4168 cb.append(tm.__file__.replace(os.path.sep, '/')[-len('modulex/topmodule/__init__.py'):])
4169 cb.append(tms.__file__.replace(os.path.sep, '/')[-len('modulex/topmodule/submodule/__init__.py'):])
4170 cb.append(tmsss.__file__.replace(os.path.sep, '/')[-len('modulex/topmodule/submodule/subsubmodule/subsubsubmodule.py'):])
4171
4172 del before
4173 del after
4174 del d
4175 del ddir
4176 del tm
4177 del tms
4178 del tmsss
4179 EOF
4180
4181 let expected =<< trim END
4182 ['.']
4183 '.'
4184 3,xx
4185 before
4186 after
4187 pythonx/topmodule/__init__.py
4188 pythonx/topmodule/submodule/__init__.py
4189 pythonx/topmodule/submodule/subsubmodule/subsubsubmodule.py
4190 END
4191 call assert_equal(expected, getline(2, '$'))
4192 close!
Bram Moolenaarab589462020-07-06 21:03:06 +02004193
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01004194 " Try to import a non-existing module with a dot (.)
Bram Moolenaarab589462020-07-06 21:03:06 +02004195 call AssertException(['py3 import a.b.c'], "No module named 'a'")
Bram Moolenaareffb0cd2020-07-03 21:17:34 +02004196endfunc
4197
4198" Test exceptions
4199func Test_python3_exception()
4200 func Exe(e)
4201 execute a:e
4202 endfunc
4203
4204 new
4205 py3 cb = vim.current.buffer
4206
4207 py3 << trim EOF
4208 Exe = vim.bindeval('function("Exe")')
4209 ee('vim.command("throw \'abcN\'")')
4210 ee('Exe("throw \'def\'")')
4211 ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
4212 ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
4213 ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
4214 ee('vim.eval("xxx_unknown_function_xxx()")')
4215 ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
4216 del Exe
4217 EOF
4218 delfunction Exe
4219
4220 let expected =<< trim END
4221 vim.command("throw 'abcN'"):(<class 'vim.error'>, error('abcN',))
4222 Exe("throw 'def'"):(<class 'vim.error'>, error('def',))
4223 vim.eval("Exe('throw ''ghi''')"):(<class 'vim.error'>, error('ghi',))
4224 vim.eval("Exe('echoerr ''jkl''')"):(<class 'vim.error'>, error('Vim(echoerr):jkl',))
4225 vim.eval("Exe('xxx_non_existent_command_xxx')"):(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
4226 vim.eval("xxx_unknown_function_xxx()"):(<class 'vim.error'>, error('Vim:E117: Unknown function: xxx_unknown_function_xxx',))
4227 vim.bindeval("Exe('xxx_non_existent_command_xxx')"):(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
4228 END
4229 call assert_equal(expected, getline(2, '$'))
4230 close!
4231endfunc
4232
4233" Regression: interrupting vim.command propagates to next vim.command
4234func Test_python3_keyboard_interrupt()
4235 new
4236 py3 cb = vim.current.buffer
4237 py3 << trim EOF
4238 def test_keyboard_interrupt():
4239 try:
4240 vim.command('while 1 | endwhile')
4241 except KeyboardInterrupt:
4242 cb.append('Caught KeyboardInterrupt')
4243 except Exception:
4244 cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
4245 else:
4246 cb.append('!!!!!!!! No exception')
4247 try:
4248 vim.command('$ put =\'Running :put\'')
4249 except KeyboardInterrupt:
4250 cb.append('!!!!!!!! Caught KeyboardInterrupt')
4251 except Exception:
4252 cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
4253 else:
4254 cb.append('No exception')
4255 EOF
4256
4257 debuggreedy
4258 call inputsave()
4259 call feedkeys("s\ns\ns\ns\nq\n")
4260 redir => output
4261 debug silent! py3 test_keyboard_interrupt()
4262 redir END
4263 0 debuggreedy
4264 call inputrestore()
4265 py3 del test_keyboard_interrupt
4266
4267 let expected =<< trim END
4268 Caught KeyboardInterrupt
4269 Running :put
4270 No exception
4271 END
4272 call assert_equal(expected, getline(2, '$'))
4273 call assert_equal('', output)
4274 close!
4275endfunc
4276
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004277" Regression: Iterator for a Vim object should hold a reference.
4278func Test_python3_iter_ref()
4279 let g:list_iter_ref_count_increase = -1
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01004280 let g:tuple_iter_ref_count_increase = -1
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004281 let g:dict_iter_ref_count_increase = -1
4282 let g:bufmap_iter_ref_count_increase = -1
4283 let g:options_iter_ref_count_increase = -1
4284
4285 py3 << trim EOF
4286 import sys
4287 import vim
4288
4289 def test_python3_iter_ref():
4290 create_list = vim.Function('Create_vim_list')
4291 v = create_list()
4292 base_ref_count = sys.getrefcount(v)
4293 for el in v:
Boris Staletic83a06702024-10-14 20:28:39 +02004294 vim.vars['list_iter_ref_count_increase'] = sys.getrefcount(v) - base_ref_count
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004295
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01004296 create_tuple = vim.Function('Create_vim_tuple')
4297 v = create_tuple()
4298 base_ref_count = sys.getrefcount(v)
4299 for el in v:
4300 vim.vars['tuple_iter_ref_count_increase'] = sys.getrefcount(v) - base_ref_count
4301
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004302 create_dict = vim.Function('Create_vim_dict')
4303 v = create_dict()
4304 base_ref_count = sys.getrefcount(v)
4305 for el in v:
Boris Staletic83a06702024-10-14 20:28:39 +02004306 vim.vars['dict_iter_ref_count_increase'] = sys.getrefcount(v) - base_ref_count
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004307
4308 v = vim.buffers
4309 base_ref_count = sys.getrefcount(v)
4310 for el in v:
Boris Staletic83a06702024-10-14 20:28:39 +02004311 vim.vars['bufmap_iter_ref_count_increase'] = sys.getrefcount(v) - base_ref_count
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004312
4313 v = vim.options
4314 base_ref_count = sys.getrefcount(v)
4315 for el in v:
Boris Staletic83a06702024-10-14 20:28:39 +02004316 vim.vars['options_iter_ref_count_increase'] = sys.getrefcount(v) - base_ref_count
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004317
4318 test_python3_iter_ref()
4319 EOF
4320
4321 call assert_equal(1, g:list_iter_ref_count_increase)
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01004322 call assert_equal(1, g:tuple_iter_ref_count_increase)
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004323 call assert_equal(1, g:dict_iter_ref_count_increase)
Boris Staletic83a06702024-10-14 20:28:39 +02004324 if py3eval('sys.version_info[:2] < (3, 13)')
4325 call assert_equal(1, g:bufmap_iter_ref_count_increase)
4326 else
4327 call assert_equal(0, g:bufmap_iter_ref_count_increase)
4328 endif
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004329 call assert_equal(1, g:options_iter_ref_count_increase)
4330endfunc
4331
Bram Moolenaar2e2f52a2020-12-21 16:03:02 +01004332func Test_python3_non_utf8_string()
4333 smap <Esc>@ <A-@>
4334 py3 vim.command('redir => _tmp_smaps | smap | redir END')
4335 py3 vim.eval('_tmp_smaps').splitlines()
4336 sunmap <Esc>@
4337endfunc
4338
Bram Moolenaar3e0107e2021-01-02 13:53:59 +01004339func Test_python3_fold_hidden_buffer()
4340 CheckFeature folding
4341
4342 set fdm=expr fde=Fde(v:lnum)
4343 let b:regex = '^'
4344 func Fde(lnum)
4345 let ld = [{}]
4346 let lines = bufnr('%')->getbufline(1, '$')
4347 let was_import = 0
4348 for lnum in range(1, len(lines))
4349 let line = lines[lnum]
4350 call add(ld, {'a': b:regex})
4351 let ld[lnum].foldexpr = was_import ? 1 : '>1'
4352 let was_import = 1
4353 endfor
4354 return ld[a:lnum].foldexpr
4355 endfunc
4356
4357 call setline(1, repeat([''], 15) + repeat(['from'], 3))
Bram Moolenaar145d1fd2022-09-30 21:57:11 +01004358 eval repeat(['x'], 17)->writefile('Xa.txt', 'D')
Bram Moolenaar3e0107e2021-01-02 13:53:59 +01004359 split Xa.txt
4360 py3 import vim
4361 py3 b = vim.current.buffer
4362 py3 aaa = b[:]
4363 hide
4364 py3 b[:] = aaa
4365
Bram Moolenaar3e0107e2021-01-02 13:53:59 +01004366 set fdm& fde&
4367 delfunc Fde
4368 bwipe! Xa.txt
4369endfunc
4370
Bram Moolenaar37233f62022-05-22 12:23:48 +01004371" Test to catch regression fix #10437.
4372func Test_python3_hidden_buf_mod_does_not_mess_up_display()
4373 CheckRunVimInTerminal
4374
4375 let testfile = 'Xtest.vim'
4376 let lines =<< trim END
4377 set hidden number
4378 new
4379 hide
4380 sil call setline(1, repeat(['aaa'], &lines) + ['bbbbbb'])
4381 fu Func()
4382 python3 << EOF
4383 import vim
4384 b = vim.buffers[2]
4385 b[:] = ['', '']
4386 EOF
4387 endfu
4388 norm! Gzb
4389 call feedkeys(":call Func()\r", 'n')
4390 END
Bram Moolenaar145d1fd2022-09-30 21:57:11 +01004391 call writefile(lines, testfile, 'D')
Bram Moolenaar37233f62022-05-22 12:23:48 +01004392
4393 let rows = 10
4394 let bufnr = term_start([GetVimProg(), '--clean', '-S', testfile], {'term_rows': rows})
4395 call TermWait(bufnr, 100)
4396 call assert_equal('run', job_status(term_getjob(bufnr)))
4397 let g:test_is_flaky = 0
4398 call WaitForAssert({-> assert_match('^ 3 aaa$', term_getline(bufnr, 1))})
4399 call WaitForAssert({-> assert_match('^ 11 bbbbbb$', term_getline(bufnr, rows - 1))})
4400
4401 call term_sendkeys(bufnr, ":qall!\<CR>")
4402 call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(bufnr)))})
Bram Moolenaar145d1fd2022-09-30 21:57:11 +01004403
Bram Moolenaar37233f62022-05-22 12:23:48 +01004404 exe bufnr . 'bwipe!'
Bram Moolenaar37233f62022-05-22 12:23:48 +01004405endfunc
4406
Bram Moolenaar1363a302020-04-12 13:50:26 +02004407" vim: shiftwidth=2 sts=2 expandtab