Mercurial > vim
view src/testdir/test87.in @ 5288:46cf49cc9289 v7.4b.020
updated for version 7.4b.020
Problem: "g~ap" changes first character of next paragraph. (Manuel Ortega)
Solution: Avoid subtracting (0 - 1) from todo. (Mike Williams)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Fri, 09 Aug 2013 19:48:40 +0200 |
parents | 29e57603bf6f |
children | 9cedb4dfd4c8 |
line wrap: on
line source
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 :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(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) :" :" 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) :" :" Locked variables :let l = [0, 1, 2, 3] :py3 l=vim.bindeval('l') :lockvar! l :py3 l[2]='i' :$put =string(l) :unlockvar! l :" :" Function calls :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) :try : py3 l[1](1, 2, 3) :catch : $put =v:exception[:13] :endtry :py3 f=l[0] :delfunction New :try : py3 f(1, 2, 3) :catch : $put =v:exception[:13] :endtry :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 d=vim.bindeval('{}') m=vim.bindeval('messages') def em(expr, g=globals(), l=locals()): try: exec(expr, g, l) except Exception as e: 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)) :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() :py3 l[0] = t.t > 8 # check if the background thread is working :py3 del time :py3 del threading :$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) :" :" 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 :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 : 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 cb = vim.current.buffer # 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 then 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'')')) :" :" 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('..') cb.append(str(fnamemodify('.', ':p:h:t'))) cb.append(vim.eval('@%').replace(os.path.sep, '/')) 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 import re py33_type_error_pattern = re.compile('^__call__\(\) takes (\d+) positional argument but (\d+) were given$') def ee(expr, g=globals(), l=locals()): 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."): cb.append(expr + ':' + 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: cb.append(expr + ':' + repr((e.__class__, 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)) cb.append(expr + ':' + repr((e.__class__, TypeError(msg)))) else: cb.append(expr + ':' + repr((e.__class__, e))) else: cb.append(expr + ':' + repr((e.__class__, e))) else: cb.append(expr + ':NOT FAILED') except Exception as e: cb.append(expr + '::' + repr((e.__class__, e))) 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 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 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('sys.stdout.attr = None') cb.append(">> OutputWrite") 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("> 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(">> 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()])') 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') 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") ee('vim.Function("123")') ee('vim.Function("xxx_non_existent_function_xxx")') ee('vim.Function("xxx#non#existent#function#xxx")') 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 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 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.bindeval("Exe(\'xxx_non_existent_command_xxx\')")') del Exe EOF :delfunction Exe :" :" Cleanup py3 << EOF del cb del ee 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 :" vim: et ts=4 isk-=\: :call getchar() ENDTEST start: