diff options
Diffstat (limited to 'src/testdir/test87.in')
-rw-r--r-- | src/testdir/test87.in | 1725 |
1 files changed, 1725 insertions, 0 deletions
diff --git a/src/testdir/test87.in b/src/testdir/test87.in new file mode 100644 index 0000000..31de37b --- /dev/null +++ b/src/testdir/test87.in @@ -0,0 +1,1725 @@ +Tests for various python features. vim: set ft=vim : + +STARTTEST +:so small.vim +:set noswapfile +:if !has('python3') | e! test.ok | wq! test.out | endif +:lang C +:fun Test() +:py3 import vim +:py3 cb = vim.current.buffer +:let l = [] +:py3 l=vim.bindeval('l') +:py3 f=vim.bindeval('function("strlen")') +:" Extending List directly with different types +:py3 l+=[1, "as'd", [1, 2, f, {'a': 1}]] +:$put =string(l) +:$put =string(l[-1]) +:try +: $put =string(l[-4]) +:catch +: $put =v:exception[:13] +:endtry +:" List assignment +:py3 l[0]=0 +:$put =string(l) +:py3 l[-2]=f +:$put =string(l) +:" +:" Extending Dictionary directly with different types +:let d = {} +:fun d.f() +: return 1 +:endfun +py3 << EOF +d=vim.bindeval('d') +d['1']='asd' +d.update() # Must not do anything, including throwing errors +d.update(b=[1, 2, f]) +d.update((('-1', {'a': 1}),)) +d.update({'0': -1}) +dk = d.keys() +dv = d.values() +di = d.items() +dk.sort(key=repr) +dv.sort(key=repr) +di.sort(key=repr) +EOF +:$put =py3eval('d[''f''](self={})') +:$put =py3eval('repr(dk)') +:$put =substitute(py3eval('repr(dv)'),'0x\x\+','','g') +:$put =substitute(py3eval('repr(di)'),'0x\x\+','','g') +:for [key, Val] in sort(items(d)) +: $put =string(key) . ' : ' . string(Val) +: unlet key Val +:endfor +:py3 del dk +:py3 del di +:py3 del dv +:" +:" removing items with del +:py3 del l[2] +:$put =string(l) +:let l = range(8) +:py3 l=vim.bindeval('l') +:try +: py3 del l[:3] +: py3 del l[1:] +:catch +: $put =v:exception +:endtry +:$put =string(l) +:" +:py3 del d['-1'] +:py3 del d['f'] +:$put =string(py3eval('d.get(''b'', 1)')) +:$put =string(py3eval('d.pop(''b'')')) +:$put =string(py3eval('d.get(''b'', 1)')) +:$put =string(py3eval('d.pop(''1'', 2)')) +:$put =string(py3eval('d.pop(''1'', 2)')) +:$put =py3eval('repr(d.has_key(''0''))') +:$put =py3eval('repr(d.has_key(''1''))') +:$put =py3eval('repr(''0'' in d)') +:$put =py3eval('repr(''1'' in d)') +:$put =py3eval('repr(list(iter(d)))') +:$put =string(d) +:$put =py3eval('repr(d.popitem())') +:$put =py3eval('repr(d.get(''0''))') +:$put =py3eval('repr(list(iter(d)))') +:" +:" removing items out of range: silently skip items that don't exist +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:" The following two ranges delete nothing as they match empty list: +:py3 del l[2:1] +:$put =string(l) +:py3 del l[2:2] +:$put =string(l) +:py3 del l[2:3] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[2:4] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[2:5] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[2:6] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:" The following two ranges delete nothing as they match empty list: +:py3 del l[-1:2] +:$put =string(l) +:py3 del l[-2:2] +:$put =string(l) +:py3 del l[-3:2] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[-4:2] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[-5:2] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[-6:2] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[::2] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[3:0:-2] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 del l[2:4:-2] +:$put =string(l) +:" +:" Slice assignment to a list +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 l[0:0]=['a'] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 l[1:2]=['b'] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 l[2:4]=['c'] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 l[4:4]=['d'] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 l[-1:2]=['e'] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 l[-10:2]=['f'] +:$put =string(l) +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:py3 l[2:-10]=['g'] +:$put =string(l) +:let l = [] +:py3 l=vim.bindeval('l') +:py3 l[0:0]=['h'] +:$put =string(l) +:let l = range(8) +:py3 l=vim.bindeval('l') +:py3 l[2:6:2] = [10, 20] +:$put =string(l) +:let l = range(8) +:py3 l=vim.bindeval('l') +:py3 l[6:2:-2] = [10, 20] +:$put =string(l) +:let l = range(8) +:py3 l=vim.bindeval('l') +:py3 l[6:2] = () +:$put =string(l) +:let l = range(8) +:py3 l=vim.bindeval('l') +:py3 l[6:2:1] = () +:$put =string(l) +:let l = range(8) +:py3 l=vim.bindeval('l') +:py3 l[2:2:1] = () +:$put =string(l) +:" +:" Locked variables +:let l = [0, 1, 2, 3] +:py3 l=vim.bindeval('l') +:lockvar! l +py3 << EOF +def emsg(ei): + return ei[0].__name__ + ':' + repr(ei[1].args) + +try: + l[2]='i' +except vim.error: + cb.append('l[2] threw vim.error: ' + emsg(sys.exc_info())) +EOF +:$put =string(l) +:unlockvar! l +:" +:" Function calls +py3 << EOF +import sys +import re + +py33_type_error_pattern = re.compile('^__call__\(\) takes (\d+) positional argument but (\d+) were given$') +py37_exception_repr = re.compile(r'([^\(\),])(\)+)$') + +def ee(expr, g=globals(), l=locals()): + cb = vim.current.buffer + try: + try: + exec(expr, g, l) + except Exception as e: + 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."): + msg = repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1]))) + elif sys.version_info >= (3, 3) and e.__class__ is ImportError and str(e).find('No module named \'') >= 0: + msg = repr((e.__class__, ImportError(str(e).replace("'", '')))) + elif sys.version_info >= (3, 6) and e.__class__ is ModuleNotFoundError: + # Python 3.6 gives ModuleNotFoundError, change it to an ImportError + msg = repr((ImportError, ImportError(str(e).replace("'", '')))) + elif sys.version_info >= (3, 3) and e.__class__ is TypeError: + m = py33_type_error_pattern.search(str(e)) + if m: + msg = '__call__() takes exactly {0} positional argument ({1} given)'.format(m.group(1), m.group(2)) + msg = repr((e.__class__, TypeError(msg))) + else: + msg = repr((e.__class__, e)) + # Messages changed with Python 3.6, change new to old. + newmsg1 = """'argument must be str, bytes or bytearray, not None'""" + oldmsg1 = '''"Can't convert 'NoneType' object to str implicitly"''' + if msg.find(newmsg1) > -1: + msg = msg.replace(newmsg1, oldmsg1) + newmsg2 = """'argument must be str, bytes or bytearray, not int'""" + oldmsg2 = '''"Can't convert 'int' object to str implicitly"''' + if msg.find(newmsg2) > -1: + msg = msg.replace(newmsg2, oldmsg2) + elif sys.version_info >= (3, 5) and e.__class__ is ValueError and str(e) == 'embedded null byte': + msg = repr((TypeError, TypeError('expected bytes with no null'))) + else: + msg = repr((e.__class__, e)) + # Some Python versions say can't, others cannot. + if msg.find('can\'t') > -1: + msg = msg.replace('can\'t', 'cannot') + # Some Python versions use single quote, some double quote + if msg.find('"cannot ') > -1: + msg = msg.replace('"cannot ', '\'cannot ') + if msg.find(' attributes"') > -1: + msg = msg.replace(' attributes"', ' attributes\'') + if sys.version_info >= (3, 7): + msg = py37_exception_repr.sub(r'\1,\2', msg) + cb.append(expr + ':' + msg) + else: + cb.append(expr + ':NOT FAILED') + except Exception as e: + msg = repr((e.__class__, e)) + if sys.version_info >= (3, 7): + msg = py37_exception_repr.sub(r'\1,\2', msg) + cb.append(expr + '::' + msg) +EOF +:fun New(...) +: return ['NewStart']+a:000+['NewEnd'] +:endfun +:fun DictNew(...) dict +: return ['DictNewStart']+a:000+['DictNewEnd', self] +:endfun +:let l=[function('New'), function('DictNew')] +:py3 l=vim.bindeval('l') +:py3 l.extend(list(l[0](1, 2, 3))) +:$put =string(l) +:py3 l.extend(list(l[1](1, 2, 3, self={'a': 'b'}))) +:$put =string(l) +:py3 l+=[l[0].name] +:$put =string(l) +:py3 ee('l[1](1, 2, 3)') +:py3 f=l[0] +:delfunction New +:py3 ee('f(1, 2, 3)') +:if has('float') +: let l=[0.0] +: py3 l=vim.bindeval('l') +: py3 l.extend([0.0]) +: $put =string(l) +:else +: $put ='[0.0, 0.0]' +:endif +:let messages=[] +:delfunction DictNew +py3 <<EOF +import sys +d=vim.bindeval('{}') +m=vim.bindeval('messages') +def em(expr, g=globals(), l=locals()): + try: + exec(expr, g, l) + except Exception as e: + if sys.version_info >= (3, 5) and e.__class__ is ValueError and str(e) == 'embedded null byte': + m.extend([TypeError.__name__]) + else: + m.extend([e.__class__.__name__]) + +em('d["abc1"]') +em('d["abc1"]="\\0"') +em('d["abc1"]=vim') +em('d[""]=1') +em('d["a\\0b"]=1') +em('d[b"a\\0b"]=1') + +em('d.pop("abc1")') +em('d.popitem()') +del em +del m +EOF +:$put =messages +:unlet messages +:" locked and scope attributes +:let d={} | let dl={} | lockvar dl +:for s in split("d dl v: g:") +: let name=tr(s, ':', 's') +: execute 'py3 '.name.'=vim.bindeval("'.s.'")' +: let toput=s.' : '.join(map(['locked', 'scope'], 'v:val.":".py3eval(name.".".v:val)'), ';') +: $put =toput +:endfor +:silent! let d.abc2=1 +:silent! let dl.abc3=1 +:py3 d.locked=True +:py3 dl.locked=False +:silent! let d.def=1 +:silent! let dl.def=1 +:put ='d:'.string(d) +:put ='dl:'.string(dl) +:unlet d dl +: +:let l=[] | let ll=[] | lockvar ll +:for s in split("l ll") +: let name=tr(s, ':', 's') +: execute 'py3 '.name.'=vim.bindeval("'.s.'")' +: let toput=s.' : locked:'.py3eval(name.'.locked') +: $put =toput +:endfor +:silent! call extend(l, [0]) +:silent! call extend(ll, [0]) +:py3 l.locked=True +:py3 ll.locked=False +:silent! call extend(l, [1]) +:silent! call extend(ll, [1]) +:put ='l:'.string(l) +:put ='ll:'.string(ll) +:unlet l ll +:" +:" py3eval() +:let l=py3eval('[0, 1, 2]') +:$put =string(l) +:let d=py3eval('{"a": "b", "c": 1, "d": ["e"]}') +:$put =sort(items(d)) +:let v:errmsg = '' +:$put ='py3eval(\"None\") = ' . py3eval('None') . v:errmsg +:if has('float') +: let f=py3eval('0.0') +: $put =string(f) +:else +: $put ='0.0' +:endif +:" Invalid values: +:for e in ['"\0"', '{"\0": 1}', 'undefined_name', 'vim'] +: try +: let v=py3eval(e) +: catch +: let toput=e.":\t".v:exception[:13] +: $put =toput +: endtry +:endfor +:" +:" threading +:let l = [0] +:py3 l=vim.bindeval('l') +py3 <<EOF +import threading +import time + +class T(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + self.t = 0 + self.running = True + + def run(self): + while self.running: + self.t += 1 + time.sleep(0.1) + +t = T() +del T +t.start() +EOF +:sleep 1 +:py3 t.running = False +:py3 t.join() +:" Check if the background thread is working. Count should be 10, but on a +:" busy system (AppVeyor) it can be much lower. +:py3 l[0] = t.t > 4 +:py3 del time +:py3 del threading +:py3 del t +:$put =string(l) +:" +:" settrace +:let l = [] +:py3 l=vim.bindeval('l') +py3 <<EOF +import sys + +def traceit(frame, event, arg): + global l + if event == "line": + l += [frame.f_lineno] + return traceit + +def trace_main(): + for i in range(5): + pass +EOF +:py3 sys.settrace(traceit) +:py3 trace_main() +:py3 sys.settrace(None) +:py3 del traceit +:py3 del trace_main +:$put =string(l) +:" +:" Slice +:py3 ll = vim.bindeval('[0, 1, 2, 3, 4, 5]') +:py3 l = ll[:4] +:$put =string(py3eval('l')) +:py3 l = ll[2:] +:$put =string(py3eval('l')) +:py3 l = ll[:-4] +:$put =string(py3eval('l')) +:py3 l = ll[-2:] +:$put =string(py3eval('l')) +:py3 l = ll[2:4] +:$put =string(py3eval('l')) +:py3 l = ll[4:2] +:$put =string(py3eval('l')) +:py3 l = ll[-4:-2] +:$put =string(py3eval('l')) +:py3 l = ll[-2:-4] +:$put =string(py3eval('l')) +:py3 l = ll[:] +:$put =string(py3eval('l')) +:py3 l = ll[0:6] +:$put =string(py3eval('l')) +:py3 l = ll[-10:10] +:$put =string(py3eval('l')) +:py3 l = ll[4:2:-1] +:$put =string(py3eval('l')) +:py3 l = ll[::2] +:$put =string(py3eval('l')) +:py3 l = ll[4:2:1] +:$put =string(py3eval('l')) +:py3 del l +:" +:" Vars +:let g:foo = 'bac' +:let w:abc3 = 'def' +:let b:baz = 'bar' +:let t:bar = 'jkl' +:try +: throw "Abc" +:catch +: put =py3eval('vim.vvars[''exception'']') +:endtry +:put =py3eval('vim.vars[''foo'']') +:put =py3eval('vim.current.window.vars[''abc3'']') +:put =py3eval('vim.current.buffer.vars[''baz'']') +:put =py3eval('vim.current.tabpage.vars[''bar'']') +:" +:" Options +:" paste: boolean, global +:" previewheight number, global +:" operatorfunc: string, global +:" number: boolean, window-local +:" numberwidth: number, window-local +:" colorcolumn: string, window-local +:" statusline: string, window-local/global +:" autoindent: boolean, buffer-local +:" shiftwidth: number, buffer-local +:" omnifunc: string, buffer-local +:" preserveindent: boolean, buffer-local/global +:" path: string, buffer-local/global +:let g:bufs=[bufnr('%')] +:new +:let g:bufs+=[bufnr('%')] +:vnew +:let g:bufs+=[bufnr('%')] +:wincmd j +:vnew +:let g:bufs+=[bufnr('%')] +:wincmd l +:fun RecVars(opt) +: let gval =string(eval('&g:'.a:opt)) +: let wvals=join(map(range(1, 4), 'v:val.":".string(getwinvar(v:val, "&".a:opt))')) +: let bvals=join(map(copy(g:bufs), 'v:val.":".string(getbufvar(v:val, "&".a:opt))')) +: put =' G: '.gval +: put =' W: '.wvals +: put =' B: '.wvals +:endfun +py3 << EOF +def e(s, g=globals(), l=locals()): + try: + exec(s, g, l) + except Exception as e: + vim.command('return ' + repr(e.__class__.__name__)) + +def ev(s, g=globals(), l=locals()): + try: + return eval(s, g, l) + except Exception as e: + vim.command('let exc=' + repr(e.__class__.__name__)) + return 0 +EOF +:fun E(s) +: python3 e(vim.eval('a:s')) +:endfun +:fun Ev(s) +: let r=py3eval('ev(vim.eval("a:s"))') +: if exists('exc') +: throw exc +: endif +: return r +:endfun +:py3 gopts1=vim.options +:py3 wopts1=vim.windows[2].options +:py3 wopts2=vim.windows[0].options +:py3 wopts3=vim.windows[1].options +:py3 bopts1=vim.buffers[vim.bindeval("g:bufs")[2]].options +:py3 bopts2=vim.buffers[vim.bindeval("g:bufs")[1]].options +:py3 bopts3=vim.buffers[vim.bindeval("g:bufs")[0]].options +:$put ='wopts iters equal: '.py3eval('list(wopts1) == list(wopts2)') +:$put ='bopts iters equal: '.py3eval('list(bopts1) == list(bopts2)') +:py3 gset=set(iter(gopts1)) +:py3 wset=set(iter(wopts1)) +:py3 bset=set(iter(bopts1)) +:set path=.,..,, +:let lst=[] +:let lst+=[['paste', 1, 0, 1, 2, 1, 1, 0 ]] +:let lst+=[['previewheight', 5, 1, 6, 'a', 0, 1, 0 ]] +:let lst+=[['operatorfunc', 'A', 'B', 'C', 2, 0, 1, 0 ]] +:let lst+=[['number', 0, 1, 1, 0, 1, 0, 1 ]] +:let lst+=[['numberwidth', 2, 3, 5, -100, 0, 0, 1 ]] +:let lst+=[['colorcolumn', '+1', '+2', '+3', 'abc4', 0, 0, 1 ]] +:let lst+=[['statusline', '1', '2', '4', 0, 0, 1, 1 ]] +:let lst+=[['autoindent', 0, 1, 1, 2, 1, 0, 2 ]] +:let lst+=[['shiftwidth', 0, 2, 1, 3, 0, 0, 2 ]] +:let lst+=[['omnifunc', 'A', 'B', 'C', 1, 0, 0, 2 ]] +:let lst+=[['preserveindent', 0, 1, 1, 2, 1, 1, 2 ]] +:let lst+=[['path', '.,,', ',,', '.', 0, 0, 1, 2 ]] +:for [oname, oval1, oval2, oval3, invval, bool, global, local] in lst +: py3 oname=vim.eval('oname') +: py3 oval1=vim.bindeval('oval1') +: py3 oval2=vim.bindeval('oval2') +: py3 oval3=vim.bindeval('oval3') +: if invval is 0 || invval is 1 +: py3 invval=bool(vim.bindeval('invval')) +: else +: py3 invval=vim.bindeval('invval') +: endif +: if bool +: py3 oval1=bool(oval1) +: py3 oval2=bool(oval2) +: py3 oval3=bool(oval3) +: endif +: put ='>>> '.oname +: $put =' g/w/b:'.py3eval('oname in gset').'/'.py3eval('oname in wset').'/'.py3eval('oname in bset') +: $put =' g/w/b (in):'.py3eval('oname in gopts1').'/'.py3eval('oname in wopts1').'/'.py3eval('oname in bopts1') +: for v in ['gopts1', 'wopts1', 'bopts1'] +: try +: put =' p/'.v.': '.Ev('repr('.v.'['''.oname.'''])') +: catch +: put =' p/'.v.'! '.v:exception +: endtry +: let r=E(v.'['''.oname.''']=invval') +: if r isnot 0 +: put =' inv: '.string(invval).'! '.r +: endif +: for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3']) +: let val=substitute(vv, '^.opts', 'oval', '') +: let r=E(vv.'['''.oname.''']='.val) +: if r isnot 0 +: put =' '.vv.'! '.r +: endif +: endfor +: endfor +: call RecVars(oname) +: for v in ['wopts3', 'bopts3'] +: let r=E('del '.v.'["'.oname.'"]') +: if r isnot 0 +: put =' del '.v.'! '.r +: endif +: endfor +: call RecVars(oname) +:endfor +:delfunction RecVars +:delfunction E +:delfunction Ev +:py3 del ev +:py3 del e +:only +:for buf in g:bufs[1:] +: execute 'bwipeout!' buf +:endfor +:py3 del gopts1 +:py3 del wopts1 +:py3 del wopts2 +:py3 del wopts3 +:py3 del bopts1 +:py3 del bopts2 +:py3 del bopts3 +:py3 del oval1 +:py3 del oval2 +:py3 del oval3 +:py3 del oname +:py3 del invval +:" +:" Test buffer object +:vnew +:put ='First line' +:put ='Second line' +:put ='Third line' +:1 delete _ +:py3 b=vim.current.buffer +:wincmd w +:mark a +:augroup BUFS +: autocmd BufFilePost * python3 cb.append(vim.eval('expand("<abuf>")') + ':BufFilePost:' + vim.eval('bufnr("%")')) +: autocmd BufFilePre * python3 cb.append(vim.eval('expand("<abuf>")') + ':BufFilePre:' + vim.eval('bufnr("%")')) +:augroup END +py3 << EOF +# Tests BufferAppend and BufferItem +cb.append(b[0]) +# Tests BufferSlice and BufferAssSlice +cb.append('abc5') # Will be overwritten +cb[-1:] = b[:-2] +# Test BufferLength and BufferAssSlice +cb.append('def') # Will not be overwritten +cb[len(cb):] = b[:] +# Test BufferAssItem and BufferMark +cb.append('ghi') # Will be overwritten +cb[-1] = repr((len(cb) - cb.mark('a')[0], cb.mark('a')[1])) +# Test BufferRepr +cb.append(repr(cb) + repr(b)) +# Modify foreign buffer +b.append('foo') +b[0]='bar' +b[0:0]=['baz'] +vim.command('call append("$", getbufline(%i, 1, "$"))' % b.number) +# Test assigning to name property +import os +old_name = cb.name +cb.name = 'foo' +cb.append(cb.name[-11:].replace(os.path.sep, '/')) +b.name = 'bar' +cb.append(b.name[-11:].replace(os.path.sep, '/')) +cb.name = old_name +cb.append(cb.name[-17:].replace(os.path.sep, '/')) +del old_name +# Test CheckBuffer +for _b in vim.buffers: + if _b is not cb: + vim.command('bwipeout! ' + str(_b.number)) +del _b +cb.append('valid: b:%s, cb:%s' % (repr(b.valid), repr(cb.valid))) +for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc6")'): + try: + exec(expr) + except vim.error: + pass + else: + # Usually a SEGV here + # Should not happen in any case + cb.append('No exception for ' + expr) +vim.command('cd .') +del b +EOF +:" +:" Test vim.buffers object +:set hidden +:edit a +:buffer # +:edit b +:buffer # +:edit c +:buffer # +py3 << EOF +# Check GCing iterator that was not fully exhausted +i = iter(vim.buffers) +cb.append('i:' + str(next(i))) +# and also check creating more than one iterator at a time +i2 = iter(vim.buffers) +cb.append('i2:' + str(next(i2))) +cb.append('i:' + str(next(i))) +# The following should trigger GC and not cause any problems +del i +del i2 +i3 = iter(vim.buffers) +cb.append('i3:' + str(next(i3))) +del i3 + +prevnum = 0 +for b in vim.buffers: + # Check buffer order + if prevnum >= b.number: + cb.append('!!! Buffer numbers not in strictly ascending order') + # Check indexing: vim.buffers[number].number == number + cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b)) + prevnum = b.number +del prevnum + +cb.append(str(len(vim.buffers))) + +bnums = list(map(lambda b: b.number, vim.buffers))[1:] + +# Test wiping out buffer with existing iterator +i4 = iter(vim.buffers) +cb.append('i4:' + str(next(i4))) +vim.command('bwipeout! ' + str(bnums.pop(0))) +try: + next(i4) +except vim.error: + pass +else: + cb.append('!!!! No vim.error') +i4 = iter(vim.buffers) +vim.command('bwipeout! ' + str(bnums.pop(-1))) +vim.command('bwipeout! ' + str(bnums.pop(-1))) +cb.append('i4:' + str(next(i4))) +try: + next(i4) +except StopIteration: + cb.append('StopIteration') +del i4 +del bnums +EOF +:" +:" Test vim.{tabpage,window}list and vim.{tabpage,window} objects +:tabnew 0 +:tabnew 1 +:vnew a.1 +:tabnew 2 +:vnew a.2 +:vnew b.2 +:vnew c.2 +py3 << EOF +cb.append('Number of tabs: ' + str(len(vim.tabpages))) +cb.append('Current tab pages:') + +def W(w): + if '(unknown)' in repr(w): + return '<window object (unknown)>' + else: + return repr(w) + +def Cursor(w, start=len(cb)): + if w.buffer is cb: + return repr((start - w.cursor[0], w.cursor[1])) + else: + return repr(w.cursor) + +for t in vim.tabpages: + cb.append(' ' + repr(t) + '(' + str(t.number) + ')' + ': ' + str(len(t.windows)) + ' windows, current is ' + W(t.window)) + cb.append(' Windows:') + for w in t.windows: + cb.append(' ' + W(w) + '(' + str(w.number) + ')' + ': displays buffer ' + repr(w.buffer) + '; cursor is at ' + Cursor(w)) + # Other values depend on the size of the terminal, so they are checked partly: + for attr in ('height', 'row', 'width', 'col'): + try: + aval = getattr(w, attr) + if type(aval) is not int: + raise TypeError + if aval < 0: + raise ValueError + except Exception as e: + cb.append('!!!!!! Error while getting attribute ' + attr + ': ' + e.__class__.__name__) + del aval + del attr + w.cursor = (len(w.buffer), 0) +del W +del Cursor +cb.append('Number of windows in current tab page: ' + str(len(vim.windows))) +if list(vim.windows) != list(vim.current.tabpage.windows): + cb.append('!!!!!! Windows differ') +EOF +:" +:" Test vim.current +py3 << EOF +def H(o): + return repr(o) +cb.append('Current tab page: ' + repr(vim.current.tabpage)) +cb.append('Current window: ' + repr(vim.current.window) + ': ' + H(vim.current.window) + ' is ' + H(vim.current.tabpage.window)) +cb.append('Current buffer: ' + repr(vim.current.buffer) + ': ' + H(vim.current.buffer) + ' is ' + H(vim.current.window.buffer)+ ' is ' + H(vim.current.tabpage.window.buffer)) +del H +# Assigning: fails +try: + vim.current.window = vim.tabpages[0].window +except ValueError: + cb.append('ValueError at assigning foreign tab window') + +for attr in ('window', 'tabpage', 'buffer'): + try: + setattr(vim.current, attr, None) + except TypeError: + cb.append('Type error at assigning None to vim.current.' + attr) +del attr + +# Assigning: success +vim.current.tabpage = vim.tabpages[-2] +vim.current.buffer = cb +vim.current.window = vim.windows[0] +vim.current.window.cursor = (len(vim.current.buffer), 0) +cb.append('Current tab page: ' + repr(vim.current.tabpage)) +cb.append('Current window: ' + repr(vim.current.window)) +cb.append('Current buffer: ' + repr(vim.current.buffer)) +cb.append('Current line: ' + repr(vim.current.line)) +ws = list(vim.windows) +ts = list(vim.tabpages) +for b in vim.buffers: + if b is not cb: + vim.command('bwipeout! ' + str(b.number)) +del b +cb.append('w.valid: ' + repr([w.valid for w in ws])) +cb.append('t.valid: ' + repr([t.valid for t in ts])) +del w +del t +del ts +del ws +EOF +:tabonly! +:only! +:" +:" Test types +py3 << EOF +for expr, attr in ( + ('vim.vars', 'Dictionary'), + ('vim.options', 'Options'), + ('vim.bindeval("{}")', 'Dictionary'), + ('vim.bindeval("[]")', 'List'), + ('vim.bindeval("function(\'tr\')")', 'Function'), + ('vim.current.buffer', 'Buffer'), + ('vim.current.range', 'Range'), + ('vim.current.window', 'Window'), + ('vim.current.tabpage', 'TabPage'), +): + cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr))) +del expr +del attr +EOF +:" +:" Test __dir__() method +py3 << EOF +for name, o in ( + ('current', vim.current), + ('buffer', vim.current.buffer), + ('window', vim.current.window), + ('tabpage', vim.current.tabpage), + ('range', vim.current.range), + ('dictionary', vim.bindeval('{}')), + ('list', vim.bindeval('[]')), + ('function', vim.bindeval('function("tr")')), + ('output', sys.stdout), + ): + cb.append(name + ':' + ','.join(dir(o))) +del name +del o +EOF +:" +:" Test vim.*.__new__ +:$put =string(py3eval('vim.Dictionary({})')) +:$put =string(py3eval('vim.Dictionary(a=1)')) +:$put =string(py3eval('vim.Dictionary(((''a'', 1),))')) +:$put =string(py3eval('vim.List()')) +:$put =string(py3eval('vim.List(iter(''abc7''))')) +:$put =string(py3eval('vim.Function(''tr'')')) +:$put =string(py3eval('vim.Function(''tr'', args=[123, 3, 4])')) +:$put =string(py3eval('vim.Function(''tr'', args=[])')) +:$put =string(py3eval('vim.Function(''tr'', self={})')) +:$put =string(py3eval('vim.Function(''tr'', args=[123, 3, 4], self={})')) +:$put ='auto_rebind' +:$put =string(py3eval('vim.Function(''tr'', auto_rebind=False)')) +:$put =string(py3eval('vim.Function(''tr'', args=[123, 3, 4], auto_rebind=False)')) +:$put =string(py3eval('vim.Function(''tr'', args=[], auto_rebind=False)')) +:$put =string(py3eval('vim.Function(''tr'', self={}, auto_rebind=False)')) +:$put =string(py3eval('vim.Function(''tr'', args=[123, 3, 4], self={}, auto_rebind=False)')) +:" +:" Test vim.Function +:function Args(...) +: return a:000 +:endfunction +:function SelfArgs(...) dict +: return [a:000, self] +:endfunction +:" The following four lines should not crash +:let Pt = function('tr', [[]], {'l': []}) +:py3 Pt = vim.bindeval('Pt') +:unlet Pt +:py3 del Pt +py3 << EOF +def ecall(out_prefix, func, *args, **kwargs): + line = out_prefix + ': ' + try: + ret = func(*args, **kwargs) + except Exception: + line += '!exception: ' + emsg(sys.exc_info()) + else: + line += '!result: ' + str(vim.Function('string')(ret), 'utf-8') + cb.append(line) +a = vim.Function('Args') +pa1 = vim.Function('Args', args=['abcArgsPA1']) +pa2 = vim.Function('Args', args=[]) +pa3 = vim.Function('Args', args=['abcArgsPA3'], self={'abcSelfPA3': 'abcSelfPA3Val'}) +pa4 = vim.Function('Args', self={'abcSelfPA4': 'abcSelfPA4Val'}) +cb.append('a: ' + repr(a)) +cb.append('pa1: ' + repr(pa1)) +cb.append('pa2: ' + repr(pa2)) +cb.append('pa3: ' + repr(pa3)) +cb.append('pa4: ' + repr(pa4)) +sa = vim.Function('SelfArgs') +psa1 = vim.Function('SelfArgs', args=['abcArgsPSA1']) +psa2 = vim.Function('SelfArgs', args=[]) +psa3 = vim.Function('SelfArgs', args=['abcArgsPSA3'], self={'abcSelfPSA3': 'abcSelfPSA3Val'}) +psa4 = vim.Function('SelfArgs', self={'abcSelfPSA4': 'abcSelfPSA4Val'}) +psa5 = vim.Function('SelfArgs', self={'abcSelfPSA5': 'abcSelfPSA5Val'}, auto_rebind=0) +psa6 = vim.Function('SelfArgs', args=['abcArgsPSA6'], self={'abcSelfPSA6': 'abcSelfPSA6Val'}, auto_rebind=()) +psa7 = vim.Function('SelfArgs', args=['abcArgsPSA7'], auto_rebind=[]) +psa8 = vim.Function('SelfArgs', auto_rebind=False) +psa9 = vim.Function('SelfArgs', self={'abcSelfPSA9': 'abcSelfPSA9Val'}, auto_rebind=True) +psaA = vim.Function('SelfArgs', args=['abcArgsPSAA'], self={'abcSelfPSAA': 'abcSelfPSAAVal'}, auto_rebind=1) +psaB = vim.Function('SelfArgs', args=['abcArgsPSAB'], auto_rebind={'abcARPSAB': 'abcARPSABVal'}) +psaC = vim.Function('SelfArgs', auto_rebind=['abcARPSAC']) +cb.append('sa: ' + repr(sa)) +cb.append('psa1: ' + repr(psa1)) +cb.append('psa2: ' + repr(psa2)) +cb.append('psa3: ' + repr(psa3)) +cb.append('psa4: ' + repr(psa4)) +cb.append('psa5: ' + repr(psa5)) +cb.append('psa6: ' + repr(psa6)) +cb.append('psa7: ' + repr(psa7)) +cb.append('psa8: ' + repr(psa8)) +cb.append('psa9: ' + repr(psa9)) +cb.append('psaA: ' + repr(psaA)) +cb.append('psaB: ' + repr(psaB)) +cb.append('psaC: ' + repr(psaC)) + +psar = vim.Function('SelfArgs', args=[{'abcArgsPSAr': 'abcArgsPSArVal'}], self={'abcSelfPSAr': 'abcSelfPSArVal'}) +psar.args[0]['abcArgsPSAr2'] = [psar.self, psar.args[0]] +psar.self['rec'] = psar +psar.self['self'] = psar.self +psar.self['args'] = psar.args + +try: + cb.append('psar: ' + repr(psar)) +except Exception: + cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info())) +EOF +:$put ='s(a): '.string(py3eval('a')) +:$put ='s(pa1): '.string(py3eval('pa1')) +:$put ='s(pa2): '.string(py3eval('pa2')) +:$put ='s(pa3): '.string(py3eval('pa3')) +:$put ='s(pa4): '.string(py3eval('pa4')) +:$put ='s(sa): '.string(py3eval('sa')) +:$put ='s(psa1): '.string(py3eval('psa1')) +:$put ='s(psa2): '.string(py3eval('psa2')) +:$put ='s(psa3): '.string(py3eval('psa3')) +:$put ='s(psa4): '.string(py3eval('psa4')) +:$put ='s(psa5): '.string(py3eval('psa5')) +:$put ='s(psa6): '.string(py3eval('psa6')) +:$put ='s(psa7): '.string(py3eval('psa7')) +:$put ='s(psa8): '.string(py3eval('psa8')) +:$put ='s(psa9): '.string(py3eval('psa9')) +:$put ='s(psaA): '.string(py3eval('psaA')) +:$put ='s(psaB): '.string(py3eval('psaB')) +:$put ='s(psaC): '.string(py3eval('psaC')) +: +:for v in ['sa', 'psa1', 'psa2', 'psa3', 'psa4', 'psa5', 'psa6', 'psa7', 'psa8', 'psa9', 'psaA', 'psaB', 'psaC'] +: let d = {'f': py3eval(v)} +: $put ='d.'.v.'(): '.string(d.f()) +:endfor +: +:py3 ecall('a()', a, ) +:py3 ecall('pa1()', pa1, ) +:py3 ecall('pa2()', pa2, ) +:py3 ecall('pa3()', pa3, ) +:py3 ecall('pa4()', pa4, ) +:py3 ecall('sa()', sa, ) +:py3 ecall('psa1()', psa1, ) +:py3 ecall('psa2()', psa2, ) +:py3 ecall('psa3()', psa3, ) +:py3 ecall('psa4()', psa4, ) +: +:py3 ecall('a(42, 43)', a, 42, 43) +:py3 ecall('pa1(42, 43)', pa1, 42, 43) +:py3 ecall('pa2(42, 43)', pa2, 42, 43) +:py3 ecall('pa3(42, 43)', pa3, 42, 43) +:py3 ecall('pa4(42, 43)', pa4, 42, 43) +:py3 ecall('sa(42, 43)', sa, 42, 43) +:py3 ecall('psa1(42, 43)', psa1, 42, 43) +:py3 ecall('psa2(42, 43)', psa2, 42, 43) +:py3 ecall('psa3(42, 43)', psa3, 42, 43) +:py3 ecall('psa4(42, 43)', psa4, 42, 43) +: +:py3 ecall('a(42, self={"20": 1})', a, 42, self={'20': 1}) +:py3 ecall('pa1(42, self={"20": 1})', pa1, 42, self={'20': 1}) +:py3 ecall('pa2(42, self={"20": 1})', pa2, 42, self={'20': 1}) +:py3 ecall('pa3(42, self={"20": 1})', pa3, 42, self={'20': 1}) +:py3 ecall('pa4(42, self={"20": 1})', pa4, 42, self={'20': 1}) +:py3 ecall('sa(42, self={"20": 1})', sa, 42, self={'20': 1}) +:py3 ecall('psa1(42, self={"20": 1})', psa1, 42, self={'20': 1}) +:py3 ecall('psa2(42, self={"20": 1})', psa2, 42, self={'20': 1}) +:py3 ecall('psa3(42, self={"20": 1})', psa3, 42, self={'20': 1}) +:py3 ecall('psa4(42, self={"20": 1})', psa4, 42, self={'20': 1}) +: +:py3 ecall('a(self={"20": 1})', a, self={'20': 1}) +:py3 ecall('pa1(self={"20": 1})', pa1, self={'20': 1}) +:py3 ecall('pa2(self={"20": 1})', pa2, self={'20': 1}) +:py3 ecall('pa3(self={"20": 1})', pa3, self={'20': 1}) +:py3 ecall('pa4(self={"20": 1})', pa4, self={'20': 1}) +:py3 ecall('sa(self={"20": 1})', sa, self={'20': 1}) +:py3 ecall('psa1(self={"20": 1})', psa1, self={'20': 1}) +:py3 ecall('psa2(self={"20": 1})', psa2, self={'20': 1}) +:py3 ecall('psa3(self={"20": 1})', psa3, self={'20': 1}) +:py3 ecall('psa4(self={"20": 1})', psa4, self={'20': 1}) +py3 << EOF +def s(v): + if v is None: + return repr(v) + else: + return str(vim.Function('string')(v), 'utf-8') + +cb.append('a.args: ' + s(a.args)) +cb.append('pa1.args: ' + s(pa1.args)) +cb.append('pa2.args: ' + s(pa2.args)) +cb.append('pa3.args: ' + s(pa3.args)) +cb.append('pa4.args: ' + s(pa4.args)) +cb.append('sa.args: ' + s(sa.args)) +cb.append('psa1.args: ' + s(psa1.args)) +cb.append('psa2.args: ' + s(psa2.args)) +cb.append('psa3.args: ' + s(psa3.args)) +cb.append('psa4.args: ' + s(psa4.args)) + +cb.append('a.self: ' + s(a.self)) +cb.append('pa1.self: ' + s(pa1.self)) +cb.append('pa2.self: ' + s(pa2.self)) +cb.append('pa3.self: ' + s(pa3.self)) +cb.append('pa4.self: ' + s(pa4.self)) +cb.append('sa.self: ' + s(sa.self)) +cb.append('psa1.self: ' + s(psa1.self)) +cb.append('psa2.self: ' + s(psa2.self)) +cb.append('psa3.self: ' + s(psa3.self)) +cb.append('psa4.self: ' + s(psa4.self)) + +cb.append('a.name: ' + s(a.name)) +cb.append('pa1.name: ' + s(pa1.name)) +cb.append('pa2.name: ' + s(pa2.name)) +cb.append('pa3.name: ' + s(pa3.name)) +cb.append('pa4.name: ' + s(pa4.name)) +cb.append('sa.name: ' + s(sa.name)) +cb.append('psa1.name: ' + s(psa1.name)) +cb.append('psa2.name: ' + s(psa2.name)) +cb.append('psa3.name: ' + s(psa3.name)) +cb.append('psa4.name: ' + s(psa4.name)) + +cb.append('a.auto_rebind: ' + s(a.auto_rebind)) +cb.append('pa1.auto_rebind: ' + s(pa1.auto_rebind)) +cb.append('pa2.auto_rebind: ' + s(pa2.auto_rebind)) +cb.append('pa3.auto_rebind: ' + s(pa3.auto_rebind)) +cb.append('pa4.auto_rebind: ' + s(pa4.auto_rebind)) +cb.append('sa.auto_rebind: ' + s(sa.auto_rebind)) +cb.append('psa1.auto_rebind: ' + s(psa1.auto_rebind)) +cb.append('psa2.auto_rebind: ' + s(psa2.auto_rebind)) +cb.append('psa3.auto_rebind: ' + s(psa3.auto_rebind)) +cb.append('psa4.auto_rebind: ' + s(psa4.auto_rebind)) +cb.append('psa5.auto_rebind: ' + s(psa5.auto_rebind)) +cb.append('psa6.auto_rebind: ' + s(psa6.auto_rebind)) +cb.append('psa7.auto_rebind: ' + s(psa7.auto_rebind)) +cb.append('psa8.auto_rebind: ' + s(psa8.auto_rebind)) +cb.append('psa9.auto_rebind: ' + s(psa9.auto_rebind)) +cb.append('psaA.auto_rebind: ' + s(psaA.auto_rebind)) +cb.append('psaB.auto_rebind: ' + s(psaB.auto_rebind)) +cb.append('psaC.auto_rebind: ' + s(psaC.auto_rebind)) + +del s + +del a +del pa1 +del pa2 +del pa3 +del pa4 +del sa +del psa1 +del psa2 +del psa3 +del psa4 +del psa5 +del psa6 +del psa7 +del psa8 +del psa9 +del psaA +del psaB +del psaC +del psar + +del ecall +EOF +:" +:" Test stdout/stderr +:redir => messages +:py3 sys.stdout.write('abc8') ; sys.stdout.write('def') +:py3 sys.stderr.write('abc9') ; sys.stderr.write('def') +:py3 sys.stdout.writelines(iter('abcA')) +:py3 sys.stderr.writelines(iter('abcB')) +:redir END +:$put =string(substitute(messages, '\d\+', '', 'g')) +:" Test subclassing +:fun Put(...) +: $put =string(a:000) +: return a:000 +:endfun +py3 << EOF +class DupDict(vim.Dictionary): + def __setitem__(self, key, value): + super(DupDict, self).__setitem__(key, value) + super(DupDict, self).__setitem__('dup_' + key, value) +dd = DupDict() +dd['a'] = 'b' + +class DupList(vim.List): + def __getitem__(self, idx): + return [super(DupList, self).__getitem__(idx)] * 2 + +dl = DupList() +dl2 = DupList(iter('abcC')) +dl.extend(dl2[0]) + +class DupFun(vim.Function): + def __call__(self, arg): + return super(DupFun, self).__call__(arg, arg) + +df = DupFun('Put') +EOF +:$put =string(sort(keys(py3eval('dd')))) +:$put =string(py3eval('dl')) +:$put =string(py3eval('dl2')) +:$put =string(py3eval('df(2)')) +:$put =string(py3eval('dl') is# py3eval('dl')) +:$put =string(py3eval('dd') is# py3eval('dd')) +:$put =string(py3eval('df')) +:delfunction Put +py3 << EOF +del DupDict +del DupList +del DupFun +del dd +del dl +del dl2 +del df +EOF +:" +:" Test chdir +py3 << EOF +import os +fnamemodify = vim.Function('fnamemodify') +cb.append(str(fnamemodify('.', ':p:h:t'))) +cb.append(vim.eval('@%')) +os.chdir('..') +path = fnamemodify('.', ':p:h:t') +if path != b'src': + # Running tests from a shadow directory, so move up another level + # This will result in @% looking like shadow/testdir/test87.in, hence the + # slicing to remove the leading path and path separator + os.chdir('..') + cb.append(str(fnamemodify('.', ':p:h:t'))) + cb.append(vim.eval('@%')[len(path)+1:].replace(os.path.sep, '/')) + os.chdir(path) +else: + cb.append(str(fnamemodify('.', ':p:h:t'))) + cb.append(vim.eval('@%').replace(os.path.sep, '/')) +del path +os.chdir('testdir') +cb.append(str(fnamemodify('.', ':p:h:t'))) +cb.append(vim.eval('@%')) +del fnamemodify +EOF +:" +:" Test errors +:fun F() dict +:endfun +:fun D() +:endfun +py3 << EOF +d = vim.Dictionary() +ned = vim.Dictionary(foo='bar', baz='abcD') +dl = vim.Dictionary(a=1) +dl.locked = True +l = vim.List() +ll = vim.List('abcE') +ll.locked = True +nel = vim.List('abcO') +f = vim.Function('string') +fd = vim.Function('F') +fdel = vim.Function('D') +vim.command('delfunction D') + +def subexpr_test(expr, name, subexprs): + cb.append('>>> Testing %s using %s' % (name, expr)) + for subexpr in subexprs: + ee(expr % subexpr) + cb.append('<<< Finished') + +def stringtochars_test(expr): + return subexpr_test(expr, 'StringToChars', ( + '1', # Fail type checks + 'b"\\0"', # Fail PyString_AsStringAndSize(object, , NULL) check + '"\\0"', # Fail PyString_AsStringAndSize(bytes, , NULL) check + )) + +class Mapping(object): + def __init__(self, d): + self.d = d + + def __getitem__(self, key): + return self.d[key] + + def keys(self): + return self.d.keys() + + def items(self): + return self.d.items() + +def convertfrompyobject_test(expr, recurse=True): + # pydict_to_tv + stringtochars_test(expr % '{%s : 1}') + if recurse: + convertfrompyobject_test(expr % '{"abcF" : %s}', False) + # pymap_to_tv + stringtochars_test(expr % 'Mapping({%s : 1})') + if recurse: + convertfrompyobject_test(expr % 'Mapping({"abcG" : %s})', False) + # pyseq_to_tv + iter_test(expr) + return subexpr_test(expr, 'ConvertFromPyObject', ( + 'None', # Not conversible + '{b"": 1}', # Empty key not allowed + '{"": 1}', # Same, but with unicode object + 'FailingMapping()', # + 'FailingMappingKey()', # + 'FailingNumber()', # + )) + +def convertfrompymapping_test(expr): + convertfrompyobject_test(expr) + return subexpr_test(expr, 'ConvertFromPyMapping', ( + '[]', + )) + +def iter_test(expr): + return subexpr_test(expr, '*Iter*', ( + 'FailingIter()', + 'FailingIterNext()', + )) + +def number_test(expr, natural=False, unsigned=False): + if natural: + unsigned = True + return subexpr_test(expr, 'NumberToLong', ( + '[]', + 'None', + ) + (('-1',) if unsigned else ()) + + (('0',) if natural else ())) + +class FailingTrue(object): + def __bool__(self): + raise NotImplementedError('bool') + +class FailingIter(object): + def __iter__(self): + raise NotImplementedError('iter') + +class FailingIterNext(object): + def __iter__(self): + return self + + def __next__(self): + raise NotImplementedError('next') + +class FailingIterNextN(object): + def __init__(self, n): + self.n = n + + def __iter__(self): + return self + + def __next__(self): + if self.n: + self.n -= 1 + return 1 + else: + raise NotImplementedError('next N') + +class FailingMappingKey(object): + def __getitem__(self, item): + raise NotImplementedError('getitem:mappingkey') + + def keys(self): + return list("abcH") + +class FailingMapping(object): + def __getitem__(self): + raise NotImplementedError('getitem:mapping') + + def keys(self): + raise NotImplementedError('keys') + +class FailingList(list): + def __getitem__(self, idx): + if i == 2: + raise NotImplementedError('getitem:list') + else: + return super(FailingList, self).__getitem__(idx) + +class NoArgsCall(object): + def __call__(self): + pass + +class FailingCall(object): + def __call__(self, path): + raise NotImplementedError('call') + +class FailingNumber(object): + def __int__(self): + raise NotImplementedError('int') + +cb.append("> Output") +cb.append(">> OutputSetattr") +ee('del sys.stdout.softspace') +number_test('sys.stdout.softspace = %s', unsigned=True) +number_test('sys.stderr.softspace = %s', unsigned=True) +ee('assert sys.stdout.isatty()==False') +ee('assert sys.stdout.seekable()==False') +ee('sys.stdout.close()') +ee('sys.stdout.flush()') +ee('assert sys.stderr.isatty()==False') +ee('assert sys.stderr.seekable()==False') +ee('sys.stderr.close()') +ee('sys.stderr.flush()') +ee('sys.stdout.attr = None') +cb.append(">> OutputWrite") +ee('assert sys.stdout.writable()==True') +ee('assert sys.stdout.readable()==False') +ee('assert sys.stderr.writable()==True') +ee('assert sys.stderr.readable()==False') +ee('assert sys.stdout.closed()==False') +ee('assert sys.stderr.closed()==False') +ee('assert sys.stdout.errors=="strict"') +ee('assert sys.stderr.errors=="strict"') +ee('assert sys.stdout.encoding==sys.stderr.encoding') +ee('sys.stdout.write(None)') +cb.append(">> OutputWriteLines") +ee('sys.stdout.writelines(None)') +ee('sys.stdout.writelines([1])') +iter_test('sys.stdout.writelines(%s)') +cb.append("> VimCommand") +stringtochars_test('vim.command(%s)') +ee('vim.command("", 2)') +#! Not checked: vim->python exceptions translating: checked later +cb.append("> VimToPython") +#! Not checked: everything: needs errors in internal python functions +cb.append("> VimEval") +stringtochars_test('vim.eval(%s)') +ee('vim.eval("", FailingTrue())') +#! Not checked: everything: needs errors in internal python functions +cb.append("> VimEvalPy") +stringtochars_test('vim.bindeval(%s)') +ee('vim.eval("", 2)') +#! Not checked: vim->python exceptions translating: checked later +cb.append("> VimStrwidth") +stringtochars_test('vim.strwidth(%s)') +cb.append("> VimForeachRTP") +ee('vim.foreach_rtp(None)') +ee('vim.foreach_rtp(NoArgsCall())') +ee('vim.foreach_rtp(FailingCall())') +ee('vim.foreach_rtp(int, 2)') +cb.append('> import') +old_rtp = vim.options['rtp'] +vim.options['rtp'] = os.getcwd().replace('\\', '\\\\').replace(',', '\\,') +ee('import xxx_no_such_module_xxx') +ee('import failing_import') +ee('import failing') +vim.options['rtp'] = old_rtp +del old_rtp +cb.append("> Options") +cb.append(">> OptionsItem") +ee('vim.options["abcQ"]') +ee('vim.options[""]') +stringtochars_test('vim.options[%s]') +cb.append(">> OptionsContains") +stringtochars_test('%s in vim.options') +cb.append("> Dictionary") +cb.append(">> DictionaryConstructor") +ee('vim.Dictionary("abcI")') +##! Not checked: py_dict_alloc failure +cb.append(">> DictionarySetattr") +ee('del d.locked') +ee('d.locked = FailingTrue()') +ee('vim.vvars.locked = False') +ee('d.scope = True') +ee('d.xxx = True') +cb.append(">> _DictionaryItem") +ee('d.get("a", 2, 3)') +stringtochars_test('d.get(%s)') +ee('d.pop("a")') +ee('dl.pop("a")') +cb.append(">> DictionaryContains") +ee('"" in d') +ee('0 in d') +cb.append(">> DictionaryIterNext") +ee('for i in ned: ned["a"] = 1') +del i +cb.append(">> DictionaryAssItem") +ee('dl["b"] = 1') +stringtochars_test('d[%s] = 1') +convertfrompyobject_test('d["a"] = %s') +cb.append(">> DictionaryUpdate") +cb.append(">>> kwargs") +cb.append(">>> iter") +ee('d.update(FailingMapping())') +ee('d.update([FailingIterNext()])') +ee('d.update([FailingIterNextN(1)])') +iter_test('d.update(%s)') +convertfrompyobject_test('d.update(%s)') +stringtochars_test('d.update(((%s, 0),))') +convertfrompyobject_test('d.update((("a", %s),))') +cb.append(">> DictionaryPopItem") +ee('d.popitem(1, 2)') +cb.append(">> DictionaryHasKey") +ee('d.has_key()') +cb.append("> List") +cb.append(">> ListConstructor") +ee('vim.List(1, 2)') +ee('vim.List(a=1)') +iter_test('vim.List(%s)') +convertfrompyobject_test('vim.List([%s])') +cb.append(">> ListItem") +ee('l[1000]') +cb.append(">> ListAssItem") +ee('ll[1] = 2') +ee('l[1000] = 3') +cb.append(">> ListAssSlice") +ee('ll[1:100] = "abcJ"') +iter_test('l[:] = %s') +ee('nel[1:10:2] = "abcK"') +cb.append(repr(tuple(nel))) +ee('nel[1:10:2] = "a"') +cb.append(repr(tuple(nel))) +ee('nel[1:1:-1] = "a"') +cb.append(repr(tuple(nel))) +ee('nel[:] = FailingIterNextN(2)') +cb.append(repr(tuple(nel))) +convertfrompyobject_test('l[:] = [%s]') +cb.append(">> ListConcatInPlace") +iter_test('l.extend(%s)') +convertfrompyobject_test('l.extend([%s])') +cb.append(">> ListSetattr") +ee('del l.locked') +ee('l.locked = FailingTrue()') +ee('l.xxx = True') +cb.append("> Function") +cb.append(">> FunctionConstructor") +cb.append(">>> FunctionConstructor") +ee('vim.Function("123")') +ee('vim.Function("xxx_non_existent_function_xxx")') +ee('vim.Function("xxx#non#existent#function#xxx")') +ee('vim.Function("xxx_non_existent_function_xxx2", args=[])') +ee('vim.Function("xxx_non_existent_function_xxx3", self={})') +ee('vim.Function("xxx_non_existent_function_xxx4", args=[], self={})') +cb.append(">>> FunctionNew") +ee('vim.Function("tr", self="abcFuncSelf")') +ee('vim.Function("tr", args=427423)') +ee('vim.Function("tr", self="abcFuncSelf2", args="abcFuncArgs2")') +ee('vim.Function(self="abcFuncSelf2", args="abcFuncArgs2")') +ee('vim.Function("tr", "", self="abcFuncSelf2", args="abcFuncArgs2")') +ee('vim.Function("tr", "")') +cb.append(">> FunctionCall") +convertfrompyobject_test('f(%s)') +convertfrompymapping_test('fd(self=%s)') +cb.append("> TabPage") +cb.append(">> TabPageAttr") +ee('vim.current.tabpage.xxx') +cb.append("> TabList") +cb.append(">> TabListItem") +ee('vim.tabpages[1000]') +cb.append("> Window") +cb.append(">> WindowAttr") +ee('vim.current.window.xxx') +cb.append(">> WindowSetattr") +ee('vim.current.window.buffer = 0') +ee('vim.current.window.cursor = (100000000, 100000000)') +ee('vim.current.window.cursor = True') +number_test('vim.current.window.height = %s', unsigned=True) +number_test('vim.current.window.width = %s', unsigned=True) +ee('vim.current.window.xxxxxx = True') +cb.append("> WinList") +cb.append(">> WinListItem") +ee('vim.windows[1000]') +cb.append("> Buffer") +cb.append(">> StringToLine (indirect)") +ee('vim.current.buffer[0] = "\\na"') +ee('vim.current.buffer[0] = b"\\na"') +cb.append(">> SetBufferLine (indirect)") +ee('vim.current.buffer[0] = True') +cb.append(">> SetBufferLineList (indirect)") +ee('vim.current.buffer[:] = True') +ee('vim.current.buffer[:] = ["\\na", "bc"]') +cb.append(">> InsertBufferLines (indirect)") +ee('vim.current.buffer.append(None)') +ee('vim.current.buffer.append(["\\na", "bc"])') +ee('vim.current.buffer.append("\\nbc")') +cb.append(">> RBItem") +ee('vim.current.buffer[100000000]') +cb.append(">> RBAsItem") +ee('vim.current.buffer[100000000] = ""') +cb.append(">> BufferAttr") +ee('vim.current.buffer.xxx') +cb.append(">> BufferSetattr") +ee('vim.current.buffer.name = True') +ee('vim.current.buffer.xxx = True') +cb.append(">> BufferMark") +ee('vim.current.buffer.mark(0)') +ee('vim.current.buffer.mark("abcM")') +ee('vim.current.buffer.mark("!")') +cb.append(">> BufferRange") +ee('vim.current.buffer.range(1, 2, 3)') +cb.append("> BufMap") +cb.append(">> BufMapItem") +ee('vim.buffers[100000000]') +number_test('vim.buffers[%s]', natural=True) +cb.append("> Current") +cb.append(">> CurrentGetattr") +ee('vim.current.xxx') +cb.append(">> CurrentSetattr") +ee('vim.current.line = True') +ee('vim.current.buffer = True') +ee('vim.current.window = True') +ee('vim.current.tabpage = True') +ee('vim.current.xxx = True') +del d +del ned +del dl +del l +del ll +del nel +del f +del fd +del fdel +del subexpr_test +del stringtochars_test +del Mapping +del convertfrompyobject_test +del convertfrompymapping_test +del iter_test +del number_test +del FailingTrue +del FailingIter +del FailingIterNext +del FailingIterNextN +del FailingMapping +del FailingMappingKey +del FailingList +del NoArgsCall +del FailingCall +del FailingNumber +EOF +:delfunction F +:" +:" Test import +py3 << EOF +sys.path.insert(0, os.path.join(os.getcwd(), 'python_before')) +sys.path.append(os.path.join(os.getcwd(), 'python_after')) +vim.options['rtp'] = os.getcwd().replace(',', '\\,').replace('\\', '\\\\') +l = [] +def callback(path): + l.append(os.path.relpath(path)) +vim.foreach_rtp(callback) +cb.append(repr(l)) +del l +def callback(path): + return os.path.relpath(path) +cb.append(repr(vim.foreach_rtp(callback))) +del callback +from module import dir as d +from modulex import ddir +cb.append(d + ',' + ddir) +import before +cb.append(before.dir) +import after +cb.append(after.dir) +import topmodule as tm +import topmodule.submodule as tms +import topmodule.submodule.subsubmodule.subsubsubmodule as tmsss +cb.append(tm.__file__.replace(os.path.sep, '/')[-len('modulex/topmodule/__init__.py'):]) +cb.append(tms.__file__.replace(os.path.sep, '/')[-len('modulex/topmodule/submodule/__init__.py'):]) +cb.append(tmsss.__file__.replace(os.path.sep, '/')[-len('modulex/topmodule/submodule/subsubmodule/subsubsubmodule.py'):]) +del before +del after +del d +del ddir +del tm +del tms +del tmsss +EOF +:" +:" Test exceptions +:fun Exe(e) +: execute a:e +:endfun +py3 << EOF +Exe = vim.bindeval('function("Exe")') +ee('vim.command("throw \'abcN\'")') +ee('Exe("throw \'def\'")') +ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")') +ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")') +ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")') +ee('vim.eval("xxx_unknown_function_xxx()")') +ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")') +del Exe +EOF +:delfunction Exe +:" +:" Regression: interrupting vim.command propagates to next vim.command +py3 << EOF +def test_keyboard_interrupt(): + try: + vim.command('while 1 | endwhile') + except KeyboardInterrupt: + cb.append('Caught KeyboardInterrupt') + except Exception: + cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info())) + else: + cb.append('!!!!!!!! No exception') + try: + vim.command('$ put =\'Running :put\'') + except KeyboardInterrupt: + cb.append('!!!!!!!! Caught KeyboardInterrupt') + except Exception: + cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info())) + else: + cb.append('No exception') +EOF +:debuggreedy +:call inputsave() +:call feedkeys("s\ns\ns\ns\nq\n") +:redir => output +:debug silent! py3 test_keyboard_interrupt() +:redir END +:0 debuggreedy +:call inputrestore() +:silent $put =output +:unlet output +:py3 del test_keyboard_interrupt +:" +:" Cleanup +py3 << EOF +del cb +del ee +del emsg +del sys +del os +del vim +EOF +:endfun +:" +:fun RunTest() +:let checkrefs = !empty($PYTHONDUMPREFS) +:let start = getline(1, '$') +:for i in range(checkrefs ? 10 : 1) +: if i != 0 +: %d _ +: call setline(1, start) +: endif +: call Test() +: if i == 0 +: let result = getline(1, '$') +: endif +:endfor +:if checkrefs +: %d _ +: call setline(1, result) +:endif +:endfun +:" +:call RunTest() +:delfunction RunTest +:delfunction Test +:call garbagecollect(1) +:" +:/^start:/,$wq! test.out +:/^start:/,$w! test.out +:" vim: et ts=4 isk-=\: +:while getchar(0) isnot 0|endwhile +ENDTEST + +start: |