Skip to content

Commit f42dd3c

Browse files
committed
patch 8.0.0251: not easy to select Python 2 or 3
Problem: It is not so easy to write a script that works with both Python 2 and Python 3, even when the Python code works with both. Solution: Add 'pyxversion', :pyx, etc. (Marc Weber, Ken Takata)
1 parent 0c0590d commit f42dd3c

27 files changed

Lines changed: 602 additions & 11 deletions

Filelist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ SRC_ALL = \
122122
src/testdir/pythonx/topmodule/submodule/subsubmodule/subsubsubmodule.py \
123123
src/testdir/python_after/*.py \
124124
src/testdir/python_before/*.py \
125+
src/testdir/pyxfile/*.py \
125126
src/testdir/bench*.in \
126127
src/testdir/bench*.vim \
127128
src/testdir/samples/*.txt \

runtime/doc/eval.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,6 +2239,7 @@ printf({fmt}, {expr1}...) String format text
22392239
pumvisible() Number whether popup menu is visible
22402240
pyeval({expr}) any evaluate |Python| expression
22412241
py3eval({expr}) any evaluate |python3| expression
2242+
pyxeval({expr}) any evaluate |python_x| expression
22422243
range({expr} [, {max} [, {stride}]])
22432244
List items from {expr} to {max}
22442245
readfile({fname} [, {binary} [, {max}]])
@@ -6163,6 +6164,14 @@ pyeval({expr}) *pyeval()*
61636164
non-string keys result in error.
61646165
{only available when compiled with the |+python| feature}
61656166

6167+
pyxeval({expr}) *pyxeval()*
6168+
Evaluate Python expression {expr} and return its result
6169+
converted to Vim data structures.
6170+
Uses Python 2 or 3, see |python_x| and 'pyxversion'.
6171+
See also: |pyeval()|, |py3eval()|
6172+
{only available when compiled with the |+python| or the
6173+
|+python3| feature}
6174+
61666175
*E726* *E727*
61676176
range({expr} [, {max} [, {stride}]]) *range()*
61686177
Returns a |List| with Numbers:
@@ -8402,6 +8411,7 @@ printer Compiled with |:hardcopy| support.
84028411
profile Compiled with |:profile| support.
84038412
python Compiled with Python 2.x interface. |has-python|
84048413
python3 Compiled with Python 3.x interface. |has-python|
8414+
pythonx Compiled with |python_x| interface. |has-pythonx|
84058415
qnx QNX version of Vim.
84068416
quickfix Compiled with |quickfix| support.
84078417
reltime Compiled with |reltime()| support.

runtime/doc/if_pyth.txt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The Python Interface to Vim *python* *Python*
1616
8. pyeval(), py3eval() Vim functions |python-pyeval|
1717
9. Dynamic loading |python-dynamic|
1818
10. Python 3 |python3|
19+
11. Python X |python_x|
1920

2021
{Vi does not have any of these commands}
2122

@@ -711,6 +712,7 @@ vim.Function object *python-Function*
711712

712713
To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()|
713714
functions to evaluate Python expressions and pass their values to VimL.
715+
|pyxeval()| is also available.
714716

715717
==============================================================================
716718
9. Dynamic loading *python-dynamic*
@@ -811,5 +813,69 @@ dynamically, these has() calls will try to load them. If only one can be
811813
loaded at a time, just checking if Python 2 or 3 are available will prevent
812814
the other one from being available.
813815

816+
==============================================================================
817+
11. Python X *python_x* *pythonx*
818+
819+
Because most python code can be written so that it works with python 2.6+ and
820+
python 3 the pyx* functions and commands have been writen. They work exactly
821+
the same as the Python 2 and 3 variants, but select the Python version using
822+
the 'pyxversion' setting.
823+
824+
You should set 'pyxversion' in your |.vimrc| to prefer Python 2 or Python 3
825+
for Python commands. If you change this setting at runtime you may risk that
826+
state of plugins (such as initialization) may be lost.
827+
828+
If you want to use a module, you can put it in the {rtp}/pythonx directory.
829+
See |pythonx-directory|.
830+
831+
*:pyx* *:pythonx*
832+
The `:pyx` and `:pythonx` commands work similar to `:python`. A simple check
833+
if the `:pyx` command is working: >
834+
:pyx print("Hello")
835+
836+
To see what version of Python is being used: >
837+
:pyx import sys
838+
:pyx print(sys.version)
839+
<
840+
*:pyxfile* *python_x-special-comments*
841+
The `:pyxfile` command works similar to `:pyfile`. However you can add one of
842+
these comments to force Vim using `:pyfile` or `:py3file`: >
843+
#!/any string/python2 " Shebang. Must be the first line of the file.
844+
#!/any string/python3 " Shebang. Must be the first line of the file.
845+
# requires python 2.x " Maximum lines depend on 'modelines'.
846+
# requires python 3.x " Maximum lines depend on 'modelines'.
847+
Unlike normal modelines, the bottom of the file is not checked.
848+
If none of them are found, the 'pyxversion' setting is used.
849+
*W20* *W21*
850+
If Vim does not support the selected Python version a silent message will be
851+
printed. Use `:messages` to read them.
852+
853+
*:pyxdo*
854+
The `:pyxdo` command works similar to `:pydo`.
855+
856+
*has-pythonx*
857+
You can test if pyx* commands are available with: >
858+
if has('pythonx')
859+
echo 'pyx* commands are available. (Python ' . &pyx . ')'
860+
endif
861+
862+
When compiled with only one of |+python| or |+python3|, the has() returns 1.
863+
When compiled with both |+python| and |+python3|, the test depends on the
864+
'pyxversion' setting. If 'pyxversion' is 0, it tests Python 3 first, and if
865+
it is not available then Python 2. If 'pyxversion' is 2 or 3, it tests only
866+
Python 2 or 3 respectively.
867+
868+
Note that for has('pythonx') to work it may try to dynamically load Python 3
869+
or 2. This may have side effects, especially when Vim can only load one of
870+
the two.
871+
872+
If a user prefers Python 2 and want to fallback to Python 3, he needs to set
873+
'pyxversion' explicitly in his |.vimrc|. E.g.: >
874+
if has('python')
875+
set pyx=2
876+
elseif has('python3')
877+
set pyx=3
878+
endif
879+
814880
==============================================================================
815881
vim:tw=78:ts=8:ft=help:norl:

runtime/doc/index.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,10 @@ tag command action ~
14401440
|:python| :py[thon] execute Python command
14411441
|:pydo| :pyd[o] execute Python command for each line
14421442
|:pyfile| :pyf[ile] execute Python script file
1443+
|:pyx| :pyx execute |python_x| command
1444+
|:pythonx| :pythonx same as :pyx
1445+
|:pyxdo| :pyxd[o] execute |python_x| command for each line
1446+
|:pyxfile| :pyxf[ile] execute |python_x| script file
14431447
|:quit| :q[uit] quit current window (when one window quit Vim)
14441448
|:quitall| :quita[ll] quit Vim
14451449
|:qall| :qa[ll] quit Vim

runtime/doc/options.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5786,6 +5786,34 @@ A jump table for the options with a short description can be found at |Q_op|.
57865786
Specifies the name of the Python 3 shared library. The default is
57875787
DYNAMIC_PYTHON3_DLL, which was specified at compile time.
57885788
Environment variables are expanded |:set_env|.
5789+
This option cannot be set from a |modeline| or in the |sandbox|, for
5790+
security reasons.
5791+
5792+
*'pyxversion'* *'pyx'*
5793+
'pyxversion' 'pyx' number (default depends on the build)
5794+
global
5795+
{not in Vi}
5796+
{only available when compiled with the |+python| or
5797+
the |+python3| feature}
5798+
Specifies the python version used for pyx* functions and commands
5799+
|python_x|. The default value is as follows:
5800+
5801+
Compiled with Default ~
5802+
|+python| and |+python3| 0
5803+
only |+python| 2
5804+
only |+python3| 3
5805+
5806+
Available values are 0, 2 and 3.
5807+
If 'pyxversion' is 0, it is set to 2 or 3 after the first execution of
5808+
any python2/3 commands or functions. E.g. `:py` sets to 2, and `:py3`
5809+
sets to 3. `:pyx` sets it to 3 if Python 3 is available, otherwise sets
5810+
to 2 if Python 2 is available.
5811+
See also: |has-pythonx|
5812+
5813+
If Vim is compiled with only |+python| or |+python3| setting
5814+
'pyxversion' has no effect. The pyx* functions and commands are
5815+
always the same as the compiled version.
5816+
57895817
This option cannot be set from a |modeline| or in the |sandbox|, for
57905818
security reasons.
57915819

runtime/doc/quickref.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ Short explanation of each option: *option-list*
835835
'pumheight' 'ph' maximum height of the popup menu
836836
'pythondll' name of the Python 2 dynamic library
837837
'pythonthreedll' name of the Python 3 dynamic library
838+
'pyxversion' 'pyx' Python version used for pyx* commands
838839
'quoteescape' 'qe' escape characters used in a string
839840
'readonly' 'ro' disallow writing the buffer
840841
'redrawtime' 'rdt' timeout for 'hlsearch' and |:match| highlighting

runtime/optwin.vim

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,7 @@ if has("folding")
923923
call append("$", "foldmarker\tmarkers used when 'foldmethod' is \"marker\"")
924924
call append("$", "\t(local to window)")
925925
call <SID>OptionL("fmr")
926-
call append("$", "foldnestmax\tmaximum fold depth for when 'foldmethod is \"indent\" or \"syntax\"")
926+
call append("$", "foldnestmax\tmaximum fold depth for when 'foldmethod' is \"indent\" or \"syntax\"")
927927
call append("$", "\t(local to window)")
928928
call <SID>OptionL("fdn")
929929
endif
@@ -1324,6 +1324,10 @@ if exists("&perldll")
13241324
call append("$", "perldll\tname of the Perl dynamic library")
13251325
call <SID>OptionG("perldll", &perldll)
13261326
endif
1327+
if has('pythonx')
1328+
call append("$", "pyxversion\twhether to use Python 2 or 3")
1329+
call append("$", " \tset pyx=" . &wd)
1330+
endif
13271331
if exists("&pythondll")
13281332
call append("$", "pythondll\tname of the Python 2 dynamic library")
13291333
call <SID>OptionG("pythondll", &pythondll)

src/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,6 +2151,8 @@ test_arglist \
21512151
test_popup \
21522152
test_profile \
21532153
test_put \
2154+
test_pyx2 \
2155+
test_pyx3 \
21542156
test_quickfix \
21552157
test_regexp_latin \
21562158
test_regexp_utf8 \
@@ -2754,6 +2756,7 @@ shadow: runtime pixmaps
27542756
../../testdir/*.vim \
27552757
../../testdir/*.py \
27562758
../../testdir/python* \
2759+
../../testdir/pyxfile \
27572760
../../testdir/sautest \
27582761
../../testdir/samples \
27592762
../../testdir/test83-tags? \

src/evalfunc.c

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ static void f_py3eval(typval_T *argvars, typval_T *rettv);
289289
#ifdef FEAT_PYTHON
290290
static void f_pyeval(typval_T *argvars, typval_T *rettv);
291291
#endif
292+
#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
293+
static void f_pyxeval(typval_T *argvars, typval_T *rettv);
294+
#endif
292295
static void f_range(typval_T *argvars, typval_T *rettv);
293296
static void f_readfile(typval_T *argvars, typval_T *rettv);
294297
static void f_reltime(typval_T *argvars, typval_T *rettv);
@@ -715,6 +718,9 @@ static struct fst
715718
#endif
716719
#ifdef FEAT_PYTHON
717720
{"pyeval", 1, 1, f_pyeval},
721+
#endif
722+
#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
723+
{"pyxeval", 1, 1, f_pyxeval},
718724
#endif
719725
{"range", 1, 3, f_range},
720726
{"readfile", 1, 3, f_readfile},
@@ -5734,15 +5740,13 @@ f_has(typval_T *argvars, typval_T *rettv)
57345740
#ifdef FEAT_PERSISTENT_UNDO
57355741
"persistent_undo",
57365742
#endif
5737-
#ifdef FEAT_PYTHON
5738-
#ifndef DYNAMIC_PYTHON
5743+
#if defined(FEAT_PYTHON) && !defined(DYNAMIC_PYTHON)
57395744
"python",
5745+
"pythonx",
57405746
#endif
5741-
#endif
5742-
#ifdef FEAT_PYTHON3
5743-
#ifndef DYNAMIC_PYTHON3
5747+
#if defined(FEAT_PYTHON3) && !defined(DYNAMIC_PYTHON3)
57445748
"python3",
5745-
#endif
5749+
"pythonx",
57465750
#endif
57475751
#ifdef FEAT_POSTSCRIPT
57485752
"postscript",
@@ -5972,17 +5976,30 @@ f_has(typval_T *argvars, typval_T *rettv)
59725976
else if (STRICMP(name, "ruby") == 0)
59735977
n = ruby_enabled(FALSE);
59745978
#endif
5975-
#ifdef FEAT_PYTHON
59765979
#ifdef DYNAMIC_PYTHON
59775980
else if (STRICMP(name, "python") == 0)
59785981
n = python_enabled(FALSE);
59795982
#endif
5980-
#endif
5981-
#ifdef FEAT_PYTHON3
59825983
#ifdef DYNAMIC_PYTHON3
59835984
else if (STRICMP(name, "python3") == 0)
59845985
n = python3_enabled(FALSE);
59855986
#endif
5987+
#if defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3)
5988+
else if (STRICMP(name, "pythonx") == 0)
5989+
{
5990+
# if defined(DYNAMIC_PYTHON) && defined(DYNAMIC_PYTHON3)
5991+
if (p_pyx == 0)
5992+
n = python3_enabled(FALSE) || python_enabled(FALSE);
5993+
else if (p_pyx == 3)
5994+
n = python3_enabled(FALSE);
5995+
else if (p_pyx == 2)
5996+
n = python_enabled(FALSE);
5997+
# elif defined(DYNAMIC_PYTHON)
5998+
n = python_enabled(FALSE);
5999+
# elif defined(DYNAMIC_PYTHON3)
6000+
n = python3_enabled(FALSE);
6001+
# endif
6002+
}
59866003
#endif
59876004
#ifdef DYNAMIC_PERL
59886005
else if (STRICMP(name, "perl") == 0)
@@ -8007,6 +8024,9 @@ f_py3eval(typval_T *argvars, typval_T *rettv)
80078024
char_u *str;
80088025
char_u buf[NUMBUFLEN];
80098026

8027+
if (p_pyx == 0)
8028+
p_pyx = 3;
8029+
80108030
str = get_tv_string_buf(&argvars[0], buf);
80118031
do_py3eval(str, rettv);
80128032
}
@@ -8022,11 +8042,35 @@ f_pyeval(typval_T *argvars, typval_T *rettv)
80228042
char_u *str;
80238043
char_u buf[NUMBUFLEN];
80248044

8045+
if (p_pyx == 0)
8046+
p_pyx = 2;
8047+
80258048
str = get_tv_string_buf(&argvars[0], buf);
80268049
do_pyeval(str, rettv);
80278050
}
80288051
#endif
80298052

8053+
#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
8054+
/*
8055+
* "pyxeval()" function
8056+
*/
8057+
static void
8058+
f_pyxeval(typval_T *argvars, typval_T *rettv)
8059+
{
8060+
# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
8061+
init_pyxversion();
8062+
if (p_pyx == 2)
8063+
f_pyeval(argvars, rettv);
8064+
else
8065+
f_py3eval(argvars, rettv);
8066+
# elif defined(FEAT_PYTHON)
8067+
f_pyeval(argvars, rettv);
8068+
# elif defined(FEAT_PYTHON3)
8069+
f_py3eval(argvars, rettv);
8070+
# endif
8071+
}
8072+
#endif
8073+
80308074
/*
80318075
* "range()" function
80328076
*/

src/ex_cmds.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,18 @@ EX(CMD_python3, "python3", ex_py3,
11321132
EX(CMD_py3file, "py3file", ex_py3file,
11331133
RANGE|FILE1|NEEDARG|CMDWIN,
11341134
ADDR_LINES),
1135+
EX(CMD_pyx, "pyx", ex_pyx,
1136+
RANGE|EXTRA|NEEDARG|CMDWIN,
1137+
ADDR_LINES),
1138+
EX(CMD_pyxdo, "pyxdo", ex_pyxdo,
1139+
RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN,
1140+
ADDR_LINES),
1141+
EX(CMD_pythonx, "pythonx", ex_pyx,
1142+
RANGE|EXTRA|NEEDARG|CMDWIN,
1143+
ADDR_LINES),
1144+
EX(CMD_pyxfile, "pyxfile", ex_pyxfile,
1145+
RANGE|FILE1|NEEDARG|CMDWIN,
1146+
ADDR_LINES),
11351147
EX(CMD_quit, "quit", ex_quit,
11361148
BANG|RANGE|COUNT|NOTADR|TRLBAR|CMDWIN,
11371149
ADDR_WINDOWS),

0 commit comments

Comments
 (0)