summaryrefslogtreecommitdiffstats
path: root/src/testdir/test87.in
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 02:44:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 02:44:24 +0000
commit8baab3c8d7a6f22888bd581cd5c6098fd2e4b5a8 (patch)
tree3537e168b860f2742f6029d70501b5ed7d15d345 /src/testdir/test87.in
parentInitial commit. (diff)
downloadvim-upstream.tar.xz
vim-upstream.zip
Adding upstream version 2:8.1.0875.upstream/2%8.1.0875upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/testdir/test87.in1725
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: