mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
feat(provider)!: remove support for python2 and python3.[3-5]
These versions of python has reached End-of-life. getting rid of python2 support removes a lot of logic to support two incompatible python versions in the same version.
This commit is contained in:
parent
b2f77c354a
commit
baec0d3152
@ -104,8 +104,8 @@ function! s:check_rplugin_manifest() abort
|
||||
if !has_key(existing_rplugins, script)
|
||||
let msg = printf('"%s" is not registered.', fnamemodify(path, ':t'))
|
||||
if python_version ==# 'pythonx'
|
||||
if !has('python2') && !has('python3')
|
||||
let msg .= ' (python2 and python3 not available)'
|
||||
if !has('python3')
|
||||
let msg .= ' (python3 not available)'
|
||||
endif
|
||||
elseif !has(python_version)
|
||||
let msg .= printf(' (%s not available)', python_version)
|
||||
|
@ -282,10 +282,10 @@ function! s:disabled_via_loaded_var(provider) abort
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:check_python(version) abort
|
||||
call health#report_start('Python ' . a:version . ' provider (optional)')
|
||||
function! s:check_python() abort
|
||||
call health#report_start('Python 3 provider (optional)')
|
||||
|
||||
let pyname = 'python'.(a:version == 2 ? '' : '3')
|
||||
let pyname = 'python3'
|
||||
let python_exe = ''
|
||||
let venv = exists('$VIRTUAL_ENV') ? resolve($VIRTUAL_ENV) : ''
|
||||
let host_prog_var = pyname.'_host_prog'
|
||||
@ -301,7 +301,7 @@ function! s:check_python(version) abort
|
||||
call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var)))
|
||||
endif
|
||||
|
||||
let [pyname, pythonx_errors] = provider#pythonx#Detect(a:version)
|
||||
let [pyname, pythonx_errors] = provider#pythonx#Detect(3)
|
||||
|
||||
if empty(pyname)
|
||||
call health#report_warn('No Python executable found that can `import neovim`. '
|
||||
@ -405,7 +405,7 @@ function! s:check_python(version) abort
|
||||
" can import 'pynvim'. If so, that Python failed to import 'neovim' as
|
||||
" well, which is most probably due to a failed pip upgrade:
|
||||
" https://github.com/neovim/neovim/wiki/Following-HEAD#20181118
|
||||
let [pynvim_exe, errors] = provider#pythonx#DetectByModule('pynvim', a:version)
|
||||
let [pynvim_exe, errors] = provider#pythonx#DetectByModule('pynvim', 3)
|
||||
if !empty(pynvim_exe)
|
||||
call health#report_error(
|
||||
\ 'Detected pip upgrade failure: Python executable can import "pynvim" but '
|
||||
@ -416,14 +416,14 @@ function! s:check_python(version) abort
|
||||
\ . pynvim_exe ." -m pip install neovim # only if needed by third-party software")
|
||||
endif
|
||||
else
|
||||
let [pyversion, current, latest, status] = s:version_info(python_exe)
|
||||
let [majorpyversion, current, latest, status] = s:version_info(python_exe)
|
||||
|
||||
if a:version != str2nr(pyversion)
|
||||
if 3 != str2nr(majorpyversion)
|
||||
call health#report_warn('Unexpected Python version.' .
|
||||
\ ' This could lead to confusing error messages.')
|
||||
endif
|
||||
|
||||
call health#report_info('Python version: ' . pyversion)
|
||||
call health#report_info('Python version: ' . majorpyversion)
|
||||
|
||||
if s:is_bad_response(status)
|
||||
call health#report_info(printf('pynvim version: %s (%s)', current, status))
|
||||
@ -751,8 +751,7 @@ endfunction
|
||||
|
||||
function! health#provider#check() abort
|
||||
call s:check_clipboard()
|
||||
call s:check_python(2)
|
||||
call s:check_python(3)
|
||||
call s:check_python()
|
||||
call s:check_virtualenv()
|
||||
call s:check_ruby()
|
||||
call s:check_node()
|
||||
|
@ -1,45 +0,0 @@
|
||||
" The Python provider uses a Python host to emulate an environment for running
|
||||
" python-vim plugins. :help provider
|
||||
"
|
||||
" Associating the plugin with the Python host is the first step because plugins
|
||||
" will be passed as command-line arguments
|
||||
|
||||
if exists('g:loaded_python_provider')
|
||||
finish
|
||||
endif
|
||||
let [s:prog, s:err] = provider#pythonx#Detect(2)
|
||||
let g:loaded_python_provider = empty(s:prog) ? 1 : 2
|
||||
|
||||
function! provider#python#Prog() abort
|
||||
return s:prog
|
||||
endfunction
|
||||
|
||||
function! provider#python#Error() abort
|
||||
return s:err
|
||||
endfunction
|
||||
|
||||
" The Python provider plugin will run in a separate instance of the Python
|
||||
" host.
|
||||
call remote#host#RegisterClone('legacy-python-provider', 'python')
|
||||
call remote#host#RegisterPlugin('legacy-python-provider', 'script_host.py', [])
|
||||
|
||||
function! provider#python#Call(method, args) abort
|
||||
if s:err != ''
|
||||
return
|
||||
endif
|
||||
if !exists('s:host')
|
||||
let s:rpcrequest = function('rpcrequest')
|
||||
|
||||
" Ensure that we can load the Python host before bootstrapping
|
||||
try
|
||||
let s:host = remote#host#Require('legacy-python-provider')
|
||||
catch
|
||||
let s:err = v:exception
|
||||
echohl WarningMsg
|
||||
echomsg v:exception
|
||||
echohl None
|
||||
return
|
||||
endtry
|
||||
endif
|
||||
return call(s:rpcrequest, insert(insert(a:args, 'python_'.a:method), s:host))
|
||||
endfunction
|
@ -6,10 +6,8 @@ endif
|
||||
let s:loaded_pythonx_provider = 1
|
||||
|
||||
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 prog = provider#python3#Prog()
|
||||
let args = [prog, '-c', 'import sys; sys.path = list(filter(lambda x: x != "", sys.path)); import neovim; neovim.start_host()']
|
||||
|
||||
|
||||
@ -23,14 +21,12 @@ function! provider#pythonx#Require(host) abort
|
||||
endfunction
|
||||
|
||||
function! s:get_python_executable_from_host_var(major_version) abort
|
||||
return expand(get(g:, 'python'.(a:major_version == 3 ? '3' : '').'_host_prog', ''), v:true)
|
||||
return expand(get(g:, 'python'.(a:major_version == 3 ? '3' : execute("throw 'unsupported'")).'_host_prog', ''), v:true)
|
||||
endfunction
|
||||
|
||||
function! s:get_python_candidates(major_version) abort
|
||||
return {
|
||||
\ 2: ['python2', 'python2.7', 'python2.6', 'python'],
|
||||
\ 3: ['python3', 'python3.10', 'python3.9', 'python3.8', 'python3.7',
|
||||
\ 'python3.6', 'python']
|
||||
\ 3: ['python3', 'python3.10', 'python3.9', 'python3.8', 'python3.7', 'python']
|
||||
\ }[a:major_version]
|
||||
endfunction
|
||||
|
||||
@ -82,7 +78,7 @@ function! provider#pythonx#CheckForModule(prog, module, major_version) abort
|
||||
return [0, a:prog . ' not found in search path or not executable.']
|
||||
endif
|
||||
|
||||
let min_version = (a:major_version == 2) ? '2.6' : '3.3'
|
||||
let min_version = '3.7'
|
||||
|
||||
" Try to load module, and output Python version.
|
||||
" Exit codes:
|
||||
|
@ -5806,7 +5806,6 @@ has({feature}) Returns 1 if {feature} is supported, 0 otherwise. The
|
||||
this is not present).
|
||||
mac MacOS system.
|
||||
nvim This is Nvim.
|
||||
python2 Legacy Vim |python2| interface. |has-python|
|
||||
python3 Legacy Vim |python3| interface. |has-python|
|
||||
pythonx Legacy Vim |python_x| interface. |has-pythonx|
|
||||
ttyin input is a terminal (tty)
|
||||
|
@ -1,10 +1,10 @@
|
||||
*if_pyth.txt* Nvim
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Paul Moore
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
|
||||
The Python Interface to Vim *if_pyth* *python* *Python*
|
||||
The Python Interface to NVim *if_pyth* *python* *Python*
|
||||
|
||||
See |provider-python| for more information.
|
||||
|
||||
@ -134,7 +134,7 @@ Instead, put the Python command in a function and call that function:
|
||||
Note that "EOF" must be at the start of the line.
|
||||
|
||||
==============================================================================
|
||||
The vim module *python-vim* *python2*
|
||||
The vim module *python-vim*
|
||||
|
||||
Python code gets all of its access to vim (with one exception - see
|
||||
|python-output| below) via the "vim" module. The vim module implements two
|
||||
@ -322,14 +322,13 @@ Output from Python *python-output*
|
||||
supported, and may cause the program to crash. This should probably be
|
||||
fixed.
|
||||
|
||||
*python2-directory* *python3-directory* *pythonx-directory*
|
||||
*python3-directory* *pythonx-directory*
|
||||
Python 'runtimepath' handling *python-special-path*
|
||||
|
||||
In python vim.VIM_SPECIAL_PATH special directory is used as a replacement for
|
||||
the list of paths found in 'runtimepath': with this directory in sys.path and
|
||||
vim.path_hooks in sys.path_hooks python will try to load module from
|
||||
{rtp}/python2 (or python3) and {rtp}/pythonx (for both python versions) for
|
||||
each {rtp} found in 'runtimepath'.
|
||||
{rtp}/python3 and {rtp}/pythonx for each {rtp} found in 'runtimepath'.
|
||||
|
||||
Implementation is similar to the following, but written in C: >
|
||||
|
||||
@ -401,8 +400,8 @@ vim._get_paths *python-_get_paths*
|
||||
hook. You should not rely on this method being present in future
|
||||
versions, but can use it for debugging.
|
||||
|
||||
It returns a list of {rtp}/python2 (or {rtp}/python3) and
|
||||
{rtp}/pythonx directories for each {rtp} in 'runtimepath'.
|
||||
It returns a list of {rtp}/python3 and {rtp}/pythonx
|
||||
directories for each {rtp} in 'runtimepath'.
|
||||
|
||||
==============================================================================
|
||||
Buffer objects *python-buffer*
|
||||
@ -590,6 +589,11 @@ functions to evaluate Python expressions and pass their values to Vim script.
|
||||
==============================================================================
|
||||
Python 3 *python3*
|
||||
|
||||
As Python 3 is the only supported version in Nvim, "python" is synonymous
|
||||
with "python3" in the current version. However, code that aims to support older
|
||||
versions of Neovim, as well as Vim, should prefer to use "python3"
|
||||
variants explicitly if Python 3 is required.
|
||||
|
||||
*:py3* *:python3*
|
||||
:[range]py3 {stmt}
|
||||
:[range]py3 << [endmarker]
|
||||
@ -619,31 +623,26 @@ Raising SystemExit exception in python isn't endorsed way to quit vim, use: >
|
||||
:py vim.command("qall!")
|
||||
<
|
||||
*has-python*
|
||||
You can test what Python version is available with: >
|
||||
if has('python')
|
||||
echo 'there is Python 2.x'
|
||||
You can test if Python is available with: >
|
||||
if has('pythonx')
|
||||
echo 'there is Python'
|
||||
endif
|
||||
if has('python3')
|
||||
echo 'there is Python 3.x'
|
||||
endif
|
||||
|
||||
Python 2 is no longer supported. Thus `has('python')` always returns
|
||||
zero for backwards compatibility reasons.
|
||||
|
||||
==============================================================================
|
||||
Python X *python_x* *pythonx*
|
||||
|
||||
Because most python code can be written so that it works with Python 2.6+ and
|
||||
Python 3, the pyx* functions and commands have been written. They work the
|
||||
same as the Python 2 and 3 variants, but select the Python version using the
|
||||
'pyxversion' setting.
|
||||
|
||||
Set 'pyxversion' in your |vimrc| to prefer Python 2 or Python 3 for Python
|
||||
commands. Changing this setting at runtime risks losing the state of plugins
|
||||
(such as initialization).
|
||||
|
||||
If you want to use a module, you can put it in the {rtp}/pythonx directory.
|
||||
See |pythonx-directory|.
|
||||
The "pythonx" and "pyx" prefixes were introduced for python code which
|
||||
works with Python 2.6+ and Python 3. As Nvim only supports Python 3,
|
||||
all these commands are now synonymous to their "python3" equivalents.
|
||||
|
||||
*:pyx* *:pythonx*
|
||||
`:pyx` and `:pythonx` work similar to `:python`. To check if `:pyx` works: >
|
||||
`:pyx` and `:pythonx` work the same as `:python3`. To check if `:pyx` works: >
|
||||
:pyx print("Hello")
|
||||
|
||||
To see what version of Python is being used: >
|
||||
@ -651,34 +650,16 @@ To see what version of Python is being used: >
|
||||
:pyx print(sys.version)
|
||||
<
|
||||
*:pyxfile* *python_x-special-comments*
|
||||
`:pyxfile` works similar to `:pyfile`. But you can add a "shebang" comment to
|
||||
force Vim to use `:pyfile` or `:py3file`: >
|
||||
#!/any string/python2 " Shebang. Must be the first line of the file.
|
||||
#!/any string/python3 " Shebang. Must be the first line of the file.
|
||||
# requires python 2.x " Maximum lines depend on 'modelines'.
|
||||
# requires python 3.x " Maximum lines depend on 'modelines'.
|
||||
Unlike normal modelines, the bottom of the file is not checked.
|
||||
If none of them are found, the 'pyxversion' option is used.
|
||||
*W20* *W21*
|
||||
If Vim does not support the selected Python version a silent message will be
|
||||
printed. Use `:messages` to read them.
|
||||
`:pyxfile` works the same as `:py3file`.
|
||||
|
||||
*:pyxdo*
|
||||
`:pyxdo` works similar to `:pydo`.
|
||||
`:pyxdo` works the same as `:py3do`.
|
||||
|
||||
*has-pythonx*
|
||||
To check if pyx* functions and commands are available: >
|
||||
To check if `pyx*` functions and commands are available: >
|
||||
if has('pythonx')
|
||||
echo 'pyx* commands are available. (Python ' . &pyx . ')'
|
||||
endif
|
||||
|
||||
If you prefer Python 2 and want to fallback to Python 3, set 'pyxversion'
|
||||
explicitly in your |.vimrc|. Example: >
|
||||
if has('python')
|
||||
set pyx=2
|
||||
elseif has('python3')
|
||||
set pyx=3
|
||||
endif
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@ -4637,26 +4637,11 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
nudged to fit on the screen.
|
||||
|
||||
*'pyxversion'* *'pyx'*
|
||||
'pyxversion' 'pyx' number (default depends on the build)
|
||||
'pyxversion' 'pyx' number (default 3)
|
||||
global
|
||||
Specifies the python version used for pyx* functions and commands
|
||||
|python_x|. The default value is as follows:
|
||||
|
||||
|provider| installed Default ~
|
||||
|+python| and |+python3| 0
|
||||
only |+python| 2
|
||||
only |+python3| 3
|
||||
|
||||
Available values are 0, 2 and 3.
|
||||
If 'pyxversion' is 0, it is set to 2 or 3 after the first execution of
|
||||
any python2/3 commands or functions. E.g. `:py` sets to 2, and `:py3`
|
||||
sets to 3. `:pyx` sets it to 3 if Python 3 is available, otherwise sets
|
||||
to 2 if Python 2 is available.
|
||||
See also: |has-pythonx|
|
||||
|
||||
If only |+python| or |+python3| are available,
|
||||
'pyxversion' has no effect. The pyx* functions and commands are
|
||||
always the same as the installed version.
|
||||
|python_x|. As only Python 3 is supported, this always has the value
|
||||
`3`. Setting any other value is an error.
|
||||
|
||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||
security reasons.
|
||||
|
@ -20,11 +20,12 @@ Run the |:checkhealth| command, and review the sections below.
|
||||
==============================================================================
|
||||
Python integration *provider-python*
|
||||
|
||||
Nvim supports Python |remote-plugin|s and the Vim legacy |python2| and
|
||||
|python3| interfaces (which are implemented as remote-plugins).
|
||||
Nvim supports Python |remote-plugin|s and the Vim legacy |python3| and
|
||||
|pythonx| interfaces (which are implemented as remote-plugins).
|
||||
|
||||
Note: Only the Vim 7.3 legacy interface is supported, not later features such
|
||||
as |python-bindeval| (Vim 7.4); use the Nvim API instead.
|
||||
as |python-bindeval| (Vim 7.4); use the Nvim API instead. Python 2 is not
|
||||
supported.
|
||||
|
||||
|
||||
PYTHON QUICKSTART ~
|
||||
@ -38,11 +39,6 @@ For Python 3 plugins:
|
||||
2. Install the module (try "python" if "python3" is missing): >
|
||||
python3 -m pip install --user --upgrade pynvim
|
||||
|
||||
For Python 2 plugins:
|
||||
1. Make sure Python 2.7 is available in your $PATH.
|
||||
2. Install the module (try "python" if "python2" is missing): >
|
||||
python2 -m pip install --user --upgrade pynvim
|
||||
|
||||
The pip `--upgrade` flag ensures that you get the latest version even if
|
||||
a previous version was already installed.
|
||||
|
||||
@ -56,21 +52,11 @@ If you run into problems, uninstall _both_ then install "pynvim" again: >
|
||||
|
||||
|
||||
PYTHON PROVIDER CONFIGURATION ~
|
||||
*g:python_host_prog*
|
||||
Command to start Python 2 (executable, not directory). Setting this makes
|
||||
startup faster. Useful for working with virtualenvs. Must be set before any
|
||||
check for has("python2"). >
|
||||
let g:python_host_prog = '/path/to/python'
|
||||
<
|
||||
*g:python3_host_prog*
|
||||
Command to start Python 3 (executable, not directory). Setting this makes
|
||||
startup faster. Useful for working with virtualenvs. Must be set before any
|
||||
check for has("python3"). >
|
||||
let g:python3_host_prog = '/path/to/python3'
|
||||
<
|
||||
*g:loaded_python_provider*
|
||||
To disable Python 2 support: >
|
||||
let g:loaded_python_provider = 0
|
||||
<
|
||||
*g:loaded_python3_provider*
|
||||
To disable Python 3 support: >
|
||||
@ -81,8 +67,8 @@ PYTHON VIRTUALENVS ~
|
||||
*python-virtualenv*
|
||||
If you plan to use per-project virtualenvs often, you should assign one
|
||||
virtualenv for Neovim and hard-code the interpreter path via
|
||||
|g:python3_host_prog| (or |g:python_host_prog|) so that the "pynvim" package
|
||||
is not required for each virtualenv.
|
||||
|g:python3_host_prog| so that the "pynvim" package is not required
|
||||
for each virtualenv.
|
||||
|
||||
Example using pyenv: >
|
||||
pyenv install 3.4.4
|
||||
|
@ -1446,7 +1446,7 @@ error message (line numbers are not part of the actual output):
|
||||
4 Traceback (most recent call last):
|
||||
5 File "unittests/dbfacadeTest.py", line 89, in testFoo
|
||||
6 self.assertEquals(34, dtid)
|
||||
7 File "/usr/lib/python2.2/unittest.py", line 286, in
|
||||
7 File "/usr/lib/python3.8/unittest.py", line 286, in
|
||||
8 failUnlessEqual
|
||||
9 raise self.failureException, \
|
||||
10 AssertionError: 34 != 33
|
||||
|
@ -270,8 +270,8 @@ return {
|
||||
pum_getpos={},
|
||||
pumvisible={},
|
||||
py3eval={args=1, base=1},
|
||||
pyeval={args=1, base=1},
|
||||
pyxeval={args=1, base=1},
|
||||
pyeval={args=1, base=1, func="f_py3eval"},
|
||||
pyxeval={args=1, base=1, func="f_py3eval"},
|
||||
perleval={args=1, base=1},
|
||||
range={args={1, 3}, base=1},
|
||||
readdir={args={1, 2}, base=1},
|
||||
|
@ -6982,36 +6982,13 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "pyeval()" function
|
||||
*/
|
||||
static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
script_host_eval("python", argvars, rettv);
|
||||
}
|
||||
|
||||
/*
|
||||
* "py3eval()" function
|
||||
*/
|
||||
/// "py3eval()" and "pyxeval()" functions (always python3)
|
||||
static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
script_host_eval("python3", argvars, rettv);
|
||||
}
|
||||
|
||||
// "pyxeval()" function
|
||||
static void f_pyxeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
init_pyxversion();
|
||||
if (p_pyx == 2) {
|
||||
f_pyeval(argvars, rettv, NULL);
|
||||
} else {
|
||||
f_py3eval(argvars, rettv, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// "perleval()" function
|
||||
///
|
||||
static void f_perleval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
script_host_eval("perl", argvars, rettv);
|
||||
|
@ -2097,19 +2097,19 @@ module.cmds = {
|
||||
command='python',
|
||||
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
|
||||
addr_type='ADDR_LINES',
|
||||
func='ex_python',
|
||||
func='ex_python3',
|
||||
},
|
||||
{
|
||||
command='pydo',
|
||||
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
|
||||
addr_type='ADDR_LINES',
|
||||
func='ex_pydo',
|
||||
func='ex_pydo3',
|
||||
},
|
||||
{
|
||||
command='pyfile',
|
||||
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
|
||||
addr_type='ADDR_LINES',
|
||||
func='ex_pyfile',
|
||||
func='ex_py3file',
|
||||
},
|
||||
{
|
||||
command='py3',
|
||||
@ -2139,25 +2139,25 @@ module.cmds = {
|
||||
command='pyx',
|
||||
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
|
||||
addr_type='ADDR_LINES',
|
||||
func='ex_pyx',
|
||||
func='ex_python3',
|
||||
},
|
||||
{
|
||||
command='pyxdo',
|
||||
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
|
||||
addr_type='ADDR_LINES',
|
||||
func='ex_pyxdo',
|
||||
func='ex_pydo3',
|
||||
},
|
||||
{
|
||||
command='pythonx',
|
||||
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
|
||||
addr_type='ADDR_LINES',
|
||||
func='ex_pyx',
|
||||
func='ex_python3',
|
||||
},
|
||||
{
|
||||
command='pyxfile',
|
||||
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
|
||||
addr_type='ADDR_LINES',
|
||||
func='ex_pyxfile',
|
||||
func='ex_py3file',
|
||||
},
|
||||
{
|
||||
command='quit',
|
||||
|
@ -135,21 +135,6 @@ void ex_profile(exarg_T *eap)
|
||||
}
|
||||
}
|
||||
|
||||
void ex_python(exarg_T *eap)
|
||||
{
|
||||
script_host_execute("python", eap);
|
||||
}
|
||||
|
||||
void ex_pyfile(exarg_T *eap)
|
||||
{
|
||||
script_host_execute_file("python", eap);
|
||||
}
|
||||
|
||||
void ex_pydo(exarg_T *eap)
|
||||
{
|
||||
script_host_do_range("python", eap);
|
||||
}
|
||||
|
||||
void ex_ruby(exarg_T *eap)
|
||||
{
|
||||
script_host_execute("ruby", eap);
|
||||
@ -1660,126 +1645,6 @@ void ex_options(exarg_T *eap)
|
||||
cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
|
||||
}
|
||||
|
||||
// Detect Python 3 or 2, and initialize 'pyxversion'.
|
||||
void init_pyxversion(void)
|
||||
{
|
||||
if (p_pyx == 0) {
|
||||
if (eval_has_provider("python3")) {
|
||||
p_pyx = 3;
|
||||
} else if (eval_has_provider("python")) {
|
||||
p_pyx = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Does a file contain one of the following strings at the beginning of any
|
||||
// line?
|
||||
// "#!(any string)python2" => returns 2
|
||||
// "#!(any string)python3" => returns 3
|
||||
// "# requires python 2.x" => returns 2
|
||||
// "# requires python 3.x" => returns 3
|
||||
// otherwise return 0.
|
||||
static int requires_py_version(char_u *filename)
|
||||
{
|
||||
FILE *file;
|
||||
int requires_py_version = 0;
|
||||
int i, lines;
|
||||
|
||||
lines = (int)p_mls;
|
||||
if (lines < 0) {
|
||||
lines = 5;
|
||||
}
|
||||
|
||||
file = os_fopen((char *)filename, "r");
|
||||
if (file != NULL) {
|
||||
for (i = 0; i < lines; i++) {
|
||||
if (vim_fgets(IObuff, IOSIZE, file)) {
|
||||
break;
|
||||
}
|
||||
if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!') {
|
||||
// Check shebang.
|
||||
if (strstr((char *)IObuff + 2, "python2") != NULL) {
|
||||
requires_py_version = 2;
|
||||
break;
|
||||
}
|
||||
if (strstr((char *)IObuff + 2, "python3") != NULL) {
|
||||
requires_py_version = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
IObuff[21] = '\0';
|
||||
if (STRCMP("# requires python 2.x", IObuff) == 0) {
|
||||
requires_py_version = 2;
|
||||
break;
|
||||
}
|
||||
if (STRCMP("# requires python 3.x", IObuff) == 0) {
|
||||
requires_py_version = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
return requires_py_version;
|
||||
}
|
||||
|
||||
|
||||
// Source a python file using the requested python version.
|
||||
static void source_pyx_file(exarg_T *eap, char_u *fname)
|
||||
{
|
||||
exarg_T ex;
|
||||
long int v = requires_py_version(fname);
|
||||
|
||||
init_pyxversion();
|
||||
if (v == 0) {
|
||||
// user didn't choose a preference, 'pyx' is used
|
||||
v = p_pyx;
|
||||
}
|
||||
|
||||
// now source, if required python version is not supported show
|
||||
// unobtrusive message.
|
||||
if (eap == NULL) {
|
||||
memset(&ex, 0, sizeof(ex));
|
||||
} else {
|
||||
ex = *eap;
|
||||
}
|
||||
ex.arg = fname;
|
||||
ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3");
|
||||
|
||||
if (v == 2) {
|
||||
ex_pyfile(&ex);
|
||||
} else {
|
||||
ex_py3file(&ex);
|
||||
}
|
||||
}
|
||||
|
||||
// ":pyxfile {fname}"
|
||||
void ex_pyxfile(exarg_T *eap)
|
||||
{
|
||||
source_pyx_file(eap, eap->arg);
|
||||
}
|
||||
|
||||
// ":pyx"
|
||||
void ex_pyx(exarg_T *eap)
|
||||
{
|
||||
init_pyxversion();
|
||||
if (p_pyx == 2) {
|
||||
ex_python(eap);
|
||||
} else {
|
||||
ex_python3(eap);
|
||||
}
|
||||
}
|
||||
|
||||
// ":pyxdo"
|
||||
void ex_pyxdo(exarg_T *eap)
|
||||
{
|
||||
init_pyxversion();
|
||||
if (p_pyx == 2) {
|
||||
ex_pydo(eap);
|
||||
} else {
|
||||
ex_pydo3(eap);
|
||||
}
|
||||
}
|
||||
|
||||
/// ":source [{fname}]"
|
||||
void ex_source(exarg_T *eap)
|
||||
{
|
||||
|
@ -4349,6 +4349,12 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
|
||||
} else if (value > 10000) {
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
} else if (pp == &p_pyx) {
|
||||
if (value == 0) {
|
||||
value = 3;
|
||||
} else if (value != 3) {
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
} else if (pp == &p_re) {
|
||||
if (value < 0 || value > 2) {
|
||||
errmsg = e_invarg;
|
||||
@ -4523,10 +4529,6 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
|
||||
if (pum_drawn()) {
|
||||
pum_redraw();
|
||||
}
|
||||
} else if (pp == &p_pyx) {
|
||||
if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3) {
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
} else if (pp == &p_ul || pp == &curbuf->b_p_ul) {
|
||||
// sync undo before 'undolevels' changes
|
||||
// use the old value, otherwise u_sync() may not work properly
|
||||
|
@ -1846,7 +1846,7 @@ return {
|
||||
type='number', scope={'global'},
|
||||
secure=true,
|
||||
varname='p_pyx',
|
||||
defaults={if_true=0}
|
||||
defaults={if_true=3}
|
||||
},
|
||||
{
|
||||
full_name='quickfixtextfunc', abbreviation='qftf',
|
||||
|
@ -69,6 +69,7 @@ func Test_vim_function()
|
||||
endfunc
|
||||
|
||||
func Test_skipped_python3_command_does_not_affect_pyxversion()
|
||||
throw 'skipped: Nvim hardcodes pyxversion=3'
|
||||
set pyxversion=0
|
||||
if 0
|
||||
python3 import vim
|
||||
|
@ -1,9 +1,9 @@
|
||||
" Test for pyx* commands and functions with Python 2.
|
||||
|
||||
set pyx=2
|
||||
if !has('python')
|
||||
finish
|
||||
endif
|
||||
set pyx=2
|
||||
|
||||
let s:py2pattern = '^2\.[0-7]\.\d\+'
|
||||
let s:py3pattern = '^3\.\d\+\.\d\+'
|
||||
|
@ -62,10 +62,10 @@ describe('script_get-based command', function()
|
||||
|
||||
-- Provider-based scripts
|
||||
test_garbage_exec('ruby', not missing_provider('ruby'))
|
||||
test_garbage_exec('python', not missing_provider('python'))
|
||||
test_garbage_exec('python3', not missing_provider('python3'))
|
||||
|
||||
-- Missing scripts
|
||||
test_garbage_exec('python', false)
|
||||
test_garbage_exec('tcl', false)
|
||||
test_garbage_exec('mzscheme', false)
|
||||
test_garbage_exec('perl', false)
|
||||
|
@ -8,6 +8,7 @@ local source = helpers.source
|
||||
local missing_provider = helpers.missing_provider
|
||||
local matches = helpers.matches
|
||||
local pcall_err = helpers.pcall_err
|
||||
local funcs = helpers.funcs
|
||||
|
||||
do
|
||||
clear()
|
||||
@ -93,16 +94,40 @@ describe('python3 provider', function()
|
||||
ghi]])
|
||||
end)
|
||||
|
||||
it('py3eval', function()
|
||||
eq({1, 2, {['key'] = 'val'}}, eval([[py3eval('[1, 2, {"key": "val"}]')]]))
|
||||
describe('py3eval()', function()
|
||||
it('works', function()
|
||||
eq({1, 2, {['key'] = 'val'}}, funcs.py3eval('[1, 2, {"key": "val"}]'))
|
||||
end)
|
||||
|
||||
it('errors out when given non-string', function()
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(10)'))
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:_null_dict)'))
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:_null_list)'))
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(0.0)'))
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(function("tr"))'))
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:true)'))
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:false)'))
|
||||
eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:null)'))
|
||||
end)
|
||||
|
||||
it('accepts NULL string', function()
|
||||
matches('.*SyntaxError.*', pcall_err(eval, 'py3eval($XXX_NONEXISTENT_VAR_XXX)'))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('pyxeval #10758', function()
|
||||
eq(0, eval([[&pyxversion]]))
|
||||
eq(3, eval([[&pyxversion]]))
|
||||
eq(3, eval([[pyxeval('sys.version_info[:3][0]')]]))
|
||||
eq(3, eval([[&pyxversion]]))
|
||||
end)
|
||||
|
||||
it("setting 'pyxversion'", function()
|
||||
command 'set pyxversion=3' -- no error
|
||||
eq('Vim(set):E474: Invalid argument: pyxversion=2', pcall_err(command, 'set pyxversion=2'))
|
||||
command 'set pyxversion=0' -- allowed, but equivalent to pyxversion=3
|
||||
eq(3, eval'&pyxversion')
|
||||
end)
|
||||
|
||||
it('RPC call to expand("<afile>") during BufDelete #5245 #5617', function()
|
||||
helpers.add_builddir_to_rtp()
|
||||
source([=[
|
||||
@ -120,3 +145,15 @@ describe('python3 provider', function()
|
||||
assert_alive()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('python2 feature test', function()
|
||||
-- python2 is not supported, so correct behaviour is to return 0
|
||||
it('works', function()
|
||||
eq(0, funcs.has('python2'))
|
||||
eq(0, funcs.has('python'))
|
||||
eq(0, funcs.has('python_compiled'))
|
||||
eq(0, funcs.has('python_dynamic'))
|
||||
eq(0, funcs.has('python_dynamic_'))
|
||||
eq(0, funcs.has('python_'))
|
||||
end)
|
||||
end)
|
||||
|
@ -1,123 +0,0 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local neq = helpers.neq
|
||||
local feed = helpers.feed
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local meths = helpers.meths
|
||||
local insert = helpers.insert
|
||||
local expect = helpers.expect
|
||||
local command = helpers.command
|
||||
local exc_exec = helpers.exc_exec
|
||||
local write_file = helpers.write_file
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
local missing_provider = helpers.missing_provider
|
||||
local matches = helpers.matches
|
||||
local pcall_err = helpers.pcall_err
|
||||
|
||||
do
|
||||
clear()
|
||||
local reason = missing_provider('python')
|
||||
if reason then
|
||||
it(':python reports E319 if provider is missing', function()
|
||||
local expected = [[Vim%(py.*%):E319: No "python" provider found.*]]
|
||||
matches(expected, pcall_err(command, 'py print("foo")'))
|
||||
matches(expected, pcall_err(command, 'pyfile foo'))
|
||||
end)
|
||||
pending(string.format('Python 2 (or the pynvim module) is broken/missing (%s)', reason), function() end)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
command('python import vim')
|
||||
end)
|
||||
|
||||
describe('python feature test', function()
|
||||
it('works', function()
|
||||
eq(1, funcs.has('python'))
|
||||
eq(1, funcs.has('python_compiled'))
|
||||
eq(1, funcs.has('python_dynamic'))
|
||||
eq(0, funcs.has('python_dynamic_'))
|
||||
eq(0, funcs.has('python_'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe(':python command', function()
|
||||
it('works with a line', function()
|
||||
command('python vim.vars["set_by_python"] = [100, 0]')
|
||||
eq({100, 0}, meths.get_var('set_by_python'))
|
||||
end)
|
||||
|
||||
-- TODO(ZyX-I): works with << EOF
|
||||
-- TODO(ZyX-I): works with execute 'python' line1."\n".line2."\n"…
|
||||
|
||||
it('supports nesting', function()
|
||||
command([[python vim.command('python vim.command("python vim.command(\'let set_by_nested_python = 555\')")')]])
|
||||
eq(555, meths.get_var('set_by_nested_python'))
|
||||
end)
|
||||
|
||||
it('supports range', function()
|
||||
insert([[
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
line4]])
|
||||
feed('ggjvj:python vim.vars["range"] = vim.current.range[:]<CR>')
|
||||
eq({'line2', 'line3'}, meths.get_var('range'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe(':pyfile command', function()
|
||||
it('works', function()
|
||||
local fname = 'pyfile.py'
|
||||
write_file(fname, 'vim.command("let set_by_pyfile = 123")')
|
||||
command('pyfile pyfile.py')
|
||||
eq(123, meths.get_var('set_by_pyfile'))
|
||||
os.remove(fname)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe(':pydo command', function()
|
||||
it('works', function()
|
||||
-- :pydo 42 returns None for all lines,
|
||||
-- the buffer should not be changed
|
||||
command('normal :pydo 42')
|
||||
eq(false, curbufmeths.get_option('modified'))
|
||||
-- insert some text
|
||||
insert('abc\ndef\nghi')
|
||||
expect([[
|
||||
abc
|
||||
def
|
||||
ghi]])
|
||||
-- go to top and select and replace the first two lines
|
||||
feed('ggvj:pydo return str(linenr)<CR>')
|
||||
expect([[
|
||||
1
|
||||
2
|
||||
ghi]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('pyeval()', function()
|
||||
it('works', function()
|
||||
eq({1, 2, {['key'] = 'val'}}, funcs.pyeval('[1, 2, {"key": "val"}]'))
|
||||
end)
|
||||
|
||||
it('errors out when given non-string', function()
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(10)'))
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_dict)'))
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_list)'))
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(0.0)'))
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(function("tr"))'))
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:true)'))
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:false)'))
|
||||
eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:null)'))
|
||||
end)
|
||||
|
||||
it('accepts NULL string', function()
|
||||
neq(0, exc_exec('call pyeval($XXX_NONEXISTENT_VAR_XXX)'))
|
||||
end)
|
||||
end)
|
Loading…
Reference in New Issue
Block a user