diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 344a1f03..84607ec8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,6 +1,6 @@ [bumpversion] commit = True -current_version = 0.10.0 +current_version = 0.14.0 files = plugin/pymode.vim tag = True tag_name = {new_version} @@ -9,3 +9,6 @@ tag_name = {new_version} search = Version: {current_version} replace = Version: {new_version} +[bumpversion:file:CHANGELOG.md] +search = Version: {current_version} +replace = Version: {new_version} diff --git a/.github/workflows/test_pymode.yml b/.github/workflows/test_pymode.yml index 7b6bab70..332dcdad 100644 --- a/.github/workflows/test_pymode.yml +++ b/.github/workflows/test_pymode.yml @@ -3,21 +3,56 @@ name: Testing python-mode on: [push] jobs: - test-python-3_6: + test-python-3_8: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Install dependencies run: | sudo apt update - sudo apt install -yqq libncurses5-dev libatk1.0-dev python-dev python3-dev lua5.1 lua5.1-dev libperl-dev git - sudo apt remove --purge vim vim-runtime gvim + export PYTHON_CONFIGURE_OPTS="--enable-shared" + sudo apt install -yqq libncurses5-dev libgtk2.0-dev libatk1.0-dev libcairo2-dev libx11-dev libxpm-dev libxt-dev python3-dev lua5.2 liblua5.2-dev libperl-dev git + sudo apt remove --purge -yqq vim vim-runtime gvim - name: build and install vim from source working-directory: /tmp run: | + export PYTHON_CONFIGURE_OPTS="--enable-shared" git clone https://github.com/vim/vim.git cd vim - ./configure --with-features=huge --enable-multibyte --enable-python3interp=yes --with-python3-config-dir=/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu --enable-perlinterp=yes --enable-luainterp=yes --enable-cscope --prefix=/usr/local + ./configure --with-features=huge --enable-multibyte --enable-python3interp=yes --with-python3-config-dir=/usr/lib/python3.8/config-3.8m-x86_64-linux-gnu --enable-perlinterp=yes --enable-luainterp=yes --enable-cscope --prefix=/usr/local + sudo make && sudo make install + - name: Install python-mode + run: | + export PYMODE_DIR="${HOME}/work/python-mode/python-mode" + mkdir -p ${HOME}/.vim/pack/foo/start/ + ln -s ${PYMODE_DIR} ${HOME}/.vim/pack/foo/start/python-mode + cp ${PYMODE_DIR}/tests/utils/pymoderc ${HOME}/.pymoderc + cp ${PYMODE_DIR}/tests/utils/vimrc ${HOME}/.vimrc + touch ${HOME}/.vimrc.before ${HOME}/.vimrc.after + - name: Run python-mode test script + run: | + alias python=python3 + cd ${HOME}/work/python-mode/python-mode + git submodule update --init --recursive + git submodule sync + bash tests/test.sh + test-python-3_9: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install dependencies + run: | + sudo apt update + export PYTHON_CONFIGURE_OPTS="--enable-shared" + sudo apt install -yqq libncurses5-dev libgtk2.0-dev libatk1.0-dev libcairo2-dev libx11-dev libxpm-dev libxt-dev python3-dev lua5.2 liblua5.2-dev libperl-dev git + sudo apt remove --purge -yqq vim vim-runtime gvim + - name: build and install vim from source + working-directory: /tmp + run: | + export PYTHON_CONFIGURE_OPTS="--enable-shared" + git clone https://github.com/vim/vim.git + cd vim + ./configure --with-features=huge --enable-multibyte --enable-python3interp=yes --with-python3-config-dir=/usr/lib/python3.9/config-3.9m-x86_64-linux-gnu --enable-perlinterp=yes --enable-luainterp=yes --enable-cscope --prefix=/usr/local sudo make && sudo make install - name: Install python-mode run: | diff --git a/.gitmodules b/.gitmodules index ada9193a..59d00541 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,36 +2,58 @@ path = submodules/autopep8 url = https://github.com/hhatto/autopep8 ignore = dirty + shallow = true [submodule "submodules/pycodestyle"] path = submodules/pycodestyle url = https://github.com/PyCQA/pycodestyle ignore = dirty + shallow = true [submodule "submodules/pydocstyle"] path = submodules/pydocstyle url = https://github.com/PyCQA/pydocstyle ignore = dirty + shallow = true [submodule "submodules/mccabe"] path = submodules/mccabe url = https://github.com/PyCQA/mccabe ignore = dirty + shallow = true [submodule "submodules/pyflakes"] path = submodules/pyflakes url = https://github.com/PyCQA/pyflakes ignore = dirty + shallow = true [submodule "submodules/snowball_py"] path = submodules/snowball_py url = https://github.com/diraol/snowball_py ignore = dirty branch = develop + shallow = true [submodule "submodules/pylint"] path = submodules/pylint url = https://github.com/PyCQA/pylint + shallow = true [submodule "submodules/rope"] path = submodules/rope url = https://github.com/python-rope/rope + shallow = true [submodule "submodules/astroid"] path = submodules/astroid url = https://github.com/PyCQA/astroid + shallow = true [submodule "submodules/pylama"] path = submodules/pylama url = https://github.com/klen/pylama + shallow = true +[submodule "submodules/toml"] + path = submodules/toml + url = https://github.com/uiri/toml.git +[submodule "submodules/pytoolconfig"] + path = submodules/pytoolconfig + url = https://github.com/bagel897/pytoolconfig.git +[submodule "submodules/tomli"] + path = submodules/tomli + url = https://github.com/hukkin/tomli.git +[submodule "submodules/appdirs"] + path = submodules/appdirs + url = https://github.com/ActiveState/appdirs.git diff --git a/AUTHORS b/AUTHORS index fd56f319..a4bcbf28 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,7 +4,7 @@ Author: Maintainers: -* Felipe M. Vieira (https://github.com/fmv1992) +* Diego Rabatone Oliveira (https://github.com/diraol); Contributors: @@ -25,9 +25,9 @@ Contributors: * Daniel Hahler (http://github.com/blueyed); * David Vogt (http://github.com/winged); * Denis Kasak (http://github.com/dkasak); -* Diego Rabatone Oliveira (https://github.com/diraol); * Dimitrios Semitsoglou-Tsiapos (https://github.com/dset0x); * Dirk Wallenstein (http://github.com/dirkwallenstein); +* Felipe M. Vieira (https://github.com/fmv1992) * Filip Poboril (https://github.com/fpob); * Florent Xicluna (http://github.com/florentx); * Fredrik Henrysson (http://github.com/fhenrysson); @@ -42,6 +42,7 @@ Contributors: * Kurtis Rader (https://github.com/krader1961); * Lawrence Akka (https://github.com/lawrenceakka); * lee (https://github.com/loyalpartner); +* Lie Ryan (https://github.com/lieryan/); * Lowe Thiderman (http://github.com/thiderman); * Martin Brochhaus (http://github.com/mbrochh); * Matt Dodge (https://github.com/mattdodge); @@ -74,3 +75,4 @@ Contributors: * Yury A. Kartynnik (https://github.com/kartynnik); * Xiangyu Xu (https://github.com/bkbncn); * Zach Himsel (https://github.com/zhimsel); +* Nathan Pemberton (https://github.com/NathanTP); diff --git a/CHANGELOG.md b/CHANGELOG.md index 001a9194..4e7668dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,38 @@ ## TODO +## 2023-07-02 0.14.0 + +- Update submodules + - Fix Errors related to these updates +- Improve tests outputs +- Fix Global and Module MoveRefactoring (#1141) Thanks to @lieryan +- Text object/operator/motion mapping to select logical line (#1145). Thanks to + @lieryan +- Remove dead keywords and builtins; add match, case (#1149). Thanks to + @NeilGirdhar +- Add syntax highlight for walrus (#1147) Thanks to @fpob +- Add configurable prefix for rope commands (#1137) TThanks to @NathanTP +- Add option g:pymode_indent_hanging_width for different hanging indentation + width (#1138). Thanks to @wookayin + +## 2020-10-08 0.13.0 + +- Add toml submodule + +## 2020-10-08 0.12.0 + +- Improve breakpoint feature +- Improve debugging script +- Update submodules +- Improve tests + +## 2020-05-28 0.11.0 + - Move changelog rst syntax to markdown - `pymode_rope`: check disables -- Remove supoort for python 2. From 0.11.0 on we will focus on supporting - python 3+ (probably 3.5+). +- BREAKING CHANGE: Remove supoort for python 2. From 0.11.0 on we will focus on + supporting python 3+ (probably 3.5+). - Inspect why files starting with the following code do not get loaded: ```python @@ -16,6 +44,12 @@ main() ``` +- added github actions test suit and remove travis +- improved submodules cloning (shallow) +- Removes `six` submodule +- Fix motion mapping +- Fix breakpoint feature + ## 2019-05-11 0.10.0 After many changes, including moving most of our dependencies from copied diff --git a/after/ftplugin/python.vim b/after/ftplugin/python.vim index 0fdd01a3..6b5a8839 100644 --- a/after/ftplugin/python.vim +++ b/after/ftplugin/python.vim @@ -42,6 +42,8 @@ if g:pymode_motion vnoremap aM :call pymode#motion#select('^s*(asyncs+)=@', '^s*(asyncs+)=defs', 0) vnoremap iM :call pymode#motion#select('^s*(asyncs+)=@', '^s*(asyncs+)=defs', 1) + onoremap V :call pymode#rope#select_logical_line() + endif if g:pymode_rope && g:pymode_rope_completion diff --git a/autoload/pymode/breakpoint.vim b/autoload/pymode/breakpoint.vim index 2692ca34..98639b57 100644 --- a/autoload/pymode/breakpoint.vim +++ b/autoload/pymode/breakpoint.vim @@ -11,10 +11,14 @@ fun! pymode#breakpoint#init() "{{{ from importlib.util import find_spec -for module in ('wdb', 'pudb', 'ipdb', 'pdb'): - if find_spec(module): - vim.command('let g:pymode_breakpoint_cmd = "import %s; %s.set_trace() # XXX BREAKPOINT"' % (module, module)) - break +if sys.version_info >= (3, 7): + vim.command('let g:pymode_breakpoint_cmd = "breakpoint()"') + +else: + for module in ('wdb', 'pudb', 'ipdb', 'pdb'): + if find_spec(module): + vim.command('let g:pymode_breakpoint_cmd = "import %s; %s.set_trace() # XXX BREAKPOINT"' % (module, module)) + break EOF endif diff --git a/autoload/pymode/debug.vim b/autoload/pymode/debug.vim index cf139b07..2be5149c 100644 --- a/autoload/pymode/debug.vim +++ b/autoload/pymode/debug.vim @@ -30,7 +30,7 @@ fun! pymode#debug#sysinfo() "{{{ echom pymodevar endfor " }}} - " Github commit info. {{{ + " Git commit info. {{{ " Find in the scriptnames the first occurence of 'python-mode'. Then parse " the result outputting its path. This is in turn fed into the git command. call pymode#debug("Git commit: ") @@ -44,6 +44,13 @@ fun! pymode#debug#sysinfo() "{{{ let l:git_head_sha1 = system('git -C ' . expand(l:pymode_folder). ' rev-parse HEAD ' ) echom join(filter(split(l:git_head_sha1, '\zs'), 'v:val =~? "[0-9A-Fa-f]"'), '') " }}} + " Git submodules status. {{{ + call pymode#debug("Git submodule status:") + let l:git_submodule_status = system('git -C ' . expand(l:pymode_folder). ' submodule status') + for submodule in split(l:git_submodule_status, '\n') + echom submodule + endfor + " }}} call pymode#debug("End of pymode#debug#sysinfo") endfunction "}}} diff --git a/autoload/pymode/indent.vim b/autoload/pymode/indent.vim index efd41f29..e964f378 100644 --- a/autoload/pymode/indent.vim +++ b/autoload/pymode/indent.vim @@ -24,7 +24,9 @@ function! pymode#indent#get_indent(lnum) if closing_paren return indent(parlnum) else - return indent(parlnum) + &shiftwidth + let l:indent_width = (g:pymode_indent_hanging_width > 0 ? + \ g:pymode_indent_hanging_width : &shiftwidth) + return indent(parlnum) + l:indent_width endif else return parcol diff --git a/autoload/pymode/motion.vim b/autoload/pymode/motion.vim index a930f35a..c88fb913 100644 --- a/autoload/pymode/motion.vim +++ b/autoload/pymode/motion.vim @@ -51,7 +51,7 @@ fun! pymode#motion#select(first_pattern, second_pattern, inner) "{{{ endif call cursor(snum, 1) - normal! v + normal! V call cursor(enum, len(getline(enum))) endif endfunction "}}} diff --git a/autoload/pymode/rope.vim b/autoload/pymode/rope.vim index c1a2de0c..36344d0a 100644 --- a/autoload/pymode/rope.vim +++ b/autoload/pymode/rope.vim @@ -194,3 +194,7 @@ fun! pymode#rope#generate_package() "{{{ endif PymodePython rope.GenerateElementRefactoring('package').run() endfunction "}}} + +fun! pymode#rope#select_logical_line() "{{{ + PymodePython rope.select_logical_line() +endfunction "}}} diff --git a/doc/pymode.txt b/doc/pymode.txt index 2e2b7f98..7235b5d5 100644 --- a/doc/pymode.txt +++ b/doc/pymode.txt @@ -6,7 +6,7 @@ (__) (__) (__) (_) (_)(_____)(_)\_) (_/\/\_)(_____)(____/(____) ~ - Version: 0.10.0 + Version: 0.14.0 =============================================================================== CONTENTS *pymode-contents* @@ -170,6 +170,16 @@ Enable pymode indentation *'g:pymode_indent' > let g:pymode_indent = 1 + +Customization: + +Hanging indent size after an open parenthesis or bracket (but nothing after the +parenthesis), when vertical alignment is not used. Defaults to `&shiftwidth`. + *'g:pymode_indent_hanging_width'* +> + let g:pymode_indent_hanging_width = &shiftwidth + let g:pymode_indent_hanging_width = 4 + ------------------------------------------------------------------------------- 2.3 Python folding ~ *pymode-folding* @@ -199,10 +209,11 @@ Key Command ]] Jump to next class or function (normal, visual, operator modes) [M Jump to previous class or method (normal, visual, operator modes) ]M Jump to next class or method (normal, visual, operator modes) -aC Select a class. Ex: vaC, daC, yaC, caC (normal, operator modes) -iC Select inner class. Ex: viC, diC, yiC, ciC (normal, operator modes) -aM Select a function or method. Ex: vaM, daM, yaM, caM (normal, operator modes) -iM Select inner function or method. Ex: viM, diM, yiM, ciM (normal, operator modes) +aC Select a class. Ex: vaC, daC, yaC, caC (operator modes) +iC Select inner class. Ex: viC, diC, yiC, ciC (operator modes) +aM Select a function or method. Ex: vaM, daM, yaM, caM (operator modes) +iM Select inner function or method. Ex: viM, diM, yiM, ciM (operator modes) +V Select logical line. Ex: dV, yV, cV (operator modes), also works with count ==== ============================ Enable pymode-motion *'g:pymode_motion'* @@ -282,7 +293,7 @@ Manually set breakpoint command (leave empty for automatic detection) 3. Code checking ~ *pymode-lint* -Pymode supports `pylint`, `pep257`, `pep8`, `pyflakes`, `mccabe` code +Pymode supports `pylint`, `pep257`, `pycodestyle`, `pyflakes`, `mccabe` code checkers. You could run several similar checkers. Pymode uses Pylama library for code checking. Many options like skip @@ -319,9 +330,9 @@ Show error message if cursor placed at the error line *'g:pymode_lint_message' Default code checkers (you could set several) *'g:pymode_lint_checkers'* > - let g:pymode_lint_checkers = ['pyflakes', 'pep8', 'mccabe'] + let g:pymode_lint_checkers = ['pyflakes', 'pycodestyle', 'mccabe'] -Values may be chosen from: `pylint`, `pep8`, `mccabe`, `pep257`, `pyflakes`. +Values may be chosen from: `pylint`, `pycodestyle`, `mccabe`, `pep257`, `pyflakes`. Skip errors and warnings *'g:pymode_lint_ignore'* E.g. ["W", "E2"] (Skip all Warnings and the Errors starting with E2) etc. @@ -365,9 +376,9 @@ Definitions for |signs| Pymode has the ability to set code checkers options from pymode variables: -Set PEP8 options *'g:pymode_lint_options_pep8'* +Set PEP8 options *'g:pymode_lint_options_pycodestyle'* > - let g:pymode_lint_options_pep8 = + let g:pymode_lint_options_pycodestyle = \ {'max_line_length': g:pymode_options_max_line_length} See https://pep8.readthedocs.org/en/1.4.6/intro.html#configuration for more @@ -413,6 +424,10 @@ Turn on the rope script *'g:pymode_rope' > let g:pymode_rope = 1 +Set the prefix for rope commands *'g:pymode_rope_prefix'* +> + let g:pymode_rope_refix = '' + .ropeproject Folder ~ *.ropeproject* @@ -603,14 +618,31 @@ code to call it instead. let g:pymode_rope_use_function_bind = 'ru' -Move method/fields ~ +Move refactoring ~ *pymode-rope-move* +Moving method/fields + It happens when you perform move refactoring on a method of a class. In this refactoring, a method of a class is moved to the class of one of its attributes. The old method will call the new method. If you want to change all of the occurrences of the old method to use the new method you can inline it afterwards. + +Moving global variable/class/function into another module + +It happens when you perform move refactoring on global variable/class/function. +In this refactoring, the object being refactored will be moved to a destination +module. All references to the object being moved will be updated to point to +the new location. + +Moving module variable/class/function into a package + +It happens when you perform move refactoring on a name referencing a module. +In this refactoring, the module being refactored will be moved to a destination +package. All references to the object being moved will be updated to point to +the new location. + > let g:pymode_rope_move_bind = 'rv' @@ -660,6 +692,10 @@ Highlight '=' operator *'g:pymode_syntax_highlight_equal_operator' > let g:pymode_syntax_highlight_equal_operator = g:pymode_syntax_all +Highlight ':=' operator *'g:pymode_syntax_highlight_walrus_operator'* +> + let g:pymode_syntax_highlight_walrus_operator = g:pymode_syntax_all + Highlight '*' operator *'g:pymode_syntax_highlight_stars_operator'* > let g:pymode_syntax_highlight_stars_operator = g:pymode_syntax_all diff --git a/ftplugin/python/pymode.vim b/ftplugin/python/pymode.vim index c13aff71..a1370669 100644 --- a/ftplugin/python/pymode.vim +++ b/ftplugin/python/pymode.vim @@ -5,7 +5,7 @@ endif if g:pymode_python == 'disable' if g:pymode_warning - call pymode#error("Pymode requires vim compiled with +python. Most of features will be disabled.") + call pymode#error("Pymode requires vim compiled with +python3 (exclusively). Most of features will be disabled.") endif finish diff --git a/plugin/pymode.vim b/plugin/pymode.vim index 67216a07..b0d99270 100644 --- a/plugin/pymode.vim +++ b/plugin/pymode.vim @@ -1,5 +1,6 @@ " vi: fdl=1 -let g:pymode_version = "0.10.0" +let g:pymode_version = "0.14.0" + " Enable pymode by default :) call pymode#default('g:pymode', 1) @@ -38,6 +39,9 @@ call pymode#default('g:pymode_doc_bind', 'K') " Enable/Disable pymode PEP8 indentation call pymode#default("g:pymode_indent", 1) +" Customize hanging indent size different than &shiftwidth +call pymode#default("g:pymode_indent_hanging_width", -1) + " TODO: currently folding suffers from a bad performance and incorrect " implementation. This feature should be considered experimental. " Enable/disable pymode folding for pyfiles. @@ -118,8 +122,8 @@ call pymode#default("g:pymode_lint_on_fly", 0) " Show message about error in command line call pymode#default("g:pymode_lint_message", 1) -" Choices are: pylint, pyflakes, pep8, mccabe and pep257 -call pymode#default("g:pymode_lint_checkers", ['pyflakes', 'pep8', 'mccabe']) +" Choices are: pylint, pyflakes, pycodestyle, mccabe and pep257 +call pymode#default("g:pymode_lint_checkers", ['pyflakes', 'pycodestyle', 'mccabe']) " Skip errors and warnings (e.g. E4,W) call pymode#default("g:pymode_lint_ignore", []) @@ -148,8 +152,8 @@ call pymode#default("g:pymode_lint_info_symbol", "II") call pymode#default("g:pymode_lint_pyflakes_symbol", "FF") " Code checkers options -" TODO: check if most adequate name name is pep8 or pycodestyle. -call pymode#default("g:pymode_lint_options_pep8", +" TODO: check if most adequate name name is pycodestyle. +call pymode#default("g:pymode_lint_options_pycodestyle", \ {'max_line_length': g:pymode_options_max_line_length}) call pymode#default("g:pymode_lint_options_pylint", @@ -182,6 +186,7 @@ call pymode#default('g:pymode_breakpoint_cmd', '') " " Rope support call pymode#default('g:pymode_rope', 0) +call pymode#default('g:pymode_rope_prefix', '') " System plugin variable if g:pymode_rope @@ -210,7 +215,7 @@ if g:pymode_rope call pymode#default('g:pymode_rope_autoimport_modules', ['os', 'shutil', 'datetime']) " Bind keys to autoimport module for object under cursor - call pymode#default('g:pymode_rope_autoimport_bind', 'ra') + call pymode#default('g:pymode_rope_autoimport_bind', g:pymode_rope_prefix . 'ra') " Automatic completion on dot call pymode#default('g:pymode_rope_complete_on_dot', 1) @@ -219,56 +224,56 @@ if g:pymode_rope call pymode#default('g:pymode_rope_completion_bind', '') " Bind keys for goto definition (leave empty for disable) - call pymode#default('g:pymode_rope_goto_definition_bind', 'g') + call pymode#default('g:pymode_rope_goto_definition_bind', g:pymode_rope_prefix . 'g') " set command for open definition (e, new, vnew) call pymode#default('g:pymode_rope_goto_definition_cmd', 'new') " Bind keys for show documentation (leave empty for disable) - call pymode#default('g:pymode_rope_show_doc_bind', 'd') + call pymode#default('g:pymode_rope_show_doc_bind', g:pymode_rope_prefix . 'd') " Bind keys for find occurencies (leave empty for disable) - call pymode#default('g:pymode_rope_find_it_bind', 'f') + call pymode#default('g:pymode_rope_find_it_bind', g:pymode_rope_prefix . 'f') " Bind keys for organize imports (leave empty for disable) - call pymode#default('g:pymode_rope_organize_imports_bind', 'ro') + call pymode#default('g:pymode_rope_organize_imports_bind', g:pymode_rope_prefix . 'ro') " Bind keys for rename variable/method/class in the project (leave empty for disable) - call pymode#default('g:pymode_rope_rename_bind', 'rr') + call pymode#default('g:pymode_rope_rename_bind', g:pymode_rope_prefix . 'rr') " Bind keys for rename module - call pymode#default('g:pymode_rope_rename_module_bind', 'r1r') + call pymode#default('g:pymode_rope_rename_module_bind', g:pymode_rope_prefix . 'r1r') " Bind keys for convert module to package - call pymode#default('g:pymode_rope_module_to_package_bind', 'r1p') + call pymode#default('g:pymode_rope_module_to_package_bind', g:pymode_rope_prefix . 'r1p') " Creates a new function or method (depending on the context) from the selected lines - call pymode#default('g:pymode_rope_extract_method_bind', 'rm') + call pymode#default('g:pymode_rope_extract_method_bind', g:pymode_rope_prefix . 'rm') " Creates a variable from the selected lines - call pymode#default('g:pymode_rope_extract_variable_bind', 'rl') + call pymode#default('g:pymode_rope_extract_variable_bind', g:pymode_rope_prefix . 'rl') " Inline refactoring - call pymode#default('g:pymode_rope_inline_bind', 'ri') + call pymode#default('g:pymode_rope_inline_bind', g:pymode_rope_prefix . 'ri') " Move refactoring - call pymode#default('g:pymode_rope_move_bind', 'rv') + call pymode#default('g:pymode_rope_move_bind', g:pymode_rope_prefix . 'rv') " Generate function - call pymode#default('g:pymode_rope_generate_function_bind', 'rnf') + call pymode#default('g:pymode_rope_generate_function_bind', g:pymode_rope_prefix . 'rnf') " Generate class - call pymode#default('g:pymode_rope_generate_class_bind', 'rnc') + call pymode#default('g:pymode_rope_generate_class_bind', g:pymode_rope_prefix . 'rnc') " Generate package - call pymode#default('g:pymode_rope_generate_package_bind', 'rnp') + call pymode#default('g:pymode_rope_generate_package_bind', g:pymode_rope_prefix . 'rnp') " Change signature - call pymode#default('g:pymode_rope_change_signature_bind', 'rs') + call pymode#default('g:pymode_rope_change_signature_bind', g:pymode_rope_prefix . 'rs') " Tries to find the places in which a function can be used and changes the " code to call it instead - call pymode#default('g:pymode_rope_use_function_bind', 'ru') + call pymode#default('g:pymode_rope_use_function_bind', g:pymode_rope_prefix . 'ru') " Regenerate project cache on every save call pymode#default('g:pymode_rope_regenerate_on_write', 1) diff --git a/pymode/__init__.py b/pymode/__init__.py index aba22870..906d7059 100644 --- a/pymode/__init__.py +++ b/pymode/__init__.py @@ -6,7 +6,13 @@ import vim # noqa if not hasattr(vim, 'find_module'): - vim.find_module = _PathFinder.find_module + try: + vim.find_module = _PathFinder.find_module # deprecated + except AttributeError: + def _find_module(package_name): + spec = _PathFinder.find_spec(package_name) + return spec.loader if spec else None + vim.find_module = _find_module def auto(): diff --git a/pymode/environment.py b/pymode/environment.py index 30ae0e50..86527f56 100644 --- a/pymode/environment.py +++ b/pymode/environment.py @@ -242,5 +242,8 @@ def goto_buffer(bufnr): if str(bufnr) != '-1': vim.command('buffer %s' % bufnr) + def select_line(self, start, end): + vim.command('normal %sggV%sgg' % (start, end)) + env = VimPymodeEnviroment() diff --git a/pymode/libs/appdirs.py b/pymode/libs/appdirs.py new file mode 120000 index 00000000..da7cbf20 --- /dev/null +++ b/pymode/libs/appdirs.py @@ -0,0 +1 @@ +../../submodules/appdirs/appdirs.py \ No newline at end of file diff --git a/pymode/libs/pytoolconfig b/pymode/libs/pytoolconfig new file mode 120000 index 00000000..0a2d520c --- /dev/null +++ b/pymode/libs/pytoolconfig @@ -0,0 +1 @@ +../../submodules/pytoolconfig/pytoolconfig/ \ No newline at end of file diff --git a/pymode/libs/toml b/pymode/libs/toml new file mode 120000 index 00000000..dc960a0a --- /dev/null +++ b/pymode/libs/toml @@ -0,0 +1 @@ +../../submodules/toml/toml \ No newline at end of file diff --git a/pymode/libs/tomli b/pymode/libs/tomli new file mode 120000 index 00000000..2413e2b5 --- /dev/null +++ b/pymode/libs/tomli @@ -0,0 +1 @@ +../../submodules/tomli/src/tomli \ No newline at end of file diff --git a/pymode/lint.py b/pymode/lint.py index ba187558..b0103a50 100644 --- a/pymode/lint.py +++ b/pymode/lint.py @@ -6,7 +6,7 @@ import os.path -from pylama.lint.extensions import LINTERS +from pylama.lint import LINTERS try: from pylama.lint.pylama_pylint import Linter @@ -35,13 +35,19 @@ def code_check(): # Fixed in v0.9.3: these two parameters may be passed as strings. # DEPRECATE: v:0.10.0: need to be set as lists. if isinstance(env.var('g:pymode_lint_ignore'), str): - raise ValueError ('g:pymode_lint_ignore should have a list type') + raise ValueError('g:pymode_lint_ignore should have a list type') else: ignore = env.var('g:pymode_lint_ignore') if isinstance(env.var('g:pymode_lint_select'), str): - raise ValueError ('g:pymode_lint_select should have a list type') + raise ValueError('g:pymode_lint_select should have a list type') else: select = env.var('g:pymode_lint_select') + if 'pep8' in linters: + # TODO: Add a user visible deprecation warning here + env.message('pep8 linter is deprecated, please use pycodestyle.') + linters.remove('pep8') + linters.append('pycodestyle') + options = parse_options( linters=linters, force=1, ignore=ignore, @@ -65,7 +71,8 @@ def code_check(): return env.stop() if env.options.get('debug'): - from pylama.core import LOGGER, logging + import logging + from pylama.core import LOGGER LOGGER.setLevel(logging.DEBUG) errors = run(path, code='\n'.join(env.curbuf) + '\n', options=options) @@ -83,11 +90,16 @@ def __sort(e): env.debug("Find sorting: ", sort_rules) errors = sorted(errors, key=__sort) + errors_list = [] for e in errors: - e._info['bufnr'] = env.curbuf.number - if e._info['col'] is None: - e._info['col'] = 1 - - env.run('g:PymodeLocList.current().extend', [e._info for e in errors]) + if e.col is None: + e.col = 1 + err_dict = e.to_dict() + err_dict['bufnr'] = env.curbuf.number + err_dict['type'] = e.etype + err_dict['text'] = e.message + errors_list.append(err_dict) + + env.run('g:PymodeLocList.current().extend', errors_list) # pylama:ignore=W0212,E1103 diff --git a/pymode/rope.py b/pymode/rope.py index ba5f55b2..65c54257 100644 --- a/pymode/rope.py +++ b/pymode/rope.py @@ -5,7 +5,7 @@ import site import sys -from rope.base import project, libutils, exceptions, change, worder, pycore +from rope.base import project, libutils, exceptions, change, worder, pycore, codeanalyze from rope.base.fscommands import FileSystemCommands # noqa from rope.base.taskhandle import TaskHandle # noqa from rope.contrib import autoimport as rope_autoimport, codeassist, findit, generate # noqa @@ -463,10 +463,11 @@ def run(self): if not input_str: return False + code_actions = self.get_code_actions() action = env.user_input_choices( - 'Choose what to do:', 'perform', 'preview', - 'perform in class hierarchy', - 'preview in class hierarchy') + 'Choose what to do:', + *code_actions, + ) in_hierarchy = action.endswith("in class hierarchy") @@ -492,6 +493,12 @@ def run(self): except Exception as e: # noqa env.error('Unhandled exception in Pymode: %s' % e) + def get_code_actions(self): + return [ + 'perform', + 'preview', + ] + @staticmethod def get_refactor(ctx): """ Get refactor object. """ @@ -546,6 +553,14 @@ def get_input_str(self, refactor, ctx): return newname + def get_code_actions(self): + return [ + 'perform', + 'preview', + 'perform in class hierarchy', + 'preview in class hierarchy', + ] + @staticmethod def get_changes(refactor, input_str, in_hierarchy=False): """ Get changes. @@ -701,6 +716,15 @@ def get_refactor(ctx): offset = None return move.create_move(ctx.project, ctx.resource, offset) + @staticmethod + def get_changes(refactor, input_str, in_hierarchy=False): + with RopeContext() as ctx: + if isinstance(refactor, (move.MoveGlobal, move.MoveModule)): + dest = ctx.project.pycore.find_module(input_str) + else: + dest = input_str + return super(MoveRefactoring, MoveRefactoring).get_changes(refactor, dest) + class ChangeSignatureRefactoring(Refactoring): @@ -728,6 +752,14 @@ def get_refactor(ctx): return change_signature.ChangeSignature( ctx.project, ctx.resource, offset) + def get_code_actions(self): + return [ + 'perform', + 'preview', + 'perform in class hierarchy', + 'preview in class hierarchy', + ] + def get_changes(self, refactor, input_string, in_hierarchy=False): """ Function description. @@ -921,6 +953,22 @@ def _insert_import(name, module, ctx): reload_changes(changes) +@env.catch_exceptions +def select_logical_line(): + source, offset = env.get_offset_params() + count = int(env.var('v:count1')) + + lines = codeanalyze.SourceLinesAdapter(source) + start_line = lines.get_line_number(offset) + line_finder = codeanalyze.LogicalLineFinder(lines) + + start_lineno, end_lineno = line_finder.logical_line_in(start_line) + for _, (_, end_lineno) in zip(range(count), line_finder.generate_regions(start_lineno)): + pass + + env.select_line(start_lineno, end_lineno) + + # Monkey patch Rope def find_source_folders(self, folder): """Look only python files an packages.""" diff --git a/readme.md b/readme.md index 5e7adb1a..49b30ea9 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/python-mode/python-mode.svg?branch=develop)](https://travis-ci.org/python-mode/python-mode) +[![Testing python-mode](https://github.com/python-mode/python-mode/workflows/Testing%20python-mode/badge.svg?branch=develop)](https://github.com/python-mode/python-mode/actions?query=workflow%3A%22Testing+python-mode%22+branch%3Adevelop) ![](https://raw.github.com/python-mode/python-mode/develop/logo.png) # Python-mode, a Python IDE for Vim @@ -23,7 +23,7 @@ hard coding 3rd party libraries into its codebase. Please issue the command: `git submodule update --init --recursive` inside your python-mode folder. - * From 2019-12-14 onwards `python-mode` **dropped python2 suuport**. If you + * From 2019-12-14 onwards `python-mode` **dropped python2 support**. If you still need to use it with python2 you should look for the `last-py2-support` branch and/or tag. @@ -156,9 +156,11 @@ Nevertheless just a refresher on how to submit bugs: **(From the FAQ)** Clear all python cache/compiled files (`*.pyc` files and `__pycache__` -directory and everything under it). In Linux/Unix/MacOS you can run: +directory and everything under it) from your _python-mode_ install directory. -`find . -type f -iname '*.pyc' -o -iname '*.pyo' -delete && find . -type d -name '__pycache__' -delete` +In Linux/Unix/MacOS you can run: + +`find -type f -iname '*.pyc' -o -iname '*.pyo' -delete && find . -type d -name '__pycache__' -delete` Then start python mode with: @@ -182,14 +184,28 @@ Please, also provide more contextual information such as: * the python version that vim has loaded in your tests: * `:PymodePython import sys; print(sys.version_info)` output. * and if you are using virtualenvs and/or conda, also state that, please. +* It would be good also to provide the output of the two following commands: +* `git status` (under your _python-mode_ directory) +* `tree ` or something similar (such as `ls -lR`) # Frequent problems Read this section before opening an issue on the tracker. +## Python 2/3 vim support + +Vim [has issues](https://github.com/vim/vim/issues/3585) to work with both +python2 and python3 at the same time, so if your VIM is compiled with support +to both version you may find problems. The best way to handle it is to build +your vim again with only python3 support. +[Here](https://github.com/ycm-core/YouCompleteMe/wiki/Building-Vim-from-source) +is a good reference on how to build vim from source. + ## Python 3 syntax -By default python-mode uses python 3 syntax checking. +`python-mode` supports only python3, so, if you are using python2 we cannot +help you that much. Look for our branch with python2-support (old version, +not maintained anymore) (`last-py2-support`). ## Symlinks on Windows @@ -208,8 +224,8 @@ Then we probably changed some repo reference or some of our dependencies had a `git push --force` in its git history. So the best way for you to handle it is to run, inside the `python-mode` directory: -`git submodule update --recursive --init --force` -`git submodule sync --recursive` +* `git submodule update --recursive --init --force` +* `git submodule sync --recursive` # Documentation diff --git a/submodules/appdirs b/submodules/appdirs new file mode 160000 index 00000000..193a2cbb --- /dev/null +++ b/submodules/appdirs @@ -0,0 +1 @@ +Subproject commit 193a2cbba58cce2542882fcedd0e49f6763672ed diff --git a/submodules/astroid b/submodules/astroid index 5b5cd7ac..8523ba82 160000 --- a/submodules/astroid +++ b/submodules/astroid @@ -1 +1 @@ -Subproject commit 5b5cd7acbecaa9b587b07de27a3334a2ec4f2a79 +Subproject commit 8523ba827006d56a770a1f6efa77215718ef26c0 diff --git a/submodules/autopep8 b/submodules/autopep8 index 159bb888..6e6d4ba4 160000 --- a/submodules/autopep8 +++ b/submodules/autopep8 @@ -1 +1 @@ -Subproject commit 159bb88843e298534e46914da242e680a1c8c47d +Subproject commit 6e6d4ba4a043da1a56ca0ec7280a7d4f40283215 diff --git a/submodules/mccabe b/submodules/mccabe index c2f5b386..85185224 160000 --- a/submodules/mccabe +++ b/submodules/mccabe @@ -1 +1 @@ -Subproject commit c2f5b386458cfda0aa4239f4d11b4e5e75027bda +Subproject commit 851852240f2fa4453c226ccc5ae88bc03b467388 diff --git a/submodules/pycodestyle b/submodules/pycodestyle index 566cdc0c..21abd9b6 160000 --- a/submodules/pycodestyle +++ b/submodules/pycodestyle @@ -1 +1 @@ -Subproject commit 566cdc0cb22e5530902e456d0b315403ebab980c +Subproject commit 21abd9b6dcbfa38635bc85a2c2327ec11ad91ffc diff --git a/submodules/pydocstyle b/submodules/pydocstyle index eea4ca17..5f59f6eb 160000 --- a/submodules/pydocstyle +++ b/submodules/pydocstyle @@ -1 +1 @@ -Subproject commit eea4ca179553189a7b8a62d6085f15b50bb98e35 +Subproject commit 5f59f6eba0d8f0168c6ab45ee97485569b861b77 diff --git a/submodules/pyflakes b/submodules/pyflakes index 45fc7324..b37f91a1 160000 --- a/submodules/pyflakes +++ b/submodules/pyflakes @@ -1 +1 @@ -Subproject commit 45fc732466056fe35c85936ff25491df7905c597 +Subproject commit b37f91a1ae25cfc242d5043985b05159e152091a diff --git a/submodules/pylama b/submodules/pylama index 837ecd3d..53ad214d 160000 --- a/submodules/pylama +++ b/submodules/pylama @@ -1 +1 @@ -Subproject commit 837ecd3d7a8597ab5f28bc83072de68e16470f1e +Subproject commit 53ad214de0aa9534e59bcd5f97d9d723d16cfdb8 diff --git a/submodules/pylint b/submodules/pylint index 66cb3218..fc34a4b6 160000 --- a/submodules/pylint +++ b/submodules/pylint @@ -1 +1 @@ -Subproject commit 66cb32187c040f82dd067bc0d226b2f105bf6c38 +Subproject commit fc34a4b6abe56f3ac07ca15d846b1c1955545f85 diff --git a/submodules/pytoolconfig b/submodules/pytoolconfig new file mode 160000 index 00000000..549787fa --- /dev/null +++ b/submodules/pytoolconfig @@ -0,0 +1 @@ +Subproject commit 549787fa7d100c93333f48aaa9b07619f171736e diff --git a/submodules/rope b/submodules/rope index 95aa2749..b0c8a5fc 160000 --- a/submodules/rope +++ b/submodules/rope @@ -1 +1 @@ -Subproject commit 95aa2749f978d579fda03478dece4d611c2323f9 +Subproject commit b0c8a5fc03ecbc94bd85dff46fc8b3f98f26a91e diff --git a/submodules/toml b/submodules/toml new file mode 160000 index 00000000..3f637dba --- /dev/null +++ b/submodules/toml @@ -0,0 +1 @@ +Subproject commit 3f637dba5f68db63d4b30967fedda51c82459471 diff --git a/submodules/tomli b/submodules/tomli new file mode 160000 index 00000000..7e563eed --- /dev/null +++ b/submodules/tomli @@ -0,0 +1 @@ +Subproject commit 7e563eed5286b5d46b8290a9f56a86d955b23a9a diff --git a/syntax/python.vim b/syntax/python.vim index b7666d86..5a76d2b0 100644 --- a/syntax/python.vim +++ b/syntax/python.vim @@ -23,6 +23,9 @@ call pymode#default("g:pymode_syntax_highlight_async_await", g:pymode_syntax_all " Highlight '=' operator call pymode#default('g:pymode_syntax_highlight_equal_operator', g:pymode_syntax_all) +" Highlight ':=' operator +call pymode#default('g:pymode_syntax_highlight_walrus_operator', g:pymode_syntax_all) + " Highlight '*' operator call pymode#default('g:pymode_syntax_highlight_stars_operator', g:pymode_syntax_all) @@ -91,7 +94,7 @@ endif syn match pythonClassParameters "[^,\*]*" contained contains=pythonBuiltin,pythonBuiltinObj,pythonBuiltinType,pythonExtraOperatorpythonStatement,pythonBrackets,pythonString,pythonComment skipwhite syn keyword pythonRepeat for while - syn keyword pythonConditional if elif else + syn keyword pythonConditional if elif else match case syn keyword pythonInclude import from syn keyword pythonException try except finally syn keyword pythonOperator and in is not or @@ -114,6 +117,10 @@ endif syn match pythonExtraOperator "\%(=\)" endif + if g:pymode_syntax_highlight_walrus_operator + syn match pythonExtraOperator "\%(:=\)" + endif + if g:pymode_syntax_highlight_stars_operator syn match pythonExtraOperator "\%(\*\|\*\*\)" endif @@ -262,26 +269,29 @@ endif " Builtin objects and types if g:pymode_syntax_builtin_objs - syn keyword pythonBuiltinObj True False Ellipsis None NotImplemented - syn keyword pythonBuiltinObj __debug__ __doc__ __file__ __name__ __package__ + " True, False, Ellipsis, and None are in fact keywords. + syn keyword pythonBuiltinObj True False Ellipsis None + syn keyword pythonBuiltinObj NotImplemented + syn keyword pythonBuiltinObj __debug__ __doc__ __file__ __name__ __package__ __loader__ + syn keyword pythonBuiltinObj __spec__ __cached__ __annotations__ endif if g:pymode_syntax_builtin_types syn keyword pythonBuiltinType type object - syn keyword pythonBuiltinType str basestring unicode buffer bytearray bytes chr unichr - syn keyword pythonBuiltinType dict int long bool float complex set frozenset list tuple - syn keyword pythonBuiltinType file super + syn keyword pythonBuiltinType str bytearray bytes chr + syn keyword pythonBuiltinType dict int bool float complex set frozenset list tuple + syn keyword pythonBuiltinType super endif " Builtin functions if g:pymode_syntax_builtin_funcs - syn keyword pythonBuiltinFunc __import__ abs all any apply - syn keyword pythonBuiltinFunc bin callable classmethod cmp coerce compile + syn keyword pythonBuiltinFunc __import__ abs all any + syn keyword pythonBuiltinFunc bin callable classmethod compile syn keyword pythonBuiltinFunc delattr dir divmod enumerate eval execfile filter syn keyword pythonBuiltinFunc format getattr globals locals hasattr hash help hex id - syn keyword pythonBuiltinFunc input intern isinstance issubclass iter len map max min - syn keyword pythonBuiltinFunc next oct open ord pow property range xrange - syn keyword pythonBuiltinFunc raw_input reduce reload repr reversed round setattr + syn keyword pythonBuiltinFunc input isinstance issubclass iter len map max min + syn keyword pythonBuiltinFunc next oct open ord pow property range + syn keyword pythonBuiltinFunc repr reversed round setattr syn keyword pythonBuiltinFunc slice sorted staticmethod sum vars zip if g:pymode_syntax_print_as_function @@ -292,31 +302,31 @@ endif " Builtin exceptions and warnings if g:pymode_syntax_highlight_exceptions - syn keyword pythonExClass BaseException - syn keyword pythonExClass Exception StandardError ArithmeticError - syn keyword pythonExClass LookupError EnvironmentError - syn keyword pythonExClass AssertionError AttributeError BufferError EOFError - syn keyword pythonExClass FloatingPointError GeneratorExit IOError - syn keyword pythonExClass ImportError IndexError KeyError - syn keyword pythonExClass KeyboardInterrupt MemoryError NameError + syn keyword pythonExClass BaseException Exception ArithmeticError + syn keyword pythonExClass BufferError LookupError + syn keyword pythonExClass AssertionError AttributeError EOFError + syn keyword pythonExClass FloatingPointError GeneratorExit + syn keyword pythonExClass ImportError ModuleNotFoundError IndexError + syn keyword pythonExClass KeyError KeyboardInterrupt MemoryError NameError syn keyword pythonExClass NotImplementedError OSError OverflowError - syn keyword pythonExClass ReferenceError RuntimeError StopIteration - syn keyword pythonExClass SyntaxError IndentationError TabError + syn keyword pythonExClass RecursionError ReferenceError RuntimeError StopIteration + syn keyword pythonExClass StopAsyncIteration SyntaxError IndentationError TabError syn keyword pythonExClass SystemError SystemExit TypeError syn keyword pythonExClass UnboundLocalError UnicodeError syn keyword pythonExClass UnicodeEncodeError UnicodeDecodeError - syn keyword pythonExClass UnicodeTranslateError ValueError VMSError + syn keyword pythonExClass UnicodeTranslateError ValueError + syn keyword pythonExClass ZeroDivisionError EnvironmentError IOError + syn keyword pythonExClass WindowsError syn keyword pythonExClass BlockingIOError ChildProcessError ConnectionError syn keyword pythonExClass BrokenPipeError ConnectionAbortedError syn keyword pythonExClass ConnectionRefusedError ConnectionResetError syn keyword pythonExClass FileExistsError FileNotFoundError InterruptedError syn keyword pythonExClass IsADirectoryError NotADirectoryError PermissionError syn keyword pythonExClass ProcessLookupError TimeoutError - syn keyword pythonExClass WindowsError ZeroDivisionError - syn keyword pythonExClass Warning UserWarning BytesWarning DeprecationWarning - syn keyword pythonExClass PendingDepricationWarning SyntaxWarning - syn keyword pythonExClass RuntimeWarning FutureWarning - syn keyword pythonExClass ImportWarning UnicodeWarning + syn keyword pythonExClass Warning UserWarning DeprecationWarning PendingDeprecationWarning + syn keyword pythonExClass SyntaxWarning RuntimeWarning FutureWarning + syn keyword pythonExClass ImportWarning UnicodeWarning EncodingWarning + syn keyword pythonExClass BytesWarning ResourceWarning endif " }}} diff --git a/tests/test.sh b/tests/test.sh index b7747308..eb4ec018 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -4,7 +4,7 @@ set -e which vim 1>/dev/null 2>/dev/null -cd $(dirname $0) +cd "$(dirname "$0")" # Source common variables. source ./test_helpers_bash/test_variables.sh @@ -20,39 +20,39 @@ declare -a TEST_ARRAY=( "./test_bash/test_autopep8.sh" "./test_bash/test_autocommands.sh" "./test_bash/test_folding.sh" + "./test_bash/test_textobject.sh" ) +MAIN_RETURN=0 ## now loop through the above array set +e -for ONE_TEST in "${TEST_ARRAY[@]}" +for TEST in "${TEST_ARRAY[@]}" do - echo "Starting test: $ONE_TEST" >> $VIM_OUTPUT_FILE - bash -x "$ONE_TEST" - echo -e "\n$ONE_TEST: Return code: $?" >> $VIM_OUTPUT_FILE + echo "Starting test: ${TEST}" | tee -a "${VIM_OUTPUT_FILE}" + bash "${TEST}" + R=$? + MAIN_RETURN=$(( MAIN_RETURN + R )) + echo -e "${TEST}: Return code: ${R}\n" | tee -a "${VIM_OUTPUT_FILE}" bash ./test_helpers_bash/test_prepare_between_tests.sh done -# Show errors: -E1=$(grep -E "^E[0-9]+:" $VIM_OUTPUT_FILE) -E2=$(grep -E "^Error" $VIM_OUTPUT_FILE) -E3="$E1\n$E2" -if [ "$E3" = "\n" ] -then - echo "No errors." -else - echo "Errors:" - echo -e "$E3\n" -fi +echo "=========================================================================" +echo " RESULTS" +echo "=========================================================================" # Show return codes. -RETURN_CODES=$(cat $VIM_OUTPUT_FILE | grep -i "Return code") +RETURN_CODES=$(grep -i "Return code" < "${VIM_OUTPUT_FILE}" | grep -v "Return code: 0") echo -e "${RETURN_CODES}" -# Exit the script with error if there are any return codes different from 0. -if echo $RETURN_CODES | grep -E "Return code: [1-9]" 1>/dev/null 2>/dev/null -then - exit 1 +# Show errors: +E1=$(grep -E "^E[0-9]+:" "${VIM_OUTPUT_FILE}") +E2=$(grep -Ei "^Error" "${VIM_OUTPUT_FILE}") +if [[ "${MAIN_RETURN}" == "0" ]]; then + echo "No errors." else - exit 0 + echo "Errors:" + echo -e "${E1}\n${E2}" fi +# Exit the script with error if there are any return codes different from 0. +exit ${MAIN_RETURN} # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_bash/test_autocommands.sh b/tests/test_bash/test_autocommands.sh index 13708c30..89d8a70d 100644 --- a/tests/test_bash/test_autocommands.sh +++ b/tests/test_bash/test_autocommands.sh @@ -15,20 +15,24 @@ declare -a TEST_PYMODE_COMMANDS_ARRAY=( ### FOR PINPOINT TESTING ### "./test_procedures_vimscript/pymoderun.vim" ### FOR PINPOINT TESTING ### ) +RETURN_CODE=0 + ## now loop through the above array set +e for ONE_PYMODE_COMMANDS_TEST in "${TEST_PYMODE_COMMANDS_ARRAY[@]}" do - echo "Starting test: $0:$ONE_PYMODE_COMMANDS_TEST" >> $VIM_OUTPUT_FILE - RETURN_CODE=$(vim -i NONE -u $VIM_TEST_VIMRC -c "source $ONE_PYMODE_COMMANDS_TEST" $VIM_DISPOSABLE_PYFILE > /dev/null 2>&1) + CONTENT="$(vim --clean -i NONE -u "${VIM_TEST_VIMRC}" -c "source ${ONE_PYMODE_COMMANDS_TEST}" "${VIM_DISPOSABLE_PYFILE}" 2>&1)" ### Enable the following to execute one test at a time. - ### FOR PINPOINT TESTING ### vim -i NONE -u $VIM_TEST_VIMRC -c "source $ONE_PYMODE_COMMANDS_TEST" $VIM_DISPOSABLE_PYFILE + ### FOR PINPOINT TESTING ### vim --clean -i NONE -u $VIM_TEST_VIMRC -c "source $ONE_PYMODE_COMMANDS_TEST" $VIM_DISPOSABLE_PYFILE ### FOR PINPOINT TESTING ### exit 1 - RETURN_CODE=$? - echo -e "\n$0:$ONE_PYMODE_COMMANDS_TEST: Return code: $RETURN_CODE" >> $VIM_OUTPUT_FILE + SUB_TEST_RETURN_CODE=$? + echo -e "${CONTENT}" >> "${VIM_OUTPUT_FILE}" + RETURN_CODE=$(( RETURN_CODE + SUB_TEST_RETURN_CODE )) + echo -e "\tSubTest: $0:${ONE_PYMODE_COMMANDS_TEST}: Return code: ${SUB_TEST_RETURN_CODE}" | tee -a "${VIM_OUTPUT_FILE}" bash ./test_helpers_bash/test_prepare_between_tests.sh done +exit ${RETURN_CODE} # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_bash/test_autopep8.sh b/tests/test_bash/test_autopep8.sh index eae173f3..2a70072a 100644 --- a/tests/test_bash/test_autopep8.sh +++ b/tests/test_bash/test_autopep8.sh @@ -2,9 +2,10 @@ # Source file. set +e -RETURN_CODE=$(vim -i NONE -u $VIM_TEST_VIMRC -c "source ./test_procedures_vimscript/autopep8.vim" $VIM_DISPOSABLE_PYFILE > /dev/null 2>&1) +CONTENT="$(vim --clean -i NONE -u "${VIM_TEST_VIMRC}" -c "source ./test_procedures_vimscript/autopep8.vim" "${VIM_DISPOSABLE_PYFILE}" 2>&1)" RETURN_CODE=$? +echo -e "${CONTENT}" >> "${VIM_OUTPUT_FILE}" set -e -exit $RETURN_CODE +exit ${RETURN_CODE} # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_bash/test_folding.sh b/tests/test_bash/test_folding.sh index 2902ef8d..60e60c42 100644 --- a/tests/test_bash/test_folding.sh +++ b/tests/test_bash/test_folding.sh @@ -2,35 +2,24 @@ # Note: a solution with unix 'timeout' program was tried but it was unsuccessful. The problem with folding 4 is that in the case of a crash one expects the folding to just stay in an infinite loop, thus never existing with error. An improvement is suggested to this case. -# Source file. -set +e -source ./test_helpers_bash/test_prepare_between_tests.sh -vim -i NONE -u $VIM_TEST_VIMRC -c "source ./test_procedures_vimscript/folding1.vim" $VIM_DISPOSABLE_PYFILE > /dev/null -R1=$? -source ./test_helpers_bash/test_prepare_between_tests.sh -vim -i NONE -u $VIM_TEST_VIMRC -c "source ./test_procedures_vimscript/folding2.vim" $VIM_DISPOSABLE_PYFILE > /dev/null -R2=$? -source ./test_helpers_bash/test_prepare_between_tests.sh -# TODO: enable folding3.vim script back. -# vim -i NONE -u $VIM_TEST_VIMRC -c "source ./test_procedures_vimscript/folding3.vim" $VIM_DISPOSABLE_PYFILE > /dev/null -# R3=$? -source ./test_helpers_bash/test_prepare_between_tests.sh -vim -i NONE -u $VIM_TEST_VIMRC -c "source ./test_procedures_vimscript/folding4.vim" $VIM_DISPOSABLE_PYFILE > /dev/null -R4=$? -set -e +declare -a TEST_PYMODE_FOLDING_TESTS_ARRAY=( + "./test_procedures_vimscript/folding1.vim" + "./test_procedures_vimscript/folding2.vim" + # "./test_procedures_vimscript/folding3.vim" + "./test_procedures_vimscript/folding4.vim" + ) + +RETURN_CODE=0 -if [[ "$R1" -ne 0 ]] -then - exit 1 -elif [[ "$R2" -ne 0 ]] -then - exit 2 -# elif [[ "$R3" -ne 0 ]] -# then -# exit 3 -elif [[ "$R4" -ne 0 ]] -then - exit 4 -fi +set +e +for SUB_TEST in "${TEST_PYMODE_FOLDING_TESTS_ARRAY[@]}"; do + CONTENT="$(vim --clean -i NONE -u "${VIM_TEST_VIMRC}" -c "source ${SUB_TEST}" "${VIM_DISPOSABLE_PYFILE}" 2>&1)" + SUB_TEST_RETURN_CODE=$? + echo -e "${CONTENT}" >> "${VIM_OUTPUT_FILE}" + RETURN_CODE=$(( RETURN_CODE + SUB_TEST_RETURN_CODE )) + echo -e "\tSubTest: $0:${SUB_TEST}: Return code: ${SUB_TEST_RETURN_CODE}" | tee -a "${VIM_OUTPUT_FILE}" + bash ./test_helpers_bash/test_prepare_between_tests.sh +done +exit ${RETURN_CODE} # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_bash/test_pymodelint.sh b/tests/test_bash/test_pymodelint.sh index cf8d626d..9f903955 100644 --- a/tests/test_bash/test_pymodelint.sh +++ b/tests/test_bash/test_pymodelint.sh @@ -5,10 +5,11 @@ # Source file. set +e -vim -i NONE -u $VIM_TEST_VIMRC -c "source ./test_procedures_vimscript/pymodelint.vim" $VIM_DISPOSABLE_PYFILE -# RETURN_CODE=$(vim -i NONE -u $VIM_TEST_VIMRC -c "source ./test_procedures_vimscript/pymodeversion.vim" $VIM_DISPOSABLE_PYFILE > /dev/null 2>&1) -# RETURN_CODE=$? +# vim --clean -i NONE -u "${VIM_TEST_VIMRC}" -c "source ./test_procedures_vimscript/pymodelint.vim" "${VIM_DISPOSABLE_PYFILE}" >> "${VIM_OUTPUT_FILE}" 2>&1 +CONTENT="$(vim --clean -i NONE -u "${VIM_TEST_VIMRC}" -c "source ./test_procedures_vimscript/pymodeversion.vim" "${VIM_DISPOSABLE_PYFILE}" 2>&1)" +RETURN_CODE=$? +echo -e "${CONTENT}" >> "${VIM_OUTPUT_FILE}" set -e -# exit $RETURN_CODE +exit ${RETURN_CODE} # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_bash/test_textobject.sh b/tests/test_bash/test_textobject.sh new file mode 100644 index 00000000..cf90c87a --- /dev/null +++ b/tests/test_bash/test_textobject.sh @@ -0,0 +1,13 @@ +#! /bin/bash + +# Source file. +set +e +# shellcheck source=../test_helpers_bash/test_prepare_between_tests.sh +source ./test_helpers_bash/test_prepare_between_tests.sh +CONTENT="$(vim --clean -i NONE -u "${VIM_TEST_VIMRC}" -c "source ./test_procedures_vimscript/textobject.vim" "${VIM_DISPOSABLE_PYFILE}" 2>&1)" +RETURN_CODE=$? +echo -e "${CONTENT}" >> "${VIM_OUTPUT_FILE}" +set -e + +exit ${RETURN_CODE} +# vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_helpers_bash/test_createvimrc.sh b/tests/test_helpers_bash/test_createvimrc.sh index ae763b95..d816df98 100644 --- a/tests/test_helpers_bash/test_createvimrc.sh +++ b/tests/test_helpers_bash/test_createvimrc.sh @@ -1,26 +1,27 @@ #! /bin/bash # Create minimal vimrc. -echo -e "syntax on\nfiletype plugin indent on\nset nocompatible" >> $VIM_TEST_VIMRC -echo "call has('python3')" >> $VIM_TEST_VIMRC -echo "set paste" >> $VIM_TEST_VIMRC -echo "set shortmess=at" >> $VIM_TEST_VIMRC -echo "set cmdheight=10" >> $VIM_TEST_VIMRC -echo "set ft=python" >> $VIM_TEST_VIMRC -echo "set shell=bash" >> $VIM_TEST_VIMRC -echo "set noswapfile" >> $VIM_TEST_VIMRC -echo "set backupdir=" >> $VIM_TEST_VIMRC -echo "set undodir=" >> $VIM_TEST_VIMRC -echo "set viewdir=" >> $VIM_TEST_VIMRC -echo "set directory=" >> $VIM_TEST_VIMRC -echo -e "set runtimepath=" >> $VIM_TEST_VIMRC -echo -e "set runtimepath+=$(dirname $PWD)\n" >> $VIM_TEST_VIMRC -echo -e "set packpath+=/tmp\n" >> $VIM_TEST_VIMRC -# echo -e "redir! >> $VIM_OUTPUT_FILE\n" >> $VIM_TEST_VIMRC -echo -e "set verbosefile=$VIM_OUTPUT_FILE\n" >> $VIM_TEST_VIMRC -echo -e "let g:pymode_debug = 1" >> $VIM_TEST_VIMRC - -echo "set nomore" >> $VIM_TEST_VIMRC - - +cat <<-EOF >> "${VIM_TEST_VIMRC}" + syntax on + filetype plugin indent on + set nocompatible + call has('python3') + set paste + set shortmess=at + set cmdheight=10 + set ft=python + set shell=bash + set noswapfile + set backupdir= + set undodir= + set viewdir= + set directory= + set runtimepath= + set runtimepath+="$(dirname "${PWD}")" + set packpath+=/tmp + " redir! >> "${VIM_OUTPUT_FILE}" + set verbosefile="${VIM_OUTPUT_FILE}" + let g:pymode_debug = 1 + set nomore +EOF # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_helpers_bash/test_prepare_between_tests.sh b/tests/test_helpers_bash/test_prepare_between_tests.sh index cdce9869..7a8f52e7 100644 --- a/tests/test_helpers_bash/test_prepare_between_tests.sh +++ b/tests/test_helpers_bash/test_prepare_between_tests.sh @@ -2,11 +2,12 @@ # Prepare tests. set +e -if [ -f $VIM_DISPOSABLE_PYFILE ]; then - rm $VIM_DISPOSABLE_PYFILE +if [ -f "${VIM_DISPOSABLE_PYFILE}" ]; then + rm "${VIM_DISPOSABLE_PYFILE}" fi -export VIM_DISPOSABLE_PYFILE=`mktemp /tmp/pymode.tmpfile.XXXXXXXXXX.py` +VIM_DISPOSABLE_PYFILE="$(mktemp /tmp/pymode.tmpfile.XXXXXXXXXX.py)" +export VIM_DISPOSABLE_PYFILE set -e -touch $VIM_DISPOSABLE_PYFILE +touch "${VIM_DISPOSABLE_PYFILE}" # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_helpers_bash/test_prepare_once.sh b/tests/test_helpers_bash/test_prepare_once.sh index dad77182..da986b53 100644 --- a/tests/test_helpers_bash/test_prepare_once.sh +++ b/tests/test_helpers_bash/test_prepare_once.sh @@ -2,11 +2,11 @@ # Prepare tests. set +e -rm $VIM_OUTPUT_FILE $VIM_TEST_VIMRC $VIM_TEST_PYMODECOMMANDS $VIM_DISPOSABLE_PYFILE 2&>/dev/null +rm "${VIM_OUTPUT_FILE}" "${VIM_TEST_VIMRC}" "${VIM_TEST_PYMODECOMMANDS}" "${VIM_DISPOSABLE_PYFILE}" 2&>/dev/null rm /tmp/*pymode* 2&>/dev/null rm -rf /tmp/pack mkdir -p /tmp/pack/test_plugins/start -ln -s $(dirname $(pwd)) /tmp/pack/test_plugins/start/ +ln -s "$(dirname "$(pwd)")" /tmp/pack/test_plugins/start/ set -e # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_helpers_bash/test_variables.sh b/tests/test_helpers_bash/test_variables.sh index 53edb5e5..f1995022 100644 --- a/tests/test_helpers_bash/test_variables.sh +++ b/tests/test_helpers_bash/test_variables.sh @@ -3,9 +3,13 @@ # Define variables for common test scripts. # Set variables. -export VIM_DISPOSABLE_PYFILE=`mktemp /tmp/pymode.tmpfile.XXXXXXXXXX.py` -export VIM_OUTPUT_FILE=/tmp/pymode.out -export VIM_TEST_VIMRC=/tmp/pymode_vimrc -export VIM_TEST_PYMODECOMMANDS=/tmp/pymode_commands.txt +VIM_DISPOSABLE_PYFILE="$(mktemp /tmp/pymode.tmpfile.XXXXXXXXXX.py)" +export VIM_DISPOSABLE_PYFILE +VIM_OUTPUT_FILE=/tmp/pymode.out +export VIM_OUTPUT_FILE +VIM_TEST_VIMRC=/tmp/pymode_vimrc +export VIM_TEST_VIMRC +VIM_TEST_PYMODECOMMANDS=/tmp/pymode_commands.txt +export VIM_TEST_PYMODECOMMANDS # vim: set fileformat=unix filetype=sh wrap tw=0 : diff --git a/tests/test_procedures_vimscript/textobject.vim b/tests/test_procedures_vimscript/textobject.vim new file mode 100644 index 00000000..cbd4ef05 --- /dev/null +++ b/tests/test_procedures_vimscript/textobject.vim @@ -0,0 +1,83 @@ +set noautoindent +let g:pymode_rope=1 + +" Load sample python file. +" With 'def'. +execute "normal! idef func1():\ a = 1\" +execute "normal! idef func2():\ b = 2" +normal 3ggdaMggf(P + +" Assert changes. +let content=getline('^', '$') +call assert_true(content == ['def func2():', ' b = 2', 'def func1():', ' a = 1']) + + +" Clean file. +%delete + +" With 'class'. +execute "normal! iclass Class1():\ a = 1\" +execute "normal! iclass Class2():\ b = 2\" +normal 3ggdaCggf(P + +" Assert changes. +let content=getline('^', '$') +call assert_true(content == ['class Class2():', ' b = 2', '', 'class Class1():', ' a = 1']) + + +" Clean file. +%delete + +" With 'def'. +execute "normal! iprint(\ 1\)\" +execute "normal! iprint(\ 2\)\" +execute "normal! iprint(\ 3\)\" +normal 4ggdV + +let content=getline('^', '$') +call assert_true(content == [ +\ "print(", " 1", ")", +\ "print(", " 3", ")", +\ "" +\]) + + +" Clean file. +%delete + +" With 'def'. +execute "normal! iprint(\ 1\)\" +execute "normal! iprint(\ 2\)\" +execute "normal! iprint(\ 3\)\" +execute "normal! iprint(\ 4\)\" +normal 5ggd2V + +let content=getline('^', '$') +call assert_true(content == [ +\ "print(", " 1", ")", +\ "print(", " 4", ")", +\ "" +\]) + +" Clean file. +%delete + +" With 'def'. +execute "normal! iprint(\ 1\)\" +execute "normal! iprint(\ 2\)\" +execute "normal! iprint(\ 3\)\" +execute "normal! iprint(\ 4\)\" +normal 5ggd2V + +let content=getline('^', '$') +call assert_true(content == [ +\ "print(", " 1", ")", +\ "print(", " 4", ")", +\ "" +\]) + +if len(v:errors) > 0 + cquit! +else + quit! +endif diff --git a/tests/utils/pymoderc b/tests/utils/pymoderc index 222c6ceb..3a8477ea 100644 --- a/tests/utils/pymoderc +++ b/tests/utils/pymoderc @@ -25,7 +25,7 @@ let g:pymode_lint_on_write = 1 let g:pymode_lint_unmodified = 0 let g:pymode_lint_on_fly = 0 let g:pymode_lint_message = 1 -let g:pymode_lint_checkers = ['pyflakes', 'pep8', 'mccabe'] +let g:pymode_lint_checkers = ['pyflakes', 'pycodestyle', 'mccabe'] let g:pymode_lint_ignore = ["E501", "W",] let g:pymode_lint_select = ["E501", "W0011", "W430"] let g:pymode_lint_sort = [] @@ -37,7 +37,7 @@ let g:pymode_lint_visual_symbol = 'RR' let g:pymode_lint_error_symbol = 'EE' let g:pymode_lint_info_symbol = 'II' let g:pymode_lint_pyflakes_symbol = 'FF' -let g:pymode_lint_options_pep8 = +let g:pymode_lint_options_pycodestyle = \ {'max_line_length': g:pymode_options_max_line_length} let g:pymode_lint_options_pyflakes = { 'builtins': '_' } let g:pymode_lint_options_mccabe = { 'complexity': 12 }