1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
" The Python provider helper
if exists('s:loaded_pythonx_provider')
finish
endif
let s:loaded_pythonx_provider = 1
let s:stderr = {}
let s:job_opts = {'rpc': v:true}
" TODO(bfredl): this logic is common and should be builtin
function! s:job_opts.on_stderr(chan_id, data, event)
let stderr = get(s:stderr, a:chan_id, [''])
let last = remove(stderr, -1)
let a:data[0] = last.a:data[0]
call extend(stderr, a:data)
let s:stderr[a:chan_id] = stderr
endfunction
function! provider#pythonx#Require(host) abort
let ver = (a:host.orig_name ==# 'python') ? 2 : 3
" Python host arguments
let prog = (ver == '2' ? provider#python#Prog() : provider#python3#Prog())
let args = [prog, '-c', 'import sys; sys.path.remove(""); import neovim; neovim.start_host()']
" Collect registered Python plugins into args
let python_plugins = remote#host#PluginsForHost(a:host.name)
for plugin in python_plugins
call add(args, plugin.path)
endfor
try
let channel_id = jobstart(args, s:job_opts)
if rpcrequest(channel_id, 'poll') ==# 'ok'
return channel_id
endif
catch
echomsg v:throwpoint
echomsg v:exception
for row in get(s:stderr, channel_id, [])
echomsg row
endfor
endtry
throw remote#host#LoadErrorForHost(a:host.orig_name,
\ '$NVIM_PYTHON_LOG_FILE')
endfunction
function! provider#pythonx#Detect(major_ver) abort
let host_var = (a:major_ver == 2) ?
\ 'g:python_host_prog' : 'g:python3_host_prog'
let skip_var = (a:major_ver == 2) ?
\ 'g:python_host_skip_check' : 'g:python3_host_skip_check'
let skip = exists(skip_var) ? {skip_var} : 0
if exists(host_var)
" Disable auto detection.
let [result, err] = s:check_interpreter({host_var}, a:major_ver, skip)
if result
return [{host_var}, err]
endif
return ['', 'provider/pythonx: Could not load Python ' . a:major_ver
\ . ' from ' . host_var . ': ' . err]
endif
let prog_suffixes = (a:major_ver == 2) ?
\ ['2', '2.7', '2.6', '']
\ : ['3', '3.5', '3.4', '3.3', '']
let errors = []
for prog in map(prog_suffixes, "'python' . v:val")
let [result, err] = s:check_interpreter(prog, a:major_ver, skip)
if result
return [prog, err]
endif
" Accumulate errors in case we don't find
" any suitable Python interpreter.
call add(errors, err)
endfor
" No suitable Python interpreter found.
return ['', 'provider/pythonx: Could not load Python ' . a:major_ver
\ . ":\n" . join(errors, "\n")]
endfunction
function! s:check_interpreter(prog, major_ver, skip) abort
let prog_path = exepath(a:prog)
if prog_path ==# ''
return [0, a:prog . ' not found in search path or not executable.']
endif
if a:skip
return [1, '']
endif
let min_version = (a:major_ver == 2) ? '2.6' : '3.3'
" Try to load neovim module, and output Python version.
" Return codes:
" 0 Neovim module can be loaded.
" 2 Neovim module cannot be loaded.
" Otherwise something else went wrong (e.g. 1 or 127).
let prog_ver = system([ a:prog , '-c' ,
\ 'import sys; ' .
\ 'sys.path.remove(""); ' .
\ 'sys.stdout.write(str(sys.version_info[0]) + "." + str(sys.version_info[1])); ' .
\ 'import pkgutil; ' .
\ 'exit(2*int(pkgutil.get_loader("neovim") is None))'
\ ])
if v:shell_error == 2 || v:shell_error == 0
" Check version only for expected return codes.
if prog_ver !~ '^' . a:major_ver
return [0, prog_path . ' is Python ' . prog_ver . ' and cannot provide Python '
\ . a:major_ver . '.']
elseif prog_ver =~ '^' . a:major_ver && prog_ver < min_version
return [0, prog_path . ' is Python ' . prog_ver . ' and cannot provide Python >= '
\ . min_version . '.']
endif
endif
if v:shell_error == 2
return [0, prog_path . ' does not have the neovim module installed. '
\ . 'See ":help provider-python".']
elseif v:shell_error == 127
" This can happen with pyenv's shims.
return [0, prog_path . ' does not exist: ' . prog_ver]
elseif v:shell_error
return [0, 'Checking ' . prog_path . ' caused an unknown error. '
\ . '(' . v:shell_error . ', output: ' . prog_ver . ')'
\ . ' Please report this at github.com/neovim/neovim.']
endif
return [1, '']
endfunction
|