dotfiles

configuration files for shell, text editor, graphical environment, etc.
git clone git://src.adamsgaard.dk/dotfiles
Log | Files | Refs | README | LICENSE Back to index

commit 70395d6fd99c3d522e92447b2b5ed09b33965102
parent 5b221339430cb273bedceb969e9fef71c5e09494
Author: Anders Damsgaard <adc@cs.au.dk>
Date:   Tue,  4 Jun 2013 22:48:02 +0200

Removed python-mode vim plugin

Diffstat:
M.vim/bundle/clone-repos.sh | 2+-
D.vim/bundle/python-mode/.gitignore | 8--------
D.vim/bundle/python-mode/Changelog.rst | 238-------------------------------------------------------------------------------
D.vim/bundle/python-mode/Makefile | 3---
D.vim/bundle/python-mode/README.rst | 528-------------------------------------------------------------------------------
D.vim/bundle/python-mode/after/ftplugin/pyrex.vim | 1-
D.vim/bundle/python-mode/after/ftplugin/python.vim | 43-------------------------------------------
D.vim/bundle/python-mode/after/indent/pyrex.vim | 1-
D.vim/bundle/python-mode/after/indent/python.vim | 14--------------
D.vim/bundle/python-mode/autoload/pymode.vim | 196-------------------------------------------------------------------------------
D.vim/bundle/python-mode/autoload/pymode/breakpoint.vim | 14--------------
D.vim/bundle/python-mode/autoload/pymode/doc.vim | 19-------------------
D.vim/bundle/python-mode/autoload/pymode/folding.vim | 60------------------------------------------------------------
D.vim/bundle/python-mode/autoload/pymode/indent.vim | 184-------------------------------------------------------------------------------
D.vim/bundle/python-mode/autoload/pymode/lint.vim | 108-------------------------------------------------------------------------------
D.vim/bundle/python-mode/autoload/pymode/motion.vim | 61-------------------------------------------------------------
D.vim/bundle/python-mode/autoload/pymode/queue.vim | 15---------------
D.vim/bundle/python-mode/autoload/pymode/run.vim | 45---------------------------------------------
D.vim/bundle/python-mode/autoload/pymode/troubleshooting.vim | 87-------------------------------------------------------------------------------
D.vim/bundle/python-mode/autoload/pymode/virtualenv.vim | 31-------------------------------
D.vim/bundle/python-mode/doc/pymode.txt | 558-------------------------------------------------------------------------------
D.vim/bundle/python-mode/doc/ropevim.txt | 340-------------------------------------------------------------------------------
D.vim/bundle/python-mode/ftplugin/pyrex.vim | 1-
D.vim/bundle/python-mode/ftplugin/python/init-pymode.vim | 344-------------------------------------------------------------------------------
D.vim/bundle/python-mode/ftplugin/python/pymode.vim | 156-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/__init__.py | 0
D.vim/bundle/python-mode/pylibs/autopep8.py | 2161-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/__init__.py | 8--------
D.vim/bundle/python-mode/pylibs/pylama/hook.py | 88-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/main.py | 205-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/mccabe.py | 312-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pep8.py | 1852-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pyflakes/__init__.py | 2--
D.vim/bundle/python-mode/pylibs/pylama/pyflakes/checker.py | 738-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pyflakes/messages.py | 113-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint.rc | 25-------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/__init__.py | 45---------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/__pkginfo__.py | 70----------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/__init__.py | 163-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/base.py | 851-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/classes.py | 662-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/design_analysis.py | 407-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/exceptions.py | 213-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/format.py | 476-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/imports.py | 392-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/logging.py | 179-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/misc.py | 78------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/newstyle.py | 112-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/raw_metrics.py | 125-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/similar.py | 357-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/string_format.py | 163-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/typecheck.py | 387-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/utils.py | 373-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/variables.py | 588-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/config.py | 152-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/interfaces.py | 98-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/lint.py | 1046-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/__init__.py | 0
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/__init__.py | 78------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/__pkginfo__.py | 52----------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/as_string.py | 427-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/bases.py | 631-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/__init__.py | 0
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2mechanize.py | 20--------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2qt4.py | 25-------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2stdlib.py | 176-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/builder.py | 226-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/exceptions.py | 60------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/inference.py | 383-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/manager.py | 299-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/mixins.py | 136-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/node_classes.py | 908-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/nodes.py | 75---------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/protocols.py | 321-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/raw_building.py | 353-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/rebuilder.py | 886-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/scoped_nodes.py | 981-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/utils.py | 241-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/__init__.py | 171-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/__pkginfo__.py | 53-----------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/changelog.py | 236-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/compat.py | 243-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/configuration.py | 1078-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/decorators.py | 283-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/deprecation.py | 188-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/graph.py | 273-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/interface.py | 71-----------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/modutils.py | 658-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/optik_ext.py | 397-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/textutils.py | 534-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/tree.py | 369-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/__init__.py | 174-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/docbook_writer.py | 139-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/html_writer.py | 131-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/nodes.py | 201-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/text_writer.py | 140-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/visitor.py | 107-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/__init__.py | 113-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/guireporter.py | 32--------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/html.py | 66------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/text.py | 147-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/pylint/utils.py | 602-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pylama/utils.py | 110-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pymode/__init__.py | 0
D.vim/bundle/python-mode/pylibs/pymode/auto.py | 18------------------
D.vim/bundle/python-mode/pylibs/pymode/interface.py | 25-------------------------
D.vim/bundle/python-mode/pylibs/pymode/lint.py | 64----------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/pymode/queue.py | 60------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/__init__.py | 17-----------------
D.vim/bundle/python-mode/pylibs/rope/base/__init__.py | 8--------
D.vim/bundle/python-mode/pylibs/rope/base/arguments.py | 109-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/ast.py | 71-----------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/astutils.py | 61-------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/builtins.py | 767-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/change.py | 448-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/codeanalyze.py | 358-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/default_config.py | 85-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/evaluate.py | 321-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/exceptions.py | 61-------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/fscommands.py | 267-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/history.py | 235-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/libutils.py | 65-----------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/__init__.py | 38--------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/doa.py | 162-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/memorydb.py | 106-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/objectdb.py | 175-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/objectinfo.py | 232-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/runmod.py | 211-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/soa.py | 136-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/soi.py | 186-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/oi/transform.py | 285-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/prefs.py | 41-----------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/project.py | 376-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/pycore.py | 410-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/pynames.py | 199-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/pynamesdef.py | 55-------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/pyobjects.py | 311-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/pyobjectsdef.py | 537-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/pyscopes.py | 313-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/resourceobserver.py | 271-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/resources.py | 211-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/simplify.py | 55-------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/stdmods.py | 40----------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/taskhandle.py | 133-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/utils.py | 78------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/base/worder.py | 524-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/__init__.py | 7-------
D.vim/bundle/python-mode/pylibs/rope/contrib/autoimport.py | 217-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/changestack.py | 52----------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/codeassist.py | 647-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/finderrors.py | 91-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/findit.py | 110-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/fixmodnames.py | 69---------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/fixsyntax.py | 178-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/contrib/generate.py | 355-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/__init__.py | 55-------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/change_signature.py | 342-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/encapsulate_field.py | 202-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/extract.py | 789-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/functionutils.py | 222-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/importutils/__init__.py | 299-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/importutils/actions.py | 359-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/importutils/importinfo.py | 201-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/importutils/module_imports.py | 455-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/inline.py | 615-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/introduce_factory.py | 133-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/introduce_parameter.py | 95-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/localtofield.py | 50--------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/method_object.py | 87-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/move.py | 629-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/multiproject.py | 78------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/occurrences.py | 334-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/patchedast.py | 734-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/rename.py | 216-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/restructure.py | 307-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/similarfinder.py | 362-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/sourceutils.py | 92-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/suites.py | 142-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/topackage.py | 32--------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/usefunction.py | 171-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/rope/refactor/wildcards.py | 176-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/ropemode/__init__.py | 16----------------
D.vim/bundle/python-mode/pylibs/ropemode/decorators.py | 98-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/ropemode/dialog.py | 97-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/ropemode/environment.py | 104-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/ropemode/filter.py | 39---------------------------------------
D.vim/bundle/python-mode/pylibs/ropemode/interface.py | 706-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/ropemode/refactor.py | 494-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylibs/ropemode/tests/__init__.py | 0
D.vim/bundle/python-mode/pylibs/ropemode/tests/decorators_test.py | 48------------------------------------------------
D.vim/bundle/python-mode/pylibs/ropevim.py | 453-------------------------------------------------------------------------------
D.vim/bundle/python-mode/pylint.ini | 25-------------------------
D.vim/bundle/python-mode/syntax/pyrex.vim | 71-----------------------------------------------------------------------
D.vim/bundle/python-mode/syntax/python.vim | 298-------------------------------------------------------------------------------
194 files changed, 1 insertion(+), 47768 deletions(-)

diff --git a/.vim/bundle/clone-repos.sh b/.vim/bundle/clone-repos.sh @@ -3,4 +3,4 @@ git clone git://github.com/Lokaltog/vim-powerline.git git clone git://github.com/scrooloose/nerdtree.git git clone git://github.com/scrooloose/syntastic.git git clone git://github.com/kien/ctrlp.vim.git -git clone git://github.com/klen/python-mode.git +#git clone git://github.com/klen/python-mode.git diff --git a/.vim/bundle/python-mode/.gitignore b/.vim/bundle/python-mode/.gitignore @@ -1,8 +0,0 @@ -*.py[cod] -.vimrc -*.sw? -*~ -.DS_Store -.ropeproject -tags -todo.txt diff --git a/.vim/bundle/python-mode/Changelog.rst b/.vim/bundle/python-mode/Changelog.rst @@ -1,238 +0,0 @@ -Changelog -========= - -## 2013-04-01 0.6.15 --------------------- -* Bugfix release - -## 2013-03-16 0.6.14 --------------------- -* Update `PEP8` to version 1.4.5; -* Update `Pylint` to version 0.27.0; -* Update `pyflakes` to version 0.6.1; -* Update `autopep8` to version 0.8.7; -* Fix breakpoint definition; -* Update python syntax; -* Fixed run-time error when output non-ascii in multibyte locale; -* Move initialization into ftplugin as it is python specific; -* Pyrex (Cython) files support; -* Support `raw_input` in run python code; - -## 2012-09-07 0.6.10 --------------------- -* Dont raise an exception when Logger has no message handler (c) nixon -* Improve performance of white space removal (c) Dave Smith -* Improve ropemode support (c) s0undt3ch -* Add `g:pymode_updatetime` option -* Update autopep8 to version 0.8.1 - -## 2012-09-07 0.6.9 -------------------- -* Update autopep8 -* Improve pymode#troubleshooting#Test() - -## 2012-09-06 0.6.8 -------------------- -* Add PEP8 indentation ":help 'pymode_indent'" - -## 2012-08-15 0.6.7 -------------------- -* Fix documentation. Thanks (c) bgrant; -* Fix pymode "async queue" support. - -## 2012-08-02 0.6.6 -------------------- -* Updated Pep8 to version 1.3.3 -* Updated Pylint to version 0.25.2 -* Fixed virtualenv support for windows users -* Added pymode modeline ':help PythonModeModeline' -* Added diagnostic tool ':call pymode#troubleshooting#Test()' -* Added `PyLintAuto` command ':help PyLintAuto' -* Code checking is async operation now -* More, more fast the pymode folding -* Repaired execution of python code - -## 2012-05-24 0.6.4 -------------------- -* Add 'pymode_paths' option -* Rope updated to version 0.9.4 - -## 2012-04-18 0.6.3 -------------------- -* Fix pydocs integration - -## 2012-04-10 0.6.2 -------------------- -* Fix pymode_run for "unnamed" clipboard -* Add 'pymode_lint_mccabe_complexity' option -* Update Pep8 to version 1.0.1 -* Warning! Change 'pymode_rope_goto_def_newwin' option - for open "goto definition" in new window, set it to 'new' or 'vnew' - for horizontally or vertically split - If you use default behaviour (in the same buffer), not changes needed. - -## 2012-03-13 0.6.0 -------------------- -* Add 'pymode_lint_hold' option -* Improve pymode loading speed -* Add pep8, mccabe lint checkers -* Now g:pymode_lint_checker can have many values - Ex. "pep8,pyflakes,mccabe" -* Add 'pymode_lint_ignore' and 'pymode_lint_select' options -* Fix rope keys -* Fix python motion in visual mode -* Add folding 'pymode_folding' -* Warning: 'pymode_lint_checker' now set to 'pyflakes,pep8,mccabe' by default - -## 2012-02-12 0.5.8 -------------------- -* Fix pylint for Windows users -* Python documentation search running from Vim (delete g:pydoc option) -* Python code execution running from Vim (delete g:python option) - -## 2012-02-11 0.5.7 -------------------- -* Fix 'g:pymode_lint_message' mode error -* Fix breakpoints -* Fix python paths and virtualenv detection - -## 2012-02-06 0.5.6 -------------------- -* Fix 'g:pymode_syntax' option -* Show error message in bottom part of screen - see 'g:pymode_lint_message' -* Fix pylint for windows users -* Fix breakpoint command (Use pdb when idpb not installed) - -## 2012-01-17 0.5.5 -------------------- -* Add a sign for info messages from pylint. - (c) Fredrik Henrysson -* Change motion keys: vic - viC, dam - daM and etc -* Add 'g:pymode_lint_onfly' option - -## 2012-01-09 0.5.3 -------------------- -* Prevent the configuration from breaking python-mode - (c) Dirk Wallenstein - -## 2012-01-08 0.5.2 -------------------- -* Fix ropeomnicompletion -* Add preview documentation - -## 2012-01-06 0.5.1 -------------------- -* Happy new year! -* Objects and motion fixes - -## 2011-11-30 0.5.0 -------------------- -* Add python objects and motions (beta) - :h pymode_motion - -## 2011-11-27 0.4.8 -------------------- -* Add `PyLintWindowToggle` command -* Fix some bugs - -## 2011-11-23 0.4.6 -------------------- -* Enable all syntax highlighting - For old settings set in your vimrc: - let g:pymode_syntax_builtin_objs = 0 - let g:pymode_syntax_builtin_funcs = 0 - -* Change namespace of syntax variables - See README - -## 2011-11-18 0.4.5 -------------------- -* Add 'g:pymode_syntax' option -* Highlight 'self' keyword - -## 2011-11-16 0.4.4 -------------------- -* Minor fixes - -## 2011-11-11 0.4.3 -------------------- -* Fix pyflakes - -## 2011-11-09 0.4.2 -------------------- -* Add FAQ -* Some refactoring and fixes - -## 2011-11-08 0.4.0 -------------------- -* Add alternative code checker "pyflakes" - See :h 'pymode_lint_checker' -* Update install docs - -## 2011-10-30 0.3.3 -------------------- -* Fix RopeShowDoc - -## 2011-10-28 0.3.2 -------------------- -* Add 'g:pymode_options_*' stuff, for ability - to disable default pymode options for python buffers - -## 2011-10-27 0.3.1 -------------------- -* Add 'g:pymode_rope_always_show_complete_menu' option -* Some pylint fixes - -## 2011-10-25 0.3.0 -------------------- -* Add g:pymode_lint_minheight and g:pymode_lint_maxheight - options -* Fix PyLintToggle -* Fix Rope and PyLint libs loading - -## 2011-10-21 0.2.12 --------------------- -* Auto open cwindow with results - on rope find operations - -## 2011-10-20 0.2.11 --------------------- -* Add 'pymode_lint_jump' option - -## 2011-10-19 0.2.10 --------------------- -* Minor fixes (virtualenv loading, buffer commands) - -## 2011-10-18 0.2.6 -------------------- -* Add <C-space> shortcut for macvim users. -* Add VIRTUALENV support - -## 2011-10-17 0.2.4 -------------------- -* Add current work path to sys.path -* Add 'g:pymode' option (disable/enable pylint and rope) -* Fix pylint copyright -* Hotfix rope autocomplete - -## 2011-10-15 0.2.1 -------------------- -* Change rope variables (ropevim_<name> -> pymode_rope_<name>) -* Add "pymode_rope_auto_project" option (default: 1) -* Update and fix docs -* 'pymode_rope_extended_complete' set by default -* Auto generate rope project and cache -* "<C-c>r a" for RopeAutoImport - -## 2011-10-12 0.1.4 -------------------- -* Add default pylint configuration - -## 2011-10-12 0.1.3 -------------------- -* Fix pylint and update docs - -## 2011-10-11 0.1.2 -------------------- -* First public release diff --git a/.vim/bundle/python-mode/Makefile b/.vim/bundle/python-mode/Makefile @@ -1,3 +0,0 @@ -.PHONY: clean -clean: - find . -name "*.pyc" -delete diff --git a/.vim/bundle/python-mode/README.rst b/.vim/bundle/python-mode/README.rst @@ -1,528 +0,0 @@ -Python-mode, Python in VIM -########################## - -Python-mode is a vim plugin that allows you to use the pylint_, rope_, pydoc_, pyflakes_, pep8_, mccabe_ libraries in vim to provide -features like python code looking for bugs, refactoring and some other useful things. - -This plugin allow you create python code in vim very easily. -There is no need to install the pylint_, rope_ or any used python library on your system. - -- Python objects and motion (]], 3[[, ]]M, vaC, viM, daC, ciM, ...) -- Folding of python code -- Virtualenv support -- Highlight syntax errors -- Highlight and auto fix unused imports -- Many linters (pylint_, pyflakes_, ...) that can be run simultaneously -- Strong code completion -- Code refactoring -- Python documentation -- Run python code -- Go to definition -- Powerful customization -- And more, more ... - -See (very old) screencast here: http://t.co/3b0bzeXA (sorry for quality, this is my first screencast) -Another old presentation here: http://www.youtube.com/watch?v=YhqsjUUHj6g - - -.. contents:: - - -Changelog -========= - -## 2013-03-15 0.6.12 --------------------- -* Update `PEP8` to version 1.4.5; -* Update `Pylint` to version 0.27.0; -* Update `autopep8` to version 0.8.7; -* Fix breakpoint definition; -* Update python syntax; -* Fixed run-time error when output non-ascii in multibyte locale; -* Move initialization into ftplugin as it is python specific; -* Pyrex (Cython) files support; -* Support `raw_input` in run python code; - - -Requirements -============ - -- VIM >= 7.0 with python support - (also ``--with-features=big`` if you want use g:pymode_lint_signs) - - - -How to install -============== - - -Using pathogen_ (recomended) ----------------------------- -:: - - % cd ~/.vim - % mkdir -p bundle && cd bundle - % git clone git://github.com/klen/python-mode.git - -- Enable pathogen_ in your ``~/.vimrc``: :: - - " Pathogen load - filetype off - - call pathogen#infect() - call pathogen#helptags() - - filetype plugin indent on - syntax on - - -Manually --------- -:: - - % git clone git://github.com/klen/python-mode.git - % cd python-mode - % cp -R * ~/.vim - -Then rebuild **helptags** in vim:: - - :helptags ~/.vim/doc/ - - -.. note:: **filetype-plugin** (``:help filetype-plugin-on``) and **filetype-indent** (``:help filetype-indent-on``) - must be enabled for use python-mode. - - -Troubleshooting -=============== - -If your python-mode dont work, open any python file and type command: :: - - :call pymode#troubleshooting#Test() - -And fix warnings or copy output and send it to me (ex. with github issue). - - -Settings -======== - -.. note:: Also you can see vim help. ``:help PythonModeOptions`` - -To change this settings, edit your ``~/.vimrc``: :: - - " Disable pylint checking every save - let g:pymode_lint_write = 0 - - " Set key 'R' for run python code - let g:pymode_run_key = 'R' - - -Loading the Plugin ------------------- - -Default values: :: - - " Load the whole plugin - let g:pymode = 1 - - -Show documentation ------------------- - -Default values: :: - - " Load show documentation plugin - let g:pymode_doc = 1 - - " Key for show python documentation - let g:pymode_doc_key = 'K' - - -Run python code ---------------- - -Default values: :: - - " Load run code plugin - let g:pymode_run = 1 - - " Key for run python code - let g:pymode_run_key = '<leader>r' - - -Code checking -------------- - -Default values: :: - - " Load pylint code plugin - let g:pymode_lint = 1 - - " Switch pylint, pyflakes, pep8, mccabe code-checkers - " Can have multiply values "pep8,pyflakes,mcccabe" - let g:pymode_lint_checker = "pyflakes,pep8,mccabe" - - " Skip errors and warnings - " E.g. "E501,W002", "E2,W" (Skip all Warnings and Errors startswith E2) and etc - let g:pymode_lint_ignore = "E501" - - " Select errors and warnings - " E.g. "E4,W" - let g:pymode_lint_select = "" - - " Run linter on the fly - let g:pymode_lint_onfly = 0 - - " Pylint configuration file - " If file not found use 'pylintrc' from python-mode plugin directory - let g:pymode_lint_config = "$HOME/.pylintrc" - - " Check code every save - let g:pymode_lint_write = 1 - - " Auto open cwindow if errors be finded - let g:pymode_lint_cwindow = 1 - - " Show error message if cursor placed at the error line - let g:pymode_lint_message = 1 - - " Auto jump on first error - let g:pymode_lint_jump = 0 - - " Hold cursor in current window - " when quickfix is open - let g:pymode_lint_hold = 0 - - " Place error signs - let g:pymode_lint_signs = 1 - - " Maximum allowed mccabe complexity - let g:pymode_lint_mccabe_complexity = 8 - - " Minimal height of pylint error window - let g:pymode_lint_minheight = 3 - - " Maximal height of pylint error window - let g:pymode_lint_maxheight = 6 - - -.. note:: - Pylint options (ex. disable messages) may be defined in ``$HOME/pylint.rc`` - See pylint documentation: http://pylint-messages.wikidot.com/all-codes - - -Rope refactoring library ------------------------- - -Default values: :: - - " Load rope plugin - let g:pymode_rope = 1 - - " Auto create and open ropeproject - let g:pymode_rope_auto_project = 1 - - " Enable autoimport - let g:pymode_rope_enable_autoimport = 1 - - " Auto generate global cache - let g:pymode_rope_autoimport_generate = 1 - - let g:pymode_rope_autoimport_underlineds = 0 - - let g:pymode_rope_codeassist_maxfixes = 10 - - let g:pymode_rope_sorted_completions = 1 - - let g:pymode_rope_extended_complete = 1 - - let g:pymode_rope_autoimport_modules = ["os","shutil","datetime"] - - let g:pymode_rope_confirm_saving = 1 - - let g:pymode_rope_global_prefix = "<C-x>p" - - let g:pymode_rope_local_prefix = "<C-c>r" - - let g:pymode_rope_vim_completion = 1 - - let g:pymode_rope_guess_project = 1 - - let g:pymode_rope_goto_def_newwin = "" - - let g:pymode_rope_always_show_complete_menu = 0 - - -Automatically folding of python code --------------------------------------- - -Default values: :: - - " Enable python folding - let g:pymode_folding = 1 - - -Vim python motions and operators --------------------------------- - -Default values: :: - - " Enable python objects and motion - let g:pymode_motion = 1 - - -Virtualenv support ------------------- - -Default values: :: - - " Auto fix vim python paths if virtualenv enabled - let g:pymode_virtualenv = 1 - - -Other stuff ------------ - -Default values: :: - - " Additional python paths - let g:pymode_paths = [] - - " Load breakpoints plugin - let g:pymode_breakpoint = 1 - - " Key for set/unset breakpoint - let g:pymode_breakpoint_key = '<leader>b' - - " Autoremove unused whitespaces - let g:pymode_utils_whitespaces = 1 - - " Enable pymode indentation - let g:pymode_indent = 1 - - " Set default pymode python options - let g:pymode_options = 1 - - -Syntax highlight ----------------- - -Default values: :: - - " Enable pymode's custom syntax highlighting - let g:pymode_syntax = 1 - - " Enable all python highlightings - let g:pymode_syntax_all = 1 - - " Highlight "print" as function - let g:pymode_syntax_print_as_function = 0 - - " Highlight indentation errors - let g:pymode_syntax_indent_errors = g:pymode_syntax_all - - " Highlight trailing spaces - let g:pymode_syntax_space_errors = g:pymode_syntax_all - - " Highlight string formatting - let g:pymode_syntax_string_formatting = g:pymode_syntax_all - - " Highlight str.format syntax - let g:pymode_syntax_string_format = g:pymode_syntax_all - - " Highlight string.Template syntax - let g:pymode_syntax_string_templates = g:pymode_syntax_all - - " Highlight doc-tests - let g:pymode_syntax_doctests = g:pymode_syntax_all - - " Highlight builtin objects (__doc__, self, etc) - let g:pymode_syntax_builtin_objs = g:pymode_syntax_all - - " Highlight builtin functions - let g:pymode_syntax_builtin_funcs = g:pymode_syntax_all - - " Highlight exceptions - let g:pymode_syntax_highlight_exceptions = g:pymode_syntax_all - - " For fast machines - let g:pymode_syntax_slow_sync = 0 - - -Default keys -============ - -.. note:: Also you can see vim help ``:help PythonModeKeys`` - -============== ============= -Keys Command -============== ============= -**K** Show python docs (g:pymode_doc enabled) --------------- ------------- -**<C-Space>** Rope autocomplete (g:pymode_rope enabled) --------------- ------------- -**<C-c>g** Rope goto definition (g:pymode_rope enabled) --------------- ------------- -**<C-c>d** Rope show documentation (g:pymode_rope enabled) --------------- ------------- -**<C-c>f** Rope find occurrences (g:pymode_rope enabled) --------------- ------------- -**<Leader>r** Run python (g:pymode_run enabled) --------------- ------------- -**<Leader>b** Set, unset breakpoint (g:pymode_breakpoint enabled) --------------- ------------- -[[ Jump on previous class or function (normal, visual, operator modes) --------------- ------------- -]] Jump on next class or function (normal, visual, operator modes) --------------- ------------- -[M Jump on previous class or method (normal, visual, operator modes) --------------- ------------- -]M Jump on next class or method (normal, visual, operator modes) --------------- ------------- -aC C Select a class. Ex: vaC, daC, dC, yaC, yC, caC, cC (normal, operator modes) --------------- ------------- -iC Select inner class. Ex: viC, diC, yiC, ciC (normal, operator modes) --------------- ------------- -aM M Select a function or method. Ex: vaM, daM, dM, yaM, yM, caM, cM (normal, operator modes) --------------- ------------- -iM Select inner function or method. Ex: viM, diM, yiM, ciM (normal, operator modes) -============== ============= - -.. note:: See also ``:help ropevim.txt`` - - -Commands -======== - -.. note:: Also you can see vim help ``:help PythonModeCommands`` - -==================== ============= -Command Description -==================== ============= -:Pydoc <args> Show python documentation --------------------- ------------- -PyLintToggle Enable, disable pylint --------------------- ------------- -PyLintCheckerToggle Toggle code checker (pylint, pyflakes) --------------------- ------------- -PyLint Check current buffer --------------------- ------------- -PyLintAuto Automatic fix PEP8 errors --------------------- ------------- -Pyrun Run current buffer in python -==================== ============= - -.. note:: See also ``:help ropevim.txt`` - - -F.A.Q. -====== - -Rope completion is very slow ----------------------------- - -To work rope_ creates a service directory: ``.ropeproject``. -If ``g:pymode_rope_guess_project`` set (by default) and ``.ropeproject`` in current dir not found, rope scan ``.ropeproject`` on every dir in parent path. -If rope finded ``.ropeproject`` in parent dirs, rope set project for all child dir and scan may be slow for many dirs and files. - -Solutions: - -- Disable ``g:pymode_rope_guess_project`` to make rope always create ``.ropeproject`` in current dir. -- Delete ``.ropeproject`` from dip parent dir to make rope create ``.ropeproject`` in current dir. -- Press ``<C-x>po`` or ``:RopeOpenProject`` to make force rope create ``.ropeproject`` in current dir. - - - -Pylint check is very slow -------------------------- - -In some projects pylint_ may check slowly, because it also scan imported modules if posible. -Try use pyflakes_, see ``:h 'pymode_lint_checker'``. - -.. note:: You may ``set exrc`` and ``set secure`` in your ``vimrc`` for auto set custom settings from ``.vimrc`` from your projects directories. - Example: On Flask projects I automaticly set ``g:pymode_lint_checker = "pyflakes"``, on django ``g:pymode_lint_cheker = "pylint"`` - - -OSX cannot import urandom -------------------------- - -See: https://groups.google.com/forum/?fromgroups=#!topic/vim_dev/2NXKF6kDONo - -The sequence of commands that fixed this: :: - - brew unlink python - brew unlink macvim - brew remove macvim - brew install -v --force macvim - brew link macvim - brew link python - - -Bugtracker -=========== - -If you have any suggestions, bug reports or -annoyances please report them to the issue tracker -at https://github.com/klen/python-mode/issues - - -Contributing -============ - -Development of pylint-mode happens at github: https://github.com/klen/python-mode - - -Copyright -========= - -Copyright (C) 2012 Kirill Klenov (klen_) - - **Rope** - Copyright (C) 2006-2010 Ali Gholami Rudi - - Copyright (C) 2009-2010 Anton Gritsay - - **Pylint** - Copyright (C) 2003-2011 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ - - **Pyflakes**: - Copyright (c) 2005 Divmod, Inc. - http://www.divmod.com/ - - **PEP8** - Copyright (C) 2006 Johann C. Rocholl <johann@rocholl.net> - http://github.com/jcrocholl/pep8 - - **autopep8**: - Copyright (c) 2012 hhatto <hhatto.jp@gmail.com> - https://github.com/hhatto/autopep8 - - **Python syntax for vim** - Copyright (c) 2010 Dmitry Vasiliev - http://www.hlabs.spb.ru/vim/python.vim - - **PEP8 VIM indentation** - Copyright (c) 2012 Hynek Schlawack <hs@ox.cx> - http://github.com/hynek/vim-python-pep8-indent - - -License -======= - -Licensed under a `GNU lesser general public license`_. - -If you like this plugin, you can send me postcard :) -My address is here: "Russia, 143401, Krasnogorsk, Shkolnaya 1-19" to "Kirill Klenov". -**Thanks for support!** - - -.. _GNU lesser general public license: http://www.gnu.org/copyleft/lesser.html -.. _klen: http://klen.github.com/ -.. _pylint: http://www.logilab.org/857 -.. _pyflakes: http://pypi.python.org/pypi/pyflakes -.. _rope: http://rope.sourceforge.net/ -.. _pydoc: http://docs.python.org/library/pydoc.html -.. _pathogen: https://github.com/tpope/vim-pathogen -.. _pep8: http://pypi.python.org/pypi/pep8 -.. _mccabe: http://en.wikipedia.org/wiki/Cyclomatic_complexity diff --git a/.vim/bundle/python-mode/after/ftplugin/pyrex.vim b/.vim/bundle/python-mode/after/ftplugin/pyrex.vim @@ -1 +0,0 @@ -runtime after/ftplugin/python.vim diff --git a/.vim/bundle/python-mode/after/ftplugin/python.vim b/.vim/bundle/python-mode/after/ftplugin/python.vim @@ -1,43 +0,0 @@ -" Fix omnifunc -if g:pymode && g:pymode_rope && g:pymode_rope_vim_completion - setlocal omnifunc=RopeOmni -endif - -" Motion {{{ - - if !pymode#Default('g:pymode_motion', 1) || g:pymode_motion - - nnoremap <buffer> ]] :<C-U>call pymode#motion#move('^\(class\\|def\)\s', '')<CR> - nnoremap <buffer> [[ :<C-U>call pymode#motion#move('^\(class\\|def\)\s', 'b')<CR> - nnoremap <buffer> ]C :<C-U>call pymode#motion#move('^\(class\\|def\)\s', '')<CR> - nnoremap <buffer> [C :<C-U>call pymode#motion#move('^\(class\\|def\)\s', 'b')<CR> - nnoremap <buffer> ]M :<C-U>call pymode#motion#move('^\s*def\s', '')<CR> - nnoremap <buffer> [M :<C-U>call pymode#motion#move('^\s*def\s', 'b')<CR> - - onoremap <buffer> ]] :<C-U>call pymode#motion#move('^\(class\\|def\)\s', '')<CR> - onoremap <buffer> [[ :<C-U>call pymode#motion#move('^\(class\\|def\)\s', 'b')<CR> - onoremap <buffer> ]C :<C-U>call pymode#motion#move('^\(class\\|def\)\s', '')<CR> - onoremap <buffer> [C :<C-U>call pymode#motion#move('^\(class\\|def\)\s', 'b')<CR> - onoremap <buffer> ]M :<C-U>call pymode#motion#move('^\s*def\s', '')<CR> - onoremap <buffer> [M :<C-U>call pymode#motion#move('^\s*def\s', 'b')<CR> - - vnoremap <buffer> ]] :call pymode#motion#vmove('^\(class\\|def\)\s', '')<CR> - vnoremap <buffer> [[ :call pymode#motion#vmove('^\(class\\|def\)\s', 'b')<CR> - vnoremap <buffer> ]M :call pymode#motion#vmove('^\s*def\s', '')<CR> - vnoremap <buffer> [M :call pymode#motion#vmove('^\s*def\s', 'b')<CR> - - onoremap <buffer> C :<C-U>call pymode#motion#select('^\s*class\s', 0)<CR> - onoremap <buffer> aC :<C-U>call pymode#motion#select('^\s*class\s', 0)<CR> - onoremap <buffer> iC :<C-U>call pymode#motion#select('^\s*class\s', 1)<CR> - vnoremap <buffer> aC :<C-U>call pymode#motion#select('^\s*class\s', 0)<CR> - vnoremap <buffer> iC :<C-U>call pymode#motion#select('^\s*class\s', 1)<CR> - - onoremap <buffer> M :<C-U>call pymode#motion#select('^\s*def\s', 0)<CR> - onoremap <buffer> aM :<C-U>call pymode#motion#select('^\s*def\s', 0)<CR> - onoremap <buffer> iM :<C-U>call pymode#motion#select('^\s*def\s', 1)<CR> - vnoremap <buffer> aM :<C-U>call pymode#motion#select('^\s*def\s', 0)<CR> - vnoremap <buffer> iM :<C-U>call pymode#motion#select('^\s*def\s', 1)<CR> - - endif - -" }}} diff --git a/.vim/bundle/python-mode/after/indent/pyrex.vim b/.vim/bundle/python-mode/after/indent/pyrex.vim @@ -1 +0,0 @@ -runtime after/indent/python.vim diff --git a/.vim/bundle/python-mode/after/indent/python.vim b/.vim/bundle/python-mode/after/indent/python.vim @@ -1,14 +0,0 @@ -if pymode#Default('b:pymode_indent', 1) || !g:pymode_indent - finish -endif - - -setlocal nolisp -setlocal tabstop=4 -setlocal softtabstop=4 -setlocal shiftwidth=4 -setlocal shiftround -setlocal expandtab -setlocal autoindent -setlocal indentexpr=pymode#indent#Indent(v:lnum) -setlocal indentkeys=!^F,o,O,<:>,0),0],0},=elif,=except diff --git a/.vim/bundle/python-mode/autoload/pymode.vim b/.vim/bundle/python-mode/autoload/pymode.vim @@ -1,196 +0,0 @@ -" Python-mode base functions - - -fun! pymode#Default(name, default) "{{{ - " DESC: Set default value if it not exists - " - if !exists(a:name) - let {a:name} = a:default - return 0 - endif - return 1 -endfunction "}}} - - -fun! pymode#Option(name) "{{{ - - let name = 'b:pymode_' . a:name - if exists(name) - return eval(name) - endif - - let name = 'g:pymode_' . a:name - return eval(name) - -endfunction "}}} - - -fun! pymode#QuickfixOpen(onlyRecognized, holdCursor, maxHeight, minHeight, jumpError) "{{{ - " DESC: Open quickfix window - " - let numErrors = len(filter(getqflist(), 'v:val.valid')) - let numOthers = len(getqflist()) - numErrors - if numErrors > 0 || (!a:onlyRecognized && numOthers > 0) - botright copen - exe max([min([line("$"), a:maxHeight]), a:minHeight]) . "wincmd _" - if a:jumpError - cc - elseif !a:holdCursor - wincmd p - endif - else - cclose - endif - redraw - if numOthers > 0 - echo printf('Quickfix: %d(+%d)', numErrors, numOthers) - else - echo printf('Quickfix: %d', numErrors) - endif -endfunction "}}} - - -fun! pymode#PlaceSigns(bnum) "{{{ - " DESC: Place error signs - " - if has('signs') - call pymode#Default('b:pymode_signs', []) - - for item in b:pymode_signs - execute printf('sign unplace %d buffer=%d', item.lnum, item.bufnr) - endfor - let b:pymode_signs = [] - - if !pymode#Default("g:pymode_lint_signs_always_visible", 0) || g:pymode_lint_signs_always_visible - call RopeShowSignsRulerIfNeeded() - endif - - for item in filter(getqflist(), 'v:val.bufnr != ""') - call add(b:pymode_signs, item) - execute printf('sign place %d line=%d name=%s buffer=%d', item.lnum, item.lnum, "Pymode".item.type, item.bufnr) - endfor - - endif -endfunction "}}} - - -fun! pymode#CheckProgram(name, append) "{{{ - " DESC: Check program is executable or redifined by user. - " - let name = 'g:' . a:name - if pymode#Default(name, a:name) - return 1 - endif - if !executable(eval(l:name)) - echoerr "Can't find '".eval(name)."'. Please set ".name .", or extend $PATH, ".a:append - return 0 - endif - return 1 -endfunction "}}} - - -fun! pymode#TempBuffer() "{{{ - " DESC: Open temp buffer. - " - pclose | botright 8new - setlocal buftype=nofile bufhidden=delete noswapfile nowrap previewwindow - redraw -endfunction "}}} - - -fun! pymode#ShowStr(str) "{{{ - " DESC: Open temp buffer with `str`. - " - let g:pymode_curbuf = bufnr("%") - call pymode#TempBuffer() - put! =a:str - wincmd p - redraw -endfunction "}}} - - -fun! pymode#ShowCommand(cmd) "{{{ - " DESC: Run command and open temp buffer with result - " - call pymode#TempBuffer() - try - silent exec 'r!' . a:cmd - catch /.*/ - close - echoerr 'Command fail: '.a:cmd - endtry - redraw - normal gg - wincmd p -endfunction "}}} - - -fun! pymode#WideMessage(msg) "{{{ - " DESC: Show wide message - - let x=&ruler | let y=&showcmd - set noruler noshowcmd - redraw - echohl Debug | echo strpart(a:msg, 0, &columns-1) | echohl none - let &ruler=x | let &showcmd=y -endfunction "}}} - - -fun! pymode#BlockStart(lnum, ...) "{{{ - let pattern = a:0 ? a:1 : '^\s*\(@\|class\s.*:\|def\s\)' - let lnum = a:lnum + 1 - let indent = 100 - while lnum - let lnum = prevnonblank(lnum - 1) - let test = indent(lnum) - let line = getline(lnum) - if line =~ '^\s*#' " Skip comments - continue - elseif !test " Zero-level regular line - return lnum - elseif test >= indent " Skip deeper or equal lines - continue - " Indent is strictly less at this point: check for def/class - elseif line =~ pattern && line !~ '^\s*@' - return lnum - endif - let indent = indent(lnum) - endwhile - return 0 -endfunction "}}} - - -fun! pymode#BlockEnd(lnum, ...) "{{{ - let indent = a:0 ? a:1 : indent(a:lnum) - let lnum = a:lnum - while lnum - let lnum = nextnonblank(lnum + 1) - if getline(lnum) =~ '^\s*#' | continue - elseif lnum && indent(lnum) <= indent - return lnum - 1 - endif - endwhile - return line('$') -endfunction "}}} - - -fun! pymode#Modeline() "{{{ - let modeline = getline(prevnonblank('$')) - if modeline =~ '^#\s\+pymode:' - for ex in split(modeline, ':')[1:] - let [name, value] = split(ex, '=') - let {'b:pymode_'.name} = value - endfor - endif - au BufRead <buffer> call pymode#Modeline() -endfunction "}}} - - -fun! pymode#TrimWhiteSpace() "{{{ - let cursor_pos = getpos('.') - silent! %s/\s\+$// - call setpos('.', cursor_pos) -endfunction "}}} - - -" vim: fdm=marker:fdl=0 diff --git a/.vim/bundle/python-mode/autoload/pymode/breakpoint.vim b/.vim/bundle/python-mode/autoload/pymode/breakpoint.vim @@ -1,14 +0,0 @@ -fun! pymode#breakpoint#Set(lnum) "{{{ - let line = getline(a:lnum) - if strridx(line, g:pymode_breakpoint_cmd) != -1 - normal dd - else - let plnum = prevnonblank(a:lnum) - call append(line('.')-1, repeat(' ', indent(plnum)).g:pymode_breakpoint_cmd) - normal k - endif - - " Save file - if &modifiable && &modified | noautocmd write | endif - -endfunction "}}} diff --git a/.vim/bundle/python-mode/autoload/pymode/doc.vim b/.vim/bundle/python-mode/autoload/pymode/doc.vim @@ -1,19 +0,0 @@ -" Python-mode search by documentation - - -fun! pymode#doc#Show(word) "{{{ - if a:word == '' - echoerr "No name/symbol under cursor!" - else - py import StringIO - py sys.stdout, _ = StringIO.StringIO(), sys.stdout - py help(vim.eval('a:word')) - py sys.stdout, out = _, sys.stdout.getvalue() - call pymode#TempBuffer() - py vim.current.buffer.append(str(out).split('\n'), 0) - wincmd p - endif -endfunction "}}} - - -" vim: fdm=marker:fdl=0 diff --git a/.vim/bundle/python-mode/autoload/pymode/folding.vim b/.vim/bundle/python-mode/autoload/pymode/folding.vim @@ -1,60 +0,0 @@ -" Python-mode folding functions - - -let s:blank_regex = '^\s*$' -let s:def_regex = '^\s*\(class\|def\) \w\+' - - -fun! pymode#folding#text() " {{{ - let fs = v:foldstart - while getline(fs) =~ '^\s*@' - let fs = nextnonblank(fs + 1) - endwhile - let line = getline(fs) - - let nucolwidth = &fdc + &number * &numberwidth - let windowwidth = winwidth(0) - nucolwidth - 3 - let foldedlinecount = v:foldend - v:foldstart - - " expand tabs into spaces - let onetab = strpart(' ', 0, &tabstop) - let line = substitute(line, '\t', onetab, 'g') - - let line = strpart(line, 0, windowwidth - 2 -len(foldedlinecount)) - let fillcharcount = windowwidth - len(line) - len(foldedlinecount) - return line . '…' . repeat(" ",fillcharcount) . foldedlinecount . '…' . ' ' -endfunction "}}} - - -fun! pymode#folding#expr(lnum) "{{{ - - let line = getline(a:lnum) - let indent = indent(a:lnum) - - if line =~ s:def_regex - return ">".(indent / &shiftwidth + 1) - endif - - if line =~ '^\s*@' - return -1 - endif - - if line =~ s:blank_regex - let prev_line = getline(a:lnum - 1) - if prev_line =~ s:blank_regex - return -1 - else - return foldlevel(prevnonblank(a:lnum)) - endif - endif - - if indent == 0 - return 0 - endif - - return '=' - -endfunction "}}} - - -" vim: fdm=marker:fdl=0 diff --git a/.vim/bundle/python-mode/autoload/pymode/indent.vim b/.vim/bundle/python-mode/autoload/pymode/indent.vim @@ -1,184 +0,0 @@ -" PEP8 compatible Python indent file -" Language: Python -" Maintainer: Hynek Schlawack <hs@ox.cx> -" Prev Maintainer: Eric Mc Sween <em@tomcom.de> (address invalid) -" Original Author: David Bustos <bustos@caltech.edu> (address invalid) -" Last Change: 2012-06-21 -" License: Public Domainlet - - -function! pymode#indent#Indent(lnum) - - " First line has indent 0 - if a:lnum == 1 - return 0 - endif - - " If we can find an open parenthesis/bracket/brace, line up with it. - call cursor(a:lnum, 1) - let parlnum = s:SearchParensPair() - if parlnum > 0 - let parcol = col('.') - let closing_paren = match(getline(a:lnum), '^\s*[])}]') != -1 - if match(getline(parlnum), '[([{]\s*$', parcol - 1) != -1 - if closing_paren - return indent(parlnum) - else - return indent(parlnum) + &shiftwidth - endif - else - return parcol - endif - endif - - " Examine this line - let thisline = getline(a:lnum) - let thisindent = indent(a:lnum) - - " If the line starts with 'elif' or 'else', line up with 'if' or 'elif' - if thisline =~ '^\s*\(elif\|else\)\>' - let bslnum = s:BlockStarter(a:lnum, '^\s*\(if\|elif\)\>') - if bslnum > 0 - return indent(bslnum) - else - return -1 - endif - endif - - " If the line starts with 'except' or 'finally', line up with 'try' - " or 'except' - if thisline =~ '^\s*\(except\|finally\)\>' - let bslnum = s:BlockStarter(a:lnum, '^\s*\(try\|except\)\>') - if bslnum > 0 - return indent(bslnum) - else - return -1 - endif - endif - - " Examine previous line - let plnum = a:lnum - 1 - let pline = getline(plnum) - let sslnum = s:StatementStart(plnum) - - " If the previous line is blank, keep the same indentation - if pline =~ '^\s*$' - return -1 - endif - - " If this line is explicitly joined, try to find an indentation that looks - " good. - if pline =~ '\\$' - let compound_statement = '^\s*\(if\|while\|for\s.*\sin\|except\)\s*' - let maybe_indent = matchend(getline(sslnum), compound_statement) - if maybe_indent != -1 - return maybe_indent - else - return indent(sslnum) + &sw * 2 - endif - endif - - " If the previous line ended with a colon and is not a comment, indent - " relative to statement start. - if pline =~ ':\s*$' && pline !~ '^\s*#' - return indent(sslnum) + &sw - endif - - " If the previous line was a stop-execution statement or a pass - if getline(sslnum) =~ '^\s*\(break\|continue\|raise\|return\|pass\)\>' - " See if the user has already dedented - if indent(a:lnum) > indent(sslnum) - &sw - " If not, recommend one dedent - return indent(sslnum) - &sw - endif - " Otherwise, trust the user - return -1 - endif - - " In all other cases, line up with the start of the previous statement. - return indent(sslnum) -endfunction - - -" Find backwards the closest open parenthesis/bracket/brace. -function! s:SearchParensPair() - let line = line('.') - let col = col('.') - - " Skip strings and comments and don't look too far - let skip = "line('.') < " . (line - 50) . " ? dummy :" . - \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? ' . - \ '"string\\|comment"' - - " Search for parentheses - call cursor(line, col) - let parlnum = searchpair('(', '', ')', 'bW', skip) - let parcol = col('.') - - " Search for brackets - call cursor(line, col) - let par2lnum = searchpair('\[', '', '\]', 'bW', skip) - let par2col = col('.') - - " Search for braces - call cursor(line, col) - let par3lnum = searchpair('{', '', '}', 'bW', skip) - let par3col = col('.') - - " Get the closest match - if par2lnum > parlnum || (par2lnum == parlnum && par2col > parcol) - let parlnum = par2lnum - let parcol = par2col - endif - if par3lnum > parlnum || (par3lnum == parlnum && par3col > parcol) - let parlnum = par3lnum - let parcol = par3col - endif - - " Put the cursor on the match - if parlnum > 0 - call cursor(parlnum, parcol) - endif - return parlnum -endfunction - - -" Find the start of a multi-line statement -function! s:StatementStart(lnum) - let lnum = a:lnum - while 1 - if getline(lnum - 1) =~ '\\$' - let lnum = lnum - 1 - else - call cursor(lnum, 1) - let maybe_lnum = s:SearchParensPair() - if maybe_lnum < 1 - return lnum - else - let lnum = maybe_lnum - endif - endif - endwhile -endfunction - - -" Find the block starter that matches the current line -function! s:BlockStarter(lnum, block_start_re) - let lnum = a:lnum - let maxindent = 10000 " whatever - while lnum > 1 - let lnum = prevnonblank(lnum - 1) - if indent(lnum) < maxindent - if getline(lnum) =~ a:block_start_re - return lnum - else - let maxindent = indent(lnum) - " It's not worth going further if we reached the top level - if maxindent == 0 - return -1 - endif - endif - endif - endwhile - return -1 -endfunction diff --git a/.vim/bundle/python-mode/autoload/pymode/lint.vim b/.vim/bundle/python-mode/autoload/pymode/lint.vim @@ -1,108 +0,0 @@ -fun! pymode#lint#Check() "{{{ - " DESC: Run checkers on current file. - " - if !g:pymode_lint | return | endif - - if &modifiable && &modified - try - noautocmd write - catch /E212/ - echohl Error | echo "File modified and I can't save it. Cancel code checking." | echohl None - return 0 - endtry - endif - - let g:pymode_lint_buffer = bufnr('%') - - py from pymode import lint - py lint.check_file() - -endfunction " }}} - - -fun! pymode#lint#Parse(bnum) - " DESC: Parse result of code checking. - " - call setqflist(g:qf_list, 'r') - - if g:pymode_lint_signs - call pymode#PlaceSigns(a:bnum) - endif - - if g:pymode_lint_cwindow - call pymode#QuickfixOpen(0, g:pymode_lint_hold, g:pymode_lint_maxheight, g:pymode_lint_minheight, g:pymode_lint_jump) - endif - - if !len(g:qf_list) - call pymode#WideMessage('Code checking is completed. No errors found.') - endif - -endfunction - - -fun! pymode#lint#Toggle() "{{{ - let g:pymode_lint = g:pymode_lint ? 0 : 1 - call pymode#lint#toggle_win(g:pymode_lint, "Pymode lint") -endfunction "}}} - - -fun! pymode#lint#ToggleWindow() "{{{ - let g:pymode_lint_cwindow = g:pymode_lint_cwindow ? 0 : 1 - call pymode#lint#toggle_win(g:pymode_lint_cwindow, "Pymode lint cwindow") -endfunction "}}} - - -fun! pymode#lint#ToggleChecker() "{{{ - let g:pymode_lint_checker = g:pymode_lint_checker == "pylint" ? "pyflakes" : "pylint" - echomsg "Pymode lint checker: " . g:pymode_lint_checker -endfunction "}}} - - -fun! pymode#lint#toggle_win(toggle, msg) "{{{ - if a:toggle - echomsg a:msg." enabled" - botright cwindow - if &buftype == "quickfix" - wincmd p - endif - else - echomsg a:msg." disabled" - cclose - endif -endfunction "}}} - - -fun! pymode#lint#show_errormessage() "{{{ - if g:pymode_lint_buffer != bufnr('%') - return 0 - endif - let errors = getqflist() - if !len(errors) - return - endif - let [_, line, _, _] = getpos(".") - for e in errors - if e['lnum'] == line - call pymode#WideMessage(e['text']) - else - echo - endif - endfor -endfunction " }}} - - -fun! pymode#lint#Auto() "{{{ - if &modifiable && &modified - try - noautocmd write - catch /E212/ - echohl Error | echo "File modified and I can't save it. Cancel operation." | echohl None - return 0 - endtry - endif - py from pymode import auto - py auto.fix_current_file() - cclose - edit - call pymode#WideMessage("AutoPep8 done.") -endfunction "}}} diff --git a/.vim/bundle/python-mode/autoload/pymode/motion.vim b/.vim/bundle/python-mode/autoload/pymode/motion.vim @@ -1,61 +0,0 @@ -" Python-mode motion functions - - -fun! pymode#motion#move(pattern, flags, ...) "{{{ - let cnt = v:count1 - 1 - let [line, column] = searchpos(a:pattern, a:flags . 'sW') - let indent = indent(line) - while cnt && line - let [line, column] = searchpos(a:pattern, a:flags . 'W') - if indent(line) == indent - let cnt = cnt - 1 - endif - endwhile - return [line, column] -endfunction "}}} - - -fun! pymode#motion#vmove(pattern, flags) range "{{{ - call cursor(a:lastline, 0) - let end = pymode#motion#move(a:pattern, a:flags) - call cursor(a:firstline, 0) - normal! v - call cursor(end) -endfunction "}}} - - -fun! pymode#motion#pos_le(pos1, pos2) "{{{ - return ((a:pos1[0] < a:pos2[0]) || (a:pos1[0] == a:pos2[0] && a:pos1[1] <= a:pos2[1])) -endfunction "}}} - - -fun! pymode#motion#select(pattern, inner) "{{{ - let cnt = v:count1 - 1 - let orig = getpos('.')[1:2] - let snum = pymode#BlockStart(orig[0], a:pattern) - if getline(snum) !~ a:pattern - return 0 - endif - let enum = pymode#BlockEnd(snum, indent(snum)) - while cnt - let lnum = search(a:pattern, 'nW') - if lnum - let enum = pymode#BlockEnd(lnum, indent(lnum)) - call cursor(enum, 1) - endif - let cnt = cnt - 1 - endwhile - if pymode#motion#pos_le([snum, 0], orig) && pymode#motion#pos_le(orig, [enum, 1]) - if a:inner - let snum = snum + 1 - let enum = prevnonblank(enum) - endif - - call cursor(snum, 1) - normal! v - call cursor(enum, len(getline(enum))) - endif -endfunction "}}} - - -" vim: fdm=marker:fdl=0 diff --git a/.vim/bundle/python-mode/autoload/pymode/queue.vim b/.vim/bundle/python-mode/autoload/pymode/queue.vim @@ -1,15 +0,0 @@ -fun! pymode#queue#Poll() "{{{ - - " Check current tasks - py queue.check_task() - - " Update interval - if mode() == 'i' - let p = getpos('.') - silent exe 'call feedkeys("\<Up>\<Down>", "n")' - call setpos('.', p) - else - call feedkeys("f\e", "n") - endif - -endfunction "}}} diff --git a/.vim/bundle/python-mode/autoload/pymode/run.vim b/.vim/bundle/python-mode/autoload/pymode/run.vim @@ -1,45 +0,0 @@ -" DESC: Save file if it modified and run python code -fun! pymode#run#Run(line1, line2) "{{{ - if &modifiable && &modified - try - noautocmd write - catch /E212/ - echohl Error | echo "File modified and I can't save it. Cancel code checking." | echohl None - return 0 - endtry - endif - py import StringIO - py sys.stdout, stdout_ = StringIO.StringIO(), sys.stdout - py sys.stderr, stderr_ = StringIO.StringIO(), sys.stderr - py enc = vim.eval('&enc') - call setqflist([]) - call pymode#WideMessage("Code running.") - try - py context = globals() - py context['raw_input'] = context['input'] = lambda s: vim.eval('input("{0}")'.format(s)) - py execfile(vim.eval('expand("%:p")'), context) - py out, err = sys.stdout.getvalue().strip(), sys.stderr.getvalue() - py sys.stdout, sys.stderr = stdout_, stderr_ - - cexpr "" - py for x in err.strip().split('\n'): vim.command('caddexpr "' + x.replace('"', r'\"') + '"') - let l:oldefm = &efm - set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m - call pymode#QuickfixOpen(0, g:pymode_lint_hold, g:pymode_lint_maxheight, g:pymode_lint_minheight, 0) - let &efm = l:oldefm - -python << EOF -if out: - vim.command("call pymode#TempBuffer()") - vim.current.buffer.append([x.encode(enc) for x in out.split('\n')], 0) - vim.command("wincmd p") -else: - vim.command('call pymode#WideMessage("No output.")') -EOF - - catch /.*/ - - echohl Error | echo "Run-time error." | echohl none - - endtry -endfunction "}}} diff --git a/.vim/bundle/python-mode/autoload/pymode/troubleshooting.vim b/.vim/bundle/python-mode/autoload/pymode/troubleshooting.vim @@ -1,87 +0,0 @@ -" DESC: Get debug information about pymode problem -fun! pymode#troubleshooting#Test() "{{{ - new - setlocal buftype=nofile bufhidden=delete noswapfile nowrap - - let os = "Unknown" - if has('win16') || has('win32') || has('win64') - let os = "Windows" - else - let os = substitute(system('uname'), "\n", "", "") - endif - - call append('0', ['Pymode diagnostic', - \ '===================', - \ 'VIM:' . v:version . ', OS: ' . os .', multi_byte:' . has('multi_byte') . ', pymode: ' . g:pymode_version, - \ '']) - - let python = 1 - let output = [] - - if !exists('#filetypeplugin') - call append('$', ['WARNING: ', 'Python-mode required :filetype plugin indent on', '']) - endif - - if !has('python') - call append('$', ['WARNING: ', 'Python-mode required vim compiled with +python.', - \ '"lint, rope, run, doc, virtualenv" features disabled.', '']) - let python = 0 - endif - - call append('$', 'Pymode variables:') - call append('$', '-------------------') - call append('$', 'let pymode = ' . string(g:pymode)) - if g:pymode - call append('$', 'let pymode_path = ' . string(g:pymode_path)) - call append('$', 'let pymode_paths = ' . string(g:pymode_paths)) - - call append('$', 'let pymode_doc = ' . string(g:pymode_doc)) - if g:pymode_doc - call append('$', 'let pymode_doc_key = ' . string(g:pymode_doc_key)) - endif - - call append('$', 'let pymode_run = ' . string(g:pymode_run)) - if g:pymode_run - call append('$', 'let pymode_run_key = ' . string(g:pymode_run_key)) - endif - - call append('$', 'let pymode_lint = ' . string(g:pymode_lint)) - if g:pymode_lint - call append('$', 'let pymode_lint_checker = ' . string(g:pymode_lint_checker)) - call append('$', 'let pymode_lint_ignore = ' . string(g:pymode_lint_ignore)) - call append('$', 'let pymode_lint_select = ' . string(g:pymode_lint_select)) - call append('$', 'let pymode_lint_onfly = ' . string(g:pymode_lint_onfly)) - call append('$', 'let pymode_lint_config = ' . string(g:pymode_lint_config)) - call append('$', 'let pymode_lint_write = ' . string(g:pymode_lint_write)) - call append('$', 'let pymode_lint_cwindow = ' . string(g:pymode_lint_cwindow)) - call append('$', 'let pymode_lint_message = ' . string(g:pymode_lint_message)) - call append('$', 'let pymode_lint_signs = ' . string(g:pymode_lint_signs)) - call append('$', 'let pymode_lint_jump = ' . string(g:pymode_lint_jump)) - call append('$', 'let pymode_lint_hold = ' . string(g:pymode_lint_hold)) - call append('$', 'let pymode_lint_minheight = ' . string(g:pymode_lint_minheight)) - call append('$', 'let pymode_lint_maxheight = ' . string(g:pymode_lint_maxheight)) - endif - - call append('$', 'let pymode_rope = ' . string(g:pymode_rope)) - call append('$', 'let pymode_folding = ' . string(g:pymode_folding)) - call append('$', 'let pymode_breakpoint = ' . string(g:pymode_breakpoint)) - call append('$', 'let pymode_syntax = ' . string(g:pymode_syntax)) - call append('$', 'let pymode_virtualenv = ' . string(g:pymode_virtualenv)) - if g:pymode_virtualenv - call append('$', 'let pymode_virtualenv_enabled = ' . string(g:pymode_virtualenv_enabled)) - endif - call append('$', 'pymode_utils_whitespaces:' . string(g:pymode_utils_whitespaces)) - call append('$', 'pymode_options:' . string(g:pymode_options)) - endif - - if python - call append('$', 'VIM python paths:') - call append('$', '-----------------') -python << EOF -vim.command('let l:output = %s' % repr(sys.path)) -EOF - call append('$', output) - call append('$', '') - endif - -endfunction "}}} diff --git a/.vim/bundle/python-mode/autoload/pymode/virtualenv.vim b/.vim/bundle/python-mode/autoload/pymode/virtualenv.vim @@ -1,31 +0,0 @@ -fun! pymode#virtualenv#Activate() "{{{ - - if !exists("$VIRTUAL_ENV") - return - endif - - for env in g:pymode_virtualenv_enabled - if env == $VIRTUAL_ENV - return 0 - endif - endfor - - call add(g:pymode_virtualenv_enabled, $VIRTUAL_ENV) - -python << EOF -import sys, vim, os - -ve_dir = vim.eval('$VIRTUAL_ENV') -ve_dir in sys.path or sys.path.insert(0, ve_dir) -activate_this = os.path.join(os.path.join(ve_dir, 'bin'), 'activate_this.py') - -# Fix for windows -if not os.path.exists(activate_this): - activate_this = os.path.join(os.path.join(ve_dir, 'Scripts'), 'activate_this.py') - -execfile(activate_this, dict(__file__=activate_this)) -EOF - - call pymode#WideMessage("Activate virtualenv: ".$VIRTUAL_ENV) - -endfunction "}}} diff --git a/.vim/bundle/python-mode/doc/pymode.txt b/.vim/bundle/python-mode/doc/pymode.txt @@ -1,558 +0,0 @@ -*pymode.txt* *python-mode.txt* Python-mode for vim! - - ____ _ _ ____ _ _ _____ _ _ __ __ _____ ____ ____ ~ - ( _ \( \/ )(_ _)( )_( )( _ )( \( )___( \/ )( _ )( _ \( ___) ~ - )___/ \ / )( ) _ ( )(_)( ) ((___)) ( )(_)( )(_) ))__) ~ - (__) (__) (__) (_) (_)(_____)(_)\_) (_/\/\_)(_____)(____/(____) ~ - - - Version: 0.6.15 - -============================================================================== -CONTENTS *Python-mode-contents* - - 1.Intro...................................|PythonMode| - 2.Options.................................|PythonModeOptions| - 2.1.Customisation details.............|PythonModeOptionsDetails| - 2.2.Modeline..........................|PythonModeModeline| - 3.Default Keys............................|PythonModeKeys| - 4.Commands................................|PythonModeCommands| - 5.FAQ.....................................|PythonModeFAQ| - 6.Credits.................................|PythonModeCredits| - 7.License.................................|PythonModeLicense| - -============================================================================== -1. Intro ~ - *PythonMode* - -Python-mode is a vim plugin that allows you to use the pylint, rope, and pydoc -libraries in vim to provide features like python code bug checking, -refactoring, and some other useful things. - -This plugin allows you to create python code in vim very easily. There is no need -to install the pylint or rope libraries on your system. - - -============================================================================== -2. Options ~ - *PythonModeOptions* - - Note: - Pylint options (ex. disable messages) may be defined in '$HOME/pylint.rc' - See pylint documentation. - -This script provides the following options that can customise the behaviour of -PythonMode. These options should be set in your vimrc. - -|'pymode'| Turn off the whole plugin - -|'pymode_paths'| Additional python paths for pymode - -|'pymode_doc'| Turns off the documentation script - -|'pymode_doc_key'| Key for show documentation - -|'pymode_run'| Turns off the run code script - -|'pymode_run_key'| Key for run python code - -|'pymode_lint'| Turns off pylint script - -|'pymode_lint_checker'| Switch code checkers (pylint, pyflakes, pep8, mccabe) - -|'pymode_lint_ignore'| Skip errors and warnings - -|'pymode_lint_select'| Select errors and warnings - -|'pymode_lint_onfly'| Run linter on the fly - -|'pymode_lint_config'| Filepath to pylint configuration - -|'pymode_lint_write'| Check code every save - -|'pymode_lint_cwindow'| Show cwindow - -|'pymode_lint_message'| Show current line errors in bottom - -|'pymode_lint_signs'| Place signs - -|'pymode_lint_jump'| Auto jump to first error - -|'pymode_lint_hold'| Hold cursor in current window - -|'pymode_lint_minheight'| Minimal height of pylint error window - -|'pymode_lint_mccabe_complexity'| Maximum allowed mccabe complexity - -|'pymode_lint_maxheight'| Maximal height of pylint error window - -|'pymode_rope'| Turns off rope script - -|'pymode_folding'| Turns on/off python folding - -|'pymode_breakpoint'| Turns off breakpoint script - -|'pymode_breakpoint_key'| Key for breakpoint - -|'pymode_virtualenv'| Turns off virtualenv - -|'pymode_utils_whitespaces'| Remove unused whitespaces - -|'pymode_syntax'| Turns off the custom syntax highlighting - -|'pymode_indent'| Enable/Disable pymode PEP8 indentation - -|'pymode_options'| Set default pymode options for - python codding - -|'pymode_motion'| Enable pymode motion stuff - - Note: - Also see |ropevim.txt| - - ------------------------------------------------------------------------------- -2.1. Customisation details ~ - *PythonModeOptionsDetails* - -To enable any of the options below you should put the given line in your -'$HOME/.vimrc'. See |vimrc-intro|. - ------------------------------------------------------------------------------- -2.2. Modeline ~ - *PythonModeModeline* - -The VIM modeline `:help modeline` feature allows you to change pymode -options for the current file. Pymode modeline should always be the -last line in the vimrc file and look like: - -> - # pymode:lint_ignore=E0202:doc=0:lint_write=0 -< - -Examples: - -Disable folding on current file: -> - # pymode:folding=0 -< - -Set linters and mccabe complexity. -> - # pymode:lint_checker=pip,mccabe:lint_mccabe_complexity=10 -< - -These changes will work only in the current buffer. - ------------------------------------------------------------------------------- - *'pymode'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then the whole plugin is disabled - ------------------------------------------------------------------------------- - *'pymode_paths'* -Values: List of strings -Default: []. - -This option sets additional python import paths - ------------------------------------------------------------------------------- - *'pymode_doc'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then the doc script is disabled. - ------------------------------------------------------------------------------- - *'pymode_doc_key'* -Default: 'K'. - -Set the key to show the show python documentation. - ------------------------------------------------------------------------------- - *'pymode_run'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then the run script is disabled. - ------------------------------------------------------------------------------- - *'pymode_run_key'* -Default: '<leader>r'. - -Set the key for running python code. - ------------------------------------------------------------------------------- - *'pymode_lint'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then the pylint script is disabled. - ------------------------------------------------------------------------------- - *'pymode_lint_checker'* -Values: "pylint", "pyflakes", "pep8", "mccabe" - You can set many checkers. E.g. "pyflakes,pep8,mccabe" ~ - -Default: "pyflakes,pep8,mccabe". - -This option sets code checkers. - ------------------------------------------------------------------------------- - *'pymode_lint_ignore'* -Values: IDs of errors, separated by commas or empty strings - E.g. "E501,W002", "E2,W" (Skip all Warnings and Errors startswith E2) and etc ~ - -Default: "". - -Skip errors and warnings. -See also: |'pymode_lint_select'|, |'pymode_lint_config'| - ------------------------------------------------------------------------------- - *'pymode_lint_select'* -Values: IDs of errors, separated by commas or empty strings - E.g. "W002,C" Force W002 and all C-ids ~ - -Default: "". - -Select errors and warnings. -See also: |'pymode_lint_ignore'|, |'pymode_lint_config'| - ------------------------------------------------------------------------------- - *'pymode_lint_onfly'* -Values: 0 or 1 -Default: 0 - -This option enables "on the fly" code checking - ------------------------------------------------------------------------------- - *'pymode_lint_config'* -Values: 'Path to pylint configuration file' -Default: "$HOME/.pylintrc" - -This option sets the path to the pylint configuration file. If the -file is not found, use the 'pylintrc' file from python-mode sources. - -See also: |'pymode_lint_ignore'|, |'pymode_lint_select'| - ------------------------------------------------------------------------------- - *'pymode_lint_write'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0, then pylint auto-checking on every save is -disabled. - ------------------------------------------------------------------------------- - *'pymode_lint_cwindow'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then pylint will not show cwindow. - ------------------------------------------------------------------------------- - *'pymode_lint_message'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then pylint will not show errors at bottom. - ------------------------------------------------------------------------------- - *'pymode_lint_signs'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then pylint will not place error signs. - ------------------------------------------------------------------------------- - *'pymode_lint_jump'* -Values: 0 or 1. -Default: 0. - -If this option is set to 0 then pylint will not jump to the first error. - ------------------------------------------------------------------------------- - *'pymode_lint_hold'* -Values: 0 or 1. -Default: 0. - -If this option is set to 0 then pylint will switch on the quickfix window when -it opens. Doesn't work when |'pymode_lint_jump'| is enabled. - ------------------------------------------------------------------------------- - *'pymode_lint_minheight'* -Values: int -Default: 3. - -Set minimal height for the pylint cwindow. - ------------------------------------------------------------------------------- - *'pymode_lint_mccabe_complexity'* -Values: int -Default: 8. - -Set minimal complexity for the mccabe linter. - ------------------------------------------------------------------------------- - *'pymode_lint_maxheight'* -Values: int -Default: 6. - -Set maximal height for the pylint cwindow. - ------------------------------------------------------------------------------- - *'pymode_rope'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then the rope script is disabled. - ------------------------------------------------------------------------------- - *'pymode_breakpoint'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then the breakpoint script is disabled. - ------------------------------------------------------------------------------- - *'pymode_breakpoint_key'* -Default: '<leader>b'. - -Key for setting/unsetting breakpoints. - ------------------------------------------------------------------------------- - *'pymode_virtualenv'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then virtualenv support is disabled. - ------------------------------------------------------------------------------- - *'pymode_utils_whitespaces'* -Values: 0 or 1. -Default: 1. - -Auto-remove unused whitespaces. - ------------------------------------------------------------------------------- - *'pymode_syntax'* -Values: 0 or 1. -Default: 1. - -If this option is set to 0 then the custom syntax highlighting will -not be used. - ------------------------------------------------------------------------------- - *'pymode_indent'* -Values: 0 or 1. -Default: 1. - -If this option is set to 1, pymode will enable python indentation support. - ------------------------------------------------------------------------------- - *'pymode_folding'* -Values: 0 or 1. -Default: 1. - -If this option is set to 1, pymode will enable python-folding. - ------------------------------------------------------------------------------- - *'pymode_options'* -Values: 0 or 1. -Default: 1. - -If this option is set to 1, pymode will enable the following options for python -buffers: > - - setlocal complete+=t - setlocal formatoptions-=t - setlocal number - setlocal nowrap - setlocal textwidth=80 -< ------------------------------------------------------------------------------- - *'pymode_motion'* -Values: 0 or 1. -Default: 1. - -If this option is set to 1, pymode will enable some python motions. -Pymode-motion is beta. - -================ ============================ -Key Command -================ ============================ -[[ Jump to previous class or function (normal, visual, operator modes) -]] 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) -================ ============================ - - -============================================================================== -3. Default Keys ~ - *PythonModeKeys* - -To redefine keys, see: |PythonModeOptions| - -================ ============================ -Key Command -================ ============================ -K Show python docs for current word under cursor -C-Space Rope code assist -<leader>r Run current buffer -<leader>b Set breakpoints -[[ Jump to previous class or function (normal, visual, operator modes) -]] 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 C Operation with a class. - Ex: vaC, daC, dC, yaC, yC, caC, cC (normal, operator modes) -iC Operation with inner class. - Ex: viC, diC, yiC, ciC (normal, operator modes) -aM M Operation with function or method. - Ex: vaM, daM, dM, yaM, yM, caM, cM (normal, operator modes) -iM Operation with inner function or method. - Ex: viM, diM, yiM, ciM (normal, operator modes) -================ ============================ - - Note: - Also see: |RopeShortcuts| - - -============================================================================== -4. Commands ~ - *PythonModeCommands* - -*:Pydoc* <args> *Pydoc* - Show python documentation - -*:PyLintToggle* *PyLintToggle* - Enable, disable pylint - -*:PyLint* *PyLint* - Check current buffer - -*:PyLintAuto* *PyLintAuto* - Automatically fix PEP8 errors in the current buffer - -*:Pyrun* *Pyrun* - Run current buffer - - -============================================================================== -5. FAQ ~ - *PythonModeFAQ* - -Python-mode doesn't work ------------------------- - -Open any python file and run ":call pymode#troubleshooting#Test()", -fix the warning or send me the output. - - -Rope completion is very slow ----------------------------- - -To work, rope_ creates a service directory: `.ropeproject`. If -|'pymode_rope_guess_project'| is set on (as it is by default) and -`.ropeproject` is not found in the current dir, rope will scan for -`.ropeproject` in every dir in the parent path. If rope finds `.ropeproject` -in parent dirs, rope sets projectis for all child dirs and the scan may be -slow for many dirs and files. - -Solutions: - -- Disable |'pymode_rope_guess_project'| to make rope always create - `.ropeproject` in the current dir. -- Delete `.ropeproject` from the parent dir to make rope create `.ropeproject` - in the current dir. -- Press `<C-x>po` or `:RopeOpenProject` to force rope to create `.ropeproject` - in the current dir. - - -Pylint check is very slow -------------------------- - -In some projects pylint_ may check slowly, because it also scans imported -modules if possible. Try using pyflakes: see |'pymode_lint_checker'|. - -You may set |exrc| and |secure| in your |vimrc| to auto-set custom settings -from `.vimrc` from your projects directories. -> - Example: On Flask projects I automatically set - 'g:pymode_lint_checker = "pyflakes"'. - On Django 'g:pymode_lint_checker = "pylint"' -< - -OSX cannot import urandom -------------------------- - -See: https://groups.google.com/forum/?fromgroups=#!topic/vim_dev/2NXKF6kDONo - -The sequence of commands that fixed this: -> - brew unlink python - brew unlink macvim - brew remove macvim - brew install -v --force macvim - brew link macvim - brew link python -< - -============================================================================== -6. Credits ~ - *PythonModeCredits* - Kirill Klenov - http://klen.github.com/ - http://github.com/klen/ - - Rope - Copyright (C) 2006-2010 Ali Gholami Rudi - Copyright (C) 2009-2010 Anton Gritsay - - Pylint - Copyright (C) 2003-2011 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ - - Pyflakes: - Copyright (c) 2005 Divmod, Inc. - http://www.divmod.com/ - - PEP8: - Copyright (c) 2006 Johann C. Rocholl <johann@rocholl.net> - http://github.com/jcrocholl/pep8 - - autopep8: - Copyright (c) 2012 hhatto <hhatto.jp@gmail.com> - https://github.com/hhatto/autopep8 - - Python syntax for vim: - Copyright (c) 2010 Dmitry Vasiliev - http://www.hlabs.spb.ru/vim/python.vim - - PEP8 VIM indentation - Copyright (c) 2012 Hynek Schlawack <hs@ox.cx> - http://github.com/hynek/vim-python-pep8-indent - - -============================================================================== -7. License ~ - *PythonModeLicense* - -Python-mode is released under the GNU lesser general public license. -See: http://www.gnu.org/copyleft/lesser.html - -If you like this plugin, you can send me a postcard :) -My address is: "Russia, 143401, Krasnogorsk, Shkolnaya 1-19" to "Kirill Klenov". -Thanks for your support! - - ------------------------------------------------------------------------------- - - vim:tw=78:ts=8:ft=help:norl: diff --git a/.vim/bundle/python-mode/doc/ropevim.txt b/.vim/bundle/python-mode/doc/ropevim.txt @@ -1,340 +0,0 @@ -*ropevim.txt* *Ropevim* Rope in VIM - -============================================================================== -CONTENTS *Rope contents* - - 1.Refactoring Dialog......................|RopeRefactoringDialog| - 2.Finding Files...........................|RopeFindingFiles| - 3.Code Assist.............................|RopeCodeAssist| - 4.Enabling Autoimport.....................|RopeEnablingAutoimport| - 5.Filtering Resources.....................|RopeFilteringResources| - 6.Finding Occurrences.....................|RopeFindOccurrences| - 7.Dialog Batchset Command.................|RopeDialogBatchsetCommand| - 8.Variables...............................|RopeVariables| - 9.Keybindings.............................|RopeKeys| - - -============================================================================== -1. Refactoring Dialog ~ - *RopeRefactoringDialog* - -Ropevim refactorings use a special kind of dialog. Depending on the -refactoring, you'll be asked about the essential information a -refactoring needs to know (like the new name in rename refactoring). - -Next you'll see the base prompt of a refactoring dialog that shows -something like "Choose what to do". By entering the name of a -refactoring option you can set its value. After setting each option -you'll be returned back to the base prompt. Finally, you can ask rope -to perform, preview or cancel the refactoring. - -See |RopeKeys| section and try the refactorings yourself. - - -============================================================================== -2. Finding Files ~ - *RopeFindingFiles* - *:RopeFindFile* - *:RopeFindFileOtherWindow* - -By using |:RopeFindFile| ("<C-x> p f" by default), you can search for -files in your project. When you complete the minibuffer you'll see -all files in the project; files are shown as their reversed paths. -For instance ``projectroot/docs/todo.txt`` is shown like -``todo.txt<docs``. This way you can find files faster in your -project. |:RopeFindFileOtherWindow| ("<C-x> p 4 f") opens the -file in the other window. - - -============================================================================== -3. Code Assist ~ - *RopeCodeAssist* - *:RopeCodeAssist* - *:RopeLuckyAssist* - *'pymode_rope_vim_completion'* - *'pymode_rope_extended_complete'* - -|:RopeCodeAssist| command (<M-/>) will let you select from a list -of completions. |:RopeLuckyAssist| command (<M-?>) does not ask -anything; instead, it inserts the first proposal. - -You can tell ropevim to use vim's complete function in insert mode; -Add: > - - let pymode_rope_vim_completion=1 -< -to your '~/.vimrc' file. - - Note: - That when this variable is set, autoimport completions no longer - work since they need to insert an import to the top of the module, - too. - -By default autocomplete feature will use plain list of proposed completion -items. You can enable showing extended information about completion -proposals by setting : > - - let pymode_rope_extended_complete=1 -< -Completion menu list will show the proposed name itself, one letter which -shows where this proposal came from (it can be "L" for locals, "G" for -globals, "B" for builtins, or empty string if such scope definition is not -applicable), a short object type description (such as "func", "param", -"meth" and so forth) and a first line of proposed object's docstring (if it -has one). For function's keyword parameters the last field shows "*" symbol -if this param is required or "= <default value>" if it is not. - - -============================================================================== -4. Enabling Autoimport ~ - *RopeEnablingAutoimport* - *:RopevimAutoImport* - *:RopeGenerateAutoimportCache* - -Rope can propose and automatically import global names in other -modules. Rope maintains a cache of global names for each project. It -updates the cache only when modules are changed; if you want to cache -all your modules at once, use |:RopeGenerateAutoimportCache|. It -will cache all of the modules inside the project plus those whose -names are listed in |'pymode_rope_autoimport_modules'| list: > - - " add the name of modules you want to autoimport - let g:pymode_rope_autoimport_modules = ["os", "shutil"] -< -Now if you are in a buffer that contains: > - - rmtree -< - -and you execute |:RopevimAutoImport| you'll end up with: > - - from shutil import rmtree - rmtree -< -Also |:RopeCodeAssist| and |:RopeLuckyAssist| propose auto-imported -names by using "name : module" style. Selecting them will import -the module automatically. - - -============================================================================== -5. Filtering Resources ~ - *RopeFilteringResources* - -Some refactorings, restructuring and find occurrences take an option -called resources. This option can be used to limit the resources on -which a refactoring should be applied. - -It uses a simple format: each line starts with either '+' or '-'. -Each '+' means include the file (or its children if it's a folder) -that comes after it. '-' has the same meaning for exclusion. So -using: > - - +rope - +ropetest - -rope/contrib -< -means include all python files inside ``rope`` and ``ropetest`` -folders and their subfolder, but those that are in ``rope/contrib``. -Or: > - - -ropetest - -setup.py -< -means include all python files inside the project but ``setup.py`` and -those under ``ropetest`` folder. - - -============================================================================== -6. Finding Occurrences ~ - *RopeFindOccurrences* - -The find occurrences command ("<C-c> f" by default) can be used to -find the occurrences of a python name. If ``unsure`` option is -``yes``, it will also show unsure occurrences; unsure occurrences are -indicated with a ``?`` mark in the end. - - Note: - That ropevim uses the quickfix feature of vim for - marking occurrence locations. - - -============================================================================== -7. Dialog Batchset Command ~ - *RopeDialogBatchsetCommand* - -When you use ropevim dialogs there is a command called ``batchset``. -It can set many options at the same time. After selecting this -command from dialog base prompt, you are asked to enter a string. - -``batchset`` strings can set the value of configs in two ways. The -single line form is like this: > - - name1 value1 - name2 value2 -< - -That is the name of config is followed its value. For multi-line -values you can use: > - - name1 - line1 - line2 - - name2 - line3 -< -Each line of the definition should start with a space or a tab. - Note: - That blank lines before the name of config definitions are ignored. - -``batchset`` command is useful when performing refactorings with long -configs, like restructurings: > - - pattern ${pycore}.create_module(${project}.root, ${name}) - - goal generate.create_module(${project}, ${name}) - - imports - from rope.contrib import generate - - args - pycore: type=rope.base.pycore.PyCore - project: type=rope.base.project.Project -< -.. ignore the two-space indents - -This is a valid ``batchset`` string for restructurings. - -Just for the sake of completeness, the reverse of the above -restructuring can be: > - - pattern ${create_module}(${project}, ${name}) - - goal ${project}.pycore.create_module(${project}.root, ${name}) - - args - create_module: name=rope.contrib.generate.create_module - project: type=rope.base.project.Project -< - -============================================================================== -8. Variables ~ - *RopeVariables* - -*'pymode_rope_codeassist_maxfixes'* The maximum number of syntax errors - to fix for code assists. - The default value is `1`. - -*'pymode_rope_local_prefix'* The prefix for ropevim refactorings. - Defaults to `<C-c> r`. - -*'pymode_rope_global_prefix'* The prefix for ropevim project commands - Defaults to `<C-x> p`. - -*'pymode_rope_enable_shortcuts'* Shows whether to bind ropevim shortcuts keys. - Defaults to `1`. - -*'pymode_rope_guess_project'* If non-zero, ropevim tries to guess and - open the project that contains the file on which - a ropevim command is performed when no project - is already open. - -*'pymode_rope_enable_autoimport'* Shows whether to enable autoimport. - -*'pymode_rope_autoimport_modules'* The name of modules whose global names should - be cached. |:RopeGenerateAutoimportCache| reads - this list and fills its cache. - -*'pymode_rope_autoimport_underlineds'* If set, autoimport will cache names starting - with underlines, too. - -*'pymode_rope_goto_def_newwin'* If set, ropevim will open a new buffer - for "go to definition" result if the definition - found is located in another file. By default the - file is open in the same buffer. - Values: '' -- same buffer, 'new' -- - horizontally split, 'vnew' -- - vertically split - -*'pymode_rope_always_show_complete_menu'* If set, rope autocompletion menu -always show. - - -============================================================================== -9. Keybinding ~ - *RopeKeys* - -Uses almost the same keybinding as ropemacs. - Note: - That global commands have a `<C-x> p` prefix and local commands - have a ``<C-c> r`` prefix. - You can change that (see |RopeVariables| section). - - -================ ============================ -Key Command -================ ============================ -C-x p o |:RopeOpenProject| -C-x p k |:RopeCloseProject| -C-x p f |:RopeFindFile| -C-x p 4 f |:RopeFindFileOtherWindow| -C-x p u |:RopeUndo| -C-x p r |:RopeRedo| -C-x p c |:RopeProjectConfig| -C-x p n [mpfd] |:RopeCreate|(Module|Package|File|Directory) - |:RopeWriteProject| - -C-c r r |:RopeRename| -C-c r l |:RopeExtractVariable| -C-c r m |:RopeExtractMethod| -C-c r i |:RopeInline| -C-c r v |:RopeMove| -C-c r x |:RopeRestructure| -C-c r u |:RopeUseFunction| -C-c r f |:RopeIntroduceFactory| -C-c r s |:RopeChangeSignature| -C-c r 1 r |:RopeRenameCurrentModule| -C-c r 1 v |:RopeMoveCurrentModule| -C-c r 1 p |:RopeModuleToPackage| - -C-c r o |:RopeOrganizeImports| -C-c r n [vfcmp] |:RopeGenerate|(Variable|Function|Class|Module|Package) - -C-c r a / |:RopeCodeAssist| -C-c r a g |:RopeGotoDefinition| -C-c r a d |:RopeShowDoc| -C-c r a f |:RopeFindOccurrences| -C-c r a ? |:RopeLuckyAssist| -C-c r a j |:RopeJumpToGlobal| -C-c r a c |:RopeShowCalltip| - |:RopeAnalyzeModule| - - |:RopeAutoImport| - |:RopeGenerateAutoimportCache| -=============== ============================ - - -============================================================================== -10. Shortcuts ~ - *RopeShortcuts* - -Some commands are used very frequently; specially the commands in -code-assist group. You can define your own shortcuts like this: > - - :map <C-c>g :call RopeGotoDefinition() - -< - -================ ============================ -Key Command -================ ============================ -<C-Space> |:RopeCodeAssist| -<C-?> |:RopeLuckyAssist| -<C-c> g |:RopeGotoDefinition| -<C-c> d |:RopeShowDoc| -<C-c> f |:RopeFindOccurrences| -================ ============================ - ------------------------------------------------------------------------------- - - vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl: diff --git a/.vim/bundle/python-mode/ftplugin/pyrex.vim b/.vim/bundle/python-mode/ftplugin/pyrex.vim @@ -1 +0,0 @@ -runtime ftplugin/python/pymode.vim diff --git a/.vim/bundle/python-mode/ftplugin/python/init-pymode.vim b/.vim/bundle/python-mode/ftplugin/python/init-pymode.vim @@ -1,344 +0,0 @@ -if exists('did_init_pymode_vim') - finish -endif -let did_init_pymode_vim = 1 - -let g:pymode_version = "0.6.15" - -com! PymodeVersion echomsg "Current python-mode version: " . g:pymode_version - -" OPTION: g:pymode -- bool. Run pymode. -if pymode#Default('g:pymode', 1) || !g:pymode - " DESC: Disable script loading - finish -endif - -" DESC: Check python support -if !has('python') - let g:pymode_virtualenv = 0 - let g:pymode_path = 0 - let g:pymode_lint = 0 - let g:pymode_doc = 0 - let g:pymode_breakpoint = 0 - let g:pymode_rope = 0 - let g:pymode_run = 0 -endif - - -" Virtualenv {{{ - -if !pymode#Default("g:pymode_virtualenv", 1) || g:pymode_virtualenv - - call pymode#Default("g:pymode_virtualenv_enabled", []) - - " Add virtualenv paths - call pymode#virtualenv#Activate() - -endif - -" }}} - - -" DESC: Add pymode's pylibs to sys.path {{{ -if !pymode#Default('g:pymode_path', 1) || g:pymode_path - - call pymode#Default('g:pymode_paths', []) - -python << EOF -import sys, vim, os - -curpath = vim.eval("getcwd()") -libpath = os.path.join(vim.eval("expand('<sfile>:p:h:h:h')"), 'pylibs') - -sys.path = [libpath, curpath] + vim.eval("g:pymode_paths") + sys.path -EOF - -endif " }}} - - -" Lint {{{ - -if !pymode#Default("g:pymode_lint", 1) || g:pymode_lint - - let g:qf_list = [] - let g:pymode_lint_buffer = 0 - - " OPTION: g:pymode_lint_write -- bool. Check code every save. - call pymode#Default("g:pymode_lint_write", 1) - - " OPTION: g:pymode_lint_onfly -- bool. Check code every save. - call pymode#Default("g:pymode_lint_onfly", 0) - - " OPTION: g:pymode_lint_message -- bool. Show current line error message - call pymode#Default("g:pymode_lint_message", 1) - - " OPTION: g:pymode_lint_checker -- str. Choices are: pylint, pyflakes, pep8, mccabe - call pymode#Default("g:pymode_lint_checker", "pyflakes,pep8,mccabe") - - " OPTION: g:pymode_lint_config -- str. Path to pylint config file - call pymode#Default("g:pymode_lint_config", $HOME . "/.pylintrc") - - " OPTION: g:pymode_lint_cwindow -- bool. Auto open cwindow if errors find - call pymode#Default("g:pymode_lint_cwindow", 1) - - " OPTION: g:pymode_lint_jump -- int. Jump on first error. - call pymode#Default("g:pymode_lint_jump", 0) - - " OPTION: g:pymode_lint_hold -- int. Hold cursor on current window when - " quickfix open - call pymode#Default("g:pymode_lint_hold", 0) - - " OPTION: g:pymode_lint_minheight -- int. Minimal height of pymode lint window - call pymode#Default("g:pymode_lint_minheight", 3) - - " OPTION: g:pymode_lint_maxheight -- int. Maximal height of pymode lint window - call pymode#Default("g:pymode_lint_maxheight", 6) - - " OPTION: g:pymode_lint_ignore -- string. Skip errors and warnings (e.g. E4,W) - call pymode#Default("g:pymode_lint_ignore", "") - - " OPTION: g:pymode_lint_select -- string. Select errors and warnings (e.g. E4,W) - call pymode#Default("g:pymode_lint_select", "") - - " OPTION: g:pymode_lint_mccabe_complexity -- int. Maximum allowed complexity - call pymode#Default("g:pymode_lint_mccabe_complexity", 8) - - " OPTION: g:pymode_lint_signs_always_visible -- bool. Always show the - " errors ruller, even if there's no errors. - call pymode#Default("g:pymode_lint_signs_always_visible", 0) - - " OPTION: g:pymode_lint_signs -- bool. Place error signs - if (!pymode#Default("g:pymode_lint_signs", 1) || g:pymode_lint_signs) && has('signs') - - " DESC: Signs definition - sign define PymodeW text=WW texthl=Todo - sign define PymodeC text=CC texthl=Comment - sign define PymodeR text=RR texthl=Visual - sign define PymodeE text=EE texthl=Error - sign define PymodeI text=II texthl=Info - sign define PymodeF text=FF texthl=Info - - if !pymode#Default("g:pymode_lint_signs_always_visible", 0) || g:pymode_lint_signs_always_visible - " Show the sign's ruller if asked for, even it there's no error to show - sign define __dummy__ - autocmd BufRead,BufNew * call RopeShowSignsRulerIfNeeded() - endif - - endif - - " DESC: Set default pylint configuration - if !filereadable(g:pymode_lint_config) - let g:pymode_lint_config = expand("<sfile>:p:h:h:h") . "/pylint.ini" - endif - - py from pymode import queue - - au VimLeavePre * py queue.stop_queue() - -endif - -" }}} - - -" Documentation {{{ - -if !pymode#Default("g:pymode_doc", 1) || g:pymode_doc - - " OPTION: g:pymode_doc_key -- string. Key for show python documantation. - call pymode#Default("g:pymode_doc_key", "K") - -endif - -" }}} - - -" Breakpoints {{{ - -if !pymode#Default("g:pymode_breakpoint", 1) || g:pymode_breakpoint - - if !pymode#Default("g:pymode_breakpoint_cmd", "import ipdb; ipdb.set_trace() # XXX BREAKPOINT") && has("python") -python << EOF -from imp import find_module -try: - find_module('ipdb') -except ImportError: - vim.command('let g:pymode_breakpoint_cmd = "import pdb; pdb.set_trace() # XXX BREAKPOINT"') -EOF - endif - - " OPTION: g:pymode_breakpoint_key -- string. Key for set/unset breakpoint. - call pymode#Default("g:pymode_breakpoint_key", "<leader>b") - -endif - -" }}} - - -" Execution {{{ - -if !pymode#Default("g:pymode_run", 1) || g:pymode_run - - " OPTION: g:pymode_doc_key -- string. Key for show python documentation. - call pymode#Default("g:pymode_run_key", "<leader>r") - -endif - -" }}} - - -" Rope {{{ - -if !pymode#Default("g:pymode_rope", 1) || g:pymode_rope - - " OPTION: g:pymode_rope_auto_project -- bool. Auto create ropeproject - call pymode#Default("g:pymode_rope_auto_project", 1) - - " OPTION: g:pymode_rope_auto_project_open -- bool. - " Auto open existing projects, ie, if the current directory has a - " `.ropeproject` subdirectory. - call pymode#Default("g:pymode_rope_auto_project_open", 1) - - " OPTION: g:pymode_rope_auto_session_manage -- bool - call pymode#Default("g:pymode_rope_auto_session_manage", 0) - - " OPTION: g:pymode_rope_enable_autoimport -- bool. Enable autoimport - call pymode#Default("g:pymode_rope_enable_autoimport", 1) - - " OPTION: g:pymode_rope_autoimport_generate -- bool. - call pymode#Default("g:pymode_rope_autoimport_generate", 1) - - " OPTION: g:pymode_rope_autoimport_underlines -- bool. - call pymode#Default("g:pymode_rope_autoimport_underlineds", 0) - - " OPTION: g:pymode_rope_codeassist_maxfiles -- bool. - call pymode#Default("g:pymode_rope_codeassist_maxfixes", 10) - - " OPTION: g:pymode_rope_sorted_completions -- bool. - call pymode#Default("g:pymode_rope_sorted_completions", 1) - - " OPTION: g:pymode_rope_extended_complete -- bool. - call pymode#Default("g:pymode_rope_extended_complete", 1) - - " OPTION: g:pymode_rope_autoimport_modules -- array. - call pymode#Default("g:pymode_rope_autoimport_modules", ["os","shutil","datetime"]) - - " OPTION: g:pymode_rope_confirm_saving -- bool. - call pymode#Default("g:pymode_rope_confirm_saving", 1) - - " OPTION: g:pymode_rope_global_prefix -- string. - call pymode#Default("g:pymode_rope_global_prefix", "<C-x>p") - - " OPTION: g:pymode_rope_local_prefix -- string. - call pymode#Default("g:pymode_rope_local_prefix", "<C-c>r") - - " OPTION: g:pymode_rope_short_prefix -- string. - call pymode#Default("g:pymode_rope_short_prefix", "<C-c>") - - " OPTION: g:pymode_rope_map_space -- string. - call pymode#Default("g:pymode_rope_map_space", 1) - - " OPTION: g:pymode_rope_vim_completion -- bool. - call pymode#Default("g:pymode_rope_vim_completion", 1) - - " OPTION: g:pymode_rope_guess_project -- bool. - call pymode#Default("g:pymode_rope_guess_project", 1) - - " OPTION: g:pymode_rope_goto_def_newwin -- str ('new', 'vnew', ''). - call pymode#Default("g:pymode_rope_goto_def_newwin", "") - - " OPTION: g:pymode_rope_always_show_complete_menu -- bool. - call pymode#Default("g:pymode_rope_always_show_complete_menu", 0) - - " DESC: Init Rope - py import ropevim - - fun! RopeCodeAssistInsertMode() "{{{ - call RopeCodeAssist() - return "" - endfunction "}}} - - fun! RopeOpenExistingProject() "{{{ - if isdirectory(getcwd() . '/.ropeproject') - " In order to pass it the quiet kwarg I need to open the project - " using python and not vim, which should be no major issue - py ropevim._interface.open_project(quiet=True) - return "" - endif - endfunction "}}} - - fun! RopeLuckyAssistInsertMode() "{{{ - call RopeLuckyAssist() - return "" - endfunction "}}} - - fun! RopeOmni(findstart, base) "{{{ - if a:findstart - py ropevim._interface._find_start() - return g:pymode_offset - else - call RopeOmniComplete() - return g:pythoncomplete_completions - endif - endfunction "}}} - - fun! RopeShowSignsRulerIfNeeded() "{{{ - if &ft == 'python' - execute printf('silent! sign place 1 line=1 name=__dummy__ file=%s', expand("%:p")) - endif - endfunction "}}} - - - " Rope menu - menu <silent> Rope.Autoimport :RopeAutoImport<CR> - menu <silent> Rope.ChangeSignature :RopeChangeSignature<CR> - menu <silent> Rope.CloseProject :RopeCloseProject<CR> - menu <silent> Rope.GenerateAutoImportCache :RopeGenerateAutoimportCache<CR> - menu <silent> Rope.ExtractVariable :RopeExtractVariable<CR> - menu <silent> Rope.ExtractMethod :RopeExtractMethod<CR> - menu <silent> Rope.Inline :RopeInline<CR> - menu <silent> Rope.IntroduceFactory :RopeIntroduceFactory<CR> - menu <silent> Rope.FindFile :RopeFindFile<CR> - menu <silent> Rope.OpenProject :RopeOpenProject<CR> - menu <silent> Rope.Move :RopeMove<CR> - menu <silent> Rope.MoveCurrentModule :RopeMoveCurrentModule<CR> - menu <silent> Rope.ModuleToPackage :RopeModuleToPackage<CR> - menu <silent> Rope.Redo :RopeRedo<CR> - menu <silent> Rope.Rename :RopeRename<CR> - menu <silent> Rope.RenameCurrentModule :RopeRenameCurrentModule<CR> - menu <silent> Rope.Restructure :RopeRestructure<CR> - menu <silent> Rope.Undo :RopeUndo<CR> - menu <silent> Rope.UseFunction :RopeUseFunction<CR> - - if !pymode#Default("g:pymode_rope_auto_project_open", 1) || g:pymode_rope_auto_project_open - call RopeOpenExistingProject() - endif - - if !pymode#Default("g:pymode_rope_auto_session_manage", 0) || g:pymode_rope_auto_session_manage - autocmd VimLeave * call RopeSaveSession() - autocmd VimEnter * call RopeRestoreSession() - endif - -endif - -" }}} - - -" OPTION: g:pymode_folding -- bool. Enable python-mode folding for pyfiles. -call pymode#Default("g:pymode_folding", 1) - -" OPTION: g:pymode_syntax -- bool. Enable python-mode syntax for pyfiles. -call pymode#Default("g:pymode_syntax", 1) - -" OPTION: g:pymode_indent -- bool. Enable/Disable pymode PEP8 indentation -call pymode#Default("g:pymode_indent", 1) - -" OPTION: g:pymode_utils_whitespaces -- bool. Remove unused whitespaces on save -call pymode#Default("g:pymode_utils_whitespaces", 1) - -" OPTION: g:pymode_options -- bool. To set some python options. -call pymode#Default("g:pymode_options", 1) - -" OPTION: g:pymode_updatetime -- int. Set updatetime for async pymode's operation -call pymode#Default("g:pymode_updatetime", 1000) - -" vim: fdm=marker:fdl=0 diff --git a/.vim/bundle/python-mode/ftplugin/python/pymode.vim b/.vim/bundle/python-mode/ftplugin/python/pymode.vim @@ -1,156 +0,0 @@ -runtime ftplugin/python/init-pymode.vim - -if pymode#Default('b:pymode', 1) - finish -endif - - -" Parse pymode modeline -call pymode#Modeline() - - -" Syntax highlight -if pymode#Option('syntax') - let python_highlight_all=1 -endif - - -" Options {{{ - -" Python other options -if pymode#Option('options') - setlocal complete+=t - setlocal formatoptions-=t - if v:version > 702 && !&relativenumber - setlocal number - endif - setlocal nowrap - setlocal textwidth=79 -endif - -" }}} - - -" Documentation {{{ - -if pymode#Option('doc') - - " DESC: Set commands - command! -buffer -nargs=1 Pydoc call pymode#doc#Show("<args>") - - " DESC: Set keys - exe "nnoremap <silent> <buffer> " g:pymode_doc_key ":call pymode#doc#Show(expand('<cword>'))<CR>" - exe "vnoremap <silent> <buffer> " g:pymode_doc_key ":<C-U>call pymode#doc#Show(@*)<CR>" - -endif - -" }}} - - -" Lint {{{ - -if pymode#Option('lint') - - " DESC: Set commands - command! -buffer -nargs=0 PyLintToggle :call pymode#lint#Toggle() - command! -buffer -nargs=0 PyLintWindowToggle :call pymode#lint#ToggleWindow() - command! -buffer -nargs=0 PyLintCheckerToggle :call pymode#lint#ToggleChecker() - command! -buffer -nargs=0 PyLint :call pymode#lint#Check() - command! -buffer -nargs=0 PyLintAuto :call pymode#lint#Auto() - - " DESC: Set autocommands - if pymode#Option('lint_write') - au BufWritePost <buffer> PyLint - endif - - if pymode#Option('lint_onfly') - au InsertLeave <buffer> PyLint - endif - - if pymode#Option('lint_message') - au CursorHold <buffer> call pymode#lint#show_errormessage() - au CursorMoved <buffer> call pymode#lint#show_errormessage() - endif - - " DESC: Run queue - let &l:updatetime = g:pymode_updatetime - au CursorHold <buffer> call pymode#queue#Poll() - au BufLeave <buffer> py queue.stop_queue() - -endif - -" }}} - - -" Rope {{{ - -if pymode#Option('rope') - - " DESC: Set keys - exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "g :RopeGotoDefinition<CR>" - exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "d :RopeShowDoc<CR>" - exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "f :RopeFindOccurrences<CR>" - exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "m :emenu Rope . <TAB>" - inoremap <silent> <buffer> <S-TAB> <C-R>=RopeLuckyAssistInsertMode()<CR> - - if g:pymode_rope_map_space - let s:prascm = g:pymode_rope_always_show_complete_menu ? "<C-P>" : "" - exe "inoremap <silent> <buffer> <Nul> <C-R>=RopeCodeAssistInsertMode()<CR>" . s:prascm - exe "inoremap <silent> <buffer> <c-space> <C-R>=RopeCodeAssistInsertMode()<CR>" . s:prascm - endif - -endif - -" }}} - - -" Execution {{{ - -if pymode#Option('run') - - " DESC: Set commands - command! -buffer -nargs=0 -range=% Pyrun call pymode#run#Run(<f-line1>, <f-line2>) - - " DESC: Set keys - exe "nnoremap <silent> <buffer> " g:pymode_run_key ":Pyrun<CR>" - exe "vnoremap <silent> <buffer> " g:pymode_run_key ":Pyrun<CR>" - -endif - -" }}} - - -" Breakpoints {{{ - -if pymode#Option('breakpoint') - - " DESC: Set keys - exe "nnoremap <silent> <buffer> " g:pymode_breakpoint_key ":call pymode#breakpoint#Set(line('.'))<CR>" - -endif - -" }}} - - -" Utils {{{ - -if pymode#Option('utils_whitespaces') - au BufWritePre <buffer> call pymode#TrimWhiteSpace() -endif - -" }}} - - -" Folding {{{ - -if pymode#Option('folding') - - setlocal foldmethod=expr - setlocal foldexpr=pymode#folding#expr(v:lnum) - setlocal foldtext=pymode#folding#text() - -endif - -" }}} - -" vim: fdm=marker:fdl=0 diff --git a/.vim/bundle/python-mode/pylibs/__init__.py b/.vim/bundle/python-mode/pylibs/__init__.py diff --git a/.vim/bundle/python-mode/pylibs/autopep8.py b/.vim/bundle/python-mode/pylibs/autopep8.py @@ -1,2161 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2010-2011 Hideo Hattori -# Copyright (C) 2011-2013 Hideo Hattori, Steven Myint -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -"""Automatically formats Python code to conform to the PEP 8 style guide.""" - -from __future__ import print_function -from __future__ import division - -import codecs -import copy -import fnmatch -import inspect -import os -import re -import sys -try: - from StringIO import StringIO -except ImportError: - from io import StringIO -import token -import tokenize -from optparse import OptionParser -import difflib -import tempfile - -from pylama import pep8 - - -try: - unicode -except NameError: - unicode = str - - -__version__ = '0.8.7' - - -CR = '\r' -LF = '\n' -CRLF = '\r\n' - - -# For generating line shortening candidates. -SHORTEN_OPERATOR_GROUPS = frozenset([ - frozenset([',']), - frozenset(['%']), - frozenset([',', '(', '[', '{']), - frozenset([',', '(', '[', '{', '%', '+', '-', '*', '/', '//']), -]) - - -def open_with_encoding(filename, encoding=None, mode='r'): - """Return opened file with a specific encoding.""" - if not encoding: - encoding = detect_encoding(filename) - - import io - return io.open(filename, mode=mode, encoding=encoding, - newline='') # Preserve line endings - - -def detect_encoding(filename): - """Return file encoding.""" - try: - with open(filename, 'rb') as input_file: - from lib2to3.pgen2 import tokenize as lib2to3_tokenize - encoding = lib2to3_tokenize.detect_encoding(input_file.readline)[0] - - # Check for correctness of encoding - with open_with_encoding(filename, encoding) as test_file: - test_file.read() - - return encoding - except (SyntaxError, LookupError, UnicodeDecodeError): - return 'latin-1' - - -def read_from_filename(filename, readlines=False): - """Return contents of file.""" - with open_with_encoding(filename) as input_file: - return input_file.readlines() if readlines else input_file.read() - - -class FixPEP8(object): - - """Fix invalid code. - - Fixer methods are prefixed "fix_". The _fix_source() method looks for these - automatically. - - The fixer method can take either one or two arguments (in addition to - self). The first argument is "result", which is the error information from - pep8. The second argument, "logical", is required only for logical-line - fixes. - - The fixer method can return the list of modified lines or None. An empty - list would mean that no changes were made. None would mean that only the - line reported in the pep8 error was modified. Note that the modified line - numbers that are returned are indexed at 1. This typically would correspond - with the line number reported in the pep8 error information. - - [fixed method list] - - e111 - - e121,e122,e123,e124,e125,e126,e127,e128 - - e201,e202,e203 - - e211 - - e221,e222,e223,e224,e225 - - e231 - - e251 - - e261,e262 - - e271,e272,e273,e274 - - e301,e302,e303 - - e401 - - e502 - - e701,e702 - - e711 - - e721 - - w291,w293 - - w391 - - w602,w603,w604 - - """ - - def __init__(self, filename, options, contents=None): - self.filename = filename - if contents is None: - self.source = read_from_filename(filename, readlines=True) - else: - sio = StringIO(contents) - self.source = sio.readlines() - self.newline = find_newline(self.source) - self.options = options - self.indent_word = _get_indentword(unicode().join(self.source)) - self.logical_start = None - self.logical_end = None - # method definition - self.fix_e111 = self.fix_e101 - self.fix_e128 = self.fix_e127 - self.fix_e202 = self.fix_e201 - self.fix_e203 = self.fix_e201 - self.fix_e211 = self.fix_e201 - self.fix_e221 = self.fix_e271 - self.fix_e222 = self.fix_e271 - self.fix_e223 = self.fix_e271 - self.fix_e226 = self.fix_e225 - self.fix_e227 = self.fix_e225 - self.fix_e228 = self.fix_e225 - self.fix_e241 = self.fix_e271 - self.fix_e242 = self.fix_e224 - self.fix_e261 = self.fix_e262 - self.fix_e272 = self.fix_e271 - self.fix_e273 = self.fix_e271 - self.fix_e274 = self.fix_e271 - self.fix_e703 = self.fix_e702 - self.fix_w191 = self.fix_e101 - - def _fix_source(self, results): - completed_lines = set() - for result in sorted(results, key=_priority_key): - if result['line'] in completed_lines: - continue - - fixed_methodname = 'fix_%s' % result['id'].lower() - if hasattr(self, fixed_methodname): - fix = getattr(self, fixed_methodname) - - is_logical_fix = len(inspect.getargspec(fix).args) > 2 - if is_logical_fix: - # Do not run logical fix if any lines have been modified. - if completed_lines: - continue - - logical = self._get_logical(result) - if not logical: - continue - - modified_lines = fix(result, logical) - else: - modified_lines = fix(result) - - if modified_lines: - completed_lines.update(modified_lines) - elif modified_lines == []: # Empty list means no fix - if self.options.verbose >= 2: - print( - '---> Not fixing {f} on line {l}'.format( - f=result['id'], l=result['line']), - file=sys.stderr) - else: # We assume one-line fix when None - completed_lines.add(result['line']) - else: - if self.options.verbose >= 3: - print("---> '%s' is not defined." % fixed_methodname, - file=sys.stderr) - info = result['info'].strip() - print('---> %s:%s:%s:%s' % (self.filename, - result['line'], - result['column'], - info), - file=sys.stderr) - - def fix(self): - """Return a version of the source code with PEP 8 violations fixed.""" - pep8_options = { - 'ignore': self.options.ignore, - 'select': self.options.select, - 'max_line_length': self.options.max_line_length, - } - results = _execute_pep8(pep8_options, self.source) - - if self.options.verbose: - progress = {} - for r in results: - if r['id'] not in progress: - progress[r['id']] = set() - progress[r['id']].add(r['line']) - print('---> {n} issue(s) to fix {progress}'.format( - n=len(results), progress=progress), file=sys.stderr) - - self._fix_source(filter_results(source=unicode().join(self.source), - results=results, - aggressive=self.options.aggressive)) - return unicode().join(self.source) - - def fix_e101(self, _): - """Reindent all lines.""" - reindenter = Reindenter(self.source, self.newline) - modified_line_numbers = reindenter.run() - if modified_line_numbers: - self.source = reindenter.fixed_lines() - return modified_line_numbers - else: - return [] - - def find_logical(self, force=False): - # make a variable which is the index of all the starts of lines - if not force and self.logical_start is not None: - return - logical_start = [] - logical_end = [] - last_newline = True - sio = StringIO(''.join(self.source)) - parens = 0 - for t in tokenize.generate_tokens(sio.readline): - if t[0] in [tokenize.COMMENT, tokenize.DEDENT, - tokenize.INDENT, tokenize.NL, - tokenize.ENDMARKER]: - continue - if not parens and t[0] in [ - tokenize.NEWLINE, tokenize.SEMI - ]: - last_newline = True - logical_end.append((t[3][0] - 1, t[2][1])) - continue - if last_newline and not parens: - logical_start.append((t[2][0] - 1, t[2][1])) - last_newline = False - if t[0] == tokenize.OP: - if t[1] in '([{': - parens += 1 - elif t[1] in '}])': - parens -= 1 - self.logical_start = logical_start - self.logical_end = logical_end - - def _get_logical(self, result): - """Return the logical line corresponding to the result. - - Assumes input is already E702-clean. - - """ - try: - self.find_logical() - except (IndentationError, tokenize.TokenError): - return None - - row = result['line'] - 1 - col = result['column'] - 1 - ls = None - le = None - for i in range(0, len(self.logical_start), 1): - x = self.logical_end[i] - if x[0] > row or (x[0] == row and x[1] > col): - le = x - ls = self.logical_start[i] - break - if ls is None: - return None - original = self.source[ls[0]:le[0] + 1] - return ls, le, original - - def _fix_reindent(self, result, logical, fix_distinct=False): - """Fix a badly indented line. - - This is done by adding or removing from its initial indent only. - - """ - if not logical: - return [] - ls, _, original = logical - try: - rewrapper = Wrapper(original) - except (tokenize.TokenError, IndentationError): - return [] - valid_indents = rewrapper.pep8_expected() - if not rewrapper.rel_indent: - return [] - if result['line'] > ls[0]: - # got a valid continuation line number from pep8 - row = result['line'] - ls[0] - 1 - # always pick the first option for this - valid = valid_indents[row] - got = rewrapper.rel_indent[row] - else: - # Line number from pep8 isn't a continuation line. Instead, - # compare our own function's result, look for the first mismatch, - # and just hope that we take fewer than 100 iterations to finish. - for row in range(0, len(original), 1): - valid = valid_indents[row] - got = rewrapper.rel_indent[row] - if valid != got: - break - line = ls[0] + row - # always pick the expected indent, for now. - indent_to = valid[0] - if fix_distinct and indent_to == 4: - if len(valid) == 1: - return [] - else: - indent_to = valid[1] - - if got != indent_to: - orig_line = self.source[line] - new_line = ' ' * (indent_to) + orig_line.lstrip() - if new_line == orig_line: - return [] - else: - self.source[line] = new_line - return [line + 1] # Line indexed at 1 - else: - return [] - - def fix_e121(self, result, logical): - """Fix indentation to be a multiple of four.""" - # Fix by adjusting initial indent level. - return self._fix_reindent(result, logical) - - def fix_e122(self, result, logical): - """Add absent indentation for hanging indentation.""" - # Fix by adding an initial indent. - return self._fix_reindent(result, logical) - - def fix_e123(self, result, logical): - """Align closing bracket to match opening bracket.""" - # Fix by deleting whitespace to the correct level. - if not logical: - return [] - logical_lines = logical[2] - line_index = result['line'] - 1 - original_line = self.source[line_index] - - fixed_line = (_get_indentation(logical_lines[0]) + - original_line.lstrip()) - if fixed_line == original_line: - # Fall back to slower method. - return self._fix_reindent(result, logical) - else: - self.source[line_index] = fixed_line - - def fix_e124(self, result, logical): - """Align closing bracket to match visual indentation.""" - # Fix by inserting whitespace before the closing bracket. - return self._fix_reindent(result, logical) - - def fix_e125(self, result, logical): - """Indent to distinguish line from next logical line.""" - # Fix by indenting the line in error to the next stop. - modified_lines = self._fix_reindent(result, logical, fix_distinct=True) - if modified_lines: - return modified_lines - else: - # Fallback - line_index = result['line'] - 1 - original_line = self.source[line_index] - self.source[line_index] = self.indent_word + original_line - - def fix_e126(self, result, logical): - """Fix over-indented hanging indentation.""" - # fix by deleting whitespace to the left - if not logical: - return [] - logical_lines = logical[2] - line_index = result['line'] - 1 - original = self.source[line_index] - - fixed = (_get_indentation(logical_lines[0]) + - self.indent_word + original.lstrip()) - if fixed == original: - # Fall back to slower method. - return self._fix_reindent(result, logical) - else: - self.source[line_index] = fixed - - def fix_e127(self, result, logical): - """Fix visual indentation.""" - # Fix by inserting/deleting whitespace to the correct level. - modified_lines = self._align_visual_indent(result, logical) - if modified_lines != []: - return modified_lines - else: - # Fall back to slower method. - return self._fix_reindent(result, logical) - - def _align_visual_indent(self, result, logical): - """Correct visual indent. - - This includes over (E127) and under (E128) indented lines. - - """ - if not logical: - return [] - logical_lines = logical[2] - line_index = result['line'] - 1 - original = self.source[line_index] - fixed = original - - if logical_lines[0].rstrip().endswith('\\'): - fixed = (_get_indentation(logical_lines[0]) + - self.indent_word + original.lstrip()) - else: - for symbol in '([{': - if symbol in logical_lines[0]: - fixed = logical_lines[0].find( - symbol) * ' ' + original.lstrip() - break - - if fixed == original: - return [] - else: - self.source[line_index] = fixed - - def fix_e201(self, result): - """Remove extraneous whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - # When multiline strings are involved, pep8 reports the error as - # being at the start of the multiline string, which doesn't work - # for us. - if ('"""' in target or - "'''" in target or - target.rstrip().endswith('\\')): - return [] - - fixed = fix_whitespace(target, - offset=offset, - replacement='') - - if fixed == target: - return [] - else: - self.source[line_index] = fixed - - def fix_e224(self, result): - """Remove extraneous whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + target[offset:].replace('\t', ' ') - self.source[result['line'] - 1] = fixed - - def fix_e225(self, result): - """Fix missing whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + ' ' + target[offset:] - - # Only proceed if non-whitespace characters match. - # And make sure we don't break the indentation. - if (fixed.replace(' ', '') == target.replace(' ', '') and - _get_indentation(fixed) == _get_indentation(target)): - self.source[result['line'] - 1] = fixed - else: - return [] - - def fix_e231(self, result): - """Add missing whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - fixed = target[:offset] + ' ' + target[offset:] - self.source[line_index] = fixed - - def fix_e251(self, result): - """Remove whitespace around parameter '=' sign.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - # This is necessary since pep8 sometimes reports columns that goes - # past the end of the physical line. This happens in cases like, - # foo(bar\n=None) - c = min(result['column'] - 1, - len(target) - 1) - - if target[c].strip(): - fixed = target - else: - fixed = target[:c].rstrip() + target[c:].lstrip() - - # There could be an escaped newline - # - # def foo(a=\ - # 1) - if (fixed.endswith('=\\\n') or - fixed.endswith('=\\\r\n') or - fixed.endswith('=\\\r')): - self.source[line_index] = fixed.rstrip('\n\r \t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] # Line indexed at 1 - - self.source[result['line'] - 1] = fixed - - def fix_e262(self, result): - """Fix spacing after comment hash.""" - target = self.source[result['line'] - 1] - offset = result['column'] - - code = target[:offset].rstrip(' \t#') - comment = target[offset:].lstrip(' \t#') - - fixed = code + (' # ' + comment if comment.strip() - else self.newline) - - self.source[result['line'] - 1] = fixed - - def fix_e271(self, result): - """Fix extraneous whitespace around keywords.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - # When multiline strings are involved, pep8 reports the error as - # being at the start of the multiline string, which doesn't work - # for us. - if ('"""' in target or - "'''" in target or - target.rstrip().endswith('\\')): - return [] - - fixed = fix_whitespace(target, - offset=offset, - replacement=' ') - - if fixed == target: - return [] - else: - self.source[line_index] = fixed - - def fix_e301(self, result): - """Add missing blank line.""" - cr = self.newline - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e302(self, result): - """Add missing 2 blank lines.""" - add_linenum = 2 - int(result['info'].split()[-1]) - cr = self.newline * add_linenum - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e303(self, result): - """Remove extra blank lines.""" - delete_linenum = int(result['info'].split('(')[1].split(')')[0]) - 2 - delete_linenum = max(1, delete_linenum) - - # We need to count because pep8 reports an offset line number if there - # are comments. - cnt = 0 - line = result['line'] - 2 - modified_lines = [] - while cnt < delete_linenum: - if line < 0: - break - if not self.source[line].strip(): - self.source[line] = '' - modified_lines.append(1 + line) # Line indexed at 1 - cnt += 1 - line -= 1 - - return modified_lines - - def fix_e304(self, result): - """Remove blank line following function decorator.""" - line = result['line'] - 2 - if not self.source[line].strip(): - self.source[line] = '' - - def fix_e401(self, result): - """Put imports on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - if not target.lstrip().startswith('import'): - return [] - - # pep8 (1.3.1) reports false positive if there is an import statement - # followed by a semicolon and some unrelated statement with commas in - # it. - if ';' in target: - return [] - - indentation = re.split(pattern=r'\bimport\b', - string=target, maxsplit=1)[0] - fixed = (target[:offset].rstrip('\t ,') + self.newline + - indentation + 'import ' + target[offset:].lstrip('\t ,')) - self.source[line_index] = fixed - - def fix_e501(self, result): - """Try to make lines fit within --max-line-length characters.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - if target.lstrip().startswith('#'): - # Shorten comment if it is the last comment line. - try: - if self.source[line_index + 1].lstrip().startswith('#'): - return [] - except IndexError: - pass - - # Wrap commented lines. - fixed = shorten_comment( - line=target, - newline=self.newline, - max_line_length=self.options.max_line_length) - if fixed == self.source[line_index]: - return [] - else: - self.source[line_index] = fixed - return - - indent = _get_indentation(target) - source = target[len(indent):] - assert source.lstrip() == source - sio = StringIO(source) - - # Check for multiline string. - try: - tokens = list(tokenize.generate_tokens(sio.readline)) - except (tokenize.TokenError, IndentationError): - multi_line_candidate = break_multi_line( - target, newline=self.newline, - indent_word=self.indent_word) - - if multi_line_candidate: - self.source[line_index] = multi_line_candidate - return - else: - return [] - - candidates = shorten_line( - tokens, source, indent, - self.indent_word, newline=self.newline, - aggressive=self.options.aggressive) - - candidates = list(sorted( - set(candidates), - key=lambda x: line_shortening_rank(x, - self.newline, - self.indent_word))) - - if self.options.verbose >= 4: - print(('-' * 79 + '\n').join([''] + candidates + ['']), - file=sys.stderr) - - for _candidate in candidates: - if _candidate is None: - continue - - if _candidate == target: - continue - - if (get_longest_length(_candidate, self.newline) >= - get_longest_length(target, self.newline)): - continue - - self.source[line_index] = _candidate - return - - return [] - - def fix_e502(self, result): - """Remove extraneous escape of newline.""" - line_index = result['line'] - 1 - target = self.source[line_index] - self.source[line_index] = target.rstrip('\n\r \t\\') + self.newline - - def fix_e701(self, result): - """Put colon-separated compound statement on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - c = result['column'] - - fixed_source = (target[:c] + self.newline + - _get_indentation(target) + self.indent_word + - target[c:].lstrip('\n\r \t\\')) - self.source[result['line'] - 1] = fixed_source - - def fix_e702(self, result, logical): - """Put semicolon-separated compound statement on separate lines.""" - logical_lines = logical[2] - - line_index = result['line'] - 1 - target = self.source[line_index] - - if target.rstrip().endswith('\\'): - # Normalize '1; \\\n2' into '1; 2'. - self.source[line_index] = target.rstrip('\n \r\t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] - - if target.rstrip().endswith(';'): - self.source[line_index] = target.rstrip('\n \r\t;') + self.newline - return - - offset = result['column'] - 1 - first = target[:offset].rstrip(';').rstrip() - second = (_get_indentation(logical_lines[0]) + - target[offset:].lstrip(';').lstrip()) - - self.source[line_index] = first + self.newline + second - - def fix_e711(self, result): - """Fix comparison with None.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - if not right.startswith('None'): - return [] - - if center.strip() == '==': - new_center = 'is' - elif center.strip() == '!=': - new_center = 'is not' - else: - return [] - - self.source[line_index] = ' '.join([left, new_center, right]) - - def fix_e712(self, result): - """Fix comparison with boolean.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - # Handle simple cases only. - new_right = None - if center.strip() == '==': - if re.match(r'\bTrue\b', right): - new_right = re.sub(r'\bTrue\b *', '', right, count=1) - elif center.strip() == '!=': - if re.match(r'\bFalse\b', right): - new_right = re.sub(r'\bFalse\b *', '', right, count=1) - - if new_right is None: - return [] - - if new_right[0].isalnum(): - new_right = ' ' + new_right - - self.source[line_index] = left + new_right - - def fix_e721(self, _): - """Switch to use isinstance().""" - return self.refactor('idioms') - - def fix_w291(self, result): - """Remove trailing whitespace.""" - fixed_line = self.source[result['line'] - 1].rstrip() - self.source[result['line'] - 1] = '%s%s' % (fixed_line, self.newline) - - def fix_w293(self, result): - """Remove trailing whitespace on blank line.""" - assert not self.source[result['line'] - 1].strip() - self.source[result['line'] - 1] = self.newline - - def fix_w391(self, _): - """Remove trailing blank lines.""" - blank_count = 0 - for line in reversed(self.source): - line = line.rstrip() - if line: - break - else: - blank_count += 1 - - original_length = len(self.source) - self.source = self.source[:original_length - blank_count] - return range(1, 1 + original_length) - - def refactor(self, fixer_name, ignore=None): - """Return refactored code using lib2to3. - - Skip if ignore string is produced in the refactored code. - - """ - from lib2to3 import pgen2 - try: - new_text = refactor_with_2to3(''.join(self.source), - fixer_name=fixer_name) - except (pgen2.parse.ParseError, - UnicodeDecodeError, UnicodeEncodeError): - return [] - - original = unicode().join(self.source).strip() - if original == new_text.strip(): - return [] - else: - if ignore: - if ignore in new_text and ignore not in ''.join(self.source): - return [] - original_length = len(self.source) - self.source = [new_text] - return range(1, 1 + original_length) - - def fix_w601(self, _): - """Replace the {}.has_key() form with 'in'.""" - return self.refactor('has_key') - - def fix_w602(self, _): - """Fix deprecated form of raising exception.""" - return self.refactor('raise', - ignore='with_traceback') - - def fix_w603(self, _): - """Replace <> with !=.""" - return self.refactor('ne') - - def fix_w604(self, _): - """Replace backticks with repr().""" - return self.refactor('repr') - - -def find_newline(source): - """Return type of newline used in source.""" - cr, lf, crlf = 0, 0, 0 - for s in source: - if s.endswith(CRLF): - crlf += 1 - elif s.endswith(CR): - cr += 1 - elif s.endswith(LF): - lf += 1 - _max = max(cr, crlf, lf) - if _max == lf: - return LF - elif _max == crlf: - return CRLF - elif _max == cr: - return CR - else: - return LF - - -def _get_indentword(source): - """Return indentation type.""" - sio = StringIO(source) - indent_word = ' ' # Default in case source has no indentation - try: - for t in tokenize.generate_tokens(sio.readline): - if t[0] == token.INDENT: - indent_word = t[1] - break - except (tokenize.TokenError, IndentationError): - pass - return indent_word - - -def _get_indentation(line): - """Return leading whitespace.""" - if line.strip(): - non_whitespace_index = len(line) - len(line.lstrip()) - return line[:non_whitespace_index] - else: - return '' - - -def _get_difftext(old, new, filename): - diff = difflib.unified_diff( - old, new, - 'original/' + filename, - 'fixed/' + filename) - return ''.join(diff) - - -def _priority_key(pep8_result): - """Key for sorting PEP8 results. - - Global fixes should be done first. This is important for things - like indentation. - - """ - priority = ['e101', 'e111', 'w191', # Global fixes - 'e701', # Fix multiline colon-based before semicolon based - 'e702', # Break multiline statements early - 'e225', 'e231', # things that make lines longer - 'e201', # Remove extraneous whitespace before breaking lines - 'e501', # before we break lines - ] - key = pep8_result['id'].lower() - if key in priority: - return priority.index(key) - else: - # Lowest priority - return len(priority) - - -def shorten_line(tokens, source, indentation, indent_word, newline, - aggressive=False): - """Separate line at OPERATOR. - - Multiple candidates will be yielded. - - """ - for candidate in _shorten_line(tokens=tokens, - source=source, - indentation=indentation, - indent_word=indent_word, - newline=newline, - aggressive=aggressive): - yield candidate - - if aggressive: - for key_token_strings in SHORTEN_OPERATOR_GROUPS: - shortened = _shorten_line_at_tokens( - tokens=tokens, - source=source, - indentation=indentation, - indent_word=indent_word, - newline=newline, - key_token_strings=key_token_strings, - aggressive=aggressive) - - if shortened is not None and shortened != source: - yield shortened - - -def _shorten_line(tokens, source, indentation, indent_word, newline, - aggressive=False): - """Separate line at OPERATOR. - - Multiple candidates will be yielded. - - """ - for tkn in tokens: - # Don't break on '=' after keyword as this violates PEP 8. - if token.OP == tkn[0] and tkn[1] != '=': - assert tkn[0] != token.INDENT - - offset = tkn[2][1] + 1 - first = source[:offset] - - second_indent = indentation - if first.rstrip().endswith('('): - second_indent += indent_word - elif '(' in first: - second_indent += ' ' * (1 + first.find('(')) - else: - second_indent += indent_word - - second = (second_indent + source[offset:].lstrip()) - if not second.strip(): - continue - - # Do not begin a line with a comma - if second.lstrip().startswith(','): - continue - # Do end a line with a dot - if first.rstrip().endswith('.'): - continue - if tkn[1] in '+-*/': - fixed = first + ' \\' + newline + second - else: - fixed = first + newline + second - - # Only fix if syntax is okay. - if check_syntax(normalize_multiline(fixed) - if aggressive else fixed): - yield indentation + fixed - - -def _shorten_line_at_tokens(tokens, source, indentation, indent_word, newline, - key_token_strings, aggressive): - """Separate line by breaking at tokens in key_token_strings. - - This will always break the line at the first parenthesis. - - """ - offsets = [] - first_paren = True - for tkn in tokens: - token_type = tkn[0] - token_string = tkn[1] - next_offset = tkn[2][1] + 1 - - assert token_type != token.INDENT - - if token_string in key_token_strings or (first_paren and - token_string == '('): - # Don't split right before newline. - if next_offset < len(source) - 1: - offsets.append(next_offset) - - if token_string == '(': - first_paren = False - - current_indent = None - fixed = None - for line in split_at_offsets(source, offsets): - if fixed: - fixed += newline + current_indent + line - - for symbol in '([{': - if line.endswith(symbol): - current_indent += indent_word - else: - # First line. - fixed = line - assert not current_indent - current_indent = indent_word - - assert fixed is not None - - if check_syntax(normalize_multiline(fixed) - if aggressive > 1 else fixed): - return indentation + fixed - else: - return None - - -def normalize_multiline(line): - """Remove multiline-related code that will cause syntax error. - - This is for purposes of checking syntax. - - """ - for quote in '\'"': - dict_pattern = r'^{q}[^{q}]*{q}\s*:\s*'.format(q=quote) - if re.match(dict_pattern, line): - if not line.strip().endswith('}'): - line += '}' - return '{' + line - - if line.startswith('def ') and line.rstrip().endswith(':'): - # Do not allow ':' to be alone. That is invalid. - if ':' not in line.split(): - return line[len('def'):].strip().rstrip(':') - - return line - - -def fix_whitespace(line, offset, replacement): - """Replace whitespace at offset and return fixed line.""" - # Replace escaped newlines too - left = line[:offset].rstrip('\n\r \t\\') - right = line[offset:].lstrip('\n\r \t\\') - if right.startswith('#'): - return line - else: - return left + replacement + right - - -def _execute_pep8(pep8_options, source): - """Execute pep8 via python method calls.""" - class QuietReport(pep8.BaseReport): - - """Version of checker that does not print.""" - - def __init__(self, options): - super(QuietReport, self).__init__(options) - self.__full_error_results = [] - - def error(self, line_number, offset, text, _): - """Collect errors.""" - code = super(QuietReport, self).error(line_number, offset, text, _) - if code: - self.__full_error_results.append( - {'id': code, - 'line': line_number, - 'column': offset + 1, - 'info': text}) - - def full_error_results(self): - """Return error results in detail. - - Results are in the form of a list of dictionaries. Each dictionary - contains 'id', 'line', 'column', and 'info'. - - """ - return self.__full_error_results - - checker = pep8.Checker('', lines=source, - reporter=QuietReport, **pep8_options) - checker.check_all() - return checker.report.full_error_results() - - -class Reindenter(object): - - """Reindents badly-indented code to uniformly use four-space indentation. - - Released to the public domain, by Tim Peters, 03 October 2000. - - """ - - def __init__(self, input_text, newline): - self.newline = newline - - # Raw file lines. - self.raw = input_text - self.after = None - - self.string_content_line_numbers = multiline_string_lines( - ''.join(self.raw)) - - # File lines, rstripped & tab-expanded. Dummy at start is so - # that we can use tokenize's 1-based line numbering easily. - # Note that a line is all-blank iff it is a newline. - self.lines = [] - for line_number, line in enumerate(self.raw, start=1): - # Do not modify if inside a multi-line string. - if line_number in self.string_content_line_numbers: - self.lines.append(line) - else: - # Only expand leading tabs. - self.lines.append(_get_indentation(line).expandtabs() + - line.strip() + newline) - - self.lines.insert(0, None) - self.index = 1 # index into self.lines of next line - - def run(self): - """Fix indentation and return modified line numbers. - - Line numbers are indexed at 1. - - """ - try: - stats = reindent_stats(tokenize.generate_tokens(self.getline)) - except (tokenize.TokenError, IndentationError): - return set() - # Remove trailing empty lines. - lines = self.lines - while lines and lines[-1] == self.newline: - lines.pop() - # Sentinel. - stats.append((len(lines), 0)) - # Map count of leading spaces to # we want. - have2want = {} - # Program after transformation. - after = self.after = [] - # Copy over initial empty lines -- there's nothing to do until - # we see a line with *something* on it. - i = stats[0][0] - after.extend(lines[1:i]) - for i in range(len(stats) - 1): - thisstmt, thislevel = stats[i] - nextstmt = stats[i + 1][0] - have = _leading_space_count(lines[thisstmt]) - want = thislevel * 4 - if want < 0: - # A comment line. - if have: - # An indented comment line. If we saw the same - # indentation before, reuse what it most recently - # mapped to. - want = have2want.get(have, - 1) - if want < 0: - # Then it probably belongs to the next real stmt. - for j in range(i + 1, len(stats) - 1): - jline, jlevel = stats[j] - if jlevel >= 0: - if have == _leading_space_count(lines[jline]): - want = jlevel * 4 - break - if want < 0: # Maybe it's a hanging - # comment like this one, - # in which case we should shift it like its base - # line got shifted. - for j in range(i - 1, -1, -1): - jline, jlevel = stats[j] - if jlevel >= 0: - want = (have + _leading_space_count( - after[jline - 1]) - - _leading_space_count(lines[jline])) - break - if want < 0: - # Still no luck -- leave it alone. - want = have - else: - want = 0 - assert want >= 0 - have2want[have] = want - diff = want - have - if diff == 0 or have == 0: - after.extend(lines[thisstmt:nextstmt]) - else: - for line_number, line in enumerate(lines[thisstmt:nextstmt], - start=thisstmt): - if line_number in self.string_content_line_numbers: - after.append(line) - elif diff > 0: - if line == self.newline: - after.append(line) - else: - after.append(' ' * diff + line) - else: - remove = min(_leading_space_count(line), -diff) - after.append(line[remove:]) - - if self.raw == self.after: - return set() - else: - return (set(range(1, 1 + len(self.raw))) - - self.string_content_line_numbers) - - def fixed_lines(self): - return self.after - - def getline(self): - """Line-getter for tokenize.""" - if self.index >= len(self.lines): - line = '' - else: - line = self.lines[self.index] - self.index += 1 - return line - - -def reindent_stats(tokens): - """Return list of (lineno, indentlevel) pairs. - - One for each stmt and comment line. indentlevel is -1 for comment lines, as - a signal that tokenize doesn't know what to do about them; indeed, they're - our headache! - - """ - find_stmt = 1 # next token begins a fresh stmt? - level = 0 # current indent level - stats = [] - - for t in tokens: - token_type = t[0] - sline = t[2][0] - line = t[4] - - if token_type == tokenize.NEWLINE: - # A program statement, or ENDMARKER, will eventually follow, - # after some (possibly empty) run of tokens of the form - # (NL | COMMENT)* (INDENT | DEDENT+)? - find_stmt = 1 - - elif token_type == tokenize.INDENT: - find_stmt = 1 - level += 1 - - elif token_type == tokenize.DEDENT: - find_stmt = 1 - level -= 1 - - elif token_type == tokenize.COMMENT: - if find_stmt: - stats.append((sline, -1)) - # but we're still looking for a new stmt, so leave - # find_stmt alone - - elif token_type == tokenize.NL: - pass - - elif find_stmt: - # This is the first "real token" following a NEWLINE, so it - # must be the first token of the next program statement, or an - # ENDMARKER. - find_stmt = 0 - if line: # not endmarker - stats.append((sline, level)) - - return stats - - -class Wrapper(object): - - """Class for functions relating to continuation lines and line folding. - - Each instance operates on a single logical line. - - """ - - SKIP_TOKENS = frozenset([ - tokenize.COMMENT, tokenize.NL, tokenize.INDENT, - tokenize.DEDENT, tokenize.NEWLINE, tokenize.ENDMARKER - ]) - - def __init__(self, physical_lines): - self.lines = physical_lines - self.tokens = [] - self.rel_indent = None - sio = StringIO(''.join(physical_lines)) - for t in tokenize.generate_tokens(sio.readline): - if not len(self.tokens) and t[0] in self.SKIP_TOKENS: - continue - if t[0] != tokenize.ENDMARKER: - self.tokens.append(t) - - self.logical_line = self.build_tokens_logical(self.tokens) - - def build_tokens_logical(self, tokens): - """Build a logical line from a list of tokens. - - Return the logical line and a list of (offset, token) tuples. Does - not mute strings like the version in pep8.py. - - """ - # from pep8.py with minor modifications - logical = [] - previous = None - for t in tokens: - token_type, text = t[0:2] - if token_type in self.SKIP_TOKENS: - continue - if previous: - end_line, end = previous[3] - start_line, start = t[2] - if end_line != start_line: # different row - prev_text = self.lines[end_line - 1][end - 1] - if prev_text == ',' or (prev_text not in '{[(' - and text not in '}])'): - logical.append(' ') - elif end != start: # different column - fill = self.lines[end_line - 1][end:start] - logical.append(fill) - logical.append(text) - previous = t - logical_line = ''.join(logical) - assert logical_line.lstrip() == logical_line - assert logical_line.rstrip() == logical_line - return logical_line - - def pep8_expected(self): - """Replicate logic in pep8.py, to know what level to indent things to. - - Return a list of lists; each list represents valid indent levels for - the line in question, relative from the initial indent. However, the - first entry is the indent level which was expected. - - """ - # What follows is an adjusted version of - # pep8.py:continuation_line_indentation. All of the comments have been - # stripped and the 'yield' statements replaced with 'pass'. - tokens = self.tokens - if not tokens: - return - - first_row = tokens[0][2][0] - nrows = 1 + tokens[-1][2][0] - first_row - - # here are the return values - valid_indents = [list()] * nrows - indent_level = tokens[0][2][1] - valid_indents[0].append(indent_level) - - if nrows == 1: - # bug, really. - return valid_indents - - indent_next = self.logical_line.endswith(':') - - row = depth = 0 - parens = [0] * nrows - self.rel_indent = rel_indent = [0] * nrows - indent = [indent_level] - indent_chances = {} - last_indent = (0, 0) - last_token_multiline = None - - for token_type, text, start, end, _ in self.tokens: - newline = row < start[0] - first_row - if newline: - row = start[0] - first_row - newline = (not last_token_multiline and - token_type not in (tokenize.NL, tokenize.NEWLINE)) - - if newline: - # This is where the differences start. Instead of looking at - # the line and determining whether the observed indent matches - # our expectations, we decide which type of indentation is in - # use at the given indent level, and return the offset. This - # algorithm is susceptible to "carried errors", but should - # through repeated runs eventually solve indentation for - # multi-line expressions less than PEP8_PASSES_MAX lines long. - - if depth: - for open_row in range(row - 1, -1, -1): - if parens[open_row]: - break - else: - open_row = 0 - - # That's all we get to work with. This code attempts to - # "reverse" the below logic, and place into the valid indents - # list - vi = [] - add_second_chances = False - if token_type == tokenize.OP and text in ']})': - # this line starts with a closing bracket, so it needs to - # be closed at the same indent as the opening one. - if indent[depth]: - # hanging indent - vi.append(indent[depth]) - else: - # visual indent - vi.append(indent_level + rel_indent[open_row]) - elif depth and indent[depth]: - # visual indent was previously confirmed. - vi.append(indent[depth]) - add_second_chances = True - elif depth and True in indent_chances.values(): - # visual indent happened before, so stick to - # visual indent this time. - if depth > 1 and indent[depth - 1]: - vi.append(indent[depth - 1]) - else: - # stupid fallback - vi.append(indent_level + 4) - add_second_chances = True - elif not depth: - vi.append(indent_level + 4) - else: - # must be in hanging indent - hang = rel_indent[open_row] + 4 - vi.append(indent_level + hang) - - # about the best we can do without look-ahead - if (indent_next and vi[0] == indent_level + 4 and - nrows == row + 1): - vi[0] += 4 - - if add_second_chances: - # visual indenters like to line things up. - min_indent = vi[0] - for col, what in indent_chances.items(): - if col > min_indent and ( - what is True or - (what == str and token_type == tokenize.STRING) or - (what == text and token_type == tokenize.OP) - ): - vi.append(col) - vi = sorted(vi) - - valid_indents[row] = vi - - # Returning to original continuation_line_indentation() from - # pep8. - visual_indent = indent_chances.get(start[1]) - last_indent = start - rel_indent[row] = start[1] - indent_level - hang = rel_indent[row] - rel_indent[open_row] - - if token_type == tokenize.OP and text in ']})': - pass - elif visual_indent is True: - if not indent[depth]: - indent[depth] = start[1] - - # line altered: comments shouldn't define a visual indent - if parens[row] and not indent[depth] and token_type not in ( - tokenize.NL, tokenize.COMMENT - ): - indent[depth] = start[1] - indent_chances[start[1]] = True - elif token_type == tokenize.STRING or text in ( - 'u', 'ur', 'b', 'br' - ): - indent_chances[start[1]] = str - - if token_type == tokenize.OP: - if text in '([{': - depth += 1 - indent.append(0) - parens[row] += 1 - elif text in ')]}' and depth > 0: - prev_indent = indent.pop() or last_indent[1] - for d in range(depth): - if indent[d] > prev_indent: - indent[d] = 0 - for ind in list(indent_chances): - if ind >= prev_indent: - del indent_chances[ind] - depth -= 1 - if depth and indent[depth]: # modified - indent_chances[indent[depth]] = True - for idx in range(row, -1, -1): - if parens[idx]: - parens[idx] -= 1 - break - assert len(indent) == depth + 1 - if start[1] not in indent_chances: - indent_chances[start[1]] = text - - last_token_multiline = (start[0] != end[0]) - - return valid_indents - - -def _leading_space_count(line): - """Return number of leading spaces in line.""" - i = 0 - while i < len(line) and line[i] == ' ': - i += 1 - return i - - -def refactor_with_2to3(source_text, fixer_name): - """Use lib2to3 to refactor the source. - - Return the refactored source code. - - """ - from lib2to3 import refactor - fixers = ['lib2to3.fixes.fix_' + fixer_name] - tool = refactor.RefactoringTool( - fixer_names=fixers, - explicit=fixers) - return unicode(tool.refactor_string(source_text, name='')) - - -def break_multi_line(source_text, newline, indent_word): - """Break first line of multi-line code. - - Return None if a break is not possible. - - """ - indentation = _get_indentation(source_text) - - # Handle special case only. - for symbol in '([{': - # Only valid if symbol is not on a line by itself. - if (symbol in source_text - and source_text.rstrip().endswith(',') - and not source_text.lstrip().startswith(symbol)): - - index = 1 + source_text.find(symbol) - - if index <= len(indent_word) + len(indentation): - continue - - if is_probably_inside_string_or_comment(source_text, index - 1): - continue - - return ( - source_text[:index].rstrip() + newline + - indentation + indent_word + - source_text[index:].lstrip()) - - return None - - -def is_probably_inside_string_or_comment(line, index): - """Return True if index may be inside a string or comment.""" - # Make sure we are not in a string. - for quote in ['"', "'"]: - if quote in line: - if line.find(quote) <= index: - return True - - # Make sure we are not in a comment. - if '#' in line: - if line.find('#') <= index: - return True - - return False - - -def check_syntax(code): - """Return True if syntax is okay.""" - try: - return compile(code, '<string>', 'exec') - except (SyntaxError, TypeError, UnicodeDecodeError): - return False - - -def filter_results(source, results, aggressive=False): - """Filter out spurious reports from pep8. - - If aggressive is True, we allow possibly unsafe fixes (E711, E712). - - """ - non_docstring_string_line_numbers = multiline_string_lines( - source, include_docstrings=False) - all_string_line_numbers = multiline_string_lines( - source, include_docstrings=True) - - split_source = [None] + source.splitlines() - - for r in results: - issue_id = r['id'].lower() - - if r['line'] in non_docstring_string_line_numbers: - if issue_id.startswith('e1'): - continue - elif issue_id in ['e501', 'w191']: - continue - - if r['line'] in all_string_line_numbers: - if issue_id in ['e501']: - continue - - # Filter out incorrect E101 reports when there are no tabs. - # pep8 will complain about this even if the tab indentation found - # elsewhere is in a multi-line string. - if issue_id == 'e101' and '\t' not in split_source[r['line']]: - continue - - if issue_id in ['e711', 'e712'] and not aggressive: - continue - - yield r - - -def multiline_string_lines(source, include_docstrings=False): - """Return line numbers that are within multiline strings. - - The line numbers are indexed at 1. - - Docstrings are ignored. - - """ - sio = StringIO(source) - line_numbers = set() - previous_token_type = '' - try: - for t in tokenize.generate_tokens(sio.readline): - token_type = t[0] - start_row = t[2][0] - end_row = t[3][0] - start_row = t[2][0] - end_row = t[3][0] - - if (token_type == tokenize.STRING and start_row != end_row): - if (include_docstrings or - previous_token_type != tokenize.INDENT): - # We increment by one since we want the contents of the - # string. - line_numbers |= set(range(1 + start_row, 1 + end_row)) - - previous_token_type = token_type - except (IndentationError, tokenize.TokenError): - pass - - return line_numbers - - -def shorten_comment(line, newline, max_line_length): - """Return trimmed or split long comment line.""" - assert len(line) > max_line_length - line = line.rstrip() - - # PEP 8 recommends 72 characters for comment text. - indentation = _get_indentation(line) + '# ' - max_line_length = min(max_line_length, - len(indentation) + 72) - - MIN_CHARACTER_REPEAT = 5 - if (len(line) - len(line.rstrip(line[-1])) >= MIN_CHARACTER_REPEAT and - not line[-1].isalnum()): - # Trim comments that end with things like --------- - return line[:max_line_length] + newline - elif re.match(r'\s*#+\s*\w+', line): - import textwrap - split_lines = textwrap.wrap(line.lstrip(' \t#'), - initial_indent=indentation, - subsequent_indent=indentation, - width=max_line_length, - break_long_words=False) - return newline.join(split_lines) + newline - else: - return line + newline - - -def format_block_comments(source): - """Format block comments.""" - if '#' not in source: - # Optimization. - return source - - string_line_numbers = multiline_string_lines(source, - include_docstrings=True) - fixed_lines = [] - sio = StringIO(source) - for (line_number, line) in enumerate(sio.readlines(), start=1): - if (re.match(r'\s*#+\w+', line) and - line_number not in string_line_numbers): - fixed_lines.append(_get_indentation(line) + - '# ' + - line.lstrip().lstrip('#')) - else: - fixed_lines.append(line) - - return ''.join(fixed_lines) - - -def normalize_line_endings(lines): - """Return fixed line endings. - - All lines will be modified to use the most common line ending. - - """ - newline = find_newline(lines) - return [line.rstrip('\n\r') + newline for line in lines] - - -def mutual_startswith(a, b): - return b.startswith(a) or a.startswith(b) - - -def code_match(code, select, ignore): - if ignore: - for ignored_code in [c.strip() for c in ignore]: - if mutual_startswith(code.lower(), ignored_code.lower()): - return False - - if select: - for selected_code in [c.strip() for c in select]: - if mutual_startswith(code.lower(), selected_code.lower()): - return True - return False - - return True - - -def fix_string(source, options=None): - """Return fixed source code.""" - if not options: - options = parse_args([''])[0] - - sio = StringIO(source) - return fix_lines(sio.readlines(), options=options) - - -def fix_lines(source_lines, options, filename=''): - """Return fixed source code.""" - tmp_source = unicode().join(normalize_line_endings(source_lines)) - - # Keep a history to break out of cycles. - previous_hashes = set([hash(tmp_source)]) - - fixed_source = tmp_source - if code_match('e26', select=options.select, ignore=options.ignore): - fixed_source = format_block_comments(fixed_source) - - for _ in range(-1, options.pep8_passes): - tmp_source = copy.copy(fixed_source) - - fix = FixPEP8(filename, options, contents=tmp_source) - fixed_source = fix.fix() - - if hash(fixed_source) in previous_hashes: - break - else: - previous_hashes.add(hash(fixed_source)) - - return fixed_source - - -def fix_file(filename, options=None, output=None): - if not options: - options = parse_args([filename])[0] - - original_source = read_from_filename(filename, readlines=True) - - fixed_source = original_source - - if options.in_place: - encoding = detect_encoding(filename) - - fixed_source = fix_lines(fixed_source, options, filename=filename) - - if options.diff: - new = StringIO(fixed_source) - new = new.readlines() - diff = _get_difftext(original_source, new, filename) - if output: - output.write(diff) - else: - return output - elif options.in_place: - fp = open_with_encoding(filename, encoding=encoding, - mode='w') - fp.write(fixed_source) - fp.close() - else: - if output: - output.write(fixed_source) - else: - return fixed_source - - -def parse_args(args): - """Parse command-line options.""" - parser = OptionParser(usage='Usage: autopep8 [options] ' - '[filename [filename ...]]' - '\nUse filename \'-\' for stdin.', - version='autopep8: %s' % __version__, - description=__doc__, - prog='autopep8') - parser.add_option('-v', '--verbose', action='count', dest='verbose', - default=0, - help='print verbose messages; ' - 'multiple -v result in more verbose messages') - parser.add_option('-d', '--diff', action='store_true', dest='diff', - help='print the diff for the fixed source') - parser.add_option('-i', '--in-place', action='store_true', - help='make changes to files in place') - parser.add_option('-r', '--recursive', action='store_true', - help='run recursively; must be used with --in-place or ' - '--diff') - parser.add_option('-j', '--jobs', type=int, metavar='n', default=1, - help='number of parallel jobs; ' - 'match CPU count if value is less than 1') - parser.add_option('-p', '--pep8-passes', metavar='n', - default=100, type=int, - help='maximum number of additional pep8 passes' - ' (default: %default)') - parser.add_option('-a', '--aggressive', action='count', default=0, - help='enable possibly unsafe changes (E711, E712); ' - 'multiple -a result in more aggressive changes') - parser.add_option('--exclude', metavar='globs', - help='exclude files/directories that match these ' - 'comma-separated globs') - parser.add_option('--list-fixes', action='store_true', - help='list codes for fixes; ' - 'used by --ignore and --select') - parser.add_option('--ignore', metavar='errors', default='', - help='do not fix these errors/warnings ' - '(default {0})'.format(pep8.DEFAULT_IGNORE)) - parser.add_option('--select', metavar='errors', default='', - help='fix only these errors/warnings (e.g. E4,W)') - parser.add_option('--max-line-length', metavar='n', default=79, type=int, - help='set maximum allowed line length ' - '(default: %default)') - options, args = parser.parse_args(args) - - if not len(args) and not options.list_fixes: - parser.error('incorrect number of arguments') - - if '-' in args and len(args) > 1: - parser.error('cannot mix stdin and regular files') - - if len(args) > 1 and not (options.in_place or options.diff): - parser.error('autopep8 only takes one filename as argument ' - 'unless the "--in-place" or "--diff" options are ' - 'used') - - if options.recursive and not (options.in_place or options.diff): - parser.error('--recursive must be used with --in-place or --diff') - - if options.exclude and not options.recursive: - parser.error('--exclude is only relevant when used with --recursive') - - if options.in_place and options.diff: - parser.error('--in-place and --diff are mutually exclusive') - - if options.max_line_length <= 0: - parser.error('--max-line-length must be greater than 0') - - if args == ['-'] and (options.in_place or options.recursive): - parser.error('--in-place or --recursive cannot be used with ' - 'standard input') - - if options.select: - options.select = options.select.split(',') - - if options.ignore: - options.ignore = options.ignore.split(',') - elif not options.select and pep8.DEFAULT_IGNORE: - options.ignore = pep8.DEFAULT_IGNORE.split(',') - - if options.exclude: - options.exclude = options.exclude.split(',') - else: - options.exclude = [] - - if options.jobs < 1: - # Do not import multiprocessing globally in case it is not supported - # on the platform. - import multiprocessing - options.jobs = multiprocessing.cpu_count() - - if options.jobs > 1 and not options.in_place: - parser.error('parallel jobs requires --in-place') - - return options, args - - -def supported_fixes(): - """Yield pep8 error codes that autopep8 fixes. - - Each item we yield is a tuple of the code followed by its description. - - """ - instance = FixPEP8(filename=None, options=None, contents='') - for attribute in dir(instance): - code = re.match('fix_([ew][0-9][0-9][0-9])', attribute) - if code: - yield (code.group(1).upper(), - re.sub(r'\s+', ' ', - getattr(instance, attribute).__doc__)) - - -def line_shortening_rank(candidate, newline, indent_word): - """Return rank of candidate. - - This is for sorting candidates. - - """ - rank = 0 - if candidate: - lines = candidate.split(newline) - - offset = 0 - if lines[0].rstrip()[-1] not in '([{': - for symbol in '([{': - offset = max(offset, 1 + lines[0].find(symbol)) - - max_length = max([offset + len(x.strip()) for x in lines]) - rank += max_length - rank += len(lines) - - bad_staring_symbol = { - '(': ')', - '[': ']', - '{': '}'}.get(lines[0][-1], None) - - if len(lines) > 1: - if (bad_staring_symbol and - lines[1].lstrip().startswith(bad_staring_symbol)): - rank += 20 - else: - rank -= 10 - - if lines[0].endswith('(['): - rank += 10 - - for current_line in lines: - for bad_start in ['.', '%', '+', '-', '/']: - if current_line.startswith(bad_start): - rank += 100 - - for ending in '([{': - # Avoid lonely opening. They result in longer lines. - if (current_line.endswith(ending) and - len(current_line.strip()) <= len(indent_word)): - rank += 100 - - if current_line.endswith('%'): - rank -= 20 - else: - rank = 100000 - - return max(0, rank) - - -def split_at_offsets(line, offsets): - """Split line at offsets. - - Return list of strings. - - """ - result = [] - - previous_offset = 0 - current_offset = 0 - for current_offset in sorted(offsets): - if current_offset < len(line) and previous_offset != current_offset: - result.append(line[previous_offset:current_offset]) - previous_offset = current_offset - - result.append(line[current_offset:]) - - return result - - -def get_longest_length(text, newline): - """Return length of longest line.""" - return max([len(line) for line in text.split(newline)]) - - -class LineEndingWrapper(object): - - r"""Replace line endings to work with sys.stdout. - - It seems that sys.stdout expects only '\n' as the line ending, no matter - the platform. Otherwise, we get repeated line endings. - - """ - - def __init__(self, output): - self.__output = output - - def write(self, s): - self.__output.write(s.replace('\r\n', '\n').replace('\r', '\n')) - - def __getattr__(self, key): - return getattr(self.__output, key) - - -def temporary_file(): - """Return temporary file.""" - try: - return tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') - except TypeError: - return tempfile.NamedTemporaryFile(mode='w') - - -def match_file(filename, exclude): - """Return True if file is okay for modifying/recursing.""" - if not filename.endswith('.py'): - return False - - if filename.startswith('.'): - return False - - for pattern in exclude: - if fnmatch.fnmatch(filename, pattern): - return False - - return True - - -def find_files(filenames, recursive, exclude): - """Yield filenames.""" - while filenames: - name = filenames.pop(0) - if recursive and os.path.isdir(name): - for root, directories, children in os.walk(name): - filenames += [os.path.join(root, f) for f in children - if match_file(f, exclude)] - for d in directories: - if d.startswith('.'): - directories.remove(d) - else: - yield name - - -def _fix_file(parameters): - """Helper function for optionally running fix_file() in parallel.""" - if parameters[1].verbose: - print('[file:{0}]'.format(parameters[0]), file=sys.stderr) - try: - fix_file(*parameters) - except IOError as error: - print(str(error), file=sys.stderr) - - -def fix_multiple_files(filenames, options, output=None): - """Fix list of files. - - Optionally fix files recursively. - - """ - filenames = find_files(filenames, options.recursive, options.exclude) - if options.jobs > 1: - import multiprocessing - pool = multiprocessing.Pool(options.jobs) - pool.map(_fix_file, - [(name, options) for name in filenames]) - else: - for name in filenames: - _fix_file((name, options, output)) - - -def main(): - """Tool main.""" - if not pep8: - print('pep8 >= 1.3.2 required', file=sys.stderr) - return 1 - - try: - options, args = parse_args(sys.argv[1:]) - - if options.list_fixes: - for code, description in supported_fixes(): - print('{code} - {description}'.format( - code=code, description=description)) - return 0 - - if options.in_place or options.diff: - filenames = list(set(args)) - else: - assert len(args) == 1 - assert not options.recursive - if args == ['-']: - assert not options.in_place - temp = temporary_file() - temp.write(sys.stdin.read()) - temp.flush() - filenames = [temp.name] - else: - filenames = args[:1] - - output = codecs.getwriter('utf-8')(sys.stdout.buffer - if sys.version_info[0] >= 3 - else sys.stdout) - - output = LineEndingWrapper(output) - - fix_multiple_files(filenames, options, output) - except KeyboardInterrupt: - return 1 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/.vim/bundle/python-mode/pylibs/pylama/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/__init__.py @@ -1,8 +0,0 @@ -" pylama -- Python code audit. " - -version_info = (0, 3, 0) - -__version__ = version = '.'.join(map(str, version_info)) -__project__ = __name__ -__author__ = "Kirill Klenov <horneds@gmail.com>" -__license__ = "GNU LGPL" diff --git a/.vim/bundle/python-mode/pylibs/pylama/hook.py b/.vim/bundle/python-mode/pylibs/pylama/hook.py @@ -1,88 +0,0 @@ -import sys -from os import path as op, chmod -from subprocess import Popen, PIPE -from .main import logger - - -try: - from configparser import ConfigParser # nolint -except ImportError: # Python 2 - from ConfigParser import ConfigParser - - -def run(command): - p = Popen(command.split(), stdout=PIPE, stderr=PIPE) - (stdout, stderr) = p.communicate() - return (p.returncode, [line.strip() for line in stdout.splitlines()], - [line.strip() for line in stderr.splitlines()]) - - -def git_hook(): - from .main import check_files - _, files_modified, _ = run("git diff-index --cached --name-only HEAD") - logger.setLevel('WARN') - check_files([f for f in map(str, files_modified) if f.endswith('.py')]) - - -def hg_hook(ui, repo, **kwargs): - from .main import check_files - seen = set() - paths = [] - for rev in range(repo[kwargs['node']], len(repo)): - for file_ in repo[rev].files(): - file_ = op.join(repo.root, file_) - if file_ in seen or not op.exists(file_): - continue - seen.add(file_) - if file_.endswith('.py'): - paths.append(file_) - logger.setLevel('WARN') - check_files(paths) - - -def install_git(path): - hook = op.join(path, 'pre-commit') - with open(hook, 'w+') as fd: - fd.write("""#!/usr/bin/env python -import sys -from pylama.hook import git_hook - -if __name__ == '__main__': - sys.exit(git_hook()) -""") - chmod(hook, 484) - return True - - -def install_hg(path): - hook = op.join(path, 'hgrc') - if not op.isfile(hook): - open(hook, 'w+').close() - - c = ConfigParser() - c.readfp(open(path, 'r')) - if not c.has_section('hooks'): - c.add_section('hooks') - - if not c.has_option('hooks', 'commit'): - c.set('hooks', 'commit', 'python:pylama.hooks.hg_hook') - - if not c.has_option('hooks', 'qrefresh'): - c.set('hooks', 'qrefresh', 'python:pylama.hooks.hg_hook') - - c.write(open(path, 'w+')) - return True - - -def install_hook(path): - git = op.join(path, '.git', 'hooks') - hg = op.join(path, '.hg') - if op.exists(git): - install_git(git) and logger.warn('Git hook has been installed.') # nolint - - elif op.exists(hg): - install_hg(git) and logger.warn('Mercurial hook has been installed.') # nolint - - else: - logger.error('VCS has not found. Check your path.') - sys.exit(1) diff --git a/.vim/bundle/python-mode/pylibs/pylama/main.py b/.vim/bundle/python-mode/pylibs/pylama/main.py @@ -1,205 +0,0 @@ -import fnmatch -import re -import sys -from os import getcwd, walk, path as op - -import logging -from argparse import ArgumentParser - -from . import utils - - -default_linters = 'pep8', 'pyflakes', 'mccabe' -default_complexity = 10 -logger = logging.Logger('pylama') -stream = logging.StreamHandler() -logger.addHandler(stream) - -SKIP_PATTERN = '# nolint' - - -def run(path, ignore=None, select=None, linters=default_linters, **meta): # nolint - errors = [] - ignore = ignore and list(ignore) or [] - select = select and list(select) or [] - - for lint in linters: - try: - linter = getattr(utils, lint) - except AttributeError: - logging.warning("Linter `{0}` not found.".format(lint)) - continue - - try: - with open(path, "rU") as f: - code = f.read() + '\n\n' - params = parse_modeline(code) - params['skip'] = [False] - for line in code.split('\n'): - params['skip'].append(line.endswith(SKIP_PATTERN)) - - if params.get('lint_ignore'): - ignore += params.get('lint_ignore').split(',') - - if params.get('lint_select'): - select += params.get('lint_select').split(',') - - if params.get('lint'): - result = linter(path, code=code, **meta) - for e in result: - e['col'] = e.get('col') or 0 - e['lnum'] = e.get('lnum') or 0 - e['type'] = e.get('type') or 'E' - e['text'] = "{0} [{1}]".format((e.get( - 'text') or '').strip() - .replace("'", "\"").split('\n')[0], lint) - e['filename'] = path or '' - if not params['skip'][e['lnum']]: - errors.append(e) - - except IOError as e: - errors.append(dict( - lnum=0, - type='E', - col=0, - text=str(e) - )) - except SyntaxError as e: - errors.append(dict( - lnum=e.lineno or 0, - type='E', - col=e.offset or 0, - text=e.args[0] - )) - break - - except Exception as e: - import traceback - logging.error(traceback.format_exc()) - - errors = [e for e in errors if _ignore_error(e, select, ignore)] - return sorted(errors, key=lambda x: x['lnum']) - - -def _ignore_error(e, select, ignore): - for s in select: - if e['text'].startswith(s): - return True - for i in ignore: - if e['text'].startswith(i): - return False - return True - - -def shell(): - parser = ArgumentParser(description="Code audit tool for python.") - parser.add_argument("path", nargs='?', default=getcwd(), - help="Path on file or directory.") - parser.add_argument( - "--verbose", "-v", action='store_true', help="Verbose mode.") - - split_csp_list = lambda s: list(set(i for i in s.split(',') if i)) - - parser.add_argument( - "--format", "-f", default='pep8', choices=['pep8', 'pylint'], - help="Error format.") - parser.add_argument( - "--select", "-s", default='', - type=split_csp_list, - help="Select errors and warnings. (comma-separated)") - parser.add_argument( - "--linters", "-l", default=','.join(default_linters), - type=split_csp_list, - help="Select linters. (comma-separated)") - parser.add_argument( - "--ignore", "-i", default='', - type=split_csp_list, - help="Ignore errors and warnings. (comma-separated)") - parser.add_argument( - "--skip", default='', - type=lambda s: [re.compile(fnmatch.translate(p)) - for p in s.split(',')], - help="Skip files by masks (comma-separated, Ex. */messages.py)") - parser.add_argument("--complexity", "-c", default=default_complexity, - type=int, help="Set mccabe complexity.") - parser.add_argument("--report", "-r", help="Filename for report.") - parser.add_argument("--hook", action="store_true", - help="Install Git (Mercurial) hook.") - args = parser.parse_args() - - # Setup logger - logger.setLevel(logging.INFO if args.verbose else logging.WARN) - if args.report: - logger.removeHandler(stream) - logger.addHandler(logging.FileHandler(args.report, mode='w')) - - if args.hook: - from .hook import install_hook - return install_hook(args.path) - - paths = [args.path] - - if op.isdir(args.path): - paths = [] - for root, _, files in walk(args.path): - paths += [op.join(root, f) for f in files if f.endswith('.py')] - - check_files( - paths, - rootpath=args.path, - skip=args.skip, - frmt=args.format, - ignore=args.ignore, - select=args.select, - linters=args.linters, - complexity=args.complexity, - ) - - -def check_files(paths, rootpath=None, skip=None, frmt="pep8", - select=None, ignore=None, linters=default_linters, - complexity=default_complexity): - rootpath = rootpath or getcwd() - pattern = "%(rel)s:%(lnum)s:%(col)s: %(text)s" - if frmt == 'pylint': - pattern = "%(rel)s:%(lnum)s: [%(type)s] %(text)s" - - errors = [] - for path in skip_paths(skip, paths): - logger.info("Parse file: %s" % path) - errors = run(path, ignore=ignore, select=select, - linters=linters, complexity=complexity) - for error in errors: - try: - error['rel'] = op.relpath( - error['filename'], op.dirname(rootpath)) - error['col'] = error.get('col', 1) - logger.warning(pattern, error) - except KeyError: - continue - - sys.exit(int(bool(errors))) - - -MODERE = re.compile( - r'^\s*#\s+(?:pymode\:)?((?:lint[\w_]*=[^:\n\s]+:?)+)', re.I | re.M) - - -def skip_paths(skip, paths): - for path in paths: - if skip and any(pattern.match(path) for pattern in skip): - continue - yield path - - -def parse_modeline(code): - seek = MODERE.search(code) - params = dict(lint=1) - if seek: - params = dict(v.split('=') for v in seek.group(1).split(':')) - params['lint'] = int(params.get('lint', 1)) - return params - - -if __name__ == '__main__': - shell() diff --git a/.vim/bundle/python-mode/pylibs/pylama/mccabe.py b/.vim/bundle/python-mode/pylibs/pylama/mccabe.py @@ -1,312 +0,0 @@ -""" Meager code path measurement tool. - Ned Batchelder - http://nedbatchelder.com/blog/200803/python_code_complexity_microtool.html - MIT License. -""" -from __future__ import with_statement - -import sys - -import ast -import optparse -from ast import iter_child_nodes -from collections import defaultdict - - -__version__ = '0.2' - - -class ASTVisitor(object): - """Performs a depth-first walk of the AST.""" - - def __init__(self): - self.node = None - self._cache = {} - - def default(self, node, *args): - for child in iter_child_nodes(node): - self.dispatch(child, *args) - - def dispatch(self, node, *args): - self.node = node - klass = node.__class__ - meth = self._cache.get(klass) - if meth is None: - className = klass.__name__ - meth = getattr(self.visitor, 'visit' + className, self.default) - self._cache[klass] = meth - return meth(node, *args) - - def preorder(self, tree, visitor, *args): - """Do preorder walk of tree using visitor""" - self.visitor = visitor - visitor.visit = self.dispatch - self.dispatch(tree, *args) # XXX *args make sense? - - -class PathNode(object): - def __init__(self, name, look="circle"): - self.name = name - self.look = look - - def to_dot(self): - print('node [shape=%s,label="%s"] %d;' % ( - self.look, self.name, self.dot_id())) - - def dot_id(self): - return id(self) - - -class PathGraph(object): - def __init__(self, name, entity, lineno): - self.name = name - self.entity = entity - self.lineno = lineno - self.nodes = defaultdict(list) - - def connect(self, n1, n2): - self.nodes[n1].append(n2) - - def to_dot(self): - print('subgraph {') - for node in self.nodes: - node.to_dot() - for node, nexts in self.nodes.items(): - for next in nexts: - print('%s -- %s;' % (node.dot_id(), next.dot_id())) - print('}') - - def complexity(self): - """ Return the McCabe complexity for the graph. - V-E+2 - """ - num_edges = sum([len(n) for n in self.nodes.values()]) - num_nodes = len(self.nodes) - return num_edges - num_nodes + 2 - - -class PathGraphingAstVisitor(ASTVisitor): - """ A visitor for a parsed Abstract Syntax Tree which finds executable - statements. - """ - - def __init__(self): - super(PathGraphingAstVisitor, self).__init__() - self.classname = "" - self.graphs = {} - self.reset() - - def reset(self): - self.graph = None - self.tail = None - - def dispatch_list(self, node_list): - for node in node_list: - self.dispatch(node) - - def visitFunctionDef(self, node): - - if self.classname: - entity = '%s%s' % (self.classname, node.name) - else: - entity = node.name - - name = '%d:1: %r' % (node.lineno, entity) - - if self.graph is not None: - # closure - pathnode = self.appendPathNode(name) - self.tail = pathnode - self.dispatch_list(node.body) - bottom = PathNode("", look='point') - self.graph.connect(self.tail, bottom) - self.graph.connect(pathnode, bottom) - self.tail = bottom - else: - self.graph = PathGraph(name, entity, node.lineno) - pathnode = PathNode(name) - self.tail = pathnode - self.dispatch_list(node.body) - self.graphs["%s%s" % (self.classname, node.name)] = self.graph - self.reset() - - def visitClassDef(self, node): - old_classname = self.classname - self.classname += node.name + "." - self.dispatch_list(node.body) - self.classname = old_classname - - def appendPathNode(self, name): - if not self.tail: - return - pathnode = PathNode(name) - self.graph.connect(self.tail, pathnode) - self.tail = pathnode - return pathnode - - def visitSimpleStatement(self, node): - if node.lineno is None: - lineno = 0 - else: - lineno = node.lineno - name = "Stmt %d" % lineno - self.appendPathNode(name) - - visitAssert = visitAssign = visitAugAssign = visitDelete = visitPrint = \ - visitRaise = visitYield = visitImport = visitCall = visitSubscript = \ - visitPass = visitContinue = visitBreak = visitGlobal = visitReturn = \ - visitSimpleStatement - - def visitLoop(self, node): - name = "Loop %d" % node.lineno - - if self.graph is None: - # global loop - self.graph = PathGraph(name, name, node.lineno) - pathnode = PathNode(name) - self.tail = pathnode - self.dispatch_list(node.body) - self.graphs["%s%s" % (self.classname, name)] = self.graph - self.reset() - else: - pathnode = self.appendPathNode(name) - self.tail = pathnode - self.dispatch_list(node.body) - bottom = PathNode("", look='point') - self.graph.connect(self.tail, bottom) - self.graph.connect(pathnode, bottom) - self.tail = bottom - - # TODO: else clause in node.orelse - - visitFor = visitWhile = visitLoop - - def visitIf(self, node): - name = "If %d" % node.lineno - pathnode = self.appendPathNode(name) - loose_ends = [] - self.dispatch_list(node.body) - loose_ends.append(self.tail) - if node.orelse: - self.tail = pathnode - self.dispatch_list(node.orelse) - loose_ends.append(self.tail) - else: - loose_ends.append(pathnode) - if pathnode: - bottom = PathNode("", look='point') - for le in loose_ends: - self.graph.connect(le, bottom) - self.tail = bottom - - def visitTryExcept(self, node): - name = "TryExcept %d" % node.lineno - pathnode = self.appendPathNode(name) - loose_ends = [] - self.dispatch_list(node.body) - loose_ends.append(self.tail) - for handler in node.handlers: - self.tail = pathnode - self.dispatch_list(handler.body) - loose_ends.append(self.tail) - if pathnode: - bottom = PathNode("", look='point') - for le in loose_ends: - self.graph.connect(le, bottom) - self.tail = bottom - - def visitWith(self, node): - name = "With %d" % node.lineno - self.appendPathNode(name) - self.dispatch_list(node.body) - - -class McCabeChecker(object): - """McCabe cyclomatic complexity checker.""" - name = 'mccabe' - version = __version__ - _code = 'C901' - _error_tmpl = "C901 %r is too complex (%d)" - max_complexity = 0 - - def __init__(self, tree, filename): - self.tree = tree - - @classmethod - def add_options(cls, parser): - parser.add_option('--max-complexity', default=-1, action='store', - type='int', help="McCabe complexity threshold") - parser.config_options.append('max-complexity') - - @classmethod - def parse_options(cls, options): - cls.max_complexity = options.max_complexity - - def run(self): - if self.max_complexity < 0: - return - visitor = PathGraphingAstVisitor() - visitor.preorder(self.tree, visitor) - for graph in visitor.graphs.values(): - if graph.complexity() >= self.max_complexity: - text = self._error_tmpl % (graph.entity, graph.complexity()) - yield graph.lineno, 0, text, type(self) - - -def get_code_complexity(code, threshold=7, filename='stdin'): - try: - tree = compile(code, filename, "exec", ast.PyCF_ONLY_AST) - except SyntaxError: - e = sys.exc_info()[1] - sys.stderr.write("Unable to parse %s: %s\n" % (filename, e)) - return 0 - - complx = [] - McCabeChecker.max_complexity = threshold - for lineno, offset, text, _ in McCabeChecker(tree, filename).run(): - complx.append(dict( - type=McCabeChecker._code, - lnum=lineno, - text=text, - )) - - return complx - - -def get_module_complexity(module_path, threshold=7): - """Returns the complexity of a module""" - with open(module_path, "rU") as mod: - code = mod.read() - return get_code_complexity(code, threshold, filename=module_path) - - -def main(argv): - opar = optparse.OptionParser() - opar.add_option("-d", "--dot", dest="dot", - help="output a graphviz dot file", action="store_true") - opar.add_option("-m", "--min", dest="threshold", - help="minimum complexity for output", type="int", - default=2) - - options, args = opar.parse_args(argv) - - with open(args[0], "rU") as mod: - code = mod.read() - tree = compile(code, args[0], "exec", ast.PyCF_ONLY_AST) - visitor = PathGraphingAstVisitor() - visitor.preorder(tree, visitor) - - if options.dot: - print('graph {') - for graph in visitor.graphs.values(): - if graph.complexity() >= options.threshold: - graph.to_dot() - print('}') - else: - for graph in visitor.graphs.values(): - if graph.complexity() >= options.threshold: - print(graph.name, graph.complexity()) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pep8.py b/.vim/bundle/python-mode/pylibs/pylama/pep8.py @@ -1,1852 +0,0 @@ -#!/usr/bin/env python -# pep8.py - Check Python source code formatting, according to PEP 8 -# Copyright (C) 2006-2009 Johann C. Rocholl <johann@rocholl.net> -# Copyright (C) 2009-2013 Florent Xicluna <florent.xicluna@gmail.com> -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -r""" -Check Python source code formatting, according to PEP 8: -http://www.python.org/dev/peps/pep-0008/ - -For usage and a list of options, try this: -$ python pep8.py -h - -This program and its regression test suite live here: -http://github.com/jcrocholl/pep8 - -Groups of errors and warnings: -E errors -W warnings -100 indentation -200 whitespace -300 blank lines -400 imports -500 line length -600 deprecation -700 statements -900 syntax error -""" -__version__ = '1.4.6a0' - -import os -import sys -import re -import time -import inspect -import keyword -import tokenize -from optparse import OptionParser -from fnmatch import fnmatch -try: - from configparser import RawConfigParser - from io import TextIOWrapper -except ImportError: - from ConfigParser import RawConfigParser - -DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__' -DEFAULT_IGNORE = 'E226,E24' -if sys.platform == 'win32': - DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8') -else: - DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or - os.path.expanduser('~/.config'), 'pep8') -PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8') -TESTSUITE_PATH = os.path.join(os.path.dirname(__file__), 'testsuite') -MAX_LINE_LENGTH = 79 -REPORT_FORMAT = { - 'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s', - 'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s', -} - -PyCF_ONLY_AST = 1024 -SINGLETONS = frozenset(['False', 'None', 'True']) -KEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS -UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-']) -ARITHMETIC_OP = frozenset(['**', '*', '/', '//', '+', '-']) -WS_OPTIONAL_OPERATORS = ARITHMETIC_OP.union(['^', '&', '|', '<<', '>>', '%']) -WS_NEEDED_OPERATORS = frozenset([ - '**=', '*=', '/=', '//=', '+=', '-=', '!=', '<>', '<', '>', - '%=', '^=', '&=', '|=', '==', '<=', '>=', '<<=', '>>=', '=']) -WHITESPACE = frozenset(' \t') -SKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE, - tokenize.INDENT, tokenize.DEDENT]) -BENCHMARK_KEYS = ['directories', 'files', 'logical lines', 'physical lines'] - -INDENT_REGEX = re.compile(r'([ \t]*)') -RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,') -RERAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,\s*\w+\s*,\s*\w+') -ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b') -DOCSTRING_REGEX = re.compile(r'u?r?["\']') -EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]') -WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)') -COMPARE_SINGLETON_REGEX = re.compile(r'([=!]=)\s*(None|False|True)') -COMPARE_TYPE_REGEX = re.compile(r'(?:[=!]=|is(?:\s+not)?)\s*type(?:s.\w+Type' - r'|\s*\(\s*([^)]*[^ )])\s*\))') -KEYWORD_REGEX = re.compile(r'(\s*)\b(?:%s)\b(\s*)' % r'|'.join(KEYWORDS)) -OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+)(\s*)') -LAMBDA_REGEX = re.compile(r'\blambda\b') -HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$') - -# Work around Python < 2.6 behaviour, which does not generate NL after -# a comment which is on a line by itself. -COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n' - - -############################################################################## -# Plugins (check functions) for physical lines -############################################################################## - - -def tabs_or_spaces(physical_line, indent_char): - r""" - Never mix tabs and spaces. - - The most popular way of indenting Python is with spaces only. The - second-most popular way is with tabs only. Code indented with a mixture - of tabs and spaces should be converted to using spaces exclusively. When - invoking the Python command line interpreter with the -t option, it issues - warnings about code that illegally mixes tabs and spaces. When using -tt - these warnings become errors. These options are highly recommended! - - Okay: if a == 0:\n a = 1\n b = 1 - E101: if a == 0:\n a = 1\n\tb = 1 - """ - indent = INDENT_REGEX.match(physical_line).group(1) - for offset, char in enumerate(indent): - if char != indent_char: - return offset, "E101 indentation contains mixed spaces and tabs" - - -def tabs_obsolete(physical_line): - r""" - For new projects, spaces-only are strongly recommended over tabs. Most - editors have features that make this easy to do. - - Okay: if True:\n return - W191: if True:\n\treturn - """ - indent = INDENT_REGEX.match(physical_line).group(1) - if '\t' in indent: - return indent.index('\t'), "W191 indentation contains tabs" - - -def trailing_whitespace(physical_line): - r""" - JCR: Trailing whitespace is superfluous. - FBM: Except when it occurs as part of a blank line (i.e. the line is - nothing but whitespace). According to Python docs[1] a line with only - whitespace is considered a blank line, and is to be ignored. However, - matching a blank line to its indentation level avoids mistakenly - terminating a multi-line statement (e.g. class declaration) when - pasting code into the standard Python interpreter. - - [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines - - The warning returned varies on whether the line itself is blank, for easier - filtering for those who want to indent their blank lines. - - Okay: spam(1)\n# - W291: spam(1) \n# - W293: class Foo(object):\n \n bang = 12 - """ - physical_line = physical_line.rstrip('\n') # chr(10), newline - physical_line = physical_line.rstrip('\r') # chr(13), carriage return - physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L - stripped = physical_line.rstrip(' \t\v') - if physical_line != stripped: - if stripped: - return len(stripped), "W291 trailing whitespace" - else: - return 0, "W293 blank line contains whitespace" - - -def trailing_blank_lines(physical_line, lines, line_number): - r""" - JCR: Trailing blank lines are superfluous. - - Okay: spam(1) - W391: spam(1)\n - """ - if not physical_line.rstrip() and line_number == len(lines): - return 0, "W391 blank line at end of file" - - -def missing_newline(physical_line): - """ - JCR: The last line should have a newline. - - Reports warning W292. - """ - if physical_line.rstrip() == physical_line: - return len(physical_line), "W292 no newline at end of file" - - -def maximum_line_length(physical_line, max_line_length): - """ - Limit all lines to a maximum of 79 characters. - - There are still many devices around that are limited to 80 character - lines; plus, limiting windows to 80 characters makes it possible to have - several windows side-by-side. The default wrapping on such devices looks - ugly. Therefore, please limit all lines to a maximum of 79 characters. - For flowing long blocks of text (docstrings or comments), limiting the - length to 72 characters is recommended. - - Reports error E501. - """ - line = physical_line.rstrip() - length = len(line) - if length > max_line_length and not noqa(line): - if hasattr(line, 'decode'): # Python 2 - # The line could contain multi-byte characters - try: - length = len(line.decode('utf-8')) - except UnicodeError: - pass - if length > max_line_length: - return (max_line_length, "E501 line too long " - "(%d > %d characters)" % (length, max_line_length)) - - -############################################################################## -# Plugins (check functions) for logical lines -############################################################################## - - -def blank_lines(logical_line, blank_lines, indent_level, line_number, - previous_logical, previous_indent_level): - r""" - Separate top-level function and class definitions with two blank lines. - - Method definitions inside a class are separated by a single blank line. - - Extra blank lines may be used (sparingly) to separate groups of related - functions. Blank lines may be omitted between a bunch of related - one-liners (e.g. a set of dummy implementations). - - Use blank lines in functions, sparingly, to indicate logical sections. - - Okay: def a():\n pass\n\n\ndef b():\n pass - Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass - - E301: class Foo:\n b = 0\n def bar():\n pass - E302: def a():\n pass\n\ndef b(n):\n pass - E303: def a():\n pass\n\n\n\ndef b(n):\n pass - E303: def a():\n\n\n\n pass - E304: @decorator\n\ndef a():\n pass - """ - if line_number < 3 and not previous_logical: - return # Don't expect blank lines before the first line - if previous_logical.startswith('@'): - if blank_lines: - yield 0, "E304 blank lines found after function decorator" - elif blank_lines > 2 or (indent_level and blank_lines == 2): - yield 0, "E303 too many blank lines (%d)" % blank_lines - elif logical_line.startswith(('def ', 'class ', '@')): - if indent_level: - if not (blank_lines or previous_indent_level < indent_level or - DOCSTRING_REGEX.match(previous_logical)): - yield 0, "E301 expected 1 blank line, found 0" - elif blank_lines != 2: - yield 0, "E302 expected 2 blank lines, found %d" % blank_lines - - -def extraneous_whitespace(logical_line): - """ - Avoid extraneous whitespace in the following situations: - - - Immediately inside parentheses, brackets or braces. - - - Immediately before a comma, semicolon, or colon. - - Okay: spam(ham[1], {eggs: 2}) - E201: spam( ham[1], {eggs: 2}) - E201: spam(ham[ 1], {eggs: 2}) - E201: spam(ham[1], { eggs: 2}) - E202: spam(ham[1], {eggs: 2} ) - E202: spam(ham[1 ], {eggs: 2}) - E202: spam(ham[1], {eggs: 2 }) - - E203: if x == 4: print x, y; x, y = y , x - E203: if x == 4: print x, y ; x, y = y, x - E203: if x == 4 : print x, y; x, y = y, x - """ - line = logical_line - for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line): - text = match.group() - char = text.strip() - found = match.start() - if text == char + ' ': - # assert char in '([{' - yield found + 1, "E201 whitespace after '%s'" % char - elif line[found - 1] != ',': - code = ('E202' if char in '}])' else 'E203') # if char in ',;:' - yield found, "%s whitespace before '%s'" % (code, char) - - -def whitespace_around_keywords(logical_line): - r""" - Avoid extraneous whitespace around keywords. - - Okay: True and False - E271: True and False - E272: True and False - E273: True and\tFalse - E274: True\tand False - """ - for match in KEYWORD_REGEX.finditer(logical_line): - before, after = match.groups() - - if '\t' in before: - yield match.start(1), "E274 tab before keyword" - elif len(before) > 1: - yield match.start(1), "E272 multiple spaces before keyword" - - if '\t' in after: - yield match.start(2), "E273 tab after keyword" - elif len(after) > 1: - yield match.start(2), "E271 multiple spaces after keyword" - - -def missing_whitespace(logical_line): - """ - JCR: Each comma, semicolon or colon should be followed by whitespace. - - Okay: [a, b] - Okay: (3,) - Okay: a[1:4] - Okay: a[:4] - Okay: a[1:] - Okay: a[1:4:2] - E231: ['a','b'] - E231: foo(bar,baz) - E231: [{'a':'b'}] - """ - line = logical_line - for index in range(len(line) - 1): - char = line[index] - if char in ',;:' and line[index + 1] not in WHITESPACE: - before = line[:index] - if char == ':' and before.count('[') > before.count(']') and \ - before.rfind('{') < before.rfind('['): - continue # Slice syntax, no space required - if char == ',' and line[index + 1] == ')': - continue # Allow tuple with only one element: (3,) - yield index, "E231 missing whitespace after '%s'" % char - - -def indentation(logical_line, previous_logical, indent_char, - indent_level, previous_indent_level): - r""" - Use 4 spaces per indentation level. - - For really old code that you don't want to mess up, you can continue to - use 8-space tabs. - - Okay: a = 1 - Okay: if a == 0:\n a = 1 - E111: a = 1 - - Okay: for item in items:\n pass - E112: for item in items:\npass - - Okay: a = 1\nb = 2 - E113: a = 1\n b = 2 - """ - if indent_char == ' ' and indent_level % 4: - yield 0, "E111 indentation is not a multiple of four" - indent_expect = previous_logical.endswith(':') - if indent_expect and indent_level <= previous_indent_level: - yield 0, "E112 expected an indented block" - if indent_level > previous_indent_level and not indent_expect: - yield 0, "E113 unexpected indentation" - - -def continued_indentation(logical_line, tokens, indent_level, noqa, verbose): - r""" - Continuation lines should align wrapped elements either vertically using - Python's implicit line joining inside parentheses, brackets and braces, or - using a hanging indent. - - When using a hanging indent the following considerations should be applied: - - - there should be no arguments on the first line, and - - - further indentation should be used to clearly distinguish itself as a - continuation line. - - Okay: a = (\n) - E123: a = (\n ) - - Okay: a = (\n 42) - E121: a = (\n 42) - E122: a = (\n42) - E123: a = (\n 42\n ) - E124: a = (24,\n 42\n) - E125: if (a or\n b):\n pass - E126: a = (\n 42) - E127: a = (24,\n 42) - E128: a = (24,\n 42) - """ - first_row = tokens[0][2][0] - nrows = 1 + tokens[-1][2][0] - first_row - if noqa or nrows == 1: - return - - # indent_next tells us whether the next block is indented; assuming - # that it is indented by 4 spaces, then we should not allow 4-space - # indents on the final continuation line; in turn, some other - # indents are allowed to have an extra 4 spaces. - indent_next = logical_line.endswith(':') - - row = depth = 0 - # remember how many brackets were opened on each line - parens = [0] * nrows - # relative indents of physical lines - rel_indent = [0] * nrows - # visual indents - indent_chances = {} - last_indent = tokens[0][2] - indent = [last_indent[1]] - if verbose >= 3: - print(">>> " + tokens[0][4].rstrip()) - - for token_type, text, start, end, line in tokens: - - newline = row < start[0] - first_row - if newline: - row = start[0] - first_row - newline = (not last_token_multiline and - token_type not in (tokenize.NL, tokenize.NEWLINE)) - - if newline: - # this is the beginning of a continuation line. - last_indent = start - if verbose >= 3: - print("... " + line.rstrip()) - - # record the initial indent. - rel_indent[row] = expand_indent(line) - indent_level - - if depth: - # a bracket expression in a continuation line. - # find the line that it was opened on - for open_row in range(row - 1, -1, -1): - if parens[open_row]: - break - else: - # an unbracketed continuation line (ie, backslash) - open_row = 0 - hang = rel_indent[row] - rel_indent[open_row] - visual_indent = indent_chances.get(start[1]) - - if token_type == tokenize.OP and text in ']})': - # this line starts with a closing bracket - if indent[depth]: - if start[1] != indent[depth]: - yield (start, "E124 closing bracket does not match " - "visual indentation") - elif hang: - yield (start, "E123 closing bracket does not match " - "indentation of opening bracket's line") - elif visual_indent is True: - # visual indent is verified - if not indent[depth]: - indent[depth] = start[1] - elif visual_indent in (text, str): - # ignore token lined up with matching one from a previous line - pass - elif indent[depth] and start[1] < indent[depth]: - # visual indent is broken - yield (start, "E128 continuation line " - "under-indented for visual indent") - elif hang == 4 or (indent_next and rel_indent[row] == 8): - # hanging indent is verified - pass - else: - # indent is broken - if hang <= 0: - error = "E122", "missing indentation or outdented" - elif indent[depth]: - error = "E127", "over-indented for visual indent" - elif hang % 4: - error = "E121", "indentation is not a multiple of four" - else: - error = "E126", "over-indented for hanging indent" - yield start, "%s continuation line %s" % error - - # look for visual indenting - if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT) - and not indent[depth]): - indent[depth] = start[1] - indent_chances[start[1]] = True - if verbose >= 4: - print("bracket depth %s indent to %s" % (depth, start[1])) - # deal with implicit string concatenation - elif (token_type in (tokenize.STRING, tokenize.COMMENT) or - text in ('u', 'ur', 'b', 'br')): - indent_chances[start[1]] = str - # special case for the "if" statement because len("if (") == 4 - elif not indent_chances and not row and not depth and text == 'if': - indent_chances[end[1] + 1] = True - - # keep track of bracket depth - if token_type == tokenize.OP: - if text in '([{': - depth += 1 - indent.append(0) - parens[row] += 1 - if verbose >= 4: - print("bracket depth %s seen, col %s, visual min = %s" % - (depth, start[1], indent[depth])) - elif text in ')]}' and depth > 0: - # parent indents should not be more than this one - prev_indent = indent.pop() or last_indent[1] - for d in range(depth): - if indent[d] > prev_indent: - indent[d] = 0 - for ind in list(indent_chances): - if ind >= prev_indent: - del indent_chances[ind] - depth -= 1 - if depth: - indent_chances[indent[depth]] = True - for idx in range(row, -1, -1): - if parens[idx]: - parens[idx] -= 1 - break - assert len(indent) == depth + 1 - if start[1] not in indent_chances: - # allow to line up tokens - indent_chances[start[1]] = text - - last_token_multiline = (start[0] != end[0]) - - if indent_next and rel_indent[-1] == 4: - yield (last_indent, "E125 continuation line does not distinguish " - "itself from next logical line") - - -def whitespace_before_parameters(logical_line, tokens): - """ - Avoid extraneous whitespace in the following situations: - - - Immediately before the open parenthesis that starts the argument - list of a function call. - - - Immediately before the open parenthesis that starts an indexing or - slicing. - - Okay: spam(1) - E211: spam (1) - - Okay: dict['key'] = list[index] - E211: dict ['key'] = list[index] - E211: dict['key'] = list [index] - """ - prev_type, prev_text, __, prev_end, __ = tokens[0] - for index in range(1, len(tokens)): - token_type, text, start, end, __ = tokens[index] - if (token_type == tokenize.OP and - text in '([' and - start != prev_end and - (prev_type == tokenize.NAME or prev_text in '}])') and - # Syntax "class A (B):" is allowed, but avoid it - (index < 2 or tokens[index - 2][1] != 'class') and - # Allow "return (a.foo for a in range(5))" - not keyword.iskeyword(prev_text)): - yield prev_end, "E211 whitespace before '%s'" % text - prev_type = token_type - prev_text = text - prev_end = end - - -def whitespace_around_operator(logical_line): - r""" - Avoid extraneous whitespace in the following situations: - - - More than one space around an assignment (or other) operator to - align it with another. - - Okay: a = 12 + 3 - E221: a = 4 + 5 - E222: a = 4 + 5 - E223: a = 4\t+ 5 - E224: a = 4 +\t5 - """ - for match in OPERATOR_REGEX.finditer(logical_line): - before, after = match.groups() - - if '\t' in before: - yield match.start(1), "E223 tab before operator" - elif len(before) > 1: - yield match.start(1), "E221 multiple spaces before operator" - - if '\t' in after: - yield match.start(2), "E224 tab after operator" - elif len(after) > 1: - yield match.start(2), "E222 multiple spaces after operator" - - -def missing_whitespace_around_operator(logical_line, tokens): - r""" - - Always surround these binary operators with a single space on - either side: assignment (=), augmented assignment (+=, -= etc.), - comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), - Booleans (and, or, not). - - - Use spaces around arithmetic operators. - - Okay: i = i + 1 - Okay: submitted += 1 - Okay: x = x * 2 - 1 - Okay: hypot2 = x * x + y * y - Okay: c = (a + b) * (a - b) - Okay: foo(bar, key='word', *args, **kwargs) - Okay: alpha[:-i] - - E225: i=i+1 - E225: submitted +=1 - E225: x = x /2 - 1 - E225: z = x **y - E226: c = (a+b) * (a-b) - E226: hypot2 = x*x + y*y - E227: c = a|b - E228: msg = fmt%(errno, errmsg) - """ - parens = 0 - need_space = False - prev_type = tokenize.OP - prev_text = prev_end = None - for token_type, text, start, end, line in tokens: - if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN): - # ERRORTOKEN is triggered by backticks in Python 3 - continue - if text in ('(', 'lambda'): - parens += 1 - elif text == ')': - parens -= 1 - if need_space: - if start != prev_end: - # Found a (probably) needed space - if need_space is not True and not need_space[1]: - yield (need_space[0], - "E225 missing whitespace around operator") - need_space = False - elif text == '>' and prev_text in ('<', '-'): - # Tolerate the "<>" operator, even if running Python 3 - # Deal with Python 3's annotated return value "->" - pass - else: - if need_space is True or need_space[1]: - # A needed trailing space was not found - yield prev_end, "E225 missing whitespace around operator" - else: - code, optype = 'E226', 'arithmetic' - if prev_text == '%': - code, optype = 'E228', 'modulo' - elif prev_text not in ARITHMETIC_OP: - code, optype = 'E227', 'bitwise or shift' - yield (need_space[0], "%s missing whitespace " - "around %s operator" % (code, optype)) - need_space = False - elif token_type == tokenize.OP and prev_end is not None: - if text == '=' and parens: - # Allow keyword args or defaults: foo(bar=None). - pass - elif text in WS_NEEDED_OPERATORS: - need_space = True - elif text in UNARY_OPERATORS: - # Check if the operator is being used as a binary operator - # Allow unary operators: -123, -x, +1. - # Allow argument unpacking: foo(*args, **kwargs). - if prev_type == tokenize.OP: - binary_usage = (prev_text in '}])') - elif prev_type == tokenize.NAME: - binary_usage = (prev_text not in KEYWORDS) - else: - binary_usage = (prev_type not in SKIP_TOKENS) - - if binary_usage: - need_space = None - elif text in WS_OPTIONAL_OPERATORS: - need_space = None - - if need_space is None: - # Surrounding space is optional, but ensure that - # trailing space matches opening space - need_space = (prev_end, start != prev_end) - elif need_space and start == prev_end: - # A needed opening space was not found - yield prev_end, "E225 missing whitespace around operator" - need_space = False - prev_type = token_type - prev_text = text - prev_end = end - - -def whitespace_around_comma(logical_line): - r""" - Avoid extraneous whitespace in the following situations: - - - More than one space around an assignment (or other) operator to - align it with another. - - Note: these checks are disabled by default - - Okay: a = (1, 2) - E241: a = (1, 2) - E242: a = (1,\t2) - """ - line = logical_line - for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line): - found = m.start() + 1 - if '\t' in m.group(): - yield found, "E242 tab after '%s'" % m.group()[0] - else: - yield found, "E241 multiple spaces after '%s'" % m.group()[0] - - -def whitespace_around_named_parameter_equals(logical_line, tokens): - """ - Don't use spaces around the '=' sign when used to indicate a - keyword argument or a default parameter value. - - Okay: def complex(real, imag=0.0): - Okay: return magic(r=real, i=imag) - Okay: boolean(a == b) - Okay: boolean(a != b) - Okay: boolean(a <= b) - Okay: boolean(a >= b) - - E251: def complex(real, imag = 0.0): - E251: return magic(r = real, i = imag) - """ - parens = 0 - no_space = False - prev_end = None - message = "E251 unexpected spaces around keyword / parameter equals" - for token_type, text, start, end, line in tokens: - if no_space: - no_space = False - if start != prev_end: - yield (prev_end, message) - elif token_type == tokenize.OP: - if text == '(': - parens += 1 - elif text == ')': - parens -= 1 - elif parens and text == '=': - no_space = True - if start != prev_end: - yield (prev_end, message) - prev_end = end - - -def whitespace_before_inline_comment(logical_line, tokens): - """ - Separate inline comments by at least two spaces. - - An inline comment is a comment on the same line as a statement. Inline - comments should be separated by at least two spaces from the statement. - They should start with a # and a single space. - - Okay: x = x + 1 # Increment x - Okay: x = x + 1 # Increment x - E261: x = x + 1 # Increment x - E262: x = x + 1 #Increment x - E262: x = x + 1 # Increment x - """ - prev_end = (0, 0) - for token_type, text, start, end, line in tokens: - if token_type == tokenize.COMMENT: - if not line[:start[1]].strip(): - continue - if prev_end[0] == start[0] and start[1] < prev_end[1] + 2: - yield (prev_end, - "E261 at least two spaces before inline comment") - symbol, sp, comment = text.partition(' ') - if symbol not in ('#', '#:') or comment[:1].isspace(): - yield start, "E262 inline comment should start with '# '" - elif token_type != tokenize.NL: - prev_end = end - - -def imports_on_separate_lines(logical_line): - r""" - Imports should usually be on separate lines. - - Okay: import os\nimport sys - E401: import sys, os - - Okay: from subprocess import Popen, PIPE - Okay: from myclas import MyClass - Okay: from foo.bar.yourclass import YourClass - Okay: import myclass - Okay: import foo.bar.yourclass - """ - line = logical_line - if line.startswith('import '): - found = line.find(',') - if -1 < found and ';' not in line[:found]: - yield found, "E401 multiple imports on one line" - - -def compound_statements(logical_line): - r""" - Compound statements (multiple statements on the same line) are - generally discouraged. - - While sometimes it's okay to put an if/for/while with a small body - on the same line, never do this for multi-clause statements. Also - avoid folding such long lines! - - Okay: if foo == 'blah':\n do_blah_thing() - Okay: do_one() - Okay: do_two() - Okay: do_three() - - E701: if foo == 'blah': do_blah_thing() - E701: for x in lst: total += x - E701: while t < 10: t = delay() - E701: if foo == 'blah': do_blah_thing() - E701: else: do_non_blah_thing() - E701: try: something() - E701: finally: cleanup() - E701: if foo == 'blah': one(); two(); three() - - E702: do_one(); do_two(); do_three() - E703: do_four(); # useless semicolon - """ - line = logical_line - last_char = len(line) - 1 - found = line.find(':') - if -1 < found < last_char: - before = line[:found] - if (before.count('{') <= before.count('}') and # {'a': 1} (dict) - before.count('[') <= before.count(']') and # [1:2] (slice) - before.count('(') <= before.count(')') and # (Python 3 annotation) - not LAMBDA_REGEX.search(before)): # lambda x: x - yield found, "E701 multiple statements on one line (colon)" - found = line.find(';') - if -1 < found: - if found < last_char: - yield found, "E702 multiple statements on one line (semicolon)" - else: - yield found, "E703 statement ends with a semicolon" - - -def explicit_line_join(logical_line, tokens): - r""" - Avoid explicit line join between brackets. - - The preferred way of wrapping long lines is by using Python's implied line - continuation inside parentheses, brackets and braces. Long lines can be - broken over multiple lines by wrapping expressions in parentheses. These - should be used in preference to using a backslash for line continuation. - - E502: aaa = [123, \\n 123] - E502: aaa = ("bbb " \\n "ccc") - - Okay: aaa = [123,\n 123] - Okay: aaa = ("bbb "\n "ccc") - Okay: aaa = "bbb " \\n "ccc" - """ - prev_start = prev_end = parens = 0 - for token_type, text, start, end, line in tokens: - if start[0] != prev_start and parens and backslash: - yield backslash, "E502 the backslash is redundant between brackets" - if end[0] != prev_end: - if line.rstrip('\r\n').endswith('\\'): - backslash = (end[0], len(line.splitlines()[-1]) - 1) - else: - backslash = None - prev_start = prev_end = end[0] - else: - prev_start = start[0] - if token_type == tokenize.OP: - if text in '([{': - parens += 1 - elif text in ')]}': - parens -= 1 - - -def comparison_to_singleton(logical_line, noqa): - """ - Comparisons to singletons like None should always be done - with "is" or "is not", never the equality operators. - - Okay: if arg is not None: - E711: if arg != None: - E712: if arg == True: - - Also, beware of writing if x when you really mean if x is not None -- - e.g. when testing whether a variable or argument that defaults to None was - set to some other value. The other value might have a type (such as a - container) that could be false in a boolean context! - """ - match = not noqa and COMPARE_SINGLETON_REGEX.search(logical_line) - if match: - same = (match.group(1) == '==') - singleton = match.group(2) - msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton) - if singleton in ('None',): - code = 'E711' - else: - code = 'E712' - nonzero = ((singleton == 'True' and same) or - (singleton == 'False' and not same)) - msg += " or 'if %scond:'" % ('' if nonzero else 'not ') - yield match.start(1), ("%s comparison to %s should be %s" % - (code, singleton, msg)) - - -def comparison_type(logical_line): - """ - Object type comparisons should always use isinstance() instead of - comparing types directly. - - Okay: if isinstance(obj, int): - E721: if type(obj) is type(1): - - When checking if an object is a string, keep in mind that it might be a - unicode string too! In Python 2.3, str and unicode have a common base - class, basestring, so you can do: - - Okay: if isinstance(obj, basestring): - Okay: if type(a1) is type(b1): - """ - match = COMPARE_TYPE_REGEX.search(logical_line) - if match: - inst = match.group(1) - if inst and isidentifier(inst) and inst not in SINGLETONS: - return # Allow comparison for types which are not obvious - yield match.start(), "E721 do not compare types, use 'isinstance()'" - - -def python_3000_has_key(logical_line): - r""" - The {}.has_key() method is removed in the Python 3. - Use the 'in' operation instead. - - Okay: if "alph" in d:\n print d["alph"] - W601: assert d.has_key('alph') - """ - pos = logical_line.find('.has_key(') - if pos > -1: - yield pos, "W601 .has_key() is deprecated, use 'in'" - - -def python_3000_raise_comma(logical_line): - """ - When raising an exception, use "raise ValueError('message')" - instead of the older form "raise ValueError, 'message'". - - The paren-using form is preferred because when the exception arguments - are long or include string formatting, you don't need to use line - continuation characters thanks to the containing parentheses. The older - form is removed in Python 3. - - Okay: raise DummyError("Message") - W602: raise DummyError, "Message" - """ - match = RAISE_COMMA_REGEX.match(logical_line) - if match and not RERAISE_COMMA_REGEX.match(logical_line): - yield match.end() - 1, "W602 deprecated form of raising exception" - - -def python_3000_not_equal(logical_line): - """ - != can also be written <>, but this is an obsolete usage kept for - backwards compatibility only. New code should always use !=. - The older syntax is removed in Python 3. - - Okay: if a != 'no': - W603: if a <> 'no': - """ - pos = logical_line.find('<>') - if pos > -1: - yield pos, "W603 '<>' is deprecated, use '!='" - - -def python_3000_backticks(logical_line): - """ - Backticks are removed in Python 3. - Use repr() instead. - - Okay: val = repr(1 + 2) - W604: val = `1 + 2` - """ - pos = logical_line.find('`') - if pos > -1: - yield pos, "W604 backticks are deprecated, use 'repr()'" - - -############################################################################## -# Helper functions -############################################################################## - - -if '' == ''.encode(): - # Python 2: implicit encoding. - def readlines(filename): - f = open(filename) - try: - return f.readlines() - finally: - f.close() - - isidentifier = re.compile(r'[a-zA-Z_]\w*').match - stdin_get_value = sys.stdin.read -else: - # Python 3 - def readlines(filename): - f = open(filename, 'rb') - try: - coding, lines = tokenize.detect_encoding(f.readline) - f = TextIOWrapper(f, coding, line_buffering=True) - return [l.decode(coding) for l in lines] + f.readlines() - except (LookupError, SyntaxError, UnicodeError): - f.close() - # Fall back if files are improperly declared - f = open(filename, encoding='latin-1') - return f.readlines() - finally: - f.close() - - isidentifier = str.isidentifier - - def stdin_get_value(): - return TextIOWrapper(sys.stdin.buffer, errors='ignore').read() -readlines.__doc__ = " Read the source code." -noqa = re.compile(r'# no(?:qa|pep8)\b', re.I).search - - -def expand_indent(line): - r""" - Return the amount of indentation. - Tabs are expanded to the next multiple of 8. - - >>> expand_indent(' ') - 4 - >>> expand_indent('\t') - 8 - >>> expand_indent(' \t') - 8 - >>> expand_indent(' \t') - 8 - >>> expand_indent(' \t') - 16 - """ - if '\t' not in line: - return len(line) - len(line.lstrip()) - result = 0 - for char in line: - if char == '\t': - result = result // 8 * 8 + 8 - elif char == ' ': - result += 1 - else: - break - return result - - -def mute_string(text): - """ - Replace contents with 'xxx' to prevent syntax matching. - - >>> mute_string('"abc"') - '"xxx"' - >>> mute_string("'''abc'''") - "'''xxx'''" - >>> mute_string("r'abc'") - "r'xxx'" - """ - # String modifiers (e.g. u or r) - start = text.index(text[-1]) + 1 - end = len(text) - 1 - # Triple quotes - if text[-3:] in ('"""', "'''"): - start += 2 - end -= 2 - return text[:start] + 'x' * (end - start) + text[end:] - - -def parse_udiff(diff, patterns=None, parent='.'): - """Return a dictionary of matching lines.""" - # For each file of the diff, the entry key is the filename, - # and the value is a set of row numbers to consider. - rv = {} - path = nrows = None - for line in diff.splitlines(): - if nrows: - if line[:1] != '-': - nrows -= 1 - continue - if line[:3] == '@@ ': - hunk_match = HUNK_REGEX.match(line) - row, nrows = [int(g or '1') for g in hunk_match.groups()] - rv[path].update(range(row, row + nrows)) - elif line[:3] == '+++': - path = line[4:].split('\t', 1)[0] - if path[:2] == 'b/': - path = path[2:] - rv[path] = set() - return dict([(os.path.join(parent, path), rows) - for (path, rows) in rv.items() - if rows and filename_match(path, patterns)]) - - -def filename_match(filename, patterns, default=True): - """ - Check if patterns contains a pattern that matches filename. - If patterns is unspecified, this always returns True. - """ - if not patterns: - return default - return any(fnmatch(filename, pattern) for pattern in patterns) - - -############################################################################## -# Framework to run all checks -############################################################################## - - -_checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}} - - -def register_check(check, codes=None): - """ - Register a new check object. - """ - def _add_check(check, kind, codes, args): - if check in _checks[kind]: - _checks[kind][check][0].extend(codes or []) - else: - _checks[kind][check] = (codes or [''], args) - if inspect.isfunction(check): - args = inspect.getargspec(check)[0] - if args and args[0] in ('physical_line', 'logical_line'): - if codes is None: - codes = ERRORCODE_REGEX.findall(check.__doc__ or '') - _add_check(check, args[0], codes, args) - elif inspect.isclass(check): - if inspect.getargspec(check.__init__)[0][:2] == ['self', 'tree']: - _add_check(check, 'tree', codes, None) - - -def init_checks_registry(): - """ - Register all globally visible functions where the first argument name - is 'physical_line' or 'logical_line'. - """ - mod = inspect.getmodule(register_check) - for (name, function) in inspect.getmembers(mod, inspect.isfunction): - register_check(function) -init_checks_registry() - - -class Checker(object): - """ - Load a Python source file, tokenize it, check coding style. - """ - - def __init__(self, filename=None, lines=None, - options=None, report=None, **kwargs): - if options is None: - options = StyleGuide(kwargs).options - else: - assert not kwargs - self._io_error = None - self._physical_checks = options.physical_checks - self._logical_checks = options.logical_checks - self._ast_checks = options.ast_checks - self.max_line_length = options.max_line_length - self.verbose = options.verbose - self.filename = filename - if filename is None: - self.filename = 'stdin' - self.lines = lines or [] - elif filename == '-': - self.filename = 'stdin' - self.lines = stdin_get_value().splitlines(True) - elif lines is None: - try: - self.lines = readlines(filename) - except IOError: - exc_type, exc = sys.exc_info()[:2] - self._io_error = '%s: %s' % (exc_type.__name__, exc) - self.lines = [] - else: - self.lines = lines - self.report = report or options.report - self.report_error = self.report.error - - def report_invalid_syntax(self): - exc_type, exc = sys.exc_info()[:2] - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - self.report_error(offset[0], offset[1] or 0, - 'E901 %s: %s' % (exc_type.__name__, exc.args[0]), - self.report_invalid_syntax) - report_invalid_syntax.__doc__ = " Check if the syntax is valid." - - def readline(self): - """ - Get the next line from the input buffer. - """ - self.line_number += 1 - if self.line_number > len(self.lines): - return '' - return self.lines[self.line_number - 1] - - def readline_check_physical(self): - """ - Check and return the next physical line. This method can be - used to feed tokenize.generate_tokens. - """ - line = self.readline() - if line: - self.check_physical(line) - return line - - def run_check(self, check, argument_names): - """ - Run a check plugin. - """ - arguments = [] - for name in argument_names: - arguments.append(getattr(self, name)) - return check(*arguments) - - def check_physical(self, line): - """ - Run all physical checks on a raw input line. - """ - self.physical_line = line - if self.indent_char is None and line[:1] in WHITESPACE: - self.indent_char = line[0] - for name, check, argument_names in self._physical_checks: - result = self.run_check(check, argument_names) - if result is not None: - offset, text = result - self.report_error(self.line_number, offset, text, check) - - def build_tokens_line(self): - """ - Build a logical line from tokens. - """ - self.mapping = [] - logical = [] - comments = [] - length = 0 - previous = None - for token in self.tokens: - token_type, text = token[0:2] - if token_type == tokenize.COMMENT: - comments.append(text) - continue - if token_type in SKIP_TOKENS: - continue - if token_type == tokenize.STRING: - text = mute_string(text) - if previous: - end_row, end = previous[3] - start_row, start = token[2] - if end_row != start_row: # different row - prev_text = self.lines[end_row - 1][end - 1] - if prev_text == ',' or (prev_text not in '{[(' - and text not in '}])'): - logical.append(' ') - length += 1 - elif end != start: # different column - fill = self.lines[end_row - 1][end:start] - logical.append(fill) - length += len(fill) - self.mapping.append((length, token)) - logical.append(text) - length += len(text) - previous = token - self.logical_line = ''.join(logical) - self.noqa = comments and noqa(''.join(comments)) - # With Python 2, if the line ends with '\r\r\n' the assertion fails - # assert self.logical_line.strip() == self.logical_line - - def check_logical(self): - """ - Build a line from tokens and run all logical checks on it. - """ - self.build_tokens_line() - self.report.increment_logical_line() - first_line = self.lines[self.mapping[0][1][2][0] - 1] - indent = first_line[:self.mapping[0][1][2][1]] - self.previous_indent_level = self.indent_level - self.indent_level = expand_indent(indent) - if self.verbose >= 2: - print(self.logical_line[:80].rstrip()) - for name, check, argument_names in self._logical_checks: - if self.verbose >= 4: - print(' ' + name) - for result in self.run_check(check, argument_names): - offset, text = result - if isinstance(offset, tuple): - orig_number, orig_offset = offset - else: - for token_offset, token in self.mapping: - if offset >= token_offset: - orig_number = token[2][0] - orig_offset = (token[2][1] + offset - token_offset) - self.report_error(orig_number, orig_offset, text, check) - self.previous_logical = self.logical_line - - def check_ast(self): - try: - tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST) - except SyntaxError: - return self.report_invalid_syntax() - for name, cls, _ in self._ast_checks: - checker = cls(tree, self.filename) - for lineno, offset, text, check in checker.run(): - if not noqa(self.lines[lineno - 1]): - self.report_error(lineno, offset, text, check) - - def generate_tokens(self): - if self._io_error: - self.report_error(1, 0, 'E902 %s' % self._io_error, readlines) - tokengen = tokenize.generate_tokens(self.readline_check_physical) - try: - for token in tokengen: - yield token - except (SyntaxError, tokenize.TokenError): - self.report_invalid_syntax() - - def check_all(self, expected=None, line_offset=0): - """ - Run all checks on the input file. - """ - self.report.init_file(self.filename, self.lines, expected, line_offset) - if self._ast_checks: - self.check_ast() - self.line_number = 0 - self.indent_char = None - self.indent_level = 0 - self.previous_logical = '' - self.tokens = [] - self.blank_lines = blank_lines_before_comment = 0 - parens = 0 - for token in self.generate_tokens(): - self.tokens.append(token) - token_type, text = token[0:2] - if self.verbose >= 3: - if token[2][0] == token[3][0]: - pos = '[%s:%s]' % (token[2][1] or '', token[3][1]) - else: - pos = 'l.%s' % token[3][0] - print('l.%s\t%s\t%s\t%r' % - (token[2][0], pos, tokenize.tok_name[token[0]], text)) - if token_type == tokenize.OP: - if text in '([{': - parens += 1 - elif text in '}])': - parens -= 1 - elif not parens: - if token_type == tokenize.NEWLINE: - if self.blank_lines < blank_lines_before_comment: - self.blank_lines = blank_lines_before_comment - self.check_logical() - self.tokens = [] - self.blank_lines = blank_lines_before_comment = 0 - elif token_type == tokenize.NL: - if len(self.tokens) == 1: - # The physical line contains only this token. - self.blank_lines += 1 - self.tokens = [] - elif token_type == tokenize.COMMENT and len(self.tokens) == 1: - if blank_lines_before_comment < self.blank_lines: - blank_lines_before_comment = self.blank_lines - self.blank_lines = 0 - if COMMENT_WITH_NL: - # The comment also ends a physical line - self.tokens = [] - return self.report.get_file_results() - - -class BaseReport(object): - """Collect the results of the checks.""" - print_filename = False - - def __init__(self, options): - self._benchmark_keys = options.benchmark_keys - self._ignore_code = options.ignore_code - # Results - self.elapsed = 0 - self.total_errors = 0 - self.counters = dict.fromkeys(self._benchmark_keys, 0) - self.messages = {} - - def start(self): - """Start the timer.""" - self._start_time = time.time() - - def stop(self): - """Stop the timer.""" - self.elapsed = time.time() - self._start_time - - def init_file(self, filename, lines, expected, line_offset): - """Signal a new file.""" - self.filename = filename - self.lines = lines - self.expected = expected or () - self.line_offset = line_offset - self.file_errors = 0 - self.counters['files'] += 1 - self.counters['physical lines'] += len(lines) - - def increment_logical_line(self): - """Signal a new logical line.""" - self.counters['logical lines'] += 1 - - def error(self, line_number, offset, text, check): - """Report an error, according to options.""" - code = text[:4] - if self._ignore_code(code): - return - if code in self.counters: - self.counters[code] += 1 - else: - self.counters[code] = 1 - self.messages[code] = text[5:] - # Don't care about expected errors or warnings - if code in self.expected: - return - if self.print_filename and not self.file_errors: - print(self.filename) - self.file_errors += 1 - self.total_errors += 1 - return code - - def get_file_results(self): - """Return the count of errors and warnings for this file.""" - return self.file_errors - - def get_count(self, prefix=''): - """Return the total count of errors and warnings.""" - return sum([self.counters[key] - for key in self.messages if key.startswith(prefix)]) - - def get_statistics(self, prefix=''): - """ - Get statistics for message codes that start with the prefix. - - prefix='' matches all errors and warnings - prefix='E' matches all errors - prefix='W' matches all warnings - prefix='E4' matches all errors that have to do with imports - """ - return ['%-7s %s %s' % (self.counters[key], key, self.messages[key]) - for key in sorted(self.messages) if key.startswith(prefix)] - - def print_statistics(self, prefix=''): - """Print overall statistics (number of errors and warnings).""" - for line in self.get_statistics(prefix): - print(line) - - def print_benchmark(self): - """Print benchmark numbers.""" - print('%-7.2f %s' % (self.elapsed, 'seconds elapsed')) - if self.elapsed: - for key in self._benchmark_keys: - print('%-7d %s per second (%d total)' % - (self.counters[key] / self.elapsed, key, - self.counters[key])) - - -class FileReport(BaseReport): - """Collect the results of the checks and print only the filenames.""" - print_filename = True - - -class StandardReport(BaseReport): - """Collect and print the results of the checks.""" - - def __init__(self, options): - super(StandardReport, self).__init__(options) - self._fmt = REPORT_FORMAT.get(options.format.lower(), - options.format) - self._repeat = options.repeat - self._show_source = options.show_source - self._show_pep8 = options.show_pep8 - - def init_file(self, filename, lines, expected, line_offset): - """Signal a new file.""" - self._deferred_print = [] - return super(StandardReport, self).init_file( - filename, lines, expected, line_offset) - - def error(self, line_number, offset, text, check): - """Report an error, according to options.""" - code = super(StandardReport, self).error(line_number, offset, - text, check) - if code and (self.counters[code] == 1 or self._repeat): - self._deferred_print.append( - (line_number, offset, code, text[5:], check.__doc__)) - return code - - def get_file_results(self): - """Print the result and return the overall count for this file.""" - self._deferred_print.sort() - for line_number, offset, code, text, doc in self._deferred_print: - print(self._fmt % { - 'path': self.filename, - 'row': self.line_offset + line_number, 'col': offset + 1, - 'code': code, 'text': text, - }) - if self._show_source: - if line_number > len(self.lines): - line = '' - else: - line = self.lines[line_number - 1] - print(line.rstrip()) - print(' ' * offset + '^') - if self._show_pep8 and doc: - print(doc.lstrip('\n').rstrip()) - return self.file_errors - - -class DiffReport(StandardReport): - """Collect and print the results for the changed lines only.""" - - def __init__(self, options): - super(DiffReport, self).__init__(options) - self._selected = options.selected_lines - - def error(self, line_number, offset, text, check): - if line_number not in self._selected[self.filename]: - return - return super(DiffReport, self).error(line_number, offset, text, check) - - -class StyleGuide(object): - """Initialize a PEP-8 instance with few options.""" - - def __init__(self, *args, **kwargs): - # build options from the command line - self.checker_class = kwargs.pop('checker_class', Checker) - parse_argv = kwargs.pop('parse_argv', False) - config_file = kwargs.pop('config_file', None) - parser = kwargs.pop('parser', None) - options, self.paths = process_options( - parse_argv=parse_argv, config_file=config_file, parser=parser) - if args or kwargs: - # build options from dict - options_dict = dict(*args, **kwargs) - options.__dict__.update(options_dict) - if 'paths' in options_dict: - self.paths = options_dict['paths'] - - self.runner = self.input_file - self.options = options - - if not options.reporter: - options.reporter = BaseReport if options.quiet else StandardReport - - for index, value in enumerate(options.exclude): - options.exclude[index] = value.rstrip('/') - options.select = tuple(options.select or ()) - if not (options.select or options.ignore or - options.testsuite or options.doctest) and DEFAULT_IGNORE: - # The default choice: ignore controversial checks - options.ignore = tuple(DEFAULT_IGNORE.split(',')) - else: - # Ignore all checks which are not explicitly selected - options.ignore = tuple(options.ignore or options.select and ('',)) - options.benchmark_keys = BENCHMARK_KEYS[:] - options.ignore_code = self.ignore_code - options.physical_checks = self.get_checks('physical_line') - options.logical_checks = self.get_checks('logical_line') - options.ast_checks = self.get_checks('tree') - self.init_report() - - def init_report(self, reporter=None): - """Initialize the report instance.""" - self.options.report = (reporter or self.options.reporter)(self.options) - return self.options.report - - def check_files(self, paths=None): - """Run all checks on the paths.""" - if paths is None: - paths = self.paths - report = self.options.report - runner = self.runner - report.start() - try: - for path in paths: - if os.path.isdir(path): - self.input_dir(path) - elif not self.excluded(path): - runner(path) - except KeyboardInterrupt: - print('... stopped') - report.stop() - return report - - def input_file(self, filename, lines=None, expected=None, line_offset=0): - """Run all checks on a Python source file.""" - if self.options.verbose: - print('checking %s' % filename) - fchecker = self.checker_class( - filename, lines=lines, options=self.options) - return fchecker.check_all(expected=expected, line_offset=line_offset) - - def input_dir(self, dirname): - """Check all files in this directory and all subdirectories.""" - dirname = dirname.rstrip('/') - if self.excluded(dirname): - return 0 - counters = self.options.report.counters - verbose = self.options.verbose - filepatterns = self.options.filename - runner = self.runner - for root, dirs, files in os.walk(dirname): - if verbose: - print('directory ' + root) - counters['directories'] += 1 - for subdir in sorted(dirs): - if self.excluded(os.path.join(root, subdir)): - dirs.remove(subdir) - for filename in sorted(files): - # contain a pattern that matches? - if ((filename_match(filename, filepatterns) and - not self.excluded(filename))): - runner(os.path.join(root, filename)) - - def excluded(self, filename): - """ - Check if options.exclude contains a pattern that matches filename. - """ - basename = os.path.basename(filename) - return any((filename_match(filename, self.options.exclude, - default=False), - filename_match(basename, self.options.exclude, - default=False))) - - def ignore_code(self, code): - """ - Check if the error code should be ignored. - - If 'options.select' contains a prefix of the error code, - return False. Else, if 'options.ignore' contains a prefix of - the error code, return True. - """ - return (code.startswith(self.options.ignore) and - not code.startswith(self.options.select)) - - def get_checks(self, argument_name): - """ - Find all globally visible functions where the first argument name - starts with argument_name and which contain selected tests. - """ - checks = [] - for check, attrs in _checks[argument_name].items(): - (codes, args) = attrs - if any(not (code and self.ignore_code(code)) for code in codes): - checks.append((check.__name__, check, args)) - return sorted(checks) - - -def get_parser(prog='pep8', version=__version__): - parser = OptionParser(prog=prog, version=version, - usage="%prog [options] input ...") - parser.config_options = [ - 'exclude', 'filename', 'select', 'ignore', 'max-line-length', 'count', - 'format', 'quiet', 'show-pep8', 'show-source', 'statistics', 'verbose'] - parser.add_option('-v', '--verbose', default=0, action='count', - help="print status messages, or debug with -vv") - parser.add_option('-q', '--quiet', default=0, action='count', - help="report only file names, or nothing with -qq") - parser.add_option('-r', '--repeat', default=True, action='store_true', - help="(obsolete) show all occurrences of the same error") - parser.add_option('--first', action='store_false', dest='repeat', - help="show first occurrence of each error") - parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE, - help="exclude files or directories which match these " - "comma separated patterns (default: %default)") - parser.add_option('--filename', metavar='patterns', default='*.py', - help="when parsing directories, only check filenames " - "matching these comma separated patterns " - "(default: %default)") - parser.add_option('--select', metavar='errors', default='', - help="select errors and warnings (e.g. E,W6)") - parser.add_option('--ignore', metavar='errors', default='', - help="skip errors and warnings (e.g. E4,W)") - parser.add_option('--show-source', action='store_true', - help="show source code for each error") - parser.add_option('--show-pep8', action='store_true', - help="show text of PEP 8 for each error " - "(implies --first)") - parser.add_option('--statistics', action='store_true', - help="count errors and warnings") - parser.add_option('--count', action='store_true', - help="print total number of errors and warnings " - "to standard error and set exit code to 1 if " - "total is not null") - parser.add_option('--max-line-length', type='int', metavar='n', - default=MAX_LINE_LENGTH, - help="set maximum allowed line length " - "(default: %default)") - parser.add_option('--format', metavar='format', default='default', - help="set the error format [default|pylint|<custom>]") - parser.add_option('--diff', action='store_true', - help="report only lines changed according to the " - "unified diff received on STDIN") - group = parser.add_option_group("Testing Options") - if os.path.exists(TESTSUITE_PATH): - group.add_option('--testsuite', metavar='dir', - help="run regression tests from dir") - group.add_option('--doctest', action='store_true', - help="run doctest on myself") - group.add_option('--benchmark', action='store_true', - help="measure processing speed") - return parser - - -def read_config(options, args, arglist, parser): - """Read both user configuration and local configuration.""" - config = RawConfigParser() - - user_conf = options.config - if user_conf and os.path.isfile(user_conf): - if options.verbose: - print('user configuration: %s' % user_conf) - config.read(user_conf) - - parent = tail = args and os.path.abspath(os.path.commonprefix(args)) - while tail: - if config.read([os.path.join(parent, fn) for fn in PROJECT_CONFIG]): - if options.verbose: - print('local configuration: in %s' % parent) - break - parent, tail = os.path.split(parent) - - pep8_section = parser.prog - if config.has_section(pep8_section): - option_list = dict([(o.dest, o.type or o.action) - for o in parser.option_list]) - - # First, read the default values - new_options, _ = parser.parse_args([]) - - # Second, parse the configuration - for opt in config.options(pep8_section): - if options.verbose > 1: - print(" %s = %s" % (opt, config.get(pep8_section, opt))) - if opt.replace('_', '-') not in parser.config_options: - print("Unknown option: '%s'\n not in [%s]" % - (opt, ' '.join(parser.config_options))) - sys.exit(1) - normalized_opt = opt.replace('-', '_') - opt_type = option_list[normalized_opt] - if opt_type in ('int', 'count'): - value = config.getint(pep8_section, opt) - elif opt_type == 'string': - value = config.get(pep8_section, opt) - else: - assert opt_type in ('store_true', 'store_false') - value = config.getboolean(pep8_section, opt) - setattr(new_options, normalized_opt, value) - - # Third, overwrite with the command-line options - options, _ = parser.parse_args(arglist, values=new_options) - options.doctest = options.testsuite = False - return options - - -def process_options(arglist=None, parse_argv=False, config_file=None, - parser=None): - """Process options passed either via arglist or via command line args.""" - if not arglist and not parse_argv: - # Don't read the command line if the module is used as a library. - arglist = [] - if not parser: - parser = get_parser() - if not parser.has_option('--config'): - if config_file is True: - config_file = DEFAULT_CONFIG - group = parser.add_option_group("Configuration", description=( - "The project options are read from the [%s] section of the " - "tox.ini file or the setup.cfg file located in any parent folder " - "of the path(s) being processed. Allowed options are: %s." % - (parser.prog, ', '.join(parser.config_options)))) - group.add_option('--config', metavar='path', default=config_file, - help="user config file location (default: %default)") - options, args = parser.parse_args(arglist) - options.reporter = None - - if options.ensure_value('testsuite', False): - args.append(options.testsuite) - elif not options.ensure_value('doctest', False): - if parse_argv and not args: - if options.diff or any(os.path.exists(name) - for name in PROJECT_CONFIG): - args = ['.'] - else: - parser.error('input not specified') - options = read_config(options, args, arglist, parser) - options.reporter = parse_argv and options.quiet == 1 and FileReport - - options.filename = options.filename and options.filename.split(',') - options.exclude = options.exclude.split(',') - options.select = options.select and options.select.split(',') - options.ignore = options.ignore and options.ignore.split(',') - - if options.diff: - options.reporter = DiffReport - stdin = stdin_get_value() - options.selected_lines = parse_udiff(stdin, options.filename, args[0]) - args = sorted(options.selected_lines) - - return options, args - - -def _main(): - """Parse options and run checks on Python source.""" - pep8style = StyleGuide(parse_argv=True, config_file=True) - options = pep8style.options - if options.doctest or options.testsuite: - from testsuite.support import run_tests - report = run_tests(pep8style) - else: - report = pep8style.check_files() - if options.statistics: - report.print_statistics() - if options.benchmark: - report.print_benchmark() - if options.testsuite and not options.quiet: - report.print_results() - if report.total_errors: - if options.count: - sys.stderr.write(str(report.total_errors) + '\n') - sys.exit(1) - -if __name__ == '__main__': - _main() diff --git a/.vim/bundle/python-mode/pylibs/pylama/pyflakes/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pyflakes/__init__.py @@ -1,2 +0,0 @@ - -__version__ = '0.6.1' diff --git a/.vim/bundle/python-mode/pylibs/pylama/pyflakes/checker.py b/.vim/bundle/python-mode/pylibs/pylama/pyflakes/checker.py @@ -1,738 +0,0 @@ -# -*- test-case-name: pyflakes -*- -# (c) 2005-2010 Divmod, Inc. -# See LICENSE file for details - -import os.path -try: - import builtins - PY2 = False -except ImportError: - import __builtin__ as builtins - PY2 = True - -try: - import ast - iter_child_nodes = ast.iter_child_nodes -except ImportError: # Python 2.5 - import _ast as ast - - if 'decorator_list' not in ast.ClassDef._fields: - # Patch the missing attribute 'decorator_list' - ast.ClassDef.decorator_list = () - ast.FunctionDef.decorator_list = property(lambda s: s.decorators) - - def iter_child_nodes(node): - """ - Yield all direct child nodes of *node*, that is, all fields that - are nodes and all items of fields that are lists of nodes. - """ - for name in node._fields: - field = getattr(node, name, None) - if isinstance(field, ast.AST): - yield field - elif isinstance(field, list): - for item in field: - yield item -# Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally) -if hasattr(ast, 'Try'): - ast_TryExcept = ast.Try - ast_TryFinally = () -else: - ast_TryExcept = ast.TryExcept - ast_TryFinally = ast.TryFinally - -from . import messages - - -class Binding(object): - """ - Represents the binding of a value to a name. - - The checker uses this to keep track of which names have been bound and - which names have not. See L{Assignment} for a special type of binding that - is checked with stricter rules. - - @ivar used: pair of (L{Scope}, line-number) indicating the scope and - line number that this binding was last used - """ - - def __init__(self, name, source): - self.name = name - self.source = source - self.used = False - - def __str__(self): - return self.name - - def __repr__(self): - return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__, - self.name, - self.source.lineno, - id(self)) - - -class UnBinding(Binding): - """Created by the 'del' operator.""" - - -class Importation(Binding): - """ - A binding created by an import statement. - - @ivar fullName: The complete name given to the import statement, - possibly including multiple dotted components. - @type fullName: C{str} - """ - def __init__(self, name, source): - self.fullName = name - name = name.split('.')[0] - super(Importation, self).__init__(name, source) - - -class Argument(Binding): - """ - Represents binding a name as an argument. - """ - - -class Definition(Binding): - """ - A binding that defines a function or a class. - """ - - -class Assignment(Binding): - """ - Represents binding a name with an explicit assignment. - - The checker will raise warnings for any Assignment that isn't used. Also, - the checker does not consider assignments in tuple/list unpacking to be - Assignments, rather it treats them as simple Bindings. - """ - - -class FunctionDefinition(Definition): - pass - - -class ClassDefinition(Definition): - pass - - -class ExportBinding(Binding): - """ - A binding created by an C{__all__} assignment. If the names in the list - can be determined statically, they will be treated as names for export and - additional checking applied to them. - - The only C{__all__} assignment that can be recognized is one which takes - the value of a literal list containing literal strings. For example:: - - __all__ = ["foo", "bar"] - - Names which are imported and not otherwise used but appear in the value of - C{__all__} will not have an unused import warning reported for them. - """ - def names(self): - """ - Return a list of the names referenced by this binding. - """ - names = [] - if isinstance(self.source, ast.List): - for node in self.source.elts: - if isinstance(node, ast.Str): - names.append(node.s) - return names - - -class Scope(dict): - importStarred = False # set to True when import * is found - usesLocals = False - - def __repr__(self): - return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self)) - - -class ClassScope(Scope): - pass - - -class FunctionScope(Scope): - """ - I represent a name scope for a function. - - @ivar globals: Names declared 'global' in this function. - """ - def __init__(self): - super(FunctionScope, self).__init__() - self.globals = {} - - -class ModuleScope(Scope): - pass - - -# Globally defined names which are not attributes of the builtins module, or -# are only present on some platforms. -_MAGIC_GLOBALS = ['__file__', '__builtins__', 'WindowsError'] - - -def getNodeName(node): - # Returns node.id, or node.name, or None - if hasattr(node, 'id'): # One of the many nodes with an id - return node.id - if hasattr(node, 'name'): # a ExceptHandler node - return node.name - - -class Checker(object): - """ - I check the cleanliness and sanity of Python code. - - @ivar _deferredFunctions: Tracking list used by L{deferFunction}. Elements - of the list are two-tuples. The first element is the callable passed - to L{deferFunction}. The second element is a copy of the scope stack - at the time L{deferFunction} was called. - - @ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for - callables which are deferred assignment checks. - """ - - nodeDepth = 0 - traceTree = False - builtIns = set(dir(builtins)) | set(_MAGIC_GLOBALS) - - def __init__(self, tree, filename='(none)', builtins=None): - self._deferredFunctions = [] - self._deferredAssignments = [] - self.deadScopes = [] - self.messages = [] - self.filename = filename - if builtins: - self.builtIns = self.builtIns.union(builtins) - self.scopeStack = [ModuleScope()] - self.futuresAllowed = True - self.root = tree - self.handleChildren(tree) - self.runDeferred(self._deferredFunctions) - # Set _deferredFunctions to None so that deferFunction will fail - # noisily if called after we've run through the deferred functions. - self._deferredFunctions = None - self.runDeferred(self._deferredAssignments) - # Set _deferredAssignments to None so that deferAssignment will fail - # noisily if called after we've run through the deferred assignments. - self._deferredAssignments = None - del self.scopeStack[1:] - self.popScope() - self.checkDeadScopes() - - def deferFunction(self, callable): - """ - Schedule a function handler to be called just before completion. - - This is used for handling function bodies, which must be deferred - because code later in the file might modify the global scope. When - `callable` is called, the scope at the time this is called will be - restored, however it will contain any new bindings added to it. - """ - self._deferredFunctions.append((callable, self.scopeStack[:])) - - def deferAssignment(self, callable): - """ - Schedule an assignment handler to be called just after deferred - function handlers. - """ - self._deferredAssignments.append((callable, self.scopeStack[:])) - - def runDeferred(self, deferred): - """ - Run the callables in C{deferred} using their associated scope stack. - """ - for handler, scope in deferred: - self.scopeStack = scope - handler() - - @property - def scope(self): - return self.scopeStack[-1] - - def popScope(self): - self.deadScopes.append(self.scopeStack.pop()) - - def checkDeadScopes(self): - """ - Look at scopes which have been fully examined and report names in them - which were imported but unused. - """ - for scope in self.deadScopes: - export = isinstance(scope.get('__all__'), ExportBinding) - if export: - all = scope['__all__'].names() - if not scope.importStarred and os.path.basename(self.filename) != '__init__.py': - # Look for possible mistakes in the export list - undefined = set(all) - set(scope) - for name in undefined: - self.report(messages.UndefinedExport, - scope['__all__'].source.lineno, name) - else: - all = [] - - # Look for imported names that aren't used. - for importation in scope.values(): - if isinstance(importation, Importation): - if not importation.used and importation.name not in all: - self.report(messages.UnusedImport, - importation.source.lineno, importation.name) - - def pushFunctionScope(self): - self.scopeStack.append(FunctionScope()) - - def pushClassScope(self): - self.scopeStack.append(ClassScope()) - - def report(self, messageClass, *args, **kwargs): - self.messages.append(messageClass(self.filename, *args, **kwargs)) - - def hasParent(self, node, kind): - while hasattr(node, 'parent'): - node = node.parent - if isinstance(node, kind): - return True - - def getCommonAncestor(self, lnode, rnode, stop=None): - if not stop: - stop = self.root - if lnode is rnode: - return lnode - if stop in (lnode, rnode): - return stop - - if not hasattr(lnode, 'parent') or not hasattr(rnode, 'parent'): - return - if (lnode.level > rnode.level): - return self.getCommonAncestor(lnode.parent, rnode, stop) - if (rnode.level > lnode.level): - return self.getCommonAncestor(lnode, rnode.parent, stop) - return self.getCommonAncestor(lnode.parent, rnode.parent, stop) - - def descendantOf(self, node, ancestors, stop=None): - for a in ancestors: - if self.getCommonAncestor(node, a, stop) not in (stop, None): - return True - return False - - def onFork(self, parent, lnode, rnode, items): - return (self.descendantOf(lnode, items, parent) ^ - self.descendantOf(rnode, items, parent)) - - def differentForks(self, lnode, rnode): - """True, if lnode and rnode are located on different forks of IF/TRY""" - ancestor = self.getCommonAncestor(lnode, rnode) - if isinstance(ancestor, ast.If): - for fork in (ancestor.body, ancestor.orelse): - if self.onFork(ancestor, lnode, rnode, fork): - return True - elif isinstance(ancestor, ast_TryExcept): - body = ancestor.body + ancestor.orelse - for fork in [body] + [[hdl] for hdl in ancestor.handlers]: - if self.onFork(ancestor, lnode, rnode, fork): - return True - elif isinstance(ancestor, ast_TryFinally): - if self.onFork(ancestor, lnode, rnode, ancestor.body): - return True - return False - - def addBinding(self, node, value, reportRedef=True): - """ - Called when a binding is altered. - - - `node` is the statement responsible for the change - - `value` is the optional new value, a Binding instance, associated - with the binding; if None, the binding is deleted if it exists. - - if `reportRedef` is True (default), rebinding while unused will be - reported. - """ - redefinedWhileUnused = False - if not isinstance(self.scope, ClassScope): - for scope in self.scopeStack[::-1]: - existing = scope.get(value.name) - if (isinstance(existing, Importation) - and not existing.used - and (not isinstance(value, Importation) or value.fullName == existing.fullName) - and reportRedef - and not self.differentForks(node, existing.source)): - redefinedWhileUnused = True - self.report(messages.RedefinedWhileUnused, - node.lineno, value.name, existing.source.lineno) - - existing = self.scope.get(value.name) - if not redefinedWhileUnused and self.hasParent(value.source, ast.ListComp): - if (existing and reportRedef - and not self.hasParent(existing.source, (ast.For, ast.ListComp)) - and not self.differentForks(node, existing.source)): - self.report(messages.RedefinedInListComp, - node.lineno, value.name, existing.source.lineno) - - if isinstance(value, UnBinding): - try: - del self.scope[value.name] - except KeyError: - self.report(messages.UndefinedName, node.lineno, value.name) - elif (isinstance(existing, Definition) - and not existing.used - and not self.differentForks(node, existing.source)): - self.report(messages.RedefinedWhileUnused, - node.lineno, value.name, existing.source.lineno) - else: - self.scope[value.name] = value - - def handleNodeLoad(self, node): - name = getNodeName(node) - if not name: - return - # try local scope - importStarred = self.scope.importStarred - try: - self.scope[name].used = (self.scope, node.lineno) - except KeyError: - pass - else: - return - - # try enclosing function scopes - for scope in self.scopeStack[-2:0:-1]: - importStarred = importStarred or scope.importStarred - if not isinstance(scope, FunctionScope): - continue - try: - scope[name].used = (self.scope, node.lineno) - except KeyError: - pass - else: - return - - # try global scope - importStarred = importStarred or self.scopeStack[0].importStarred - try: - self.scopeStack[0][name].used = (self.scope, node.lineno) - except KeyError: - if not importStarred and name not in self.builtIns: - if (os.path.basename(self.filename) == '__init__.py' and name == '__path__'): - # the special name __path__ is valid only in packages - pass - else: - self.report(messages.UndefinedName, node.lineno, name) - - def handleNodeStore(self, node): - name = getNodeName(node) - if not name: - return - # if the name hasn't already been defined in the current scope - if isinstance(self.scope, FunctionScope) and name not in self.scope: - # for each function or module scope above us - for scope in self.scopeStack[:-1]: - if not isinstance(scope, (FunctionScope, ModuleScope)): - continue - # if the name was defined in that scope, and the name has - # been accessed already in the current scope, and hasn't - # been declared global - if (name in scope and scope[name].used and scope[name].used[0] is self.scope - and name not in self.scope.globals): - # then it's probably a mistake - self.report(messages.UndefinedLocal, - scope[name].used[1], name, scope[name].source.lineno) - break - - parent = getattr(node, 'parent', None) - if isinstance(parent, (ast.For, ast.comprehension, ast.Tuple, ast.List)): - binding = Binding(name, node) - elif parent is not None and name == '__all__' and isinstance(self.scope, ModuleScope): - binding = ExportBinding(name, parent.value) - else: - binding = Assignment(name, node) - if name in self.scope: - binding.used = self.scope[name].used - self.addBinding(node, binding) - - def handleNodeDelete(self, node): - name = getNodeName(node) - if not name: - return - if isinstance(self.scope, FunctionScope) and name in self.scope.globals: - del self.scope.globals[name] - else: - self.addBinding(node, UnBinding(name, node)) - - def handleChildren(self, tree): - for node in iter_child_nodes(tree): - self.handleNode(node, tree) - - def isDocstring(self, node): - """ - Determine if the given node is a docstring, as long as it is at the - correct place in the node tree. - """ - return isinstance(node, ast.Str) or (isinstance(node, ast.Expr) and - isinstance(node.value, ast.Str)) - - def handleNode(self, node, parent): - if node is None: - return - node.parent = parent - if self.traceTree: - print(' ' * self.nodeDepth + node.__class__.__name__) - self.nodeDepth += 1 - if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or - self.isDocstring(node)): - self.futuresAllowed = False - nodeType = node.__class__.__name__.upper() - node.level = self.nodeDepth - try: - handler = getattr(self, nodeType) - handler(node) - finally: - self.nodeDepth -= 1 - if self.traceTree: - print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__) - - def ignore(self, node): - pass - - # "stmt" type nodes - RETURN = DELETE = PRINT = WHILE = IF = WITH = WITHITEM = RAISE = \ - TRYEXCEPT = TRYFINALLY = TRY = ASSERT = EXEC = EXPR = handleChildren - - CONTINUE = BREAK = PASS = ignore - - # "expr" type nodes - BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = YIELD = YIELDFROM = \ - COMPARE = CALL = REPR = ATTRIBUTE = SUBSCRIPT = LIST = TUPLE = \ - STARRED = handleChildren - - NUM = STR = BYTES = ELLIPSIS = ignore - - # "slice" type nodes - SLICE = EXTSLICE = INDEX = handleChildren - - # expression contexts are node instances too, though being constants - LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore - - # same for operators - AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \ - BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \ - EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore - - # additional node types - COMPREHENSION = KEYWORD = handleChildren - - def GLOBAL(self, node): - """ - Keep track of globals declarations. - """ - if isinstance(self.scope, FunctionScope): - self.scope.globals.update(dict.fromkeys(node.names)) - - NONLOCAL = GLOBAL - - def LISTCOMP(self, node): - # handle generators before element - for gen in node.generators: - self.handleNode(gen, node) - self.handleNode(node.elt, node) - - def GENERATOREXP(self, node): - self.pushFunctionScope() - # handle generators before element - for gen in node.generators: - self.handleNode(gen, node) - self.handleNode(node.elt, node) - self.popScope() - - SETCOMP = GENERATOREXP - - def DICTCOMP(self, node): - self.pushFunctionScope() - for gen in node.generators: - self.handleNode(gen, node) - self.handleNode(node.key, node) - self.handleNode(node.value, node) - self.popScope() - - def FOR(self, node): - """ - Process bindings for loop variables. - """ - vars = [] - - def collectLoopVars(n): - if isinstance(n, ast.Name): - vars.append(n.id) - elif isinstance(n, ast.expr_context): - return - else: - for c in iter_child_nodes(n): - collectLoopVars(c) - - collectLoopVars(node.target) - for varn in vars: - if (isinstance(self.scope.get(varn), Importation) - # unused ones will get an unused import warning - and self.scope[varn].used): - self.report(messages.ImportShadowedByLoopVar, - node.lineno, varn, self.scope[varn].source.lineno) - - self.handleChildren(node) - - def NAME(self, node): - """ - Handle occurrence of Name (which can be a load/store/delete access.) - """ - if node.id == 'locals' and isinstance(node.parent, ast.Call): - # we are doing locals() call in current scope - self.scope.usesLocals = True - # Locate the name in locals / function / globals scopes. - if isinstance(node.ctx, (ast.Load, ast.AugLoad)): - self.handleNodeLoad(node) - elif isinstance(node.ctx, (ast.Store, ast.AugStore)): - self.handleNodeStore(node) - elif isinstance(node.ctx, ast.Del): - self.handleNodeDelete(node) - else: - # must be a Param context -- this only happens for names in function - # arguments, but these aren't dispatched through here - raise RuntimeError("Got impossible expression context: %r" % (node.ctx,)) - - def FUNCTIONDEF(self, node): - for deco in node.decorator_list: - self.handleNode(deco, node) - self.addBinding(node, FunctionDefinition(node.name, node)) - self.LAMBDA(node) - - def LAMBDA(self, node): - args = [] - - if PY2: - def addArgs(arglist): - for arg in arglist: - if isinstance(arg, ast.Tuple): - addArgs(arg.elts) - else: - if arg.id in args: - self.report(messages.DuplicateArgument, - node.lineno, arg.id) - args.append(arg.id) - addArgs(node.args.args) - defaults = node.args.defaults - else: - for arg in node.args.args + node.args.kwonlyargs: - if arg.arg in args: - self.report(messages.DuplicateArgument, - node.lineno, arg.arg) - args.append(arg.arg) - self.handleNode(arg.annotation, node) - if hasattr(node, 'returns'): # Only for FunctionDefs - for annotation in (node.args.varargannotation, - node.args.kwargannotation, node.returns): - self.handleNode(annotation, node) - defaults = node.args.defaults + node.args.kw_defaults - - # vararg/kwarg identifiers are not Name nodes - for wildcard in (node.args.vararg, node.args.kwarg): - if not wildcard: - continue - if wildcard in args: - self.report(messages.DuplicateArgument, node.lineno, wildcard) - args.append(wildcard) - for default in defaults: - self.handleNode(default, node) - - def runFunction(): - - self.pushFunctionScope() - for name in args: - self.addBinding(node, Argument(name, node), reportRedef=False) - if isinstance(node.body, list): - # case for FunctionDefs - for stmt in node.body: - self.handleNode(stmt, node) - else: - # case for Lambdas - self.handleNode(node.body, node) - - def checkUnusedAssignments(): - """ - Check to see if any assignments have not been used. - """ - for name, binding in self.scope.items(): - if (not binding.used and name not in self.scope.globals - and not self.scope.usesLocals - and isinstance(binding, Assignment)): - self.report(messages.UnusedVariable, - binding.source.lineno, name) - self.deferAssignment(checkUnusedAssignments) - self.popScope() - - self.deferFunction(runFunction) - - def CLASSDEF(self, node): - """ - Check names used in a class definition, including its decorators, base - classes, and the body of its definition. Additionally, add its name to - the current scope. - """ - for deco in node.decorator_list: - self.handleNode(deco, node) - for baseNode in node.bases: - self.handleNode(baseNode, node) - if not PY2: - for keywordNode in node.keywords: - self.handleNode(keywordNode, node) - self.pushClassScope() - for stmt in node.body: - self.handleNode(stmt, node) - self.popScope() - self.addBinding(node, ClassDefinition(node.name, node)) - - def ASSIGN(self, node): - self.handleNode(node.value, node) - for target in node.targets: - self.handleNode(target, node) - - def AUGASSIGN(self, node): - self.handleNodeLoad(node.target) - self.handleNode(node.value, node) - self.handleNode(node.target, node) - - def IMPORT(self, node): - for alias in node.names: - name = alias.asname or alias.name - importation = Importation(name, node) - self.addBinding(node, importation) - - def IMPORTFROM(self, node): - if node.module == '__future__': - if not self.futuresAllowed: - self.report(messages.LateFutureImport, - node.lineno, [n.name for n in node.names]) - else: - self.futuresAllowed = False - - for alias in node.names: - if alias.name == '*': - self.scope.importStarred = True - self.report(messages.ImportStarUsed, node.lineno, node.module) - continue - name = alias.asname or alias.name - importation = Importation(name, node) - if node.module == '__future__': - importation.used = (self.scope, node.lineno) - self.addBinding(node, importation) - - def EXCEPTHANDLER(self, node): - # 3.x: in addition to handling children, we must handle the name of - # the exception, which is not a Name node, but a simple string. - if isinstance(node.name, str): - self.handleNodeStore(node) - self.handleChildren(node) - -# pymode:lint=0 diff --git a/.vim/bundle/python-mode/pylibs/pylama/pyflakes/messages.py b/.vim/bundle/python-mode/pylibs/pylama/pyflakes/messages.py @@ -1,113 +0,0 @@ -# (c) 2005 Divmod, Inc. See LICENSE file for details - - -class Message(object): - message = '' - message_args = () - - def __init__(self, filename, lineno): - self.filename = filename - self.lineno = lineno - - def __str__(self): - return '%s:%s: %s' % (self.filename, self.lineno, self.message % self.message_args) - - -class UnusedImport(Message): - message = 'W402 %r imported but unused' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class RedefinedWhileUnused(Message): - message = 'W801 redefinition of unused %r from line %r' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class RedefinedInListComp(Message): - message = 'W801 rlist comprehension redefines %r from line %r' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class ImportShadowedByLoopVar(Message): - message = 'W403 iimport %r from line %r shadowed by loop variable' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class ImportStarUsed(Message): - message = "W404 ''from %s import *' used; unable to detect undefined names" - - def __init__(self, filename, lineno, modname): - Message.__init__(self, filename, lineno) - self.message_args = (modname,) - - -class UndefinedName(Message): - message = 'W802 undefined name %r' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class UndefinedExport(Message): - message = 'W803 undefined name %r in __all__' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class UndefinedLocal(Message): - message = "W804 local variable %r (defined in enclosing scope on line %r) referenced before assignment" - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class DuplicateArgument(Message): - message = 'W805 duplicate argument %r in function definition' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class Redefined(Message): - message = 'W806 redefinition of %r from line %r' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class LateFutureImport(Message): - message = 'W405 future import(s) %r after other statements' - - def __init__(self, filename, lineno, names): - Message.__init__(self, filename, lineno) - self.message_args = (names,) - - -class UnusedVariable(Message): - """ - Indicates that a variable has been explicity assigned to but not actually - used. - """ - message = 'W806 local variable %r is assigned to but never used' - - def __init__(self, filename, lineno, names): - Message.__init__(self, filename, lineno) - self.message_args = (names,) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint.rc b/.vim/bundle/python-mode/pylibs/pylama/pylint.rc @@ -1,25 +0,0 @@ -[MESSAGES CONTROL] -# Disable the message(s) with the given id(s). -# http://pylint-messages.wikidot.com/all-codes -# -# C0103: Invalid name "%s" (should match %s) -# C0111: Missing docstring -# E1101: %s %r has no %r member -# R0901: Too many ancestors (%s/%s) -# R0902: Too many instance attributes (%s/%s) -# R0903: Too few public methods (%s/%s) -# R0904: Too many public methods (%s/%s) -# R0913: Too many arguments (%s/%s) -# R0915: Too many statements (%s/%s) -# W0141: Used builtin function %r -# W0142: Used * or ** magic -# W0221: Arguments number differs from %s method -# W0232: Class has no __init__ method -# W0401: Wildcard import %s -# W0613: Unused argument %r -# W0631: Using possibly undefined loop variable %r -# -disable = C0103,C0111,E1101,R0901,R0902,R0903,R0904,R0913,R0915,W0141,W0142,W0221,W0232,W0401,W0613,W0631 - -[TYPECHECK] -generated-members = REQUEST,acl_users,aq_parent,objects,DoesNotExist,_meta,status_code,content,context diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/__init__.py @@ -1,45 +0,0 @@ -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import sys - -def run_pylint(): - """run pylint""" - from .lint import Run - Run(sys.argv[1:]) - -def run_pylint_gui(): - """run pylint-gui""" - try: - from pylint.gui import Run - Run(sys.argv[1:]) - except ImportError: - sys.exit('tkinter is not available') - -def run_epylint(): - """run pylint""" - from pylint.epylint import Run - Run() - -def run_pyreverse(): - """run pyreverse""" - from pylint.pyreverse.main import Run - Run(sys.argv[1:]) - -def run_symilar(): - """run symilar""" - from .checkers.similar import Run - Run(sys.argv[1:]) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/__pkginfo__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/__pkginfo__.py @@ -1,70 +0,0 @@ -# pylint: disable=W0622,C0103 -# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""pylint packaging information""" - -modname = distname = 'pylint' - -numversion = (0, 27, 0) -version = '.'.join([str(num) for num in numversion]) - -install_requires = ['logilab-common >= 0.53.0', 'logilab-astng >= 0.21.1'] - -license = 'GPL' -copyright = 'Logilab S.A.' -description = "python code static checker" -web = "http://www.logilab.org/project/%s" % distname -ftp = "ftp://ftp.logilab.org/pub/%s" % modname -mailinglist = "mailto://python-projects@lists.logilab.org" -author = 'Logilab' -author_email = 'python-projects@lists.logilab.org' - -classifiers = ['Development Status :: 4 - Beta', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: GNU General Public License (GPL)', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 3', - 'Topic :: Software Development :: Debuggers', - 'Topic :: Software Development :: Quality Assurance', - 'Topic :: Software Development :: Testing', - ] - - -long_desc = """\ - Pylint is a Python source code analyzer which looks for programming - errors, helps enforcing a coding standard and sniffs for some code - smells (as defined in Martin Fowler's Refactoring book) - . - Pylint can be seen as another PyChecker since nearly all tests you - can do with PyChecker can also be done with Pylint. However, Pylint - offers some more features, like checking length of lines of code, - checking if variable names are well-formed according to your coding - standard, or checking if declared interfaces are truly implemented, - and much more. - . - Additionally, it is possible to write plugins to add your own checks. - . - Pylint is shipped with "pylint-gui", "pyreverse" (UML diagram generator) - and "symilar" (an independent similarities checker).""" - -from os.path import join -scripts = [join('bin', filename) - for filename in ('pylint', 'pylint-gui', "symilar", "epylint", - "pyreverse")] - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/__init__.py @@ -1,163 +0,0 @@ -# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""utilities methods and classes for checkers - -Base id of standard checkers (used in msg and report ids): -01: base -02: classes -03: format -04: import -05: misc -06: variables -07: exceptions -08: similar -09: design_analysis -10: newstyle -11: typecheck -12: logging -13: string_format -14: string_constant -14-50: not yet used: reserved for future internal checkers. -51-99: perhaps used: reserved for external checkers - -The raw_metrics checker has no number associated since it doesn't emit any -messages nor reports. XXX not true, emit a 07 report ! - -""" - -import tokenize -from os import listdir -from os.path import dirname, join, isdir, splitext - -from ..logilab.astng.utils import ASTWalker -from ..logilab.common.modutils import load_module_from_file -from ..logilab.common.configuration import OptionsProviderMixIn - -from ..reporters import diff_string, EmptyReport - -def table_lines_from_stats(stats, old_stats, columns): - """get values listed in <columns> from <stats> and <old_stats>, - and return a formated list of values, designed to be given to a - ureport.Table object - """ - lines = [] - for m_type in columns: - new = stats[m_type] - format = str - if isinstance(new, float): - format = lambda num: '%.3f' % num - old = old_stats.get(m_type) - if old is not None: - diff_str = diff_string(old, new) - old = format(old) - else: - old, diff_str = 'NC', 'NC' - lines += (m_type.replace('_', ' '), format(new), old, diff_str) - return lines - - -class BaseChecker(OptionsProviderMixIn, ASTWalker): - """base class for checkers""" - # checker name (you may reuse an existing one) - name = None - # options level (0 will be displaying in --help, 1 in --long-help) - level = 1 - # ordered list of options to control the ckecker behaviour - options = () - # messages issued by this checker - msgs = {} - # reports issued by this checker - reports = () - - def __init__(self, linter=None): - """checker instances should have the linter as argument - - linter is an object implementing ILinter - """ - ASTWalker.__init__(self, self) - self.name = self.name.lower() - OptionsProviderMixIn.__init__(self) - self.linter = linter - # messages that are active for the current check - self.active_msgs = set() - - def add_message(self, msg_id, line=None, node=None, args=None): - """add a message of a given type""" - self.linter.add_message(msg_id, line, node, args) - - def package_dir(self): - """return the base directory for the analysed package""" - return dirname(self.linter.base_file) - - # dummy methods implementing the IChecker interface - - def open(self): - """called before visiting project (i.e set of modules)""" - - def close(self): - """called after visiting project (i.e set of modules)""" - - -class BaseRawChecker(BaseChecker): - """base class for raw checkers""" - - def process_module(self, node): - """process a module - - the module's content is accessible via the stream object - - stream must implement the readline method - """ - stream = node.file_stream - stream.seek(0) # XXX may be removed with astng > 0.23 - self.process_tokens(tokenize.generate_tokens(stream.readline)) - - def process_tokens(self, tokens): - """should be overridden by subclasses""" - raise NotImplementedError() - - -PY_EXTS = ('.py', '.pyc', '.pyo', '.pyw', '.so', '.dll') - -def initialize(linter): - """initialize linter with checkers in this package """ - package_load(linter, __path__[0]) - -def package_load(linter, directory): - """load all module and package in the given directory, looking for a - 'register' function in each one, used to register pylint checkers - """ - imported = {} - for filename in listdir(directory): - basename, extension = splitext(filename) - if basename in imported or basename == '__pycache__': - continue - if extension in PY_EXTS and basename != '__init__' or ( - not extension and isdir(join(directory, basename))): - try: - module = load_module_from_file(join(directory, filename)) - except ValueError: - # empty module name (usually emacs auto-save files) - continue - except ImportError, exc: - import sys - print >> sys.stderr, "Problem importing module %s: %s" % (filename, exc) - else: - if hasattr(module, 'register'): - module.register(linter) - imported[basename] = 1 - -__all__ = ('BaseChecker', 'initialize', 'package_load') diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/base.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/base.py @@ -1,851 +0,0 @@ -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# Copyright (c) 2009-2010 Arista Networks, Inc. -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""basic checker for Python code""" - - -from ..logilab import astng -from ..logilab.common.ureports import Table -from ..logilab.astng import are_exclusive - -from ..interfaces import IASTNGChecker -from ..reporters import diff_string -from ..checkers import BaseChecker, EmptyReport -from ..checkers.utils import ( - check_messages, - clobber_in_except, - is_inside_except, - safe_infer, - ) - - -import re - -# regex for class/function/variable/constant name -CLASS_NAME_RGX = re.compile('[A-Z_][a-zA-Z0-9]+$') -MOD_NAME_RGX = re.compile('(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$') -CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$') -COMP_VAR_RGX = re.compile('[A-Za-z_][A-Za-z0-9_]*$') -DEFAULT_NAME_RGX = re.compile('[a-z_][a-z0-9_]{2,30}$') -# do not require a doc string on system methods -NO_REQUIRED_DOC_RGX = re.compile('__.*__') - -del re - -def in_loop(node): - """return True if the node is inside a kind of for loop""" - parent = node.parent - while parent is not None: - if isinstance(parent, (astng.For, astng.ListComp, astng.SetComp, - astng.DictComp, astng.GenExpr)): - return True - parent = parent.parent - return False - -def in_nested_list(nested_list, obj): - """return true if the object is an element of <nested_list> or of a nested - list - """ - for elmt in nested_list: - if isinstance(elmt, (list, tuple)): - if in_nested_list(elmt, obj): - return True - elif elmt == obj: - return True - return False - -def report_by_type_stats(sect, stats, old_stats): - """make a report of - - * percentage of different types documented - * percentage of different types with a bad name - """ - # percentage of different types documented and/or with a bad name - nice_stats = {} - for node_type in ('module', 'class', 'method', 'function'): - try: - total = stats[node_type] - except KeyError: - raise EmptyReport() - nice_stats[node_type] = {} - if total != 0: - try: - documented = total - stats['undocumented_'+node_type] - percent = (documented * 100.) / total - nice_stats[node_type]['percent_documented'] = '%.2f' % percent - except KeyError: - nice_stats[node_type]['percent_documented'] = 'NC' - try: - percent = (stats['badname_'+node_type] * 100.) / total - nice_stats[node_type]['percent_badname'] = '%.2f' % percent - except KeyError: - nice_stats[node_type]['percent_badname'] = 'NC' - lines = ('type', 'number', 'old number', 'difference', - '%documented', '%badname') - for node_type in ('module', 'class', 'method', 'function'): - new = stats[node_type] - old = old_stats.get(node_type, None) - if old is not None: - diff_str = diff_string(old, new) - else: - old, diff_str = 'NC', 'NC' - lines += (node_type, str(new), str(old), diff_str, - nice_stats[node_type].get('percent_documented', '0'), - nice_stats[node_type].get('percent_badname', '0')) - sect.append(Table(children=lines, cols=6, rheaders=1)) - -def redefined_by_decorator(node): - """return True if the object is a method redefined via decorator. - - For example: - @property - def x(self): return self._x - @x.setter - def x(self, value): self._x = value - """ - if node.decorators: - for decorator in node.decorators.nodes: - if (isinstance(decorator, astng.Getattr) and - getattr(decorator.expr, 'name', None) == node.name): - return True - return False - -class _BasicChecker(BaseChecker): - __implements__ = IASTNGChecker - name = 'basic' - -class BasicErrorChecker(_BasicChecker): - msgs = { - 'E0100': ('__init__ method is a generator', - 'init-is-generator', - 'Used when the special class method __init__ is turned into a ' - 'generator by a yield in its body.'), - 'E0101': ('Explicit return in __init__', - 'return-in-init', - 'Used when the special class method __init__ has an explicit \ - return value.'), - 'E0102': ('%s already defined line %s', - 'function-redefined', - 'Used when a function / class / method is redefined.'), - 'E0103': ('%r not properly in loop', - 'not-in-loop', - 'Used when break or continue keywords are used outside a loop.'), - - 'E0104': ('Return outside function', - 'return-outside-function', - 'Used when a "return" statement is found outside a function or ' - 'method.'), - 'E0105': ('Yield outside function', - 'yield-outside-function', - 'Used when a "yield" statement is found outside a function or ' - 'method.'), - 'E0106': ('Return with argument inside generator', - 'return-arg-in-generator', - 'Used when a "return" statement with an argument is found ' - 'outside in a generator function or method (e.g. with some ' - '"yield" statements).'), - 'E0107': ("Use of the non-existent %s operator", - 'nonexistent-operator', - "Used when you attempt to use the C-style pre-increment or" - "pre-decrement operator -- and ++, which doesn't exist in Python."), - } - - def __init__(self, linter): - _BasicChecker.__init__(self, linter) - - @check_messages('E0102') - def visit_class(self, node): - self._check_redefinition('class', node) - - @check_messages('E0100', 'E0101', 'E0102', 'E0106') - def visit_function(self, node): - if not redefined_by_decorator(node): - self._check_redefinition(node.is_method() and 'method' or 'function', node) - # checks for max returns, branch, return in __init__ - returns = node.nodes_of_class(astng.Return, - skip_klass=(astng.Function, astng.Class)) - if node.is_method() and node.name == '__init__': - if node.is_generator(): - self.add_message('E0100', node=node) - else: - values = [r.value for r in returns] - if [v for v in values if not (v is None or - (isinstance(v, astng.Const) and v.value is None) - or (isinstance(v, astng.Name) and v.name == 'None'))]: - self.add_message('E0101', node=node) - elif node.is_generator(): - # make sure we don't mix non-None returns and yields - for retnode in returns: - if isinstance(retnode.value, astng.Const) and \ - retnode.value.value is not None: - self.add_message('E0106', node=node, - line=retnode.fromlineno) - - @check_messages('E0104') - def visit_return(self, node): - if not isinstance(node.frame(), astng.Function): - self.add_message('E0104', node=node) - - @check_messages('E0105') - def visit_yield(self, node): - if not isinstance(node.frame(), astng.Function): - self.add_message('E0105', node=node) - - @check_messages('E0103') - def visit_continue(self, node): - self._check_in_loop(node, 'continue') - - @check_messages('E0103') - def visit_break(self, node): - self._check_in_loop(node, 'break') - - @check_messages('E0107') - def visit_unaryop(self, node): - """check use of the non-existent ++ adn -- operator operator""" - if ((node.op in '+-') and - isinstance(node.operand, astng.UnaryOp) and - (node.operand.op == node.op)): - self.add_message('E0107', node=node, args=node.op*2) - - def _check_in_loop(self, node, node_name): - """check that a node is inside a for or while loop""" - _node = node.parent - while _node: - if isinstance(_node, (astng.For, astng.While)): - break - _node = _node.parent - else: - self.add_message('E0103', node=node, args=node_name) - - def _check_redefinition(self, redeftype, node): - """check for redefinition of a function / method / class name""" - defined_self = node.parent.frame()[node.name] - if defined_self is not node and not are_exclusive(node, defined_self): - self.add_message('E0102', node=node, - args=(redeftype, defined_self.fromlineno)) - - - -class BasicChecker(_BasicChecker): - """checks for : - * doc strings - * modules / classes / functions / methods / arguments / variables name - * number of arguments, local variables, branches, returns and statements in -functions, methods - * required module attributes - * dangerous default values as arguments - * redefinition of function / method / class - * uses of the global statement - """ - - __implements__ = IASTNGChecker - - name = 'basic' - msgs = { - 'W0101': ('Unreachable code', - 'unreachable', - 'Used when there is some code behind a "return" or "raise" \ - statement, which will never be accessed.'), - 'W0102': ('Dangerous default value %s as argument', - 'dangerous-default-value', - 'Used when a mutable value as list or dictionary is detected in \ - a default value for an argument.'), - 'W0104': ('Statement seems to have no effect', - 'pointless-statement', - 'Used when a statement doesn\'t have (or at least seems to) \ - any effect.'), - 'W0105': ('String statement has no effect', - 'pointless-string-statement', - 'Used when a string is used as a statement (which of course \ - has no effect). This is a particular case of W0104 with its \ - own message so you can easily disable it if you\'re using \ - those strings as documentation, instead of comments.'), - 'W0106': ('Expression "%s" is assigned to nothing', - 'expression-not-assigned', - 'Used when an expression that is not a function call is assigned\ - to nothing. Probably something else was intended.'), - 'W0108': ('Lambda may not be necessary', - 'unnecessary-lambda', - 'Used when the body of a lambda expression is a function call \ - on the same argument list as the lambda itself; such lambda \ - expressions are in all but a few cases replaceable with the \ - function being called in the body of the lambda.'), - 'W0109': ("Duplicate key %r in dictionary", - 'duplicate-key', - "Used when a dictionary expression binds the same key multiple \ - times."), - 'W0122': ('Use of the exec statement', - 'exec-statement', - 'Used when you use the "exec" statement, to discourage its \ - usage. That doesn\'t mean you can not use it !'), - - 'W0141': ('Used builtin function %r', - 'bad-builtin', - 'Used when a black listed builtin function is used (see the ' - 'bad-function option). Usual black listed functions are the ones ' - 'like map, or filter , where Python offers now some cleaner ' - 'alternative like list comprehension.'), - 'W0142': ('Used * or ** magic', - 'star-args', - 'Used when a function or method is called using `*args` or ' - '`**kwargs` to dispatch arguments. This doesn\'t improve ' - 'readability and should be used with care.'), - 'W0150': ("%s statement in finally block may swallow exception", - 'lost-exception', - "Used when a break or a return statement is found inside the \ - finally clause of a try...finally block: the exceptions raised \ - in the try clause will be silently swallowed instead of being \ - re-raised."), - 'W0199': ('Assert called on a 2-uple. Did you mean \'assert x,y\'?', - 'assert-on-tuple', - 'A call of assert on a tuple will always evaluate to true if ' - 'the tuple is not empty, and will always evaluate to false if ' - 'it is.'), - - 'C0121': ('Missing required attribute "%s"', # W0103 - 'missing-module-attribute', - 'Used when an attribute required for modules is missing.'), - - } - - options = (('required-attributes', - {'default' : (), 'type' : 'csv', - 'metavar' : '<attributes>', - 'help' : 'Required attributes for module, separated by a ' - 'comma'} - ), - ('bad-functions', - {'default' : ('map', 'filter', 'apply', 'input'), - 'type' :'csv', 'metavar' : '<builtin function names>', - 'help' : 'List of builtins function names that should not be ' - 'used, separated by a comma'} - ), - ) - reports = ( ('RP0101', 'Statistics by type', report_by_type_stats), ) - - def __init__(self, linter): - _BasicChecker.__init__(self, linter) - self.stats = None - self._tryfinallys = None - - def open(self): - """initialize visit variables and statistics - """ - self._tryfinallys = [] - self.stats = self.linter.add_stats(module=0, function=0, - method=0, class_=0) - - def visit_module(self, node): - """check module name, docstring and required arguments - """ - self.stats['module'] += 1 - for attr in self.config.required_attributes: - if attr not in node: - self.add_message('C0121', node=node, args=attr) - - def visit_class(self, node): - """check module name, docstring and redefinition - increment branch counter - """ - self.stats['class'] += 1 - - @check_messages('W0104', 'W0105') - def visit_discard(self, node): - """check for various kind of statements without effect""" - expr = node.value - if isinstance(expr, astng.Const) and isinstance(expr.value, - basestring): - # treat string statement in a separated message - self.add_message('W0105', node=node) - return - # ignore if this is : - # * a direct function call - # * the unique child of a try/except body - # * a yield (which are wrapped by a discard node in _ast XXX) - # warn W0106 if we have any underlying function call (we can't predict - # side effects), else W0104 - if (isinstance(expr, (astng.Yield, astng.CallFunc)) or - (isinstance(node.parent, astng.TryExcept) and - node.parent.body == [node])): - return - if any(expr.nodes_of_class(astng.CallFunc)): - self.add_message('W0106', node=node, args=expr.as_string()) - else: - self.add_message('W0104', node=node) - - @check_messages('W0108') - def visit_lambda(self, node): - """check whether or not the lambda is suspicious - """ - # if the body of the lambda is a call expression with the same - # argument list as the lambda itself, then the lambda is - # possibly unnecessary and at least suspicious. - if node.args.defaults: - # If the arguments of the lambda include defaults, then a - # judgment cannot be made because there is no way to check - # that the defaults defined by the lambda are the same as - # the defaults defined by the function called in the body - # of the lambda. - return - call = node.body - if not isinstance(call, astng.CallFunc): - # The body of the lambda must be a function call expression - # for the lambda to be unnecessary. - return - # XXX are lambda still different with astng >= 0.18 ? - # *args and **kwargs need to be treated specially, since they - # are structured differently between the lambda and the function - # call (in the lambda they appear in the args.args list and are - # indicated as * and ** by two bits in the lambda's flags, but - # in the function call they are omitted from the args list and - # are indicated by separate attributes on the function call node). - ordinary_args = list(node.args.args) - if node.args.kwarg: - if (not call.kwargs - or not isinstance(call.kwargs, astng.Name) - or node.args.kwarg != call.kwargs.name): - return - elif call.kwargs: - return - if node.args.vararg: - if (not call.starargs - or not isinstance(call.starargs, astng.Name) - or node.args.vararg != call.starargs.name): - return - elif call.starargs: - return - # The "ordinary" arguments must be in a correspondence such that: - # ordinary_args[i].name == call.args[i].name. - if len(ordinary_args) != len(call.args): - return - for i in xrange(len(ordinary_args)): - if not isinstance(call.args[i], astng.Name): - return - if node.args.args[i].name != call.args[i].name: - return - self.add_message('W0108', line=node.fromlineno, node=node) - - def visit_function(self, node): - """check function name, docstring, arguments, redefinition, - variable names, max locals - """ - self.stats[node.is_method() and 'method' or 'function'] += 1 - # check for dangerous default values as arguments - for default in node.args.defaults: - try: - value = default.infer().next() - except astng.InferenceError: - continue - if isinstance(value, (astng.Dict, astng.List)): - if value is default: - msg = default.as_string() - else: - msg = '%s (%s)' % (default.as_string(), value.as_string()) - self.add_message('W0102', node=node, args=(msg,)) - if value.qname() == '__builtin__.set': - if isinstance(default, astng.CallFunc): - msg = default.as_string() - else: - msg = '%s (%s)' % (default.as_string(), value.qname()) - self.add_message('W0102', node=node, args=(msg,)) - - @check_messages('W0101', 'W0150') - def visit_return(self, node): - """1 - check is the node has a right sibling (if so, that's some - unreachable code) - 2 - check is the node is inside the finally clause of a try...finally - block - """ - self._check_unreachable(node) - # Is it inside final body of a try...finally bloc ? - self._check_not_in_finally(node, 'return', (astng.Function,)) - - @check_messages('W0101') - def visit_continue(self, node): - """check is the node has a right sibling (if so, that's some unreachable - code) - """ - self._check_unreachable(node) - - @check_messages('W0101', 'W0150') - def visit_break(self, node): - """1 - check is the node has a right sibling (if so, that's some - unreachable code) - 2 - check is the node is inside the finally clause of a try...finally - block - """ - # 1 - Is it right sibling ? - self._check_unreachable(node) - # 2 - Is it inside final body of a try...finally bloc ? - self._check_not_in_finally(node, 'break', (astng.For, astng.While,)) - - @check_messages('W0101') - def visit_raise(self, node): - """check is the node has a right sibling (if so, that's some unreachable - code) - """ - self._check_unreachable(node) - - @check_messages('W0122') - def visit_exec(self, node): - """just print a warning on exec statements""" - self.add_message('W0122', node=node) - - @check_messages('W0141', 'W0142') - def visit_callfunc(self, node): - """visit a CallFunc node -> check if this is not a blacklisted builtin - call and check for * or ** use - """ - if isinstance(node.func, astng.Name): - name = node.func.name - # ignore the name if it's not a builtin (i.e. not defined in the - # locals nor globals scope) - if not (name in node.frame() or - name in node.root()): - if name in self.config.bad_functions: - self.add_message('W0141', node=node, args=name) - if node.starargs or node.kwargs: - scope = node.scope() - if isinstance(scope, astng.Function): - toprocess = [(n, vn) for (n, vn) in ((node.starargs, scope.args.vararg), - (node.kwargs, scope.args.kwarg)) if n] - if toprocess: - for cfnode, fargname in toprocess[:]: - if getattr(cfnode, 'name', None) == fargname: - toprocess.remove((cfnode, fargname)) - if not toprocess: - return # W0142 can be skipped - self.add_message('W0142', node=node.func) - - @check_messages('W0199') - def visit_assert(self, node): - """check the use of an assert statement on a tuple.""" - if node.fail is None and isinstance(node.test, astng.Tuple) and \ - len(node.test.elts) == 2: - self.add_message('W0199', line=node.fromlineno, node=node) - - @check_messages('W0109') - def visit_dict(self, node): - """check duplicate key in dictionary""" - keys = set() - for k, _ in node.items: - if isinstance(k, astng.Const): - key = k.value - if key in keys: - self.add_message('W0109', node=node, args=key) - keys.add(key) - - def visit_tryfinally(self, node): - """update try...finally flag""" - self._tryfinallys.append(node) - - def leave_tryfinally(self, node): - """update try...finally flag""" - self._tryfinallys.pop() - - def _check_unreachable(self, node): - """check unreachable code""" - unreach_stmt = node.next_sibling() - if unreach_stmt is not None: - self.add_message('W0101', node=unreach_stmt) - - def _check_not_in_finally(self, node, node_name, breaker_classes=()): - """check that a node is not inside a finally clause of a - try...finally statement. - If we found before a try...finally bloc a parent which its type is - in breaker_classes, we skip the whole check.""" - # if self._tryfinallys is empty, we're not a in try...finally bloc - if not self._tryfinallys: - return - # the node could be a grand-grand...-children of the try...finally - _parent = node.parent - _node = node - while _parent and not isinstance(_parent, breaker_classes): - if hasattr(_parent, 'finalbody') and _node in _parent.finalbody: - self.add_message('W0150', node=node, args=node_name) - return - _node = _parent - _parent = _node.parent - - - -class NameChecker(_BasicChecker): - msgs = { - 'C0102': ('Black listed name "%s"', - 'blacklisted-name', - 'Used when the name is listed in the black list (unauthorized \ - names).'), - 'C0103': ('Invalid name "%s" for type %s (should match %s)', - 'invalid-name', - 'Used when the name doesn\'t match the regular expression \ - associated to its type (constant, variable, class...).'), - - } - options = (('module-rgx', - {'default' : MOD_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'module names'} - ), - ('const-rgx', - {'default' : CONST_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'module level names'} - ), - ('class-rgx', - {'default' : CLASS_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'class names'} - ), - ('function-rgx', - {'default' : DEFAULT_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'function names'} - ), - ('method-rgx', - {'default' : DEFAULT_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'method names'} - ), - ('attr-rgx', - {'default' : DEFAULT_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'instance attribute names'} - ), - ('argument-rgx', - {'default' : DEFAULT_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'argument names'}), - ('variable-rgx', - {'default' : DEFAULT_NAME_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'variable names'} - ), - ('inlinevar-rgx', - {'default' : COMP_VAR_RGX, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match correct ' - 'list comprehension / generator expression variable \ - names'} - ), - # XXX use set - ('good-names', - {'default' : ('i', 'j', 'k', 'ex', 'Run', '_'), - 'type' :'csv', 'metavar' : '<names>', - 'help' : 'Good variable names which should always be accepted,' - ' separated by a comma'} - ), - ('bad-names', - {'default' : ('foo', 'bar', 'baz', 'toto', 'tutu', 'tata'), - 'type' :'csv', 'metavar' : '<names>', - 'help' : 'Bad variable names which should always be refused, ' - 'separated by a comma'} - ), - ) - - def open(self): - self.stats = self.linter.add_stats(badname_module=0, - badname_class=0, badname_function=0, - badname_method=0, badname_attr=0, - badname_const=0, - badname_variable=0, - badname_inlinevar=0, - badname_argument=0) - - @check_messages('C0102', 'C0103') - def visit_module(self, node): - self._check_name('module', node.name.split('.')[-1], node) - - @check_messages('C0102', 'C0103') - def visit_class(self, node): - self._check_name('class', node.name, node) - for attr, anodes in node.instance_attrs.iteritems(): - self._check_name('attr', attr, anodes[0]) - - @check_messages('C0102', 'C0103') - def visit_function(self, node): - self._check_name(node.is_method() and 'method' or 'function', - node.name, node) - # check arguments name - args = node.args.args - if args is not None: - self._recursive_check_names(args, node) - - @check_messages('C0102', 'C0103') - def visit_assname(self, node): - """check module level assigned names""" - frame = node.frame() - ass_type = node.ass_type() - if isinstance(ass_type, (astng.Comprehension, astng.Comprehension)): - self._check_name('inlinevar', node.name, node) - elif isinstance(frame, astng.Module): - if isinstance(ass_type, astng.Assign) and not in_loop(ass_type): - self._check_name('const', node.name, node) - elif isinstance(ass_type, astng.ExceptHandler): - self._check_name('variable', node.name, node) - elif isinstance(frame, astng.Function): - # global introduced variable aren't in the function locals - if node.name in frame: - self._check_name('variable', node.name, node) - - def _recursive_check_names(self, args, node): - """check names in a possibly recursive list <arg>""" - for arg in args: - if isinstance(arg, astng.AssName): - self._check_name('argument', arg.name, node) - else: - self._recursive_check_names(arg.elts, node) - - def _check_name(self, node_type, name, node): - """check for a name using the type's regexp""" - if is_inside_except(node): - clobbering, _ = clobber_in_except(node) - if clobbering: - return - if name in self.config.good_names: - return - if name in self.config.bad_names: - self.stats['badname_' + node_type] += 1 - self.add_message('C0102', node=node, args=name) - return - regexp = getattr(self.config, node_type + '_rgx') - if regexp.match(name) is None: - type_label = {'inlinedvar': 'inlined variable', - 'const': 'constant', - 'attr': 'attribute', - }.get(node_type, node_type) - self.add_message('C0103', node=node, args=(name, type_label, regexp.pattern)) - self.stats['badname_' + node_type] += 1 - - -class DocStringChecker(_BasicChecker): - msgs = { - 'C0111': ('Missing docstring', # W0131 - 'missing-docstring', - 'Used when a module, function, class or method has no docstring.\ - Some special methods like __init__ doesn\'t necessary require a \ - docstring.'), - 'C0112': ('Empty docstring', # W0132 - 'empty-docstring', - 'Used when a module, function, class or method has an empty \ - docstring (it would be too easy ;).'), - } - options = (('no-docstring-rgx', - {'default' : NO_REQUIRED_DOC_RGX, - 'type' : 'regexp', 'metavar' : '<regexp>', - 'help' : 'Regular expression which should only match ' - 'functions or classes name which do not require a ' - 'docstring'} - ), - ) - - def open(self): - self.stats = self.linter.add_stats(undocumented_module=0, - undocumented_function=0, - undocumented_method=0, - undocumented_class=0) - - def visit_module(self, node): - self._check_docstring('module', node) - - def visit_class(self, node): - if self.config.no_docstring_rgx.match(node.name) is None: - self._check_docstring('class', node) - - def visit_function(self, node): - if self.config.no_docstring_rgx.match(node.name) is None: - ftype = node.is_method() and 'method' or 'function' - if isinstance(node.parent.frame(), astng.Class): - overridden = False - # check if node is from a method overridden by its ancestor - for ancestor in node.parent.frame().ancestors(): - if node.name in ancestor and \ - isinstance(ancestor[node.name], astng.Function): - overridden = True - break - if not overridden: - self._check_docstring(ftype, node) - else: - self._check_docstring(ftype, node) - - def _check_docstring(self, node_type, node): - """check the node has a non empty docstring""" - docstring = node.doc - if docstring is None: - self.stats['undocumented_'+node_type] += 1 - self.add_message('C0111', node=node) - elif not docstring.strip(): - self.stats['undocumented_'+node_type] += 1 - self.add_message('C0112', node=node) - - -class PassChecker(_BasicChecker): - """check is the pass statement is really necessary""" - msgs = {'W0107': ('Unnecessary pass statement', - 'unnecessary-pass', - 'Used when a "pass" statement that can be avoided is ' - 'encountered.'), - } - - def visit_pass(self, node): - if len(node.parent.child_sequence(node)) > 1: - self.add_message('W0107', node=node) - - -class LambdaForComprehensionChecker(_BasicChecker): - """check for using a lambda where a comprehension would do. - - See <http://www.artima.com/weblogs/viewpost.jsp?thread=98196> - where GvR says comprehensions would be clearer. - """ - - msgs = {'W0110': ('map/filter on lambda could be replaced by comprehension', - 'deprecated-lambda', - 'Used when a lambda is the first argument to "map" or ' - '"filter". It could be clearer as a list ' - 'comprehension or generator expression.'), - } - - @check_messages('W0110') - def visit_callfunc(self, node): - """visit a CallFunc node, check if map or filter are called with a - lambda - """ - if not node.args: - return - if not isinstance(node.args[0], astng.Lambda): - return - infered = safe_infer(node.func) - if (infered - and infered.parent.name == '__builtin__' - and infered.name in ['map', 'filter']): - self.add_message('W0110', node=node) - - -def register(linter): - """required method to auto register this checker""" - linter.register_checker(BasicErrorChecker(linter)) - linter.register_checker(BasicChecker(linter)) - linter.register_checker(NameChecker(linter)) - linter.register_checker(DocStringChecker(linter)) - linter.register_checker(PassChecker(linter)) - linter.register_checker(LambdaForComprehensionChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/classes.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/classes.py @@ -1,662 +0,0 @@ -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""classes checker for Python code -""" -from __future__ import generators - -from ..logilab import astng -from ..logilab.astng import YES, Instance, are_exclusive, AssAttr - -from ..interfaces import IASTNGChecker -from ..checkers import BaseChecker -from ..checkers.utils import (PYMETHODS, overrides_a_method, - check_messages, is_attr_private, is_attr_protected, node_frame_class) - -def class_is_abstract(node): - """return true if the given class node should be considered as an abstract - class - """ - for method in node.methods(): - if method.parent.frame() is node: - if method.is_abstract(pass_is_abstract=False): - return True - return False - - -MSGS = { - 'F0202': ('Unable to check methods signature (%s / %s)', - 'method-check-failed', - 'Used when PyLint has been unable to check methods signature \ - compatibility for an unexpected reason. Please report this kind \ - if you don\'t make sense of it.'), - - 'E0202': ('An attribute affected in %s line %s hide this method', - 'method-hidden', - 'Used when a class defines a method which is hidden by an ' - 'instance attribute from an ancestor class or set by some ' - 'client code.'), - 'E0203': ('Access to member %r before its definition line %s', - 'access-member-before-definition', - 'Used when an instance member is accessed before it\'s actually\ - assigned.'), - 'W0201': ('Attribute %r defined outside __init__', - 'attribute-defined-outside-init', - 'Used when an instance attribute is defined outside the __init__\ - method.'), - - 'W0212': ('Access to a protected member %s of a client class', # E0214 - 'protected-access', - 'Used when a protected member (i.e. class member with a name \ - beginning with an underscore) is access outside the class or a \ - descendant of the class where it\'s defined.'), - - 'E0211': ('Method has no argument', - 'no-method-argument', - 'Used when a method which should have the bound instance as \ - first argument has no argument defined.'), - 'E0213': ('Method should have "self" as first argument', - 'no-self-argument', - 'Used when a method has an attribute different the "self" as\ - first argument. This is considered as an error since this is\ - a so common convention that you shouldn\'t break it!'), - 'C0202': ('Class method %s should have %s as first argument', # E0212 - 'bad-classmethod-argument', - 'Used when a class method has a first argument named differently ' - 'than the value specified in valid-classmethod-first-arg option ' - '(default to "cls"), recommended to easily differentiate them ' - 'from regular instance methods.'), - 'C0203': ('Metaclass method %s should have %s as first argument', # E0214 - 'bad-mcs-method-argument', - 'Used when a metaclass method has a first agument named ' - 'differently than the value specified in valid-classmethod-first' - '-arg option (default to "cls"), recommended to easily ' - 'differentiate them from regular instance methods.'), - 'C0204': ('Metaclass class method %s should have %s as first argument', - 'bad-mcs-classmethod-argument', - 'Used when a metaclass class method has a first argument named ' - 'differently than the value specified in valid-metaclass-' - 'classmethod-first-arg option (default to "mcs"), recommended to ' - 'easily differentiate them from regular instance methods.'), - - 'W0211': ('Static method with %r as first argument', - 'bad-staticmethod-argument', - 'Used when a static method has "self" or a value specified in ' - 'valid-classmethod-first-arg option or ' - 'valid-metaclass-classmethod-first-arg option as first argument.' - ), - 'R0201': ('Method could be a function', - 'no-self-use', - 'Used when a method doesn\'t use its bound instance, and so could\ - be written as a function.' - ), - - 'E0221': ('Interface resolved to %s is not a class', - 'interface-is-not-class', - 'Used when a class claims to implement an interface which is not \ - a class.'), - 'E0222': ('Missing method %r from %s interface', - 'missing-interface-method', - 'Used when a method declared in an interface is missing from a \ - class implementing this interface'), - 'W0221': ('Arguments number differs from %s method', - 'arguments-differ', - 'Used when a method has a different number of arguments than in \ - the implemented interface or in an overridden method.'), - 'W0222': ('Signature differs from %s method', - 'signature-differs', - 'Used when a method signature is different than in the \ - implemented interface or in an overridden method.'), - 'W0223': ('Method %r is abstract in class %r but is not overridden', - 'abstract-method', - 'Used when an abstract method (i.e. raise NotImplementedError) is \ - not overridden in concrete class.' - ), - 'F0220': ('failed to resolve interfaces implemented by %s (%s)', # W0224 - 'unresolved-interface', - 'Used when a PyLint as failed to find interfaces implemented by \ - a class'), - - - 'W0231': ('__init__ method from base class %r is not called', - 'super-init-not-called', - 'Used when an ancestor class method has an __init__ method \ - which is not called by a derived class.'), - 'W0232': ('Class has no __init__ method', - 'no-init', - 'Used when a class has no __init__ method, neither its parent \ - classes.'), - 'W0233': ('__init__ method from a non direct base class %r is called', - 'non-parent-init-called', - 'Used when an __init__ method is called on a class which is not \ - in the direct ancestors for the analysed class.'), - - } - - -class ClassChecker(BaseChecker): - """checks for : - * methods without self as first argument - * overridden methods signature - * access only to existent members via self - * attributes not defined in the __init__ method - * supported interfaces implementation - * unreachable code - """ - - __implements__ = (IASTNGChecker,) - - # configuration section name - name = 'classes' - # messages - msgs = MSGS - priority = -2 - # configuration options - options = (('ignore-iface-methods', - {'default' : (#zope interface - 'isImplementedBy', 'deferred', 'extends', 'names', - 'namesAndDescriptions', 'queryDescriptionFor', 'getBases', - 'getDescriptionFor', 'getDoc', 'getName', 'getTaggedValue', - 'getTaggedValueTags', 'isEqualOrExtendedBy', 'setTaggedValue', - 'isImplementedByInstancesOf', - # twisted - 'adaptWith', - # logilab.common interface - 'is_implemented_by'), - 'type' : 'csv', - 'metavar' : '<method names>', - 'help' : 'List of interface methods to ignore, \ -separated by a comma. This is used for instance to not check methods defines \ -in Zope\'s Interface base class.'} - ), - - ('defining-attr-methods', - {'default' : ('__init__', '__new__', 'setUp'), - 'type' : 'csv', - 'metavar' : '<method names>', - 'help' : 'List of method names used to declare (i.e. assign) \ -instance attributes.'} - ), - ('valid-classmethod-first-arg', - {'default' : ('cls',), - 'type' : 'csv', - 'metavar' : '<argument names>', - 'help' : 'List of valid names for the first argument in \ -a class method.'} - ), - ('valid-metaclass-classmethod-first-arg', - {'default' : ('mcs',), - 'type' : 'csv', - 'metavar' : '<argument names>', - 'help' : 'List of valid names for the first argument in \ -a metaclass class method.'} - ), - - ) - - def __init__(self, linter=None): - BaseChecker.__init__(self, linter) - self._accessed = [] - self._first_attrs = [] - self._meth_could_be_func = None - - def visit_class(self, node): - """init visit variable _accessed and check interfaces - """ - self._accessed.append({}) - self._check_bases_classes(node) - self._check_interfaces(node) - # if not an interface, exception, metaclass - if node.type == 'class': - try: - node.local_attr('__init__') - except astng.NotFoundError: - self.add_message('W0232', args=node, node=node) - - @check_messages('E0203', 'W0201') - def leave_class(self, cnode): - """close a class node: - check that instance attributes are defined in __init__ and check - access to existent members - """ - # check access to existent members on non metaclass classes - accessed = self._accessed.pop() - if cnode.type != 'metaclass': - self._check_accessed_members(cnode, accessed) - # checks attributes are defined in an allowed method such as __init__ - if 'W0201' not in self.active_msgs: - return - defining_methods = self.config.defining_attr_methods - for attr, nodes in cnode.instance_attrs.iteritems(): - nodes = [n for n in nodes if not - isinstance(n.statement(), (astng.Delete, astng.AugAssign))] - if not nodes: - continue # error detected by typechecking - attr_defined = False - # check if any method attr is defined in is a defining method - for node in nodes: - if node.frame().name in defining_methods: - attr_defined = True - if not attr_defined: - # check attribute is defined in a parent's __init__ - for parent in cnode.instance_attr_ancestors(attr): - attr_defined = False - # check if any parent method attr is defined in is a defining method - for node in parent.instance_attrs[attr]: - if node.frame().name in defining_methods: - attr_defined = True - if attr_defined: - # we're done :) - break - else: - # check attribute is defined as a class attribute - try: - cnode.local_attr(attr) - except astng.NotFoundError: - self.add_message('W0201', args=attr, node=node) - - def visit_function(self, node): - """check method arguments, overriding""" - # ignore actual functions - if not node.is_method(): - return - klass = node.parent.frame() - self._meth_could_be_func = True - # check first argument is self if this is actually a method - self._check_first_arg_for_type(node, klass.type == 'metaclass') - if node.name == '__init__': - self._check_init(node) - return - # check signature if the method overloads inherited method - for overridden in klass.local_attr_ancestors(node.name): - # get astng for the searched method - try: - meth_node = overridden[node.name] - except KeyError: - # we have found the method but it's not in the local - # dictionary. - # This may happen with astng build from living objects - continue - if not isinstance(meth_node, astng.Function): - continue - self._check_signature(node, meth_node, 'overridden') - break - if node.decorators: - for decorator in node.decorators.nodes: - if isinstance(decorator, astng.Getattr) and \ - decorator.attrname in ('getter', 'setter', 'deleter'): - # attribute affectation will call this method, not hiding it - return - if isinstance(decorator, astng.Name) and decorator.name == 'property': - # attribute affectation will either call a setter or raise - # an attribute error, anyway not hiding the function - return - # check if the method is hidden by an attribute - try: - overridden = klass.instance_attr(node.name)[0] # XXX - args = (overridden.root().name, overridden.fromlineno) - self.add_message('E0202', args=args, node=node) - except astng.NotFoundError: - pass - - def leave_function(self, node): - """on method node, check if this method couldn't be a function - - ignore class, static and abstract methods, initializer, - methods overridden from a parent class and any - kind of method defined in an interface for this warning - """ - if node.is_method(): - if node.args.args is not None: - self._first_attrs.pop() - if 'R0201' not in self.active_msgs: - return - class_node = node.parent.frame() - if (self._meth_could_be_func and node.type == 'method' - and not node.name in PYMETHODS - and not (node.is_abstract() or - overrides_a_method(class_node, node.name)) - and class_node.type != 'interface'): - self.add_message('R0201', node=node) - - def visit_getattr(self, node): - """check if the getattr is an access to a class member - if so, register it. Also check for access to protected - class member from outside its class (but ignore __special__ - methods) - """ - attrname = node.attrname - # Check self - if self.is_first_attr(node): - self._accessed[-1].setdefault(attrname, []).append(node) - return - if 'W0212' not in self.active_msgs: - return - - self._check_protected_attribute_access(node) - - def visit_assign(self, assign_node): - if 'W0212' not in self.active_msgs: - return - - node = assign_node.targets[0] - if not isinstance(node, AssAttr): - return - - if self.is_first_attr(node): - return - - self._check_protected_attribute_access(node) - - def _check_protected_attribute_access(self, node): - '''Given an attribute access node (set or get), check if attribute - access is legitimate. Call _check_first_attr with node before calling - this method. Valid cases are: - * self._attr in a method or cls._attr in a classmethod. Checked by - _check_first_attr. - * Klass._attr inside "Klass" class. - * Klass2._attr inside "Klass" class when Klass2 is a base class of - Klass. - ''' - attrname = node.attrname - - if is_attr_protected(attrname): - - klass = node_frame_class(node) - - # XXX infer to be more safe and less dirty ?? - # in classes, check we are not getting a parent method - # through the class object or through super - callee = node.expr.as_string() - - # We are not in a class, no remaining valid case - if klass is None: - self.add_message('W0212', node=node, args=attrname) - return - - # If the expression begins with a call to super, that's ok. - if isinstance(node.expr, astng.CallFunc) and \ - isinstance(node.expr.func, astng.Name) and \ - node.expr.func.name == 'super': - return - - # We are in a class, one remaining valid cases, Klass._attr inside - # Klass - if not (callee == klass.name or callee in klass.basenames): - self.add_message('W0212', node=node, args=attrname) - - def visit_name(self, node): - """check if the name handle an access to a class member - if so, register it - """ - if self._first_attrs and (node.name == self._first_attrs[-1] or - not self._first_attrs[-1]): - self._meth_could_be_func = False - - def _check_accessed_members(self, node, accessed): - """check that accessed members are defined""" - # XXX refactor, probably much simpler now that E0201 is in type checker - for attr, nodes in accessed.iteritems(): - # deactivate "except doesn't do anything", that's expected - # pylint: disable=W0704 - # is it a class attribute ? - try: - node.local_attr(attr) - # yes, stop here - continue - except astng.NotFoundError: - pass - # is it an instance attribute of a parent class ? - try: - node.instance_attr_ancestors(attr).next() - # yes, stop here - continue - except StopIteration: - pass - # is it an instance attribute ? - try: - defstmts = node.instance_attr(attr) - except astng.NotFoundError: - pass - else: - if len(defstmts) == 1: - defstmt = defstmts[0] - # check that if the node is accessed in the same method as - # it's defined, it's accessed after the initial assignment - frame = defstmt.frame() - lno = defstmt.fromlineno - for _node in nodes: - if _node.frame() is frame and _node.fromlineno < lno \ - and not are_exclusive(_node.statement(), defstmt, ('AttributeError', 'Exception', 'BaseException')): - self.add_message('E0203', node=_node, - args=(attr, lno)) - - def _check_first_arg_for_type(self, node, metaclass=0): - """check the name of first argument, expect: - - * 'self' for a regular method - * 'cls' for a class method or a metaclass regular method (actually - valid-classmethod-first-arg value) - * 'mcs' for a metaclass class method (actually - valid-metaclass-classmethod-first-arg) - * not one of the above for a static method - """ - # don't care about functions with unknown argument (builtins) - if node.args.args is None: - return - first_arg = node.args.args and node.argnames()[0] - self._first_attrs.append(first_arg) - first = self._first_attrs[-1] - # static method - if node.type == 'staticmethod': - if (first_arg == 'self' or - first_arg in self.config.valid_classmethod_first_arg or - first_arg in self.config.valid_metaclass_classmethod_first_arg): - self.add_message('W0211', args=first, node=node) - return - self._first_attrs[-1] = None - # class / regular method with no args - elif not node.args.args: - self.add_message('E0211', node=node) - # metaclass - elif metaclass: - # metaclass __new__ or classmethod - if node.type == 'classmethod': - self._check_first_arg_config(first, - self.config.valid_metaclass_classmethod_first_arg, node, - 'C0204', node.name) - # metaclass regular method - else: - self._check_first_arg_config(first, - self.config.valid_classmethod_first_arg, node, 'C0203', - node.name) - # regular class - else: - # class method - if node.type == 'classmethod': - self._check_first_arg_config(first, - self.config.valid_classmethod_first_arg, node, 'C0202', - node.name) - # regular method without self as argument - elif first != 'self': - self.add_message('E0213', node=node) - - def _check_first_arg_config(self, first, config, node, message, - method_name): - if first not in config: - if len(config) == 1: - valid = repr(config[0]) - else: - valid = ', '.join( - repr(v) - for v in config[:-1]) - valid = '%s or %r' % ( - valid, config[-1]) - self.add_message(message, args=(method_name, valid), node=node) - - def _check_bases_classes(self, node): - """check that the given class node implements abstract methods from - base classes - """ - # check if this class abstract - if class_is_abstract(node): - return - for method in node.methods(): - owner = method.parent.frame() - if owner is node: - continue - # owner is not this class, it must be a parent class - # check that the ancestor's method is not abstract - if method.is_abstract(pass_is_abstract=False): - self.add_message('W0223', node=node, - args=(method.name, owner.name)) - - def _check_interfaces(self, node): - """check that the given class node really implements declared - interfaces - """ - e0221_hack = [False] - def iface_handler(obj): - """filter interface objects, it should be classes""" - if not isinstance(obj, astng.Class): - e0221_hack[0] = True - self.add_message('E0221', node=node, - args=(obj.as_string(),)) - return False - return True - ignore_iface_methods = self.config.ignore_iface_methods - try: - for iface in node.interfaces(handler_func=iface_handler): - for imethod in iface.methods(): - name = imethod.name - if name.startswith('_') or name in ignore_iface_methods: - # don't check method beginning with an underscore, - # usually belonging to the interface implementation - continue - # get class method astng - try: - method = node_method(node, name) - except astng.NotFoundError: - self.add_message('E0222', args=(name, iface.name), - node=node) - continue - # ignore inherited methods - if method.parent.frame() is not node: - continue - # check signature - self._check_signature(method, imethod, - '%s interface' % iface.name) - except astng.InferenceError: - if e0221_hack[0]: - return - implements = Instance(node).getattr('__implements__')[0] - assignment = implements.parent - assert isinstance(assignment, astng.Assign) - # assignment.expr can be a Name or a Tuple or whatever. - # Use as_string() for the message - # FIXME: in case of multiple interfaces, find which one could not - # be resolved - self.add_message('F0220', node=implements, - args=(node.name, assignment.value.as_string())) - - def _check_init(self, node): - """check that the __init__ method call super or ancestors'__init__ - method - """ - if not set(('W0231', 'W0233')) & self.active_msgs: - return - klass_node = node.parent.frame() - to_call = _ancestors_to_call(klass_node) - not_called_yet = dict(to_call) - for stmt in node.nodes_of_class(astng.CallFunc): - expr = stmt.func - if not isinstance(expr, astng.Getattr) \ - or expr.attrname != '__init__': - continue - # skip the test if using super - if isinstance(expr.expr, astng.CallFunc) and \ - isinstance(expr.expr.func, astng.Name) and \ - expr.expr.func.name == 'super': - return - try: - klass = expr.expr.infer().next() - if klass is YES: - continue - try: - del not_called_yet[klass] - except KeyError: - if klass not in to_call: - self.add_message('W0233', node=expr, args=klass.name) - except astng.InferenceError: - continue - for klass, method in not_called_yet.iteritems(): - if klass.name == 'object' or method.parent.name == 'object': - continue - self.add_message('W0231', args=klass.name, node=node) - - def _check_signature(self, method1, refmethod, class_type): - """check that the signature of the two given methods match - - class_type is in 'class', 'interface' - """ - if not (isinstance(method1, astng.Function) - and isinstance(refmethod, astng.Function)): - self.add_message('F0202', args=(method1, refmethod), node=method1) - return - # don't care about functions with unknown argument (builtins) - if method1.args.args is None or refmethod.args.args is None: - return - # if we use *args, **kwargs, skip the below checks - if method1.args.vararg or method1.args.kwarg: - return - if is_attr_private(method1.name): - return - if len(method1.args.args) != len(refmethod.args.args): - self.add_message('W0221', args=class_type, node=method1) - elif len(method1.args.defaults) < len(refmethod.args.defaults): - self.add_message('W0222', args=class_type, node=method1) - - def is_first_attr(self, node): - """Check that attribute lookup name use first attribute variable name - (self for method, cls for classmethod and mcs for metaclass). - """ - return self._first_attrs and isinstance(node.expr, astng.Name) and \ - node.expr.name == self._first_attrs[-1] - -def _ancestors_to_call(klass_node, method='__init__'): - """return a dictionary where keys are the list of base classes providing - the queried method, and so that should/may be called from the method node - """ - to_call = {} - for base_node in klass_node.ancestors(recurs=False): - try: - to_call[base_node] = base_node.igetattr(method).next() - except astng.InferenceError: - continue - return to_call - - -def node_method(node, method_name): - """get astng for <method_name> on the given class node, ensuring it - is a Function node - """ - for n in node.local_attr(method_name): - if isinstance(n, astng.Function): - return n - raise astng.NotFoundError(method_name) - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(ClassChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/design_analysis.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/design_analysis.py @@ -1,407 +0,0 @@ -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""check for signs of poor design - - - see http://intranet.logilab.fr/jpl/view?rql=Any%20X%20where%20X%20eid%201243 - FIXME: missing 13, 15, 16 -""" - -from ..logilab.astng import Function, If, InferenceError - -from ..interfaces import IASTNGChecker -from ..checkers import BaseChecker - -import re - -# regexp for ignored argument name -IGNORED_ARGUMENT_NAMES = re.compile('_.*') - -SPECIAL_METHODS = [('Context manager', set(('__enter__', - '__exit__',))), - ('Container', set(('__len__', - '__getitem__', - '__setitem__', - '__delitem__',))), - ('Callable', set(('__call__',))), - ] - -class SpecialMethodChecker(object): - """A functor that checks for consistency of a set of special methods""" - def __init__(self, methods_found, on_error): - """Stores the set of __x__ method names that were found in the - class and a callable that will be called with args to R0024 if - the check fails - """ - self.methods_found = methods_found - self.on_error = on_error - - def __call__(self, methods_required, protocol): - """Checks the set of method names given to __init__ against the set - required. - - If they are all present, returns true. - If they are all absent, returns false. - If some are present, reports the error and returns false. - """ - required_methods_found = methods_required & self.methods_found - if required_methods_found == methods_required: - return True - if required_methods_found != set(): - required_methods_missing = methods_required - self.methods_found - self.on_error((protocol, - ', '.join(sorted(required_methods_found)), - ', '.join(sorted(required_methods_missing)))) - return False - - -def class_is_abstract(klass): - """return true if the given class node should be considered as an abstract - class - """ - for attr in klass.values(): - if isinstance(attr, Function): - if attr.is_abstract(pass_is_abstract=False): - return True - return False - - -MSGS = { - 'R0901': ('Too many ancestors (%s/%s)', - 'too-many-ancestors', - 'Used when class has too many parent classes, try to reduce \ - this to get a more simple (and so easier to use) class.'), - 'R0902': ('Too many instance attributes (%s/%s)', - 'too-many-instance-attributes', - 'Used when class has too many instance attributes, try to reduce \ - this to get a more simple (and so easier to use) class.'), - 'R0903': ('Too few public methods (%s/%s)', - 'too-few-public-methods', - 'Used when class has too few public methods, so be sure it\'s \ - really worth it.'), - 'R0904': ('Too many public methods (%s/%s)', - 'too-many-public-methods', - 'Used when class has too many public methods, try to reduce \ - this to get a more simple (and so easier to use) class.'), - - 'R0911': ('Too many return statements (%s/%s)', - 'too-many-return-statements', - 'Used when a function or method has too many return statement, \ - making it hard to follow.'), - 'R0912': ('Too many branches (%s/%s)', - 'too-many-branches', - 'Used when a function or method has too many branches, \ - making it hard to follow.'), - 'R0913': ('Too many arguments (%s/%s)', - 'too-many-arguments', - 'Used when a function or method takes too many arguments.'), - 'R0914': ('Too many local variables (%s/%s)', - 'too-many-locals', - 'Used when a function or method has too many local variables.'), - 'R0915': ('Too many statements (%s/%s)', - 'too-many-statements', - 'Used when a function or method has too many statements. You \ - should then split it in smaller functions / methods.'), - - 'R0921': ('Abstract class not referenced', - 'abstract-class-not-used', - 'Used when an abstract class is not used as ancestor anywhere.'), - 'R0922': ('Abstract class is only referenced %s times', - 'abstract-class-little-used', - 'Used when an abstract class is used less than X times as \ - ancestor.'), - 'R0923': ('Interface not implemented', - 'interface-not-implemented', - 'Used when an interface class is not implemented anywhere.'), - 'R0924': ('Badly implemented %s, implements %s but not %s', - 'incomplete-protocol', - 'A class implements some of the special methods for a particular \ - protocol, but not all of them') - } - - -class MisdesignChecker(BaseChecker): - """checks for sign of poor/misdesign: - * number of methods, attributes, local variables... - * size, complexity of functions, methods - """ - - __implements__ = (IASTNGChecker,) - - # configuration section name - name = 'design' - # messages - msgs = MSGS - priority = -2 - # configuration options - options = (('max-args', - {'default' : 5, 'type' : 'int', 'metavar' : '<int>', - 'help': 'Maximum number of arguments for function / method'} - ), - ('ignored-argument-names', - {'default' : IGNORED_ARGUMENT_NAMES, - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'Argument names that match this expression will be ' - 'ignored. Default to name with leading underscore'} - ), - ('max-locals', - {'default' : 15, 'type' : 'int', 'metavar' : '<int>', - 'help': 'Maximum number of locals for function / method body'} - ), - ('max-returns', - {'default' : 6, 'type' : 'int', 'metavar' : '<int>', - 'help': 'Maximum number of return / yield for function / ' - 'method body'} - ), - ('max-branchs', - {'default' : 12, 'type' : 'int', 'metavar' : '<int>', - 'help': 'Maximum number of branch for function / method body'} - ), - ('max-statements', - {'default' : 50, 'type' : 'int', 'metavar' : '<int>', - 'help': 'Maximum number of statements in function / method ' - 'body'} - ), - ('max-parents', - {'default' : 7, - 'type' : 'int', - 'metavar' : '<num>', - 'help' : 'Maximum number of parents for a class (see R0901).'} - ), - ('max-attributes', - {'default' : 7, - 'type' : 'int', - 'metavar' : '<num>', - 'help' : 'Maximum number of attributes for a class \ -(see R0902).'} - ), - ('min-public-methods', - {'default' : 2, - 'type' : 'int', - 'metavar' : '<num>', - 'help' : 'Minimum number of public methods for a class \ -(see R0903).'} - ), - ('max-public-methods', - {'default' : 20, - 'type' : 'int', - 'metavar' : '<num>', - 'help' : 'Maximum number of public methods for a class \ -(see R0904).'} - ), - ) - - def __init__(self, linter=None): - BaseChecker.__init__(self, linter) - self.stats = None - self._returns = None - self._branchs = None - self._used_abstracts = None - self._used_ifaces = None - self._abstracts = None - self._ifaces = None - self._stmts = 0 - - def open(self): - """initialize visit variables""" - self.stats = self.linter.add_stats() - self._returns = [] - self._branchs = [] - self._used_abstracts = {} - self._used_ifaces = {} - self._abstracts = [] - self._ifaces = [] - - def close(self): - """check that abstract/interface classes are used""" - for abstract in self._abstracts: - if not abstract in self._used_abstracts: - self.add_message('R0921', node=abstract) - elif self._used_abstracts[abstract] < 2: - self.add_message('R0922', node=abstract, - args=self._used_abstracts[abstract]) - for iface in self._ifaces: - if not iface in self._used_ifaces: - self.add_message('R0923', node=iface) - - def visit_class(self, node): - """check size of inheritance hierarchy and number of instance attributes - """ - self._inc_branch() - # Is the total inheritance hierarchy is 7 or less? - nb_parents = len(list(node.ancestors())) - if nb_parents > self.config.max_parents: - self.add_message('R0901', node=node, - args=(nb_parents, self.config.max_parents)) - # Does the class contain less than 20 attributes for - # non-GUI classes (40 for GUI)? - # FIXME detect gui classes - if len(node.instance_attrs) > self.config.max_attributes: - self.add_message('R0902', node=node, - args=(len(node.instance_attrs), - self.config.max_attributes)) - # update abstract / interface classes structures - if class_is_abstract(node): - self._abstracts.append(node) - elif node.type == 'interface' and node.name != 'Interface': - self._ifaces.append(node) - for parent in node.ancestors(False): - if parent.name == 'Interface': - continue - self._used_ifaces[parent] = 1 - try: - for iface in node.interfaces(): - self._used_ifaces[iface] = 1 - except InferenceError: - # XXX log ? - pass - for parent in node.ancestors(): - try: - self._used_abstracts[parent] += 1 - except KeyError: - self._used_abstracts[parent] = 1 - - def leave_class(self, node): - """check number of public methods""" - nb_public_methods = 0 - special_methods = set() - for method in node.methods(): - if not method.name.startswith('_'): - nb_public_methods += 1 - if method.name.startswith("__"): - special_methods.add(method.name) - # Does the class contain less than 20 public methods ? - if nb_public_methods > self.config.max_public_methods: - self.add_message('R0904', node=node, - args=(nb_public_methods, - self.config.max_public_methods)) - # stop here for exception, metaclass and interface classes - if node.type != 'class': - return - # Does the class implement special methods consitently? - # If so, don't enforce minimum public methods. - check_special = SpecialMethodChecker( - special_methods, lambda args: self.add_message('R0924', node=node, args=args)) - protocols = [check_special(pmethods, pname) for pname, pmethods in SPECIAL_METHODS] - if True in protocols: - return - # Does the class contain more than 5 public methods ? - if nb_public_methods < self.config.min_public_methods: - self.add_message('R0903', node=node, - args=(nb_public_methods, - self.config.min_public_methods)) - - def visit_function(self, node): - """check function name, docstring, arguments, redefinition, - variable names, max locals - """ - self._inc_branch() - # init branch and returns counters - self._returns.append(0) - self._branchs.append(0) - # check number of arguments - args = node.args.args - if args is not None: - ignored_args_num = len( - [arg for arg in args - if self.config.ignored_argument_names.match(arg.name)]) - argnum = len(args) - ignored_args_num - if argnum > self.config.max_args: - self.add_message('R0913', node=node, - args=(len(args), self.config.max_args)) - else: - ignored_args_num = 0 - # check number of local variables - locnum = len(node.locals) - ignored_args_num - if locnum > self.config.max_locals: - self.add_message('R0914', node=node, - args=(locnum, self.config.max_locals)) - # init statements counter - self._stmts = 1 - - def leave_function(self, node): - """most of the work is done here on close: - checks for max returns, branch, return in __init__ - """ - returns = self._returns.pop() - if returns > self.config.max_returns: - self.add_message('R0911', node=node, - args=(returns, self.config.max_returns)) - branchs = self._branchs.pop() - if branchs > self.config.max_branchs: - self.add_message('R0912', node=node, - args=(branchs, self.config.max_branchs)) - # check number of statements - if self._stmts > self.config.max_statements: - self.add_message('R0915', node=node, - args=(self._stmts, self.config.max_statements)) - - def visit_return(self, _): - """count number of returns""" - if not self._returns: - return # return outside function, reported by the base checker - self._returns[-1] += 1 - - def visit_default(self, node): - """default visit method -> increments the statements counter if - necessary - """ - if node.is_statement: - self._stmts += 1 - - def visit_tryexcept(self, node): - """increments the branchs counter""" - branchs = len(node.handlers) - if node.orelse: - branchs += 1 - self._inc_branch(branchs) - self._stmts += branchs - - def visit_tryfinally(self, _): - """increments the branchs counter""" - self._inc_branch(2) - self._stmts += 2 - - def visit_if(self, node): - """increments the branchs counter""" - branchs = 1 - # don't double count If nodes coming from some 'elif' - if node.orelse and (len(node.orelse)>1 or - not isinstance(node.orelse[0], If)): - branchs += 1 - self._inc_branch(branchs) - self._stmts += branchs - - def visit_while(self, node): - """increments the branchs counter""" - branchs = 1 - if node.orelse: - branchs += 1 - self._inc_branch(branchs) - - visit_for = visit_while - - def _inc_branch(self, branchsnum=1): - """increments the branchs counter""" - branchs = self._branchs - for i in xrange(len(branchs)): - branchs[i] += branchsnum - - # FIXME: make a nice report... - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(MisdesignChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/exceptions.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/exceptions.py @@ -1,213 +0,0 @@ -# Copyright (c) 2003-2007 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""exceptions handling (raising, catching, exceptions classes) checker -""" -import sys - -from ..logilab.common.compat import builtins -BUILTINS_NAME = builtins.__name__ -from ..logilab import astng -from ..logilab.astng import YES, Instance, unpack_infer - -from ..checkers import BaseChecker -from ..checkers.utils import is_empty, is_raising -from ..interfaces import IASTNGChecker - - -OVERGENERAL_EXCEPTIONS = ('Exception',) - -MSGS = { - 'E0701': ('Bad except clauses order (%s)', - 'bad-except-order', - 'Used when except clauses are not in the correct order (from the ' - 'more specific to the more generic). If you don\'t fix the order, ' - 'some exceptions may not be catched by the most specific handler.'), - 'E0702': ('Raising %s while only classes, instances or string are allowed', - 'raising-bad-type', - 'Used when something which is neither a class, an instance or a \ - string is raised (i.e. a `TypeError` will be raised).'), - 'E0710': ('Raising a new style class which doesn\'t inherit from BaseException', - 'raising-non-exception', - 'Used when a new style class which doesn\'t inherit from \ - BaseException is raised.'), - 'E0711': ('NotImplemented raised - should raise NotImplementedError', - 'notimplemented-raised', - 'Used when NotImplemented is raised instead of \ - NotImplementedError'), - - 'W0701': ('Raising a string exception', - 'raising-string', - 'Used when a string exception is raised.'), - 'W0702': ('No exception type(s) specified', - 'bare-except', - 'Used when an except clause doesn\'t specify exceptions type to \ - catch.'), - 'W0703': ('Catching too general exception %s', - 'broad-except', - 'Used when an except catches a too general exception, \ - possibly burying unrelated errors.'), - 'W0704': ('Except doesn\'t do anything', - 'pointless-except', - 'Used when an except clause does nothing but "pass" and there is\ - no "else" clause.'), - 'W0710': ('Exception doesn\'t inherit from standard "Exception" class', - 'nonstandard-exception', - 'Used when a custom exception class is raised but doesn\'t \ - inherit from the builtin "Exception" class.'), - 'W0711': ('Exception to catch is the result of a binary "%s" operation', - 'binary-op-exception', - 'Used when the exception to catch is of the form \ - "except A or B:". If intending to catch multiple, \ - rewrite as "except (A, B):"'), - } - - -if sys.version_info < (3, 0): - EXCEPTIONS_MODULE = "exceptions" -else: - EXCEPTIONS_MODULE = "builtins" - -class ExceptionsChecker(BaseChecker): - """checks for - * excepts without exception filter - * type of raise argument : string, Exceptions, other values - """ - - __implements__ = IASTNGChecker - - name = 'exceptions' - msgs = MSGS - priority = -4 - options = (('overgeneral-exceptions', - {'default' : OVERGENERAL_EXCEPTIONS, - 'type' :'csv', 'metavar' : '<comma-separated class names>', - 'help' : 'Exceptions that will emit a warning ' - 'when being caught. Defaults to "%s"' % ( - ', '.join(OVERGENERAL_EXCEPTIONS),)} - ), - ) - - def visit_raise(self, node): - """visit raise possibly inferring value""" - # ignore empty raise - if node.exc is None: - return - expr = node.exc - if self._check_raise_value(node, expr): - return - else: - try: - value = unpack_infer(expr).next() - except astng.InferenceError: - return - self._check_raise_value(node, value) - - def _check_raise_value(self, node, expr): - """check for bad values, string exception and class inheritance - """ - value_found = True - if isinstance(expr, astng.Const): - value = expr.value - if isinstance(value, str): - self.add_message('W0701', node=node) - else: - self.add_message('E0702', node=node, - args=value.__class__.__name__) - elif (isinstance(expr, astng.Name) and \ - expr.name in ('None', 'True', 'False')) or \ - isinstance(expr, (astng.List, astng.Dict, astng.Tuple, - astng.Module, astng.Function)): - self.add_message('E0702', node=node, args=expr.name) - elif ( (isinstance(expr, astng.Name) and expr.name == 'NotImplemented') - or (isinstance(expr, astng.CallFunc) and - isinstance(expr.func, astng.Name) and - expr.func.name == 'NotImplemented') ): - self.add_message('E0711', node=node) - elif isinstance(expr, astng.BinOp) and expr.op == '%': - self.add_message('W0701', node=node) - elif isinstance(expr, (Instance, astng.Class)): - if isinstance(expr, Instance): - expr = expr._proxied - if (isinstance(expr, astng.Class) and - not inherit_from_std_ex(expr) and - expr.root().name != BUILTINS_NAME): - if expr.newstyle: - self.add_message('E0710', node=node) - else: - self.add_message('W0710', node=node) - else: - value_found = False - else: - value_found = False - return value_found - - - def visit_tryexcept(self, node): - """check for empty except""" - exceptions_classes = [] - nb_handlers = len(node.handlers) - for index, handler in enumerate(node.handlers): - # single except doing nothing but "pass" without else clause - if nb_handlers == 1 and is_empty(handler.body) and not node.orelse: - self.add_message('W0704', node=handler.type or handler.body[0]) - if handler.type is None: - if nb_handlers == 1 and not is_raising(handler.body): - self.add_message('W0702', node=handler) - # check if a "except:" is followed by some other - # except - elif index < (nb_handlers - 1): - msg = 'empty except clause should always appear last' - self.add_message('E0701', node=node, args=msg) - - elif isinstance(handler.type, astng.BoolOp): - self.add_message('W0711', node=handler, args=handler.type.op) - else: - try: - excs = list(unpack_infer(handler.type)) - except astng.InferenceError: - continue - for exc in excs: - # XXX skip other non class nodes - if exc is YES or not isinstance(exc, astng.Class): - continue - exc_ancestors = [anc for anc in exc.ancestors() - if isinstance(anc, astng.Class)] - for previous_exc in exceptions_classes: - if previous_exc in exc_ancestors: - msg = '%s is an ancestor class of %s' % ( - previous_exc.name, exc.name) - self.add_message('E0701', node=handler.type, args=msg) - if (exc.name in self.config.overgeneral_exceptions - and exc.root().name == EXCEPTIONS_MODULE - and nb_handlers == 1 and not is_raising(handler.body)): - self.add_message('W0703', args=exc.name, node=handler.type) - exceptions_classes += excs - - -def inherit_from_std_ex(node): - """return true if the given class node is subclass of - exceptions.Exception - """ - if node.name in ('Exception', 'BaseException') \ - and node.root().name == EXCEPTIONS_MODULE: - return True - for parent in node.ancestors(recurs=False): - if inherit_from_std_ex(parent): - return True - return False - -def register(linter): - """required method to auto register this checker""" - linter.register_checker(ExceptionsChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/format.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/format.py @@ -1,476 +0,0 @@ -# Copyright (c) 2003-2010 Sylvain Thenault (thenault@gmail.com). -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# Copyright 2012 Google Inc. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Python code format's checker. - -By default try to follow Guido's style guide : - -http://www.python.org/doc/essays/styleguide.html - -Some parts of the process_token method is based from The Tab Nanny std module. -""" - -import re, sys -import tokenize -if not hasattr(tokenize, 'NL'): - raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") - -from ..logilab.common.textutils import pretty_match -from ..logilab.astng import nodes - -from ..interfaces import IRawChecker, IASTNGChecker -from ..checkers import BaseRawChecker -from ..checkers.utils import check_messages - -MSGS = { - 'C0301': ('Line too long (%s/%s)', - 'line-too-long', - 'Used when a line is longer than a given number of characters.'), - 'C0302': ('Too many lines in module (%s)', # was W0302 - 'too-many-lines', - 'Used when a module has too much lines, reducing its readability.' - ), - - 'W0311': ('Bad indentation. Found %s %s, expected %s', - 'bad-indentation', - 'Used when an unexpected number of indentation\'s tabulations or ' - 'spaces has been found.'), - 'W0312': ('Found indentation with %ss instead of %ss', - 'mixed-indentation', - 'Used when there are some mixed tabs and spaces in a module.'), - 'W0301': ('Unnecessary semicolon', # was W0106 - 'unnecessary-semicolon', - 'Used when a statement is ended by a semi-colon (";"), which \ - isn\'t necessary (that\'s python, not C ;).'), - 'C0321': ('More than one statement on a single line', - 'multiple-statements', - 'Used when more than on statement are found on the same line.'), - 'C0322': ('Operator not preceded by a space\n%s', - 'no-space-before-operator', - 'Used when one of the following operator (!= | <= | == | >= | < ' - '| > | = | \\+= | -= | \\*= | /= | %) is not preceded by a space.'), - 'C0323': ('Operator not followed by a space\n%s', - 'no-space-after-operator', - 'Used when one of the following operator (!= | <= | == | >= | < ' - '| > | = | \\+= | -= | \\*= | /= | %) is not followed by a space.'), - 'C0324': ('Comma not followed by a space\n%s', - 'no-space-after-comma', - 'Used when a comma (",") is not followed by a space.'), - } - -if sys.version_info < (3, 0): - - MSGS.update({ - 'W0331': ('Use of the <> operator', - 'old-ne-operator', - 'Used when the deprecated "<>" operator is used instead \ - of "!=".'), - 'W0332': ('Use of "l" as long integer identifier', - 'lowercase-l-suffix', - 'Used when a lower case "l" is used to mark a long integer. You ' - 'should use a upper case "L" since the letter "l" looks too much ' - 'like the digit "1"'), - 'W0333': ('Use of the `` operator', - 'backtick', - 'Used when the deprecated "``" (backtick) operator is used ' - 'instead of the str() function.'), - }) - -# simple quoted string rgx -SQSTRING_RGX = r'"([^"\\]|\\.)*?"' -# simple apostrophed rgx -SASTRING_RGX = r"'([^'\\]|\\.)*?'" -# triple quoted string rgx -TQSTRING_RGX = r'"""([^"]|("(?!"")))*?(""")' -# triple apostrophe'd string rgx -TASTRING_RGX = r"'''([^']|('(?!'')))*?(''')" - -# finally, the string regular expression -STRING_RGX = re.compile('(%s)|(%s)|(%s)|(%s)' % (TQSTRING_RGX, TASTRING_RGX, - SQSTRING_RGX, SASTRING_RGX), - re.MULTILINE|re.DOTALL) - -COMMENT_RGX = re.compile("#.*$", re.M) - -OPERATORS = r'!=|<=|==|>=|<|>|=|\+=|-=|\*=|/=|%' - -OP_RGX_MATCH_1 = r'[^(]*(?<!\s|\^|<|>|=|\+|-|\*|/|!|%%|&|\|)(%s).*' % OPERATORS -OP_RGX_SEARCH_1 = r'(?<!\s|\^|<|>|=|\+|-|\*|/|!|%%|&|\|)(%s)' % OPERATORS - -OP_RGX_MATCH_2 = r'[^(]*(%s)(?!\s|=|>|<).*' % OPERATORS -OP_RGX_SEARCH_2 = r'(%s)(?!\s|=|>)' % OPERATORS - -BAD_CONSTRUCT_RGXS = ( - - (re.compile(OP_RGX_MATCH_1, re.M), - re.compile(OP_RGX_SEARCH_1, re.M), - 'C0322'), - - (re.compile(OP_RGX_MATCH_2, re.M), - re.compile(OP_RGX_SEARCH_2, re.M), - 'C0323'), - - (re.compile(r'.*,[^(\s|\]|}|\))].*', re.M), - re.compile(r',[^\s)]', re.M), - 'C0324'), - ) - -_PY3K = sys.version_info >= (3, 0) - -def get_string_coords(line): - """return a list of string positions (tuple (start, end)) in the line - """ - result = [] - for match in re.finditer(STRING_RGX, line): - result.append( (match.start(), match.end()) ) - return result - -def in_coords(match, string_coords): - """return true if the match is in the string coord""" - mstart = match.start() - for start, end in string_coords: - if mstart >= start and mstart < end: - return True - return False - -def check_line(line): - """check a line for a bad construction - if it founds one, return a message describing the problem - else return None - """ - cleanstr = COMMENT_RGX.sub('', STRING_RGX.sub('', line)) - for rgx_match, rgx_search, msg_id in BAD_CONSTRUCT_RGXS: - if rgx_match.match(cleanstr): - string_positions = get_string_coords(line) - for match in re.finditer(rgx_search, line): - if not in_coords(match, string_positions): - return msg_id, pretty_match(match, line.rstrip()) - - -class FormatChecker(BaseRawChecker): - """checks for : - * unauthorized constructions - * strict indentation - * line length - * use of <> instead of != - """ - - __implements__ = (IRawChecker, IASTNGChecker) - - # configuration section name - name = 'format' - # messages - msgs = MSGS - # configuration options - # for available dict keys/values see the optik parser 'add_option' method - options = (('max-line-length', - {'default' : 80, 'type' : "int", 'metavar' : '<int>', - 'help' : 'Maximum number of characters on a single line.'}), - ('max-module-lines', - {'default' : 1000, 'type' : 'int', 'metavar' : '<int>', - 'help': 'Maximum number of lines in a module'} - ), - ('indent-string', - {'default' : ' ', 'type' : "string", 'metavar' : '<string>', - 'help' : 'String used as indentation unit. This is usually \ -" " (4 spaces) or "\\t" (1 tab).'}), - ) - def __init__(self, linter=None): - BaseRawChecker.__init__(self, linter) - self._lines = None - self._visited_lines = None - - def process_module(self, node): - """extracts encoding from the stream and decodes each line, so that - international text's length is properly calculated. - """ - stream = node.file_stream - stream.seek(0) # XXX may be removed with astng > 0.23 - readline = stream.readline - if sys.version_info < (3, 0): - if node.file_encoding is not None: - readline = lambda: stream.readline().decode(node.file_encoding, 'replace') - self.process_tokens(tokenize.generate_tokens(readline)) - - def new_line(self, tok_type, line, line_num, junk): - """a new line has been encountered, process it if necessary""" - if not tok_type in junk: - self._lines[line_num] = line.split('\n')[0] - self.check_lines(line, line_num) - - def process_tokens(self, tokens): - """process tokens and search for : - - _ non strict indentation (i.e. not always using the <indent> parameter as - indent unit) - _ too long lines (i.e. longer than <max_chars>) - _ optionally bad construct (if given, bad_construct must be a compiled - regular expression). - """ - indent = tokenize.INDENT - dedent = tokenize.DEDENT - newline = tokenize.NEWLINE - junk = (tokenize.COMMENT, tokenize.NL) - indents = [0] - check_equal = 0 - line_num = 0 - previous = None - self._lines = {} - self._visited_lines = {} - for (tok_type, token, start, _, line) in tokens: - if start[0] != line_num: - if previous is not None and previous[0] == tokenize.OP and previous[1] == ';': - self.add_message('W0301', line=previous[2]) - previous = None - line_num = start[0] - self.new_line(tok_type, line, line_num, junk) - if tok_type not in (indent, dedent, newline) + junk: - previous = tok_type, token, start[0] - - if tok_type == tokenize.OP: - if token == '<>': - self.add_message('W0331', line=line_num) - elif tok_type == tokenize.NUMBER: - if token.endswith('l'): - self.add_message('W0332', line=line_num) - - elif tok_type == newline: - # a program statement, or ENDMARKER, will eventually follow, - # after some (possibly empty) run of tokens of the form - # (NL | COMMENT)* (INDENT | DEDENT+)? - # If an INDENT appears, setting check_equal is wrong, and will - # be undone when we see the INDENT. - check_equal = 1 - - elif tok_type == indent: - check_equal = 0 - self.check_indent_level(token, indents[-1]+1, line_num) - indents.append(indents[-1]+1) - - elif tok_type == dedent: - # there's nothing we need to check here! what's important is - # that when the run of DEDENTs ends, the indentation of the - # program statement (or ENDMARKER) that triggered the run is - # equal to what's left at the top of the indents stack - check_equal = 1 - if len(indents) > 1: - del indents[-1] - - elif check_equal and tok_type not in junk: - # this is the first "real token" following a NEWLINE, so it - # must be the first token of the next program statement, or an - # ENDMARKER; the "line" argument exposes the leading whitespace - # for this statement; in the case of ENDMARKER, line is an empty - # string, so will properly match the empty string with which the - # "indents" stack was seeded - check_equal = 0 - self.check_indent_level(line, indents[-1], line_num) - - line_num -= 1 # to be ok with "wc -l" - if line_num > self.config.max_module_lines: - self.add_message('C0302', args=line_num, line=1) - - @check_messages('C0321' ,'C03232', 'C0323', 'C0324') - def visit_default(self, node): - """check the node line number and check it if not yet done""" - if not node.is_statement: - return - if not node.root().pure_python: - return # XXX block visit of child nodes - prev_sibl = node.previous_sibling() - if prev_sibl is not None: - prev_line = prev_sibl.fromlineno - else: - prev_line = node.parent.statement().fromlineno - line = node.fromlineno - assert line, node - if prev_line == line and self._visited_lines.get(line) != 2: - # py2.5 try: except: finally: - if not (isinstance(node, nodes.TryExcept) - and isinstance(node.parent, nodes.TryFinally) - and node.fromlineno == node.parent.fromlineno): - self.add_message('C0321', node=node) - self._visited_lines[line] = 2 - return - if line in self._visited_lines: - return - try: - tolineno = node.blockstart_tolineno - except AttributeError: - tolineno = node.tolineno - assert tolineno, node - lines = [] - for line in xrange(line, tolineno + 1): - self._visited_lines[line] = 1 - try: - lines.append(self._lines[line].rstrip()) - except KeyError: - lines.append('') - try: - msg_def = check_line('\n'.join(lines)) - if msg_def: - self.add_message(msg_def[0], node=node, args=msg_def[1]) - except KeyError: - # FIXME: internal error ! - pass - - @check_messages('W0333') - def visit_backquote(self, node): - self.add_message('W0333', node=node) - - def check_lines(self, lines, i): - """check lines have less than a maximum number of characters - """ - max_chars = self.config.max_line_length - for line in lines.splitlines(): - if len(line) > max_chars: - self.add_message('C0301', line=i, args=(len(line), max_chars)) - i += 1 - - def check_indent_level(self, string, expected, line_num): - """return the indent level of the string - """ - indent = self.config.indent_string - if indent == '\\t': # \t is not interpreted in the configuration file - indent = '\t' - level = 0 - unit_size = len(indent) - while string[:unit_size] == indent: - string = string[unit_size:] - level += 1 - suppl = '' - while string and string[0] in ' \t': - if string[0] != indent[0]: - if string[0] == '\t': - args = ('tab', 'space') - else: - args = ('space', 'tab') - self.add_message('W0312', args=args, line=line_num) - return level - suppl += string[0] - string = string [1:] - if level != expected or suppl: - i_type = 'spaces' - if indent[0] == '\t': - i_type = 'tabs' - self.add_message('W0311', line=line_num, - args=(level * unit_size + len(suppl), i_type, - expected * unit_size)) - - -class StringConstantChecker(BaseRawChecker): - """Check string literals""" - - msgs = { - 'W1401': ('Anomalous backslash in string: \'%s\'. ' - 'String constant might be missing an r prefix.', - 'anomalous-backslash-in-string', - 'Used when a backslash is in a literal string but not as an ' - 'escape.'), - 'W1402': ('Anomalous Unicode escape in byte string: \'%s\'. ' - 'String constant might be missing an r or u prefix.', - 'anomalous-unicode-escape-in-string', - 'Used when an escape like \\u is encountered in a byte ' - 'string where it has no effect.'), - } - name = 'string_constant' - __implements__ = (IRawChecker, IASTNGChecker) - - # Characters that have a special meaning after a backslash in either - # Unicode or byte strings. - ESCAPE_CHARACTERS = 'abfnrtvx\n\r\t\\\'\"01234567' - - # TODO(mbp): Octal characters are quite an edge case today; people may - # prefer a separate warning where they occur. \0 should be allowed. - - # Characters that have a special meaning after a backslash but only in - # Unicode strings. - UNICODE_ESCAPE_CHARACTERS = 'uUN' - - def process_tokens(self, tokens): - for (tok_type, token, (start_row, start_col), _, _) in tokens: - if tok_type == tokenize.STRING: - # 'token' is the whole un-parsed token; we can look at the start - # of it to see whether it's a raw or unicode string etc. - self.process_string_token(token, start_row, start_col) - - def process_string_token(self, token, start_row, start_col): - for i, c in enumerate(token): - if c in '\'\"': - quote_char = c - break - prefix = token[:i].lower() # markers like u, b, r. - after_prefix = token[i:] - if after_prefix[:3] == after_prefix[-3:] == 3 * quote_char: - string_body = after_prefix[3:-3] - else: - string_body = after_prefix[1:-1] # Chop off quotes - # No special checks on raw strings at the moment. - if 'r' not in prefix: - self.process_non_raw_string_token(prefix, string_body, - start_row, start_col) - - def process_non_raw_string_token(self, prefix, string_body, start_row, - start_col): - """check for bad escapes in a non-raw string. - - prefix: lowercase string of eg 'ur' string prefix markers. - string_body: the un-parsed body of the string, not including the quote - marks. - start_row: integer line number in the source. - start_col: integer column number in the source. - """ - # Walk through the string; if we see a backslash then escape the next - # character, and skip over it. If we see a non-escaped character, - # alert, and continue. - # - # Accept a backslash when it escapes a backslash, or a quote, or - # end-of-line, or one of the letters that introduce a special escape - # sequence <http://docs.python.org/reference/lexical_analysis.html> - # - # TODO(mbp): Maybe give a separate warning about the rarely-used - # \a \b \v \f? - # - # TODO(mbp): We could give the column of the problem character, but - # add_message doesn't seem to have a way to pass it through at present. - i = 0 - while True: - i = string_body.find('\\', i) - if i == -1: - break - # There must be a next character; having a backslash at the end - # of the string would be a SyntaxError. - next_char = string_body[i+1] - match = string_body[i:i+2] - if next_char in self.UNICODE_ESCAPE_CHARACTERS: - if 'u' in prefix: - pass - elif _PY3K and 'b' not in prefix: - pass # unicode by default - else: - self.add_message('W1402', line=start_row, args=(match, )) - elif next_char not in self.ESCAPE_CHARACTERS: - self.add_message('W1401', line=start_row, args=(match, )) - # Whether it was a valid escape or not, backslash followed by - # another character can always be consumed whole: the second - # character can never be the start of a new backslash escape. - i += 2 - - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(FormatChecker(linter)) - linter.register_checker(StringConstantChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/imports.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/imports.py @@ -1,392 +0,0 @@ -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""imports checkers for Python code""" - -from ..logilab.common.graph import get_cycles, DotBackend -from ..logilab.common.modutils import is_standard_module -from ..logilab.common.ureports import VerbatimText, Paragraph - -from ..logilab import astng -from ..logilab.astng import are_exclusive - -from ..interfaces import IASTNGChecker -from ..checkers import BaseChecker, EmptyReport - - -def get_first_import(node, context, name, base, level): - """return the node where [base.]<name> is imported or None if not found - """ - fullname = '%s.%s' % (base, name) if base else name - - first = None - found = False - for first in context.body: - if first is node: - continue - if first.scope() is node.scope() and first.fromlineno > node.fromlineno: - continue - if isinstance(first, astng.Import): - if any(fullname == iname[0] for iname in first.names): - found = True - break - elif isinstance(first, astng.From): - if level == first.level and any( - fullname == '%s.%s' % (first.modname, iname[0]) for iname in first.names): - found = True - break - if found and not are_exclusive(first, node): - return first - -# utilities to represents import dependencies as tree and dot graph ########### - -def filter_dependencies_info(dep_info, package_dir, mode='external'): - """filter external or internal dependencies from dep_info (return a - new dictionary containing the filtered modules only) - """ - if mode == 'external': - filter_func = lambda x: not is_standard_module(x, (package_dir,)) - else: - assert mode == 'internal' - filter_func = lambda x: is_standard_module(x, (package_dir,)) - result = {} - for importee, importers in dep_info.iteritems(): - if filter_func(importee): - result[importee] = importers - return result - -def make_tree_defs(mod_files_list): - """get a list of 2-uple (module, list_of_files_which_import_this_module), - it will return a dictionary to represent this as a tree - """ - tree_defs = {} - for mod, files in mod_files_list: - node = (tree_defs, ()) - for prefix in mod.split('.'): - node = node[0].setdefault(prefix, [{}, []]) - node[1] += files - return tree_defs - -def repr_tree_defs(data, indent_str=None): - """return a string which represents imports as a tree""" - lines = [] - nodes = data.items() - for i, (mod, (sub, files)) in enumerate(sorted(nodes, key=lambda x: x[0])): - if not files: - files = '' - else: - files = '(%s)' % ','.join(files) - if indent_str is None: - lines.append('%s %s' % (mod, files)) - sub_indent_str = ' ' - else: - lines.append(r'%s\-%s %s' % (indent_str, mod, files)) - if i == len(nodes)-1: - sub_indent_str = '%s ' % indent_str - else: - sub_indent_str = '%s| ' % indent_str - if sub: - lines.append(repr_tree_defs(sub, sub_indent_str)) - return '\n'.join(lines) - - -def dependencies_graph(filename, dep_info): - """write dependencies as a dot (graphviz) file - """ - done = {} - printer = DotBackend(filename[:-4], rankdir = "LR") - printer.emit('URL="." node[shape="box"]') - for modname, dependencies in sorted(dep_info.iteritems()): - done[modname] = 1 - printer.emit_node(modname) - for modname in dependencies: - if modname not in done: - done[modname] = 1 - printer.emit_node(modname) - for depmodname, dependencies in sorted(dep_info.iteritems()): - for modname in dependencies: - printer.emit_edge(modname, depmodname) - printer.generate(filename) - - -def make_graph(filename, dep_info, sect, gtype): - """generate a dependencies graph and add some information about it in the - report's section - """ - dependencies_graph(filename, dep_info) - sect.append(Paragraph('%simports graph has been written to %s' - % (gtype, filename))) - - -# the import checker itself ################################################### - -MSGS = { - 'F0401': ('Unable to import %s', - 'import-error', - 'Used when pylint has been unable to import a module.'), - 'R0401': ('Cyclic import (%s)', - 'cyclic-import', - 'Used when a cyclic import between two or more modules is \ - detected.'), - - 'W0401': ('Wildcard import %s', - 'wildcard-import', - 'Used when `from module import *` is detected.'), - 'W0402': ('Uses of a deprecated module %r', - 'deprecated-module', - 'Used a module marked as deprecated is imported.'), - 'W0403': ('Relative import %r, should be %r', - 'relative-import', - 'Used when an import relative to the package directory is \ - detected.'), - 'W0404': ('Reimport %r (imported line %s)', - 'reimported', - 'Used when a module is reimported multiple times.'), - 'W0406': ('Module import itself', - 'import-self', - 'Used when a module is importing itself.'), - - 'W0410': ('__future__ import is not the first non docstring statement', - 'misplaced-future', - 'Python 2.5 and greater require __future__ import to be the \ - first non docstring statement in the module.'), - } - -class ImportsChecker(BaseChecker): - """checks for - * external modules dependencies - * relative / wildcard imports - * cyclic imports - * uses of deprecated modules - """ - - __implements__ = IASTNGChecker - - name = 'imports' - msgs = MSGS - priority = -2 - - options = (('deprecated-modules', - {'default' : ('regsub', 'string', 'TERMIOS', - 'Bastion', 'rexec'), - 'type' : 'csv', - 'metavar' : '<modules>', - 'help' : 'Deprecated modules which should not be used, \ -separated by a comma'} - ), - ('import-graph', - {'default' : '', - 'type' : 'string', - 'metavar' : '<file.dot>', - 'help' : 'Create a graph of every (i.e. internal and \ -external) dependencies in the given file (report RP0402 must not be disabled)'} - ), - ('ext-import-graph', - {'default' : '', - 'type' : 'string', - 'metavar' : '<file.dot>', - 'help' : 'Create a graph of external dependencies in the \ -given file (report RP0402 must not be disabled)'} - ), - ('int-import-graph', - {'default' : '', - 'type' : 'string', - 'metavar' : '<file.dot>', - 'help' : 'Create a graph of internal dependencies in the \ -given file (report RP0402 must not be disabled)'} - ), - - ) - - def __init__(self, linter=None): - BaseChecker.__init__(self, linter) - self.stats = None - self.import_graph = None - self.__int_dep_info = self.__ext_dep_info = None - self.reports = (('RP0401', 'External dependencies', - self.report_external_dependencies), - ('RP0402', 'Modules dependencies graph', - self.report_dependencies_graph), - ) - - def open(self): - """called before visiting project (i.e set of modules)""" - self.linter.add_stats(dependencies={}) - self.linter.add_stats(cycles=[]) - self.stats = self.linter.stats - self.import_graph = {} - - def close(self): - """called before visiting project (i.e set of modules)""" - # don't try to compute cycles if the associated message is disabled - if self.linter.is_message_enabled('R0401'): - for cycle in get_cycles(self.import_graph): - self.add_message('R0401', args=' -> '.join(cycle)) - - def visit_import(self, node): - """triggered when an import statement is seen""" - modnode = node.root() - for name, _ in node.names: - importedmodnode = self.get_imported_module(modnode, node, name) - if importedmodnode is None: - continue - self._check_relative_import(modnode, node, importedmodnode, name) - self._add_imported_module(node, importedmodnode.name) - self._check_deprecated_module(node, name) - self._check_reimport(node, name) - - - def visit_from(self, node): - """triggered when a from statement is seen""" - basename = node.modname - if basename == '__future__': - # check if this is the first non-docstring statement in the module - prev = node.previous_sibling() - if prev: - # consecutive future statements are possible - if not (isinstance(prev, astng.From) - and prev.modname == '__future__'): - self.add_message('W0410', node=node) - return - modnode = node.root() - importedmodnode = self.get_imported_module(modnode, node, basename) - if importedmodnode is None: - return - self._check_relative_import(modnode, node, importedmodnode, basename) - self._check_deprecated_module(node, basename) - for name, _ in node.names: - if name == '*': - self.add_message('W0401', args=basename, node=node) - continue - self._add_imported_module(node, '%s.%s' % (importedmodnode.name, name)) - self._check_reimport(node, name, basename, node.level) - - def get_imported_module(self, modnode, importnode, modname): - try: - return importnode.do_import_module(modname) - except astng.InferenceError, ex: - if str(ex) != modname: - args = '%r (%s)' % (modname, ex) - else: - args = repr(modname) - self.add_message("F0401", args=args, node=importnode) - - def _check_relative_import(self, modnode, importnode, importedmodnode, - importedasname): - """check relative import. node is either an Import or From node, modname - the imported module name. - """ - if 'W0403' not in self.active_msgs: - return - if importedmodnode.file is None: - return False # built-in module - if modnode is importedmodnode: - return False # module importing itself - if modnode.absolute_import_activated() or getattr(importnode, 'level', None): - return False - if importedmodnode.name != importedasname: - # this must be a relative import... - self.add_message('W0403', args=(importedasname, importedmodnode.name), - node=importnode) - - def _add_imported_module(self, node, importedmodname): - """notify an imported module, used to analyze dependencies""" - context_name = node.root().name - if context_name == importedmodname: - # module importing itself ! - self.add_message('W0406', node=node) - elif not is_standard_module(importedmodname): - # handle dependencies - importedmodnames = self.stats['dependencies'].setdefault( - importedmodname, set()) - if not context_name in importedmodnames: - importedmodnames.add(context_name) - if is_standard_module( importedmodname, (self.package_dir(),) ): - # update import graph - mgraph = self.import_graph.setdefault(context_name, set()) - if not importedmodname in mgraph: - mgraph.add(importedmodname) - - def _check_deprecated_module(self, node, mod_path): - """check if the module is deprecated""" - for mod_name in self.config.deprecated_modules: - if mod_path == mod_name or mod_path.startswith(mod_name + '.'): - self.add_message('W0402', node=node, args=mod_path) - - def _check_reimport(self, node, name, basename=None, level=None): - """check if the import is necessary (i.e. not already done)""" - if 'W0404' not in self.active_msgs: - return - frame = node.frame() - root = node.root() - contexts = [(frame, level)] - if root is not frame: - contexts.append((root, None)) - for context, level in contexts: - first = get_first_import(node, context, name, basename, level) - if first is not None: - self.add_message('W0404', node=node, - args=(name, first.fromlineno)) - - - def report_external_dependencies(self, sect, _, dummy): - """return a verbatim layout for displaying dependencies""" - dep_info = make_tree_defs(self._external_dependencies_info().iteritems()) - if not dep_info: - raise EmptyReport() - tree_str = repr_tree_defs(dep_info) - sect.append(VerbatimText(tree_str)) - - def report_dependencies_graph(self, sect, _, dummy): - """write dependencies as a dot (graphviz) file""" - dep_info = self.stats['dependencies'] - if not dep_info or not (self.config.import_graph - or self.config.ext_import_graph - or self.config.int_import_graph): - raise EmptyReport() - filename = self.config.import_graph - if filename: - make_graph(filename, dep_info, sect, '') - filename = self.config.ext_import_graph - if filename: - make_graph(filename, self._external_dependencies_info(), - sect, 'external ') - filename = self.config.int_import_graph - if filename: - make_graph(filename, self._internal_dependencies_info(), - sect, 'internal ') - - def _external_dependencies_info(self): - """return cached external dependencies information or build and - cache them - """ - if self.__ext_dep_info is None: - self.__ext_dep_info = filter_dependencies_info( - self.stats['dependencies'], self.package_dir(), 'external') - return self.__ext_dep_info - - def _internal_dependencies_info(self): - """return cached internal dependencies information or build and - cache them - """ - if self.__int_dep_info is None: - self.__int_dep_info = filter_dependencies_info( - self.stats['dependencies'], self.package_dir(), 'internal') - return self.__int_dep_info - - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(ImportsChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/logging.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/logging.py @@ -1,179 +0,0 @@ -# Copyright (c) 2009-2010 Google, Inc. -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""checker for use of Python logging -""" - -from ..logilab import astng -from .. import checkers -from .. import interfaces -from ..checkers import utils - - -MSGS = { - 'W1201': ('Specify string format arguments as logging function parameters', - 'logging-not-lazy', - 'Used when a logging statement has a call form of ' - '"logging.<logging method>(format_string % (format_args...))". ' - 'Such calls should leave string interpolation to the logging ' - 'method itself and be written ' - '"logging.<logging method>(format_string, format_args...)" ' - 'so that the program may avoid incurring the cost of the ' - 'interpolation in those cases in which no message will be ' - 'logged. For more, see ' - 'http://www.python.org/dev/peps/pep-0282/.'), - 'E1200': ('Unsupported logging format character %r (%#02x) at index %d', - 'logging-unsupported-format', - 'Used when an unsupported format character is used in a logging\ - statement format string.'), - 'E1201': ('Logging format string ends in middle of conversion specifier', - 'logging-format-truncated', - 'Used when a logging statement format string terminates before\ - the end of a conversion specifier.'), - 'E1205': ('Too many arguments for logging format string', - 'logging-too-many-args', - 'Used when a logging format string is given too few arguments.'), - 'E1206': ('Not enough arguments for logging format string', - 'logging-too-few-args', - 'Used when a logging format string is given too many arguments'), - } - - -CHECKED_CONVENIENCE_FUNCTIONS = set([ - 'critical', 'debug', 'error', 'exception', 'fatal', 'info', 'warn', - 'warning']) - - -class LoggingChecker(checkers.BaseChecker): - """Checks use of the logging module.""" - - __implements__ = interfaces.IASTNGChecker - name = 'logging' - msgs = MSGS - - def visit_module(self, unused_node): - """Clears any state left in this checker from last module checked.""" - # The code being checked can just as easily "import logging as foo", - # so it is necessary to process the imports and store in this field - # what name the logging module is actually given. - self._logging_name = None - - def visit_import(self, node): - """Checks to see if this module uses Python's built-in logging.""" - for module, as_name in node.names: - if module == 'logging': - if as_name: - self._logging_name = as_name - else: - self._logging_name = 'logging' - - def visit_callfunc(self, node): - """Checks calls to (simple forms of) logging methods.""" - if (not isinstance(node.func, astng.Getattr) - or not isinstance(node.func.expr, astng.Name)): - return - try: - logger_class = [inferred for inferred in node.func.expr.infer() if ( - isinstance(inferred, astng.Instance) - and [ancestor for ancestor in inferred._proxied.ancestors() if ( - ancestor.name == 'Logger' - and ancestor.parent.name == 'logging')])] - except astng.exceptions.InferenceError: - return - if (node.func.expr.name != self._logging_name and not logger_class): - return - self._check_convenience_methods(node) - self._check_log_methods(node) - - def _check_convenience_methods(self, node): - """Checks calls to logging convenience methods (like logging.warn).""" - if node.func.attrname not in CHECKED_CONVENIENCE_FUNCTIONS: - return - if node.starargs or node.kwargs or not node.args: - # Either no args, star args, or double-star args. Beyond the - # scope of this checker. - return - if isinstance(node.args[0], astng.BinOp) and node.args[0].op == '%': - self.add_message('W1201', node=node) - elif isinstance(node.args[0], astng.Const): - self._check_format_string(node, 0) - - def _check_log_methods(self, node): - """Checks calls to logging.log(level, format, *format_args).""" - if node.func.attrname != 'log': - return - if node.starargs or node.kwargs or len(node.args) < 2: - # Either a malformed call, star args, or double-star args. Beyond - # the scope of this checker. - return - if isinstance(node.args[1], astng.BinOp) and node.args[1].op == '%': - self.add_message('W1201', node=node) - elif isinstance(node.args[1], astng.Const): - self._check_format_string(node, 1) - - def _check_format_string(self, node, format_arg): - """Checks that format string tokens match the supplied arguments. - - Args: - node: AST node to be checked. - format_arg: Index of the format string in the node arguments. - """ - num_args = self._count_supplied_tokens(node.args[format_arg + 1:]) - if not num_args: - # If no args were supplied, then all format strings are valid - - # don't check any further. - return - format_string = node.args[format_arg].value - if not isinstance(format_string, basestring): - # If the log format is constant non-string (e.g. logging.debug(5)), - # ensure there are no arguments. - required_num_args = 0 - else: - try: - keyword_args, required_num_args = \ - utils.parse_format_string(format_string) - if keyword_args: - # Keyword checking on logging strings is complicated by - # special keywords - out of scope. - return - except utils.UnsupportedFormatCharacter, e: - c = format_string[e.index] - self.add_message('E1200', node=node, args=(c, ord(c), e.index)) - return - except utils.IncompleteFormatString: - self.add_message('E1201', node=node) - return - if num_args > required_num_args: - self.add_message('E1205', node=node) - elif num_args < required_num_args: - self.add_message('E1206', node=node) - - def _count_supplied_tokens(self, args): - """Counts the number of tokens in an args list. - - The Python log functions allow for special keyword arguments: func, - exc_info and extra. To handle these cases correctly, we only count - arguments that aren't keywords. - - Args: - args: List of AST nodes that are arguments for a log format string. - - Returns: - Number of AST nodes that aren't keywords. - """ - return sum(1 for arg in args if not isinstance(arg, astng.Keyword)) - - -def register(linter): - """Required method to auto-register this checker.""" - linter.register_checker(LoggingChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/misc.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/misc.py @@ -1,78 +0,0 @@ -# pylint: disable=W0511 -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -""" Copyright (c) 2000-2010 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ -- mailto:contact@logilab.fr - -Check source code is ascii only or has an encoding declaration (PEP 263) -""" - -import re - -from ..interfaces import IRawChecker -from ..checkers import BaseChecker - - -MSGS = { - 'W0511': ('%s', - 'fixme', - 'Used when a warning note as FIXME or XXX is detected.'), - } - -class EncodingChecker(BaseChecker): - """checks for: - * warning notes in the code like FIXME, XXX - * PEP 263: source code with non ascii character but no encoding declaration - """ - __implements__ = IRawChecker - - # configuration section name - name = 'miscellaneous' - msgs = MSGS - - options = (('notes', - {'type' : 'csv', 'metavar' : '<comma separated values>', - 'default' : ('FIXME', 'XXX', 'TODO'), - 'help' : 'List of note tags to take in consideration, \ -separated by a comma.' - }), - ) - - def __init__(self, linter=None): - BaseChecker.__init__(self, linter) - - def process_module(self, node): - """inspect the source file to found encoding problem or fixmes like - notes - """ - stream = node.file_stream - stream.seek(0) # XXX may be removed with astng > 0.23 - # warning notes in the code - notes = [] - for note in self.config.notes: - notes.append(re.compile(note)) - linenum = 1 - for line in stream.readlines(): - for note in notes: - match = note.search(line) - if match: - self.add_message('W0511', args=line[match.start():-1], - line=linenum) - break - linenum += 1 - - - -def register(linter): - """required method to auto register this checker""" - linter.register_checker(EncodingChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/newstyle.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/newstyle.py @@ -1,112 +0,0 @@ -# Copyright (c) 2005-2006 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""check for new / old style related problems -""" - -from ..logilab import astng - -from ..interfaces import IASTNGChecker -from ..checkers import BaseChecker -from ..checkers.utils import check_messages - -MSGS = { - 'E1001': ('Use of __slots__ on an old style class', - 'slots-on-old-class', - 'Used when an old style class uses the __slots__ attribute.'), - 'E1002': ('Use of super on an old style class', - 'super-on-old-class', - 'Used when an old style class uses the super builtin.'), - 'E1003': ('Bad first argument %r given to super class', - 'bad-super-call', - 'Used when another argument than the current class is given as \ - first argument of the super builtin.'), - 'W1001': ('Use of "property" on an old style class', - 'property-on-old-class', - 'Used when PyLint detect the use of the builtin "property" \ - on an old style class while this is relying on new style \ - classes features'), - } - - -class NewStyleConflictChecker(BaseChecker): - """checks for usage of new style capabilities on old style classes and - other new/old styles conflicts problems - * use of property, __slots__, super - * "super" usage - """ - - __implements__ = (IASTNGChecker,) - - # configuration section name - name = 'newstyle' - # messages - msgs = MSGS - priority = -2 - # configuration options - options = () - - @check_messages('E1001') - def visit_class(self, node): - """check __slots__ usage - """ - if '__slots__' in node and not node.newstyle: - self.add_message('E1001', node=node) - - @check_messages('W1001') - def visit_callfunc(self, node): - """check property usage""" - parent = node.parent.frame() - if (isinstance(parent, astng.Class) and - not parent.newstyle and - isinstance(node.func, astng.Name)): - name = node.func.name - if name == 'property': - self.add_message('W1001', node=node) - - @check_messages('E1002', 'E1003') - def visit_function(self, node): - """check use of super""" - # ignore actual functions or method within a new style class - if not node.is_method(): - return - klass = node.parent.frame() - for stmt in node.nodes_of_class(astng.CallFunc): - expr = stmt.func - if not isinstance(expr, astng.Getattr): - continue - call = expr.expr - # skip the test if using super - if isinstance(call, astng.CallFunc) and \ - isinstance(call.func, astng.Name) and \ - call.func.name == 'super': - if not klass.newstyle: - # super should not be used on an old style class - self.add_message('E1002', node=node) - else: - # super first arg should be the class - try: - supcls = (call.args and call.args[0].infer().next() - or None) - except astng.InferenceError: - continue - if klass is not supcls: - supcls = getattr(supcls, 'name', supcls) - self.add_message('E1003', node=node, args=supcls) - - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(NewStyleConflictChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/raw_metrics.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/raw_metrics.py @@ -1,125 +0,0 @@ -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -""" Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ -- mailto:contact@logilab.fr - -Raw metrics checker -""" - -import tokenize - -# pylint now requires pylint >= 2.2, so this is no longer necessary -#if not hasattr(tokenize, 'NL'): -# raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") - -from ..logilab.common.ureports import Table - -from ..interfaces import IRawChecker -from ..checkers import BaseRawChecker, EmptyReport -from ..reporters import diff_string - -def report_raw_stats(sect, stats, old_stats): - """calculate percentage of code / doc / comment / empty - """ - total_lines = stats['total_lines'] - if not total_lines: - raise EmptyReport() - sect.description = '%s lines have been analyzed' % total_lines - lines = ('type', 'number', '%', 'previous', 'difference') - for node_type in ('code', 'docstring', 'comment', 'empty'): - key = node_type + '_lines' - total = stats[key] - percent = float(total * 100) / total_lines - old = old_stats.get(key, None) - if old is not None: - diff_str = diff_string(old, total) - else: - old, diff_str = 'NC', 'NC' - lines += (node_type, str(total), '%.2f' % percent, - str(old), diff_str) - sect.append(Table(children=lines, cols=5, rheaders=1)) - - -class RawMetricsChecker(BaseRawChecker): - """does not check anything but gives some raw metrics : - * total number of lines - * total number of code lines - * total number of docstring lines - * total number of comments lines - * total number of empty lines - """ - - __implements__ = (IRawChecker,) - - # configuration section name - name = 'metrics' - # configuration options - options = ( ) - # messages - msgs = {} - # reports - reports = ( ('RP0701', 'Raw metrics', report_raw_stats), ) - - def __init__(self, linter): - BaseRawChecker.__init__(self, linter) - self.stats = None - - def open(self): - """init statistics""" - self.stats = self.linter.add_stats(total_lines=0, code_lines=0, - empty_lines=0, docstring_lines=0, - comment_lines=0) - - def process_tokens(self, tokens): - """update stats""" - i = 0 - tokens = list(tokens) - while i < len(tokens): - i, lines_number, line_type = get_type(tokens, i) - self.stats['total_lines'] += lines_number - self.stats[line_type] += lines_number - - -JUNK = (tokenize.NL, tokenize.INDENT, tokenize.NEWLINE, tokenize.ENDMARKER) - -def get_type(tokens, start_index): - """return the line type : docstring, comment, code, empty""" - i = start_index - tok_type = tokens[i][0] - start = tokens[i][2] - pos = start - line_type = None - while i < len(tokens) and tokens[i][2][0] == start[0]: - tok_type = tokens[i][0] - pos = tokens[i][3] - if line_type is None: - if tok_type == tokenize.STRING: - line_type = 'docstring_lines' - elif tok_type == tokenize.COMMENT: - line_type = 'comment_lines' - elif tok_type in JUNK: - pass - else: - line_type = 'code_lines' - i += 1 - if line_type is None: - line_type = 'empty_lines' - elif i < len(tokens) and tok_type == tokenize.NEWLINE: - i += 1 - return i, pos[0] - start[0] + 1, line_type - - -def register(linter): - """ required method to auto register this checker """ - linter.register_checker(RawMetricsChecker(linter)) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/similar.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/similar.py @@ -1,357 +0,0 @@ -# pylint: disable=W0622 -# Copyright (c) 2004-2012 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""a similarities / code duplication command line tool and pylint checker -""" -import sys -from itertools import izip - -from ..logilab.common.ureports import Table - -from ..interfaces import IRawChecker -from ..checkers import BaseChecker, table_lines_from_stats - - -class Similar: - """finds copy-pasted lines of code in a project""" - - def __init__(self, min_lines=4, ignore_comments=False, - ignore_docstrings=False, ignore_imports=False): - self.min_lines = min_lines - self.ignore_comments = ignore_comments - self.ignore_docstrings = ignore_docstrings - self.ignore_imports = ignore_imports - self.linesets = [] - - def append_stream(self, streamid, stream): - """append a file to search for similarities""" - stream.seek(0) # XXX may be removed with astng > 0.23 - self.linesets.append(LineSet(streamid, - stream.readlines(), - self.ignore_comments, - self.ignore_docstrings, - self.ignore_imports)) - - def run(self): - """start looking for similarities and display results on stdout""" - self._display_sims(self._compute_sims()) - - def _compute_sims(self): - """compute similarities in appended files""" - no_duplicates = {} - for num, lineset1, idx1, lineset2, idx2 in self._iter_sims(): - duplicate = no_duplicates.setdefault(num, []) - for couples in duplicate: - if (lineset1, idx1) in couples or (lineset2, idx2) in couples: - couples.add( (lineset1, idx1) ) - couples.add( (lineset2, idx2) ) - break - else: - duplicate.append( set([(lineset1, idx1), (lineset2, idx2)]) ) - sims = [] - for num, ensembles in no_duplicates.iteritems(): - for couples in ensembles: - sims.append( (num, couples) ) - sims.sort() - sims.reverse() - return sims - - def _display_sims(self, sims): - """display computed similarities on stdout""" - nb_lignes_dupliquees = 0 - for num, couples in sims: - print - print num, "similar lines in", len(couples), "files" - couples = sorted(couples) - for lineset, idx in couples: - print "==%s:%s" % (lineset.name, idx) - # pylint: disable=W0631 - for line in lineset._real_lines[idx:idx+num]: - print " ", line, - nb_lignes_dupliquees += num * (len(couples)-1) - nb_total_lignes = sum([len(lineset) for lineset in self.linesets]) - print "TOTAL lines=%s duplicates=%s percent=%.2f" \ - % (nb_total_lignes, nb_lignes_dupliquees, - nb_lignes_dupliquees*100. / nb_total_lignes) - - def _find_common(self, lineset1, lineset2): - """find similarities in the two given linesets""" - lines1 = lineset1.enumerate_stripped - lines2 = lineset2.enumerate_stripped - find = lineset2.find - index1 = 0 - min_lines = self.min_lines - while index1 < len(lineset1): - skip = 1 - num = 0 - for index2 in find( lineset1[index1] ): - non_blank = 0 - for num, ((_, line1), (_, line2)) in enumerate( - izip(lines1(index1), lines2(index2))): - if line1 != line2: - if non_blank > min_lines: - yield num, lineset1, index1, lineset2, index2 - skip = max(skip, num) - break - if line1: - non_blank += 1 - else: - # we may have reach the end - num += 1 - if non_blank > min_lines: - yield num, lineset1, index1, lineset2, index2 - skip = max(skip, num) - index1 += skip - - def _iter_sims(self): - """iterate on similarities among all files, by making a cartesian - product - """ - for idx, lineset in enumerate(self.linesets[:-1]): - for lineset2 in self.linesets[idx+1:]: - for sim in self._find_common(lineset, lineset2): - yield sim - -def stripped_lines(lines, ignore_comments, ignore_docstrings, ignore_imports): - """return lines with leading/trailing whitespace and any ignored code - features removed - """ - - strippedlines = [] - docstring = None - for line in lines: - line = line.strip() - if ignore_docstrings: - if not docstring and \ - (line.startswith('"""') or line.startswith("'''")): - docstring = line[:3] - line = line[3:] - if docstring: - if line.endswith(docstring): - docstring = None - line = '' - if ignore_imports: - if line.startswith("import ") or line.startswith("from "): - line = '' - if ignore_comments: - # XXX should use regex in checkers/format to avoid cutting - # at a "#" in a string - line = line.split('#', 1)[0].strip() - strippedlines.append(line) - return strippedlines - -class LineSet: - """Holds and indexes all the lines of a single source file""" - def __init__(self, name, lines, ignore_comments=False, - ignore_docstrings=False, ignore_imports=False): - self.name = name - self._real_lines = lines - self._stripped_lines = stripped_lines(lines, ignore_comments, - ignore_docstrings, - ignore_imports) - self._index = self._mk_index() - - def __str__(self): - return '<Lineset for %s>' % self.name - - def __len__(self): - return len(self._real_lines) - - def __getitem__(self, index): - return self._stripped_lines[index] - - def __lt__(self, other): - return self.name < other.name - - def __hash__(self): - return id(self) - - def enumerate_stripped(self, start_at=0): - """return an iterator on stripped lines, starting from a given index - if specified, else 0 - """ - idx = start_at - if start_at: - lines = self._stripped_lines[start_at:] - else: - lines = self._stripped_lines - for line in lines: - #if line: - yield idx, line - idx += 1 - - def find(self, stripped_line): - """return positions of the given stripped line in this set""" - return self._index.get(stripped_line, ()) - - def _mk_index(self): - """create the index for this set""" - index = {} - for line_no, line in enumerate(self._stripped_lines): - if line: - index.setdefault(line, []).append( line_no ) - return index - - -MSGS = {'R0801': ('Similar lines in %s files\n%s', - 'duplicate-code', - 'Indicates that a set of similar lines has been detected \ - among multiple file. This usually means that the code should \ - be refactored to avoid this duplication.')} - -def report_similarities(sect, stats, old_stats): - """make a layout with some stats about duplication""" - lines = ['', 'now', 'previous', 'difference'] - lines += table_lines_from_stats(stats, old_stats, - ('nb_duplicated_lines', - 'percent_duplicated_lines')) - sect.append(Table(children=lines, cols=4, rheaders=1, cheaders=1)) - - -# wrapper to get a pylint checker from the similar class -class SimilarChecker(BaseChecker, Similar): - """checks for similarities and duplicated code. This computation may be - memory / CPU intensive, so you should disable it if you experiment some - problems. - """ - - __implements__ = (IRawChecker,) - # configuration section name - name = 'similarities' - # messages - msgs = MSGS - # configuration options - # for available dict keys/values see the optik parser 'add_option' method - options = (('min-similarity-lines', - {'default' : 4, 'type' : "int", 'metavar' : '<int>', - 'help' : 'Minimum lines number of a similarity.'}), - ('ignore-comments', - {'default' : True, 'type' : 'yn', 'metavar' : '<y or n>', - 'help': 'Ignore comments when computing similarities.'} - ), - ('ignore-docstrings', - {'default' : True, 'type' : 'yn', 'metavar' : '<y or n>', - 'help': 'Ignore docstrings when computing similarities.'} - ), - ('ignore-imports', - {'default' : False, 'type' : 'yn', 'metavar' : '<y or n>', - 'help': 'Ignore imports when computing similarities.'} - ), - ) - # reports - reports = ( ('RP0801', 'Duplication', report_similarities), ) - - def __init__(self, linter=None): - BaseChecker.__init__(self, linter) - Similar.__init__(self, min_lines=4, - ignore_comments=True, ignore_docstrings=True) - self.stats = None - - def set_option(self, optname, value, action=None, optdict=None): - """method called to set an option (registered in the options list) - - overridden to report options setting to Similar - """ - BaseChecker.set_option(self, optname, value, action, optdict) - if optname == 'min-similarity-lines': - self.min_lines = self.config.min_similarity_lines - elif optname == 'ignore-comments': - self.ignore_comments = self.config.ignore_comments - elif optname == 'ignore-docstrings': - self.ignore_docstrings = self.config.ignore_docstrings - elif optname == 'ignore-imports': - self.ignore_imports = self.config.ignore_imports - - def open(self): - """init the checkers: reset linesets and statistics information""" - self.linesets = [] - self.stats = self.linter.add_stats(nb_duplicated_lines=0, - percent_duplicated_lines=0) - - def process_module(self, node): - """process a module - - the module's content is accessible via the stream object - - stream must implement the readlines method - """ - self.append_stream(self.linter.current_name, node.file_stream) - - def close(self): - """compute and display similarities on closing (i.e. end of parsing)""" - total = sum([len(lineset) for lineset in self.linesets]) - duplicated = 0 - stats = self.stats - for num, couples in self._compute_sims(): - msg = [] - for lineset, idx in couples: - msg.append("==%s:%s" % (lineset.name, idx)) - msg.sort() - # pylint: disable=W0631 - for line in lineset._real_lines[idx:idx+num]: - msg.append(line.rstrip()) - self.add_message('R0801', args=(len(couples), '\n'.join(msg))) - duplicated += num * (len(couples) - 1) - stats['nb_duplicated_lines'] = duplicated - stats['percent_duplicated_lines'] = total and duplicated * 100. / total - - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(SimilarChecker(linter)) - -def usage(status=0): - """display command line usage information""" - print "finds copy pasted blocks in a set of files" - print - print 'Usage: symilar [-d|--duplicates min_duplicated_lines] \ -[-i|--ignore-comments] [--ignore-docstrings] [--ignore-imports] file1...' - sys.exit(status) - -def Run(argv=None): - """standalone command line access point""" - if argv is None: - argv = sys.argv[1:] - from getopt import getopt - s_opts = 'hdi' - l_opts = ('help', 'duplicates=', 'ignore-comments', 'ignore-imports', - 'ignore-docstrings') - min_lines = 4 - ignore_comments = False - ignore_docstrings = False - ignore_imports = False - opts, args = getopt(argv, s_opts, l_opts) - for opt, val in opts: - if opt in ('-d', '--duplicates'): - min_lines = int(val) - elif opt in ('-h', '--help'): - usage() - elif opt in ('-i', '--ignore-comments'): - ignore_comments = True - elif opt in ('--ignore-docstrings'): - ignore_docstrings = True - elif opt in ('--ignore-imports'): - ignore_imports = True - if not args: - usage(1) - sim = Similar(min_lines, ignore_comments, ignore_docstrings, ignore_imports) - for filename in args: - sim.append_stream(filename, open(filename)) - sim.run() - sys.exit(0) - -if __name__ == '__main__': - Run() diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/string_format.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/string_format.py @@ -1,163 +0,0 @@ -# Copyright (c) 2009-2010 Arista Networks, Inc. - James Lingard -# Copyright (c) 2004-2010 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Checker for string formatting operations. -""" - -from ..logilab import astng -from ..interfaces import IASTNGChecker -from ..checkers import BaseChecker -from ..checkers import utils - - -MSGS = { - 'E1300': ("Unsupported format character %r (%#02x) at index %d", - "bad-format-character", - "Used when a unsupported format character is used in a format\ - string."), - 'E1301': ("Format string ends in middle of conversion specifier", - "truncated-format-string", - "Used when a format string terminates before the end of a \ - conversion specifier."), - 'E1302': ("Mixing named and unnamed conversion specifiers in format string", - "mixed-format-string", - "Used when a format string contains both named (e.g. '%(foo)d') \ - and unnamed (e.g. '%d') conversion specifiers. This is also \ - used when a named conversion specifier contains * for the \ - minimum field width and/or precision."), - 'E1303': ("Expected mapping for format string, not %s", - "format-needs-mapping", - "Used when a format string that uses named conversion specifiers \ - is used with an argument that is not a mapping."), - 'W1300': ("Format string dictionary key should be a string, not %s", - "bad-format-string-key", - "Used when a format string that uses named conversion specifiers \ - is used with a dictionary whose keys are not all strings."), - 'W1301': ("Unused key %r in format string dictionary", - "unused-format-string-key", - "Used when a format string that uses named conversion specifiers \ - is used with a dictionary that conWtains keys not required by the \ - format string."), - 'E1304': ("Missing key %r in format string dictionary", - "missing-format-string-key", - "Used when a format string that uses named conversion specifiers \ - is used with a dictionary that doesn't contain all the keys \ - required by the format string."), - 'E1305': ("Too many arguments for format string", - "too-many-format-args", - "Used when a format string that uses unnamed conversion \ - specifiers is given too few arguments."), - 'E1306': ("Not enough arguments for format string", - "too-few-format-args", - "Used when a format string that uses unnamed conversion \ - specifiers is given too many arguments"), - } - -OTHER_NODES = (astng.Const, astng.List, astng.Backquote, - astng.Lambda, astng.Function, - astng.ListComp, astng.SetComp, astng.GenExpr) - -class StringFormatChecker(BaseChecker): - """Checks string formatting operations to ensure that the format string - is valid and the arguments match the format string. - """ - - __implements__ = (IASTNGChecker,) - name = 'string_format' - msgs = MSGS - - def visit_binop(self, node): - if node.op != '%': - return - left = node.left - args = node.right - - if not (isinstance(left, astng.Const) - and isinstance(left.value, basestring)): - return - format_string = left.value - try: - required_keys, required_num_args = \ - utils.parse_format_string(format_string) - except utils.UnsupportedFormatCharacter, e: - c = format_string[e.index] - self.add_message('E1300', node=node, args=(c, ord(c), e.index)) - return - except utils.IncompleteFormatString: - self.add_message('E1301', node=node) - return - if required_keys and required_num_args: - # The format string uses both named and unnamed format - # specifiers. - self.add_message('E1302', node=node) - elif required_keys: - # The format string uses only named format specifiers. - # Check that the RHS of the % operator is a mapping object - # that contains precisely the set of keys required by the - # format string. - if isinstance(args, astng.Dict): - keys = set() - unknown_keys = False - for k, _ in args.items: - if isinstance(k, astng.Const): - key = k.value - if isinstance(key, basestring): - keys.add(key) - else: - self.add_message('W1300', node=node, args=key) - else: - # One of the keys was something other than a - # constant. Since we can't tell what it is, - # supress checks for missing keys in the - # dictionary. - unknown_keys = True - if not unknown_keys: - for key in required_keys: - if key not in keys: - self.add_message('E1304', node=node, args=key) - for key in keys: - if key not in required_keys: - self.add_message('W1301', node=node, args=key) - elif isinstance(args, OTHER_NODES + (astng.Tuple,)): - type_name = type(args).__name__ - self.add_message('E1303', node=node, args=type_name) - # else: - # The RHS of the format specifier is a name or - # expression. It may be a mapping object, so - # there's nothing we can check. - else: - # The format string uses only unnamed format specifiers. - # Check that the number of arguments passed to the RHS of - # the % operator matches the number required by the format - # string. - if isinstance(args, astng.Tuple): - num_args = len(args.elts) - elif isinstance(args, OTHER_NODES + (astng.Dict, astng.DictComp)): - num_args = 1 - else: - # The RHS of the format specifier is a name or - # expression. It could be a tuple of unknown size, so - # there's nothing we can check. - num_args = None - if num_args is not None: - if num_args > required_num_args: - self.add_message('E1305', node=node) - elif num_args < required_num_args: - self.add_message('E1306', node=node) - - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(StringFormatChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/typecheck.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/typecheck.py @@ -1,387 +0,0 @@ -# Copyright (c) 2006-2010 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""try to find more bugs in the code using astng inference capabilities -""" - -import re -import shlex - -from ..logilab import astng -from ..logilab.astng import InferenceError, NotFoundError, YES, Instance - -from ..interfaces import IASTNGChecker -from ..checkers import BaseChecker -from ..checkers.utils import safe_infer, is_super, check_messages - -MSGS = { - 'E1101': ('%s %r has no %r member', - 'no-member', - 'Used when a variable is accessed for an unexistent member.'), - 'E1102': ('%s is not callable', - 'not-callable', - 'Used when an object being called has been inferred to a non \ - callable object'), - 'E1103': ('%s %r has no %r member (but some types could not be inferred)', - 'maybe-no-member', - 'Used when a variable is accessed for an unexistent member, but \ - astng was not able to interpret all possible types of this \ - variable.'), - 'E1111': ('Assigning to function call which doesn\'t return', - 'assignment-from-no-return', - 'Used when an assignment is done on a function call but the \ - inferred function doesn\'t return anything.'), - 'W1111': ('Assigning to function call which only returns None', - 'assignment-from-none', - 'Used when an assignment is done on a function call but the \ - inferred function returns nothing but None.'), - - 'E1120': ('No value passed for parameter %s in function call', - 'no-value-for-parameter', - 'Used when a function call passes too few arguments.'), - 'E1121': ('Too many positional arguments for function call', - 'too-many-function-args', - 'Used when a function call passes too many positional \ - arguments.'), - 'E1122': ('Duplicate keyword argument %r in function call', - 'duplicate-keyword-arg', - 'Used when a function call passes the same keyword argument \ - multiple times.'), - 'E1123': ('Passing unexpected keyword argument %r in function call', - 'unexpected-keyword-arg', - 'Used when a function call passes a keyword argument that \ - doesn\'t correspond to one of the function\'s parameter names.'), - 'E1124': ('Multiple values passed for parameter %r in function call', - 'redundant-keyword-arg', - 'Used when a function call would result in assigning multiple \ - values to a function parameter, one value from a positional \ - argument and one from a keyword argument.'), - } - -class TypeChecker(BaseChecker): - """try to find bugs in the code using type inference - """ - - __implements__ = (IASTNGChecker,) - - # configuration section name - name = 'typecheck' - # messages - msgs = MSGS - priority = -1 - # configuration options - options = (('ignore-mixin-members', - {'default' : True, 'type' : 'yn', 'metavar': '<y_or_n>', - 'help' : 'Tells whether missing members accessed in mixin \ -class should be ignored. A mixin class is detected if its name ends with \ -"mixin" (case insensitive).'} - ), - - ('ignored-classes', - {'default' : ('SQLObject',), - 'type' : 'csv', - 'metavar' : '<members names>', - 'help' : 'List of classes names for which member attributes \ -should not be checked (useful for classes with attributes dynamically set).'} - ), - - ('zope', - {'default' : False, 'type' : 'yn', 'metavar': '<y_or_n>', - 'help' : 'When zope mode is activated, add a predefined set \ -of Zope acquired attributes to generated-members.'} - ), - ('generated-members', - {'default' : ( - 'REQUEST', 'acl_users', 'aq_parent'), - 'type' : 'string', - 'metavar' : '<members names>', - 'help' : 'List of members which are set dynamically and \ -missed by pylint inference system, and so shouldn\'t trigger E0201 when \ -accessed. Python regular expressions are accepted.'} - ), - ) - - def open(self): - # do this in open since config not fully initialized in __init__ - self.generated_members = list(self.config.generated_members) - if self.config.zope: - self.generated_members.extend(('REQUEST', 'acl_users', 'aq_parent')) - - def visit_assattr(self, node): - if isinstance(node.ass_type(), astng.AugAssign): - self.visit_getattr(node) - - def visit_delattr(self, node): - self.visit_getattr(node) - - @check_messages('E1101', 'E1103') - def visit_getattr(self, node): - """check that the accessed attribute exists - - to avoid to much false positives for now, we'll consider the code as - correct if a single of the inferred nodes has the accessed attribute. - - function/method, super call and metaclasses are ignored - """ - # generated_members may containt regular expressions - # (surrounded by quote `"` and followed by a comma `,`) - # REQUEST,aq_parent,"[a-zA-Z]+_set{1,2}"' => - # ('REQUEST', 'aq_parent', '[a-zA-Z]+_set{1,2}') - if isinstance(self.config.generated_members, str): - gen = shlex.shlex(self.config.generated_members) - gen.whitespace += ',' - gen.wordchars += '[]-+' - self.config.generated_members = tuple(tok.strip('"') for tok in gen) - for pattern in self.config.generated_members: - # attribute is marked as generated, stop here - if re.match(pattern, node.attrname): - return - try: - infered = list(node.expr.infer()) - except InferenceError: - return - # list of (node, nodename) which are missing the attribute - missingattr = set() - ignoremim = self.config.ignore_mixin_members - inference_failure = False - for owner in infered: - # skip yes object - if owner is YES: - inference_failure = True - continue - # skip None anyway - if isinstance(owner, astng.Const) and owner.value is None: - continue - # XXX "super" / metaclass call - if is_super(owner) or getattr(owner, 'type', None) == 'metaclass': - continue - name = getattr(owner, 'name', 'None') - if name in self.config.ignored_classes: - continue - if ignoremim and name[-5:].lower() == 'mixin': - continue - try: - if not [n for n in owner.getattr(node.attrname) - if not isinstance(n.statement(), astng.AugAssign)]: - missingattr.add((owner, name)) - continue - except AttributeError: - # XXX method / function - continue - except NotFoundError: - if isinstance(owner, astng.Function) and owner.decorators: - continue - if isinstance(owner, Instance) and owner.has_dynamic_getattr(): - continue - # explicit skipping of optparse'Values class - if owner.name == 'Values' and owner.root().name == 'optparse': - continue - missingattr.add((owner, name)) - continue - # stop on the first found - break - else: - # we have not found any node with the attributes, display the - # message for infered nodes - done = set() - for owner, name in missingattr: - if isinstance(owner, Instance): - actual = owner._proxied - else: - actual = owner - if actual in done: - continue - done.add(actual) - if inference_failure: - msgid = 'E1103' - else: - msgid = 'E1101' - self.add_message(msgid, node=node, - args=(owner.display_type(), name, - node.attrname)) - - - def visit_assign(self, node): - """check that if assigning to a function call, the function is - possibly returning something valuable - """ - if not isinstance(node.value, astng.CallFunc): - return - function_node = safe_infer(node.value.func) - # skip class, generator and incomplete function definition - if not (isinstance(function_node, astng.Function) and - function_node.root().fully_defined()): - return - if function_node.is_generator() \ - or function_node.is_abstract(pass_is_abstract=False): - return - returns = list(function_node.nodes_of_class(astng.Return, - skip_klass=astng.Function)) - if len(returns) == 0: - self.add_message('E1111', node=node) - else: - for rnode in returns: - if not (isinstance(rnode.value, astng.Const) - and rnode.value.value is None): - break - else: - self.add_message('W1111', node=node) - - def visit_callfunc(self, node): - """check that called functions/methods are inferred to callable objects, - and that the arguments passed to the function match the parameters in - the inferred function's definition - """ - - # Build the set of keyword arguments, checking for duplicate keywords, - # and count the positional arguments. - keyword_args = set() - num_positional_args = 0 - for arg in node.args: - if isinstance(arg, astng.Keyword): - keyword = arg.arg - if keyword in keyword_args: - self.add_message('E1122', node=node, args=keyword) - keyword_args.add(keyword) - else: - num_positional_args += 1 - - called = safe_infer(node.func) - # only function, generator and object defining __call__ are allowed - if called is not None and not called.callable(): - self.add_message('E1102', node=node, args=node.func.as_string()) - - # Note that BoundMethod is a subclass of UnboundMethod (huh?), so must - # come first in this 'if..else'. - if isinstance(called, astng.BoundMethod): - # Bound methods have an extra implicit 'self' argument. - num_positional_args += 1 - elif isinstance(called, astng.UnboundMethod): - if called.decorators is not None: - for d in called.decorators.nodes: - if isinstance(d, astng.Name) and (d.name == 'classmethod'): - # Class methods have an extra implicit 'cls' argument. - num_positional_args += 1 - break - elif (isinstance(called, astng.Function) or - isinstance(called, astng.Lambda)): - pass - else: - return - - if called.args.args is None: - # Built-in functions have no argument information. - return - - if len( called.argnames() ) != len( set( called.argnames() ) ): - # Duplicate parameter name (see E9801). We can't really make sense - # of the function call in this case, so just return. - return - - # Analyze the list of formal parameters. - num_mandatory_parameters = len(called.args.args) - len(called.args.defaults) - parameters = [] - parameter_name_to_index = {} - for i, arg in enumerate(called.args.args): - if isinstance(arg, astng.Tuple): - name = None - # Don't store any parameter names within the tuple, since those - # are not assignable from keyword arguments. - else: - if isinstance(arg, astng.Keyword): - name = arg.arg - else: - assert isinstance(arg, astng.AssName) - # This occurs with: - # def f( (a), (b) ): pass - name = arg.name - parameter_name_to_index[name] = i - if i >= num_mandatory_parameters: - defval = called.args.defaults[i - num_mandatory_parameters] - else: - defval = None - parameters.append([(name, defval), False]) - - # Match the supplied arguments against the function parameters. - - # 1. Match the positional arguments. - for i in range(num_positional_args): - if i < len(parameters): - parameters[i][1] = True - elif called.args.vararg is not None: - # The remaining positional arguments get assigned to the *args - # parameter. - break - else: - # Too many positional arguments. - self.add_message('E1121', node=node) - break - - # 2. Match the keyword arguments. - for keyword in keyword_args: - if keyword in parameter_name_to_index: - i = parameter_name_to_index[keyword] - if parameters[i][1]: - # Duplicate definition of function parameter. - self.add_message('E1124', node=node, args=keyword) - else: - parameters[i][1] = True - elif called.args.kwarg is not None: - # The keyword argument gets assigned to the **kwargs parameter. - pass - else: - # Unexpected keyword argument. - self.add_message('E1123', node=node, args=keyword) - - # 3. Match the *args, if any. Note that Python actually processes - # *args _before_ any keyword arguments, but we wait until after - # looking at the keyword arguments so as to make a more conservative - # guess at how many values are in the *args sequence. - if node.starargs is not None: - for i in range(num_positional_args, len(parameters)): - [(name, defval), assigned] = parameters[i] - # Assume that *args provides just enough values for all - # non-default parameters after the last parameter assigned by - # the positional arguments but before the first parameter - # assigned by the keyword arguments. This is the best we can - # get without generating any false positives. - if (defval is not None) or assigned: - break - parameters[i][1] = True - - # 4. Match the **kwargs, if any. - if node.kwargs is not None: - for i, [(name, defval), assigned] in enumerate(parameters): - # Assume that *kwargs provides values for all remaining - # unassigned named parameters. - if name is not None: - parameters[i][1] = True - else: - # **kwargs can't assign to tuples. - pass - - # Check that any parameters without a default have been assigned - # values. - for [(name, defval), assigned] in parameters: - if (defval is None) and not assigned: - if name is None: - display_name = '<tuple>' - else: - display_name = repr(name) - self.add_message('E1120', node=node, args=display_name) - -def register(linter): - """required method to auto register this checker """ - linter.register_checker(TypeChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/utils.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/utils.py @@ -1,373 +0,0 @@ -# pylint: disable=W0611 -# -# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""some functions that may be useful for various checkers -""" - -import re -import string -from ..logilab import astng -from ..logilab.astng import scoped_nodes -from ..logilab.common.compat import builtins -BUILTINS_NAME = builtins.__name__ - -COMP_NODE_TYPES = astng.ListComp, astng.SetComp, astng.DictComp, astng.GenExpr - - -def is_inside_except(node): - """Returns true if node is inside the name of an except handler.""" - current = node - while current and not isinstance(current.parent, astng.ExceptHandler): - current = current.parent - - return current and current is current.parent.name - - -def get_all_elements(node): - """Recursively returns all atoms in nested lists and tuples.""" - if isinstance(node, (astng.Tuple, astng.List)): - for child in node.elts: - for e in get_all_elements(child): - yield e - else: - yield node - - -def clobber_in_except(node): - """Checks if an assignment node in an except handler clobbers an existing - variable. - - Returns (True, args for W0623) if assignment clobbers an existing variable, - (False, None) otherwise. - """ - if isinstance(node, astng.AssAttr): - return (True, (node.attrname, 'object %r' % (node.expr.name,))) - elif isinstance(node, astng.AssName): - name = node.name - if is_builtin(name): - return (True, (name, 'builtins')) - else: - scope, stmts = node.lookup(name) - if (stmts and - not isinstance(stmts[0].ass_type(), - (astng.Assign, astng.AugAssign, astng.ExceptHandler))): - return (True, (name, 'outer scope (line %s)' % (stmts[0].fromlineno,))) - return (False, None) - - -def safe_infer(node): - """return the inferred value for the given node. - Return None if inference failed or if there is some ambiguity (more than - one node has been inferred) - """ - try: - inferit = node.infer() - value = inferit.next() - except astng.InferenceError: - return - try: - inferit.next() - return # None if there is ambiguity on the inferred node - except astng.InferenceError: - return # there is some kind of ambiguity - except StopIteration: - return value - -def is_super(node): - """return True if the node is referencing the "super" builtin function - """ - if getattr(node, 'name', None) == 'super' and \ - node.root().name == BUILTINS_NAME: - return True - return False - -def is_error(node): - """return true if the function does nothing but raising an exception""" - for child_node in node.get_children(): - if isinstance(child_node, astng.Raise): - return True - return False - -def is_raising(body): - """return true if the given statement node raise an exception""" - for node in body: - if isinstance(node, astng.Raise): - return True - return False - -def is_empty(body): - """return true if the given node does nothing but 'pass'""" - return len(body) == 1 and isinstance(body[0], astng.Pass) - -builtins = builtins.__dict__.copy() -SPECIAL_BUILTINS = ('__builtins__',) # '__path__', '__file__') - -def is_builtin(name): # was is_native_builtin - """return true if <name> could be considered as a builtin defined by python - """ - if name in builtins: - return True - if name in SPECIAL_BUILTINS: - return True - return False - -def is_defined_before(var_node): - """return True if the variable node is defined by a parent node (list, - set, dict, or generator comprehension, lambda) or in a previous sibling - node on the same line (statement_defining ; statement_using) - """ - varname = var_node.name - _node = var_node.parent - while _node: - if isinstance(_node, COMP_NODE_TYPES): - for ass_node in _node.nodes_of_class(astng.AssName): - if ass_node.name == varname: - return True - elif isinstance(_node, astng.For): - for ass_node in _node.target.nodes_of_class(astng.AssName): - if ass_node.name == varname: - return True - elif isinstance(_node, astng.With): - if _node.vars is None: - # quickfix : case in which 'with' is used without 'as' - return False - if _node.vars.name == varname: - return True - elif isinstance(_node, (astng.Lambda, astng.Function)): - if _node.args.is_argument(varname): - return True - if getattr(_node, 'name', None) == varname: - return True - break - _node = _node.parent - # possibly multiple statements on the same line using semi colon separator - stmt = var_node.statement() - _node = stmt.previous_sibling() - lineno = stmt.fromlineno - while _node and _node.fromlineno == lineno: - for ass_node in _node.nodes_of_class(astng.AssName): - if ass_node.name == varname: - return True - for imp_node in _node.nodes_of_class( (astng.From, astng.Import)): - if varname in [name[1] or name[0] for name in imp_node.names]: - return True - _node = _node.previous_sibling() - return False - -def is_func_default(node): - """return true if the given Name node is used in function default argument's - value - """ - parent = node.scope() - if isinstance(parent, astng.Function): - for default_node in parent.args.defaults: - for default_name_node in default_node.nodes_of_class(astng.Name): - if default_name_node is node: - return True - return False - -def is_func_decorator(node): - """return true if the name is used in function decorator""" - parent = node.parent - while parent is not None: - if isinstance(parent, astng.Decorators): - return True - if (parent.is_statement or - isinstance(parent, astng.Lambda) or - isinstance(parent, (scoped_nodes.ComprehensionScope, - scoped_nodes.ListComp))): - break - parent = parent.parent - return False - -def is_ancestor_name(frame, node): - """return True if `frame` is a astng.Class node with `node` in the - subtree of its bases attribute - """ - try: - bases = frame.bases - except AttributeError: - return False - for base in bases: - if node in base.nodes_of_class(astng.Name): - return True - return False - -def assign_parent(node): - """return the higher parent which is not an AssName, Tuple or List node - """ - while node and isinstance(node, (astng.AssName, - astng.Tuple, - astng.List)): - node = node.parent - return node - -def overrides_an_abstract_method(class_node, name): - """return True if pnode is a parent of node""" - for ancestor in class_node.ancestors(): - if name in ancestor and isinstance(ancestor[name], astng.Function) and \ - ancestor[name].is_abstract(pass_is_abstract=False): - return True - return False - -def overrides_a_method(class_node, name): - """return True if <name> is a method overridden from an ancestor""" - for ancestor in class_node.ancestors(): - if name in ancestor and isinstance(ancestor[name], astng.Function): - return True - return False - -PYMETHODS = set(('__new__', '__init__', '__del__', '__hash__', - '__str__', '__repr__', - '__len__', '__iter__', - '__delete__', '__get__', '__set__', - '__getitem__', '__setitem__', '__delitem__', '__contains__', - '__getattribute__', '__getattr__', '__setattr__', '__delattr__', - '__call__', - '__enter__', '__exit__', - '__cmp__', '__ge__', '__gt__', '__le__', '__lt__', '__eq__', - '__nonzero__', '__neg__', '__invert__', - '__mul__', '__imul__', '__rmul__', - '__div__', '__idiv__', '__rdiv__', - '__add__', '__iadd__', '__radd__', - '__sub__', '__isub__', '__rsub__', - '__pow__', '__ipow__', '__rpow__', - '__mod__', '__imod__', '__rmod__', - '__and__', '__iand__', '__rand__', - '__or__', '__ior__', '__ror__', - '__xor__', '__ixor__', '__rxor__', - # XXX To be continued - )) - -def check_messages(*messages): - """decorator to store messages that are handled by a checker method""" - - def store_messages(func): - func.checks_msgs = messages - return func - return store_messages - -class IncompleteFormatString(Exception): - """A format string ended in the middle of a format specifier.""" - pass - -class UnsupportedFormatCharacter(Exception): - """A format character in a format string is not one of the supported - format characters.""" - def __init__(self, index): - Exception.__init__(self, index) - self.index = index - -def parse_format_string(format_string): - """Parses a format string, returning a tuple of (keys, num_args), where keys - is the set of mapping keys in the format string, and num_args is the number - of arguments required by the format string. Raises - IncompleteFormatString or UnsupportedFormatCharacter if a - parse error occurs.""" - keys = set() - num_args = 0 - def next_char(i): - i += 1 - if i == len(format_string): - raise IncompleteFormatString - return (i, format_string[i]) - i = 0 - while i < len(format_string): - c = format_string[i] - if c == '%': - i, c = next_char(i) - # Parse the mapping key (optional). - key = None - if c == '(': - depth = 1 - i, c = next_char(i) - key_start = i - while depth != 0: - if c == '(': - depth += 1 - elif c == ')': - depth -= 1 - i, c = next_char(i) - key_end = i - 1 - key = format_string[key_start:key_end] - - # Parse the conversion flags (optional). - while c in '#0- +': - i, c = next_char(i) - # Parse the minimum field width (optional). - if c == '*': - num_args += 1 - i, c = next_char(i) - else: - while c in string.digits: - i, c = next_char(i) - # Parse the precision (optional). - if c == '.': - i, c = next_char(i) - if c == '*': - num_args += 1 - i, c = next_char(i) - else: - while c in string.digits: - i, c = next_char(i) - # Parse the length modifier (optional). - if c in 'hlL': - i, c = next_char(i) - # Parse the conversion type (mandatory). - if c not in 'diouxXeEfFgGcrs%': - raise UnsupportedFormatCharacter(i) - if key: - keys.add(key) - elif c != '%': - num_args += 1 - i += 1 - return keys, num_args - -def is_attr_protected(attrname): - """return True if attribute name is protected (start with _ and some other - details), False otherwise. - """ - return attrname[0] == '_' and not attrname == '_' and not ( - attrname.startswith('__') and attrname.endswith('__')) - -def node_frame_class(node): - """return klass node for a method node (or a staticmethod or a - classmethod), return null otherwise - """ - klass = node.frame() - - while klass is not None and not isinstance(klass, astng.Class): - if klass.parent is None: - klass = None - else: - klass = klass.parent.frame() - - return klass - -def is_super_call(expr): - """return True if expression node is a function call and if function name - is super. Check before that you're in a method. - """ - return (isinstance(expr, astng.CallFunc) and - isinstance(expr.func, astng.Name) and - expr.func.name == 'super') -def is_attr_private(attrname): - """Check that attribute name is private (at least two leading underscores, - at most one trailing underscore) - """ - regex = re.compile('^_{2,}.*[^_]+_?$') - return regex.match(attrname) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/variables.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/checkers/variables.py @@ -1,588 +0,0 @@ -# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""variables checkers for Python code -""" - -import sys -from copy import copy - -from ..logilab import astng -from ..logilab.astng import are_exclusive, builtin_lookup, ASTNGBuildingException - -from ..interfaces import IASTNGChecker -from ..checkers import BaseChecker -from ..checkers.utils import (PYMETHODS, is_ancestor_name, is_builtin, - is_defined_before, is_error, is_func_default, is_func_decorator, - assign_parent, check_messages, is_inside_except, clobber_in_except, - get_all_elements) - - -def in_for_else_branch(parent, stmt): - """Returns True if stmt in inside the else branch for a parent For stmt.""" - return (isinstance(parent, astng.For) and - any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse)) - -def overridden_method(klass, name): - """get overridden method if any""" - try: - parent = klass.local_attr_ancestors(name).next() - except (StopIteration, KeyError): - return None - try: - meth_node = parent[name] - except KeyError: - # We have found an ancestor defining <name> but it's not in the local - # dictionary. This may happen with astng built from living objects. - return None - if isinstance(meth_node, astng.Function): - return meth_node - return None - - -MSGS = { - 'E0601': ('Using variable %r before assignment', - 'used-before-assignment', - 'Used when a local variable is accessed before it\'s \ - assignment.'), - 'E0602': ('Undefined variable %r', - 'undefined-variable', - 'Used when an undefined variable is accessed.'), - 'E0603': ('Undefined variable name %r in __all__', - 'undefined-all-variable', - 'Used when an undefined variable name is referenced in __all__.'), - 'E0604': ('Invalid object %r in __all__, must contain only strings', - 'invalid-all-object', - 'Used when an invalid (non-string) object occurs in __all__.'), - 'E0611': ('No name %r in module %r', - 'no-name-in-module', - 'Used when a name cannot be found in a module.'), - - 'W0601': ('Global variable %r undefined at the module level', - 'global-variable-undefined', - 'Used when a variable is defined through the "global" statement \ - but the variable is not defined in the module scope.'), - 'W0602': ('Using global for %r but no assignment is done', - 'global-variable-not-assigned', - 'Used when a variable is defined through the "global" statement \ - but no assignment to this variable is done.'), - 'W0603': ('Using the global statement', # W0121 - 'global-statement', - 'Used when you use the "global" statement to update a global \ - variable. PyLint just try to discourage this \ - usage. That doesn\'t mean you can not use it !'), - 'W0604': ('Using the global statement at the module level', # W0103 - 'global-at-module-level', - 'Used when you use the "global" statement at the module level \ - since it has no effect'), - 'W0611': ('Unused import %s', - 'unused-import', - 'Used when an imported module or variable is not used.'), - 'W0612': ('Unused variable %r', - 'unused-variable', - 'Used when a variable is defined but not used.'), - 'W0613': ('Unused argument %r', - 'unused-argument', - 'Used when a function or method argument is not used.'), - 'W0614': ('Unused import %s from wildcard import', - 'unused-wildcard-import', - 'Used when an imported module or variable is not used from a \ - \'from X import *\' style import.'), - - 'W0621': ('Redefining name %r from outer scope (line %s)', - 'redefined-outer-name', - 'Used when a variable\'s name hide a name defined in the outer \ - scope.'), - 'W0622': ('Redefining built-in %r', - 'redefined-builtin', - 'Used when a variable or function override a built-in.'), - 'W0623': ('Redefining name %r from %s in exception handler', - 'redefine-in-handler', - 'Used when an exception handler assigns the exception \ - to an existing name'), - - 'W0631': ('Using possibly undefined loop variable %r', - 'undefined-loop-variable', - 'Used when an loop variable (i.e. defined by a for loop or \ - a list comprehension or a generator expression) is used outside \ - the loop.'), - } - -class VariablesChecker(BaseChecker): - """checks for - * unused variables / imports - * undefined variables - * redefinition of variable from builtins or from an outer scope - * use of variable before assignment - * __all__ consistency - """ - - __implements__ = IASTNGChecker - - name = 'variables' - msgs = MSGS - priority = -1 - options = ( - ("init-import", - {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>', - 'help' : 'Tells whether we should check for unused import in \ -__init__ files.'}), - ("dummy-variables-rgx", - {'default': ('_|dummy'), - 'type' :'regexp', 'metavar' : '<regexp>', - 'help' : 'A regular expression matching the beginning of \ - the name of dummy variables (i.e. not used).'}), - ("additional-builtins", - {'default': (), 'type' : 'csv', - 'metavar' : '<comma separated list>', - 'help' : 'List of additional names supposed to be defined in \ -builtins. Remember that you should avoid to define new builtins when possible.' - }), - ) - def __init__(self, linter=None): - BaseChecker.__init__(self, linter) - self._to_consume = None - self._checking_mod_attr = None - - def visit_module(self, node): - """visit module : update consumption analysis variable - checks globals doesn't overrides builtins - """ - self._to_consume = [(copy(node.locals), {}, 'module')] - for name, stmts in node.locals.iteritems(): - if is_builtin(name) and not is_inside_except(stmts[0]): - # do not print Redefining builtin for additional builtins - self.add_message('W0622', args=name, node=stmts[0]) - - @check_messages('W0611', 'W0614') - def leave_module(self, node): - """leave module: check globals - """ - assert len(self._to_consume) == 1 - not_consumed = self._to_consume.pop()[0] - # attempt to check for __all__ if defined - if '__all__' in node.locals: - assigned = node.igetattr('__all__').next() - if assigned is not astng.YES: - for elt in getattr(assigned, 'elts', ()): - try: - elt_name = elt.infer().next() - except astng.InferenceError: - continue - - if not isinstance(elt_name, astng.Const) or not isinstance(elt_name.value, basestring): - self.add_message('E0604', args=elt.as_string(), node=elt) - continue - elt_name = elt.value - # If elt is in not_consumed, remove it from not_consumed - if elt_name in not_consumed: - del not_consumed[elt_name] - continue - if elt_name not in node.locals: - self.add_message('E0603', args=elt_name, node=elt) - # don't check unused imports in __init__ files - if not self.config.init_import and node.package: - return - for name, stmts in not_consumed.iteritems(): - stmt = stmts[0] - if isinstance(stmt, astng.Import): - self.add_message('W0611', args=name, node=stmt) - elif isinstance(stmt, astng.From) and stmt.modname != '__future__': - if stmt.names[0][0] == '*': - self.add_message('W0614', args=name, node=stmt) - else: - self.add_message('W0611', args=name, node=stmt) - del self._to_consume - - def visit_class(self, node): - """visit class: update consumption analysis variable - """ - self._to_consume.append((copy(node.locals), {}, 'class')) - - def leave_class(self, _): - """leave class: update consumption analysis variable - """ - # do not check for not used locals here (no sense) - self._to_consume.pop() - - def visit_lambda(self, node): - """visit lambda: update consumption analysis variable - """ - self._to_consume.append((copy(node.locals), {}, 'lambda')) - - def leave_lambda(self, _): - """leave lambda: update consumption analysis variable - """ - # do not check for not used locals here - self._to_consume.pop() - - def visit_genexpr(self, node): - """visit genexpr: update consumption analysis variable - """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) - - def leave_genexpr(self, _): - """leave genexpr: update consumption analysis variable - """ - # do not check for not used locals here - self._to_consume.pop() - - def visit_dictcomp(self, node): - """visit dictcomp: update consumption analysis variable - """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) - - def leave_dictcomp(self, _): - """leave dictcomp: update consumption analysis variable - """ - # do not check for not used locals here - self._to_consume.pop() - - def visit_setcomp(self, node): - """visit setcomp: update consumption analysis variable - """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) - - def leave_setcomp(self, _): - """leave setcomp: update consumption analysis variable - """ - # do not check for not used locals here - self._to_consume.pop() - - def visit_function(self, node): - """visit function: update consumption analysis variable and check locals - """ - self._to_consume.append((copy(node.locals), {}, 'function')) - if not set(('W0621', 'W0622')) & self.active_msgs: - return - globs = node.root().globals - for name, stmt in node.items(): - if is_inside_except(stmt): - continue - if name in globs and not isinstance(stmt, astng.Global): - line = globs[name][0].fromlineno - self.add_message('W0621', args=(name, line), node=stmt) - elif is_builtin(name): - # do not print Redefining builtin for additional builtins - self.add_message('W0622', args=name, node=stmt) - - def leave_function(self, node): - """leave function: check function's locals are consumed""" - not_consumed = self._to_consume.pop()[0] - if not set(('W0612', 'W0613')) & self.active_msgs: - return - # don't check arguments of function which are only raising an exception - if is_error(node): - return - # don't check arguments of abstract methods or within an interface - is_method = node.is_method() - klass = node.parent.frame() - if is_method and (klass.type == 'interface' or node.is_abstract()): - return - authorized_rgx = self.config.dummy_variables_rgx - called_overridden = False - argnames = node.argnames() - for name, stmts in not_consumed.iteritems(): - # ignore some special names specified by user configuration - if authorized_rgx.match(name): - continue - # ignore names imported by the global statement - # FIXME: should only ignore them if it's assigned latter - stmt = stmts[0] - if isinstance(stmt, astng.Global): - continue - # care about functions with unknown argument (builtins) - if name in argnames: - if is_method: - # don't warn for the first argument of a (non static) method - if node.type != 'staticmethod' and name == argnames[0]: - continue - # don't warn for argument of an overridden method - if not called_overridden: - overridden = overridden_method(klass, node.name) - called_overridden = True - if overridden is not None and name in overridden.argnames(): - continue - if node.name in PYMETHODS and node.name not in ('__init__', '__new__'): - continue - # don't check callback arguments XXX should be configurable - if node.name.startswith('cb_') or node.name.endswith('_cb'): - continue - self.add_message('W0613', args=name, node=stmt) - else: - self.add_message('W0612', args=name, node=stmt) - - @check_messages('W0601', 'W0602', 'W0603', 'W0604', 'W0622') - def visit_global(self, node): - """check names imported exists in the global scope""" - frame = node.frame() - if isinstance(frame, astng.Module): - self.add_message('W0604', node=node) - return - module = frame.root() - default_message = True - for name in node.names: - try: - assign_nodes = module.getattr(name) - except astng.NotFoundError: - # unassigned global, skip - assign_nodes = [] - for anode in assign_nodes: - if anode.parent is None: - # node returned for builtin attribute such as __file__, - # __doc__, etc... - continue - if anode.frame() is frame: - # same scope level assignment - break - else: - # global but no assignment - self.add_message('W0602', args=name, node=node) - default_message = False - if not assign_nodes: - continue - for anode in assign_nodes: - if anode.parent is None: - self.add_message('W0622', args=name, node=node) - break - if anode.frame() is module: - # module level assignment - break - else: - # global undefined at the module scope - self.add_message('W0601', args=name, node=node) - default_message = False - if default_message: - self.add_message('W0603', node=node) - - def _loopvar_name(self, node, name): - # filter variables according to node's scope - # XXX used to filter parents but don't remember why, and removing this - # fixes a W0631 false positive reported by Paul Hachmann on 2008/12 on - # python-projects (added to func_use_for_or_listcomp_var test) - #astmts = [stmt for stmt in node.lookup(name)[1] - # if hasattr(stmt, 'ass_type')] and - # not stmt.statement().parent_of(node)] - if 'W0631' not in self.active_msgs: - return - astmts = [stmt for stmt in node.lookup(name)[1] - if hasattr(stmt, 'ass_type')] - # filter variables according their respective scope test is_statement - # and parent to avoid #74747. This is not a total fix, which would - # introduce a mechanism similar to special attribute lookup in - # modules. Also, in order to get correct inference in this case, the - # scope lookup rules would need to be changed to return the initial - # assignment (which does not exist in code per se) as well as any later - # modifications. - if not astmts or (astmts[0].is_statement or astmts[0].parent) \ - and astmts[0].statement().parent_of(node): - _astmts = [] - else: - _astmts = astmts[:1] - for i, stmt in enumerate(astmts[1:]): - if (astmts[i].statement().parent_of(stmt) - and not in_for_else_branch(astmts[i].statement(), stmt)): - continue - _astmts.append(stmt) - astmts = _astmts - if len(astmts) == 1: - ass = astmts[0].ass_type() - if isinstance(ass, (astng.For, astng.Comprehension, astng.GenExpr)) \ - and not ass.statement() is node.statement(): - self.add_message('W0631', args=name, node=node) - - def visit_excepthandler(self, node): - for name in get_all_elements(node.name): - clobbering, args = clobber_in_except(name) - if clobbering: - self.add_message('W0623', args=args, node=name) - - def visit_assname(self, node): - if isinstance(node.ass_type(), astng.AugAssign): - self.visit_name(node) - - def visit_delname(self, node): - self.visit_name(node) - - def visit_name(self, node): - """check that a name is defined if the current scope and doesn't - redefine a built-in - """ - stmt = node.statement() - if stmt.fromlineno is None: - # name node from a astng built from live code, skip - assert not stmt.root().file.endswith('.py') - return - name = node.name - frame = stmt.scope() - # if the name node is used as a function default argument's value or as - # a decorator, then start from the parent frame of the function instead - # of the function frame - and thus open an inner class scope - if (is_func_default(node) or is_func_decorator(node) - or is_ancestor_name(frame, node)): - start_index = len(self._to_consume) - 2 - else: - start_index = len(self._to_consume) - 1 - # iterates through parent scopes, from the inner to the outer - base_scope_type = self._to_consume[start_index][-1] - for i in range(start_index, -1, -1): - to_consume, consumed, scope_type = self._to_consume[i] - # if the current scope is a class scope but it's not the inner - # scope, ignore it. This prevents to access this scope instead of - # the globals one in function members when there are some common - # names. The only exception is when the starting scope is a - # comprehension and its direct outer scope is a class - if scope_type == 'class' and i != start_index and not ( - base_scope_type == 'comprehension' and i == start_index-1): - # XXX find a way to handle class scope in a smoother way - continue - # the name has already been consumed, only check it's not a loop - # variable used outside the loop - if name in consumed: - self._loopvar_name(node, name) - break - # mark the name as consumed if it's defined in this scope - # (i.e. no KeyError is raised by "to_consume[name]") - try: - consumed[name] = to_consume[name] - except KeyError: - continue - # checks for use before assignment - defnode = assign_parent(to_consume[name][0]) - if defnode is not None: - defstmt = defnode.statement() - defframe = defstmt.frame() - maybee0601 = True - if not frame is defframe: - maybee0601 = False - elif defframe.parent is None: - # we are at the module level, check the name is not - # defined in builtins - if name in defframe.scope_attrs or builtin_lookup(name)[1]: - maybee0601 = False - else: - # we are in a local scope, check the name is not - # defined in global or builtin scope - if defframe.root().lookup(name)[1]: - maybee0601 = False - if (maybee0601 - and stmt.fromlineno <= defstmt.fromlineno - and not is_defined_before(node) - and not are_exclusive(stmt, defstmt, ('NameError', 'Exception', 'BaseException'))): - if defstmt is stmt and isinstance(node, (astng.DelName, - astng.AssName)): - self.add_message('E0602', args=name, node=node) - elif self._to_consume[-1][-1] != 'lambda': - # E0601 may *not* occurs in lambda scope - self.add_message('E0601', args=name, node=node) - if not isinstance(node, astng.AssName): # Aug AssName - del to_consume[name] - else: - del consumed[name] - # check it's not a loop variable used outside the loop - self._loopvar_name(node, name) - break - else: - # we have not found the name, if it isn't a builtin, that's an - # undefined name ! - if not (name in astng.Module.scope_attrs or is_builtin(name) - or name in self.config.additional_builtins): - self.add_message('E0602', args=name, node=node) - - @check_messages('E0611') - def visit_import(self, node): - """check modules attribute accesses""" - for name, _ in node.names: - parts = name.split('.') - try: - module = node.infer_name_module(parts[0]).next() - except astng.ResolveError: - continue - self._check_module_attrs(node, module, parts[1:]) - - @check_messages('E0611') - def visit_from(self, node): - """check modules attribute accesses""" - name_parts = node.modname.split('.') - level = getattr(node, 'level', None) - try: - module = node.root().import_module(name_parts[0], level=level) - except ASTNGBuildingException: - return - except Exception, exc: - print 'Unhandled exception in VariablesChecker:', exc - return - module = self._check_module_attrs(node, module, name_parts[1:]) - if not module: - return - for name, _ in node.names: - if name == '*': - continue - self._check_module_attrs(node, module, name.split('.')) - - def _check_module_attrs(self, node, module, module_names): - """check that module_names (list of string) are accessible through the - given module - if the latest access name corresponds to a module, return it - """ - assert isinstance(module, astng.Module), module - while module_names: - name = module_names.pop(0) - if name == '__dict__': - module = None - break - try: - module = module.getattr(name)[0].infer().next() - if module is astng.YES: - return None - except astng.NotFoundError: - self.add_message('E0611', args=(name, module.name), node=node) - return None - except astng.InferenceError: - return None - if module_names: - # FIXME: other message if name is not the latest part of - # module_names ? - modname = module and module.name or '__dict__' - self.add_message('E0611', node=node, - args=('.'.join(module_names), modname)) - return None - if isinstance(module, astng.Module): - return module - return None - - -class VariablesChecker3k(VariablesChecker): - '''Modified variables checker for 3k''' - # listcomp have now also their scope - - def visit_listcomp(self, node): - """visit dictcomp: update consumption analysis variable - """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) - - def leave_listcomp(self, _): - """leave dictcomp: update consumption analysis variable - """ - # do not check for not used locals here - self._to_consume.pop() - -if sys.version_info >= (3, 0): - VariablesChecker = VariablesChecker3k - - -def register(linter): - """required method to auto register this checker""" - linter.register_checker(VariablesChecker(linter)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/config.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/config.py @@ -1,152 +0,0 @@ -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""utilities for PyLint configuration : - -* pylintrc -* pylint.d (PYLINTHOME) -""" - -import pickle -import os -import sys -from os.path import exists, isfile, join, expanduser, abspath, dirname - -# pylint home is used to save old runs results ################################ - -USER_HOME = expanduser('~') -if 'PYLINTHOME' in os.environ: - PYLINT_HOME = os.environ['PYLINTHOME'] - if USER_HOME == '~': - USER_HOME = dirname(PYLINT_HOME) -elif USER_HOME == '~': - PYLINT_HOME = ".pylint.d" -else: - PYLINT_HOME = join(USER_HOME, '.pylint.d') - -if not exists(PYLINT_HOME): - try: - os.mkdir(PYLINT_HOME) - except OSError: - print >> sys.stderr, 'Unable to create directory %s' % PYLINT_HOME - -def get_pdata_path(base_name, recurs): - """return the path of the file which should contain old search data for the - given base_name with the given options values - """ - base_name = base_name.replace(os.sep, '_') - return join(PYLINT_HOME, "%s%s%s"%(base_name, recurs, '.stats')) - -def load_results(base): - """try to unpickle and return data from file if it exists and is not - corrupted - - return an empty dictionary if it doesn't exists - """ - data_file = get_pdata_path(base, 1) - try: - return pickle.load(open(data_file)) - except: - return {} - -if sys.version_info < (3, 0): - _PICK_MOD = 'w' -else: - _PICK_MOD = 'wb' - -def save_results(results, base): - """pickle results""" - data_file = get_pdata_path(base, 1) - try: - pickle.dump(results, open(data_file, _PICK_MOD)) - except (IOError, OSError), ex: - print >> sys.stderr, 'Unable to create file %s: %s' % (data_file, ex) - -# location of the configuration file ########################################## - - -def find_pylintrc(): - """search the pylint rc file and return its path if it find it, else None - """ - # is there a pylint rc file in the current directory ? - if exists('pylintrc'): - return abspath('pylintrc') - if isfile('__init__.py'): - curdir = abspath(os.getcwd()) - while isfile(join(curdir, '__init__.py')): - curdir = abspath(join(curdir, '..')) - if isfile(join(curdir, 'pylintrc')): - return join(curdir, 'pylintrc') - if 'PYLINTRC' in os.environ and exists(os.environ['PYLINTRC']): - pylintrc = os.environ['PYLINTRC'] - else: - user_home = expanduser('~') - if user_home == '~' or user_home == '/root': - pylintrc = ".pylintrc" - else: - pylintrc = join(user_home, '.pylintrc') - if not isfile(pylintrc): - if isfile('/etc/pylintrc'): - pylintrc = '/etc/pylintrc' - else: - pylintrc = None - return pylintrc - -PYLINTRC = find_pylintrc() - -ENV_HELP = ''' -The following environment variables are used: - * PYLINTHOME - path to the directory where data of persistent run will be stored. If not -found, it defaults to ~/.pylint.d/ or .pylint.d (in the current working -directory). - * PYLINTRC - path to the configuration file. If not found, it will use the first -existing file among (~/.pylintrc, /etc/pylintrc). -''' % globals() - -# evaluation messages ######################################################### - -def get_note_message(note): - """return a message according to note - note is a float < 10 (10 is the highest note) - """ - assert note <= 10, "Note is %.2f. Either you cheated, or pylint's \ -broken!" % note - if note < 0: - msg = 'You have to do something quick !' - elif note < 1: - msg = 'Hey! This is really dreadful. Or maybe pylint is buggy?' - elif note < 2: - msg = "Come on! You can't be proud of this code" - elif note < 3: - msg = 'Hum... Needs work.' - elif note < 4: - msg = 'Wouldn\'t you be a bit lazy?' - elif note < 5: - msg = 'A little more work would make it acceptable.' - elif note < 6: - msg = 'Just the bare minimum. Give it a bit more polish. ' - elif note < 7: - msg = 'This is okay-ish, but I\'m sure you can do better.' - elif note < 8: - msg = 'If you commit now, people should not be making nasty \ -comments about you on c.l.py' - elif note < 9: - msg = 'That\'s pretty good. Good work mate.' - elif note < 10: - msg = 'So close to being perfect...' - else: - msg = 'Wow ! Now this deserves our uttermost respect.\nPlease send \ -your code to python-projects@logilab.org' - return msg diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/interfaces.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/interfaces.py @@ -1,98 +0,0 @@ -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -""" Copyright (c) 2002-2003 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ -- mailto:contact@logilab.fr - -Interfaces for PyLint objects -""" - -__revision__ = "$Id: interfaces.py,v 1.9 2004-04-24 12:14:53 syt Exp $" - -from .logilab.common.interface import Interface - - -class IChecker(Interface): - """This is an base interface, not designed to be used elsewhere than for - sub interfaces definition. - """ - - def open(self): - """called before visiting project (i.e set of modules)""" - - def close(self): - """called after visiting project (i.e set of modules)""" - -## def open_module(self): -## """called before visiting a module""" - -## def close_module(self): -## """called after visiting a module""" - - -class IRawChecker(IChecker): - """interface for checker which need to parse the raw file - """ - - def process_module(self, astng): - """ process a module - - the module's content is accessible via astng.file_stream - """ - - -class IASTNGChecker(IChecker): - """ interface for checker which prefers receive events according to - statement type - """ - - -class ILinter(Interface): - """interface for the linter class - - the linter class will generate events to its registered checkers. - Each checker may interact with the linter instance using this API - """ - - def register_checker(self, checker): - """register a new checker class - - checker is a class implementing IrawChecker or / and IASTNGChecker - """ - - def add_message(self, msg_id, line=None, node=None, args=None): - """add the message corresponding to the given id. - - If provided, msg is expanded using args - - astng checkers should provide the node argument, - raw checkers should provide the line argument. - """ - - -class IReporter(Interface): - """ reporter collect messages and display results encapsulated in a layout - """ - def add_message(self, msg_id, location, msg): - """add a message of a given type - - msg_id is a message identifier - location is a 3-uple (module, object, line) - msg is the actual message - """ - - def display_results(self, layout): - """display results encapsulated in the layout tree - """ - - -__all__ = ('IRawChecker', 'ILinter', 'IReporter') diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/lint.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/lint.py @@ -1,1046 +0,0 @@ -# Copyright (c) 2003-2010 Sylvain Thenault (thenault@gmail.com). -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -""" %prog [options] module_or_package - - Check that a module satisfies a coding standard (and more !). - - %prog --help - - Display this help message and exit. - - %prog --help-msg <msg-id>[,<msg-id>] - - Display help messages about given message identifiers and exit. -""" - -# import this first to avoid builtin namespace pollution -from .checkers import utils - -import sys -import os -import re -import tokenize -from warnings import warn - -from .logilab.common.configuration import UnsupportedAction, OptionsManagerMixIn -from .logilab.common.optik_ext import check_csv -from .logilab.common.modutils import load_module_from_name, get_module_part -from .logilab.common.interface import implements -from .logilab.common.textutils import splitstrip -from .logilab.common.ureports import Table, Text, Section -from .logilab.common.__pkginfo__ import version as common_version - -from .logilab.astng import MANAGER, nodes, ASTNGBuildingException -from .logilab.astng.__pkginfo__ import version as astng_version - -from .utils import (PyLintASTWalker, UnknownMessage, MessagesHandlerMixIn, - ReportsHandlerMixIn, MSG_TYPES, expand_modules) -from .interfaces import ILinter, IRawChecker, IASTNGChecker -from .checkers import (BaseRawChecker, EmptyReport, - table_lines_from_stats) -from .reporters.text import (TextReporter, ParseableTextReporter, - VSTextReporter, ColorizedTextReporter) -from .reporters.html import HTMLReporter -from . import config - -from .__pkginfo__ import version - - -OPTION_RGX = re.compile(r'\s*#.*\bpylint:(.*)') -REPORTER_OPT_MAP = {'text': TextReporter, - 'parseable': ParseableTextReporter, - 'msvs': VSTextReporter, - 'colorized': ColorizedTextReporter, - 'html': HTMLReporter,} - - -def _get_python_path(filepath): - dirname = os.path.dirname(os.path.realpath( - os.path.expanduser(filepath))) - while True: - if not os.path.exists(os.path.join(dirname, "__init__.py")): - return dirname - old_dirname = dirname - dirname = os.path.dirname(dirname) - if old_dirname == dirname: - return os.getcwd() - - -# Python Linter class ######################################################### - -MSGS = { - 'F0001': ('%s', - 'fatal', - 'Used when an error occurred preventing the analysis of a \ - module (unable to find it for instance).'), - 'F0002': ('%s: %s', - 'astng-error', - 'Used when an unexpected error occurred while building the ASTNG \ - representation. This is usually accompanied by a traceback. \ - Please report such errors !'), - 'F0003': ('ignored builtin module %s', - 'ignored-builtin-module', - 'Used to indicate that the user asked to analyze a builtin module \ - which has been skipped.'), - 'F0004': ('unexpected inferred value %s', - 'unexpected-inferred-value', - 'Used to indicate that some value of an unexpected type has been \ - inferred.'), - 'F0010': ('error while code parsing: %s', - 'parse-error', - 'Used when an exception occured while building the ASTNG \ - representation which could be handled by astng.'), - - 'I0001': ('Unable to run raw checkers on built-in module %s', - 'raw-checker-failed', - 'Used to inform that a built-in module has not been checked \ - using the raw checkers.'), - - 'I0010': ('Unable to consider inline option %r', - 'bad-inline-option', - 'Used when an inline option is either badly formatted or can\'t \ - be used inside modules.'), - - 'I0011': ('Locally disabling %s', - 'locally-disabled', - 'Used when an inline option disables a message or a messages \ - category.'), - 'I0012': ('Locally enabling %s', - 'locally-enabled', - 'Used when an inline option enables a message or a messages \ - category.'), - 'I0013': ('Ignoring entire file', - 'file-ignored', - 'Used to inform that the file will not be checked'), - 'I0014': ('Used deprecated directive "pylint:disable-all" or "pylint:disable=all"', - 'deprecated-disable-all', - 'You should preferably use "pylint:skip-file" as this directive ' - 'has a less confusing name. Do this only if you are sure that all ' - 'people running Pylint on your code have version >= 0.26'), - 'I0020': ('Suppressed %s (from line %d)', - 'suppressed-message', - 'A message was triggered on a line, but suppressed explicitly ' - 'by a disable= comment in the file. This message is not ' - 'generated for messages that are ignored due to configuration ' - 'settings.'), - 'I0021': ('Useless suppression of %s', - 'useless-suppression', - 'Reported when a message is explicitly disabled for a line or ' - 'a block of code, but never triggered.'), - - - 'E0001': ('%s', - 'syntax-error', - 'Used when a syntax error is raised for a module.'), - - 'E0011': ('Unrecognized file option %r', - 'unrecognized-inline-option', - 'Used when an unknown inline option is encountered.'), - 'E0012': ('Bad option value %r', - 'bad-option-value', - 'Used when a bad value for an inline option is encountered.'), - } - - -class PyLinter(OptionsManagerMixIn, MessagesHandlerMixIn, ReportsHandlerMixIn, - BaseRawChecker): - """lint Python modules using external checkers. - - This is the main checker controlling the other ones and the reports - generation. It is itself both a raw checker and an astng checker in order - to: - * handle message activation / deactivation at the module level - * handle some basic but necessary stats'data (number of classes, methods...) - - IDE plugins developpers: you may have to call - `logilab.astng.builder.MANAGER.astng_cache.clear()` accross run if you want - to ensure the latest code version is actually checked. - """ - - __implements__ = (ILinter, IRawChecker) - - name = 'master' - priority = 0 - level = 0 - msgs = MSGS - may_be_disabled = False - - @staticmethod - def make_options(): - return (('ignore', - {'type' : 'csv', 'metavar' : '<file>[,<file>...]', - 'dest' : 'black_list', 'default' : ('CVS',), - 'help' : 'Add files or directories to the blacklist. \ -They should be base names, not paths.'}), - ('persistent', - {'default': True, 'type' : 'yn', 'metavar' : '<y_or_n>', - 'level': 1, - 'help' : 'Pickle collected data for later comparisons.'}), - - ('load-plugins', - {'type' : 'csv', 'metavar' : '<modules>', 'default' : (), - 'level': 1, - 'help' : 'List of plugins (as comma separated values of \ -python modules names) to load, usually to register additional checkers.'}), - - ('output-format', - {'default': 'text', 'type': 'string', 'metavar' : '<format>', - 'short': 'f', - 'group': 'Reports', - 'help' : 'Set the output format. Available formats are text,' - ' parseable, colorized, msvs (visual studio) and html. You ' - 'can also give a reporter class, eg mypackage.mymodule.' - 'MyReporterClass.'}), - - ('include-ids', - {'type' : 'yn', 'metavar' : '<y_or_n>', 'default' : 0, - 'short': 'i', - 'group': 'Reports', - 'help' : 'Include message\'s id in output'}), - - ('symbols', - {'type' : 'yn', 'metavar' : '<y_or_n>', 'default' : 0, - 'short': 's', - 'group': 'Reports', - 'help' : 'Include symbolic ids of messages in output'}), - - ('files-output', - {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>', - 'group': 'Reports', 'level': 1, - 'help' : 'Put messages in a separate file for each module / \ -package specified on the command line instead of printing them on stdout. \ -Reports (if any) will be written in a file name "pylint_global.[txt|html]".'}), - - ('reports', - {'default': 1, 'type' : 'yn', 'metavar' : '<y_or_n>', - 'short': 'r', - 'group': 'Reports', - 'help' : 'Tells whether to display a full report or only the\ - messages'}), - - ('evaluation', - {'type' : 'string', 'metavar' : '<python_expression>', - 'group': 'Reports', 'level': 1, - 'default': '10.0 - ((float(5 * error + warning + refactor + \ -convention) / statement) * 10)', - 'help' : 'Python expression which should return a note less \ -than 10 (10 is the highest note). You have access to the variables errors \ -warning, statement which respectively contain the number of errors / warnings\ - messages and the total number of statements analyzed. This is used by the \ - global evaluation report (RP0004).'}), - - ('comment', - {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>', - 'group': 'Reports', 'level': 1, - 'help' : 'Add a comment according to your evaluation note. \ -This is used by the global evaluation report (RP0004).'}), - - ('enable', - {'type' : 'csv', 'metavar': '<msg ids>', - 'short': 'e', - 'group': 'Messages control', - 'help' : 'Enable the message, report, category or checker with the ' - 'given id(s). You can either give multiple identifier ' - 'separated by comma (,) or put this option multiple time. ' - 'See also the "--disable" option for examples. '}), - - ('disable', - {'type' : 'csv', 'metavar': '<msg ids>', - 'short': 'd', - 'group': 'Messages control', - 'help' : 'Disable the message, report, category or checker ' - 'with the given id(s). You can either give multiple identifiers' - ' separated by comma (,) or put this option multiple times ' - '(only on the command line, not in the configuration file ' - 'where it should appear only once).' - 'You can also use "--disable=all" to disable everything first ' - 'and then reenable specific checks. For example, if you want ' - 'to run only the similarities checker, you can use ' - '"--disable=all --enable=similarities". ' - 'If you want to run only the classes checker, but have no ' - 'Warning level messages displayed, use' - '"--disable=all --enable=classes --disable=W"'}), - ) - - option_groups = ( - ('Messages control', 'Options controling analysis messages'), - ('Reports', 'Options related to output formating and reporting'), - ) - - def __init__(self, options=(), reporter=None, option_groups=(), - pylintrc=None): - # some stuff has to be done before ancestors initialization... - # - # checkers / reporter / astng manager - self.reporter = None - self._checkers = {} - self._ignore_file = False - # visit variables - self.base_name = None - self.base_file = None - self.current_name = None - self.current_file = None - self.stats = None - # init options - self.options = options + PyLinter.make_options() - self.option_groups = option_groups + PyLinter.option_groups - self._options_methods = { - 'enable': self.enable, - 'disable': self.disable} - self._bw_options_methods = {'disable-msg': self.disable, - 'enable-msg': self.enable} - full_version = '%%prog %s, \nastng %s, common %s\nPython %s' % ( - version, astng_version, common_version, sys.version) - OptionsManagerMixIn.__init__(self, usage=__doc__, - version=full_version, - config_file=pylintrc or config.PYLINTRC) - MessagesHandlerMixIn.__init__(self) - ReportsHandlerMixIn.__init__(self) - BaseRawChecker.__init__(self) - # provided reports - self.reports = (('RP0001', 'Messages by category', - report_total_messages_stats), - ('RP0002', '% errors / warnings by module', - report_messages_by_module_stats), - ('RP0003', 'Messages', - report_messages_stats), - ('RP0004', 'Global evaluation', - self.report_evaluation), - ) - self.register_checker(self) - self._dynamic_plugins = [] - self.load_provider_defaults() - self.set_reporter(reporter or TextReporter(sys.stdout)) - - def load_default_plugins(self): - from . import checkers - checkers.initialize(self) - - def prepare_import_path(self, args): - """Prepare sys.path for running the linter checks.""" - if len(args) == 1: - sys.path.insert(0, _get_python_path(args[0])) - else: - sys.path.insert(0, os.getcwd()) - - def cleanup_import_path(self): - """Revert any changes made to sys.path in prepare_import_path.""" - sys.path.pop(0) - - def load_plugin_modules(self, modnames): - """take a list of module names which are pylint plugins and load - and register them - """ - for modname in modnames: - if modname in self._dynamic_plugins: - continue - self._dynamic_plugins.append(modname) - module = load_module_from_name(modname) - module.register(self) - - def set_reporter(self, reporter): - """set the reporter used to display messages and reports""" - self.reporter = reporter - reporter.linter = self - - def set_option(self, optname, value, action=None, optdict=None): - """overridden from configuration.OptionsProviderMixin to handle some - special options - """ - if optname in self._options_methods or optname in self._bw_options_methods: - if value: - try: - meth = self._options_methods[optname] - except KeyError: - meth = self._bw_options_methods[optname] - warn('%s is deprecated, replace it by %s' % ( - optname, optname.split('-')[0]), DeprecationWarning) - value = check_csv(None, optname, value) - if isinstance(value, (list, tuple)): - for _id in value : - meth(_id) - else : - meth(value) - elif optname == 'output-format': - if value.lower() in REPORTER_OPT_MAP: - self.set_reporter(REPORTER_OPT_MAP[value.lower()]()) - else: - module = load_module_from_name(get_module_part(value)) - class_name = value.split('.')[-1] - reporter_class = getattr(module, class_name) - self.set_reporter(reporter_class()) - - try: - BaseRawChecker.set_option(self, optname, value, action, optdict) - except UnsupportedAction: - print >> sys.stderr, 'option %s can\'t be read from config file' % \ - optname - - # checkers manipulation methods ############################################ - - def register_checker(self, checker): - """register a new checker - - checker is an object implementing IRawChecker or / and IASTNGChecker - """ - assert checker.priority <= 0, 'checker priority can\'t be >= 0' - self._checkers.setdefault(checker.name, []).append(checker) - for r_id, r_title, r_cb in checker.reports: - self.register_report(r_id, r_title, r_cb, checker) - self.register_options_provider(checker) - if hasattr(checker, 'msgs'): - self.register_messages(checker) - checker.load_defaults() - - def disable_noerror_messages(self): - for msgcat, msgids in self._msgs_by_category.iteritems(): - if msgcat == 'E': - for msgid in msgids: - self.enable(msgid) - else: - for msgid in msgids: - self.disable(msgid) - - def disable_reporters(self): - """disable all reporters""" - for reporters in self._reports.itervalues(): - for report_id, _title, _cb in reporters: - self.disable_report(report_id) - - def error_mode(self): - """error mode: enable only errors; no reports, no persistent""" - self.disable_noerror_messages() - self.disable('miscellaneous') - self.set_option('reports', False) - self.set_option('persistent', False) - - # block level option handling ############################################# - # - # see func_block_disable_msg.py test case for expected behaviour - - def process_tokens(self, tokens): - """process tokens from the current module to search for module/block - level options - """ - comment = tokenize.COMMENT - newline = tokenize.NEWLINE - for (tok_type, _, start, _, line) in tokens: - if tok_type not in (comment, newline): - continue - match = OPTION_RGX.search(line) - if match is None: - continue - if match.group(1).strip() == "disable-all" or match.group(1).strip() == 'skip-file': - if match.group(1).strip() == "disable-all": - self.add_message('I0014', line=start[0]) - self.add_message('I0013', line=start[0]) - self._ignore_file = True - return - try: - opt, value = match.group(1).split('=', 1) - except ValueError: - self.add_message('I0010', args=match.group(1).strip(), - line=start[0]) - continue - opt = opt.strip() - if opt in self._options_methods or opt in self._bw_options_methods: - try: - meth = self._options_methods[opt] - except KeyError: - meth = self._bw_options_methods[opt] - warn('%s is deprecated, replace it with %s (%s, line %s)' % ( - opt, opt.split('-')[0], self.current_file, line), - DeprecationWarning) - for msgid in splitstrip(value): - try: - if (opt, msgid) == ('disable', 'all'): - self.add_message('I0014', line=start[0]) - self.add_message('I0013', line=start[0]) - self._ignore_file = True - return - meth(msgid, 'module', start[0]) - except UnknownMessage: - self.add_message('E0012', args=msgid, line=start[0]) - else: - self.add_message('E0011', args=opt, line=start[0]) - - def collect_block_lines(self, node, msg_state): - """walk ast to collect block level options line numbers""" - # recurse on children (depth first) - for child in node.get_children(): - self.collect_block_lines(child, msg_state) - first = node.fromlineno - last = node.tolineno - # first child line number used to distinguish between disable - # which are the first child of scoped node with those defined later. - # For instance in the code below: - # - # 1. def meth8(self): - # 2. """test late disabling""" - # 3. # pylint: disable=E1102 - # 4. print self.blip - # 5. # pylint: disable=E1101 - # 6. print self.bla - # - # E1102 should be disabled from line 1 to 6 while E1101 from line 5 to 6 - # - # this is necessary to disable locally messages applying to class / - # function using their fromlineno - if isinstance(node, (nodes.Module, nodes.Class, nodes.Function)) and node.body: - firstchildlineno = node.body[0].fromlineno - else: - firstchildlineno = last - for msgid, lines in msg_state.iteritems(): - for lineno, state in lines.items(): - original_lineno = lineno - if first <= lineno <= last: - if lineno > firstchildlineno: - state = True - # set state for all lines for this block - first, last = node.block_range(lineno) - for line in xrange(first, last+1): - # do not override existing entries - if not line in self._module_msgs_state.get(msgid, ()): - if line in lines: # state change in the same block - state = lines[line] - original_lineno = line - if not state: - self._suppression_mapping[(msgid, line)] = original_lineno - try: - self._module_msgs_state[msgid][line] = state - except KeyError: - self._module_msgs_state[msgid] = {line: state} - del lines[lineno] - - - # code checking methods ################################################### - - def get_checkers(self): - """return all available checkers as a list""" - return [self] + [c for checkers in self._checkers.itervalues() - for c in checkers if c is not self] - - def prepare_checkers(self): - """return checkers needed for activated messages and reports""" - if not self.config.reports: - self.disable_reporters() - # get needed checkers - neededcheckers = [self] - for checker in self.get_checkers()[1:]: - # fatal errors should not trigger enable / disabling a checker - messages = set(msg for msg in checker.msgs - if msg[0] != 'F' and self.is_message_enabled(msg)) - if (messages or - any(self.report_is_enabled(r[0]) for r in checker.reports)): - neededcheckers.append(checker) - checker.active_msgs = messages - return neededcheckers - - def check(self, files_or_modules): - """main checking entry: check a list of files or modules from their - name. - """ - self.reporter.include_ids = self.config.include_ids - self.reporter.symbols = self.config.symbols - if not isinstance(files_or_modules, (list, tuple)): - files_or_modules = (files_or_modules,) - walker = PyLintASTWalker(self) - checkers = self.prepare_checkers() - rawcheckers = [c for c in checkers if implements(c, IRawChecker) - and c is not self] - # notify global begin - for checker in checkers: - checker.open() - if implements(checker, IASTNGChecker): - walker.add_checker(checker) - # build ast and check modules or packages - for descr in self.expand_files(files_or_modules): - modname, filepath = descr['name'], descr['path'] - if self.config.files_output: - reportfile = 'pylint_%s.%s' % (modname, self.reporter.extension) - self.reporter.set_output(open(reportfile, 'w')) - self.set_current_module(modname, filepath) - # get the module representation - astng = self.get_astng(filepath, modname) - if astng is None: - continue - self.base_name = descr['basename'] - self.base_file = descr['basepath'] - self._ignore_file = False - # fix the current file (if the source file was not available or - # if it's actually a c extension) - self.current_file = astng.file - self.check_astng_module(astng, walker, rawcheckers) - self._add_suppression_messages() - # notify global end - self.set_current_module('') - self.stats['statement'] = walker.nbstatements - checkers.reverse() - for checker in checkers: - checker.close() - - def expand_files(self, modules): - """get modules and errors from a list of modules and handle errors - """ - result, errors = expand_modules(modules, self.config.black_list) - for error in errors: - message = modname = error["mod"] - key = error["key"] - self.set_current_module(modname) - if key == "F0001": - message = str(error["ex"]).replace(os.getcwd() + os.sep, '') - self.add_message(key, args=message) - return result - - def set_current_module(self, modname, filepath=None): - """set the name of the currently analyzed module and - init statistics for it - """ - if not modname and filepath is None: - return - self.reporter.on_set_current_module(modname, filepath) - self.current_name = modname - self.current_file = filepath or modname - self.stats['by_module'][modname] = {} - self.stats['by_module'][modname]['statement'] = 0 - for msg_cat in MSG_TYPES.itervalues(): - self.stats['by_module'][modname][msg_cat] = 0 - # XXX hack, to be correct we need to keep module_msgs_state - # for every analyzed module (the problem stands with localized - # messages which are only detected in the .close step) - if modname: - self._module_msgs_state = {} - self._module_msg_cats_state = {} - self._raw_module_msgs_state = {} - self._ignored_msgs = {} - - def get_astng(self, filepath, modname): - """return a astng representation for a module""" - try: - return MANAGER.astng_from_file(filepath, modname, source=True) - except SyntaxError, ex: - self.add_message('E0001', line=ex.lineno, args=ex.msg) - except ASTNGBuildingException, ex: - self.add_message('F0010', args=ex) - except Exception, ex: - import traceback - traceback.print_exc() - self.add_message('F0002', args=(ex.__class__, ex)) - - def check_astng_module(self, astng, walker, rawcheckers): - """check a module from its astng representation, real work""" - # call raw checkers if possible - if not astng.pure_python: - self.add_message('I0001', args=astng.name) - else: - #assert astng.file.endswith('.py') - # invoke IRawChecker interface on self to fetch module/block - # level options - self.process_module(astng) - if self._ignore_file: - return False - # walk ast to collect line numbers - for msg, lines in self._module_msgs_state.iteritems(): - self._raw_module_msgs_state[msg] = lines.copy() - orig_state = self._module_msgs_state.copy() - self._module_msgs_state = {} - self._suppression_mapping = {} - self.collect_block_lines(astng, orig_state) - for checker in rawcheckers: - checker.process_module(astng) - # generate events to astng checkers - walker.walk(astng) - return True - - # IASTNGChecker interface ################################################# - - def open(self): - """initialize counters""" - self.stats = { 'by_module' : {}, - 'by_msg' : {}, - } - for msg_cat in MSG_TYPES.itervalues(): - self.stats[msg_cat] = 0 - - def close(self): - """close the whole package /module, it's time to make reports ! - - if persistent run, pickle results for later comparison - """ - if self.base_name is not None: - # load previous results if any - previous_stats = config.load_results(self.base_name) - # XXX code below needs refactoring to be more reporter agnostic - self.reporter.on_close(self.stats, previous_stats) - if self.config.reports: - sect = self.make_reports(self.stats, previous_stats) - if self.config.files_output: - filename = 'pylint_global.' + self.reporter.extension - self.reporter.set_output(open(filename, 'w')) - else: - sect = Section() - if self.config.reports or self.config.output_format == 'html': - self.reporter.display_results(sect) - # save results if persistent run - if self.config.persistent: - config.save_results(self.stats, self.base_name) - - # specific reports ######################################################## - - def _add_suppression_messages(self): - for warning, lines in self._raw_module_msgs_state.iteritems(): - for line, enable in lines.iteritems(): - if not enable and (warning, line) not in self._ignored_msgs: - self.add_message('I0021', line, None, - (self.get_msg_display_string(warning),)) - - for (warning, from_), lines in self._ignored_msgs.iteritems(): - for line in lines: - self.add_message('I0020', line, None, - (self.get_msg_display_string(warning), from_)) - - def report_evaluation(self, sect, stats, previous_stats): - """make the global evaluation report""" - # check with at least check 1 statements (usually 0 when there is a - # syntax error preventing pylint from further processing) - if stats['statement'] == 0: - raise EmptyReport() - # get a global note for the code - evaluation = self.config.evaluation - try: - note = eval(evaluation, {}, self.stats) - except Exception, ex: - msg = 'An exception occurred while rating: %s' % ex - else: - stats['global_note'] = note - msg = 'Your code has been rated at %.2f/10' % note - if 'global_note' in previous_stats: - msg += ' (previous run: %.2f/10)' % previous_stats['global_note'] - if self.config.comment: - msg = '%s\n%s' % (msg, config.get_note_message(note)) - sect.append(Text(msg)) - -# some reporting functions #################################################### - -def report_total_messages_stats(sect, stats, previous_stats): - """make total errors / warnings report""" - lines = ['type', 'number', 'previous', 'difference'] - lines += table_lines_from_stats(stats, previous_stats, - ('convention', 'refactor', - 'warning', 'error')) - sect.append(Table(children=lines, cols=4, rheaders=1)) - -def report_messages_stats(sect, stats, _): - """make messages type report""" - if not stats['by_msg']: - # don't print this report when we didn't detected any errors - raise EmptyReport() - in_order = sorted([(value, msg_id) - for msg_id, value in stats['by_msg'].iteritems() - if not msg_id.startswith('I')]) - in_order.reverse() - lines = ('message id', 'occurrences') - for value, msg_id in in_order: - lines += (msg_id, str(value)) - sect.append(Table(children=lines, cols=2, rheaders=1)) - -def report_messages_by_module_stats(sect, stats, _): - """make errors / warnings by modules report""" - if len(stats['by_module']) == 1: - # don't print this report when we are analysing a single module - raise EmptyReport() - by_mod = {} - for m_type in ('fatal', 'error', 'warning', 'refactor', 'convention'): - total = stats[m_type] - for module in stats['by_module'].iterkeys(): - mod_total = stats['by_module'][module][m_type] - if total == 0: - percent = 0 - else: - percent = float((mod_total)*100) / total - by_mod.setdefault(module, {})[m_type] = percent - sorted_result = [] - for module, mod_info in by_mod.iteritems(): - sorted_result.append((mod_info['error'], - mod_info['warning'], - mod_info['refactor'], - mod_info['convention'], - module)) - sorted_result.sort() - sorted_result.reverse() - lines = ['module', 'error', 'warning', 'refactor', 'convention'] - for line in sorted_result: - if line[0] == 0 and line[1] == 0: - break - lines.append(line[-1]) - for val in line[:-1]: - lines.append('%.2f' % val) - if len(lines) == 5: - raise EmptyReport() - sect.append(Table(children=lines, cols=5, rheaders=1)) - - -# utilities ################################################################### - -# this may help to import modules using gettext -# XXX syt, actually needed since we don't import code? - -from .logilab.common.compat import builtins -builtins._ = str - - -class ArgumentPreprocessingError(Exception): - """Raised if an error occurs during argument preprocessing.""" - - -def preprocess_options(args, search_for): - """look for some options (keys of <search_for>) which have to be processed - before others - - values of <search_for> are callback functions to call when the option is - found - """ - i = 0 - while i < len(args): - arg = args[i] - if arg.startswith('--'): - try: - option, val = arg[2:].split('=', 1) - except ValueError: - option, val = arg[2:], None - try: - cb, takearg = search_for[option] - del args[i] - if takearg and val is None: - if i >= len(args) or args[i].startswith('-'): - raise ArgumentPreprocessingError(arg) - val = args[i] - del args[i] - cb(option, val) - except KeyError: - i += 1 - else: - i += 1 - -class Run: - """helper class to use as main for pylint : - - run(*sys.argv[1:]) - """ - LinterClass = PyLinter - option_groups = ( - ('Commands', 'Options which are actually commands. Options in this \ -group are mutually exclusive.'), - ) - - def __init__(self, args, reporter=None, exit=True): - self._rcfile = None - self._plugins = [] - try: - preprocess_options(args, { - # option: (callback, takearg) - 'rcfile': (self.cb_set_rcfile, True), - 'load-plugins': (self.cb_add_plugins, True), - }) - except ArgumentPreprocessingError, e: - print >> sys.stderr, 'Argument %s expects a value.' % (e.args[0],) - sys.exit(32) - - self.linter = linter = self.LinterClass(( - ('rcfile', - {'action' : 'callback', 'callback' : lambda *args: 1, - 'type': 'string', 'metavar': '<file>', - 'help' : 'Specify a configuration file.'}), - - ('init-hook', - {'action' : 'callback', 'type' : 'string', 'metavar': '<code>', - 'callback' : cb_init_hook, 'level': 1, - 'help' : 'Python code to execute, usually for sys.path \ -manipulation such as pygtk.require().'}), - - ('help-msg', - {'action' : 'callback', 'type' : 'string', 'metavar': '<msg-id>', - 'callback' : self.cb_help_message, - 'group': 'Commands', - 'help' : '''Display a help message for the given message id and \ -exit. The value may be a comma separated list of message ids.'''}), - - ('list-msgs', - {'action' : 'callback', 'metavar': '<msg-id>', - 'callback' : self.cb_list_messages, - 'group': 'Commands', 'level': 1, - 'help' : "Generate pylint's messages."}), - - ('full-documentation', - {'action' : 'callback', 'metavar': '<msg-id>', - 'callback' : self.cb_full_documentation, - 'group': 'Commands', 'level': 1, - 'help' : "Generate pylint's full documentation."}), - - ('generate-rcfile', - {'action' : 'callback', 'callback' : self.cb_generate_config, - 'group': 'Commands', - 'help' : '''Generate a sample configuration file according to \ -the current configuration. You can put other options before this one to get \ -them in the generated configuration.'''}), - - ('generate-man', - {'action' : 'callback', 'callback' : self.cb_generate_manpage, - 'group': 'Commands', - 'help' : "Generate pylint's man page.",'hide': True}), - - ('errors-only', - {'action' : 'callback', 'callback' : self.cb_error_mode, - 'short': 'E', - 'help' : '''In error mode, checkers without error messages are \ -disabled and for others, only the ERROR messages are displayed, and no reports \ -are done by default'''}), - - ('profile', - {'type' : 'yn', 'metavar' : '<y_or_n>', - 'default': False, 'hide': True, - 'help' : 'Profiled execution.'}), - - ), option_groups=self.option_groups, - reporter=reporter, pylintrc=self._rcfile) - # register standard checkers - linter.load_default_plugins() - # load command line plugins - linter.load_plugin_modules(self._plugins) - # add some help section - linter.add_help_section('Environment variables', config.ENV_HELP, level=1) - linter.add_help_section('Output', -'Using the default text output, the message format is : \n' -' \n' -' MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE \n' -' \n' -'There are 5 kind of message types : \n' -' * (C) convention, for programming standard violation \n' -' * (R) refactor, for bad code smell \n' -' * (W) warning, for python specific problems \n' -' * (E) error, for probable bugs in the code \n' -' * (F) fatal, if an error occurred which prevented pylint from doing further\n' -'processing.\n' - , level=1) - linter.add_help_section('Output status code', -'Pylint should leave with following status code: \n' -' * 0 if everything went fine \n' -' * 1 if a fatal message was issued \n' -' * 2 if an error message was issued \n' -' * 4 if a warning message was issued \n' -' * 8 if a refactor message was issued \n' -' * 16 if a convention message was issued \n' -' * 32 on usage error \n' -' \n' -'status 1 to 16 will be bit-ORed so you can know which different categories has\n' -'been issued by analysing pylint output status code\n', - level=1) - # read configuration - linter.disable('W0704') - linter.disable('I0020') - linter.disable('I0021') - linter.read_config_file() - # is there some additional plugins in the file configuration, in - config_parser = linter.cfgfile_parser - if config_parser.has_option('MASTER', 'load-plugins'): - plugins = splitstrip(config_parser.get('MASTER', 'load-plugins')) - linter.load_plugin_modules(plugins) - # now we can load file config and command line, plugins (which can - # provide options) have been registered - linter.load_config_file() - if reporter: - # if a custom reporter is provided as argument, it may be overridden - # by file parameters, so re-set it here, but before command line - # parsing so it's still overrideable by command line option - linter.set_reporter(reporter) - try: - args = linter.load_command_line_configuration(args) - except SystemExit, exc: - if exc.code == 2: # bad options - exc.code = 32 - raise - if not args: - print linter.help() - sys.exit(32) - # insert current working directory to the python path to have a correct - # behaviour - linter.prepare_import_path(args) - if self.linter.config.profile: - print >> sys.stderr, '** profiled run' - import cProfile, pstats - cProfile.runctx('linter.check(%r)' % args, globals(), locals(), 'stones.prof' ) - data = pstats.Stats('stones.prof') - data.strip_dirs() - data.sort_stats('time', 'calls') - data.print_stats(30) - else: - linter.check(args) - linter.cleanup_import_path() - if exit: - sys.exit(self.linter.msg_status) - - def cb_set_rcfile(self, name, value): - """callback for option preprocessing (i.e. before optik parsing)""" - self._rcfile = value - - def cb_add_plugins(self, name, value): - """callback for option preprocessing (i.e. before optik parsing)""" - self._plugins.extend(splitstrip(value)) - - def cb_error_mode(self, *args, **kwargs): - """error mode: - * disable all but error messages - * disable the 'miscellaneous' checker which can be safely deactivated in - debug - * disable reports - * do not save execution information - """ - self.linter.error_mode() - - def cb_generate_config(self, *args, **kwargs): - """optik callback for sample config file generation""" - self.linter.generate_config(skipsections=('COMMANDS',)) - sys.exit(0) - - def cb_generate_manpage(self, *args, **kwargs): - """optik callback for sample config file generation""" - from . import __pkginfo__ - self.linter.generate_manpage(__pkginfo__) - sys.exit(0) - - def cb_help_message(self, option, optname, value, parser): - """optik callback for printing some help about a particular message""" - self.linter.help_message(splitstrip(value)) - sys.exit(0) - - def cb_full_documentation(self, option, optname, value, parser): - """optik callback for printing full documentation""" - self.linter.print_full_documentation() - sys.exit(0) - - def cb_list_messages(self, option, optname, value, parser): # FIXME - """optik callback for printing available messages""" - self.linter.list_messages() - sys.exit(0) - -def cb_init_hook(option, optname, value, parser): - """exec arbitrary code to set sys.path for instance""" - exec value - - -if __name__ == '__main__': - Run(sys.argv[1:]) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/__init__.py diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/__init__.py @@ -1,78 +0,0 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""Python Abstract Syntax Tree New Generation - -The aim of this module is to provide a common base representation of -python source code for projects such as pychecker, pyreverse, -pylint... Well, actually the development of this library is essentially -governed by pylint's needs. - -It extends class defined in the python's _ast module with some -additional methods and attributes. Instance attributes are added by a -builder object, which can either generate extended ast (let's call -them astng ;) by visiting an existent ast tree or by inspecting living -object. Methods are added by monkey patching ast classes. - -Main modules are: - -* nodes and scoped_nodes for more information about methods and - attributes added to different node classes - -* the manager contains a high level object to get astng trees from - source files and living objects. It maintains a cache of previously - constructed tree for quick access - -* builder contains the class responsible to build astng trees -""" -__doctype__ = "restructuredtext en" - -import sys -if sys.version_info >= (3, 0): - BUILTINS_MODULE = 'builtins' -else: - BUILTINS_MODULE = '__builtin__' - -# WARNING: internal imports order matters ! - -# make all exception classes accessible from astng package -from .exceptions import * - -# make all node classes accessible from astng package -from .nodes import * - -# trigger extra monkey-patching -from . import inference - -# more stuff available -from . import raw_building -from .bases import YES, Instance, BoundMethod, UnboundMethod -from .node_classes import are_exclusive, unpack_infer -from .scoped_nodes import builtin_lookup - -# make a manager instance (borg) as well as Project and Package classes -# accessible from astng package -from .manager import ASTNGManager, Project -MANAGER = ASTNGManager() -del ASTNGManager - -# load brain plugins -from .brain import py2mechanize -from .brain import py2qt4 -from .brain import py2stdlib diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/__pkginfo__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/__pkginfo__.py @@ -1,52 +0,0 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""logilab.astng packaging information""" - -distname = 'logilab-astng' - -modname = 'astng' -subpackage_of = 'logilab' - -numversion = (0, 24, 2) -version = '.'.join([str(num) for num in numversion]) - -install_requires = ['logilab-common >= 0.53.0'] - -license = 'LGPL' - -author = 'Logilab' -author_email = 'python-projects@lists.logilab.org' -mailinglist = "mailto://%s" % author_email -web = "http://www.logilab.org/project/%s" % distname -ftp = "ftp://ftp.logilab.org/pub/%s" % modname - -description = "rebuild a new abstract syntax tree from Python's ast" - -from os.path import join -include_dirs = ['brain', - join('test', 'regrtest_data'), - join('test', 'data'), join('test', 'data2')] - -classifiers = ["Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: Software Development :: Quality Assurance", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 3", - ] diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/as_string.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/as_string.py @@ -1,427 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""This module renders ASTNG nodes to string representation. - -It will probably not work on bare _ast trees. -""" -import sys - - -INDENT = ' ' # 4 spaces ; keep indentation variable - - -def _import_string(names): - """return a list of (name, asname) formatted as a string""" - _names = [] - for name, asname in names: - if asname is not None: - _names.append('%s as %s' % (name, asname)) - else: - _names.append(name) - return ', '.join(_names) - - -class AsStringVisitor(object): - """Visitor to render an ASTNG node as string """ - - def __call__(self, node): - """Makes this visitor behave as a simple function""" - return node.accept(self) - - def _stmt_list(self, stmts): - """return a list of nodes to string""" - stmts = '\n'.join([nstr for nstr in [n.accept(self) for n in stmts] if nstr]) - return INDENT + stmts.replace('\n', '\n'+INDENT) - - - ## visit_<node> methods ########################################### - - def visit_arguments(self, node): - """return an astng.Function node as string""" - return node.format_args() - - def visit_assattr(self, node): - """return an astng.AssAttr node as string""" - return self.visit_getattr(node) - - def visit_assert(self, node): - """return an astng.Assert node as string""" - if node.fail: - return 'assert %s, %s' % (node.test.accept(self), - node.fail.accept(self)) - return 'assert %s' % node.test.accept(self) - - def visit_assname(self, node): - """return an astng.AssName node as string""" - return node.name - - def visit_assign(self, node): - """return an astng.Assign node as string""" - lhs = ' = '.join([n.accept(self) for n in node.targets]) - return '%s = %s' % (lhs, node.value.accept(self)) - - def visit_augassign(self, node): - """return an astng.AugAssign node as string""" - return '%s %s %s' % (node.target.accept(self), node.op, node.value.accept(self)) - - def visit_backquote(self, node): - """return an astng.Backquote node as string""" - return '`%s`' % node.value.accept(self) - - def visit_binop(self, node): - """return an astng.BinOp node as string""" - return '(%s) %s (%s)' % (node.left.accept(self), node.op, node.right.accept(self)) - - def visit_boolop(self, node): - """return an astng.BoolOp node as string""" - return (' %s ' % node.op).join(['(%s)' % n.accept(self) - for n in node.values]) - - def visit_break(self, node): - """return an astng.Break node as string""" - return 'break' - - def visit_callfunc(self, node): - """return an astng.CallFunc node as string""" - expr_str = node.func.accept(self) - args = [arg.accept(self) for arg in node.args] - if node.starargs: - args.append( '*' + node.starargs.accept(self)) - if node.kwargs: - args.append( '**' + node.kwargs.accept(self)) - return '%s(%s)' % (expr_str, ', '.join(args)) - - def visit_class(self, node): - """return an astng.Class node as string""" - decorate = node.decorators and node.decorators.accept(self) or '' - bases = ', '.join([n.accept(self) for n in node.bases]) - bases = bases and '(%s)' % bases or '' - docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' - return '\n\n%sclass %s%s:%s\n%s\n' % (decorate, node.name, bases, docs, - self._stmt_list( node.body)) - - def visit_compare(self, node): - """return an astng.Compare node as string""" - rhs_str = ' '.join(['%s %s' % (op, expr.accept(self)) - for op, expr in node.ops]) - return '%s %s' % (node.left.accept(self), rhs_str) - - def visit_comprehension(self, node): - """return an astng.Comprehension node as string""" - ifs = ''.join([ ' if %s' % n.accept(self) for n in node.ifs]) - return 'for %s in %s%s' % (node.target.accept(self), - node.iter.accept(self), ifs ) - - def visit_const(self, node): - """return an astng.Const node as string""" - return repr(node.value) - - def visit_continue(self, node): - """return an astng.Continue node as string""" - return 'continue' - - def visit_delete(self, node): # XXX check if correct - """return an astng.Delete node as string""" - return 'del %s' % ', '.join([child.accept(self) - for child in node.targets]) - - def visit_delattr(self, node): - """return an astng.DelAttr node as string""" - return self.visit_getattr(node) - - def visit_delname(self, node): - """return an astng.DelName node as string""" - return node.name - - def visit_decorators(self, node): - """return an astng.Decorators node as string""" - return '@%s\n' % '\n@'.join([item.accept(self) for item in node.nodes]) - - def visit_dict(self, node): - """return an astng.Dict node as string""" - return '{%s}' % ', '.join(['%s: %s' % (key.accept(self), - value.accept(self)) for key, value in node.items]) - - def visit_dictcomp(self, node): - """return an astng.DictComp node as string""" - return '{%s: %s %s}' % (node.key.accept(self), node.value.accept(self), - ' '.join([n.accept(self) for n in node.generators])) - - def visit_discard(self, node): - """return an astng.Discard node as string""" - return node.value.accept(self) - - def visit_emptynode(self, node): - """dummy method for visiting an Empty node""" - return '' - - def visit_excepthandler(self, node): - if node.type: - if node.name: - excs = 'except %s, %s' % (node.type.accept(self), - node.name.accept(self)) - else: - excs = 'except %s' % node.type.accept(self) - else: - excs = 'except' - return '%s:\n%s' % (excs, self._stmt_list(node.body)) - - def visit_ellipsis(self, node): - """return an astng.Ellipsis node as string""" - return '...' - - def visit_empty(self, node): - """return an Empty node as string""" - return '' - - def visit_exec(self, node): - """return an astng.Exec node as string""" - if node.locals: - return 'exec %s in %s, %s' % (node.expr.accept(self), - node.locals.accept(self), - node.globals.accept(self)) - if node.globals: - return 'exec %s in %s' % (node.expr.accept(self), - node.globals.accept(self)) - return 'exec %s' % node.expr.accept(self) - - def visit_extslice(self, node): - """return an astng.ExtSlice node as string""" - return ','.join( [dim.accept(self) for dim in node.dims] ) - - def visit_for(self, node): - """return an astng.For node as string""" - fors = 'for %s in %s:\n%s' % (node.target.accept(self), - node.iter.accept(self), - self._stmt_list( node.body)) - if node.orelse: - fors = '%s\nelse:\n%s' % (fors, self._stmt_list(node.orelse)) - return fors - - def visit_from(self, node): - """return an astng.From node as string""" - return 'from %s import %s' % ('.' * (node.level or 0) + node.modname, - _import_string(node.names)) - - def visit_function(self, node): - """return an astng.Function node as string""" - decorate = node.decorators and node.decorators.accept(self) or '' - docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' - return '\n%sdef %s(%s):%s\n%s' % (decorate, node.name, node.args.accept(self), - docs, self._stmt_list(node.body)) - - def visit_genexpr(self, node): - """return an astng.GenExpr node as string""" - return '(%s %s)' % (node.elt.accept(self), ' '.join([n.accept(self) - for n in node.generators])) - - def visit_getattr(self, node): - """return an astng.Getattr node as string""" - return '%s.%s' % (node.expr.accept(self), node.attrname) - - def visit_global(self, node): - """return an astng.Global node as string""" - return 'global %s' % ', '.join(node.names) - - def visit_if(self, node): - """return an astng.If node as string""" - ifs = ['if %s:\n%s' % (node.test.accept(self), self._stmt_list(node.body))] - if node.orelse:# XXX use elif ??? - ifs.append('else:\n%s' % self._stmt_list(node.orelse)) - return '\n'.join(ifs) - - def visit_ifexp(self, node): - """return an astng.IfExp node as string""" - return '%s if %s else %s' % (node.body.accept(self), - node.test.accept(self), node.orelse.accept(self)) - - def visit_import(self, node): - """return an astng.Import node as string""" - return 'import %s' % _import_string(node.names) - - def visit_keyword(self, node): - """return an astng.Keyword node as string""" - return '%s=%s' % (node.arg, node.value.accept(self)) - - def visit_lambda(self, node): - """return an astng.Lambda node as string""" - return 'lambda %s: %s' % (node.args.accept(self), node.body.accept(self)) - - def visit_list(self, node): - """return an astng.List node as string""" - return '[%s]' % ', '.join([child.accept(self) for child in node.elts]) - - def visit_listcomp(self, node): - """return an astng.ListComp node as string""" - return '[%s %s]' % (node.elt.accept(self), ' '.join([n.accept(self) - for n in node.generators])) - - def visit_module(self, node): - """return an astng.Module node as string""" - docs = node.doc and '"""%s"""\n\n' % node.doc or '' - return docs + '\n'.join([n.accept(self) for n in node.body]) + '\n\n' - - def visit_name(self, node): - """return an astng.Name node as string""" - return node.name - - def visit_pass(self, node): - """return an astng.Pass node as string""" - return 'pass' - - def visit_print(self, node): - """return an astng.Print node as string""" - nodes = ', '.join([n.accept(self) for n in node.values]) - if not node.nl: - nodes = '%s,' % nodes - if node.dest: - return 'print >> %s, %s' % (node.dest.accept(self), nodes) - return 'print %s' % nodes - - def visit_raise(self, node): - """return an astng.Raise node as string""" - if node.exc: - if node.inst: - if node.tback: - return 'raise %s, %s, %s' % (node.exc.accept(self), - node.inst.accept(self), - node.tback.accept(self)) - return 'raise %s, %s' % (node.exc.accept(self), - node.inst.accept(self)) - return 'raise %s' % node.exc.accept(self) - return 'raise' - - def visit_return(self, node): - """return an astng.Return node as string""" - if node.value: - return 'return %s' % node.value.accept(self) - else: - return 'return' - - def visit_index(self, node): - """return a astng.Index node as string""" - return node.value.accept(self) - - def visit_set(self, node): - """return an astng.Set node as string""" - return '{%s}' % ', '.join([child.accept(self) for child in node.elts]) - - def visit_setcomp(self, node): - """return an astng.SetComp node as string""" - return '{%s %s}' % (node.elt.accept(self), ' '.join([n.accept(self) - for n in node.generators])) - - def visit_slice(self, node): - """return a astng.Slice node as string""" - lower = node.lower and node.lower.accept(self) or '' - upper = node.upper and node.upper.accept(self) or '' - step = node.step and node.step.accept(self) or '' - if step: - return '%s:%s:%s' % (lower, upper, step) - return '%s:%s' % (lower, upper) - - def visit_subscript(self, node): - """return an astng.Subscript node as string""" - return '%s[%s]' % (node.value.accept(self), node.slice.accept(self)) - - def visit_tryexcept(self, node): - """return an astng.TryExcept node as string""" - trys = ['try:\n%s' % self._stmt_list( node.body)] - for handler in node.handlers: - trys.append(handler.accept(self)) - if node.orelse: - trys.append('else:\n%s' % self._stmt_list(node.orelse)) - return '\n'.join(trys) - - def visit_tryfinally(self, node): - """return an astng.TryFinally node as string""" - return 'try:\n%s\nfinally:\n%s' % (self._stmt_list( node.body), - self._stmt_list(node.finalbody)) - - def visit_tuple(self, node): - """return an astng.Tuple node as string""" - return '(%s)' % ', '.join([child.accept(self) for child in node.elts]) - - def visit_unaryop(self, node): - """return an astng.UnaryOp node as string""" - if node.op == 'not': - operator = 'not ' - else: - operator = node.op - return '%s%s' % (operator, node.operand.accept(self)) - - def visit_while(self, node): - """return an astng.While node as string""" - whiles = 'while %s:\n%s' % (node.test.accept(self), - self._stmt_list(node.body)) - if node.orelse: - whiles = '%s\nelse:\n%s' % (whiles, self._stmt_list(node.orelse)) - return whiles - - def visit_with(self, node): # 'with' without 'as' is possible - """return an astng.With node as string""" - as_var = node.vars and " as (%s)" % (node.vars.accept(self)) or "" - withs = 'with (%s)%s:\n%s' % (node.expr.accept(self), as_var, - self._stmt_list( node.body)) - return withs - - def visit_yield(self, node): - """yield an ast.Yield node as string""" - yi_val = node.value and (" " + node.value.accept(self)) or "" - return 'yield' + yi_val - - -class AsStringVisitor3k(AsStringVisitor): - """AsStringVisitor3k overwrites some AsStringVisitor methods""" - - def visit_excepthandler(self, node): - if node.type: - if node.name: - excs = 'except %s as %s' % (node.type.accept(self), - node.name.accept(self)) - else: - excs = 'except %s' % node.type.accept(self) - else: - excs = 'except' - return '%s:\n%s' % (excs, self._stmt_list(node.body)) - - def visit_nonlocal(self, node): - """return an astng.Nonlocal node as string""" - return 'nonlocal %s' % ', '.join(node.names) - - def visit_raise(self, node): - """return an astng.Raise node as string""" - if node.exc: - if node.cause: - return 'raise %s from %s' % (node.exc.accept(self), - node.cause.accept(self)) - return 'raise %s' % node.exc.accept(self) - return 'raise' - - def visit_starred(self, node): - """return Starred node as string""" - return "*" + node.value.accept(self) - -if sys.version_info >= (3, 0): - AsStringVisitor = AsStringVisitor3k - -# this visitor is stateless, thus it can be reused -as_string = AsStringVisitor() - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/bases.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/bases.py @@ -1,631 +0,0 @@ -# -*- coding: utf-8 -*- -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""This module contains base classes and functions for the nodes and some -inference utils. -""" - -__docformat__ = "restructuredtext en" - -from contextlib import contextmanager - -from ..common.compat import builtins - -from . import BUILTINS_MODULE -from .exceptions import InferenceError, ASTNGError, \ - NotFoundError, UnresolvableName -from .as_string import as_string - -BUILTINS_NAME = builtins.__name__ - -class Proxy(object): - """a simple proxy object""" - _proxied = None - - def __init__(self, proxied=None): - if proxied is not None: - self._proxied = proxied - - def __getattr__(self, name): - if name == '_proxied': - return getattr(self.__class__, '_proxied') - if name in self.__dict__: - return self.__dict__[name] - return getattr(self._proxied, name) - - def infer(self, context=None): - yield self - - -# Inference ################################################################## - -class InferenceContext(object): - __slots__ = ('path', 'lookupname', 'callcontext', 'boundnode') - - def __init__(self, path=None): - if path is None: - self.path = set() - else: - self.path = path - self.lookupname = None - self.callcontext = None - self.boundnode = None - - def push(self, node): - name = self.lookupname - if (node, name) in self.path: - raise StopIteration() - self.path.add( (node, name) ) - - def clone(self): - # XXX copy lookupname/callcontext ? - clone = InferenceContext(self.path) - clone.callcontext = self.callcontext - clone.boundnode = self.boundnode - return clone - - @contextmanager - def restore_path(self): - path = set(self.path) - yield - self.path = path - -def copy_context(context): - if context is not None: - return context.clone() - else: - return InferenceContext() - - -def _infer_stmts(stmts, context, frame=None): - """return an iterator on statements inferred by each statement in <stmts> - """ - stmt = None - infered = False - if context is not None: - name = context.lookupname - context = context.clone() - else: - name = None - context = InferenceContext() - for stmt in stmts: - if stmt is YES: - yield stmt - infered = True - continue - context.lookupname = stmt._infer_name(frame, name) - try: - for infered in stmt.infer(context): - yield infered - infered = True - except UnresolvableName: - continue - except InferenceError: - yield YES - infered = True - if not infered: - raise InferenceError(str(stmt)) - - -# special inference objects (e.g. may be returned as nodes by .infer()) ####### - -class _Yes(object): - """a yes object""" - def __repr__(self): - return 'YES' - def __getattribute__(self, name): - if name == 'next': - raise AttributeError('next method should not be called') - if name.startswith('__') and name.endswith('__'): - # to avoid inspection pb - return super(_Yes, self).__getattribute__(name) - return self - def __call__(self, *args, **kwargs): - return self - - -YES = _Yes() - - -class Instance(Proxy): - """a special node representing a class instance""" - def getattr(self, name, context=None, lookupclass=True): - try: - values = self._proxied.instance_attr(name, context) - except NotFoundError: - if name == '__class__': - return [self._proxied] - if lookupclass: - # class attributes not available through the instance - # unless they are explicitly defined - if name in ('__name__', '__bases__', '__mro__', '__subclasses__'): - return self._proxied.local_attr(name) - return self._proxied.getattr(name, context) - raise NotFoundError(name) - # since we've no context information, return matching class members as - # well - if lookupclass: - try: - return values + self._proxied.getattr(name, context) - except NotFoundError: - pass - return values - - def igetattr(self, name, context=None): - """inferred getattr""" - try: - # XXX frame should be self._proxied, or not ? - get_attr = self.getattr(name, context, lookupclass=False) - return _infer_stmts(self._wrap_attr(get_attr, context), context, - frame=self) - except NotFoundError: - try: - # fallback to class'igetattr since it has some logic to handle - # descriptors - return self._wrap_attr(self._proxied.igetattr(name, context), - context) - except NotFoundError: - raise InferenceError(name) - - def _wrap_attr(self, attrs, context=None): - """wrap bound methods of attrs in a InstanceMethod proxies""" - for attr in attrs: - if isinstance(attr, UnboundMethod): - if BUILTINS_NAME + '.property' in attr.decoratornames(): - for infered in attr.infer_call_result(self, context): - yield infered - else: - yield BoundMethod(attr, self) - else: - yield attr - - def infer_call_result(self, caller, context=None): - """infer what a class instance is returning when called""" - infered = False - for node in self._proxied.igetattr('__call__', context): - for res in node.infer_call_result(caller, context): - infered = True - yield res - if not infered: - raise InferenceError() - - def __repr__(self): - return '<Instance of %s.%s at 0x%s>' % (self._proxied.root().name, - self._proxied.name, - id(self)) - def __str__(self): - return 'Instance of %s.%s' % (self._proxied.root().name, - self._proxied.name) - - def callable(self): - try: - self._proxied.getattr('__call__') - return True - except NotFoundError: - return False - - def pytype(self): - return self._proxied.qname() - - def display_type(self): - return 'Instance of' - - -class UnboundMethod(Proxy): - """a special node representing a method not bound to an instance""" - def __repr__(self): - frame = self._proxied.parent.frame() - return '<%s %s of %s at 0x%s' % (self.__class__.__name__, - self._proxied.name, - frame.qname(), id(self)) - - def is_bound(self): - return False - - def getattr(self, name, context=None): - if name == 'im_func': - return [self._proxied] - return super(UnboundMethod, self).getattr(name, context) - - def igetattr(self, name, context=None): - if name == 'im_func': - return iter((self._proxied,)) - return super(UnboundMethod, self).igetattr(name, context) - - def infer_call_result(self, caller, context): - # If we're unbound method __new__ of builtin object, the result is an - # instance of the class given as first argument. - if (self._proxied.name == '__new__' and - self._proxied.parent.frame().qname() == '%s.object' % BUILTINS_MODULE): - return (x is YES and x or Instance(x) for x in caller.args[0].infer()) - return self._proxied.infer_call_result(caller, context) - - -class BoundMethod(UnboundMethod): - """a special node representing a method bound to an instance""" - def __init__(self, proxy, bound): - UnboundMethod.__init__(self, proxy) - self.bound = bound - - def is_bound(self): - return True - - def infer_call_result(self, caller, context): - context = context.clone() - context.boundnode = self.bound - return self._proxied.infer_call_result(caller, context) - - -class Generator(Instance): - """a special node representing a generator""" - def callable(self): - return True - - def pytype(self): - return '%s.generator' % BUILTINS_MODULE - - def display_type(self): - return 'Generator' - - def __repr__(self): - return '<Generator(%s) l.%s at 0x%s>' % (self._proxied.name, self.lineno, id(self)) - - def __str__(self): - return 'Generator(%s)' % (self._proxied.name) - - -# decorators ################################################################## - -def path_wrapper(func): - """return the given infer function wrapped to handle the path""" - def wrapped(node, context=None, _func=func, **kwargs): - """wrapper function handling context""" - if context is None: - context = InferenceContext() - context.push(node) - yielded = set() - for res in _func(node, context, **kwargs): - # unproxy only true instance, not const, tuple, dict... - if res.__class__ is Instance: - ares = res._proxied - else: - ares = res - if not ares in yielded: - yield res - yielded.add(ares) - return wrapped - -def yes_if_nothing_infered(func): - def wrapper(*args, **kwargs): - infered = False - for node in func(*args, **kwargs): - infered = True - yield node - if not infered: - yield YES - return wrapper - -def raise_if_nothing_infered(func): - def wrapper(*args, **kwargs): - infered = False - for node in func(*args, **kwargs): - infered = True - yield node - if not infered: - raise InferenceError() - return wrapper - - -# Node ###################################################################### - -class NodeNG(object): - """Base Class for all ASTNG node classes. - - It represents a node of the new abstract syntax tree. - """ - is_statement = False - optional_assign = False # True for For (and for Comprehension if py <3.0) - is_function = False # True for Function nodes - # attributes below are set by the builder module or by raw factories - lineno = None - fromlineno = None - tolineno = None - col_offset = None - # parent node in the tree - parent = None - # attributes containing child node(s) redefined in most concrete classes: - _astng_fields = () - - def _repr_name(self): - """return self.name or self.attrname or '' for nice representation""" - return getattr(self, 'name', getattr(self, 'attrname', '')) - - def __str__(self): - return '%s(%s)' % (self.__class__.__name__, self._repr_name()) - - def __repr__(self): - return '<%s(%s) l.%s [%s] at Ox%x>' % (self.__class__.__name__, - self._repr_name(), - self.fromlineno, - self.root().name, - id(self)) - - - def accept(self, visitor): - klass = self.__class__.__name__ - func = getattr(visitor, "visit_" + self.__class__.__name__.lower()) - return func(self) - - def get_children(self): - for field in self._astng_fields: - attr = getattr(self, field) - if attr is None: - continue - if isinstance(attr, (list, tuple)): - for elt in attr: - yield elt - else: - yield attr - - def last_child(self): - """an optimized version of list(get_children())[-1]""" - for field in self._astng_fields[::-1]: - attr = getattr(self, field) - if not attr: # None or empty listy / tuple - continue - if isinstance(attr, (list, tuple)): - return attr[-1] - else: - return attr - return None - - def parent_of(self, node): - """return true if i'm a parent of the given node""" - parent = node.parent - while parent is not None: - if self is parent: - return True - parent = parent.parent - return False - - def statement(self): - """return the first parent node marked as statement node""" - if self.is_statement: - return self - return self.parent.statement() - - def frame(self): - """return the first parent frame node (i.e. Module, Function or Class) - """ - return self.parent.frame() - - def scope(self): - """return the first node defining a new scope (i.e. Module, Function, - Class, Lambda but also GenExpr) - """ - return self.parent.scope() - - def root(self): - """return the root node of the tree, (i.e. a Module)""" - if self.parent: - return self.parent.root() - return self - - def child_sequence(self, child): - """search for the right sequence where the child lies in""" - for field in self._astng_fields: - node_or_sequence = getattr(self, field) - if node_or_sequence is child: - return [node_or_sequence] - # /!\ compiler.ast Nodes have an __iter__ walking over child nodes - if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence: - return node_or_sequence - else: - msg = 'Could not found %s in %s\'s children' - raise ASTNGError(msg % (repr(child), repr(self))) - - def locate_child(self, child): - """return a 2-uple (child attribute name, sequence or node)""" - for field in self._astng_fields: - node_or_sequence = getattr(self, field) - # /!\ compiler.ast Nodes have an __iter__ walking over child nodes - if child is node_or_sequence: - return field, child - if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence: - return field, node_or_sequence - msg = 'Could not found %s in %s\'s children' - raise ASTNGError(msg % (repr(child), repr(self))) - # FIXME : should we merge child_sequence and locate_child ? locate_child - # is only used in are_exclusive, child_sequence one time in pylint. - - def next_sibling(self): - """return the next sibling statement""" - return self.parent.next_sibling() - - def previous_sibling(self): - """return the previous sibling statement""" - return self.parent.previous_sibling() - - def nearest(self, nodes): - """return the node which is the nearest before this one in the - given list of nodes - """ - myroot = self.root() - mylineno = self.fromlineno - nearest = None, 0 - for node in nodes: - assert node.root() is myroot, \ - 'nodes %s and %s are not from the same module' % (self, node) - lineno = node.fromlineno - if node.fromlineno > mylineno: - break - if lineno > nearest[1]: - nearest = node, lineno - # FIXME: raise an exception if nearest is None ? - return nearest[0] - - def set_line_info(self, lastchild): - if self.lineno is None: - self.fromlineno = self._fixed_source_line() - else: - self.fromlineno = self.lineno - if lastchild is None: - self.tolineno = self.fromlineno - else: - self.tolineno = lastchild.tolineno - return - # TODO / FIXME: - assert self.fromlineno is not None, self - assert self.tolineno is not None, self - - def _fixed_source_line(self): - """return the line number where the given node appears - - we need this method since not all nodes have the lineno attribute - correctly set... - """ - line = self.lineno - _node = self - try: - while line is None: - _node = _node.get_children().next() - line = _node.lineno - except StopIteration: - _node = self.parent - while _node and line is None: - line = _node.lineno - _node = _node.parent - return line - - def block_range(self, lineno): - """handle block line numbers range for non block opening statements - """ - return lineno, self.tolineno - - def set_local(self, name, stmt): - """delegate to a scoped parent handling a locals dictionary""" - self.parent.set_local(name, stmt) - - def nodes_of_class(self, klass, skip_klass=None): - """return an iterator on nodes which are instance of the given class(es) - - klass may be a class object or a tuple of class objects - """ - if isinstance(self, klass): - yield self - for child_node in self.get_children(): - if skip_klass is not None and isinstance(child_node, skip_klass): - continue - for matching in child_node.nodes_of_class(klass, skip_klass): - yield matching - - def _infer_name(self, frame, name): - # overridden for From, Import, Global, TryExcept and Arguments - return None - - def infer(self, context=None): - """we don't know how to resolve a statement by default""" - # this method is overridden by most concrete classes - raise InferenceError(self.__class__.__name__) - - def infered(self): - '''return list of infered values for a more simple inference usage''' - return list(self.infer()) - - def instanciate_class(self): - """instanciate a node if it is a Class node, else return self""" - return self - - def has_base(self, node): - return False - - def callable(self): - return False - - def eq(self, value): - return False - - def as_string(self): - return as_string(self) - - def repr_tree(self, ids=False): - """print a nice astng tree representation. - - :param ids: if true, we also print the ids (usefull for debugging)""" - result = [] - _repr_tree(self, result, ids=ids) - return "\n".join(result) - - -class Statement(NodeNG): - """Statement node adding a few attributes""" - is_statement = True - - def next_sibling(self): - """return the next sibling statement""" - stmts = self.parent.child_sequence(self) - index = stmts.index(self) - try: - return stmts[index +1] - except IndexError: - pass - - def previous_sibling(self): - """return the previous sibling statement""" - stmts = self.parent.child_sequence(self) - index = stmts.index(self) - if index >= 1: - return stmts[index -1] - -INDENT = " " - -def _repr_tree(node, result, indent='', _done=None, ids=False): - """built a tree representation of a node as a list of lines""" - if _done is None: - _done = set() - if not hasattr(node, '_astng_fields'): # not a astng node - return - if node in _done: - result.append( indent + 'loop in tree: %s' % node ) - return - _done.add(node) - node_str = str(node) - if ids: - node_str += ' . \t%x' % id(node) - result.append( indent + node_str ) - indent += INDENT - for field in node._astng_fields: - value = getattr(node, field) - if isinstance(value, (list, tuple) ): - result.append( indent + field + " = [" ) - for child in value: - if isinstance(child, (list, tuple) ): - # special case for Dict # FIXME - _repr_tree(child[0], result, indent, _done, ids) - _repr_tree(child[1], result, indent, _done, ids) - result.append(indent + ',') - else: - _repr_tree(child, result, indent, _done, ids) - result.append( indent + "]" ) - else: - result.append( indent + field + " = " ) - _repr_tree(value, result, indent, _done, ids) - - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/__init__.py diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2mechanize.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2mechanize.py @@ -1,20 +0,0 @@ -from .. import MANAGER -from ..builder import ASTNGBuilder - -def mechanize_transform(module): - fake = ASTNGBuilder(MANAGER).string_build(''' - -class Browser(object): - def open(self, url, data=None, timeout=None): - return None - def open_novisit(self, url, data=None, timeout=None): - return None - def open_local_file(self, filename): - return None - -''') - module.locals['Browser'] = fake.locals['Browser'] - -import py2stdlib -py2stdlib.MODULE_TRANSFORMS['mechanize'] = mechanize_transform - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2qt4.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2qt4.py @@ -1,25 +0,0 @@ -"""ASTNG hooks for the Python 2 qt4 module. - -Currently help understanding of : - -* PyQT4.QtCore -""" - -from .. import MANAGER -from ..builder import ASTNGBuilder - - -def pyqt4_qtcore_transform(module): - fake = ASTNGBuilder(MANAGER).string_build(''' - -def SIGNAL(signal_name): pass - -class QObject(object): - def emit(self, signal): pass -''') - for klass in ('QObject',): - module.locals[klass] = fake.locals[klass] - - -import py2stdlib -py2stdlib.MODULE_TRANSFORMS['PyQt4.QtCore'] = pyqt4_qtcore_transform diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2stdlib.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/brain/py2stdlib.py @@ -1,176 +0,0 @@ -"""ASTNG hooks for the Python 2 standard library. - -Currently help understanding of : - -* hashlib.md5 and hashlib.sha1 -""" - -from .. import MANAGER -from ..builder import ASTNGBuilder - -MODULE_TRANSFORMS = {} - -def hashlib_transform(module): - fake = ASTNGBuilder(MANAGER).string_build(''' - -class md5(object): - def __init__(self, value): pass - def hexdigest(self): - return u'' - -class sha1(object): - def __init__(self, value): pass - def hexdigest(self): - return u'' - -''') - for hashfunc in ('sha1', 'md5'): - module.locals[hashfunc] = fake.locals[hashfunc] - -def collections_transform(module): - fake = ASTNGBuilder(MANAGER).string_build(''' - -class defaultdict(dict): - default_factory = None - def __missing__(self, key): pass - -class deque(object): - maxlen = 0 - def __init__(iterable=None, maxlen=None): pass - def append(self, x): pass - def appendleft(self, x): pass - def clear(self): pass - def count(self, x): return 0 - def extend(self, iterable): pass - def extendleft(self, iterable): pass - def pop(self): pass - def popleft(self): pass - def remove(self, value): pass - def reverse(self): pass - def rotate(self, n): pass - -''') - - for klass in ('deque', 'defaultdict'): - module.locals[klass] = fake.locals[klass] - -def pkg_resources_transform(module): - fake = ASTNGBuilder(MANAGER).string_build(''' - -def resource_exists(package_or_requirement, resource_name): - pass - -def resource_isdir(package_or_requirement, resource_name): - pass - -def resource_filename(package_or_requirement, resource_name): - pass - -def resource_stream(package_or_requirement, resource_name): - pass - -def resource_string(package_or_requirement, resource_name): - pass - -def resource_listdir(package_or_requirement, resource_name): - pass - -def extraction_error(): - pass - -def get_cache_path(archive_name, names=()): - pass - -def postprocess(tempname, filename): - pass - -def set_extraction_path(path): - pass - -def cleanup_resources(force=False): - pass - -''') - - for func_name, func in fake.locals.items(): - module.locals[func_name] = func - - -def urlparse_transform(module): - fake = ASTNGBuilder(MANAGER).string_build(''' - -def urlparse(urlstring, default_scheme='', allow_fragments=True): - return ParseResult() - -class ParseResult(object): - def __init__(self): - self.scheme = '' - self.netloc = '' - self.path = '' - self.params = '' - self.query = '' - self.fragment = '' - self.username = None - self.password = None - self.hostname = None - self.port = None - - def geturl(self): - return '' -''') - - for func_name, func in fake.locals.items(): - module.locals[func_name] = func - -def subprocess_transform(module): - fake = ASTNGBuilder(MANAGER).string_build(''' - -class Popen(object): - returncode = pid = 0 - stdin = stdout = stderr = file() - - def __init__(self, args, bufsize=0, executable=None, - stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=False, shell=False, - cwd=None, env=None, universal_newlines=False, - startupinfo=None, creationflags=0): - pass - - def communicate(self, input=None): - return ('string', 'string') - def wait(self): - return self.returncode - def poll(self): - return self.returncode - def send_signal(self, signal): - pass - def terminate(self): - pass - def kill(self): - pass - ''') - - for func_name, func in fake.locals.items(): - module.locals[func_name] = func - - - -MODULE_TRANSFORMS['hashlib'] = hashlib_transform -MODULE_TRANSFORMS['collections'] = collections_transform -MODULE_TRANSFORMS['pkg_resources'] = pkg_resources_transform -MODULE_TRANSFORMS['urlparse'] = urlparse_transform -MODULE_TRANSFORMS['subprocess'] = subprocess_transform - - -def transform(module): - try: - tr = MODULE_TRANSFORMS[module.name] - except KeyError: - pass - else: - tr(module) - -from .. import MANAGER -MANAGER.register_transformer(transform) - - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/builder.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/builder.py @@ -1,226 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""The ASTNGBuilder makes astng from living object and / or from _ast - -The builder is not thread safe and can't be used to parse different sources -at the same time. -""" - -__docformat__ = "restructuredtext en" - -import sys, re -from os.path import splitext, basename, dirname, exists, abspath - -from ..common.modutils import modpath_from_file - -from .exceptions import ASTNGBuildingException, InferenceError -from .raw_building import InspectBuilder -from .rebuilder import TreeRebuilder -from .manager import ASTNGManager -from .bases import YES, Instance - -from _ast import PyCF_ONLY_AST -def parse(string): - return compile(string, "<string>", 'exec', PyCF_ONLY_AST) - -if sys.version_info >= (3, 0): - from tokenize import detect_encoding - - def open_source_file(filename): - byte_stream = open(filename, 'bU') - encoding = detect_encoding(byte_stream.readline)[0] - stream = open(filename, 'U', encoding=encoding) - try: - data = stream.read() - except UnicodeError, uex: # wrong encodingg - # detect_encoding returns utf-8 if no encoding specified - msg = 'Wrong (%s) or no encoding specified' % encoding - raise ASTNGBuildingException(msg) - return stream, encoding, data - -else: - import re - - _ENCODING_RGX = re.compile("\s*#+.*coding[:=]\s*([-\w.]+)") - - def _guess_encoding(string): - """get encoding from a python file as string or return None if not found - """ - # check for UTF-8 byte-order mark - if string.startswith('\xef\xbb\xbf'): - return 'UTF-8' - for line in string.split('\n', 2)[:2]: - # check for encoding declaration - match = _ENCODING_RGX.match(line) - if match is not None: - return match.group(1) - - def open_source_file(filename): - """get data for parsing a file""" - stream = open(filename, 'U') - data = stream.read() - encoding = _guess_encoding(data) - return stream, encoding, data - -# ast NG builder ############################################################## - -MANAGER = ASTNGManager() - -class ASTNGBuilder(InspectBuilder): - """provide astng building methods""" - rebuilder = TreeRebuilder() - - def __init__(self, manager=None): - self._manager = manager or MANAGER - - def module_build(self, module, modname=None): - """build an astng from a living module instance - """ - node = None - path = getattr(module, '__file__', None) - if path is not None: - path_, ext = splitext(module.__file__) - if ext in ('.py', '.pyc', '.pyo') and exists(path_ + '.py'): - node = self.file_build(path_ + '.py', modname) - if node is None: - # this is a built-in module - # get a partial representation by introspection - node = self.inspect_build(module, modname=modname, path=path) - return node - - def file_build(self, path, modname=None): - """build astng from a source code file (i.e. from an ast) - - path is expected to be a python source file - """ - try: - stream, encoding, data = open_source_file(path) - except IOError, exc: - msg = 'Unable to load file %r (%s)' % (path, exc) - raise ASTNGBuildingException(msg) - except SyntaxError, exc: # py3k encoding specification error - raise ASTNGBuildingException(exc) - except LookupError, exc: # unknown encoding - raise ASTNGBuildingException(exc) - # get module name if necessary - if modname is None: - try: - modname = '.'.join(modpath_from_file(path)) - except ImportError: - modname = splitext(basename(path))[0] - # build astng representation - node = self.string_build(data, modname, path) - node.file_encoding = encoding - return node - - def string_build(self, data, modname='', path=None): - """build astng from source code string and return rebuilded astng""" - module = self._data_build(data, modname, path) - self._manager.astng_cache[module.name] = module - # post tree building steps after we stored the module in the cache: - for from_node in module._from_nodes: - self.add_from_names_to_locals(from_node) - # handle delayed assattr nodes - for delayed in module._delayed_assattr: - self.delayed_assattr(delayed) - if modname: - for transformer in self._manager.transformers: - transformer(module) - return module - - def _data_build(self, data, modname, path): - """build tree node from data and add some informations""" - # this method could be wrapped with a pickle/cache function - node = parse(data + '\n') - if path is not None: - node_file = abspath(path) - else: - node_file = '<?>' - if modname.endswith('.__init__'): - modname = modname[:-9] - package = True - else: - package = path and path.find('__init__.py') > -1 or False - self.rebuilder.init() - module = self.rebuilder.visit_module(node, modname, package) - module.file = module.path = node_file - module._from_nodes = self.rebuilder._from_nodes - module._delayed_assattr = self.rebuilder._delayed_assattr - return module - - def add_from_names_to_locals(self, node): - """store imported names to the locals; - resort the locals if coming from a delayed node - """ - - _key_func = lambda node: node.fromlineno - def sort_locals(my_list): - my_list.sort(key=_key_func) - for (name, asname) in node.names: - if name == '*': - try: - imported = node.root().import_module(node.modname) - except ASTNGBuildingException: - continue - for name in imported.wildcard_import_names(): - node.parent.set_local(name, node) - sort_locals(node.parent.scope().locals[name]) - else: - node.parent.set_local(asname or name, node) - sort_locals(node.parent.scope().locals[asname or name]) - - def delayed_assattr(self, node): - """visit a AssAttr node -> add name to locals, handle members - definition - """ - try: - frame = node.frame() - for infered in node.expr.infer(): - if infered is YES: - continue - try: - if infered.__class__ is Instance: - infered = infered._proxied - iattrs = infered.instance_attrs - elif isinstance(infered, Instance): - # Const, Tuple, ... we may be wrong, may be not, but - # anyway we don't want to pollute builtin's namespace - continue - elif infered.is_function: - iattrs = infered.instance_attrs - else: - iattrs = infered.locals - except AttributeError: - # XXX log error - #import traceback - #traceback.print_exc() - continue - values = iattrs.setdefault(node.attrname, []) - if node in values: - continue - # get assign in __init__ first XXX useful ? - if frame.name == '__init__' and values and not \ - values[0].frame().name == '__init__': - values.insert(0, node) - else: - values.append(node) - except InferenceError: - pass - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/exceptions.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/exceptions.py @@ -1,60 +0,0 @@ -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""this module contains exceptions used in the astng library - -""" - -__doctype__ = "restructuredtext en" - -class ASTNGError(Exception): - """base exception class for all astng related exceptions""" - -class ASTNGBuildingException(ASTNGError): - """exception class when we are unable to build an astng representation""" - -class ResolveError(ASTNGError): - """base class of astng resolution/inference error""" - -class NotFoundError(ResolveError): - """raised when we are unable to resolve a name""" - -class InferenceError(ResolveError): - """raised when we are unable to infer a node""" - -class UnresolvableName(InferenceError): - """raised when we are unable to resolve a name""" - -class NoDefault(ASTNGError): - """raised by function's `default_value` method when an argument has - no default value - """ - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/inference.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/inference.py @@ -1,383 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""this module contains a set of functions to handle inference on astng trees -""" - -__doctype__ = "restructuredtext en" - -from itertools import chain -import sys - -from . import nodes - -from .manager import ASTNGManager -from .exceptions import (ASTNGBuildingException, ASTNGError, - InferenceError, NoDefault, NotFoundError, UnresolvableName) -from .bases import YES, Instance, InferenceContext, Generator, \ - _infer_stmts, copy_context, path_wrapper, raise_if_nothing_infered -from .protocols import _arguments_infer_argname - -MANAGER = ASTNGManager() - - -class CallContext: - """when inferring a function call, this class is used to remember values - given as argument - """ - def __init__(self, args, starargs, dstarargs): - self.args = [] - self.nargs = {} - for arg in args: - if isinstance(arg, nodes.Keyword): - self.nargs[arg.arg] = arg.value - else: - self.args.append(arg) - self.starargs = starargs - self.dstarargs = dstarargs - - def infer_argument(self, funcnode, name, context): - """infer a function argument value according to the call context""" - # 1. search in named keywords - try: - return self.nargs[name].infer(context) - except KeyError: - # Function.args.args can be None in astng (means that we don't have - # information on argnames) - argindex = funcnode.args.find_argname(name)[0] - if argindex is not None: - # 2. first argument of instance/class method - if argindex == 0 and funcnode.type in ('method', 'classmethod'): - if context.boundnode is not None: - boundnode = context.boundnode - else: - # XXX can do better ? - boundnode = funcnode.parent.frame() - if funcnode.type == 'method': - if not isinstance(boundnode, Instance): - boundnode = Instance(boundnode) - return iter((boundnode,)) - if funcnode.type == 'classmethod': - return iter((boundnode,)) - # 2. search arg index - try: - return self.args[argindex].infer(context) - except IndexError: - pass - # 3. search in *args (.starargs) - if self.starargs is not None: - its = [] - for infered in self.starargs.infer(context): - if infered is YES: - its.append((YES,)) - continue - try: - its.append(infered.getitem(argindex, context).infer(context)) - except (InferenceError, AttributeError): - its.append((YES,)) - except (IndexError, TypeError): - continue - if its: - return chain(*its) - # 4. XXX search in **kwargs (.dstarargs) - if self.dstarargs is not None: - its = [] - for infered in self.dstarargs.infer(context): - if infered is YES: - its.append((YES,)) - continue - try: - its.append(infered.getitem(name, context).infer(context)) - except (InferenceError, AttributeError): - its.append((YES,)) - except (IndexError, TypeError): - continue - if its: - return chain(*its) - # 5. */** argument, (Tuple or Dict) - if name == funcnode.args.vararg: - return iter((nodes.const_factory(()))) - if name == funcnode.args.kwarg: - return iter((nodes.const_factory({}))) - # 6. return default value if any - try: - return funcnode.args.default_value(name).infer(context) - except NoDefault: - raise InferenceError(name) - - -# .infer method ############################################################### - - -def infer_end(self, context=None): - """inference's end for node such as Module, Class, Function, Const... - """ - yield self -nodes.Module.infer = infer_end -nodes.Class.infer = infer_end -nodes.Function.infer = infer_end -nodes.Lambda.infer = infer_end -nodes.Const.infer = infer_end -nodes.List.infer = infer_end -nodes.Tuple.infer = infer_end -nodes.Dict.infer = infer_end - - -def infer_name(self, context=None): - """infer a Name: use name lookup rules""" - frame, stmts = self.lookup(self.name) - if not stmts: - raise UnresolvableName(self.name) - context = context.clone() - context.lookupname = self.name - return _infer_stmts(stmts, context, frame) -nodes.Name.infer = path_wrapper(infer_name) -nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper - - -def infer_callfunc(self, context=None): - """infer a CallFunc node by trying to guess what the function returns""" - callcontext = context.clone() - callcontext.callcontext = CallContext(self.args, self.starargs, self.kwargs) - callcontext.boundnode = None - for callee in self.func.infer(context): - if callee is YES: - yield callee - continue - try: - if hasattr(callee, 'infer_call_result'): - for infered in callee.infer_call_result(self, callcontext): - yield infered - except InferenceError: - ## XXX log error ? - continue -nodes.CallFunc.infer = path_wrapper(raise_if_nothing_infered(infer_callfunc)) - - -def infer_import(self, context=None, asname=True): - """infer an Import node: return the imported module/object""" - name = context.lookupname - if name is None: - raise InferenceError() - if asname: - yield self.do_import_module(self.real_name(name)) - else: - yield self.do_import_module(name) -nodes.Import.infer = path_wrapper(infer_import) - -def infer_name_module(self, name): - context = InferenceContext() - context.lookupname = name - return self.infer(context, asname=False) -nodes.Import.infer_name_module = infer_name_module - - -def infer_from(self, context=None, asname=True): - """infer a From nodes: return the imported module/object""" - name = context.lookupname - if name is None: - raise InferenceError() - if asname: - name = self.real_name(name) - module = self.do_import_module(self.modname) - try: - context = copy_context(context) - context.lookupname = name - return _infer_stmts(module.getattr(name, ignore_locals=module is self.root()), context) - except NotFoundError: - raise InferenceError(name) -nodes.From.infer = path_wrapper(infer_from) - - -def infer_getattr(self, context=None): - """infer a Getattr node by using getattr on the associated object""" - #context = context.clone() - for owner in self.expr.infer(context): - if owner is YES: - yield owner - continue - try: - context.boundnode = owner - for obj in owner.igetattr(self.attrname, context): - yield obj - context.boundnode = None - except (NotFoundError, InferenceError): - context.boundnode = None - except AttributeError: - # XXX method / function - context.boundnode = None -nodes.Getattr.infer = path_wrapper(raise_if_nothing_infered(infer_getattr)) -nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work with a path wrapper - - -def infer_global(self, context=None): - if context.lookupname is None: - raise InferenceError() - try: - return _infer_stmts(self.root().getattr(context.lookupname), context) - except NotFoundError: - raise InferenceError() -nodes.Global.infer = path_wrapper(infer_global) - - -def infer_subscript(self, context=None): - """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]""" - if isinstance(self.slice, nodes.Index): - index = self.slice.value.infer(context).next() - if index is YES: - yield YES - return - try: - # suppose it's a Tuple/List node (attribute error else) - # XXX infer self.value? - assigned = self.value.getitem(index.value, context) - except AttributeError: - raise InferenceError() - except (IndexError, TypeError): - yield YES - return - for infered in assigned.infer(context): - yield infered - else: - raise InferenceError() -nodes.Subscript.infer = path_wrapper(infer_subscript) -nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript) - - -UNARY_OP_METHOD = {'+': '__pos__', - '-': '__neg__', - '~': '__invert__', - 'not': None, # XXX not '__nonzero__' - } - -def infer_unaryop(self, context=None): - for operand in self.operand.infer(context): - try: - yield operand.infer_unary_op(self.op) - except TypeError: - continue - except AttributeError: - meth = UNARY_OP_METHOD[self.op] - if meth is None: - yield YES - else: - try: - # XXX just suppose if the type implement meth, returned type - # will be the same - operand.getattr(meth) - yield operand - except GeneratorExit: - raise - except: - yield YES -nodes.UnaryOp.infer = path_wrapper(infer_unaryop) - - -BIN_OP_METHOD = {'+': '__add__', - '-': '__sub__', - '/': '__div__', - '//': '__floordiv__', - '*': '__mul__', - '**': '__power__', - '%': '__mod__', - '&': '__and__', - '|': '__or__', - '^': '__xor__', - '<<': '__lshift__', - '>>': '__rshift__', - } - -def _infer_binop(operator, operand1, operand2, context, failures=None): - if operand1 is YES: - yield operand1 - return - try: - for valnode in operand1.infer_binary_op(operator, operand2, context): - yield valnode - except AttributeError: - try: - # XXX just suppose if the type implement meth, returned type - # will be the same - operand1.getattr(BIN_OP_METHOD[operator]) - yield operand1 - except: - if failures is None: - yield YES - else: - failures.append(operand1) - -def infer_binop(self, context=None): - failures = [] - for lhs in self.left.infer(context): - for val in _infer_binop(self.op, lhs, self.right, context, failures): - yield val - for lhs in failures: - for rhs in self.right.infer(context): - for val in _infer_binop(self.op, rhs, lhs, context): - yield val -nodes.BinOp.infer = path_wrapper(infer_binop) - - -def infer_arguments(self, context=None): - name = context.lookupname - if name is None: - raise InferenceError() - return _arguments_infer_argname(self, name, context) -nodes.Arguments.infer = infer_arguments - - -def infer_ass(self, context=None): - """infer a AssName/AssAttr: need to inspect the RHS part of the - assign node - """ - stmt = self.statement() - if isinstance(stmt, nodes.AugAssign): - return stmt.infer(context) - stmts = list(self.assigned_stmts(context=context)) - return _infer_stmts(stmts, context) -nodes.AssName.infer = path_wrapper(infer_ass) -nodes.AssAttr.infer = path_wrapper(infer_ass) - -def infer_augassign(self, context=None): - failures = [] - for lhs in self.target.infer_lhs(context): - for val in _infer_binop(self.op, lhs, self.value, context, failures): - yield val - for lhs in failures: - for rhs in self.value.infer(context): - for val in _infer_binop(self.op, rhs, lhs, context): - yield val -nodes.AugAssign.infer = path_wrapper(infer_augassign) - - -# no infer method on DelName and DelAttr (expected InferenceError) - - -def infer_empty_node(self, context=None): - if not self.has_underlying_object(): - yield YES - else: - try: - for infered in MANAGER.infer_astng_from_something(self.object, - context=context): - yield infered - except ASTNGError: - yield YES -nodes.EmptyNode.infer = path_wrapper(infer_empty_node) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/manager.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/manager.py @@ -1,299 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""astng manager: avoid multiple astng build of a same module when -possible by providing a class responsible to get astng representation -from various source and using a cache of built modules) -""" - -__docformat__ = "restructuredtext en" - -import sys -import os -from os.path import dirname, basename, abspath, join, isdir, exists - -from ..common.modutils import NoSourceFile, is_python_source, \ - file_from_modpath, load_module_from_name, modpath_from_file, \ - get_module_files, get_source_file, zipimport -from ..common.configuration import OptionsProviderMixIn - -from .exceptions import ASTNGBuildingException - -def astng_wrapper(func, modname): - """wrapper to give to ASTNGManager.project_from_files""" - print 'parsing %s...' % modname - try: - return func(modname) - except ASTNGBuildingException, exc: - print exc - except Exception, exc: - import traceback - traceback.print_exc() - -def _silent_no_wrap(func, modname): - """silent wrapper that doesn't do anything; can be used for tests""" - return func(modname) - -def safe_repr(obj): - try: - return repr(obj) - except: - return '???' - - - -class ASTNGManager(OptionsProviderMixIn): - """the astng manager, responsible to build astng from files - or modules. - - Use the Borg pattern. - """ - - name = 'astng loader' - options = (("ignore", - {'type' : "csv", 'metavar' : "<file>", - 'dest' : "black_list", "default" : ('CVS',), - 'help' : "add <file> (may be a directory) to the black list\ -. It should be a base name, not a path. You may set this option multiple times\ -."}), - ("project", - {'default': "No Name", 'type' : 'string', 'short': 'p', - 'metavar' : '<project name>', - 'help' : 'set the project name.'}), - ) - brain = {} - def __init__(self): - self.__dict__ = ASTNGManager.brain - if not self.__dict__: - OptionsProviderMixIn.__init__(self) - self.load_defaults() - # NOTE: cache entries are added by the [re]builder - self.astng_cache = {} - self._mod_file_cache = {} - self.transformers = [] - - def astng_from_file(self, filepath, modname=None, fallback=True, source=False): - """given a module name, return the astng object""" - try: - filepath = get_source_file(filepath, include_no_ext=True) - source = True - except NoSourceFile: - pass - if modname is None: - try: - modname = '.'.join(modpath_from_file(filepath)) - except ImportError: - modname = filepath - if modname in self.astng_cache: - return self.astng_cache[modname] - if source: - from .builder import ASTNGBuilder - return ASTNGBuilder(self).file_build(filepath, modname) - elif fallback and modname: - return self.astng_from_module_name(modname) - raise ASTNGBuildingException('unable to get astng for file %s' % - filepath) - - def astng_from_module_name(self, modname, context_file=None): - """given a module name, return the astng object""" - if modname in self.astng_cache: - return self.astng_cache[modname] - if modname == '__main__': - from .builder import ASTNGBuilder - return ASTNGBuilder(self).string_build('', modname) - old_cwd = os.getcwd() - if context_file: - os.chdir(dirname(context_file)) - try: - filepath = self.file_from_module_name(modname, context_file) - if filepath is not None and not is_python_source(filepath): - module = self.zip_import_data(filepath) - if module is not None: - return module - if filepath is None or not is_python_source(filepath): - try: - module = load_module_from_name(modname) - except Exception, ex: - msg = 'Unable to load module %s (%s)' % (modname, ex) - raise ASTNGBuildingException(msg) - return self.astng_from_module(module, modname) - return self.astng_from_file(filepath, modname, fallback=False) - finally: - os.chdir(old_cwd) - - def zip_import_data(self, filepath): - if zipimport is None: - return None - from .builder import ASTNGBuilder - builder = ASTNGBuilder(self) - for ext in ('.zip', '.egg'): - try: - eggpath, resource = filepath.rsplit(ext + '/', 1) - except ValueError: - continue - try: - importer = zipimport.zipimporter(eggpath + ext) - zmodname = resource.replace('/', '.') - if importer.is_package(resource): - zmodname = zmodname + '.__init__' - module = builder.string_build(importer.get_source(resource), - zmodname, filepath) - return module - except: - continue - return None - - def file_from_module_name(self, modname, contextfile): - try: - value = self._mod_file_cache[(modname, contextfile)] - except KeyError: - try: - value = file_from_modpath(modname.split('.'), - context_file=contextfile) - except ImportError, ex: - msg = 'Unable to load module %s (%s)' % (modname, ex) - value = ASTNGBuildingException(msg) - self._mod_file_cache[(modname, contextfile)] = value - if isinstance(value, ASTNGBuildingException): - raise value - return value - - def astng_from_module(self, module, modname=None): - """given an imported module, return the astng object""" - modname = modname or module.__name__ - if modname in self.astng_cache: - return self.astng_cache[modname] - try: - # some builtin modules don't have __file__ attribute - filepath = module.__file__ - if is_python_source(filepath): - return self.astng_from_file(filepath, modname) - except AttributeError: - pass - from .builder import ASTNGBuilder - return ASTNGBuilder(self).module_build(module, modname) - - def astng_from_class(self, klass, modname=None): - """get astng for the given class""" - if modname is None: - try: - modname = klass.__module__ - except AttributeError: - raise ASTNGBuildingException( - 'Unable to get module for class %s' % safe_repr(klass)) - modastng = self.astng_from_module_name(modname) - return modastng.getattr(klass.__name__)[0] # XXX - - - def infer_astng_from_something(self, obj, context=None): - """infer astng for the given class""" - if hasattr(obj, '__class__') and not isinstance(obj, type): - klass = obj.__class__ - else: - klass = obj - try: - modname = klass.__module__ - except AttributeError: - raise ASTNGBuildingException( - 'Unable to get module for %s' % safe_repr(klass)) - except Exception, ex: - raise ASTNGBuildingException( - 'Unexpected error while retrieving module for %s: %s' - % (safe_repr(klass), ex)) - try: - name = klass.__name__ - except AttributeError: - raise ASTNGBuildingException( - 'Unable to get name for %s' % safe_repr(klass)) - except Exception, ex: - raise ASTNGBuildingException( - 'Unexpected error while retrieving name for %s: %s' - % (safe_repr(klass), ex)) - # take care, on living object __module__ is regularly wrong :( - modastng = self.astng_from_module_name(modname) - if klass is obj: - for infered in modastng.igetattr(name, context): - yield infered - else: - for infered in modastng.igetattr(name, context): - yield infered.instanciate_class() - - def project_from_files(self, files, func_wrapper=astng_wrapper, - project_name=None, black_list=None): - """return a Project from a list of files or modules""" - # build the project representation - project_name = project_name or self.config.project - black_list = black_list or self.config.black_list - project = Project(project_name) - for something in files: - if not exists(something): - fpath = file_from_modpath(something.split('.')) - elif isdir(something): - fpath = join(something, '__init__.py') - else: - fpath = something - astng = func_wrapper(self.astng_from_file, fpath) - if astng is None: - continue - # XXX why is first file defining the project.path ? - project.path = project.path or astng.file - project.add_module(astng) - base_name = astng.name - # recurse in package except if __init__ was explicitly given - if astng.package and something.find('__init__') == -1: - # recurse on others packages / modules if this is a package - for fpath in get_module_files(dirname(astng.file), - black_list): - astng = func_wrapper(self.astng_from_file, fpath) - if astng is None or astng.name == base_name: - continue - project.add_module(astng) - return project - - def register_transformer(self, transformer): - self.transformers.append(transformer) - -class Project: - """a project handle a set of modules / packages""" - def __init__(self, name=''): - self.name = name - self.path = None - self.modules = [] - self.locals = {} - self.__getitem__ = self.locals.__getitem__ - self.__iter__ = self.locals.__iter__ - self.values = self.locals.values - self.keys = self.locals.keys - self.items = self.locals.items - - def add_module(self, node): - self.locals[node.name] = node - self.modules.append(node) - - def get_module(self, name): - return self.locals[name] - - def get_children(self): - return self.modules - - def __repr__(self): - return '<Project %r at %s (%s modules)>' % (self.name, id(self), - len(self.modules)) - - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/mixins.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/mixins.py @@ -1,136 +0,0 @@ -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""This module contains some mixins for the different nodes. -""" - -from .exceptions import (ASTNGBuildingException, InferenceError, - NotFoundError) - - -class BlockRangeMixIn(object): - """override block range """ - def set_line_info(self, lastchild): - self.fromlineno = self.lineno - self.tolineno = lastchild.tolineno - self.blockstart_tolineno = self._blockstart_toline() - - def _elsed_block_range(self, lineno, orelse, last=None): - """handle block line numbers range for try/finally, for, if and while - statements - """ - if lineno == self.fromlineno: - return lineno, lineno - if orelse: - if lineno >= orelse[0].fromlineno: - return lineno, orelse[-1].tolineno - return lineno, orelse[0].fromlineno - 1 - return lineno, last or self.tolineno - -class FilterStmtsMixin(object): - """Mixin for statement filtering and assignment type""" - - def _get_filtered_stmts(self, _, node, _stmts, mystmt): - """method used in _filter_stmts to get statemtents and trigger break""" - if self.statement() is mystmt: - # original node's statement is the assignment, only keep - # current node (gen exp, list comp) - return [node], True - return _stmts, False - - def ass_type(self): - return self - - -class AssignTypeMixin(object): - - def ass_type(self): - return self - - def _get_filtered_stmts(self, lookup_node, node, _stmts, mystmt): - """method used in filter_stmts""" - if self is mystmt: - return _stmts, True - if self.statement() is mystmt: - # original node's statement is the assignment, only keep - # current node (gen exp, list comp) - return [node], True - return _stmts, False - - -class ParentAssignTypeMixin(AssignTypeMixin): - - def ass_type(self): - return self.parent.ass_type() - - - -class FromImportMixIn(FilterStmtsMixin): - """MixIn for From and Import Nodes""" - - def _infer_name(self, frame, name): - return name - - def do_import_module(self, modname): - """return the ast for a module whose name is <modname> imported by <self> - """ - # handle special case where we are on a package node importing a module - # using the same name as the package, which may end in an infinite loop - # on relative imports - # XXX: no more needed ? - mymodule = self.root() - level = getattr(self, 'level', None) # Import as no level - # XXX we should investigate deeper if we really want to check - # importing itself: modname and mymodule.name be relative or absolute - if mymodule.relative_to_absolute_name(modname, level) == mymodule.name: - # FIXME: we used to raise InferenceError here, but why ? - return mymodule - try: - return mymodule.import_module(modname, level=level) - except ASTNGBuildingException: - raise InferenceError(modname) - except SyntaxError, ex: - raise InferenceError(str(ex)) - - def real_name(self, asname): - """get name from 'as' name""" - for name, _asname in self.names: - if name == '*': - return asname - if not _asname: - name = name.split('.', 1)[0] - _asname = name - if asname == _asname: - return name - raise NotFoundError(asname) - - - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/node_classes.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/node_classes.py @@ -1,908 +0,0 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""Module for some node classes. More nodes in scoped_nodes.py -""" - -import sys - -from . import BUILTINS_MODULE -from .exceptions import NoDefault -from .bases import (NodeNG, Statement, Instance, InferenceContext, - _infer_stmts, YES) -from .mixins import BlockRangeMixIn, AssignTypeMixin, \ - ParentAssignTypeMixin, FromImportMixIn - - -def unpack_infer(stmt, context=None): - """recursively generate nodes inferred by the given statement. - If the inferred value is a list or a tuple, recurse on the elements - """ - if isinstance(stmt, (List, Tuple)): - for elt in stmt.elts: - for infered_elt in unpack_infer(elt, context): - yield infered_elt - return - # if infered is a final node, return it and stop - infered = stmt.infer(context).next() - if infered is stmt: - yield infered - return - # else, infer recursivly, except YES object that should be returned as is - for infered in stmt.infer(context): - if infered is YES: - yield infered - else: - for inf_inf in unpack_infer(infered, context): - yield inf_inf - - -def are_exclusive(stmt1, stmt2, exceptions=None): - """return true if the two given statements are mutually exclusive - - `exceptions` may be a list of exception names. If specified, discard If - branches and check one of the statement is in an exception handler catching - one of the given exceptions. - - algorithm : - 1) index stmt1's parents - 2) climb among stmt2's parents until we find a common parent - 3) if the common parent is a If or TryExcept statement, look if nodes are - in exclusive branches - """ - # index stmt1's parents - stmt1_parents = {} - children = {} - node = stmt1.parent - previous = stmt1 - while node: - stmt1_parents[node] = 1 - children[node] = previous - previous = node - node = node.parent - # climb among stmt2's parents until we find a common parent - node = stmt2.parent - previous = stmt2 - while node: - if node in stmt1_parents: - # if the common parent is a If or TryExcept statement, look if - # nodes are in exclusive branches - if isinstance(node, If) and exceptions is None: - if (node.locate_child(previous)[1] - is not node.locate_child(children[node])[1]): - return True - elif isinstance(node, TryExcept): - c2attr, c2node = node.locate_child(previous) - c1attr, c1node = node.locate_child(children[node]) - if c1node is not c2node: - if ((c2attr == 'body' and c1attr == 'handlers' and children[node].catch(exceptions)) or - (c2attr == 'handlers' and c1attr == 'body' and previous.catch(exceptions)) or - (c2attr == 'handlers' and c1attr == 'orelse') or - (c2attr == 'orelse' and c1attr == 'handlers')): - return True - elif c2attr == 'handlers' and c1attr == 'handlers': - return previous is not children[node] - return False - previous = node - node = node.parent - return False - - -class LookupMixIn(object): - """Mixin looking up a name in the right scope - """ - - def lookup(self, name): - """lookup a variable name - - return the scope node and the list of assignments associated to the given - name according to the scope where it has been found (locals, globals or - builtin) - - The lookup is starting from self's scope. If self is not a frame itself and - the name is found in the inner frame locals, statements will be filtered - to remove ignorable statements according to self's location - """ - return self.scope().scope_lookup(self, name) - - def ilookup(self, name): - """infered lookup - - return an iterator on infered values of the statements returned by - the lookup method - """ - frame, stmts = self.lookup(name) - context = InferenceContext() - return _infer_stmts(stmts, context, frame) - - def _filter_stmts(self, stmts, frame, offset): - """filter statements to remove ignorable statements. - - If self is not a frame itself and the name is found in the inner - frame locals, statements will be filtered to remove ignorable - statements according to self's location - """ - # if offset == -1, my actual frame is not the inner frame but its parent - # - # class A(B): pass - # - # we need this to resolve B correctly - if offset == -1: - myframe = self.frame().parent.frame() - else: - myframe = self.frame() - if not myframe is frame or self is frame: - return stmts - mystmt = self.statement() - # line filtering if we are in the same frame - # - # take care node may be missing lineno information (this is the case for - # nodes inserted for living objects) - if myframe is frame and mystmt.fromlineno is not None: - assert mystmt.fromlineno is not None, mystmt - mylineno = mystmt.fromlineno + offset - else: - # disabling lineno filtering - mylineno = 0 - _stmts = [] - _stmt_parents = [] - for node in stmts: - stmt = node.statement() - # line filtering is on and we have reached our location, break - if mylineno > 0 and stmt.fromlineno > mylineno: - break - assert hasattr(node, 'ass_type'), (node, node.scope(), - node.scope().locals) - ass_type = node.ass_type() - - if node.has_base(self): - break - - _stmts, done = ass_type._get_filtered_stmts(self, node, _stmts, mystmt) - if done: - break - - optional_assign = ass_type.optional_assign - if optional_assign and ass_type.parent_of(self): - # we are inside a loop, loop var assigment is hidding previous - # assigment - _stmts = [node] - _stmt_parents = [stmt.parent] - continue - - # XXX comment various branches below!!! - try: - pindex = _stmt_parents.index(stmt.parent) - except ValueError: - pass - else: - # we got a parent index, this means the currently visited node - # is at the same block level as a previously visited node - if _stmts[pindex].ass_type().parent_of(ass_type): - # both statements are not at the same block level - continue - # if currently visited node is following previously considered - # assignement and both are not exclusive, we can drop the - # previous one. For instance in the following code :: - # - # if a: - # x = 1 - # else: - # x = 2 - # print x - # - # we can't remove neither x = 1 nor x = 2 when looking for 'x' - # of 'print x'; while in the following :: - # - # x = 1 - # x = 2 - # print x - # - # we can remove x = 1 when we see x = 2 - # - # moreover, on loop assignment types, assignment won't - # necessarily be done if the loop has no iteration, so we don't - # want to clear previous assigments if any (hence the test on - # optional_assign) - if not (optional_assign or are_exclusive(_stmts[pindex], node)): - del _stmt_parents[pindex] - del _stmts[pindex] - if isinstance(node, AssName): - if not optional_assign and stmt.parent is mystmt.parent: - _stmts = [] - _stmt_parents = [] - elif isinstance(node, DelName): - _stmts = [] - _stmt_parents = [] - continue - if not are_exclusive(self, node): - _stmts.append(node) - _stmt_parents.append(stmt.parent) - return _stmts - -# Name classes - -class AssName(LookupMixIn, ParentAssignTypeMixin, NodeNG): - """class representing an AssName node""" - - -class DelName(LookupMixIn, ParentAssignTypeMixin, NodeNG): - """class representing a DelName node""" - - -class Name(LookupMixIn, NodeNG): - """class representing a Name node""" - - - - -##################### node classes ######################################## - -class Arguments(NodeNG, AssignTypeMixin): - """class representing an Arguments node""" - _astng_fields = ('args', 'defaults') - args = None - defaults = None - - def __init__(self, vararg=None, kwarg=None): - self.vararg = vararg - self.kwarg = kwarg - - def _infer_name(self, frame, name): - if self.parent is frame: - return name - return None - - def format_args(self): - """return arguments formatted as string""" - result = [_format_args(self.args, self.defaults)] - if self.vararg: - result.append('*%s' % self.vararg) - if self.kwarg: - result.append('**%s' % self.kwarg) - return ', '.join(result) - - def default_value(self, argname): - """return the default value for an argument - - :raise `NoDefault`: if there is no default value defined - """ - i = _find_arg(argname, self.args)[0] - if i is not None: - idx = i - (len(self.args) - len(self.defaults)) - if idx >= 0: - return self.defaults[idx] - raise NoDefault() - - def is_argument(self, name): - """return True if the name is defined in arguments""" - if name == self.vararg: - return True - if name == self.kwarg: - return True - return self.find_argname(name, True)[1] is not None - - def find_argname(self, argname, rec=False): - """return index and Name node with given name""" - if self.args: # self.args may be None in some cases (builtin function) - return _find_arg(argname, self.args, rec) - return None, None - - -def _find_arg(argname, args, rec=False): - for i, arg in enumerate(args): - if isinstance(arg, Tuple): - if rec: - found = _find_arg(argname, arg.elts) - if found[0] is not None: - return found - elif arg.name == argname: - return i, arg - return None, None - - -def _format_args(args, defaults=None): - values = [] - if args is None: - return '' - if defaults is not None: - default_offset = len(args) - len(defaults) - for i, arg in enumerate(args): - if isinstance(arg, Tuple): - values.append('(%s)' % _format_args(arg.elts)) - else: - values.append(arg.name) - if defaults is not None and i >= default_offset: - values[-1] += '=' + defaults[i-default_offset].as_string() - return ', '.join(values) - - -class AssAttr(NodeNG, ParentAssignTypeMixin): - """class representing an AssAttr node""" - _astng_fields = ('expr',) - expr = None - -class Assert(Statement): - """class representing an Assert node""" - _astng_fields = ('test', 'fail',) - test = None - fail = None - -class Assign(Statement, AssignTypeMixin): - """class representing an Assign node""" - _astng_fields = ('targets', 'value',) - targets = None - value = None - -class AugAssign(Statement, AssignTypeMixin): - """class representing an AugAssign node""" - _astng_fields = ('target', 'value',) - target = None - value = None - -class Backquote(NodeNG): - """class representing a Backquote node""" - _astng_fields = ('value',) - value = None - -class BinOp(NodeNG): - """class representing a BinOp node""" - _astng_fields = ('left', 'right',) - left = None - right = None - -class BoolOp(NodeNG): - """class representing a BoolOp node""" - _astng_fields = ('values',) - values = None - -class Break(Statement): - """class representing a Break node""" - - -class CallFunc(NodeNG): - """class representing a CallFunc node""" - _astng_fields = ('func', 'args', 'starargs', 'kwargs') - func = None - args = None - starargs = None - kwargs = None - - def __init__(self): - self.starargs = None - self.kwargs = None - -class Compare(NodeNG): - """class representing a Compare node""" - _astng_fields = ('left', 'ops',) - left = None - ops = None - - def get_children(self): - """override get_children for tuple fields""" - yield self.left - for _, comparator in self.ops: - yield comparator # we don't want the 'op' - - def last_child(self): - """override last_child""" - # XXX maybe if self.ops: - return self.ops[-1][1] - #return self.left - -class Comprehension(NodeNG): - """class representing a Comprehension node""" - _astng_fields = ('target', 'iter' ,'ifs') - target = None - iter = None - ifs = None - - optional_assign = True - def ass_type(self): - return self - - def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt): - """method used in filter_stmts""" - if self is mystmt: - if isinstance(lookup_node, (Const, Name)): - return [lookup_node], True - - elif self.statement() is mystmt: - # original node's statement is the assignment, only keeps - # current node (gen exp, list comp) - - return [node], True - - return stmts, False - - -class Const(NodeNG, Instance): - """represent a constant node like num, str, bool, None, bytes""" - - def __init__(self, value=None): - self.value = value - - def getitem(self, index, context=None): - if isinstance(self.value, basestring): - return Const(self.value[index]) - raise TypeError('%r (value=%s)' % (self, self.value)) - - def has_dynamic_getattr(self): - return False - - def itered(self): - if isinstance(self.value, basestring): - return self.value - raise TypeError() - - def pytype(self): - return self._proxied.qname() - - -class Continue(Statement): - """class representing a Continue node""" - - -class Decorators(NodeNG): - """class representing a Decorators node""" - _astng_fields = ('nodes',) - nodes = None - - def __init__(self, nodes=None): - self.nodes = nodes - - def scope(self): - # skip the function node to go directly to the upper level scope - return self.parent.parent.scope() - -class DelAttr(NodeNG, ParentAssignTypeMixin): - """class representing a DelAttr node""" - _astng_fields = ('expr',) - expr = None - - -class Delete(Statement, AssignTypeMixin): - """class representing a Delete node""" - _astng_fields = ('targets',) - targets = None - - -class Dict(NodeNG, Instance): - """class representing a Dict node""" - _astng_fields = ('items',) - - def __init__(self, items=None): - if items is None: - self.items = [] - else: - self.items = [(const_factory(k), const_factory(v)) - for k,v in items.iteritems()] - - def pytype(self): - return '%s.dict' % BUILTINS_MODULE - - def get_children(self): - """get children of a Dict node""" - # overrides get_children - for key, value in self.items: - yield key - yield value - - def last_child(self): - """override last_child""" - if self.items: - return self.items[-1][1] - return None - - def itered(self): - return self.items[::2] - - def getitem(self, key, context=None): - for i in xrange(0, len(self.items), 2): - for inferedkey in self.items[i].infer(context): - if inferedkey is YES: - continue - if isinstance(inferedkey, Const) and inferedkey.value == key: - return self.items[i+1] - raise IndexError(key) - - -class Discard(Statement): - """class representing a Discard node""" - _astng_fields = ('value',) - value = None - - -class Ellipsis(NodeNG): - """class representing an Ellipsis node""" - - -class EmptyNode(NodeNG): - """class representing an EmptyNode node""" - - -class ExceptHandler(Statement, AssignTypeMixin): - """class representing an ExceptHandler node""" - _astng_fields = ('type', 'name', 'body',) - type = None - name = None - body = None - - def _blockstart_toline(self): - if self.name: - return self.name.tolineno - elif self.type: - return self.type.tolineno - else: - return self.lineno - - def set_line_info(self, lastchild): - self.fromlineno = self.lineno - self.tolineno = lastchild.tolineno - self.blockstart_tolineno = self._blockstart_toline() - - def catch(self, exceptions): - if self.type is None or exceptions is None: - return True - for node in self.type.nodes_of_class(Name): - if node.name in exceptions: - return True - - -class Exec(Statement): - """class representing an Exec node""" - _astng_fields = ('expr', 'globals', 'locals',) - expr = None - globals = None - locals = None - - -class ExtSlice(NodeNG): - """class representing an ExtSlice node""" - _astng_fields = ('dims',) - dims = None - -class For(BlockRangeMixIn, AssignTypeMixin, Statement): - """class representing a For node""" - _astng_fields = ('target', 'iter', 'body', 'orelse',) - target = None - iter = None - body = None - orelse = None - - optional_assign = True - def _blockstart_toline(self): - return self.iter.tolineno - - -class From(FromImportMixIn, Statement): - """class representing a From node""" - - def __init__(self, fromname, names, level=0): - self.modname = fromname - self.names = names - self.level = level - -class Getattr(NodeNG): - """class representing a Getattr node""" - _astng_fields = ('expr',) - expr = None - - -class Global(Statement): - """class representing a Global node""" - - def __init__(self, names): - self.names = names - - def _infer_name(self, frame, name): - return name - - -class If(BlockRangeMixIn, Statement): - """class representing an If node""" - _astng_fields = ('test', 'body', 'orelse') - test = None - body = None - orelse = None - - def _blockstart_toline(self): - return self.test.tolineno - - def block_range(self, lineno): - """handle block line numbers range for if statements""" - if lineno == self.body[0].fromlineno: - return lineno, lineno - if lineno <= self.body[-1].tolineno: - return lineno, self.body[-1].tolineno - return self._elsed_block_range(lineno, self.orelse, - self.body[0].fromlineno - 1) - - -class IfExp(NodeNG): - """class representing an IfExp node""" - _astng_fields = ('test', 'body', 'orelse') - test = None - body = None - orelse = None - - -class Import(FromImportMixIn, Statement): - """class representing an Import node""" - - -class Index(NodeNG): - """class representing an Index node""" - _astng_fields = ('value',) - value = None - - -class Keyword(NodeNG): - """class representing a Keyword node""" - _astng_fields = ('value',) - value = None - - -class List(NodeNG, Instance, ParentAssignTypeMixin): - """class representing a List node""" - _astng_fields = ('elts',) - - def __init__(self, elts=None): - if elts is None: - self.elts = [] - else: - self.elts = [const_factory(e) for e in elts] - - def pytype(self): - return '%s.list' % BUILTINS_MODULE - - def getitem(self, index, context=None): - return self.elts[index] - - def itered(self): - return self.elts - - -class Nonlocal(Statement): - """class representing a Nonlocal node""" - - def __init__(self, names): - self.names = names - - def _infer_name(self, frame, name): - return name - - -class Pass(Statement): - """class representing a Pass node""" - - -class Print(Statement): - """class representing a Print node""" - _astng_fields = ('dest', 'values',) - dest = None - values = None - - -class Raise(Statement): - """class representing a Raise node""" - exc = None - if sys.version_info < (3, 0): - _astng_fields = ('exc', 'inst', 'tback') - inst = None - tback = None - else: - _astng_fields = ('exc', 'cause') - exc = None - cause = None - - def raises_not_implemented(self): - if not self.exc: - return - for name in self.exc.nodes_of_class(Name): - if name.name == 'NotImplementedError': - return True - - -class Return(Statement): - """class representing a Return node""" - _astng_fields = ('value',) - value = None - - -class Set(NodeNG, Instance, ParentAssignTypeMixin): - """class representing a Set node""" - _astng_fields = ('elts',) - - def __init__(self, elts=None): - if elts is None: - self.elts = [] - else: - self.elts = [const_factory(e) for e in elts] - - def pytype(self): - return '%s.set' % BUILTINS_MODULE - - def itered(self): - return self.elts - - -class Slice(NodeNG): - """class representing a Slice node""" - _astng_fields = ('lower', 'upper', 'step') - lower = None - upper = None - step = None - -class Starred(NodeNG, ParentAssignTypeMixin): - """class representing a Starred node""" - _astng_fields = ('value',) - value = None - - -class Subscript(NodeNG): - """class representing a Subscript node""" - _astng_fields = ('value', 'slice') - value = None - slice = None - - -class TryExcept(BlockRangeMixIn, Statement): - """class representing a TryExcept node""" - _astng_fields = ('body', 'handlers', 'orelse',) - body = None - handlers = None - orelse = None - - def _infer_name(self, frame, name): - return name - - def _blockstart_toline(self): - return self.lineno - - def block_range(self, lineno): - """handle block line numbers range for try/except statements""" - last = None - for exhandler in self.handlers: - if exhandler.type and lineno == exhandler.type.fromlineno: - return lineno, lineno - if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno: - return lineno, exhandler.body[-1].tolineno - if last is None: - last = exhandler.body[0].fromlineno - 1 - return self._elsed_block_range(lineno, self.orelse, last) - - -class TryFinally(BlockRangeMixIn, Statement): - """class representing a TryFinally node""" - _astng_fields = ('body', 'finalbody',) - body = None - finalbody = None - - def _blockstart_toline(self): - return self.lineno - - def block_range(self, lineno): - """handle block line numbers range for try/finally statements""" - child = self.body[0] - # py2.5 try: except: finally: - if (isinstance(child, TryExcept) and child.fromlineno == self.fromlineno - and lineno > self.fromlineno and lineno <= child.tolineno): - return child.block_range(lineno) - return self._elsed_block_range(lineno, self.finalbody) - - -class Tuple(NodeNG, Instance, ParentAssignTypeMixin): - """class representing a Tuple node""" - _astng_fields = ('elts',) - - def __init__(self, elts=None): - if elts is None: - self.elts = [] - else: - self.elts = [const_factory(e) for e in elts] - - def pytype(self): - return '%s.tuple' % BUILTINS_MODULE - - def getitem(self, index, context=None): - return self.elts[index] - - def itered(self): - return self.elts - - -class UnaryOp(NodeNG): - """class representing an UnaryOp node""" - _astng_fields = ('operand',) - operand = None - - -class While(BlockRangeMixIn, Statement): - """class representing a While node""" - _astng_fields = ('test', 'body', 'orelse',) - test = None - body = None - orelse = None - - def _blockstart_toline(self): - return self.test.tolineno - - def block_range(self, lineno): - """handle block line numbers range for for and while statements""" - return self. _elsed_block_range(lineno, self.orelse) - - -class With(BlockRangeMixIn, AssignTypeMixin, Statement): - """class representing a With node""" - _astng_fields = ('expr', 'vars', 'body') - expr = None - vars = None - body = None - - def _blockstart_toline(self): - if self.vars: - return self.vars.tolineno - else: - return self.expr.tolineno - - -class Yield(NodeNG): - """class representing a Yield node""" - _astng_fields = ('value',) - value = None - -# constants ############################################################## - -CONST_CLS = { - list: List, - tuple: Tuple, - dict: Dict, - set: Set, - type(None): Const, - } - -def _update_const_classes(): - """update constant classes, so the keys of CONST_CLS can be reused""" - klasses = (bool, int, float, complex, str) - if sys.version_info < (3, 0): - klasses += (unicode, long) - if sys.version_info >= (2, 6): - klasses += (bytes,) - for kls in klasses: - CONST_CLS[kls] = Const -_update_const_classes() - -def const_factory(value): - """return an astng node for a python value""" - # since const_factory is called to evaluate content of container (eg list, - # tuple), it may be called with some node as argument that should be left - # untouched - if isinstance(value, NodeNG): - return value - try: - return CONST_CLS[value.__class__](value) - except (KeyError, AttributeError): - # some constants (like from gtk._gtk) don't have their class in - # CONST_CLS, though we can "assert isinstance(value, tuple(CONST_CLS))" - if isinstance(value, tuple(CONST_CLS)): - return Const(value) - node = EmptyNode() - node.object = value - return node diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/nodes.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/nodes.py @@ -1,75 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -""" -on all nodes : - .is_statement, returning true if the node should be considered as a - statement node - .root(), returning the root node of the tree (i.e. a Module) - .previous_sibling(), returning previous sibling statement node - .next_sibling(), returning next sibling statement node - .statement(), returning the first parent node marked as statement node - .frame(), returning the first node defining a new local scope (i.e. - Module, Function or Class) - .set_local(name, node), define an identifier <name> on the first parent frame, - with the node defining it. This is used by the astng builder and should not - be used from out there. - -on From and Import : - .real_name(name), - - -""" - -__docformat__ = "restructuredtext en" - -from .node_classes import Arguments, AssAttr, Assert, Assign, \ - AssName, AugAssign, Backquote, BinOp, BoolOp, Break, CallFunc, Compare, \ - Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, \ - Dict, Discard, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, \ - From, Getattr, Global, If, IfExp, Import, Index, Keyword, \ - List, Name, Nonlocal, Pass, Print, Raise, Return, Set, Slice, Starred, Subscript, \ - TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, \ - const_factory -from .scoped_nodes import Module, GenExpr, Lambda, DictComp, \ - ListComp, SetComp, Function, Class - -ALL_NODE_CLASSES = ( - Arguments, AssAttr, Assert, Assign, AssName, AugAssign, - Backquote, BinOp, BoolOp, Break, - CallFunc, Class, Compare, Comprehension, Const, Continue, - Decorators, DelAttr, DelName, Delete, - Dict, DictComp, Discard, - Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, - For, From, Function, - Getattr, GenExpr, Global, - If, IfExp, Import, Index, - Keyword, - Lambda, List, ListComp, - Name, Nonlocal, - Module, - Pass, Print, - Raise, Return, - Set, SetComp, Slice, Starred, Subscript, - TryExcept, TryFinally, Tuple, - UnaryOp, - While, With, - Yield, - ) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/protocols.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/protocols.py @@ -1,321 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""this module contains a set of functions to handle python protocols for nodes -where it makes sense. -""" - -__doctype__ = "restructuredtext en" - -from .exceptions import InferenceError, NoDefault -from .node_classes import unpack_infer -from .bases import copy_context, \ - raise_if_nothing_infered, yes_if_nothing_infered, Instance, Generator, YES -from .nodes import const_factory -from . import nodes - -# unary operations ############################################################ - -def tl_infer_unary_op(self, operator): - if operator == 'not': - return const_factory(not bool(self.elts)) - raise TypeError() # XXX log unsupported operation -nodes.Tuple.infer_unary_op = tl_infer_unary_op -nodes.List.infer_unary_op = tl_infer_unary_op - - -def dict_infer_unary_op(self, operator): - if operator == 'not': - return const_factory(not bool(self.items)) - raise TypeError() # XXX log unsupported operation -nodes.Dict.infer_unary_op = dict_infer_unary_op - - -def const_infer_unary_op(self, operator): - if operator == 'not': - return const_factory(not self.value) - # XXX log potentially raised TypeError - elif operator == '+': - return const_factory(+self.value) - else: # operator == '-': - return const_factory(-self.value) -nodes.Const.infer_unary_op = const_infer_unary_op - - -# binary operations ########################################################### - -BIN_OP_IMPL = {'+': lambda a, b: a + b, - '-': lambda a, b: a - b, - '/': lambda a, b: a / b, - '//': lambda a, b: a // b, - '*': lambda a, b: a * b, - '**': lambda a, b: a ** b, - '%': lambda a, b: a % b, - '&': lambda a, b: a & b, - '|': lambda a, b: a | b, - '^': lambda a, b: a ^ b, - '<<': lambda a, b: a << b, - '>>': lambda a, b: a >> b, - } -for key, impl in BIN_OP_IMPL.items(): - BIN_OP_IMPL[key+'='] = impl - -def const_infer_binary_op(self, operator, other, context): - for other in other.infer(context): - if isinstance(other, nodes.Const): - try: - impl = BIN_OP_IMPL[operator] - - try: - yield const_factory(impl(self.value, other.value)) - except Exception: - # ArithmeticError is not enough: float >> float is a TypeError - # TODO : let pylint know about the problem - pass - except TypeError: - # XXX log TypeError - continue - elif other is YES: - yield other - else: - try: - for val in other.infer_binary_op(operator, self, context): - yield val - except AttributeError: - yield YES -nodes.Const.infer_binary_op = yes_if_nothing_infered(const_infer_binary_op) - - -def tl_infer_binary_op(self, operator, other, context): - for other in other.infer(context): - if isinstance(other, self.__class__) and operator == '+': - node = self.__class__() - elts = [n for elt in self.elts for n in elt.infer(context) - if not n is YES] - elts += [n for elt in other.elts for n in elt.infer(context) - if not n is YES] - node.elts = elts - yield node - elif isinstance(other, nodes.Const) and operator == '*': - if not isinstance(other.value, int): - yield YES - continue - node = self.__class__() - elts = [n for elt in self.elts for n in elt.infer(context) - if not n is YES] * other.value - node.elts = elts - yield node - elif isinstance(other, Instance) and not isinstance(other, nodes.Const): - yield YES - # XXX else log TypeError -nodes.Tuple.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op) -nodes.List.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op) - - -def dict_infer_binary_op(self, operator, other, context): - for other in other.infer(context): - if isinstance(other, Instance) and isinstance(other._proxied, nodes.Class): - yield YES - # XXX else log TypeError -nodes.Dict.infer_binary_op = yes_if_nothing_infered(dict_infer_binary_op) - - -# assignment ################################################################## - -"""the assigned_stmts method is responsible to return the assigned statement -(e.g. not inferred) according to the assignment type. - -The `asspath` argument is used to record the lhs path of the original node. -For instance if we want assigned statements for 'c' in 'a, (b,c)', asspath -will be [1, 1] once arrived to the Assign node. - -The `context` argument is the current inference context which should be given -to any intermediary inference necessary. -""" - -def _resolve_looppart(parts, asspath, context): - """recursive function to resolve multiple assignments on loops""" - asspath = asspath[:] - index = asspath.pop(0) - for part in parts: - if part is YES: - continue - # XXX handle __iter__ and log potentially detected errors - if not hasattr(part, 'itered'): - continue - try: - itered = part.itered() - except TypeError: - continue # XXX log error - for stmt in itered: - try: - assigned = stmt.getitem(index, context) - except (AttributeError, IndexError): - continue - except TypeError, exc: # stmt is unsubscriptable Const - continue - if not asspath: - # we achieved to resolved the assignment path, - # don't infer the last part - yield assigned - elif assigned is YES: - break - else: - # we are not yet on the last part of the path - # search on each possibly inferred value - try: - for infered in _resolve_looppart(assigned.infer(context), - asspath, context): - yield infered - except InferenceError: - break - - -def for_assigned_stmts(self, node, context=None, asspath=None): - if asspath is None: - for lst in self.iter.infer(context): - if isinstance(lst, (nodes.Tuple, nodes.List)): - for item in lst.elts: - yield item - else: - for infered in _resolve_looppart(self.iter.infer(context), - asspath, context): - yield infered - -nodes.For.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts) -nodes.Comprehension.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts) - - -def mulass_assigned_stmts(self, node, context=None, asspath=None): - if asspath is None: - asspath = [] - asspath.insert(0, self.elts.index(node)) - return self.parent.assigned_stmts(self, context, asspath) -nodes.Tuple.assigned_stmts = mulass_assigned_stmts -nodes.List.assigned_stmts = mulass_assigned_stmts - - -def assend_assigned_stmts(self, context=None): - return self.parent.assigned_stmts(self, context=context) -nodes.AssName.assigned_stmts = assend_assigned_stmts -nodes.AssAttr.assigned_stmts = assend_assigned_stmts - - -def _arguments_infer_argname(self, name, context): - # arguments information may be missing, in which case we can't do anything - # more - if not (self.args or self.vararg or self.kwarg): - yield YES - return - # first argument of instance/class method - if self.args and getattr(self.args[0], 'name', None) == name: - functype = self.parent.type - if functype == 'method': - yield Instance(self.parent.parent.frame()) - return - if functype == 'classmethod': - yield self.parent.parent.frame() - return - if name == self.vararg: - yield const_factory(()) - return - if name == self.kwarg: - yield const_factory({}) - return - # if there is a default value, yield it. And then yield YES to reflect - # we can't guess given argument value - try: - context = copy_context(context) - for infered in self.default_value(name).infer(context): - yield infered - yield YES - except NoDefault: - yield YES - - -def arguments_assigned_stmts(self, node, context, asspath=None): - if context.callcontext: - # reset call context/name - callcontext = context.callcontext - context = copy_context(context) - context.callcontext = None - for infered in callcontext.infer_argument(self.parent, node.name, context): - yield infered - return - for infered in _arguments_infer_argname(self, node.name, context): - yield infered -nodes.Arguments.assigned_stmts = arguments_assigned_stmts - - -def assign_assigned_stmts(self, node, context=None, asspath=None): - if not asspath: - yield self.value - return - for infered in _resolve_asspart(self.value.infer(context), asspath, context): - yield infered -nodes.Assign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts) -nodes.AugAssign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts) - - -def _resolve_asspart(parts, asspath, context): - """recursive function to resolve multiple assignments""" - asspath = asspath[:] - index = asspath.pop(0) - for part in parts: - if hasattr(part, 'getitem'): - try: - assigned = part.getitem(index, context) - # XXX raise a specific exception to avoid potential hiding of - # unexpected exception ? - except (TypeError, IndexError): - return - if not asspath: - # we achieved to resolved the assignment path, don't infer the - # last part - yield assigned - elif assigned is YES: - return - else: - # we are not yet on the last part of the path search on each - # possibly inferred value - try: - for infered in _resolve_asspart(assigned.infer(context), - asspath, context): - yield infered - except InferenceError: - return - - -def excepthandler_assigned_stmts(self, node, context=None, asspath=None): - for assigned in unpack_infer(self.type): - if isinstance(assigned, nodes.Class): - assigned = Instance(assigned) - yield assigned -nodes.ExceptHandler.assigned_stmts = raise_if_nothing_infered(excepthandler_assigned_stmts) - - -def with_assigned_stmts(self, node, context=None, asspath=None): - if asspath is None: - for lst in self.vars.infer(context): - if isinstance(lst, (nodes.Tuple, nodes.List)): - for item in lst.nodes: - yield item -nodes.With.assigned_stmts = raise_if_nothing_infered(with_assigned_stmts) - - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/raw_building.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/raw_building.py @@ -1,353 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""this module contains a set of functions to create astng trees from scratch -(build_* functions) or from living object (object_build_* functions) -""" - -__docformat__ = "restructuredtext en" - -import sys -from os.path import abspath -from inspect import (getargspec, isdatadescriptor, isfunction, ismethod, - ismethoddescriptor, isclass, isbuiltin) - -from . import BUILTINS_MODULE -from .node_classes import CONST_CLS -from .nodes import (Module, Class, Const, const_factory, From, - Function, EmptyNode, Name, Arguments, Dict, List, Set, Tuple) -from .bases import Generator -from .manager import ASTNGManager -MANAGER = ASTNGManager() - -_CONSTANTS = tuple(CONST_CLS) # the keys of CONST_CLS eg python builtin types - -def _attach_local_node(parent, node, name): - node.name = name # needed by add_local_node - parent.add_local_node(node) - -_marker = object() - -def attach_dummy_node(node, name, object=_marker): - """create a dummy node and register it in the locals of the given - node with the specified name - """ - enode = EmptyNode() - enode.object = object - _attach_local_node(node, enode, name) - -EmptyNode.has_underlying_object = lambda self: self.object is not _marker - -def attach_const_node(node, name, value): - """create a Const node and register it in the locals of the given - node with the specified name - """ - if not name in node.special_attributes: - _attach_local_node(node, const_factory(value), name) - -def attach_import_node(node, modname, membername): - """create a From node and register it in the locals of the given - node with the specified name - """ - from_node = From(modname, [(membername, None)]) - _attach_local_node(node, from_node, membername) - - -def build_module(name, doc=None): - """create and initialize a astng Module node""" - node = Module(name, doc, pure_python=False) - node.package = False - node.parent = None - return node - -def build_class(name, basenames=(), doc=None): - """create and initialize a astng Class node""" - node = Class(name, doc) - for base in basenames: - basenode = Name() - basenode.name = base - node.bases.append(basenode) - basenode.parent = node - return node - -def build_function(name, args=None, defaults=None, flag=0, doc=None): - """create and initialize a astng Function node""" - args, defaults = args or [], defaults or [] - # first argument is now a list of decorators - func = Function(name, doc) - func.args = argsnode = Arguments() - argsnode.args = [] - for arg in args: - argsnode.args.append(Name()) - argsnode.args[-1].name = arg - argsnode.args[-1].parent = argsnode - argsnode.defaults = [] - for default in defaults: - argsnode.defaults.append(const_factory(default)) - argsnode.defaults[-1].parent = argsnode - argsnode.kwarg = None - argsnode.vararg = None - argsnode.parent = func - if args: - register_arguments(func) - return func - - -def build_from_import(fromname, names): - """create and initialize an astng From import statement""" - return From(fromname, [(name, None) for name in names]) - -def register_arguments(func, args=None): - """add given arguments to local - - args is a list that may contains nested lists - (i.e. def func(a, (b, c, d)): ...) - """ - if args is None: - args = func.args.args - if func.args.vararg: - func.set_local(func.args.vararg, func.args) - if func.args.kwarg: - func.set_local(func.args.kwarg, func.args) - for arg in args: - if isinstance(arg, Name): - func.set_local(arg.name, arg) - else: - register_arguments(func, arg.elts) - -def object_build_class(node, member, localname): - """create astng for a living class object""" - basenames = [base.__name__ for base in member.__bases__] - return _base_class_object_build(node, member, basenames, - localname=localname) - -def object_build_function(node, member, localname): - """create astng for a living function object""" - args, varargs, varkw, defaults = getargspec(member) - if varargs is not None: - args.append(varargs) - if varkw is not None: - args.append(varkw) - func = build_function(getattr(member, '__name__', None) or localname, args, - defaults, member.func_code.co_flags, member.__doc__) - node.add_local_node(func, localname) - -def object_build_datadescriptor(node, member, name): - """create astng for a living data descriptor object""" - return _base_class_object_build(node, member, [], name) - -def object_build_methoddescriptor(node, member, localname): - """create astng for a living method descriptor object""" - # FIXME get arguments ? - func = build_function(getattr(member, '__name__', None) or localname, - doc=member.__doc__) - # set node's arguments to None to notice that we have no information, not - # and empty argument list - func.args.args = None - node.add_local_node(func, localname) - -def _base_class_object_build(node, member, basenames, name=None, localname=None): - """create astng for a living class object, with a given set of base names - (e.g. ancestors) - """ - klass = build_class(name or getattr(member, '__name__', None) or localname, - basenames, member.__doc__) - klass._newstyle = isinstance(member, type) - node.add_local_node(klass, localname) - try: - # limit the instantiation trick since it's too dangerous - # (such as infinite test execution...) - # this at least resolves common case such as Exception.args, - # OSError.errno - if issubclass(member, Exception): - instdict = member().__dict__ - else: - raise TypeError - except: - pass - else: - for name, obj in instdict.items(): - valnode = EmptyNode() - valnode.object = obj - valnode.parent = klass - valnode.lineno = 1 - klass.instance_attrs[name] = [valnode] - return klass - - - - -class InspectBuilder(object): - """class for building nodes from living object - - this is actually a really minimal representation, including only Module, - Function and Class nodes and some others as guessed. - """ - - # astng from living objects ############################################### - - def __init__(self): - self._done = {} - self._module = None - - def inspect_build(self, module, modname=None, path=None): - """build astng from a living module (i.e. using inspect) - this is used when there is no python source code available (either - because it's a built-in module or because the .py is not available) - """ - self._module = module - if modname is None: - modname = module.__name__ - try: - node = build_module(modname, module.__doc__) - except AttributeError: - # in jython, java modules have no __doc__ (see #109562) - node = build_module(modname) - node.file = node.path = path and abspath(path) or path - MANAGER.astng_cache[modname] = node - node.package = hasattr(module, '__path__') - self._done = {} - self.object_build(node, module) - return node - - def object_build(self, node, obj): - """recursive method which create a partial ast from real objects - (only function, class, and method are handled) - """ - if obj in self._done: - return self._done[obj] - self._done[obj] = node - for name in dir(obj): - try: - member = getattr(obj, name) - except AttributeError: - # damned ExtensionClass.Base, I know you're there ! - attach_dummy_node(node, name) - continue - if ismethod(member): - member = member.im_func - if isfunction(member): - # verify this is not an imported function - filename = getattr(member.func_code, 'co_filename', None) - if filename is None: - assert isinstance(member, object) - object_build_methoddescriptor(node, member, name) - elif filename != getattr(self._module, '__file__', None): - attach_dummy_node(node, name, member) - else: - object_build_function(node, member, name) - elif isbuiltin(member): - if self.imported_member(node, member, name): - #if obj is object: - # print 'skippp', obj, name, member - continue - object_build_methoddescriptor(node, member, name) - elif isclass(member): - if self.imported_member(node, member, name): - continue - if member in self._done: - class_node = self._done[member] - if not class_node in node.locals.get(name, ()): - node.add_local_node(class_node, name) - else: - class_node = object_build_class(node, member, name) - # recursion - self.object_build(class_node, member) - if name == '__class__' and class_node.parent is None: - class_node.parent = self._done[self._module] - elif ismethoddescriptor(member): - assert isinstance(member, object) - object_build_methoddescriptor(node, member, name) - elif isdatadescriptor(member): - assert isinstance(member, object) - object_build_datadescriptor(node, member, name) - elif isinstance(member, _CONSTANTS): - attach_const_node(node, name, member) - else: - # create an empty node so that the name is actually defined - attach_dummy_node(node, name, member) - - def imported_member(self, node, member, name): - """verify this is not an imported class or handle it""" - # /!\ some classes like ExtensionClass doesn't have a __module__ - # attribute ! Also, this may trigger an exception on badly built module - # (see http://www.logilab.org/ticket/57299 for instance) - try: - modname = getattr(member, '__module__', None) - except: - # XXX use logging - print 'unexpected error while building astng from living object' - import traceback - traceback.print_exc() - modname = None - if modname is None: - if name in ('__new__', '__subclasshook__'): - # Python 2.5.1 (r251:54863, Sep 1 2010, 22:03:14) - # >>> print object.__new__.__module__ - # None - modname = BUILTINS_MODULE - else: - attach_dummy_node(node, name, member) - return True - if {'gtk': 'gtk._gtk'}.get(modname, modname) != self._module.__name__: - # check if it sounds valid and then add an import node, else use a - # dummy node - try: - getattr(sys.modules[modname], name) - except (KeyError, AttributeError): - attach_dummy_node(node, name, member) - else: - attach_import_node(node, modname, name) - return True - return False - - -### astng boot strapping ################################################### ### - -_CONST_PROXY = {} -def astng_boot_strapping(): - """astng boot strapping the builtins module""" - # this boot strapping is necessary since we need the Const nodes to - # inspect_build builtins, and then we can proxy Const - builder = InspectBuilder() - from ..common.compat import builtins - astng_builtin = builder.inspect_build(builtins) - for cls, node_cls in CONST_CLS.items(): - if cls is type(None): - proxy = build_class('NoneType') - proxy.parent = astng_builtin - else: - proxy = astng_builtin.getattr(cls.__name__)[0] # XXX - if cls in (dict, list, set, tuple): - node_cls._proxied = proxy - else: - _CONST_PROXY[cls] = proxy - -astng_boot_strapping() - -# TODO : find a nicer way to handle this situation; -# However __proxied introduced an -# infinite recursion (see https://bugs.launchpad.net/pylint/+bug/456870) -def _set_proxied(const): - return _CONST_PROXY[const.value.__class__] -Const._proxied = property(_set_proxied) - -# FIXME : is it alright that Generator._proxied is not a astng node? -Generator._proxied = MANAGER.infer_astng_from_something(type(a for a in ())) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/rebuilder.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/rebuilder.py @@ -1,886 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""this module contains utilities for rebuilding a _ast tree in -order to get a single ASTNG representation -""" - -import sys -from _ast import (Expr as Discard, Str, - # binary operators - Add, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor, - LShift, RShift, - # logical operators - And, Or, - # unary operators - UAdd, USub, Not, Invert, - # comparison operators - Eq, Gt, GtE, In, Is, IsNot, Lt, LtE, NotEq, NotIn, - ) - -from .exceptions import ASTNGBuildingException -from . import nodes as new - - -_BIN_OP_CLASSES = {Add: '+', - BitAnd: '&', - BitOr: '|', - BitXor: '^', - Div: '/', - FloorDiv: '//', - Mod: '%', - Mult: '*', - Pow: '**', - Sub: '-', - LShift: '<<', - RShift: '>>'} - -_BOOL_OP_CLASSES = {And: 'and', - Or: 'or'} - -_UNARY_OP_CLASSES = {UAdd: '+', - USub: '-', - Not: 'not', - Invert: '~'} - -_CMP_OP_CLASSES = {Eq: '==', - Gt: '>', - GtE: '>=', - In: 'in', - Is: 'is', - IsNot: 'is not', - Lt: '<', - LtE: '<=', - NotEq: '!=', - NotIn: 'not in'} - -CONST_NAME_TRANSFORMS = {'None': None, - 'True': True, - 'False': False} - -REDIRECT = {'arguments': 'Arguments', - 'Attribute': 'Getattr', - 'comprehension': 'Comprehension', - 'Call': 'CallFunc', - 'ClassDef': 'Class', - "ListCompFor": 'Comprehension', - "GenExprFor": 'Comprehension', - 'excepthandler': 'ExceptHandler', - 'Expr': 'Discard', - 'FunctionDef': 'Function', - 'GeneratorExp': 'GenExpr', - 'ImportFrom': 'From', - 'keyword': 'Keyword', - 'Repr': 'Backquote', - } - -def _init_set_doc(node, newnode): - newnode.doc = None - try: - if isinstance(node.body[0], Discard) and isinstance(node.body[0].value, Str): - newnode.tolineno = node.body[0].lineno - newnode.doc = node.body[0].value.s - node.body = node.body[1:] - - except IndexError: - pass # ast built from scratch - -def _lineno_parent(oldnode, newnode, parent): - newnode.parent = parent - if hasattr(oldnode, 'lineno'): - newnode.lineno = oldnode.lineno - if hasattr(oldnode, 'col_offset'): - newnode.col_offset = oldnode.col_offset - -def _set_infos(oldnode, newnode, parent): - newnode.parent = parent - if hasattr(oldnode, 'lineno'): - newnode.lineno = oldnode.lineno - if hasattr(oldnode, 'col_offset'): - newnode.col_offset = oldnode.col_offset - newnode.set_line_info(newnode.last_child()) # set_line_info accepts None - - - - -class TreeRebuilder(object): - """Rebuilds the _ast tree to become an ASTNG tree""" - - _visit_meths = {} - def __init__(self): - self.init() - - def init(self): - self.asscontext = None - self._metaclass = [''] - self._global_names = [] - self._from_nodes = [] - self._delayed_assattr = [] - - def visit(self, node, parent): - cls = node.__class__ - if cls in self._visit_meths: - return self._visit_meths[cls](node, parent) - else: - cls_name = cls.__name__ - visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower() - visit_method = getattr(self, visit_name) - self._visit_meths[cls] = visit_method - return visit_method(node, parent) - - def _save_assignment(self, node, name=None): - """save assignement situation since node.parent is not available yet""" - if self._global_names and node.name in self._global_names[-1]: - node.root().set_local(node.name, node) - else: - node.parent.set_local(node.name, node) - - - def visit_arguments(self, node, parent): - """visit a Arguments node by returning a fresh instance of it""" - newnode = new.Arguments() - _lineno_parent(node, newnode, parent) - self.asscontext = "Ass" - newnode.args = [self.visit(child, newnode) for child in node.args] - self.asscontext = None - newnode.defaults = [self.visit(child, newnode) for child in node.defaults] - newnode.vararg = node.vararg - newnode.kwarg = node.kwarg - # save argument names in locals: - if node.vararg: - newnode.parent.set_local(newnode.vararg, newnode) - if node.kwarg: - newnode.parent.set_local(newnode.kwarg, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_assattr(self, node, parent): - """visit a AssAttr node by returning a fresh instance of it""" - assc, self.asscontext = self.asscontext, None - newnode = new.AssAttr() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.expr, newnode) - self.asscontext = assc - self._delayed_assattr.append(newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_assert(self, node, parent): - """visit a Assert node by returning a fresh instance of it""" - newnode = new.Assert() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode) - if node.msg is not None: - newnode.fail = self.visit(node.msg, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_assign(self, node, parent): - """visit a Assign node by returning a fresh instance of it""" - newnode = new.Assign() - _lineno_parent(node, newnode, parent) - self.asscontext = "Ass" - newnode.targets = [self.visit(child, newnode) for child in node.targets] - self.asscontext = None - newnode.value = self.visit(node.value, newnode) - # set some function or metaclass infos XXX explain ? - klass = newnode.parent.frame() - if (isinstance(klass, new.Class) - and isinstance(newnode.value, new.CallFunc) - and isinstance(newnode.value.func, new.Name)): - func_name = newnode.value.func.name - for ass_node in newnode.targets: - try: - meth = klass[ass_node.name] - if isinstance(meth, new.Function): - if func_name in ('classmethod', 'staticmethod'): - meth.type = func_name - elif func_name == 'classproperty': # see lgc.decorators - meth.type = 'classmethod' - meth.extra_decorators.append(newnode.value) - except (AttributeError, KeyError): - continue - elif getattr(newnode.targets[0], 'name', None) == '__metaclass__': - # XXX check more... - self._metaclass[-1] = 'type' # XXX get the actual metaclass - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_assname(self, node, parent, node_name=None): - '''visit a node and return a AssName node''' - newnode = new.AssName() - _set_infos(node, newnode, parent) - newnode.name = node_name - self._save_assignment(newnode) - return newnode - - def visit_augassign(self, node, parent): - """visit a AugAssign node by returning a fresh instance of it""" - newnode = new.AugAssign() - _lineno_parent(node, newnode, parent) - newnode.op = _BIN_OP_CLASSES[node.op.__class__] + "=" - self.asscontext = "Ass" - newnode.target = self.visit(node.target, newnode) - self.asscontext = None - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_backquote(self, node, parent): - """visit a Backquote node by returning a fresh instance of it""" - newnode = new.Backquote() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_binop(self, node, parent): - """visit a BinOp node by returning a fresh instance of it""" - newnode = new.BinOp() - _lineno_parent(node, newnode, parent) - newnode.left = self.visit(node.left, newnode) - newnode.right = self.visit(node.right, newnode) - newnode.op = _BIN_OP_CLASSES[node.op.__class__] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_boolop(self, node, parent): - """visit a BoolOp node by returning a fresh instance of it""" - newnode = new.BoolOp() - _lineno_parent(node, newnode, parent) - newnode.values = [self.visit(child, newnode) for child in node.values] - newnode.op = _BOOL_OP_CLASSES[node.op.__class__] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_break(self, node, parent): - """visit a Break node by returning a fresh instance of it""" - newnode = new.Break() - _set_infos(node, newnode, parent) - return newnode - - def visit_callfunc(self, node, parent): - """visit a CallFunc node by returning a fresh instance of it""" - newnode = new.CallFunc() - _lineno_parent(node, newnode, parent) - newnode.func = self.visit(node.func, newnode) - newnode.args = [self.visit(child, newnode) for child in node.args] - if node.starargs is not None: - newnode.starargs = self.visit(node.starargs, newnode) - if node.kwargs is not None: - newnode.kwargs = self.visit(node.kwargs, newnode) - newnode.args.extend(self.visit(child, newnode) for child in node.keywords) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_class(self, node, parent): - """visit a Class node to become astng""" - self._metaclass.append(self._metaclass[-1]) - newnode = new.Class(node.name, None) - _lineno_parent(node, newnode, parent) - _init_set_doc(node, newnode) - newnode.bases = [self.visit(child, newnode) for child in node.bases] - newnode.body = [self.visit(child, newnode) for child in node.body] - if 'decorator_list' in node._fields and node.decorator_list:# py >= 2.6 - newnode.decorators = self.visit_decorators(node, newnode) - newnode.set_line_info(newnode.last_child()) - metaclass = self._metaclass.pop() - if not newnode.bases: - # no base classes, detect new / style old style according to - # current scope - newnode._newstyle = metaclass == 'type' - newnode.parent.frame().set_local(newnode.name, newnode) - return newnode - - def visit_const(self, node, parent): - """visit a Const node by returning a fresh instance of it""" - newnode = new.Const(node.value) - _set_infos(node, newnode, parent) - return newnode - - def visit_continue(self, node, parent): - """visit a Continue node by returning a fresh instance of it""" - newnode = new.Continue() - _set_infos(node, newnode, parent) - return newnode - - def visit_compare(self, node, parent): - """visit a Compare node by returning a fresh instance of it""" - newnode = new.Compare() - _lineno_parent(node, newnode, parent) - newnode.left = self.visit(node.left, newnode) - newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode)) - for (op, expr) in zip(node.ops, node.comparators)] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_comprehension(self, node, parent): - """visit a Comprehension node by returning a fresh instance of it""" - newnode = new.Comprehension() - _lineno_parent(node, newnode, parent) - self.asscontext = "Ass" - newnode.target = self.visit(node.target, newnode) - self.asscontext = None - newnode.iter = self.visit(node.iter, newnode) - newnode.ifs = [self.visit(child, newnode) for child in node.ifs] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_decorators(self, node, parent): - """visit a Decorators node by returning a fresh instance of it""" - # /!\ node is actually a _ast.Function node while - # parent is a astng.nodes.Function node - newnode = new.Decorators() - _lineno_parent(node, newnode, parent) - if 'decorators' in node._fields: # py < 2.6, i.e. 2.5 - decorators = node.decorators - else: - decorators= node.decorator_list - newnode.nodes = [self.visit(child, newnode) for child in decorators] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_delete(self, node, parent): - """visit a Delete node by returning a fresh instance of it""" - newnode = new.Delete() - _lineno_parent(node, newnode, parent) - self.asscontext = "Del" - newnode.targets = [self.visit(child, newnode) for child in node.targets] - self.asscontext = None - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_dict(self, node, parent): - """visit a Dict node by returning a fresh instance of it""" - newnode = new.Dict() - _lineno_parent(node, newnode, parent) - newnode.items = [(self.visit(key, newnode), self.visit(value, newnode)) - for key, value in zip(node.keys, node.values)] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_dictcomp(self, node, parent): - """visit a DictComp node by returning a fresh instance of it""" - newnode = new.DictComp() - _lineno_parent(node, newnode, parent) - newnode.key = self.visit(node.key, newnode) - newnode.value = self.visit(node.value, newnode) - newnode.generators = [self.visit(child, newnode) - for child in node.generators] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_discard(self, node, parent): - """visit a Discard node by returning a fresh instance of it""" - newnode = new.Discard() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_ellipsis(self, node, parent): - """visit an Ellipsis node by returning a fresh instance of it""" - newnode = new.Ellipsis() - _set_infos(node, newnode, parent) - return newnode - - def visit_emptynode(self, node, parent): - """visit an EmptyNode node by returning a fresh instance of it""" - newnode = new.EmptyNode() - _set_infos(node, newnode, parent) - return newnode - - def visit_excepthandler(self, node, parent): - """visit an ExceptHandler node by returning a fresh instance of it""" - newnode = new.ExceptHandler() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.type = self.visit(node.type, newnode) - if node.name is not None: - # /!\ node.name can be a tuple - self.asscontext = "Ass" - newnode.name = self.visit(node.name, newnode) - self.asscontext = None - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_exec(self, node, parent): - """visit an Exec node by returning a fresh instance of it""" - newnode = new.Exec() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.body, newnode) - if node.globals is not None: - newnode.globals = self.visit(node.globals, newnode) - if node.locals is not None: - newnode.locals = self.visit(node.locals, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_extslice(self, node, parent): - """visit an ExtSlice node by returning a fresh instance of it""" - newnode = new.ExtSlice() - _lineno_parent(node, newnode, parent) - newnode.dims = [self.visit(dim, newnode) for dim in node.dims] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_for(self, node, parent): - """visit a For node by returning a fresh instance of it""" - newnode = new.For() - _lineno_parent(node, newnode, parent) - self.asscontext = "Ass" - newnode.target = self.visit(node.target, newnode) - self.asscontext = None - newnode.iter = self.visit(node.iter, newnode) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.orelse = [self.visit(child, newnode) for child in node.orelse] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_from(self, node, parent): - """visit a From node by returning a fresh instance of it""" - names = [(alias.name, alias.asname) for alias in node.names] - newnode = new.From(node.module or '', names, node.level or None) - _set_infos(node, newnode, parent) - # store From names to add them to locals after building - self._from_nodes.append(newnode) - return newnode - - def visit_function(self, node, parent): - """visit an Function node to become astng""" - self._global_names.append({}) - newnode = new.Function(node.name, None) - _lineno_parent(node, newnode, parent) - _init_set_doc(node, newnode) - newnode.args = self.visit(node.args, newnode) - newnode.body = [self.visit(child, newnode) for child in node.body] - if 'decorators' in node._fields: # py < 2.6 - attr = 'decorators' - else: - attr = 'decorator_list' - decorators = getattr(node, attr) - if decorators: - newnode.decorators = self.visit_decorators(node, newnode) - newnode.set_line_info(newnode.last_child()) - self._global_names.pop() - frame = newnode.parent.frame() - if isinstance(frame, new.Class): - if newnode.name == '__new__': - newnode.type = 'classmethod' - else: - newnode.type = 'method' - if newnode.decorators is not None: - for decorator_expr in newnode.decorators.nodes: - if isinstance(decorator_expr, new.Name): - if decorator_expr.name in ('classmethod', 'staticmethod'): - newnode.type = decorator_expr.name - elif decorator_expr.name == 'classproperty': - newnode.type = 'classmethod' - frame.set_local(newnode.name, newnode) - return newnode - - def visit_genexpr(self, node, parent): - """visit a GenExpr node by returning a fresh instance of it""" - newnode = new.GenExpr() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode) - newnode.generators = [self.visit(child, newnode) for child in node.generators] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_getattr(self, node, parent): - """visit a Getattr node by returning a fresh instance of it""" - if self.asscontext == "Del": - # FIXME : maybe we should reintroduce and visit_delattr ? - # for instance, deactivating asscontext - newnode = new.DelAttr() - elif self.asscontext == "Ass": - # FIXME : maybe we should call visit_assattr ? - newnode = new.AssAttr() - self._delayed_assattr.append(newnode) - else: - newnode = new.Getattr() - _lineno_parent(node, newnode, parent) - asscontext, self.asscontext = self.asscontext, None - newnode.expr = self.visit(node.value, newnode) - self.asscontext = asscontext - newnode.attrname = node.attr - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_global(self, node, parent): - """visit an Global node to become astng""" - newnode = new.Global(node.names) - _set_infos(node, newnode, parent) - if self._global_names: # global at the module level, no effect - for name in node.names: - self._global_names[-1].setdefault(name, []).append(newnode) - return newnode - - def visit_if(self, node, parent): - """visit a If node by returning a fresh instance of it""" - newnode = new.If() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.orelse = [self.visit(child, newnode) for child in node.orelse] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_ifexp(self, node, parent): - """visit a IfExp node by returning a fresh instance of it""" - newnode = new.IfExp() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode) - newnode.body = self.visit(node.body, newnode) - newnode.orelse = self.visit(node.orelse, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_import(self, node, parent): - """visit a Import node by returning a fresh instance of it""" - newnode = new.Import() - _set_infos(node, newnode, parent) - newnode.names = [(alias.name, alias.asname) for alias in node.names] - # save import names in parent's locals: - for (name, asname) in newnode.names: - name = asname or name - newnode.parent.set_local(name.split('.')[0], newnode) - return newnode - - def visit_index(self, node, parent): - """visit a Index node by returning a fresh instance of it""" - newnode = new.Index() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_keyword(self, node, parent): - """visit a Keyword node by returning a fresh instance of it""" - newnode = new.Keyword() - _lineno_parent(node, newnode, parent) - newnode.arg = node.arg - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_lambda(self, node, parent): - """visit a Lambda node by returning a fresh instance of it""" - newnode = new.Lambda() - _lineno_parent(node, newnode, parent) - newnode.args = self.visit(node.args, newnode) - newnode.body = self.visit(node.body, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_list(self, node, parent): - """visit a List node by returning a fresh instance of it""" - newnode = new.List() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode) for child in node.elts] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_listcomp(self, node, parent): - """visit a ListComp node by returning a fresh instance of it""" - newnode = new.ListComp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode) - newnode.generators = [self.visit(child, newnode) - for child in node.generators] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_module(self, node, modname, package): - """visit a Module node by returning a fresh instance of it""" - newnode = new.Module(modname, None) - newnode.package = package - _lineno_parent(node, newnode, parent=None) - _init_set_doc(node, newnode) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_name(self, node, parent): - """visit a Name node by returning a fresh instance of it""" - # True and False can be assigned to something in py2x, so we have to - # check first the asscontext - if self.asscontext == "Del": - newnode = new.DelName() - elif self.asscontext is not None: # Ass - assert self.asscontext == "Ass" - newnode = new.AssName() - elif node.id in CONST_NAME_TRANSFORMS: - newnode = new.Const(CONST_NAME_TRANSFORMS[node.id]) - _set_infos(node, newnode, parent) - return newnode - else: - newnode = new.Name() - _lineno_parent(node, newnode, parent) - newnode.name = node.id - # XXX REMOVE me : - if self.asscontext in ('Del', 'Ass'): # 'Aug' ?? - self._save_assignment(newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_bytes(self, node, parent): - """visit a Bytes node by returning a fresh instance of Const""" - newnode = new.Const(node.s) - _set_infos(node, newnode, parent) - return newnode - - def visit_num(self, node, parent): - """visit a Num node by returning a fresh instance of Const""" - newnode = new.Const(node.n) - _set_infos(node, newnode, parent) - return newnode - - def visit_pass(self, node, parent): - """visit a Pass node by returning a fresh instance of it""" - newnode = new.Pass() - _set_infos(node, newnode, parent) - return newnode - - def visit_str(self, node, parent): - """visit a Str node by returning a fresh instance of Const""" - newnode = new.Const(node.s) - _set_infos(node, newnode, parent) - return newnode - - def visit_print(self, node, parent): - """visit a Print node by returning a fresh instance of it""" - newnode = new.Print() - _lineno_parent(node, newnode, parent) - newnode.nl = node.nl - if node.dest is not None: - newnode.dest = self.visit(node.dest, newnode) - newnode.values = [self.visit(child, newnode) for child in node.values] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_raise(self, node, parent): - """visit a Raise node by returning a fresh instance of it""" - newnode = new.Raise() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.exc = self.visit(node.type, newnode) - if node.inst is not None: - newnode.inst = self.visit(node.inst, newnode) - if node.tback is not None: - newnode.tback = self.visit(node.tback, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_return(self, node, parent): - """visit a Return node by returning a fresh instance of it""" - newnode = new.Return() - _lineno_parent(node, newnode, parent) - if node.value is not None: - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_set(self, node, parent): - """visit a Tuple node by returning a fresh instance of it""" - newnode = new.Set() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode) for child in node.elts] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_setcomp(self, node, parent): - """visit a SetComp node by returning a fresh instance of it""" - newnode = new.SetComp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode) - newnode.generators = [self.visit(child, newnode) - for child in node.generators] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_slice(self, node, parent): - """visit a Slice node by returning a fresh instance of it""" - newnode = new.Slice() - _lineno_parent(node, newnode, parent) - if node.lower is not None: - newnode.lower = self.visit(node.lower, newnode) - if node.upper is not None: - newnode.upper = self.visit(node.upper, newnode) - if node.step is not None: - newnode.step = self.visit(node.step, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_subscript(self, node, parent): - """visit a Subscript node by returning a fresh instance of it""" - newnode = new.Subscript() - _lineno_parent(node, newnode, parent) - subcontext, self.asscontext = self.asscontext, None - newnode.value = self.visit(node.value, newnode) - newnode.slice = self.visit(node.slice, newnode) - self.asscontext = subcontext - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_tryexcept(self, node, parent): - """visit a TryExcept node by returning a fresh instance of it""" - newnode = new.TryExcept() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.handlers = [self.visit(child, newnode) for child in node.handlers] - newnode.orelse = [self.visit(child, newnode) for child in node.orelse] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_tryfinally(self, node, parent): - """visit a TryFinally node by returning a fresh instance of it""" - newnode = new.TryFinally() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_tuple(self, node, parent): - """visit a Tuple node by returning a fresh instance of it""" - newnode = new.Tuple() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode) for child in node.elts] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_unaryop(self, node, parent): - """visit a UnaryOp node by returning a fresh instance of it""" - newnode = new.UnaryOp() - _lineno_parent(node, newnode, parent) - newnode.operand = self.visit(node.operand, newnode) - newnode.op = _UNARY_OP_CLASSES[node.op.__class__] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_while(self, node, parent): - """visit a While node by returning a fresh instance of it""" - newnode = new.While() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.orelse = [self.visit(child, newnode) for child in node.orelse] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_with(self, node, parent): - newnode = new.With() - _lineno_parent(node, newnode, parent) - _node = getattr(node, 'items', [node])[0] # python 3.3 XXX - newnode.expr = self.visit(_node.context_expr, newnode) - self.asscontext = "Ass" - if _node.optional_vars is not None: - newnode.vars = self.visit(_node.optional_vars, newnode) - self.asscontext = None - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_yield(self, node, parent): - """visit a Yield node by returning a fresh instance of it""" - newnode = new.Yield() - _lineno_parent(node, newnode, parent) - if node.value is not None: - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - -class TreeRebuilder3k(TreeRebuilder): - """extend and overwrite TreeRebuilder for python3k""" - - def visit_arg(self, node, parent): - """visit a arg node by returning a fresh AssName instance""" - # the <arg> node is coming from py>=3.0, but we use AssName in py2.x - # XXX or we should instead introduce a Arg node in astng ? - return self.visit_assname(node, parent, node.arg) - - def visit_excepthandler(self, node, parent): - """visit an ExceptHandler node by returning a fresh instance of it""" - newnode = new.ExceptHandler() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.type = self.visit(node.type, newnode) - if node.name is not None: - newnode.name = self.visit_assname(node, newnode, node.name) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_nonlocal(self, node, parent): - """visit a Nonlocal node and return a new instance of it""" - newnode = new.Nonlocal(node.names) - _set_infos(node, newnode, parent) - return newnode - - def visit_raise(self, node, parent): - """visit a Raise node by returning a fresh instance of it""" - newnode = new.Raise() - _lineno_parent(node, newnode, parent) - # no traceback; anyway it is not used in Pylint - if node.exc is not None: - newnode.exc = self.visit(node.exc, newnode) - if node.cause is not None: - newnode.cause = self.visit(node.cause, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_starred(self, node, parent): - """visit a Starred node and return a new instance of it""" - newnode = new.Starred() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode) - newnode.set_line_info(newnode.last_child()) - return newnode - - def visit_try(self, node, parent): - # python 3.3 introduce a new Try node replacing TryFinally/TryExcept nodes - if node.finalbody: - newnode = new.TryFinally() - _lineno_parent(node, newnode, parent) - newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody] - if node.handlers: - excnode = new.TryExcept() - _lineno_parent(node, excnode, parent) - excnode.body = [self.visit(child, newnode) for child in node.body] - excnode.handlers = [self.visit(child, newnode) for child in node.handlers] - excnode.orelse = [self.visit(child, newnode) for child in node.orelse] - newnode.body = [excnode] - else: - newnode.body = [self.visit(child, newnode) for child in node.body] - elif node.handlers: - newnode = new.TryExcept() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.handlers = [self.visit(child, newnode) for child in node.handlers] - newnode.orelse = [self.visit(child, newnode) for child in node.orelse] - newnode.set_line_info(newnode.last_child()) - return newnode - - -if sys.version_info >= (3, 0): - TreeRebuilder = TreeRebuilder3k - - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/scoped_nodes.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/scoped_nodes.py @@ -1,981 +0,0 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""This module contains the classes for "scoped" node, i.e. which are opening a -new local scope in the language definition : Module, Class, Function (and -Lambda, GenExpr, DictComp and SetComp to some extent). -""" -from __future__ import with_statement - -__doctype__ = "restructuredtext en" - -import sys -from itertools import chain - -from ..common.compat import builtins -from ..common.decorators import cached - -from . import BUILTINS_MODULE -from .exceptions import NotFoundError, NoDefault, \ - ASTNGBuildingException, InferenceError -from .node_classes import Const, DelName, DelAttr, \ - Dict, From, List, Name, Pass, Raise, Return, Tuple, Yield, \ - are_exclusive, LookupMixIn, const_factory as cf, unpack_infer -from .bases import NodeNG, InferenceContext, Instance,\ - YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context, \ - BUILTINS_NAME -from .mixins import FilterStmtsMixin -from .bases import Statement -from .manager import ASTNGManager - - -def remove_nodes(func, cls): - def wrapper(*args, **kwargs): - nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)] - if not nodes: - raise NotFoundError() - return nodes - return wrapper - - -def function_to_method(n, klass): - if isinstance(n, Function): - if n.type == 'classmethod': - return BoundMethod(n, klass) - if n.type != 'staticmethod': - return UnboundMethod(n) - return n - -def std_special_attributes(self, name, add_locals=True): - if add_locals: - locals = self.locals - else: - locals = {} - if name == '__name__': - return [cf(self.name)] + locals.get(name, []) - if name == '__doc__': - return [cf(self.doc)] + locals.get(name, []) - if name == '__dict__': - return [Dict()] + locals.get(name, []) - raise NotFoundError(name) - -MANAGER = ASTNGManager() -def builtin_lookup(name): - """lookup a name into the builtin module - return the list of matching statements and the astng for the builtin - module - """ - builtin_astng = MANAGER.astng_from_module(builtins) - if name == '__dict__': - return builtin_astng, () - try: - stmts = builtin_astng.locals[name] - except KeyError: - stmts = () - return builtin_astng, stmts - - -# TODO move this Mixin to mixins.py; problem: 'Function' in _scope_lookup -class LocalsDictNodeNG(LookupMixIn, NodeNG): - """ this class provides locals handling common to Module, Function - and Class nodes, including a dict like interface for direct access - to locals information - """ - - # attributes below are set by the builder module or by raw factories - - # dictionary of locals with name as key and node defining the local as - # value - - def qname(self): - """return the 'qualified' name of the node, eg module.name, - module.class.name ... - """ - if self.parent is None: - return self.name - return '%s.%s' % (self.parent.frame().qname(), self.name) - - def frame(self): - """return the first parent frame node (i.e. Module, Function or Class) - """ - return self - - def scope(self): - """return the first node defining a new scope (i.e. Module, - Function, Class, Lambda but also GenExpr, DictComp and SetComp) - """ - return self - - - def _scope_lookup(self, node, name, offset=0): - """XXX method for interfacing the scope lookup""" - try: - stmts = node._filter_stmts(self.locals[name], self, offset) - except KeyError: - stmts = () - if stmts: - return self, stmts - if self.parent: # i.e. not Module - # nested scope: if parent scope is a function, that's fine - # else jump to the module - pscope = self.parent.scope() - if not pscope.is_function: - pscope = pscope.root() - return pscope.scope_lookup(node, name) - return builtin_lookup(name) # Module - - - - def set_local(self, name, stmt): - """define <name> in locals (<stmt> is the node defining the name) - if the node is a Module node (i.e. has globals), add the name to - globals - - if the name is already defined, ignore it - """ - #assert not stmt in self.locals.get(name, ()), (self, stmt) - self.locals.setdefault(name, []).append(stmt) - - __setitem__ = set_local - - def _append_node(self, child): - """append a child, linking it in the tree""" - self.body.append(child) - child.parent = self - - def add_local_node(self, child_node, name=None): - """append a child which should alter locals to the given node""" - if name != '__class__': - # add __class__ node as a child will cause infinite recursion later! - self._append_node(child_node) - self.set_local(name or child_node.name, child_node) - - - def __getitem__(self, item): - """method from the `dict` interface returning the first node - associated with the given name in the locals dictionary - - :type item: str - :param item: the name of the locally defined object - :raises KeyError: if the name is not defined - """ - return self.locals[item][0] - - def __iter__(self): - """method from the `dict` interface returning an iterator on - `self.keys()` - """ - return iter(self.keys()) - - def keys(self): - """method from the `dict` interface returning a tuple containing - locally defined names - """ - return self.locals.keys() - - def values(self): - """method from the `dict` interface returning a tuple containing - locally defined nodes which are instance of `Function` or `Class` - """ - return [self[key] for key in self.keys()] - - def items(self): - """method from the `dict` interface returning a list of tuple - containing each locally defined name with its associated node, - which is an instance of `Function` or `Class` - """ - return zip(self.keys(), self.values()) - - - def __contains__(self, name): - return name in self.locals - has_key = __contains__ - -# Module ##################################################################### - -class Module(LocalsDictNodeNG): - _astng_fields = ('body',) - - fromlineno = 0 - lineno = 0 - - # attributes below are set by the builder module or by raw factories - - # the file from which as been extracted the astng representation. It may - # be None if the representation has been built from a built-in module - file = None - # encoding of python source file, so we can get unicode out of it (python2 - # only) - file_encoding = None - # the module name - name = None - # boolean for astng built from source (i.e. ast) - pure_python = None - # boolean for package module - package = None - # dictionary of globals with name as key and node defining the global - # as value - globals = None - - # names of python special attributes (handled by getattr impl.) - special_attributes = set(('__name__', '__doc__', '__file__', '__path__', - '__dict__')) - # names of module attributes available through the global scope - scope_attrs = set(('__name__', '__doc__', '__file__', '__path__')) - - def __init__(self, name, doc, pure_python=True): - self.name = name - self.doc = doc - self.pure_python = pure_python - self.locals = self.globals = {} - self.body = [] - - @property - def file_stream(self): - if self.file is not None: - return open(self.file) - return None - - def block_range(self, lineno): - """return block line numbers. - - start from the beginning whatever the given lineno - """ - return self.fromlineno, self.tolineno - - def scope_lookup(self, node, name, offset=0): - if name in self.scope_attrs and not name in self.locals: - try: - return self, self.getattr(name) - except NotFoundError: - return self, () - return self._scope_lookup(node, name, offset) - - def pytype(self): - return '%s.module' % BUILTINS_MODULE - - def display_type(self): - return 'Module' - - def getattr(self, name, context=None, ignore_locals=False): - if name in self.special_attributes: - if name == '__file__': - return [cf(self.file)] + self.locals.get(name, []) - if name == '__path__' and self.package: - return [List()] + self.locals.get(name, []) - return std_special_attributes(self, name) - if not ignore_locals and name in self.locals: - return self.locals[name] - if self.package: - try: - return [self.import_module(name, relative_only=True)] - except ASTNGBuildingException: - raise NotFoundError(name) - except Exception:# XXX pylint tests never pass here; do we need it? - import traceback - traceback.print_exc() - raise NotFoundError(name) - getattr = remove_nodes(getattr, DelName) - - def igetattr(self, name, context=None): - """inferred getattr""" - # set lookup name since this is necessary to infer on import nodes for - # instance - context = copy_context(context) - context.lookupname = name - try: - return _infer_stmts(self.getattr(name, context), context, frame=self) - except NotFoundError: - raise InferenceError(name) - - def fully_defined(self): - """return True if this module has been built from a .py file - and so contains a complete representation including the code - """ - return self.file is not None and self.file.endswith('.py') - - def statement(self): - """return the first parent node marked as statement node - consider a module as a statement... - """ - return self - - def previous_sibling(self): - """module has no sibling""" - return - - def next_sibling(self): - """module has no sibling""" - return - - if sys.version_info < (2, 8): - def absolute_import_activated(self): - for stmt in self.locals.get('absolute_import', ()): - if isinstance(stmt, From) and stmt.modname == '__future__': - return True - return False - else: - absolute_import_activated = lambda self: True - - def import_module(self, modname, relative_only=False, level=None): - """import the given module considering self as context""" - if relative_only and level is None: - level = 0 - absmodname = self.relative_to_absolute_name(modname, level) - try: - return MANAGER.astng_from_module_name(absmodname) - except ASTNGBuildingException: - # we only want to import a sub module or package of this module, - # skip here - if relative_only: - raise - return MANAGER.astng_from_module_name(modname) - - def relative_to_absolute_name(self, modname, level): - """return the absolute module name for a relative import. - - The relative import can be implicit or explicit. - """ - # XXX this returns non sens when called on an absolute import - # like 'pylint.checkers.logilab.astng.utils' - # XXX doesn't return absolute name if self.name isn't absolute name - if self.absolute_import_activated() and level is None: - return modname - if level: - if self.package: - level = level - 1 - package_name = self.name.rsplit('.', level)[0] - elif self.package: - package_name = self.name - else: - package_name = self.name.rsplit('.', 1)[0] - if package_name: - if not modname: - return package_name - return '%s.%s' % (package_name, modname) - return modname - - - def wildcard_import_names(self): - """return the list of imported names when this module is 'wildcard - imported' - - It doesn't include the '__builtins__' name which is added by the - current CPython implementation of wildcard imports. - """ - # take advantage of a living module if it exists - try: - living = sys.modules[self.name] - except KeyError: - pass - else: - try: - return living.__all__ - except AttributeError: - return [name for name in living.__dict__.keys() - if not name.startswith('_')] - # else lookup the astng - # - # We separate the different steps of lookup in try/excepts - # to avoid catching too many Exceptions - # However, we can not analyse dynamically constructed __all__ - try: - all = self['__all__'] - except KeyError: - return [name for name in self.keys() if not name.startswith('_')] - try: - explicit = all.assigned_stmts().next() - except InferenceError: - return [name for name in self.keys() if not name.startswith('_')] - except AttributeError: - # not an assignment node - # XXX infer? - return [name for name in self.keys() if not name.startswith('_')] - try: - # should be a Tuple/List of constant string / 1 string not allowed - return [const.value for const in explicit.elts] - except AttributeError: - return [name for name in self.keys() if not name.startswith('_')] - - -class ComprehensionScope(LocalsDictNodeNG): - def frame(self): - return self.parent.frame() - - scope_lookup = LocalsDictNodeNG._scope_lookup - - -class GenExpr(ComprehensionScope): - _astng_fields = ('elt', 'generators') - - def __init__(self): - self.locals = {} - self.elt = None - self.generators = [] - - -class DictComp(ComprehensionScope): - _astng_fields = ('key', 'value', 'generators') - - def __init__(self): - self.locals = {} - self.key = None - self.value = None - self.generators = [] - - -class SetComp(ComprehensionScope): - _astng_fields = ('elt', 'generators') - - def __init__(self): - self.locals = {} - self.elt = None - self.generators = [] - - -class _ListComp(NodeNG): - """class representing a ListComp node""" - _astng_fields = ('elt', 'generators') - elt = None - generators = None - -if sys.version_info >= (3, 0): - class ListComp(_ListComp, ComprehensionScope): - """class representing a ListComp node""" - def __init__(self): - self.locals = {} -else: - class ListComp(_ListComp): - """class representing a ListComp node""" - -# Function ################################################################### - - -class Lambda(LocalsDictNodeNG, FilterStmtsMixin): - _astng_fields = ('args', 'body',) - name = '<lambda>' - - # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod' - type = 'function' - - def __init__(self): - self.locals = {} - self.args = [] - self.body = [] - - def pytype(self): - if 'method' in self.type: - return '%s.instancemethod' % BUILTINS_MODULE - return '%s.function' % BUILTINS_MODULE - - def display_type(self): - if 'method' in self.type: - return 'Method' - return 'Function' - - def callable(self): - return True - - def argnames(self): - """return a list of argument names""" - if self.args.args: # maybe None with builtin functions - names = _rec_get_names(self.args.args) - else: - names = [] - if self.args.vararg: - names.append(self.args.vararg) - if self.args.kwarg: - names.append(self.args.kwarg) - return names - - def infer_call_result(self, caller, context=None): - """infer what a function is returning when called""" - return self.body.infer(context) - - def scope_lookup(self, node, name, offset=0): - if node in self.args.defaults: - frame = self.parent.frame() - # line offset to avoid that def func(f=func) resolve the default - # value to the defined function - offset = -1 - else: - # check this is not used in function decorators - frame = self - return frame._scope_lookup(node, name, offset) - - -class Function(Statement, Lambda): - _astng_fields = ('decorators', 'args', 'body') - - special_attributes = set(('__name__', '__doc__', '__dict__')) - is_function = True - # attributes below are set by the builder module or by raw factories - blockstart_tolineno = None - decorators = None - - def __init__(self, name, doc): - self.locals = {} - self.args = [] - self.body = [] - self.decorators = None - self.name = name - self.doc = doc - self.extra_decorators = [] - self.instance_attrs = {} - - def set_line_info(self, lastchild): - self.fromlineno = self.lineno - # lineno is the line number of the first decorator, we want the def statement lineno - if self.decorators is not None: - self.fromlineno += sum(node.tolineno - node.lineno + 1 - for node in self.decorators.nodes) - self.tolineno = lastchild.tolineno - self.blockstart_tolineno = self.args.tolineno - - def block_range(self, lineno): - """return block line numbers. - - start from the "def" position whatever the given lineno - """ - return self.fromlineno, self.tolineno - - def getattr(self, name, context=None): - """this method doesn't look in the instance_attrs dictionary since it's - done by an Instance proxy at inference time. - """ - if name == '__module__': - return [cf(self.root().qname())] - if name in self.instance_attrs: - return self.instance_attrs[name] - return std_special_attributes(self, name, False) - - def is_method(self): - """return true if the function node should be considered as a method""" - # check we are defined in a Class, because this is usually expected - # (e.g. pylint...) when is_method() return True - return self.type != 'function' and isinstance(self.parent.frame(), Class) - - def decoratornames(self): - """return a list of decorator qualified names""" - result = set() - decoratornodes = [] - if self.decorators is not None: - decoratornodes += self.decorators.nodes - decoratornodes += self.extra_decorators - for decnode in decoratornodes: - for infnode in decnode.infer(): - result.add(infnode.qname()) - return result - decoratornames = cached(decoratornames) - - def is_bound(self): - """return true if the function is bound to an Instance or a class""" - return self.type == 'classmethod' - - def is_abstract(self, pass_is_abstract=True): - """return true if the method is abstract - It's considered as abstract if the only statement is a raise of - NotImplementError, or, if pass_is_abstract, a pass statement - """ - for child_node in self.body: - if isinstance(child_node, Raise): - if child_node.raises_not_implemented(): - return True - if pass_is_abstract and isinstance(child_node, Pass): - return True - return False - # empty function is the same as function with a single "pass" statement - if pass_is_abstract: - return True - - def is_generator(self): - """return true if this is a generator function""" - # XXX should be flagged, not computed - try: - return self.nodes_of_class(Yield, skip_klass=Function).next() - except StopIteration: - return False - - def infer_call_result(self, caller, context=None): - """infer what a function is returning when called""" - if self.is_generator(): - yield Generator(self) - return - returns = self.nodes_of_class(Return, skip_klass=Function) - for returnnode in returns: - if returnnode.value is None: - yield Const(None) - else: - try: - for infered in returnnode.value.infer(context): - yield infered - except InferenceError: - yield YES - - -def _rec_get_names(args, names=None): - """return a list of all argument names""" - if names is None: - names = [] - for arg in args: - if isinstance(arg, Tuple): - _rec_get_names(arg.elts, names) - else: - names.append(arg.name) - return names - - -# Class ###################################################################### - -def _class_type(klass, ancestors=None): - """return a Class node type to differ metaclass, interface and exception - from 'regular' classes - """ - # XXX we have to store ancestors in case we have a ancestor loop - if klass._type is not None: - return klass._type - if klass.name == 'type': - klass._type = 'metaclass' - elif klass.name.endswith('Interface'): - klass._type = 'interface' - elif klass.name.endswith('Exception'): - klass._type = 'exception' - else: - if ancestors is None: - ancestors = set() - if klass in ancestors: - # XXX we are in loop ancestors, and have found no type - klass._type = 'class' - return 'class' - ancestors.add(klass) - # print >> sys.stderr, '_class_type', repr(klass) - for base in klass.ancestors(recurs=False): - if _class_type(base, ancestors) != 'class': - klass._type = base.type - break - if klass._type is None: - klass._type = 'class' - return klass._type - -def _iface_hdlr(iface_node): - """a handler function used by interfaces to handle suspicious - interface nodes - """ - return True - - -class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin): - - # some of the attributes below are set by the builder module or - # by a raw factories - - # a dictionary of class instances attributes - _astng_fields = ('decorators', 'bases', 'body') # name - - decorators = None - special_attributes = set(('__name__', '__doc__', '__dict__', '__module__', - '__bases__', '__mro__', '__subclasses__')) - blockstart_tolineno = None - - _type = None - type = property(_class_type, - doc="class'type, possible values are 'class' | " - "'metaclass' | 'interface' | 'exception'") - - def __init__(self, name, doc): - self.instance_attrs = {} - self.locals = {} - self.bases = [] - self.body = [] - self.name = name - self.doc = doc - - def _newstyle_impl(self, context=None): - if context is None: - context = InferenceContext() - if self._newstyle is not None: - return self._newstyle - for base in self.ancestors(recurs=False, context=context): - if base._newstyle_impl(context): - self._newstyle = True - break - if self._newstyle is None: - self._newstyle = False - return self._newstyle - - _newstyle = None - newstyle = property(_newstyle_impl, - doc="boolean indicating if it's a new style class" - "or not") - - def set_line_info(self, lastchild): - self.fromlineno = self.lineno - self.blockstart_tolineno = self.bases and self.bases[-1].tolineno or self.fromlineno - if lastchild is not None: - self.tolineno = lastchild.tolineno - # else this is a class with only a docstring, then tolineno is (should be) already ok - - def block_range(self, lineno): - """return block line numbers. - - start from the "class" position whatever the given lineno - """ - return self.fromlineno, self.tolineno - - def pytype(self): - if self.newstyle: - return '%s.type' % BUILTINS_MODULE - return '%s.classobj' % BUILTINS_MODULE - - def display_type(self): - return 'Class' - - def callable(self): - return True - - def infer_call_result(self, caller, context=None): - """infer what a class is returning when called""" - yield Instance(self) - - def scope_lookup(self, node, name, offset=0): - if node in self.bases: - frame = self.parent.frame() - # line offset to avoid that class A(A) resolve the ancestor to - # the defined class - offset = -1 - else: - frame = self - return frame._scope_lookup(node, name, offset) - - # list of parent class as a list of string (i.e. names as they appear - # in the class definition) XXX bw compat - def basenames(self): - return [bnode.as_string() for bnode in self.bases] - basenames = property(basenames) - - def ancestors(self, recurs=True, context=None): - """return an iterator on the node base classes in a prefixed - depth first order - - :param recurs: - boolean indicating if it should recurse or return direct - ancestors only - """ - # FIXME: should be possible to choose the resolution order - # XXX inference make infinite loops possible here (see BaseTransformer - # manipulation in the builder module for instance) - yielded = set([self]) - if context is None: - context = InferenceContext() - for stmt in self.bases: - with context.restore_path(): - try: - for baseobj in stmt.infer(context): - if not isinstance(baseobj, Class): - # duh ? - continue - if baseobj in yielded: - continue # cf xxx above - yielded.add(baseobj) - yield baseobj - if recurs: - for grandpa in baseobj.ancestors(True, context): - if grandpa in yielded: - continue # cf xxx above - yielded.add(grandpa) - yield grandpa - except InferenceError: - # XXX log error ? - continue - - def local_attr_ancestors(self, name, context=None): - """return an iterator on astng representation of parent classes - which have <name> defined in their locals - """ - for astng in self.ancestors(context=context): - if name in astng: - yield astng - - def instance_attr_ancestors(self, name, context=None): - """return an iterator on astng representation of parent classes - which have <name> defined in their instance attribute dictionary - """ - for astng in self.ancestors(context=context): - if name in astng.instance_attrs: - yield astng - - def has_base(self, node): - return node in self.bases - - def local_attr(self, name, context=None): - """return the list of assign node associated to name in this class - locals or in its parents - - :raises `NotFoundError`: - if no attribute with this name has been find in this class or - its parent classes - """ - try: - return self.locals[name] - except KeyError: - # get if from the first parent implementing it if any - for class_node in self.local_attr_ancestors(name, context): - return class_node.locals[name] - raise NotFoundError(name) - local_attr = remove_nodes(local_attr, DelAttr) - - def instance_attr(self, name, context=None): - """return the astng nodes associated to name in this class instance - attributes dictionary and in its parents - - :raises `NotFoundError`: - if no attribute with this name has been find in this class or - its parent classes - """ - values = self.instance_attrs.get(name, []) - # get all values from parents - for class_node in self.instance_attr_ancestors(name, context): - values += class_node.instance_attrs[name] - if not values: - raise NotFoundError(name) - return values - instance_attr = remove_nodes(instance_attr, DelAttr) - - def instanciate_class(self): - """return Instance of Class node, else return self""" - return Instance(self) - - def getattr(self, name, context=None): - """this method doesn't look in the instance_attrs dictionary since it's - done by an Instance proxy at inference time. - - It may return a YES object if the attribute has not been actually - found but a __getattr__ or __getattribute__ method is defined - """ - values = self.locals.get(name, []) - if name in self.special_attributes: - if name == '__module__': - return [cf(self.root().qname())] + values - # FIXME : what is expected by passing the list of ancestors to cf: - # you can just do [cf(tuple())] + values without breaking any test - # this is ticket http://www.logilab.org/ticket/52785 - if name == '__bases__': - return [cf(tuple(self.ancestors(recurs=False, context=context)))] + values - # XXX need proper meta class handling + MRO implementation - if name == '__mro__' and self.newstyle: - # XXX mro is read-only but that's not our job to detect that - return [cf(tuple(self.ancestors(recurs=True, context=context)))] + values - return std_special_attributes(self, name) - # don't modify the list in self.locals! - values = list(values) - for classnode in self.ancestors(recurs=True, context=context): - values += classnode.locals.get(name, []) - if not values: - raise NotFoundError(name) - return values - - def igetattr(self, name, context=None): - """inferred getattr, need special treatment in class to handle - descriptors - """ - # set lookup name since this is necessary to infer on import nodes for - # instance - context = copy_context(context) - context.lookupname = name - try: - for infered in _infer_stmts(self.getattr(name, context), context, - frame=self): - # yield YES object instead of descriptors when necessary - if not isinstance(infered, Const) and isinstance(infered, Instance): - try: - infered._proxied.getattr('__get__', context) - except NotFoundError: - yield infered - else: - yield YES - else: - yield function_to_method(infered, self) - except NotFoundError: - if not name.startswith('__') and self.has_dynamic_getattr(context): - # class handle some dynamic attributes, return a YES object - yield YES - else: - raise InferenceError(name) - - def has_dynamic_getattr(self, context=None): - """return True if the class has a custom __getattr__ or - __getattribute__ method - """ - # need to explicitly handle optparse.Values (setattr is not detected) - if self.name == 'Values' and self.root().name == 'optparse': - return True - try: - self.getattr('__getattr__', context) - return True - except NotFoundError: - #if self.newstyle: XXX cause an infinite recursion error - try: - getattribute = self.getattr('__getattribute__', context)[0] - if getattribute.root().name != BUILTINS_NAME: - # class has a custom __getattribute__ defined - return True - except NotFoundError: - pass - return False - - def methods(self): - """return an iterator on all methods defined in the class and - its ancestors - """ - done = {} - for astng in chain(iter((self,)), self.ancestors()): - for meth in astng.mymethods(): - if meth.name in done: - continue - done[meth.name] = None - yield meth - - def mymethods(self): - """return an iterator on all methods defined in the class""" - for member in self.values(): - if isinstance(member, Function): - yield member - - def interfaces(self, herited=True, handler_func=_iface_hdlr): - """return an iterator on interfaces implemented by the given - class node - """ - # FIXME: what if __implements__ = (MyIFace, MyParent.__implements__)... - try: - implements = Instance(self).getattr('__implements__')[0] - except NotFoundError: - return - if not herited and not implements.frame() is self: - return - found = set() - missing = False - for iface in unpack_infer(implements): - if iface is YES: - missing = True - continue - if not iface in found and handler_func(iface): - found.add(iface) - yield iface - if missing: - raise InferenceError() diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/utils.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/astng/utils.py @@ -1,241 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# copyright 2003-2010 Sylvain Thenault, all rights reserved. -# contact mailto:thenault@gmail.com -# -# This file is part of logilab-astng. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see <http://www.gnu.org/licenses/>. -"""this module contains some utilities to navigate in the tree or to -extract information from it -""" - -__docformat__ = "restructuredtext en" - -from .exceptions import ASTNGBuildingException - - -class ASTWalker: - """a walker visiting a tree in preorder, calling on the handler: - - * visit_<class name> on entering a node, where class name is the class of - the node in lower case - - * leave_<class name> on leaving a node, where class name is the class of - the node in lower case - """ - - def __init__(self, handler): - self.handler = handler - self._cache = {} - - def walk(self, node, _done=None): - """walk on the tree from <node>, getting callbacks from handler""" - if _done is None: - _done = set() - if node in _done: - raise AssertionError((id(node), node, node.parent)) - _done.add(node) - self.visit(node) - for child_node in node.get_children(): - self.handler.set_context(node, child_node) - assert child_node is not node - self.walk(child_node, _done) - self.leave(node) - assert node.parent is not node - - def get_callbacks(self, node): - """get callbacks from handler for the visited node""" - klass = node.__class__ - methods = self._cache.get(klass) - if methods is None: - handler = self.handler - kid = klass.__name__.lower() - e_method = getattr(handler, 'visit_%s' % kid, - getattr(handler, 'visit_default', None)) - l_method = getattr(handler, 'leave_%s' % kid, - getattr(handler, 'leave_default', None)) - self._cache[klass] = (e_method, l_method) - else: - e_method, l_method = methods - return e_method, l_method - - def visit(self, node): - """walk on the tree from <node>, getting callbacks from handler""" - method = self.get_callbacks(node)[0] - if method is not None: - method(node) - - def leave(self, node): - """walk on the tree from <node>, getting callbacks from handler""" - method = self.get_callbacks(node)[1] - if method is not None: - method(node) - - -class LocalsVisitor(ASTWalker): - """visit a project by traversing the locals dictionary""" - def __init__(self): - ASTWalker.__init__(self, self) - self._visited = {} - - def visit(self, node): - """launch the visit starting from the given node""" - if node in self._visited: - return - self._visited[node] = 1 # FIXME: use set ? - methods = self.get_callbacks(node) - if methods[0] is not None: - methods[0](node) - if 'locals' in node.__dict__: # skip Instance and other proxy - for name, local_node in node.items(): - self.visit(local_node) - if methods[1] is not None: - return methods[1](node) - - -def _check_children(node): - """a helper function to check children - parent relations""" - for child in node.get_children(): - ok = False - if child is None: - print "Hm, child of %s is None" % node - continue - if not hasattr(child, 'parent'): - print " ERROR: %s has child %s %x with no parent" % (node, child, id(child)) - elif not child.parent: - print " ERROR: %s has child %s %x with parent %r" % (node, child, id(child), child.parent) - elif child.parent is not node: - print " ERROR: %s %x has child %s %x with wrong parent %s" % (node, - id(node), child, id(child), child.parent) - else: - ok = True - if not ok: - print "lines;", node.lineno, child.lineno - print "of module", node.root(), node.root().name - raise ASTNGBuildingException - _check_children(child) - - -from _ast import PyCF_ONLY_AST -def parse(string): - return compile(string, "<string>", 'exec', PyCF_ONLY_AST) - -class TreeTester(object): - '''A helper class to see _ast tree and compare with astng tree - - indent: string for tree indent representation - lineno: bool to tell if we should print the line numbers - - >>> tester = TreeTester('print') - >>> print tester.native_tree_repr() - - <Module> - . body = [ - . <Print> - . . nl = True - . ] - >>> print tester.astng_tree_repr() - Module() - body = [ - Print() - dest = - values = [ - ] - ] - ''' - - indent = '. ' - lineno = False - - def __init__(self, sourcecode): - self._string = '' - self.sourcecode = sourcecode - self._ast_node = None - self.build_ast() - - def build_ast(self): - """build the _ast tree from the source code""" - self._ast_node = parse(self.sourcecode) - - def native_tree_repr(self, node=None, indent=''): - """get a nice representation of the _ast tree""" - self._string = '' - if node is None: - node = self._ast_node - self._native_repr_tree(node, indent) - return self._string - - - def _native_repr_tree(self, node, indent, _done=None): - """recursive method for the native tree representation""" - from _ast import Load as _Load, Store as _Store, Del as _Del - from _ast import AST as Node - if _done is None: - _done = set() - if node in _done: - self._string += '\nloop in tree: %r (%s)' % (node, - getattr(node, 'lineno', None)) - return - _done.add(node) - self._string += '\n' + indent + '<%s>' % node.__class__.__name__ - indent += self.indent - if not hasattr(node, '__dict__'): - self._string += '\n' + self.indent + " ** node has no __dict__ " + str(node) - return - node_dict = node.__dict__ - if hasattr(node, '_attributes'): - for a in node._attributes: - attr = node_dict[a] - if attr is None: - continue - if a in ("lineno", "col_offset") and not self.lineno: - continue - self._string +='\n' + indent + a + " = " + repr(attr) - for field in node._fields or (): - attr = node_dict[field] - if attr is None: - continue - if isinstance(attr, list): - if not attr: - continue - self._string += '\n' + indent + field + ' = [' - for elt in attr: - self._native_repr_tree(elt, indent, _done) - self._string += '\n' + indent + ']' - continue - if isinstance(attr, (_Load, _Store, _Del)): - continue - if isinstance(attr, Node): - self._string += '\n' + indent + field + " = " - self._native_repr_tree(attr, indent, _done) - else: - self._string += '\n' + indent + field + " = " + repr(attr) - - - def build_astng_tree(self): - """build astng tree from the _ast tree - """ - from logilab.astng.builder import ASTNGBuilder - tree = ASTNGBuilder().string_build(self.sourcecode) - return tree - - def astng_tree_repr(self, ids=False): - """build the astng tree and return a nice tree representation""" - mod = self.build_astng_tree() - return mod.repr_tree(ids) - - -__all__ = ('LocalsVisitor', 'ASTWalker',) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/__init__.py @@ -1,171 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Logilab common library (aka Logilab's extension to the standard library). - -:type STD_BLACKLIST: tuple -:var STD_BLACKLIST: directories ignored by default by the functions in - this package which have to recurse into directories - -:type IGNORED_EXTENSIONS: tuple -:var IGNORED_EXTENSIONS: file extensions that may usually be ignored -""" -__docformat__ = "restructuredtext en" -from .__pkginfo__ import version as __version__ - -STD_BLACKLIST = ('CVS', '.svn', '.hg', 'debian', 'dist', 'build') - -IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~', '.swp', '.orig') - -# set this to False if you've mx DateTime installed but you don't want your db -# adapter to use it (should be set before you got a connection) -USE_MX_DATETIME = True - - -class attrdict(dict): - """A dictionary for which keys are also accessible as attributes.""" - def __getattr__(self, attr): - try: - return self[attr] - except KeyError: - raise AttributeError(attr) - -class dictattr(dict): - def __init__(self, proxy): - self.__proxy = proxy - - def __getitem__(self, attr): - try: - return getattr(self.__proxy, attr) - except AttributeError: - raise KeyError(attr) - -class nullobject(object): - def __repr__(self): - return '<nullobject>' - def __nonzero__(self): - return False - -class tempattr(object): - def __init__(self, obj, attr, value): - self.obj = obj - self.attr = attr - self.value = value - - def __enter__(self): - self.oldvalue = getattr(self.obj, self.attr) - setattr(self.obj, self.attr, self.value) - return self.obj - - def __exit__(self, exctype, value, traceback): - setattr(self.obj, self.attr, self.oldvalue) - - - -# flatten ----- -# XXX move in a specific module and use yield instead -# do not mix flatten and translate -# -# def iterable(obj): -# try: iter(obj) -# except: return False -# return True -# -# def is_string_like(obj): -# try: obj +'' -# except (TypeError, ValueError): return False -# return True -# -#def is_scalar(obj): -# return is_string_like(obj) or not iterable(obj) -# -#def flatten(seq): -# for item in seq: -# if is_scalar(item): -# yield item -# else: -# for subitem in flatten(item): -# yield subitem - -def flatten(iterable, tr_func=None, results=None): - """Flatten a list of list with any level. - - If tr_func is not None, it should be a one argument function that'll be called - on each final element. - - :rtype: list - - >>> flatten([1, [2, 3]]) - [1, 2, 3] - """ - if results is None: - results = [] - for val in iterable: - if isinstance(val, (list, tuple)): - flatten(val, tr_func, results) - elif tr_func is None: - results.append(val) - else: - results.append(tr_func(val)) - return results - - -# XXX is function below still used ? - -def make_domains(lists): - """ - Given a list of lists, return a list of domain for each list to produce all - combinations of possibles values. - - :rtype: list - - Example: - - >>> make_domains(['a', 'b'], ['c','d', 'e']) - [['a', 'b', 'a', 'b', 'a', 'b'], ['c', 'c', 'd', 'd', 'e', 'e']] - """ - domains = [] - for iterable in lists: - new_domain = iterable[:] - for i in range(len(domains)): - domains[i] = domains[i]*len(iterable) - if domains: - missing = (len(domains[0]) - len(iterable)) / len(iterable) - i = 0 - for j in range(len(iterable)): - value = iterable[j] - for dummy in range(missing): - new_domain.insert(i, value) - i += 1 - i += 1 - domains.append(new_domain) - return domains - - -# private stuff ################################################################ - -def _handle_blacklist(blacklist, dirnames, filenames): - """remove files/directories in the black list - - dirnames/filenames are usually from os.walk - """ - for norecurs in blacklist: - if norecurs in dirnames: - dirnames.remove(norecurs) - elif norecurs in filenames: - filenames.remove(norecurs) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/__pkginfo__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/__pkginfo__.py @@ -1,53 +0,0 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""logilab.common packaging information""" -__docformat__ = "restructuredtext en" -import sys -import os - -distname = 'logilab-common' -modname = 'common' -subpackage_of = 'logilab' -subpackage_master = True - -numversion = (0, 58, 3) -version = '.'.join([str(num) for num in numversion]) - -license = 'LGPL' # 2.1 or later -description = "collection of low-level Python packages and modules used by Logilab projects" -web = "http://www.logilab.org/project/%s" % distname -mailinglist = "mailto://python-projects@lists.logilab.org" -author = "Logilab" -author_email = "contact@logilab.fr" - - -from os.path import join -scripts = [join('bin', 'pytest')] -include_dirs = [join('test', 'data')] - -install_requires = [] -if sys.version_info < (2, 7): - install_requires.append('unittest2 >= 0.5.1') -if os.name == 'nt': - install_requires.append('colorama') - -classifiers = ["Topic :: Utilities", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 3", - ] diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/changelog.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/changelog.py @@ -1,236 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Manipulation of upstream change log files. - -The upstream change log files format handled is simpler than the one -often used such as those generated by the default Emacs changelog mode. - -Sample ChangeLog format:: - - Change log for project Yoo - ========================== - - -- - * add a new functionality - - 2002-02-01 -- 0.1.1 - * fix bug #435454 - * fix bug #434356 - - 2002-01-01 -- 0.1 - * initial release - - -There is 3 entries in this change log, one for each released version and one -for the next version (i.e. the current entry). -Each entry contains a set of messages corresponding to changes done in this -release. -All the non empty lines before the first entry are considered as the change -log title. -""" - -__docformat__ = "restructuredtext en" - -import sys -from stat import S_IWRITE - -BULLET = '*' -SUBBULLET = '-' -INDENT = ' ' * 4 - -class NoEntry(Exception): - """raised when we are unable to find an entry""" - -class EntryNotFound(Exception): - """raised when we are unable to find a given entry""" - -class Version(tuple): - """simple class to handle soft version number has a tuple while - correctly printing it as X.Y.Z - """ - def __new__(cls, versionstr): - if isinstance(versionstr, basestring): - versionstr = versionstr.strip(' :') # XXX (syt) duh? - parsed = cls.parse(versionstr) - else: - parsed = versionstr - return tuple.__new__(cls, parsed) - - @classmethod - def parse(cls, versionstr): - versionstr = versionstr.strip(' :') - try: - return [int(i) for i in versionstr.split('.')] - except ValueError, ex: - raise ValueError("invalid literal for version '%s' (%s)"%(versionstr, ex)) - - def __str__(self): - return '.'.join([str(i) for i in self]) - -# upstream change log ######################################################### - -class ChangeLogEntry(object): - """a change log entry, i.e. a set of messages associated to a version and - its release date - """ - version_class = Version - - def __init__(self, date=None, version=None, **kwargs): - self.__dict__.update(kwargs) - if version: - self.version = self.version_class(version) - else: - self.version = None - self.date = date - self.messages = [] - - def add_message(self, msg): - """add a new message""" - self.messages.append(([msg], [])) - - def complete_latest_message(self, msg_suite): - """complete the latest added message - """ - if not self.messages: - raise ValueError('unable to complete last message as there is no previous message)') - if self.messages[-1][1]: # sub messages - self.messages[-1][1][-1].append(msg_suite) - else: # message - self.messages[-1][0].append(msg_suite) - - def add_sub_message(self, sub_msg, key=None): - if not self.messages: - raise ValueError('unable to complete last message as there is no previous message)') - if key is None: - self.messages[-1][1].append([sub_msg]) - else: - raise NotImplementedError("sub message to specific key are not implemented yet") - - def write(self, stream=sys.stdout): - """write the entry to file """ - stream.write('%s -- %s\n' % (self.date or '', self.version or '')) - for msg, sub_msgs in self.messages: - stream.write('%s%s %s\n' % (INDENT, BULLET, msg[0])) - stream.write(''.join(msg[1:])) - if sub_msgs: - stream.write('\n') - for sub_msg in sub_msgs: - stream.write('%s%s %s\n' % (INDENT * 2, SUBBULLET, sub_msg[0])) - stream.write(''.join(sub_msg[1:])) - stream.write('\n') - - stream.write('\n\n') - -class ChangeLog(object): - """object representation of a whole ChangeLog file""" - - entry_class = ChangeLogEntry - - def __init__(self, changelog_file, title=''): - self.file = changelog_file - self.title = title - self.additional_content = '' - self.entries = [] - self.load() - - def __repr__(self): - return '<ChangeLog %s at %s (%s entries)>' % (self.file, id(self), - len(self.entries)) - - def add_entry(self, entry): - """add a new entry to the change log""" - self.entries.append(entry) - - def get_entry(self, version='', create=None): - """ return a given changelog entry - if version is omitted, return the current entry - """ - if not self.entries: - if version or not create: - raise NoEntry() - self.entries.append(self.entry_class()) - if not version: - if self.entries[0].version and create is not None: - self.entries.insert(0, self.entry_class()) - return self.entries[0] - version = self.version_class(version) - for entry in self.entries: - if entry.version == version: - return entry - raise EntryNotFound() - - def add(self, msg, create=None): - """add a new message to the latest opened entry""" - entry = self.get_entry(create=create) - entry.add_message(msg) - - def load(self): - """ read a logilab's ChangeLog from file """ - try: - stream = open(self.file) - except IOError: - return - last = None - expect_sub = False - for line in stream.readlines(): - sline = line.strip() - words = sline.split() - # if new entry - if len(words) == 1 and words[0] == '--': - expect_sub = False - last = self.entry_class() - self.add_entry(last) - # if old entry - elif len(words) == 3 and words[1] == '--': - expect_sub = False - last = self.entry_class(words[0], words[2]) - self.add_entry(last) - # if title - elif sline and last is None: - self.title = '%s%s' % (self.title, line) - # if new entry - elif sline and sline[0] == BULLET: - expect_sub = False - last.add_message(sline[1:].strip()) - # if new sub_entry - elif expect_sub and sline and sline[0] == SUBBULLET: - last.add_sub_message(sline[1:].strip()) - # if new line for current entry - elif sline and last.messages: - last.complete_latest_message(line) - else: - expect_sub = True - self.additional_content += line - stream.close() - - def format_title(self): - return '%s\n\n' % self.title.strip() - - def save(self): - """write back change log""" - # filetutils isn't importable in appengine, so import locally - from logilab.common.fileutils import ensure_fs_mode - ensure_fs_mode(self.file, S_IWRITE) - self.write(open(self.file, 'w')) - - def write(self, stream=sys.stdout): - """write changelog to stream""" - stream.write(self.format_title()) - for entry in self.entries: - entry.write(stream) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/compat.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/compat.py @@ -1,243 +0,0 @@ -# pylint: disable=E0601,W0622,W0611 -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Wrappers around some builtins introduced in python 2.3, 2.4 and -2.5, making them available in for earlier versions of python. - -See another compatibility snippets from other projects: - - :mod:`lib2to3.fixes` - :mod:`coverage.backward` - :mod:`unittest2.compatibility` -""" - -from __future__ import generators - -__docformat__ = "restructuredtext en" - -import os -import sys -import types -from warnings import warn - -import __builtin__ as builtins # 2to3 will tranform '__builtin__' to 'builtins' - -if sys.version_info < (3, 0): - str_to_bytes = str - def str_encode(string, encoding): - if isinstance(string, unicode): - return string.encode(encoding) - return str(string) -else: - def str_to_bytes(string): - return str.encode(string) - # we have to ignore the encoding in py3k to be able to write a string into a - # TextIOWrapper or like object (which expect an unicode string) - def str_encode(string, encoding): - return str(string) - -# XXX callable built-in seems back in all python versions -try: - callable = builtins.callable -except AttributeError: - from collections import Callable - def callable(something): - return isinstance(something, Callable) - del Callable - -# See also http://bugs.python.org/issue11776 -if sys.version_info[0] == 3: - def method_type(callable, instance, klass): - # api change. klass is no more considered - return types.MethodType(callable, instance) -else: - # alias types otherwise - method_type = types.MethodType - -if sys.version_info < (3, 0): - raw_input = raw_input -else: - raw_input = input - -# Pythons 2 and 3 differ on where to get StringIO -if sys.version_info < (3, 0): - from cStringIO import StringIO - FileIO = file - BytesIO = StringIO - reload = reload -else: - from io import FileIO, BytesIO, StringIO - from imp import reload - -# Where do pickles come from? -try: - import cPickle as pickle -except ImportError: - import pickle - -from .deprecation import deprecated - -from itertools import izip, chain, imap -if sys.version_info < (3, 0):# 2to3 will remove the imports - izip = deprecated('izip exists in itertools since py2.3')(izip) - imap = deprecated('imap exists in itertools since py2.3')(imap) -chain = deprecated('chain exists in itertools since py2.3')(chain) - -sum = deprecated('sum exists in builtins since py2.3')(sum) -enumerate = deprecated('enumerate exists in builtins since py2.3')(enumerate) -frozenset = deprecated('frozenset exists in builtins since py2.4')(frozenset) -reversed = deprecated('reversed exists in builtins since py2.4')(reversed) -sorted = deprecated('sorted exists in builtins since py2.4')(sorted) -max = deprecated('max exists in builtins since py2.4')(max) - - -# Python2.5 builtins -try: - any = any - all = all -except NameError: - def any(iterable): - """any(iterable) -> bool - - Return True if bool(x) is True for any x in the iterable. - """ - for elt in iterable: - if elt: - return True - return False - - def all(iterable): - """all(iterable) -> bool - - Return True if bool(x) is True for all values x in the iterable. - """ - for elt in iterable: - if not elt: - return False - return True - - -# Python2.5 subprocess added functions and exceptions -try: - from subprocess import Popen -except ImportError: - # gae or python < 2.3 - - class CalledProcessError(Exception): - """This exception is raised when a process run by check_call() returns - a non-zero exit status. The exit status will be stored in the - returncode attribute.""" - def __init__(self, returncode, cmd): - self.returncode = returncode - self.cmd = cmd - def __str__(self): - return "Command '%s' returned non-zero exit status %d" % (self.cmd, - self.returncode) - - def call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete, then - return the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - retcode = call(["ls", "-l"]) - """ - # workaround: subprocess.Popen(cmd, stdout=sys.stdout) fails - # see http://bugs.python.org/issue1531862 - if "stdout" in kwargs: - fileno = kwargs.get("stdout").fileno() - del kwargs['stdout'] - return Popen(stdout=os.dup(fileno), *popenargs, **kwargs).wait() - return Popen(*popenargs, **kwargs).wait() - - def check_call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete. If - the exit code was zero then return, otherwise raise - CalledProcessError. The CalledProcessError object will have the - return code in the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - check_call(["ls", "-l"]) - """ - retcode = call(*popenargs, **kwargs) - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - if retcode: - raise CalledProcessError(retcode, cmd) - return retcode - -try: - from os.path import relpath -except ImportError: # python < 2.6 - from os.path import curdir, abspath, sep, commonprefix, pardir, join - def relpath(path, start=curdir): - """Return a relative version of a path""" - - if not path: - raise ValueError("no path specified") - - start_list = abspath(start).split(sep) - path_list = abspath(path).split(sep) - - # Work out how much of the filepath is shared by start and path. - i = len(commonprefix([start_list, path_list])) - - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return curdir - return join(*rel_list) - - -# XXX don't know why tests don't pass if I don't do that : -_real_set, set = set, deprecated('set exists in builtins since py2.4')(set) -if (2, 5) <= sys.version_info[:2]: - InheritableSet = _real_set -else: - class InheritableSet(_real_set): - """hacked resolving inheritancy issue from old style class in 2.4""" - def __new__(cls, *args, **kwargs): - if args: - new_args = (args[0], ) - else: - new_args = () - obj = _real_set.__new__(cls, *new_args) - obj.__init__(*args, **kwargs) - return obj - -# XXX shouldn't we remove this and just let 2to3 do his job ? -# range or xrange? -try: - range = xrange -except NameError: - range = range - -# ConfigParser was renamed to the more-standard configparser -try: - import configparser -except ImportError: - import ConfigParser as configparser - -try: - import json -except ImportError: - try: - import simplejson as json - except ImportError: - json = None diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/configuration.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/configuration.py @@ -1,1078 +0,0 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Classes to handle advanced configuration in simple to complex applications. - -Allows to load the configuration from a file or from command line -options, to generate a sample configuration file or to display -program's usage. Fills the gap between optik/optparse and ConfigParser -by adding data types (which are also available as a standalone optik -extension in the `optik_ext` module). - - -Quick start: simplest usage ---------------------------- - -.. python :: - - >>> import sys - >>> from logilab.common.configuration import Configuration - >>> options = [('dothis', {'type':'yn', 'default': True, 'metavar': '<y or n>'}), - ... ('value', {'type': 'string', 'metavar': '<string>'}), - ... ('multiple', {'type': 'csv', 'default': ('yop',), - ... 'metavar': '<comma separated values>', - ... 'help': 'you can also document the option'}), - ... ('number', {'type': 'int', 'default':2, 'metavar':'<int>'}), - ... ] - >>> config = Configuration(options=options, name='My config') - >>> print config['dothis'] - True - >>> print config['value'] - None - >>> print config['multiple'] - ('yop',) - >>> print config['number'] - 2 - >>> print config.help() - Usage: [options] - - Options: - -h, --help show this help message and exit - --dothis=<y or n> - --value=<string> - --multiple=<comma separated values> - you can also document the option [current: none] - --number=<int> - - >>> f = open('myconfig.ini', 'w') - >>> f.write('''[MY CONFIG] - ... number = 3 - ... dothis = no - ... multiple = 1,2,3 - ... ''') - >>> f.close() - >>> config.load_file_configuration('myconfig.ini') - >>> print config['dothis'] - False - >>> print config['value'] - None - >>> print config['multiple'] - ['1', '2', '3'] - >>> print config['number'] - 3 - >>> sys.argv = ['mon prog', '--value', 'bacon', '--multiple', '4,5,6', - ... 'nonoptionargument'] - >>> print config.load_command_line_configuration() - ['nonoptionargument'] - >>> print config['value'] - bacon - >>> config.generate_config() - # class for simple configurations which don't need the - # manager / providers model and prefer delegation to inheritance - # - # configuration values are accessible through a dict like interface - # - [MY CONFIG] - - dothis=no - - value=bacon - - # you can also document the option - multiple=4,5,6 - - number=3 - >>> -""" -__docformat__ = "restructuredtext en" - -__all__ = ('OptionsManagerMixIn', 'OptionsProviderMixIn', - 'ConfigurationMixIn', 'Configuration', - 'OptionsManager2ConfigurationAdapter') - -import os -import sys -import re -from os.path import exists, expanduser -from copy import copy -from ConfigParser import ConfigParser, NoOptionError, NoSectionError, \ - DuplicateSectionError -from warnings import warn - -from .compat import callable, raw_input, str_encode as _encode - -from .textutils import normalize_text, unquote -from . import optik_ext as optparse - -OptionError = optparse.OptionError - -REQUIRED = [] - -class UnsupportedAction(Exception): - """raised by set_option when it doesn't know what to do for an action""" - - -def _get_encoding(encoding, stream): - encoding = encoding or getattr(stream, 'encoding', None) - if not encoding: - import locale - encoding = locale.getpreferredencoding() - return encoding - - -# validation functions ######################################################## - -def choice_validator(optdict, name, value): - """validate and return a converted value for option of type 'choice' - """ - if not value in optdict['choices']: - msg = "option %s: invalid value: %r, should be in %s" - raise optparse.OptionValueError(msg % (name, value, optdict['choices'])) - return value - -def multiple_choice_validator(optdict, name, value): - """validate and return a converted value for option of type 'choice' - """ - choices = optdict['choices'] - values = optparse.check_csv(None, name, value) - for value in values: - if not value in choices: - msg = "option %s: invalid value: %r, should be in %s" - raise optparse.OptionValueError(msg % (name, value, choices)) - return values - -def csv_validator(optdict, name, value): - """validate and return a converted value for option of type 'csv' - """ - return optparse.check_csv(None, name, value) - -def yn_validator(optdict, name, value): - """validate and return a converted value for option of type 'yn' - """ - return optparse.check_yn(None, name, value) - -def named_validator(optdict, name, value): - """validate and return a converted value for option of type 'named' - """ - return optparse.check_named(None, name, value) - -def file_validator(optdict, name, value): - """validate and return a filepath for option of type 'file'""" - return optparse.check_file(None, name, value) - -def color_validator(optdict, name, value): - """validate and return a valid color for option of type 'color'""" - return optparse.check_color(None, name, value) - -def password_validator(optdict, name, value): - """validate and return a string for option of type 'password'""" - return optparse.check_password(None, name, value) - -def date_validator(optdict, name, value): - """validate and return a mx DateTime object for option of type 'date'""" - return optparse.check_date(None, name, value) - -def time_validator(optdict, name, value): - """validate and return a time object for option of type 'time'""" - return optparse.check_time(None, name, value) - -def bytes_validator(optdict, name, value): - """validate and return an integer for option of type 'bytes'""" - return optparse.check_bytes(None, name, value) - - -VALIDATORS = {'string': unquote, - 'int': int, - 'float': float, - 'file': file_validator, - 'font': unquote, - 'color': color_validator, - 'regexp': re.compile, - 'csv': csv_validator, - 'yn': yn_validator, - 'bool': yn_validator, - 'named': named_validator, - 'password': password_validator, - 'date': date_validator, - 'time': time_validator, - 'bytes': bytes_validator, - 'choice': choice_validator, - 'multiple_choice': multiple_choice_validator, - } - -def _call_validator(opttype, optdict, option, value): - if opttype not in VALIDATORS: - raise Exception('Unsupported type "%s"' % opttype) - try: - return VALIDATORS[opttype](optdict, option, value) - except TypeError: - try: - return VALIDATORS[opttype](value) - except optparse.OptionValueError: - raise - except: - raise optparse.OptionValueError('%s value (%r) should be of type %s' % - (option, value, opttype)) - -# user input functions ######################################################## - -def input_password(optdict, question='password:'): - from getpass import getpass - while True: - value = getpass(question) - value2 = getpass('confirm: ') - if value == value2: - return value - print 'password mismatch, try again' - -def input_string(optdict, question): - value = raw_input(question).strip() - return value or None - -def _make_input_function(opttype): - def input_validator(optdict, question): - while True: - value = raw_input(question) - if not value.strip(): - return None - try: - return _call_validator(opttype, optdict, None, value) - except optparse.OptionValueError, ex: - msg = str(ex).split(':', 1)[-1].strip() - print 'bad value: %s' % msg - return input_validator - -INPUT_FUNCTIONS = { - 'string': input_string, - 'password': input_password, - } - -for opttype in VALIDATORS.keys(): - INPUT_FUNCTIONS.setdefault(opttype, _make_input_function(opttype)) - -def expand_default(self, option): - """monkey patch OptionParser.expand_default since we have a particular - way to handle defaults to avoid overriding values in the configuration - file - """ - if self.parser is None or not self.default_tag: - return option.help - optname = option._long_opts[0][2:] - try: - provider = self.parser.options_manager._all_options[optname] - except KeyError: - value = None - else: - optdict = provider.get_option_def(optname) - optname = provider.option_name(optname, optdict) - value = getattr(provider.config, optname, optdict) - value = format_option_value(optdict, value) - if value is optparse.NO_DEFAULT or not value: - value = self.NO_DEFAULT_VALUE - return option.help.replace(self.default_tag, str(value)) - - -def convert(value, optdict, name=''): - """return a validated value for an option according to its type - - optional argument name is only used for error message formatting - """ - try: - _type = optdict['type'] - except KeyError: - # FIXME - return value - return _call_validator(_type, optdict, name, value) - -def comment(string): - """return string as a comment""" - lines = [line.strip() for line in string.splitlines()] - return '# ' + ('%s# ' % os.linesep).join(lines) - -def format_time(value): - if not value: - return '0' - if value != int(value): - return '%.2fs' % value - value = int(value) - nbmin, nbsec = divmod(value, 60) - if nbsec: - return '%ss' % value - nbhour, nbmin_ = divmod(nbmin, 60) - if nbmin_: - return '%smin' % nbmin - nbday, nbhour_ = divmod(nbhour, 24) - if nbhour_: - return '%sh' % nbhour - return '%sd' % nbday - -def format_bytes(value): - if not value: - return '0' - if value != int(value): - return '%.2fB' % value - value = int(value) - prevunit = 'B' - for unit in ('KB', 'MB', 'GB', 'TB'): - next, remain = divmod(value, 1024) - if remain: - return '%s%s' % (value, prevunit) - prevunit = unit - value = next - return '%s%s' % (value, unit) - -def format_option_value(optdict, value): - """return the user input's value from a 'compiled' value""" - if isinstance(value, (list, tuple)): - value = ','.join(value) - elif isinstance(value, dict): - value = ','.join(['%s:%s' % (k, v) for k, v in value.items()]) - elif hasattr(value, 'match'): # optdict.get('type') == 'regexp' - # compiled regexp - value = value.pattern - elif optdict.get('type') == 'yn': - value = value and 'yes' or 'no' - elif isinstance(value, (str, unicode)) and value.isspace(): - value = "'%s'" % value - elif optdict.get('type') == 'time' and isinstance(value, (float, int, long)): - value = format_time(value) - elif optdict.get('type') == 'bytes' and hasattr(value, '__int__'): - value = format_bytes(value) - return value - -def ini_format_section(stream, section, options, encoding=None, doc=None): - """format an options section using the INI format""" - encoding = _get_encoding(encoding, stream) - if doc: - print >> stream, _encode(comment(doc), encoding) - print >> stream, '[%s]' % section - ini_format(stream, options, encoding) - -def ini_format(stream, options, encoding): - """format options using the INI format""" - for optname, optdict, value in options: - value = format_option_value(optdict, value) - help = optdict.get('help') - if help: - help = normalize_text(help, line_len=79, indent='# ') - print >> stream - print >> stream, _encode(help, encoding) - else: - print >> stream - if value is None: - print >> stream, '#%s=' % optname - else: - value = _encode(value, encoding).strip() - print >> stream, '%s=%s' % (optname, value) - -format_section = ini_format_section - -def rest_format_section(stream, section, options, encoding=None, doc=None): - """format an options section using the INI format""" - encoding = _get_encoding(encoding, stream) - if section: - print >> stream, '%s\n%s' % (section, "'"*len(section)) - if doc: - print >> stream, _encode(normalize_text(doc, line_len=79, indent=''), - encoding) - print >> stream - for optname, optdict, value in options: - help = optdict.get('help') - print >> stream, ':%s:' % optname - if help: - help = normalize_text(help, line_len=79, indent=' ') - print >> stream, _encode(help, encoding) - if value: - value = _encode(format_option_value(optdict, value), encoding) - print >> stream, '' - print >> stream, ' Default: ``%s``' % value.replace("`` ", "```` ``") - - -class OptionsManagerMixIn(object): - """MixIn to handle a configuration from both a configuration file and - command line options - """ - - def __init__(self, usage, config_file=None, version=None, quiet=0): - self.config_file = config_file - self.reset_parsers(usage, version=version) - # list of registered options providers - self.options_providers = [] - # dictionary associating option name to checker - self._all_options = {} - self._short_options = {} - self._nocallback_options = {} - self._mygroups = dict() - # verbosity - self.quiet = quiet - self._maxlevel = 0 - - def reset_parsers(self, usage='', version=None): - # configuration file parser - self.cfgfile_parser = ConfigParser() - # command line parser - self.cmdline_parser = optparse.OptionParser(usage=usage, version=version) - self.cmdline_parser.options_manager = self - self._optik_option_attrs = set(self.cmdline_parser.option_class.ATTRS) - - def register_options_provider(self, provider, own_group=True): - """register an options provider""" - assert provider.priority <= 0, "provider's priority can't be >= 0" - for i in range(len(self.options_providers)): - if provider.priority > self.options_providers[i].priority: - self.options_providers.insert(i, provider) - break - else: - self.options_providers.append(provider) - non_group_spec_options = [option for option in provider.options - if 'group' not in option[1]] - groups = getattr(provider, 'option_groups', ()) - if own_group and non_group_spec_options: - self.add_option_group(provider.name.upper(), provider.__doc__, - non_group_spec_options, provider) - else: - for opt, optdict in non_group_spec_options: - self.add_optik_option(provider, self.cmdline_parser, opt, optdict) - for gname, gdoc in groups: - gname = gname.upper() - goptions = [option for option in provider.options - if option[1].get('group', '').upper() == gname] - self.add_option_group(gname, gdoc, goptions, provider) - - def add_option_group(self, group_name, doc, options, provider): - """add an option group including the listed options - """ - assert options - # add option group to the command line parser - if group_name in self._mygroups: - group = self._mygroups[group_name] - else: - group = optparse.OptionGroup(self.cmdline_parser, - title=group_name.capitalize()) - self.cmdline_parser.add_option_group(group) - group.level = provider.level - self._mygroups[group_name] = group - # add section to the config file - if group_name != "DEFAULT": - self.cfgfile_parser.add_section(group_name) - # add provider's specific options - for opt, optdict in options: - self.add_optik_option(provider, group, opt, optdict) - - def add_optik_option(self, provider, optikcontainer, opt, optdict): - if 'inputlevel' in optdict: - warn('[0.50] "inputlevel" in option dictionary for %s is deprecated,' - ' use "level"' % opt, DeprecationWarning) - optdict['level'] = optdict.pop('inputlevel') - args, optdict = self.optik_option(provider, opt, optdict) - option = optikcontainer.add_option(*args, **optdict) - self._all_options[opt] = provider - self._maxlevel = max(self._maxlevel, option.level or 0) - - def optik_option(self, provider, opt, optdict): - """get our personal option definition and return a suitable form for - use with optik/optparse - """ - optdict = copy(optdict) - others = {} - if 'action' in optdict: - self._nocallback_options[provider] = opt - else: - optdict['action'] = 'callback' - optdict['callback'] = self.cb_set_provider_option - # default is handled here and *must not* be given to optik if you - # want the whole machinery to work - if 'default' in optdict: - if (optparse.OPTPARSE_FORMAT_DEFAULT and 'help' in optdict and - optdict.get('default') is not None and - not optdict['action'] in ('store_true', 'store_false')): - optdict['help'] += ' [current: %default]' - del optdict['default'] - args = ['--' + str(opt)] - if 'short' in optdict: - self._short_options[optdict['short']] = opt - args.append('-' + optdict['short']) - del optdict['short'] - # cleanup option definition dict before giving it to optik - for key in optdict.keys(): - if not key in self._optik_option_attrs: - optdict.pop(key) - return args, optdict - - def cb_set_provider_option(self, option, opt, value, parser): - """optik callback for option setting""" - if opt.startswith('--'): - # remove -- on long option - opt = opt[2:] - else: - # short option, get its long equivalent - opt = self._short_options[opt[1:]] - # trick since we can't set action='store_true' on options - if value is None: - value = 1 - self.global_set_option(opt, value) - - def global_set_option(self, opt, value): - """set option on the correct option provider""" - self._all_options[opt].set_option(opt, value) - - def generate_config(self, stream=None, skipsections=(), encoding=None): - """write a configuration file according to the current configuration - into the given stream or stdout - """ - options_by_section = {} - sections = [] - for provider in self.options_providers: - for section, options in provider.options_by_section(): - if section is None: - section = provider.name - if section in skipsections: - continue - options = [(n, d, v) for (n, d, v) in options - if d.get('type') is not None] - if not options: - continue - if not section in sections: - sections.append(section) - alloptions = options_by_section.setdefault(section, []) - alloptions += options - stream = stream or sys.stdout - encoding = _get_encoding(encoding, stream) - printed = False - for section in sections: - if printed: - print >> stream, '\n' - format_section(stream, section.upper(), options_by_section[section], - encoding) - printed = True - - def generate_manpage(self, pkginfo, section=1, stream=None): - """write a man page for the current configuration into the given - stream or stdout - """ - self._monkeypatch_expand_default() - try: - optparse.generate_manpage(self.cmdline_parser, pkginfo, - section, stream=stream or sys.stdout, - level=self._maxlevel) - finally: - self._unmonkeypatch_expand_default() - - # initialization methods ################################################## - - def load_provider_defaults(self): - """initialize configuration using default values""" - for provider in self.options_providers: - provider.load_defaults() - - def load_file_configuration(self, config_file=None): - """load the configuration from file""" - self.read_config_file(config_file) - self.load_config_file() - - def read_config_file(self, config_file=None): - """read the configuration file but do not load it (i.e. dispatching - values to each options provider) - """ - helplevel = 1 - while helplevel <= self._maxlevel: - opt = '-'.join(['long'] * helplevel) + '-help' - if opt in self._all_options: - break # already processed - def helpfunc(option, opt, val, p, level=helplevel): - print self.help(level) - sys.exit(0) - helpmsg = '%s verbose help.' % ' '.join(['more'] * helplevel) - optdict = {'action' : 'callback', 'callback' : helpfunc, - 'help' : helpmsg} - provider = self.options_providers[0] - self.add_optik_option(provider, self.cmdline_parser, opt, optdict) - provider.options += ( (opt, optdict), ) - helplevel += 1 - if config_file is None: - config_file = self.config_file - if config_file is not None: - config_file = expanduser(config_file) - if config_file and exists(config_file): - parser = self.cfgfile_parser - parser.read([config_file]) - # normalize sections'title - for sect, values in parser._sections.items(): - if not sect.isupper() and values: - parser._sections[sect.upper()] = values - elif not self.quiet: - msg = 'No config file found, using default configuration' - print >> sys.stderr, msg - return - - def input_config(self, onlysection=None, inputlevel=0, stream=None): - """interactively get configuration values by asking to the user and generate - a configuration file - """ - if onlysection is not None: - onlysection = onlysection.upper() - for provider in self.options_providers: - for section, option, optdict in provider.all_options(): - if onlysection is not None and section != onlysection: - continue - if not 'type' in optdict: - # ignore action without type (callback, store_true...) - continue - provider.input_option(option, optdict, inputlevel) - # now we can generate the configuration file - if stream is not None: - self.generate_config(stream) - - def load_config_file(self): - """dispatch values previously read from a configuration file to each - options provider) - """ - parser = self.cfgfile_parser - for provider in self.options_providers: - for section, option, optdict in provider.all_options(): - try: - value = parser.get(section, option) - provider.set_option(option, value, optdict=optdict) - except (NoSectionError, NoOptionError), ex: - continue - - def load_configuration(self, **kwargs): - """override configuration according to given parameters - """ - for opt, opt_value in kwargs.items(): - opt = opt.replace('_', '-') - provider = self._all_options[opt] - provider.set_option(opt, opt_value) - - def load_command_line_configuration(self, args=None): - """override configuration according to command line parameters - - return additional arguments - """ - self._monkeypatch_expand_default() - try: - if args is None: - args = sys.argv[1:] - else: - args = list(args) - (options, args) = self.cmdline_parser.parse_args(args=args) - for provider in self._nocallback_options.keys(): - config = provider.config - for attr in config.__dict__.keys(): - value = getattr(options, attr, None) - if value is None: - continue - setattr(config, attr, value) - return args - finally: - self._unmonkeypatch_expand_default() - - - # help methods ############################################################ - - def add_help_section(self, title, description, level=0): - """add a dummy option section for help purpose """ - group = optparse.OptionGroup(self.cmdline_parser, - title=title.capitalize(), - description=description) - group.level = level - self._maxlevel = max(self._maxlevel, level) - self.cmdline_parser.add_option_group(group) - - def _monkeypatch_expand_default(self): - # monkey patch optparse to deal with our default values - try: - self.__expand_default_backup = optparse.HelpFormatter.expand_default - optparse.HelpFormatter.expand_default = expand_default - except AttributeError: - # python < 2.4: nothing to be done - pass - def _unmonkeypatch_expand_default(self): - # remove monkey patch - if hasattr(optparse.HelpFormatter, 'expand_default'): - # unpatch optparse to avoid side effects - optparse.HelpFormatter.expand_default = self.__expand_default_backup - - def help(self, level=0): - """return the usage string for available options """ - self.cmdline_parser.formatter.output_level = level - self._monkeypatch_expand_default() - try: - return self.cmdline_parser.format_help() - finally: - self._unmonkeypatch_expand_default() - - -class Method(object): - """used to ease late binding of default method (so you can define options - on the class using default methods on the configuration instance) - """ - def __init__(self, methname): - self.method = methname - self._inst = None - - def bind(self, instance): - """bind the method to its instance""" - if self._inst is None: - self._inst = instance - - def __call__(self, *args, **kwargs): - assert self._inst, 'unbound method' - return getattr(self._inst, self.method)(*args, **kwargs) - - -class OptionsProviderMixIn(object): - """Mixin to provide options to an OptionsManager""" - - # those attributes should be overridden - priority = -1 - name = 'default' - options = () - level = 0 - - def __init__(self): - self.config = optparse.Values() - for option in self.options: - try: - option, optdict = option - except ValueError: - raise Exception('Bad option: %r' % option) - if isinstance(optdict.get('default'), Method): - optdict['default'].bind(self) - elif isinstance(optdict.get('callback'), Method): - optdict['callback'].bind(self) - self.load_defaults() - - def load_defaults(self): - """initialize the provider using default values""" - for opt, optdict in self.options: - action = optdict.get('action') - if action != 'callback': - # callback action have no default - default = self.option_default(opt, optdict) - if default is REQUIRED: - continue - self.set_option(opt, default, action, optdict) - - def option_default(self, opt, optdict=None): - """return the default value for an option""" - if optdict is None: - optdict = self.get_option_def(opt) - default = optdict.get('default') - if callable(default): - default = default() - return default - - def option_name(self, opt, optdict=None): - """get the config attribute corresponding to opt - """ - if optdict is None: - optdict = self.get_option_def(opt) - return optdict.get('dest', opt.replace('-', '_')) - - def option_value(self, opt): - """get the current value for the given option""" - return getattr(self.config, self.option_name(opt), None) - - def set_option(self, opt, value, action=None, optdict=None): - """method called to set an option (registered in the options list) - """ - # print "************ setting option", opt," to value", value - if optdict is None: - optdict = self.get_option_def(opt) - if value is not None: - value = convert(value, optdict, opt) - if action is None: - action = optdict.get('action', 'store') - if optdict.get('type') == 'named': # XXX need specific handling - optname = self.option_name(opt, optdict) - currentvalue = getattr(self.config, optname, None) - if currentvalue: - currentvalue.update(value) - value = currentvalue - if action == 'store': - setattr(self.config, self.option_name(opt, optdict), value) - elif action in ('store_true', 'count'): - setattr(self.config, self.option_name(opt, optdict), 0) - elif action == 'store_false': - setattr(self.config, self.option_name(opt, optdict), 1) - elif action == 'append': - opt = self.option_name(opt, optdict) - _list = getattr(self.config, opt, None) - if _list is None: - if isinstance(value, (list, tuple)): - _list = value - elif value is not None: - _list = [] - _list.append(value) - setattr(self.config, opt, _list) - elif isinstance(_list, tuple): - setattr(self.config, opt, _list + (value,)) - else: - _list.append(value) - elif action == 'callback': - optdict['callback'](None, opt, value, None) - else: - raise UnsupportedAction(action) - - def input_option(self, option, optdict, inputlevel=99): - default = self.option_default(option, optdict) - if default is REQUIRED: - defaultstr = '(required): ' - elif optdict.get('level', 0) > inputlevel: - return - elif optdict['type'] == 'password' or default is None: - defaultstr = ': ' - else: - defaultstr = '(default: %s): ' % format_option_value(optdict, default) - print ':%s:' % option - print optdict.get('help') or option - inputfunc = INPUT_FUNCTIONS[optdict['type']] - value = inputfunc(optdict, defaultstr) - while default is REQUIRED and not value: - print 'please specify a value' - value = inputfunc(optdict, '%s: ' % option) - if value is None and default is not None: - value = default - self.set_option(option, value, optdict=optdict) - - def get_option_def(self, opt): - """return the dictionary defining an option given it's name""" - assert self.options - for option in self.options: - if option[0] == opt: - return option[1] - raise OptionError('no such option %s in section %r' - % (opt, self.name), opt) - - - def all_options(self): - """return an iterator on available options for this provider - option are actually described by a 3-uple: - (section, option name, option dictionary) - """ - for section, options in self.options_by_section(): - if section is None: - if self.name is None: - continue - section = self.name.upper() - for option, optiondict, value in options: - yield section, option, optiondict - - def options_by_section(self): - """return an iterator on options grouped by section - - (section, [list of (optname, optdict, optvalue)]) - """ - sections = {} - for optname, optdict in self.options: - sections.setdefault(optdict.get('group'), []).append( - (optname, optdict, self.option_value(optname))) - if None in sections: - yield None, sections.pop(None) - for section, options in sections.items(): - yield section.upper(), options - - def options_and_values(self, options=None): - if options is None: - options = self.options - for optname, optdict in options: - yield (optname, optdict, self.option_value(optname)) - - -class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn): - """basic mixin for simple configurations which don't need the - manager / providers model - """ - def __init__(self, *args, **kwargs): - if not args: - kwargs.setdefault('usage', '') - kwargs.setdefault('quiet', 1) - OptionsManagerMixIn.__init__(self, *args, **kwargs) - OptionsProviderMixIn.__init__(self) - if not getattr(self, 'option_groups', None): - self.option_groups = [] - for option, optdict in self.options: - try: - gdef = (optdict['group'].upper(), '') - except KeyError: - continue - if not gdef in self.option_groups: - self.option_groups.append(gdef) - self.register_options_provider(self, own_group=0) - - def register_options(self, options): - """add some options to the configuration""" - options_by_group = {} - for optname, optdict in options: - options_by_group.setdefault(optdict.get('group', self.name.upper()), []).append((optname, optdict)) - for group, options in options_by_group.items(): - self.add_option_group(group, None, options, self) - self.options += tuple(options) - - def load_defaults(self): - OptionsProviderMixIn.load_defaults(self) - - def __iter__(self): - return iter(self.config.__dict__.iteritems()) - - def __getitem__(self, key): - try: - return getattr(self.config, self.option_name(key)) - except (optparse.OptionValueError, AttributeError): - raise KeyError(key) - - def __setitem__(self, key, value): - self.set_option(key, value) - - def get(self, key, default=None): - try: - return getattr(self.config, self.option_name(key)) - except (OptionError, AttributeError): - return default - - -class Configuration(ConfigurationMixIn): - """class for simple configurations which don't need the - manager / providers model and prefer delegation to inheritance - - configuration values are accessible through a dict like interface - """ - - def __init__(self, config_file=None, options=None, name=None, - usage=None, doc=None, version=None): - if options is not None: - self.options = options - if name is not None: - self.name = name - if doc is not None: - self.__doc__ = doc - super(Configuration, self).__init__(config_file=config_file, usage=usage, version=version) - - -class OptionsManager2ConfigurationAdapter(object): - """Adapt an option manager to behave like a - `logilab.common.configuration.Configuration` instance - """ - def __init__(self, provider): - self.config = provider - - def __getattr__(self, key): - return getattr(self.config, key) - - def __getitem__(self, key): - provider = self.config._all_options[key] - try: - return getattr(provider.config, provider.option_name(key)) - except AttributeError: - raise KeyError(key) - - def __setitem__(self, key, value): - self.config.global_set_option(self.config.option_name(key), value) - - def get(self, key, default=None): - provider = self.config._all_options[key] - try: - return getattr(provider.config, provider.option_name(key)) - except AttributeError: - return default - - -def read_old_config(newconfig, changes, configfile): - """initialize newconfig from a deprecated configuration file - - possible changes: - * ('renamed', oldname, newname) - * ('moved', option, oldgroup, newgroup) - * ('typechanged', option, oldtype, newvalue) - """ - # build an index of changes - changesindex = {} - for action in changes: - if action[0] == 'moved': - option, oldgroup, newgroup = action[1:] - changesindex.setdefault(option, []).append((action[0], oldgroup, newgroup)) - continue - if action[0] == 'renamed': - oldname, newname = action[1:] - changesindex.setdefault(newname, []).append((action[0], oldname)) - continue - if action[0] == 'typechanged': - option, oldtype, newvalue = action[1:] - changesindex.setdefault(option, []).append((action[0], oldtype, newvalue)) - continue - if action[1] in ('added', 'removed'): - continue # nothing to do here - raise Exception('unknown change %s' % action[0]) - # build a config object able to read the old config - options = [] - for optname, optdef in newconfig.options: - for action in changesindex.pop(optname, ()): - if action[0] == 'moved': - oldgroup, newgroup = action[1:] - optdef = optdef.copy() - optdef['group'] = oldgroup - elif action[0] == 'renamed': - optname = action[1] - elif action[0] == 'typechanged': - oldtype = action[1] - optdef = optdef.copy() - optdef['type'] = oldtype - options.append((optname, optdef)) - if changesindex: - raise Exception('unapplied changes: %s' % changesindex) - oldconfig = Configuration(options=options, name=newconfig.name) - # read the old config - oldconfig.load_file_configuration(configfile) - # apply values reverting changes - changes.reverse() - done = set() - for action in changes: - if action[0] == 'renamed': - oldname, newname = action[1:] - newconfig[newname] = oldconfig[oldname] - done.add(newname) - elif action[0] == 'typechanged': - optname, oldtype, newvalue = action[1:] - newconfig[optname] = newvalue - done.add(optname) - for optname, optdef in newconfig.options: - if optdef.get('type') and not optname in done: - newconfig.set_option(optname, oldconfig[optname], optdict=optdef) - - -def merge_options(options, optgroup=None): - """preprocess a list of options and remove duplicates, returning a new list - (tuple actually) of options. - - Options dictionaries are copied to avoid later side-effect. Also, if - `otpgroup` argument is specified, ensure all options are in the given group. - """ - alloptions = {} - options = list(options) - for i in range(len(options)-1, -1, -1): - optname, optdict = options[i] - if optname in alloptions: - options.pop(i) - alloptions[optname].update(optdict) - else: - optdict = optdict.copy() - options[i] = (optname, optdict) - alloptions[optname] = optdict - if optgroup is not None: - alloptions[optname]['group'] = optgroup - return tuple(options) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/decorators.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/decorators.py @@ -1,283 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -""" A few useful function/method decorators. """ -__docformat__ = "restructuredtext en" - -import sys -from time import clock, time - -from .compat import callable, method_type - -# XXX rewrite so we can use the decorator syntax when keyarg has to be specified - -def _is_generator_function(callableobj): - return callableobj.func_code.co_flags & 0x20 - -class cached_decorator(object): - def __init__(self, cacheattr=None, keyarg=None): - self.cacheattr = cacheattr - self.keyarg = keyarg - def __call__(self, callableobj=None): - assert not _is_generator_function(callableobj), \ - 'cannot cache generator function: %s' % callableobj - if callableobj.func_code.co_argcount == 1 or self.keyarg == 0: - cache = _SingleValueCache(callableobj, self.cacheattr) - elif self.keyarg: - cache = _MultiValuesKeyArgCache(callableobj, self.keyarg, self.cacheattr) - else: - cache = _MultiValuesCache(callableobj, self.cacheattr) - return cache.closure() - -class _SingleValueCache(object): - def __init__(self, callableobj, cacheattr=None): - self.callable = callableobj - if cacheattr is None: - self.cacheattr = '_%s_cache_' % callableobj.__name__ - else: - assert cacheattr != callableobj.__name__ - self.cacheattr = cacheattr - - def __call__(__me, self, *args): - try: - return self.__dict__[__me.cacheattr] - except KeyError: - value = __me.callable(self, *args) - setattr(self, __me.cacheattr, value) - return value - - def closure(self): - def wrapped(*args, **kwargs): - return self.__call__(*args, **kwargs) - wrapped.cache_obj = self - try: - wrapped.__doc__ = self.callable.__doc__ - wrapped.__name__ = self.callable.__name__ - wrapped.func_name = self.callable.func_name - except: - pass - return wrapped - - def clear(self, holder): - holder.__dict__.pop(self.cacheattr, None) - - -class _MultiValuesCache(_SingleValueCache): - def _get_cache(self, holder): - try: - _cache = holder.__dict__[self.cacheattr] - except KeyError: - _cache = {} - setattr(holder, self.cacheattr, _cache) - return _cache - - def __call__(__me, self, *args, **kwargs): - _cache = __me._get_cache(self) - try: - return _cache[args] - except KeyError: - _cache[args] = __me.callable(self, *args) - return _cache[args] - -class _MultiValuesKeyArgCache(_MultiValuesCache): - def __init__(self, callableobj, keyarg, cacheattr=None): - super(_MultiValuesKeyArgCache, self).__init__(callableobj, cacheattr) - self.keyarg = keyarg - - def __call__(__me, self, *args, **kwargs): - _cache = __me._get_cache(self) - key = args[__me.keyarg-1] - try: - return _cache[key] - except KeyError: - _cache[key] = __me.callable(self, *args, **kwargs) - return _cache[key] - - -def cached(callableobj=None, keyarg=None, **kwargs): - """Simple decorator to cache result of method call.""" - kwargs['keyarg'] = keyarg - decorator = cached_decorator(**kwargs) - if callableobj is None: - return decorator - else: - return decorator(callableobj) - - -class cachedproperty(object): - """ Provides a cached property equivalent to the stacking of - @cached and @property, but more efficient. - - After first usage, the <property_name> becomes part of the object's - __dict__. Doing: - - del obj.<property_name> empties the cache. - - Idea taken from the pyramid_ framework and the mercurial_ project. - - .. _pyramid: http://pypi.python.org/pypi/pyramid - .. _mercurial: http://pypi.python.org/pypi/Mercurial - """ - __slots__ = ('wrapped',) - - def __init__(self, wrapped): - try: - wrapped.__name__ - except AttributeError: - raise TypeError('%s must have a __name__ attribute' % - wrapped) - self.wrapped = wrapped - - @property - def __doc__(self): - doc = getattr(self.wrapped, '__doc__', None) - return ('<wrapped by the cachedproperty decorator>%s' - % ('\n%s' % doc if doc else '')) - - def __get__(self, inst, objtype=None): - if inst is None: - return self - val = self.wrapped(inst) - setattr(inst, self.wrapped.__name__, val) - return val - - -def get_cache_impl(obj, funcname): - cls = obj.__class__ - member = getattr(cls, funcname) - if isinstance(member, property): - member = member.fget - return member.cache_obj - -def clear_cache(obj, funcname): - """Clear a cache handled by the :func:`cached` decorator. If 'x' class has - @cached on its method `foo`, type - - >>> clear_cache(x, 'foo') - - to purge this method's cache on the instance. - """ - get_cache_impl(obj, funcname).clear(obj) - -def copy_cache(obj, funcname, cacheobj): - """Copy cache for <funcname> from cacheobj to obj.""" - cacheattr = get_cache_impl(obj, funcname).cacheattr - try: - setattr(obj, cacheattr, cacheobj.__dict__[cacheattr]) - except KeyError: - pass - - -class wproperty(object): - """Simple descriptor expecting to take a modifier function as first argument - and looking for a _<function name> to retrieve the attribute. - """ - def __init__(self, setfunc): - self.setfunc = setfunc - self.attrname = '_%s' % setfunc.__name__ - - def __set__(self, obj, value): - self.setfunc(obj, value) - - def __get__(self, obj, cls): - assert obj is not None - return getattr(obj, self.attrname) - - -class classproperty(object): - """this is a simple property-like class but for class attributes. - """ - def __init__(self, get): - self.get = get - def __get__(self, inst, cls): - return self.get(cls) - - -class iclassmethod(object): - '''Descriptor for method which should be available as class method if called - on the class or instance method if called on an instance. - ''' - def __init__(self, func): - self.func = func - def __get__(self, instance, objtype): - if instance is None: - return method_type(self.func, objtype, objtype.__class__) - return method_type(self.func, instance, objtype) - def __set__(self, instance, value): - raise AttributeError("can't set attribute") - - -def timed(f): - def wrap(*args, **kwargs): - t = time() - c = clock() - res = f(*args, **kwargs) - print '%s clock: %.9f / time: %.9f' % (f.__name__, - clock() - c, time() - t) - return res - return wrap - - -def locked(acquire, release): - """Decorator taking two methods to acquire/release a lock as argument, - returning a decorator function which will call the inner method after - having called acquire(self) et will call release(self) afterwards. - """ - def decorator(f): - def wrapper(self, *args, **kwargs): - acquire(self) - try: - return f(self, *args, **kwargs) - finally: - release(self) - return wrapper - return decorator - - -def monkeypatch(klass, methodname=None): - """Decorator extending class with the decorated callable - >>> class A: - ... pass - >>> @monkeypatch(A) - ... def meth(self): - ... return 12 - ... - >>> a = A() - >>> a.meth() - 12 - >>> @monkeypatch(A, 'foo') - ... def meth(self): - ... return 12 - ... - >>> a.foo() - 12 - """ - def decorator(func): - try: - name = methodname or func.__name__ - except AttributeError: - raise AttributeError('%s has no __name__ attribute: ' - 'you should provide an explicit `methodname`' - % func) - if callable(func) and sys.version_info < (3, 0): - setattr(klass, name, method_type(func, None, klass)) - else: - # likely a property - # this is quite borderline but usage already in the wild ... - setattr(klass, name, func) - return func - return decorator diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/deprecation.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/deprecation.py @@ -1,188 +0,0 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Deprecation utilities.""" - -__docformat__ = "restructuredtext en" - -import sys -from warnings import warn - -from .changelog import Version - - -class DeprecationWrapper(object): - """proxy to print a warning on access to any attribute of the wrapped object - """ - def __init__(self, proxied, msg=None): - self._proxied = proxied - self._msg = msg - - def __getattr__(self, attr): - warn(self._msg, DeprecationWarning, stacklevel=2) - return getattr(self._proxied, attr) - - def __setattr__(self, attr, value): - if attr in ('_proxied', '_msg'): - self.__dict__[attr] = value - else: - warn(self._msg, DeprecationWarning, stacklevel=2) - setattr(self._proxied, attr, value) - - -class DeprecationManager(object): - """Manage the deprecation message handling. Messages are dropped for - versions more recent than the 'compatible' version. Example:: - - deprecator = deprecation.DeprecationManager("module_name") - deprecator.compatibility('1.3') - - deprecator.warn('1.2', "message.") - - @deprecator.deprecated('1.2', 'Message') - def any_func(): - pass - - class AnyClass(object): - __metaclass__ = deprecator.class_deprecated('1.2') - """ - def __init__(self, module_name=None): - """ - """ - self.module_name = module_name - self.compatible_version = None - - def compatibility(self, compatible_version): - """Set the compatible version. - """ - self.compatible_version = compatible_version - - def deprecated(self, version=None, reason=None, stacklevel=2, name=None, doc=None): - """Display a deprecation message only if the version is older than the - compatible version. - """ - def decorator(func): - message = reason or 'The function "%s" is deprecated' - if '%s' in message: - message %= func.func_name - def wrapped(*args, **kwargs): - self.warn(version, message, stacklevel) - return func(*args, **kwargs) - return wrapped - return decorator - - def class_deprecated(self, version=None): - class metaclass(type): - """metaclass to print a warning on instantiation of a deprecated class""" - - def __call__(cls, *args, **kwargs): - msg = getattr(cls, "__deprecation_warning__", - "%(cls)s is deprecated") % {'cls': cls.__name__} - self.warn(version, msg) - return type.__call__(cls, *args, **kwargs) - return metaclass - - def moved(self, version, modpath, objname): - """use to tell that a callable has been moved to a new module. - - It returns a callable wrapper, so that when its called a warning is printed - telling where the object can be found, import is done (and not before) and - the actual object is called. - - NOTE: the usage is somewhat limited on classes since it will fail if the - wrapper is use in a class ancestors list, use the `class_moved` function - instead (which has no lazy import feature though). - """ - def callnew(*args, **kwargs): - from logilab.common.modutils import load_module_from_name - message = "object %s has been moved to module %s" % (objname, modpath) - self.warn(version, message) - m = load_module_from_name(modpath) - return getattr(m, objname)(*args, **kwargs) - return callnew - - def class_renamed(self, version, old_name, new_class, message=None): - clsdict = {} - if message is None: - message = '%s is deprecated, use %s' % (old_name, new_class.__name__) - clsdict['__deprecation_warning__'] = message - try: - # new-style class - return self.class_deprecated(version)(old_name, (new_class,), clsdict) - except (NameError, TypeError): - # old-style class - class DeprecatedClass(new_class): - """FIXME: There might be a better way to handle old/new-style class - """ - def __init__(self, *args, **kwargs): - self.warn(version, message) - new_class.__init__(self, *args, **kwargs) - return DeprecatedClass - - def class_moved(self, version, new_class, old_name=None, message=None): - """nice wrapper around class_renamed when a class has been moved into - another module - """ - if old_name is None: - old_name = new_class.__name__ - if message is None: - message = 'class %s is now available as %s.%s' % ( - old_name, new_class.__module__, new_class.__name__) - return self.class_renamed(version, old_name, new_class, message) - - def warn(self, version=None, reason="", stacklevel=2): - """Display a deprecation message only if the version is older than the - compatible version. - """ - if self.module_name and version: - reason = '[%s %s] %s' % (self.module_name, version, reason) - elif self.module_name: - reason = '[%s] %s' % (self.module_name, reason) - elif version: - reason = '[%s] %s' % (version, reason) - if (self.compatible_version is None - or version is None - or Version(version) < Version(self.compatible_version)): - warn(reason, DeprecationWarning, stacklevel=stacklevel) - -_defaultdeprecator = DeprecationManager() - -def deprecated(reason=None, stacklevel=2, name=None, doc=None): - return _defaultdeprecator.deprecated(None, reason, stacklevel, name, doc) - -class_deprecated = _defaultdeprecator.class_deprecated() - -def moved(modpath, objname): - return _defaultdeprecator.moved(None, modpath, objname) -moved.__doc__ = _defaultdeprecator.moved.__doc__ - -def class_renamed(old_name, new_class, message=None): - """automatically creates a class which fires a DeprecationWarning - when instantiated. - - >>> Set = class_renamed('Set', set, 'Set is now replaced by set') - >>> s = Set() - sample.py:57: DeprecationWarning: Set is now replaced by set - s = Set() - >>> - """ - return _defaultdeprecator.class_renamed(None, old_name, new_class, message) - -def class_moved(new_class, old_name=None, message=None): - return _defaultdeprecator.class_moved(None, new_class, old_name, message) -class_moved.__doc__ = _defaultdeprecator.class_moved.__doc__ - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/graph.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/graph.py @@ -1,273 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Graph manipulation utilities. - -(dot generation adapted from pypy/translator/tool/make_dot.py) -""" - -__docformat__ = "restructuredtext en" - -__metaclass__ = type - -import os.path as osp -import os -import sys -import tempfile -from .compat import str_encode - -def escape(value): - """Make <value> usable in a dot file.""" - lines = [line.replace('"', '\\"') for line in value.split('\n')] - data = '\\l'.join(lines) - return '\\n' + data - -def target_info_from_filename(filename): - """Transforms /some/path/foo.png into ('/some/path', 'foo.png', 'png').""" - basename = osp.basename(filename) - storedir = osp.dirname(osp.abspath(filename)) - target = filename.split('.')[-1] - return storedir, basename, target - - -class DotBackend: - """Dot File backend.""" - def __init__(self, graphname, rankdir=None, size=None, ratio=None, - charset='utf-8', renderer='dot', additionnal_param={}): - self.graphname = graphname - self.renderer = renderer - self.lines = [] - self._source = None - self.emit("digraph %s {" % normalize_node_id(graphname)) - if rankdir: - self.emit('rankdir=%s' % rankdir) - if ratio: - self.emit('ratio=%s' % ratio) - if size: - self.emit('size="%s"' % size) - if charset: - assert charset.lower() in ('utf-8', 'iso-8859-1', 'latin1'), \ - 'unsupported charset %s' % charset - self.emit('charset="%s"' % charset) - for param in additionnal_param.iteritems(): - self.emit('='.join(param)) - - def get_source(self): - """returns self._source""" - if self._source is None: - self.emit("}\n") - self._source = '\n'.join(self.lines) - del self.lines - return self._source - - source = property(get_source) - - def generate(self, outputfile=None, dotfile=None, mapfile=None): - """Generates a graph file. - - :param outputfile: filename and path [defaults to graphname.png] - :param dotfile: filename and path [defaults to graphname.dot] - - :rtype: str - :return: a path to the generated file - """ - import subprocess # introduced in py 2.4 - name = self.graphname - if not dotfile: - # if 'outputfile' is a dot file use it as 'dotfile' - if outputfile and outputfile.endswith(".dot"): - dotfile = outputfile - else: - dotfile = '%s.dot' % name - if outputfile is not None: - storedir, basename, target = target_info_from_filename(outputfile) - if target != "dot": - pdot, dot_sourcepath = tempfile.mkstemp(".dot", name) - os.close(pdot) - else: - dot_sourcepath = osp.join(storedir, dotfile) - else: - target = 'png' - pdot, dot_sourcepath = tempfile.mkstemp(".dot", name) - ppng, outputfile = tempfile.mkstemp(".png", name) - os.close(pdot) - os.close(ppng) - pdot = open(dot_sourcepath, 'w') - pdot.write(str_encode(self.source, 'utf8')) - pdot.close() - if target != 'dot': - if sys.platform == 'win32': - use_shell = True - else: - use_shell = False - if mapfile: - subprocess.call([self.renderer, '-Tcmapx', '-o', mapfile, '-T', target, dot_sourcepath, '-o', outputfile], - shell=use_shell) - else: - subprocess.call([self.renderer, '-T', target, - dot_sourcepath, '-o', outputfile], - shell=use_shell) - os.unlink(dot_sourcepath) - return outputfile - - def emit(self, line): - """Adds <line> to final output.""" - self.lines.append(line) - - def emit_edge(self, name1, name2, **props): - """emit an edge from <name1> to <name2>. - edge properties: see http://www.graphviz.org/doc/info/attrs.html - """ - attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()] - n_from, n_to = normalize_node_id(name1), normalize_node_id(name2) - self.emit('%s -> %s [%s];' % (n_from, n_to, ", ".join(attrs)) ) - - def emit_node(self, name, **props): - """emit a node with given properties. - node properties: see http://www.graphviz.org/doc/info/attrs.html - """ - attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()] - self.emit('%s [%s];' % (normalize_node_id(name), ", ".join(attrs))) - -def normalize_node_id(nid): - """Returns a suitable DOT node id for `nid`.""" - return '"%s"' % nid - -class GraphGenerator: - def __init__(self, backend): - # the backend is responsible to output the graph in a particular format - self.backend = backend - - # XXX doesn't like space in outpufile / mapfile - def generate(self, visitor, propshdlr, outputfile=None, mapfile=None): - # the visitor - # the property handler is used to get node and edge properties - # according to the graph and to the backend - self.propshdlr = propshdlr - for nodeid, node in visitor.nodes(): - props = propshdlr.node_properties(node) - self.backend.emit_node(nodeid, **props) - for subjnode, objnode, edge in visitor.edges(): - props = propshdlr.edge_properties(edge, subjnode, objnode) - self.backend.emit_edge(subjnode, objnode, **props) - return self.backend.generate(outputfile=outputfile, mapfile=mapfile) - - -class UnorderableGraph(Exception): - pass - -def ordered_nodes(graph): - """takes a dependency graph dict as arguments and return an ordered tuple of - nodes starting with nodes without dependencies and up to the outermost node. - - If there is some cycle in the graph, :exc:`UnorderableGraph` will be raised. - - Also the given graph dict will be emptied. - """ - # check graph consistency - cycles = get_cycles(graph) - if cycles: - cycles = '\n'.join([' -> '.join(cycle) for cycle in cycles]) - raise UnorderableGraph('cycles in graph: %s' % cycles) - vertices = set(graph) - to_vertices = set() - for edges in graph.values(): - to_vertices |= set(edges) - missing_vertices = to_vertices - vertices - if missing_vertices: - raise UnorderableGraph('missing vertices: %s' % ', '.join(missing_vertices)) - # order vertices - order = [] - order_set = set() - old_len = None - while graph: - if old_len == len(graph): - raise UnorderableGraph('unknown problem with %s' % graph) - old_len = len(graph) - deps_ok = [] - for node, node_deps in graph.items(): - for dep in node_deps: - if dep not in order_set: - break - else: - deps_ok.append(node) - order.append(deps_ok) - order_set |= set(deps_ok) - for node in deps_ok: - del graph[node] - result = [] - for grp in reversed(order): - result.extend(sorted(grp)) - return tuple(result) - - -def get_cycles(graph_dict, vertices=None): - '''given a dictionary representing an ordered graph (i.e. key are vertices - and values is a list of destination vertices representing edges), return a - list of detected cycles - ''' - if not graph_dict: - return () - result = [] - if vertices is None: - vertices = graph_dict.keys() - for vertice in vertices: - _get_cycles(graph_dict, vertice, [], result) - return result - -def _get_cycles(graph_dict, vertice=None, path=None, result=None): - """recursive function doing the real work for get_cycles""" - if vertice in path: - cycle = [vertice] - for node in path[::-1]: - if node == vertice: - break - cycle.insert(0, node) - # make a canonical representation - start_from = min(cycle) - index = cycle.index(start_from) - cycle = cycle[index:] + cycle[0:index] - # append it to result if not already in - if not cycle in result: - result.append(cycle) - return - path.append(vertice) - try: - for node in graph_dict[vertice]: - _get_cycles(graph_dict, node, path, result) - except KeyError: - pass - path.pop() - -def has_path(graph_dict, fromnode, tonode, path=None): - """generic function taking a simple graph definition as a dictionary, with - node has key associated to a list of nodes directly reachable from it. - - Return None if no path exists to go from `fromnode` to `tonode`, else the - first path found (as a list including the destination node at last) - """ - if path is None: - path = [] - elif fromnode in path: - return None - path.append(fromnode) - for destnode in graph_dict[fromnode]: - if destnode == tonode or has_path(graph_dict, destnode, tonode, path): - return path[1:] + [tonode] - path.pop() - return None - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/interface.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/interface.py @@ -1,71 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Bases class for interfaces to provide 'light' interface handling. - - TODO: - _ implements a check method which check that an object implements the - interface - _ Attribute objects - - This module requires at least python 2.2 -""" -__docformat__ = "restructuredtext en" - - -class Interface(object): - """Base class for interfaces.""" - def is_implemented_by(cls, instance): - return implements(instance, cls) - is_implemented_by = classmethod(is_implemented_by) - - -def implements(obj, interface): - """Return true if the give object (maybe an instance or class) implements - the interface. - """ - kimplements = getattr(obj, '__implements__', ()) - if not isinstance(kimplements, (list, tuple)): - kimplements = (kimplements,) - for implementedinterface in kimplements: - if issubclass(implementedinterface, interface): - return True - return False - - -def extend(klass, interface, _recurs=False): - """Add interface to klass'__implements__ if not already implemented in. - - If klass is subclassed, ensure subclasses __implements__ it as well. - - NOTE: klass should be e new class. - """ - if not implements(klass, interface): - try: - kimplements = klass.__implements__ - kimplementsklass = type(kimplements) - kimplements = list(kimplements) - except AttributeError: - kimplementsklass = tuple - kimplements = [] - kimplements.append(interface) - klass.__implements__ = kimplementsklass(kimplements) - for subklass in klass.__subclasses__(): - extend(subklass, interface, _recurs=True) - elif _recurs: - for subklass in klass.__subclasses__(): - extend(subklass, interface, _recurs=True) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/modutils.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/modutils.py @@ -1,658 +0,0 @@ -# -*- coding: utf-8 -*- -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Python modules manipulation utility functions. - -:type PY_SOURCE_EXTS: tuple(str) -:var PY_SOURCE_EXTS: list of possible python source file extension - -:type STD_LIB_DIR: str -:var STD_LIB_DIR: directory where standard modules are located - -:type BUILTIN_MODULES: dict -:var BUILTIN_MODULES: dictionary with builtin module names has key -""" -__docformat__ = "restructuredtext en" - -import sys -import os -from os.path import splitext, join, abspath, isdir, dirname, exists, basename -from imp import find_module, load_module, C_BUILTIN, PY_COMPILED, PKG_DIRECTORY -from distutils.sysconfig import get_config_var, get_python_lib, get_python_version -from distutils.errors import DistutilsPlatformError - -try: - import zipimport -except ImportError: - zipimport = None - -ZIPFILE = object() - -from . import STD_BLACKLIST, _handle_blacklist - -# Notes about STD_LIB_DIR -# Consider arch-specific installation for STD_LIB_DIR definition -# :mod:`distutils.sysconfig` contains to much hardcoded values to rely on -# -# :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_ -# :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEFORMATESSENTIAL>`_ -if sys.platform.startswith('win'): - PY_SOURCE_EXTS = ('py', 'pyw') - PY_COMPILED_EXTS = ('dll', 'pyd') -else: - PY_SOURCE_EXTS = ('py',) - PY_COMPILED_EXTS = ('so',) - -try: - STD_LIB_DIR = get_python_lib(standard_lib=1) -# get_python_lib(standard_lib=1) is not available on pypy, set STD_LIB_DIR to -# non-valid path, see https://bugs.pypy.org/issue1164 -except DistutilsPlatformError: - STD_LIB_DIR = '//' - -EXT_LIB_DIR = get_python_lib() - -BUILTIN_MODULES = dict(zip(sys.builtin_module_names, - [1]*len(sys.builtin_module_names))) - - -class NoSourceFile(Exception): - """exception raised when we are not able to get a python - source file for a precompiled file - """ - -class LazyObject(object): - def __init__(self, module, obj): - self.module = module - self.obj = obj - self._imported = None - - def _getobj(self): - if self._imported is None: - self._imported = getattr(load_module_from_name(self.module), - self.obj) - return self._imported - - def __getattribute__(self, attr): - try: - return super(LazyObject, self).__getattribute__(attr) - except AttributeError, ex: - return getattr(self._getobj(), attr) - - def __call__(self, *args, **kwargs): - return self._getobj()(*args, **kwargs) - - -def load_module_from_name(dotted_name, path=None, use_sys=1): - """Load a Python module from its name. - - :type dotted_name: str - :param dotted_name: python name of a module or package - - :type path: list or None - :param path: - optional list of path where the module or package should be - searched (use sys.path if nothing or None is given) - - :type use_sys: bool - :param use_sys: - boolean indicating whether the sys.modules dictionary should be - used or not - - - :raise ImportError: if the module or package is not found - - :rtype: module - :return: the loaded module - """ - return load_module_from_modpath(dotted_name.split('.'), path, use_sys) - - -def load_module_from_modpath(parts, path=None, use_sys=1): - """Load a python module from its splitted name. - - :type parts: list(str) or tuple(str) - :param parts: - python name of a module or package splitted on '.' - - :type path: list or None - :param path: - optional list of path where the module or package should be - searched (use sys.path if nothing or None is given) - - :type use_sys: bool - :param use_sys: - boolean indicating whether the sys.modules dictionary should be used or not - - :raise ImportError: if the module or package is not found - - :rtype: module - :return: the loaded module - """ - if use_sys: - try: - return sys.modules['.'.join(parts)] - except KeyError: - pass - modpath = [] - prevmodule = None - for part in parts: - modpath.append(part) - curname = '.'.join(modpath) - module = None - if len(modpath) != len(parts): - # even with use_sys=False, should try to get outer packages from sys.modules - module = sys.modules.get(curname) - elif use_sys: - # because it may have been indirectly loaded through a parent - module = sys.modules.get(curname) - if module is None: - mp_file, mp_filename, mp_desc = find_module(part, path) - module = load_module(curname, mp_file, mp_filename, mp_desc) - if prevmodule: - setattr(prevmodule, part, module) - _file = getattr(module, '__file__', '') - if not _file and len(modpath) != len(parts): - raise ImportError('no module in %s' % '.'.join(parts[len(modpath):]) ) - path = [dirname( _file )] - prevmodule = module - return module - - -def load_module_from_file(filepath, path=None, use_sys=1, extrapath=None): - """Load a Python module from it's path. - - :type filepath: str - :param filepath: path to the python module or package - - :type path: list or None - :param path: - optional list of path where the module or package should be - searched (use sys.path if nothing or None is given) - - :type use_sys: bool - :param use_sys: - boolean indicating whether the sys.modules dictionary should be - used or not - - - :raise ImportError: if the module or package is not found - - :rtype: module - :return: the loaded module - """ - modpath = modpath_from_file(filepath, extrapath) - return load_module_from_modpath(modpath, path, use_sys) - - -def _check_init(path, mod_path): - """check there are some __init__.py all along the way""" - for part in mod_path: - path = join(path, part) - if not _has_init(path): - return False - return True - - -def modpath_from_file(filename, extrapath=None): - """given a file path return the corresponding splitted module's name - (i.e name of a module or package splitted on '.') - - :type filename: str - :param filename: file's path for which we want the module's name - - :type extrapath: dict - :param extrapath: - optional extra search path, with path as key and package name for the path - as value. This is usually useful to handle package splitted in multiple - directories using __path__ trick. - - - :raise ImportError: - if the corresponding module's name has not been found - - :rtype: list(str) - :return: the corresponding splitted module's name - """ - base = splitext(abspath(filename))[0] - if extrapath is not None: - for path_ in extrapath: - path = abspath(path_) - if path and base[:len(path)] == path: - submodpath = [pkg for pkg in base[len(path):].split(os.sep) - if pkg] - if _check_init(path, submodpath[:-1]): - return extrapath[path_].split('.') + submodpath - for path in sys.path: - path = abspath(path) - if path and base.startswith(path): - modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] - if _check_init(path, modpath[:-1]): - return modpath - raise ImportError('Unable to find module for %s in %s' % ( - filename, ', \n'.join(sys.path))) - - - -def file_from_modpath(modpath, path=None, context_file=None): - """given a mod path (i.e. splitted module / package name), return the - corresponding file, giving priority to source file over precompiled - file if it exists - - :type modpath: list or tuple - :param modpath: - splitted module's name (i.e name of a module or package splitted - on '.') - (this means explicit relative imports that start with dots have - empty strings in this list!) - - :type path: list or None - :param path: - optional list of path where the module or package should be - searched (use sys.path if nothing or None is given) - - :type context_file: str or None - :param context_file: - context file to consider, necessary if the identifier has been - introduced using a relative import unresolvable in the actual - context (i.e. modutils) - - :raise ImportError: if there is no such module in the directory - - :rtype: str or None - :return: - the path to the module's file or None if it's an integrated - builtin module such as 'sys' - """ - if context_file is not None: - context = dirname(context_file) - else: - context = context_file - if modpath[0] == 'xml': - # handle _xmlplus - try: - return _file_from_modpath(['_xmlplus'] + modpath[1:], path, context) - except ImportError: - return _file_from_modpath(modpath, path, context) - elif modpath == ['os', 'path']: - # FIXME: currently ignoring search_path... - return os.path.__file__ - return _file_from_modpath(modpath, path, context) - - - -def get_module_part(dotted_name, context_file=None): - """given a dotted name return the module part of the name : - - >>> get_module_part('logilab.common.modutils.get_module_part') - 'logilab.common.modutils' - - :type dotted_name: str - :param dotted_name: full name of the identifier we are interested in - - :type context_file: str or None - :param context_file: - context file to consider, necessary if the identifier has been - introduced using a relative import unresolvable in the actual - context (i.e. modutils) - - - :raise ImportError: if there is no such module in the directory - - :rtype: str or None - :return: - the module part of the name or None if we have not been able at - all to import the given name - - XXX: deprecated, since it doesn't handle package precedence over module - (see #10066) - """ - # os.path trick - if dotted_name.startswith('os.path'): - return 'os.path' - parts = dotted_name.split('.') - if context_file is not None: - # first check for builtin module which won't be considered latter - # in that case (path != None) - if parts[0] in BUILTIN_MODULES: - if len(parts) > 2: - raise ImportError(dotted_name) - return parts[0] - # don't use += or insert, we want a new list to be created ! - path = None - starti = 0 - if parts[0] == '': - assert context_file is not None, \ - 'explicit relative import, but no context_file?' - path = [] # prevent resolving the import non-relatively - starti = 1 - while parts[starti] == '': # for all further dots: change context - starti += 1 - context_file = dirname(context_file) - for i in range(starti, len(parts)): - try: - file_from_modpath(parts[starti:i+1], - path=path, context_file=context_file) - except ImportError: - if not i >= max(1, len(parts) - 2): - raise - return '.'.join(parts[:i]) - return dotted_name - - -def get_modules(package, src_directory, blacklist=STD_BLACKLIST): - """given a package directory return a list of all available python - modules in the package and its subpackages - - :type package: str - :param package: the python name for the package - - :type src_directory: str - :param src_directory: - path of the directory corresponding to the package - - :type blacklist: list or tuple - :param blacklist: - optional list of files or directory to ignore, default to - the value of `logilab.common.STD_BLACKLIST` - - :rtype: list - :return: - the list of all available python modules in the package and its - subpackages - """ - modules = [] - for directory, dirnames, filenames in os.walk(src_directory): - _handle_blacklist(blacklist, dirnames, filenames) - # check for __init__.py - if not '__init__.py' in filenames: - dirnames[:] = () - continue - if directory != src_directory: - dir_package = directory[len(src_directory):].replace(os.sep, '.') - modules.append(package + dir_package) - for filename in filenames: - if _is_python_file(filename) and filename != '__init__.py': - src = join(directory, filename) - module = package + src[len(src_directory):-3] - modules.append(module.replace(os.sep, '.')) - return modules - - - -def get_module_files(src_directory, blacklist=STD_BLACKLIST): - """given a package directory return a list of all available python - module's files in the package and its subpackages - - :type src_directory: str - :param src_directory: - path of the directory corresponding to the package - - :type blacklist: list or tuple - :param blacklist: - optional list of files or directory to ignore, default to the value of - `logilab.common.STD_BLACKLIST` - - :rtype: list - :return: - the list of all available python module's files in the package and - its subpackages - """ - files = [] - for directory, dirnames, filenames in os.walk(src_directory): - _handle_blacklist(blacklist, dirnames, filenames) - # check for __init__.py - if not '__init__.py' in filenames: - dirnames[:] = () - continue - for filename in filenames: - if _is_python_file(filename): - src = join(directory, filename) - files.append(src) - return files - - -def get_source_file(filename, include_no_ext=False): - """given a python module's file name return the matching source file - name (the filename will be returned identically if it's a already an - absolute path to a python source file...) - - :type filename: str - :param filename: python module's file name - - - :raise NoSourceFile: if no source file exists on the file system - - :rtype: str - :return: the absolute path of the source file if it exists - """ - base, orig_ext = splitext(abspath(filename)) - for ext in PY_SOURCE_EXTS: - source_path = '%s.%s' % (base, ext) - if exists(source_path): - return source_path - if include_no_ext and not orig_ext and exists(base): - return base - raise NoSourceFile(filename) - - -def cleanup_sys_modules(directories): - """remove submodules of `directories` from `sys.modules`""" - for modname, module in sys.modules.items(): - modfile = getattr(module, '__file__', None) - if modfile: - for directory in directories: - if modfile.startswith(directory): - del sys.modules[modname] - break - - -def is_python_source(filename): - """ - rtype: bool - return: True if the filename is a python source file - """ - return splitext(filename)[1][1:] in PY_SOURCE_EXTS - - - -def is_standard_module(modname, std_path=(STD_LIB_DIR,)): - """try to guess if a module is a standard python module (by default, - see `std_path` parameter's description) - - :type modname: str - :param modname: name of the module we are interested in - - :type std_path: list(str) or tuple(str) - :param std_path: list of path considered has standard - - - :rtype: bool - :return: - true if the module: - - is located on the path listed in one of the directory in `std_path` - - is a built-in module - """ - modname = modname.split('.')[0] - try: - filename = file_from_modpath([modname]) - except ImportError, ex: - # import failed, i'm probably not so wrong by supposing it's - # not standard... - return 0 - # modules which are not living in a file are considered standard - # (sys and __builtin__ for instance) - if filename is None: - return 1 - filename = abspath(filename) - if filename.startswith(EXT_LIB_DIR): - return 0 - for path in std_path: - if filename.startswith(abspath(path)): - return 1 - return False - - - -def is_relative(modname, from_file): - """return true if the given module name is relative to the given - file name - - :type modname: str - :param modname: name of the module we are interested in - - :type from_file: str - :param from_file: - path of the module from which modname has been imported - - :rtype: bool - :return: - true if the module has been imported relatively to `from_file` - """ - if not isdir(from_file): - from_file = dirname(from_file) - if from_file in sys.path: - return False - try: - find_module(modname.split('.')[0], [from_file]) - return True - except ImportError: - return False - - -# internal only functions ##################################################### - -def _file_from_modpath(modpath, path=None, context=None): - """given a mod path (i.e. splitted module / package name), return the - corresponding file - - this function is used internally, see `file_from_modpath`'s - documentation for more information - """ - assert len(modpath) > 0 - if context is not None: - try: - mtype, mp_filename = _module_file(modpath, [context]) - except ImportError: - mtype, mp_filename = _module_file(modpath, path) - else: - mtype, mp_filename = _module_file(modpath, path) - if mtype == PY_COMPILED: - try: - return get_source_file(mp_filename) - except NoSourceFile: - return mp_filename - elif mtype == C_BUILTIN: - # integrated builtin module - return None - elif mtype == PKG_DIRECTORY: - mp_filename = _has_init(mp_filename) - return mp_filename - -def _search_zip(modpath, pic): - for filepath, importer in pic.items(): - if importer is not None: - if importer.find_module(modpath[0]): - if not importer.find_module('/'.join(modpath)): - raise ImportError('No module named %s in %s/%s' % ( - '.'.join(modpath[1:]), file, modpath)) - return ZIPFILE, abspath(filepath) + '/' + '/'.join(modpath), filepath - raise ImportError('No module named %s' % '.'.join(modpath)) - -def _module_file(modpath, path=None): - """get a module type / file path - - :type modpath: list or tuple - :param modpath: - splitted module's name (i.e name of a module or package splitted - on '.'), with leading empty strings for explicit relative import - - :type path: list or None - :param path: - optional list of path where the module or package should be - searched (use sys.path if nothing or None is given) - - - :rtype: tuple(int, str) - :return: the module type flag and the file path for a module - """ - # egg support compat - try: - pic = sys.path_importer_cache - _path = (path is None and sys.path or path) - for __path in _path: - if not __path in pic: - try: - pic[__path] = zipimport.zipimporter(__path) - except zipimport.ZipImportError: - pic[__path] = None - checkeggs = True - except AttributeError: - checkeggs = False - imported = [] - while modpath: - try: - _, mp_filename, mp_desc = find_module(modpath[0], path) - except ImportError: - if checkeggs: - return _search_zip(modpath, pic)[:2] - raise - else: - if checkeggs: - fullabspath = [abspath(x) for x in _path] - try: - pathindex = fullabspath.index(dirname(abspath(mp_filename))) - emtype, emp_filename, zippath = _search_zip(modpath, pic) - if pathindex > _path.index(zippath): - # an egg takes priority - return emtype, emp_filename - except ValueError: - # XXX not in _path - pass - except ImportError: - pass - checkeggs = False - imported.append(modpath.pop(0)) - mtype = mp_desc[2] - if modpath: - if mtype != PKG_DIRECTORY: - raise ImportError('No module %s in %s' % ('.'.join(modpath), - '.'.join(imported))) - path = [mp_filename] - return mtype, mp_filename - -def _is_python_file(filename): - """return true if the given filename should be considered as a python file - - .pyc and .pyo are ignored - """ - for ext in ('.py', '.so', '.pyd', '.pyw'): - if filename.endswith(ext): - return True - return False - - -def _has_init(directory): - """if the given directory has a valid __init__ file, return its path, - else return None - """ - mod_or_pack = join(directory, '__init__') - for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'): - if exists(mod_or_pack + '.' + ext): - return mod_or_pack + '.' + ext - return None diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/optik_ext.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/optik_ext.py @@ -1,397 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Add an abstraction level to transparently import optik classes from optparse -(python >= 2.3) or the optik package. - -It also defines three new types for optik/optparse command line parser : - - * regexp - argument of this type will be converted using re.compile - * csv - argument of this type will be converted using split(',') - * yn - argument of this type will be true if 'y' or 'yes', false if 'n' or 'no' - * named - argument of this type are in the form <NAME>=<VALUE> or <NAME>:<VALUE> - * password - argument of this type wont be converted but this is used by other tools - such as interactive prompt for configuration to double check value and - use an invisible field - * multiple_choice - same as default "choice" type but multiple choices allowed - * file - argument of this type wont be converted but checked that the given file exists - * color - argument of this type wont be converted but checked its either a - named color or a color specified using hexadecimal notation (preceded by a #) - * time - argument of this type will be converted to a float value in seconds - according to time units (ms, s, min, h, d) - * bytes - argument of this type will be converted to a float value in bytes - according to byte units (b, kb, mb, gb, tb) -""" -__docformat__ = "restructuredtext en" - -import re -import sys -import time -from copy import copy -from os.path import exists - -# python >= 2.3 -from optparse import OptionParser as BaseParser, Option as BaseOption, \ - OptionGroup, OptionContainer, OptionValueError, OptionError, \ - Values, HelpFormatter, NO_DEFAULT, SUPPRESS_HELP - -try: - from mx import DateTime - HAS_MX_DATETIME = True -except ImportError: - HAS_MX_DATETIME = False - - -OPTPARSE_FORMAT_DEFAULT = sys.version_info >= (2, 4) - -from .textutils import splitstrip - -def check_regexp(option, opt, value): - """check a regexp value by trying to compile it - return the compiled regexp - """ - if hasattr(value, 'pattern'): - return value - try: - return re.compile(value) - except ValueError: - raise OptionValueError( - "option %s: invalid regexp value: %r" % (opt, value)) - -def check_csv(option, opt, value): - """check a csv value by trying to split it - return the list of separated values - """ - if isinstance(value, (list, tuple)): - return value - try: - return splitstrip(value) - except ValueError: - raise OptionValueError( - "option %s: invalid csv value: %r" % (opt, value)) - -def check_yn(option, opt, value): - """check a yn value - return true for yes and false for no - """ - if isinstance(value, int): - return bool(value) - if value in ('y', 'yes'): - return True - if value in ('n', 'no'): - return False - msg = "option %s: invalid yn value %r, should be in (y, yes, n, no)" - raise OptionValueError(msg % (opt, value)) - -def check_named(option, opt, value): - """check a named value - return a dictionary containing (name, value) associations - """ - if isinstance(value, dict): - return value - values = [] - for value in check_csv(option, opt, value): - if value.find('=') != -1: - values.append(value.split('=', 1)) - elif value.find(':') != -1: - values.append(value.split(':', 1)) - if values: - return dict(values) - msg = "option %s: invalid named value %r, should be <NAME>=<VALUE> or \ -<NAME>:<VALUE>" - raise OptionValueError(msg % (opt, value)) - -def check_password(option, opt, value): - """check a password value (can't be empty) - """ - # no actual checking, monkey patch if you want more - return value - -def check_file(option, opt, value): - """check a file value - return the filepath - """ - if exists(value): - return value - msg = "option %s: file %r does not exist" - raise OptionValueError(msg % (opt, value)) - -# XXX use python datetime -def check_date(option, opt, value): - """check a file value - return the filepath - """ - try: - return DateTime.strptime(value, "%Y/%m/%d") - except DateTime.Error : - raise OptionValueError( - "expected format of %s is yyyy/mm/dd" % opt) - -def check_color(option, opt, value): - """check a color value and returns it - /!\ does *not* check color labels (like 'red', 'green'), only - checks hexadecimal forms - """ - # Case (1) : color label, we trust the end-user - if re.match('[a-z0-9 ]+$', value, re.I): - return value - # Case (2) : only accepts hexadecimal forms - if re.match('#[a-f0-9]{6}', value, re.I): - return value - # Else : not a color label neither a valid hexadecimal form => error - msg = "option %s: invalid color : %r, should be either hexadecimal \ - value or predefined color" - raise OptionValueError(msg % (opt, value)) - -def check_time(option, opt, value): - from logilab.common.textutils import TIME_UNITS, apply_units - if isinstance(value, (int, long, float)): - return value - return apply_units(value, TIME_UNITS) - -def check_bytes(option, opt, value): - from logilab.common.textutils import BYTE_UNITS, apply_units - if hasattr(value, '__int__'): - return value - return apply_units(value, BYTE_UNITS) - -import types - -class Option(BaseOption): - """override optik.Option to add some new option types - """ - TYPES = BaseOption.TYPES + ('regexp', 'csv', 'yn', 'named', 'password', - 'multiple_choice', 'file', 'color', - 'time', 'bytes') - ATTRS = BaseOption.ATTRS + ['hide', 'level'] - TYPE_CHECKER = copy(BaseOption.TYPE_CHECKER) - TYPE_CHECKER['regexp'] = check_regexp - TYPE_CHECKER['csv'] = check_csv - TYPE_CHECKER['yn'] = check_yn - TYPE_CHECKER['named'] = check_named - TYPE_CHECKER['multiple_choice'] = check_csv - TYPE_CHECKER['file'] = check_file - TYPE_CHECKER['color'] = check_color - TYPE_CHECKER['password'] = check_password - TYPE_CHECKER['time'] = check_time - TYPE_CHECKER['bytes'] = check_bytes - if HAS_MX_DATETIME: - TYPES += ('date',) - TYPE_CHECKER['date'] = check_date - - def __init__(self, *opts, **attrs): - BaseOption.__init__(self, *opts, **attrs) - if hasattr(self, "hide") and self.hide: - self.help = SUPPRESS_HELP - - def _check_choice(self): - """FIXME: need to override this due to optik misdesign""" - if self.type in ("choice", "multiple_choice"): - if self.choices is None: - raise OptionError( - "must supply a list of choices for type 'choice'", self) - elif type(self.choices) not in (types.TupleType, types.ListType): - raise OptionError( - "choices must be a list of strings ('%s' supplied)" - % str(type(self.choices)).split("'")[1], self) - elif self.choices is not None: - raise OptionError( - "must not supply choices for type %r" % self.type, self) - BaseOption.CHECK_METHODS[2] = _check_choice - - - def process(self, opt, value, values, parser): - # First, convert the value(s) to the right type. Howl if any - # value(s) are bogus. - try: - value = self.convert_value(opt, value) - except AttributeError: # py < 2.4 - value = self.check_value(opt, value) - if self.type == 'named': - existant = getattr(values, self.dest) - if existant: - existant.update(value) - value = existant - # And then take whatever action is expected of us. - # This is a separate method to make life easier for - # subclasses to add new actions. - return self.take_action( - self.action, self.dest, opt, value, values, parser) - - -class OptionParser(BaseParser): - """override optik.OptionParser to use our Option class - """ - def __init__(self, option_class=Option, *args, **kwargs): - BaseParser.__init__(self, option_class=Option, *args, **kwargs) - - def format_option_help(self, formatter=None): - if formatter is None: - formatter = self.formatter - outputlevel = getattr(formatter, 'output_level', 0) - formatter.store_option_strings(self) - result = [] - result.append(formatter.format_heading("Options")) - formatter.indent() - if self.option_list: - result.append(OptionContainer.format_option_help(self, formatter)) - result.append("\n") - for group in self.option_groups: - if group.level <= outputlevel and ( - group.description or level_options(group, outputlevel)): - result.append(group.format_help(formatter)) - result.append("\n") - formatter.dedent() - # Drop the last "\n", or the header if no options or option groups: - return "".join(result[:-1]) - - -OptionGroup.level = 0 - -def level_options(group, outputlevel): - return [option for option in group.option_list - if (getattr(option, 'level', 0) or 0) <= outputlevel - and not option.help is SUPPRESS_HELP] - -def format_option_help(self, formatter): - result = [] - outputlevel = getattr(formatter, 'output_level', 0) or 0 - for option in level_options(self, outputlevel): - result.append(formatter.format_option(option)) - return "".join(result) -OptionContainer.format_option_help = format_option_help - - -class ManHelpFormatter(HelpFormatter): - """Format help using man pages ROFF format""" - - def __init__ (self, - indent_increment=0, - max_help_position=24, - width=79, - short_first=0): - HelpFormatter.__init__ ( - self, indent_increment, max_help_position, width, short_first) - - def format_heading(self, heading): - return '.SH %s\n' % heading.upper() - - def format_description(self, description): - return description - - def format_option(self, option): - try: - optstring = option.option_strings - except AttributeError: - optstring = self.format_option_strings(option) - if option.help: - help_text = self.expand_default(option) - help = ' '.join([l.strip() for l in help_text.splitlines()]) - else: - help = '' - return '''.IP "%s" -%s -''' % (optstring, help) - - def format_head(self, optparser, pkginfo, section=1): - long_desc = "" - try: - pgm = optparser._get_prog_name() - except AttributeError: - # py >= 2.4.X (dunno which X exactly, at least 2) - pgm = optparser.get_prog_name() - short_desc = self.format_short_description(pgm, pkginfo.description) - if hasattr(pkginfo, "long_desc"): - long_desc = self.format_long_description(pgm, pkginfo.long_desc) - return '%s\n%s\n%s\n%s' % (self.format_title(pgm, section), - short_desc, self.format_synopsis(pgm), - long_desc) - - def format_title(self, pgm, section): - date = '-'.join([str(num) for num in time.localtime()[:3]]) - return '.TH %s %s "%s" %s' % (pgm, section, date, pgm) - - def format_short_description(self, pgm, short_desc): - return '''.SH NAME -.B %s -\- %s -''' % (pgm, short_desc.strip()) - - def format_synopsis(self, pgm): - return '''.SH SYNOPSIS -.B %s -[ -.I OPTIONS -] [ -.I <arguments> -] -''' % pgm - - def format_long_description(self, pgm, long_desc): - long_desc = '\n'.join([line.lstrip() - for line in long_desc.splitlines()]) - long_desc = long_desc.replace('\n.\n', '\n\n') - if long_desc.lower().startswith(pgm): - long_desc = long_desc[len(pgm):] - return '''.SH DESCRIPTION -.B %s -%s -''' % (pgm, long_desc.strip()) - - def format_tail(self, pkginfo): - tail = '''.SH SEE ALSO -/usr/share/doc/pythonX.Y-%s/ - -.SH BUGS -Please report bugs on the project\'s mailing list: -%s - -.SH AUTHOR -%s <%s> -''' % (getattr(pkginfo, 'debian_name', pkginfo.modname), - pkginfo.mailinglist, pkginfo.author, pkginfo.author_email) - - if hasattr(pkginfo, "copyright"): - tail += ''' -.SH COPYRIGHT -%s -''' % pkginfo.copyright - - return tail - -def generate_manpage(optparser, pkginfo, section=1, stream=sys.stdout, level=0): - """generate a man page from an optik parser""" - formatter = ManHelpFormatter() - formatter.output_level = level - formatter.parser = optparser - print >> stream, formatter.format_head(optparser, pkginfo, section) - print >> stream, optparser.format_option_help(formatter) - print >> stream, formatter.format_tail(pkginfo) - - -__all__ = ('OptionParser', 'Option', 'OptionGroup', 'OptionValueError', - 'Values') diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/textutils.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/textutils.py @@ -1,534 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Some text manipulation utility functions. - - -:group text formatting: normalize_text, normalize_paragraph, pretty_match,\ -unquote, colorize_ansi -:group text manipulation: searchall, splitstrip -:sort: text formatting, text manipulation - -:type ANSI_STYLES: dict(str) -:var ANSI_STYLES: dictionary mapping style identifier to ANSI terminal code - -:type ANSI_COLORS: dict(str) -:var ANSI_COLORS: dictionary mapping color identifier to ANSI terminal code - -:type ANSI_PREFIX: str -:var ANSI_PREFIX: - ANSI terminal code notifying the start of an ANSI escape sequence - -:type ANSI_END: str -:var ANSI_END: - ANSI terminal code notifying the end of an ANSI escape sequence - -:type ANSI_RESET: str -:var ANSI_RESET: - ANSI terminal code resetting format defined by a previous ANSI escape sequence -""" -__docformat__ = "restructuredtext en" - -import sys -import re -import os.path as osp -from warnings import warn -from unicodedata import normalize as _uninormalize -try: - from os import linesep -except ImportError: - linesep = '\n' # gae - -from .deprecation import deprecated - -MANUAL_UNICODE_MAP = { - u'\xa1': u'!', # INVERTED EXCLAMATION MARK - u'\u0142': u'l', # LATIN SMALL LETTER L WITH STROKE - u'\u2044': u'/', # FRACTION SLASH - u'\xc6': u'AE', # LATIN CAPITAL LETTER AE - u'\xa9': u'(c)', # COPYRIGHT SIGN - u'\xab': u'"', # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - u'\xe6': u'ae', # LATIN SMALL LETTER AE - u'\xae': u'(r)', # REGISTERED SIGN - u'\u0153': u'oe', # LATIN SMALL LIGATURE OE - u'\u0152': u'OE', # LATIN CAPITAL LIGATURE OE - u'\xd8': u'O', # LATIN CAPITAL LETTER O WITH STROKE - u'\xf8': u'o', # LATIN SMALL LETTER O WITH STROKE - u'\xbb': u'"', # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - u'\xdf': u'ss', # LATIN SMALL LETTER SHARP S - } - -def unormalize(ustring, ignorenonascii=None, substitute=None): - """replace diacritical characters with their corresponding ascii characters - - Convert the unicode string to its long normalized form (unicode character - will be transform into several characters) and keep the first one only. - The normal form KD (NFKD) will apply the compatibility decomposition, i.e. - replace all compatibility characters with their equivalents. - - :type substitute: str - :param substitute: replacement character to use if decomposition fails - - :see: Another project about ASCII transliterations of Unicode text - http://pypi.python.org/pypi/Unidecode - """ - # backward compatibility, ignorenonascii was a boolean - if ignorenonascii is not None: - warn("ignorenonascii is deprecated, use substitute named parameter instead", - DeprecationWarning, stacklevel=2) - if ignorenonascii: - substitute = '' - res = [] - for letter in ustring[:]: - try: - replacement = MANUAL_UNICODE_MAP[letter] - except KeyError: - replacement = _uninormalize('NFKD', letter)[0] - if ord(replacement) >= 2 ** 7: - if substitute is None: - raise ValueError("can't deal with non-ascii based characters") - replacement = substitute - res.append(replacement) - return u''.join(res) - -def unquote(string): - """remove optional quotes (simple or double) from the string - - :type string: str or unicode - :param string: an optionally quoted string - - :rtype: str or unicode - :return: the unquoted string (or the input string if it wasn't quoted) - """ - if not string: - return string - if string[0] in '"\'': - string = string[1:] - if string[-1] in '"\'': - string = string[:-1] - return string - - -_BLANKLINES_RGX = re.compile('\r?\n\r?\n') -_NORM_SPACES_RGX = re.compile('\s+') - -def normalize_text(text, line_len=80, indent='', rest=False): - """normalize a text to display it with a maximum line size and - optionally arbitrary indentation. Line jumps are normalized but blank - lines are kept. The indentation string may be used to insert a - comment (#) or a quoting (>) mark for instance. - - :type text: str or unicode - :param text: the input text to normalize - - :type line_len: int - :param line_len: expected maximum line's length, default to 80 - - :type indent: str or unicode - :param indent: optional string to use as indentation - - :rtype: str or unicode - :return: - the input text normalized to fit on lines with a maximized size - inferior to `line_len`, and optionally prefixed by an - indentation string - """ - if rest: - normp = normalize_rest_paragraph - else: - normp = normalize_paragraph - result = [] - for text in _BLANKLINES_RGX.split(text): - result.append(normp(text, line_len, indent)) - return ('%s%s%s' % (linesep, indent, linesep)).join(result) - - -def normalize_paragraph(text, line_len=80, indent=''): - """normalize a text to display it with a maximum line size and - optionally arbitrary indentation. Line jumps are normalized. The - indentation string may be used top insert a comment mark for - instance. - - :type text: str or unicode - :param text: the input text to normalize - - :type line_len: int - :param line_len: expected maximum line's length, default to 80 - - :type indent: str or unicode - :param indent: optional string to use as indentation - - :rtype: str or unicode - :return: - the input text normalized to fit on lines with a maximized size - inferior to `line_len`, and optionally prefixed by an - indentation string - """ - text = _NORM_SPACES_RGX.sub(' ', text) - line_len = line_len - len(indent) - lines = [] - while text: - aline, text = splittext(text.strip(), line_len) - lines.append(indent + aline) - return linesep.join(lines) - -def normalize_rest_paragraph(text, line_len=80, indent=''): - """normalize a ReST text to display it with a maximum line size and - optionally arbitrary indentation. Line jumps are normalized. The - indentation string may be used top insert a comment mark for - instance. - - :type text: str or unicode - :param text: the input text to normalize - - :type line_len: int - :param line_len: expected maximum line's length, default to 80 - - :type indent: str or unicode - :param indent: optional string to use as indentation - - :rtype: str or unicode - :return: - the input text normalized to fit on lines with a maximized size - inferior to `line_len`, and optionally prefixed by an - indentation string - """ - toreport = '' - lines = [] - line_len = line_len - len(indent) - for line in text.splitlines(): - line = toreport + _NORM_SPACES_RGX.sub(' ', line.strip()) - toreport = '' - while len(line) > line_len: - # too long line, need split - line, toreport = splittext(line, line_len) - lines.append(indent + line) - if toreport: - line = toreport + ' ' - toreport = '' - else: - line = '' - if line: - lines.append(indent + line.strip()) - return linesep.join(lines) - - -def splittext(text, line_len): - """split the given text on space according to the given max line size - - return a 2-uple: - * a line <= line_len if possible - * the rest of the text which has to be reported on another line - """ - if len(text) <= line_len: - return text, '' - pos = min(len(text)-1, line_len) - while pos > 0 and text[pos] != ' ': - pos -= 1 - if pos == 0: - pos = min(len(text), line_len) - while len(text) > pos and text[pos] != ' ': - pos += 1 - return text[:pos], text[pos+1:].strip() - - -def splitstrip(string, sep=','): - """return a list of stripped string by splitting the string given as - argument on `sep` (',' by default). Empty string are discarded. - - >>> splitstrip('a, b, c , 4,,') - ['a', 'b', 'c', '4'] - >>> splitstrip('a') - ['a'] - >>> - - :type string: str or unicode - :param string: a csv line - - :type sep: str or unicode - :param sep: field separator, default to the comma (',') - - :rtype: str or unicode - :return: the unquoted string (or the input string if it wasn't quoted) - """ - return [word.strip() for word in string.split(sep) if word.strip()] - -get_csv = deprecated('get_csv is deprecated, use splitstrip')(splitstrip) - - -def split_url_or_path(url_or_path): - """return the latest component of a string containing either an url of the - form <scheme>://<path> or a local file system path - """ - if '://' in url_or_path: - return url_or_path.rstrip('/').rsplit('/', 1) - return osp.split(url_or_path.rstrip(osp.sep)) - - -def text_to_dict(text): - """parse multilines text containing simple 'key=value' lines and return a - dict of {'key': 'value'}. When the same key is encountered multiple time, - value is turned into a list containing all values. - - >>> text_to_dict('''multiple=1 - ... multiple= 2 - ... single =3 - ... ''') - {'single': '3', 'multiple': ['1', '2']} - - """ - res = {} - if not text: - return res - for line in text.splitlines(): - line = line.strip() - if line and not line.startswith('#'): - key, value = [w.strip() for w in line.split('=', 1)] - if key in res: - try: - res[key].append(value) - except AttributeError: - res[key] = [res[key], value] - else: - res[key] = value - return res - - -_BLANK_URE = r'(\s|,)+' -_BLANK_RE = re.compile(_BLANK_URE) -__VALUE_URE = r'-?(([0-9]+\.[0-9]*)|((0x?)?[0-9]+))' -__UNITS_URE = r'[a-zA-Z]+' -_VALUE_RE = re.compile(r'(?P<value>%s)(?P<unit>%s)?'%(__VALUE_URE, __UNITS_URE)) -_VALIDATION_RE = re.compile(r'^((%s)(%s))*(%s)?$' % (__VALUE_URE, __UNITS_URE, - __VALUE_URE)) - -BYTE_UNITS = { - "b": 1, - "kb": 1024, - "mb": 1024 ** 2, - "gb": 1024 ** 3, - "tb": 1024 ** 4, -} - -TIME_UNITS = { - "ms": 0.0001, - "s": 1, - "min": 60, - "h": 60 * 60, - "d": 60 * 60 *24, -} - -def apply_units(string, units, inter=None, final=float, blank_reg=_BLANK_RE, - value_reg=_VALUE_RE): - """Parse the string applying the units defined in units - (e.g.: "1.5m",{'m',60} -> 80). - - :type string: str or unicode - :param string: the string to parse - - :type units: dict (or any object with __getitem__ using basestring key) - :param units: a dict mapping a unit string repr to its value - - :type inter: type - :param inter: used to parse every intermediate value (need __sum__) - - :type blank_reg: regexp - :param blank_reg: should match every blank char to ignore. - - :type value_reg: regexp with "value" and optional "unit" group - :param value_reg: match a value and it's unit into the - """ - if inter is None: - inter = final - fstring = _BLANK_RE.sub('', string) - if not (fstring and _VALIDATION_RE.match(fstring)): - raise ValueError("Invalid unit string: %r." % string) - values = [] - for match in value_reg.finditer(fstring): - dic = match.groupdict() - lit, unit = dic["value"], dic.get("unit") - value = inter(lit) - if unit is not None: - try: - value *= units[unit.lower()] - except KeyError: - raise KeyError('invalid unit %s. valid units are %s' % - (unit, units.keys())) - values.append(value) - return final(sum(values)) - - -_LINE_RGX = re.compile('\r\n|\r+|\n') - -def pretty_match(match, string, underline_char='^'): - """return a string with the match location underlined: - - >>> import re - >>> print(pretty_match(re.search('mange', 'il mange du bacon'), 'il mange du bacon')) - il mange du bacon - ^^^^^ - >>> - - :type match: _sre.SRE_match - :param match: object returned by re.match, re.search or re.finditer - - :type string: str or unicode - :param string: - the string on which the regular expression has been applied to - obtain the `match` object - - :type underline_char: str or unicode - :param underline_char: - character to use to underline the matched section, default to the - carret '^' - - :rtype: str or unicode - :return: - the original string with an inserted line to underline the match - location - """ - start = match.start() - end = match.end() - string = _LINE_RGX.sub(linesep, string) - start_line_pos = string.rfind(linesep, 0, start) - if start_line_pos == -1: - start_line_pos = 0 - result = [] - else: - result = [string[:start_line_pos]] - start_line_pos += len(linesep) - offset = start - start_line_pos - underline = ' ' * offset + underline_char * (end - start) - end_line_pos = string.find(linesep, end) - if end_line_pos == -1: - string = string[start_line_pos:] - result.append(string) - result.append(underline) - else: - end = string[end_line_pos + len(linesep):] - string = string[start_line_pos:end_line_pos] - result.append(string) - result.append(underline) - result.append(end) - return linesep.join(result).rstrip() - - -# Ansi colorization ########################################################### - -ANSI_PREFIX = '\033[' -ANSI_END = 'm' -ANSI_RESET = '\033[0m' -ANSI_STYLES = { - 'reset': "0", - 'bold': "1", - 'italic': "3", - 'underline': "4", - 'blink': "5", - 'inverse': "7", - 'strike': "9", -} -ANSI_COLORS = { - 'reset': "0", - 'black': "30", - 'red': "31", - 'green': "32", - 'yellow': "33", - 'blue': "34", - 'magenta': "35", - 'cyan': "36", - 'white': "37", -} - -def _get_ansi_code(color=None, style=None): - """return ansi escape code corresponding to color and style - - :type color: str or None - :param color: - the color name (see `ANSI_COLORS` for available values) - or the color number when 256 colors are available - - :type style: str or None - :param style: - style string (see `ANSI_COLORS` for available values). To get - several style effects at the same time, use a coma as separator. - - :raise KeyError: if an unexistent color or style identifier is given - - :rtype: str - :return: the built escape code - """ - ansi_code = [] - if style: - style_attrs = splitstrip(style) - for effect in style_attrs: - ansi_code.append(ANSI_STYLES[effect]) - if color: - if color.isdigit(): - ansi_code.extend(['38', '5']) - ansi_code.append(color) - else: - ansi_code.append(ANSI_COLORS[color]) - if ansi_code: - return ANSI_PREFIX + ';'.join(ansi_code) + ANSI_END - return '' - -def colorize_ansi(msg, color=None, style=None): - """colorize message by wrapping it with ansi escape codes - - :type msg: str or unicode - :param msg: the message string to colorize - - :type color: str or None - :param color: - the color identifier (see `ANSI_COLORS` for available values) - - :type style: str or None - :param style: - style string (see `ANSI_COLORS` for available values). To get - several style effects at the same time, use a coma as separator. - - :raise KeyError: if an unexistent color or style identifier is given - - :rtype: str or unicode - :return: the ansi escaped string - """ - # If both color and style are not defined, then leave the text as is - if color is None and style is None: - return msg - escape_code = _get_ansi_code(color, style) - # If invalid (or unknown) color, don't wrap msg with ansi codes - if escape_code: - return '%s%s%s' % (escape_code, msg, ANSI_RESET) - return msg - -DIFF_STYLE = {'separator': 'cyan', 'remove': 'red', 'add': 'green'} - -def diff_colorize_ansi(lines, out=sys.stdout, style=DIFF_STYLE): - for line in lines: - if line[:4] in ('--- ', '+++ '): - out.write(colorize_ansi(line, style['separator'])) - elif line[0] == '-': - out.write(colorize_ansi(line, style['remove'])) - elif line[0] == '+': - out.write(colorize_ansi(line, style['add'])) - elif line[:4] == '--- ': - out.write(colorize_ansi(line, style['separator'])) - elif line[:4] == '+++ ': - out.write(colorize_ansi(line, style['separator'])) - else: - out.write(line) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/tree.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/tree.py @@ -1,369 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Base class to represent a tree structure. - - - - -""" -__docformat__ = "restructuredtext en" - -import sys - -from . import flatten -from .visitor import VisitedMixIn, FilteredIterator, no_filter - -## Exceptions ################################################################# - -class NodeNotFound(Exception): - """raised when a node has not been found""" - -EX_SIBLING_NOT_FOUND = "No such sibling as '%s'" -EX_CHILD_NOT_FOUND = "No such child as '%s'" -EX_NODE_NOT_FOUND = "No such node as '%s'" - - -# Base node ################################################################### - -class Node(object): - """a basic tree node, characterized by an id""" - - def __init__(self, nid=None) : - self.id = nid - # navigation - self.parent = None - self.children = [] - - def __iter__(self): - return iter(self.children) - - def __str__(self, indent=0): - s = ['%s%s %s' % (' '*indent, self.__class__.__name__, self.id)] - indent += 2 - for child in self.children: - try: - s.append(child.__str__(indent)) - except TypeError: - s.append(child.__str__()) - return '\n'.join(s) - - def is_leaf(self): - return not self.children - - def append(self, child): - """add a node to children""" - self.children.append(child) - child.parent = self - - def remove(self, child): - """remove a child node""" - self.children.remove(child) - child.parent = None - - def insert(self, index, child): - """insert a child node""" - self.children.insert(index, child) - child.parent = self - - def replace(self, old_child, new_child): - """replace a child node with another""" - i = self.children.index(old_child) - self.children.pop(i) - self.children.insert(i, new_child) - new_child.parent = self - - def get_sibling(self, nid): - """return the sibling node that has given id""" - try: - return self.parent.get_child_by_id(nid) - except NodeNotFound : - raise NodeNotFound(EX_SIBLING_NOT_FOUND % nid) - - def next_sibling(self): - """ - return the next sibling for this node if any - """ - parent = self.parent - if parent is None: - # root node has no sibling - return None - index = parent.children.index(self) - try: - return parent.children[index+1] - except IndexError: - return None - - def previous_sibling(self): - """ - return the previous sibling for this node if any - """ - parent = self.parent - if parent is None: - # root node has no sibling - return None - index = parent.children.index(self) - if index > 0: - return parent.children[index-1] - return None - - def get_node_by_id(self, nid): - """ - return node in whole hierarchy that has given id - """ - root = self.root() - try: - return root.get_child_by_id(nid, 1) - except NodeNotFound : - raise NodeNotFound(EX_NODE_NOT_FOUND % nid) - - def get_child_by_id(self, nid, recurse=None): - """ - return child of given id - """ - if self.id == nid: - return self - for c in self.children : - if recurse: - try: - return c.get_child_by_id(nid, 1) - except NodeNotFound : - continue - if c.id == nid : - return c - raise NodeNotFound(EX_CHILD_NOT_FOUND % nid) - - def get_child_by_path(self, path): - """ - return child of given path (path is a list of ids) - """ - if len(path) > 0 and path[0] == self.id: - if len(path) == 1 : - return self - else : - for c in self.children : - try: - return c.get_child_by_path(path[1:]) - except NodeNotFound : - pass - raise NodeNotFound(EX_CHILD_NOT_FOUND % path) - - def depth(self): - """ - return depth of this node in the tree - """ - if self.parent is not None: - return 1 + self.parent.depth() - else : - return 0 - - def depth_down(self): - """ - return depth of the tree from this node - """ - if self.children: - return 1 + max([c.depth_down() for c in self.children]) - return 1 - - def width(self): - """ - return the width of the tree from this node - """ - return len(self.leaves()) - - def root(self): - """ - return the root node of the tree - """ - if self.parent is not None: - return self.parent.root() - return self - - def leaves(self): - """ - return a list with all the leaves nodes descendant from this node - """ - leaves = [] - if self.children: - for child in self.children: - leaves += child.leaves() - return leaves - else: - return [self] - - def flatten(self, _list=None): - """ - return a list with all the nodes descendant from this node - """ - if _list is None: - _list = [] - _list.append(self) - for c in self.children: - c.flatten(_list) - return _list - - def lineage(self): - """ - return list of parents up to root node - """ - lst = [self] - if self.parent is not None: - lst.extend(self.parent.lineage()) - return lst - -class VNode(Node, VisitedMixIn): - """a visitable node - """ - pass - - -class BinaryNode(VNode): - """a binary node (i.e. only two children - """ - def __init__(self, lhs=None, rhs=None) : - VNode.__init__(self) - if lhs is not None or rhs is not None: - assert lhs and rhs - self.append(lhs) - self.append(rhs) - - def remove(self, child): - """remove the child and replace this node with the other child - """ - self.children.remove(child) - self.parent.replace(self, self.children[0]) - - def get_parts(self): - """ - return the left hand side and the right hand side of this node - """ - return self.children[0], self.children[1] - - - -if sys.version_info[0:2] >= (2, 2): - list_class = list -else: - from UserList import UserList - list_class = UserList - -class ListNode(VNode, list_class): - """Used to manipulate Nodes as Lists - """ - def __init__(self): - list_class.__init__(self) - VNode.__init__(self) - self.children = self - - def __str__(self, indent=0): - return '%s%s %s' % (indent*' ', self.__class__.__name__, - ', '.join([str(v) for v in self])) - - def append(self, child): - """add a node to children""" - list_class.append(self, child) - child.parent = self - - def insert(self, index, child): - """add a node to children""" - list_class.insert(self, index, child) - child.parent = self - - def remove(self, child): - """add a node to children""" - list_class.remove(self, child) - child.parent = None - - def pop(self, index): - """add a node to children""" - child = list_class.pop(self, index) - child.parent = None - - def __iter__(self): - return list_class.__iter__(self) - -# construct list from tree #################################################### - -def post_order_list(node, filter_func=no_filter): - """ - create a list with tree nodes for which the <filter> function returned true - in a post order fashion - """ - l, stack = [], [] - poped, index = 0, 0 - while node: - if filter_func(node): - if node.children and not poped: - stack.append((node, index)) - index = 0 - node = node.children[0] - else: - l.append(node) - index += 1 - try: - node = stack[-1][0].children[index] - except IndexError: - node = None - else: - node = None - poped = 0 - if node is None and stack: - node, index = stack.pop() - poped = 1 - return l - -def pre_order_list(node, filter_func=no_filter): - """ - create a list with tree nodes for which the <filter> function returned true - in a pre order fashion - """ - l, stack = [], [] - poped, index = 0, 0 - while node: - if filter_func(node): - if not poped: - l.append(node) - if node.children and not poped: - stack.append((node, index)) - index = 0 - node = node.children[0] - else: - index += 1 - try: - node = stack[-1][0].children[index] - except IndexError: - node = None - else: - node = None - poped = 0 - if node is None and len(stack) > 1: - node, index = stack.pop() - poped = 1 - return l - -class PostfixedDepthFirstIterator(FilteredIterator): - """a postfixed depth first iterator, designed to be used with visitors - """ - def __init__(self, node, filter_func=None): - FilteredIterator.__init__(self, node, post_order_list, filter_func) - -class PrefixedDepthFirstIterator(FilteredIterator): - """a prefixed depth first iterator, designed to be used with visitors - """ - def __init__(self, node, filter_func=None): - FilteredIterator.__init__(self, node, pre_order_list, filter_func) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/__init__.py @@ -1,174 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Universal report objects and some formatting drivers. - -A way to create simple reports using python objects, primarily designed to be -formatted as text and html. -""" -from __future__ import generators -__docformat__ = "restructuredtext en" - -import sys -from cStringIO import StringIO -from StringIO import StringIO as UStringIO - -from ..textutils import linesep - - -def get_nodes(node, klass): - """return an iterator on all children node of the given klass""" - for child in node.children: - if isinstance(child, klass): - yield child - # recurse (FIXME: recursion controled by an option) - for grandchild in get_nodes(child, klass): - yield grandchild - -def layout_title(layout): - """try to return the layout's title as string, return None if not found - """ - for child in layout.children: - if isinstance(child, Title): - return ' '.join([node.data for node in get_nodes(child, Text)]) - -def build_summary(layout, level=1): - """make a summary for the report, including X level""" - assert level > 0 - level -= 1 - summary = List(klass='summary') - for child in layout.children: - if not isinstance(child, Section): - continue - label = layout_title(child) - if not label and not child.id: - continue - if not child.id: - child.id = label.replace(' ', '-') - node = Link('#'+child.id, label=label or child.id) - # FIXME: Three following lines produce not very compliant - # docbook: there are some useless <para><para>. They might be - # replaced by the three commented lines but this then produces - # a bug in html display... - if level and [n for n in child.children if isinstance(n, Section)]: - node = Paragraph([node, build_summary(child, level)]) - summary.append(node) -# summary.append(node) -# if level and [n for n in child.children if isinstance(n, Section)]: -# summary.append(build_summary(child, level)) - return summary - - -class BaseWriter(object): - """base class for ureport writers""" - - def format(self, layout, stream=None, encoding=None): - """format and write the given layout into the stream object - - unicode policy: unicode strings may be found in the layout; - try to call stream.write with it, but give it back encoded using - the given encoding if it fails - """ - if stream is None: - stream = sys.stdout - if not encoding: - encoding = getattr(stream, 'encoding', 'UTF-8') - self.encoding = encoding or 'UTF-8' - self.__compute_funcs = [] - self.out = stream - self.begin_format(layout) - layout.accept(self) - self.end_format(layout) - - def format_children(self, layout): - """recurse on the layout children and call their accept method - (see the Visitor pattern) - """ - for child in getattr(layout, 'children', ()): - child.accept(self) - - def writeln(self, string=''): - """write a line in the output buffer""" - self.write(string + linesep) - - def write(self, string): - """write a string in the output buffer""" - try: - self.out.write(string) - except UnicodeEncodeError: - self.out.write(string.encode(self.encoding)) - - def begin_format(self, layout): - """begin to format a layout""" - self.section = 0 - - def end_format(self, layout): - """finished to format a layout""" - - def get_table_content(self, table): - """trick to get table content without actually writing it - - return an aligned list of lists containing table cells values as string - """ - result = [[]] - cols = table.cols - for cell in self.compute_content(table): - if cols == 0: - result.append([]) - cols = table.cols - cols -= 1 - result[-1].append(cell) - # fill missing cells - while len(result[-1]) < cols: - result[-1].append('') - return result - - def compute_content(self, layout): - """trick to compute the formatting of children layout before actually - writing it - - return an iterator on strings (one for each child element) - """ - # use cells ! - def write(data): - try: - stream.write(data) - except UnicodeEncodeError: - stream.write(data.encode(self.encoding)) - def writeln(data=''): - try: - stream.write(data+linesep) - except UnicodeEncodeError: - stream.write(data.encode(self.encoding)+linesep) - self.write = write - self.writeln = writeln - self.__compute_funcs.append((write, writeln)) - for child in layout.children: - stream = UStringIO() - child.accept(self) - yield stream.getvalue() - self.__compute_funcs.pop() - try: - self.write, self.writeln = self.__compute_funcs[-1] - except IndexError: - del self.write - del self.writeln - - -from .nodes import * -from .text_writer import TextWriter -from .html_writer import HTMLWriter diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/docbook_writer.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/docbook_writer.py @@ -1,139 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""HTML formatting drivers for ureports""" -from __future__ import generators -__docformat__ = "restructuredtext en" - -from ..ureports import HTMLWriter - -class DocbookWriter(HTMLWriter): - """format layouts as HTML""" - - def begin_format(self, layout): - """begin to format a layout""" - super(HTMLWriter, self).begin_format(layout) - if self.snippet is None: - self.writeln('<?xml version="1.0" encoding="ISO-8859-1"?>') - self.writeln(""" -<book xmlns:xi='http://www.w3.org/2001/XInclude' - lang='fr'> -""") - - def end_format(self, layout): - """finished to format a layout""" - if self.snippet is None: - self.writeln('</book>') - - def visit_section(self, layout): - """display a section (using <chapter> (level 0) or <section>)""" - if self.section == 0: - tag = "chapter" - else: - tag = "section" - self.section += 1 - self.writeln(self._indent('<%s%s>' % (tag, self.handle_attrs(layout)))) - self.format_children(layout) - self.writeln(self._indent('</%s>'% tag)) - self.section -= 1 - - def visit_title(self, layout): - """display a title using <title>""" - self.write(self._indent(' <title%s>' % self.handle_attrs(layout))) - self.format_children(layout) - self.writeln('</title>') - - def visit_table(self, layout): - """display a table as html""" - self.writeln(self._indent(' <table%s><title>%s</title>' \ - % (self.handle_attrs(layout), layout.title))) - self.writeln(self._indent(' <tgroup cols="%s">'% layout.cols)) - for i in range(layout.cols): - self.writeln(self._indent(' <colspec colname="c%s" colwidth="1*"/>' % i)) - - table_content = self.get_table_content(layout) - # write headers - if layout.cheaders: - self.writeln(self._indent(' <thead>')) - self._write_row(table_content[0]) - self.writeln(self._indent(' </thead>')) - table_content = table_content[1:] - elif layout.rcheaders: - self.writeln(self._indent(' <thead>')) - self._write_row(table_content[-1]) - self.writeln(self._indent(' </thead>')) - table_content = table_content[:-1] - # write body - self.writeln(self._indent(' <tbody>')) - for i in range(len(table_content)): - row = table_content[i] - self.writeln(self._indent(' <row>')) - for j in range(len(row)): - cell = row[j] or '&#160;' - self.writeln(self._indent(' <entry>%s</entry>' % cell)) - self.writeln(self._indent(' </row>')) - self.writeln(self._indent(' </tbody>')) - self.writeln(self._indent(' </tgroup>')) - self.writeln(self._indent(' </table>')) - - def _write_row(self, row): - """write content of row (using <row> <entry>)""" - self.writeln(' <row>') - for j in range(len(row)): - cell = row[j] or '&#160;' - self.writeln(' <entry>%s</entry>' % cell) - self.writeln(self._indent(' </row>')) - - def visit_list(self, layout): - """display a list (using <itemizedlist>)""" - self.writeln(self._indent(' <itemizedlist%s>' % self.handle_attrs(layout))) - for row in list(self.compute_content(layout)): - self.writeln(' <listitem><para>%s</para></listitem>' % row) - self.writeln(self._indent(' </itemizedlist>')) - - def visit_paragraph(self, layout): - """display links (using <para>)""" - self.write(self._indent(' <para>')) - self.format_children(layout) - self.writeln('</para>') - - def visit_span(self, layout): - """display links (using <p>)""" - #TODO: translate in docbook - self.write('<literal %s>' % self.handle_attrs(layout)) - self.format_children(layout) - self.write('</literal>') - - def visit_link(self, layout): - """display links (using <ulink>)""" - self.write('<ulink url="%s"%s>%s</ulink>' % (layout.url, - self.handle_attrs(layout), - layout.label)) - - def visit_verbatimtext(self, layout): - """display verbatim text (using <programlisting>)""" - self.writeln(self._indent(' <programlisting>')) - self.write(layout.data.replace('&', '&amp;').replace('<', '&lt;')) - self.writeln(self._indent(' </programlisting>')) - - def visit_text(self, layout): - """add some text""" - self.write(layout.data.replace('&', '&amp;').replace('<', '&lt;')) - - def _indent(self, string): - """correctly indent string according to section""" - return ' ' * 2*(self.section) + string diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/html_writer.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/html_writer.py @@ -1,131 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""HTML formatting drivers for ureports""" -__docformat__ = "restructuredtext en" - -from cgi import escape - -from ..ureports import BaseWriter - - -class HTMLWriter(BaseWriter): - """format layouts as HTML""" - - def __init__(self, snippet=None): - super(HTMLWriter, self).__init__() - self.snippet = snippet - - def handle_attrs(self, layout): - """get an attribute string from layout member attributes""" - attrs = '' - klass = getattr(layout, 'klass', None) - if klass: - attrs += ' class="%s"' % klass - nid = getattr(layout, 'id', None) - if nid: - attrs += ' id="%s"' % nid - return attrs - - def begin_format(self, layout): - """begin to format a layout""" - super(HTMLWriter, self).begin_format(layout) - if self.snippet is None: - self.writeln('<html>') - self.writeln('<body>') - - def end_format(self, layout): - """finished to format a layout""" - if self.snippet is None: - self.writeln('</body>') - self.writeln('</html>') - - - def visit_section(self, layout): - """display a section as html, using div + h[section level]""" - self.section += 1 - self.writeln('<div%s>' % self.handle_attrs(layout)) - self.format_children(layout) - self.writeln('</div>') - self.section -= 1 - - def visit_title(self, layout): - """display a title using <hX>""" - self.write('<h%s%s>' % (self.section, self.handle_attrs(layout))) - self.format_children(layout) - self.writeln('</h%s>' % self.section) - - def visit_table(self, layout): - """display a table as html""" - self.writeln('<table%s>' % self.handle_attrs(layout)) - table_content = self.get_table_content(layout) - for i in range(len(table_content)): - row = table_content[i] - if i == 0 and layout.rheaders: - self.writeln('<tr class="header">') - elif i+1 == len(table_content) and layout.rrheaders: - self.writeln('<tr class="header">') - else: - self.writeln('<tr class="%s">' % (i%2 and 'even' or 'odd')) - for j in range(len(row)): - cell = row[j] or '&#160;' - if (layout.rheaders and i == 0) or \ - (layout.cheaders and j == 0) or \ - (layout.rrheaders and i+1 == len(table_content)) or \ - (layout.rcheaders and j+1 == len(row)): - self.writeln('<th>%s</th>' % cell) - else: - self.writeln('<td>%s</td>' % cell) - self.writeln('</tr>') - self.writeln('</table>') - - def visit_list(self, layout): - """display a list as html""" - self.writeln('<ul%s>' % self.handle_attrs(layout)) - for row in list(self.compute_content(layout)): - self.writeln('<li>%s</li>' % row) - self.writeln('</ul>') - - def visit_paragraph(self, layout): - """display links (using <p>)""" - self.write('<p>') - self.format_children(layout) - self.write('</p>') - - def visit_span(self, layout): - """display links (using <p>)""" - self.write('<span%s>' % self.handle_attrs(layout)) - self.format_children(layout) - self.write('</span>') - - def visit_link(self, layout): - """display links (using <a>)""" - self.write(' <a href="%s"%s>%s</a>' % (layout.url, - self.handle_attrs(layout), - layout.label)) - def visit_verbatimtext(self, layout): - """display verbatim text (using <pre>)""" - self.write('<pre>') - self.write(layout.data.replace('&', '&amp;').replace('<', '&lt;')) - self.write('</pre>') - - def visit_text(self, layout): - """add some text""" - data = layout.data - if layout.escaped: - data = data.replace('&', '&amp;').replace('<', '&lt;') - self.write(data) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/nodes.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/nodes.py @@ -1,201 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Micro reports objects. - -A micro report is a tree of layout and content objects. -""" -__docformat__ = "restructuredtext en" - -from ..tree import VNode - -class BaseComponent(VNode): - """base report component - - attributes - * id : the component's optional id - * klass : the component's optional klass - """ - def __init__(self, id=None, klass=None): - VNode.__init__(self, id) - self.klass = klass - -class BaseLayout(BaseComponent): - """base container node - - attributes - * BaseComponent attributes - * children : components in this table (i.e. the table's cells) - """ - def __init__(self, children=(), **kwargs): - super(BaseLayout, self).__init__(**kwargs) - for child in children: - if isinstance(child, BaseComponent): - self.append(child) - else: - self.add_text(child) - - def append(self, child): - """overridden to detect problems easily""" - assert child not in self.parents() - VNode.append(self, child) - - def parents(self): - """return the ancestor nodes""" - assert self.parent is not self - if self.parent is None: - return [] - return [self.parent] + self.parent.parents() - - def add_text(self, text): - """shortcut to add text data""" - self.children.append(Text(text)) - - -# non container nodes ######################################################### - -class Text(BaseComponent): - """a text portion - - attributes : - * BaseComponent attributes - * data : the text value as an encoded or unicode string - """ - def __init__(self, data, escaped=True, **kwargs): - super(Text, self).__init__(**kwargs) - #if isinstance(data, unicode): - # data = data.encode('ascii') - assert isinstance(data, (str, unicode)), data.__class__ - self.escaped = escaped - self.data = data - -class VerbatimText(Text): - """a verbatim text, display the raw data - - attributes : - * BaseComponent attributes - * data : the text value as an encoded or unicode string - """ - -class Link(BaseComponent): - """a labelled link - - attributes : - * BaseComponent attributes - * url : the link's target (REQUIRED) - * label : the link's label as a string (use the url by default) - """ - def __init__(self, url, label=None, **kwargs): - super(Link, self).__init__(**kwargs) - assert url - self.url = url - self.label = label or url - - -class Image(BaseComponent): - """an embedded or a single image - - attributes : - * BaseComponent attributes - * filename : the image's filename (REQUIRED) - * stream : the stream object containing the image data (REQUIRED) - * title : the image's optional title - """ - def __init__(self, filename, stream, title=None, **kwargs): - super(Image, self).__init__(**kwargs) - assert filename - assert stream - self.filename = filename - self.stream = stream - self.title = title - - -# container nodes ############################################################# - -class Section(BaseLayout): - """a section - - attributes : - * BaseLayout attributes - - a title may also be given to the constructor, it'll be added - as a first element - a description may also be given to the constructor, it'll be added - as a first paragraph - """ - def __init__(self, title=None, description=None, **kwargs): - super(Section, self).__init__(**kwargs) - if description: - self.insert(0, Paragraph([Text(description)])) - if title: - self.insert(0, Title(children=(title,))) - -class Title(BaseLayout): - """a title - - attributes : - * BaseLayout attributes - - A title must not contains a section nor a paragraph! - """ - -class Span(BaseLayout): - """a title - - attributes : - * BaseLayout attributes - - A span should only contains Text and Link nodes (in-line elements) - """ - -class Paragraph(BaseLayout): - """a simple text paragraph - - attributes : - * BaseLayout attributes - - A paragraph must not contains a section ! - """ - -class Table(BaseLayout): - """some tabular data - - attributes : - * BaseLayout attributes - * cols : the number of columns of the table (REQUIRED) - * rheaders : the first row's elements are table's header - * cheaders : the first col's elements are table's header - * title : the table's optional title - """ - def __init__(self, cols, title=None, - rheaders=0, cheaders=0, rrheaders=0, rcheaders=0, - **kwargs): - super(Table, self).__init__(**kwargs) - assert isinstance(cols, int) - self.cols = cols - self.title = title - self.rheaders = rheaders - self.cheaders = cheaders - self.rrheaders = rrheaders - self.rcheaders = rcheaders - -class List(BaseLayout): - """some list data - - attributes : - * BaseLayout attributes - """ diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/text_writer.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/ureports/text_writer.py @@ -1,140 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""Text formatting drivers for ureports""" -__docformat__ = "restructuredtext en" - -from ..textutils import linesep -from ..ureports import BaseWriter - - -TITLE_UNDERLINES = ['', '=', '-', '`', '.', '~', '^'] -BULLETS = ['*', '-'] - -class TextWriter(BaseWriter): - """format layouts as text - (ReStructured inspiration but not totally handled yet) - """ - def begin_format(self, layout): - super(TextWriter, self).begin_format(layout) - self.list_level = 0 - self.pending_urls = [] - - def visit_section(self, layout): - """display a section as text - """ - self.section += 1 - self.writeln() - self.format_children(layout) - if self.pending_urls: - self.writeln() - for label, url in self.pending_urls: - self.writeln('.. _`%s`: %s' % (label, url)) - self.pending_urls = [] - self.section -= 1 - self.writeln() - - def visit_title(self, layout): - title = ''.join(list(self.compute_content(layout))) - self.writeln(title) - try: - self.writeln(TITLE_UNDERLINES[self.section] * len(title)) - except IndexError: - print "FIXME TITLE TOO DEEP. TURNING TITLE INTO TEXT" - - def visit_paragraph(self, layout): - """enter a paragraph""" - self.format_children(layout) - self.writeln() - - def visit_span(self, layout): - """enter a span""" - self.format_children(layout) - - def visit_table(self, layout): - """display a table as text""" - table_content = self.get_table_content(layout) - # get columns width - cols_width = [0]*len(table_content[0]) - for row in table_content: - for index in range(len(row)): - col = row[index] - cols_width[index] = max(cols_width[index], len(col)) - if layout.klass == 'field': - self.field_table(layout, table_content, cols_width) - else: - self.default_table(layout, table_content, cols_width) - self.writeln() - - def default_table(self, layout, table_content, cols_width): - """format a table""" - cols_width = [size+1 for size in cols_width] - format_strings = ' '.join(['%%-%ss'] * len(cols_width)) - format_strings = format_strings % tuple(cols_width) - format_strings = format_strings.split(' ') - table_linesep = '\n+' + '+'.join(['-'*w for w in cols_width]) + '+\n' - headsep = '\n+' + '+'.join(['='*w for w in cols_width]) + '+\n' - # FIXME: layout.cheaders - self.write(table_linesep) - for i in range(len(table_content)): - self.write('|') - line = table_content[i] - for j in range(len(line)): - self.write(format_strings[j] % line[j]) - self.write('|') - if i == 0 and layout.rheaders: - self.write(headsep) - else: - self.write(table_linesep) - - def field_table(self, layout, table_content, cols_width): - """special case for field table""" - assert layout.cols == 2 - format_string = '%s%%-%ss: %%s' % (linesep, cols_width[0]) - for field, value in table_content: - self.write(format_string % (field, value)) - - - def visit_list(self, layout): - """display a list layout as text""" - bullet = BULLETS[self.list_level % len(BULLETS)] - indent = ' ' * self.list_level - self.list_level += 1 - for child in layout.children: - self.write('%s%s%s ' % (linesep, indent, bullet)) - child.accept(self) - self.list_level -= 1 - - def visit_link(self, layout): - """add a hyperlink""" - if layout.label != layout.url: - self.write('`%s`_' % layout.label) - self.pending_urls.append( (layout.label, layout.url) ) - else: - self.write(layout.url) - - def visit_verbatimtext(self, layout): - """display a verbatim layout as text (so difficult ;) - """ - self.writeln('::\n') - for line in layout.data.splitlines(): - self.writeln(' ' + line) - self.writeln() - - def visit_text(self, layout): - """add some text""" - self.write(layout.data) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/visitor.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/logilab/common/visitor.py @@ -1,107 +0,0 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of logilab-common. -# -# logilab-common is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# logilab-common is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-common. If not, see <http://www.gnu.org/licenses/>. -"""A generic visitor abstract implementation. - - - - -""" -__docformat__ = "restructuredtext en" - -def no_filter(_): - return 1 - -# Iterators ################################################################### -class FilteredIterator(object): - - def __init__(self, node, list_func, filter_func=None): - self._next = [(node, 0)] - if filter_func is None: - filter_func = no_filter - self._list = list_func(node, filter_func) - - def next(self): - try: - return self._list.pop(0) - except : - return None - -# Base Visitor ################################################################ -class Visitor(object): - - def __init__(self, iterator_class, filter_func=None): - self._iter_class = iterator_class - self.filter = filter_func - - def visit(self, node, *args, **kargs): - """ - launch the visit on a given node - - call 'open_visit' before the beginning of the visit, with extra args - given - when all nodes have been visited, call the 'close_visit' method - """ - self.open_visit(node, *args, **kargs) - return self.close_visit(self._visit(node)) - - def _visit(self, node): - iterator = self._get_iterator(node) - n = iterator.next() - while n: - result = n.accept(self) - n = iterator.next() - return result - - def _get_iterator(self, node): - return self._iter_class(node, self.filter) - - def open_visit(self, *args, **kargs): - """ - method called at the beginning of the visit - """ - pass - - def close_visit(self, result): - """ - method called at the end of the visit - """ - return result - -# standard visited mixin ###################################################### -class VisitedMixIn(object): - """ - Visited interface allow node visitors to use the node - """ - def get_visit_name(self): - """ - return the visit name for the mixed class. When calling 'accept', the - method <'visit_' + name returned by this method> will be called on the - visitor - """ - try: - return self.TYPE.replace('-', '_') - except: - return self.__class__.__name__.lower() - - def accept(self, visitor, *args, **kwargs): - func = getattr(visitor, 'visit_%s' % self.get_visit_name()) - return func(self, *args, **kwargs) - - def leave(self, visitor, *args, **kwargs): - func = getattr(visitor, 'leave_%s' % self.get_visit_name()) - return func(self, *args, **kwargs) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/__init__.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/__init__.py @@ -1,113 +0,0 @@ -# Copyright (c) 2003-2010 Sylvain Thenault (thenault@gmail.com). -# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE). -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""utilities methods and classes for reporters""" - -import sys, locale - -CMPS = ['=', '-', '+'] - -# py3k has no more cmp builtin -if sys.version_info >= (3, 0): - def cmp(a, b): - return (a > b) - (a < b) - -def diff_string(old, new): - """given a old and new int value, return a string representing the - difference - """ - diff = abs(old - new) - diff_str = "%s%s" % (CMPS[cmp(old, new)], diff and ('%.2f' % diff) or '') - return diff_str - - -class EmptyReport(Exception): - """raised when a report is empty and so should not be displayed""" - -class BaseReporter: - """base class for reporters - - symbols: show short symbolic names for messages. - """ - - extension = '' - - def __init__(self, output=None): - self.linter = None - self.include_ids = None - self.symbols = None - self.section = 0 - self.out = None - self.out_encoding = None - self.set_output(output) - - def make_sigle(self, msg_id): - """generate a short prefix for a message. - - The sigle can include the id, the symbol, or both, or it can just be - the message class. - """ - if self.include_ids: - sigle = msg_id - else: - sigle = msg_id[0] - if self.symbols: - symbol = self.linter.check_message_id(msg_id).symbol - if symbol: - sigle += '(%s)' % symbol - return sigle - - def set_output(self, output=None): - """set output stream""" - self.out = output or sys.stdout - # py3k streams handle their encoding : - if sys.version_info >= (3, 0): - self.encode = lambda x: x - return - - def encode(string): - if not isinstance(string, unicode): - return string - encoding = (getattr(self.out, 'encoding', None) or - locale.getdefaultlocale()[1] or - sys.getdefaultencoding()) - return string.encode(encoding) - self.encode = encode - - def writeln(self, string=''): - """write a line in the output buffer""" - print >> self.out, self.encode(string) - - def display_results(self, layout): - """display results encapsulated in the layout tree""" - self.section = 0 - if self.include_ids and hasattr(layout, 'report_id'): - layout.children[0].children[0].data += ' (%s)' % layout.report_id - self._display(layout) - - def _display(self, layout): - """display the layout""" - raise NotImplementedError() - - # Event callbacks - - def on_set_current_module(self, module, filepath): - """starting analyzis of a module""" - pass - - def on_close(self, stats, previous_stats): - """global end of analyzis""" - pass - - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/guireporter.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/guireporter.py @@ -1,32 +0,0 @@ -""" reporter used by gui.py """ - -import sys - -from ..interfaces import IReporter -from . import BaseReporter -from ..logilab.common.ureports import TextWriter - - -class GUIReporter(BaseReporter): - """saves messages""" - - __implements__ = IReporter - extension = '' - - def __init__(self, gui, output=sys.stdout): - """init""" - BaseReporter.__init__(self, output) - self.msgs = [] - self.gui = gui - - def add_message(self, msg_id, location, msg): - """manage message of different type and in the context of path""" - module, obj, line, col_offset = location[1:] - sigle = self.make_sigle(msg_id) - full_msg = [sigle, module, obj, str(line), msg] - self.msgs += [[sigle, module, obj, str(line)]] - self.gui.msg_queue.put(full_msg) - - def _display(self, layout): - """launch layouts display""" - TextWriter().format(layout, self.out) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/html.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/html.py @@ -1,66 +0,0 @@ -# Copyright (c) 2003-2006 Sylvain Thenault (thenault@gmail.com). -# Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE). -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""HTML reporter""" - -import sys -from cgi import escape - -from ..logilab.common.ureports import HTMLWriter, Section, Table - -from ..interfaces import IReporter -from . import BaseReporter - - -class HTMLReporter(BaseReporter): - """report messages and layouts in HTML""" - - __implements__ = IReporter - extension = 'html' - - def __init__(self, output=sys.stdout): - BaseReporter.__init__(self, output) - self.msgs = [] - - def add_message(self, msg_id, location, msg): - """manage message of different type and in the context of path""" - module, obj, line, col_offset = location[1:] - sigle = self.make_sigle(msg_id) - self.msgs += [sigle, module, obj, str(line), str(col_offset), escape(msg)] - - def set_output(self, output=None): - """set output stream - - messages buffered for old output is processed first""" - if self.out and self.msgs: - self._display(Section()) - BaseReporter.set_output(self, output) - - def _display(self, layout): - """launch layouts display - - overridden from BaseReporter to add insert the messages section - (in add_message, message is not displayed, just collected so it - can be displayed in an html table) - """ - if self.msgs: - # add stored messages to the layout - msgs = ['type', 'module', 'object', 'line', 'col_offset', 'message'] - msgs += self.msgs - sect = Section('Messages') - layout.append(sect) - sect.append(Table(cols=6, children=msgs, rheaders=1)) - self.msgs = [] - HTMLWriter().format(layout, self.out) - diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/text.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/reporters/text.py @@ -1,147 +0,0 @@ -# Copyright (c) 2003-2007 Sylvain Thenault (thenault@gmail.com). -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Plain text reporters: - -:text: the default one grouping messages by module -:parseable: - standard parseable output with full module path on each message (for - editor integration) -:colorized: an ANSI colorized text reporter - -""" - -import os -import sys - -from ..logilab.common.ureports import TextWriter -from ..logilab.common.textutils import colorize_ansi - -from ..interfaces import IReporter -from . import BaseReporter - -TITLE_UNDERLINES = ['', '=', '-', '.'] - - -class TextReporter(BaseReporter): - """reports messages and layouts in plain text - """ - - __implements__ = IReporter - extension = 'txt' - - def __init__(self, output=None): - BaseReporter.__init__(self, output) - self._modules = {} - - def add_message(self, msg_id, location, msg): - """manage message of different type and in the context of path""" - module, obj, line, col_offset = location[1:] - if module not in self._modules: - if module: - self.writeln('************* Module %s' % module) - self._modules[module] = 1 - else: - self.writeln('************* %s' % module) - if obj: - obj = ':%s' % obj - sigle = self.make_sigle(msg_id) - self.writeln('%s:%3s,%s%s: %s' % (sigle, line, col_offset, obj, msg)) - - def _display(self, layout): - """launch layouts display""" - print >> self.out - TextWriter().format(layout, self.out) - - -class ParseableTextReporter(TextReporter): - """a reporter very similar to TextReporter, but display messages in a form - recognized by most text editors : - - <filename>:<linenum>:<msg> - """ - line_format = '%(path)s:%(line)s: [%(sigle)s%(obj)s] %(msg)s' - - def __init__(self, output=None, relative=True): - TextReporter.__init__(self, output) - if relative: - self._prefix = os.getcwd() + os.sep - else: - self._prefix = '' - - def add_message(self, msg_id, location, msg): - """manage message of different type and in the context of path""" - path, _, obj, line, _ = location - if obj: - obj = ', %s' % obj - sigle = self.make_sigle(msg_id) - if self._prefix: - path = path.replace(self._prefix, '') - self.writeln(self.line_format % locals()) - - -class VSTextReporter(ParseableTextReporter): - """Visual studio text reporter""" - line_format = '%(path)s(%(line)s): [%(sigle)s%(obj)s] %(msg)s' - -class ColorizedTextReporter(TextReporter): - """Simple TextReporter that colorizes text output""" - - COLOR_MAPPING = { - "I" : ("green", None), - 'C' : (None, "bold"), - 'R' : ("magenta", "bold, italic"), - 'W' : ("blue", None), - 'E' : ("red", "bold"), - 'F' : ("red", "bold, underline"), - 'S' : ("yellow", "inverse"), # S stands for module Separator - } - - def __init__(self, output=None, color_mapping=None): - TextReporter.__init__(self, output) - self.color_mapping = color_mapping or \ - dict(ColorizedTextReporter.COLOR_MAPPING) - - - def _get_decoration(self, msg_id): - """Returns the tuple color, style associated with msg_id as defined - in self.color_mapping - """ - try: - return self.color_mapping[msg_id[0]] - except KeyError: - return None, None - - def add_message(self, msg_id, location, msg): - """manage message of different types, and colorize output - using ansi escape codes - """ - module, obj, line, _ = location[1:] - if module not in self._modules: - color, style = self._get_decoration('S') - if module: - modsep = colorize_ansi('************* Module %s' % module, - color, style) - else: - modsep = colorize_ansi('************* %s' % module, - color, style) - self.writeln(modsep) - self._modules[module] = 1 - if obj: - obj = ':%s' % obj - sigle = self.make_sigle(msg_id) - color, style = self._get_decoration(sigle) - msg = colorize_ansi(msg, color, style) - sigle = colorize_ansi(sigle, color, style) - self.writeln('%s:%3s%s: %s' % (sigle, line, obj, msg)) diff --git a/.vim/bundle/python-mode/pylibs/pylama/pylint/utils.py b/.vim/bundle/python-mode/pylibs/pylama/pylint/utils.py @@ -1,602 +0,0 @@ -# Copyright (c) 2003-2010 Sylvain Thenault (thenault@gmail.com). -# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""some various utilities and helper classes, most of them used in the -main pylint class -""" - -import sys -from warnings import warn -from os.path import dirname, basename, splitext, exists, isdir, join, normpath - -from .logilab.common.modutils import modpath_from_file, get_module_files, \ - file_from_modpath -from .logilab.common.textutils import normalize_text -from .logilab.common.configuration import rest_format_section -from .logilab.common.ureports import Section - -from .logilab.astng import nodes, Module - -from .checkers import EmptyReport - - -class UnknownMessage(Exception): - """raised when a unregistered message id is encountered""" - - -MSG_TYPES = { - 'I' : 'info', - 'C' : 'convention', - 'R' : 'refactor', - 'W' : 'warning', - 'E' : 'error', - 'F' : 'fatal' - } -MSG_TYPES_LONG = dict([(v, k) for k, v in MSG_TYPES.iteritems()]) - -MSG_TYPES_STATUS = { - 'I' : 0, - 'C' : 16, - 'R' : 8, - 'W' : 4, - 'E' : 2, - 'F' : 1 - } - -_MSG_ORDER = 'EWRCIF' -MSG_STATE_SCOPE_CONFIG = 0 -MSG_STATE_SCOPE_MODULE = 1 - -def sort_msgs(msgids): - """sort message identifiers according to their category first""" - msgs = {} - for msg in msgids: - msgs.setdefault(msg[0], []).append(msg) - result = [] - for m_id in _MSG_ORDER: - if m_id in msgs: - result.extend( sorted(msgs[m_id]) ) - return result - -def get_module_and_frameid(node): - """return the module name and the frame id in the module""" - frame = node.frame() - module, obj = '', [] - while frame: - if isinstance(frame, Module): - module = frame.name - else: - obj.append(getattr(frame, 'name', '<lambda>')) - try: - frame = frame.parent.frame() - except AttributeError: - frame = None - obj.reverse() - return module, '.'.join(obj) - -def category_id(id): - id = id.upper() - if id in MSG_TYPES: - return id - return MSG_TYPES_LONG.get(id) - - -class Message: - def __init__(self, checker, msgid, msg, descr, symbol): - assert len(msgid) == 5, 'Invalid message id %s' % msgid - assert msgid[0] in MSG_TYPES, \ - 'Bad message type %s in %r' % (msgid[0], msgid) - self.msgid = msgid - self.msg = msg - self.descr = descr - self.checker = checker - self.symbol = symbol - -class MessagesHandlerMixIn: - """a mix-in class containing all the messages related methods for the main - lint class - """ - - def __init__(self): - # dictionary of registered messages - self._messages = {} - # dictionary from string symbolic id to Message object. - self._messages_by_symbol = {} - self._msgs_state = {} - self._module_msgs_state = {} # None - self._raw_module_msgs_state = {} - self._msgs_by_category = {} - self.msg_status = 0 - self._ignored_msgs = {} - - def register_messages(self, checker): - """register a dictionary of messages - - Keys are message ids, values are a 2-uple with the message type and the - message itself - - message ids should be a string of len 4, where the two first characters - are the checker id and the two last the message id in this checker - """ - msgs_dict = checker.msgs - chkid = None - for msgid, msg_tuple in msgs_dict.iteritems(): - if len(msg_tuple) == 3: - (msg, msgsymbol, msgdescr) = msg_tuple - assert msgsymbol not in self._messages_by_symbol, \ - 'Message symbol %r is already defined' % msgsymbol - else: - # messages should have a symbol, but for backward compatibility - # they may not. - (msg, msgdescr) = msg_tuple - warn("[pylint 0.26] description of message %s doesn't include " - "a symbolic name" % msgid, DeprecationWarning) - msgsymbol = None - # avoid duplicate / malformed ids - assert msgid not in self._messages, \ - 'Message id %r is already defined' % msgid - assert chkid is None or chkid == msgid[1:3], \ - 'Inconsistent checker part in message id %r' % msgid - chkid = msgid[1:3] - msg = Message(checker, msgid, msg, msgdescr, msgsymbol) - self._messages[msgid] = msg - self._messages_by_symbol[msgsymbol] = msg - self._msgs_by_category.setdefault(msgid[0], []).append(msgid) - - def get_message_help(self, msgid, checkerref=False): - """return the help string for the given message id""" - msg = self.check_message_id(msgid) - desc = normalize_text(' '.join(msg.descr.split()), indent=' ') - if checkerref: - desc += ' This message belongs to the %s checker.' % \ - msg.checker.name - title = msg.msg - if msg.symbol: - symbol_part = ' (%s)' % msg.symbol - else: - symbol_part = '' - if title != '%s': - title = title.splitlines()[0] - return ':%s%s: *%s*\n%s' % (msg.msgid, symbol_part, title, desc) - return ':%s%s:\n%s' % (msg.msgid, symbol_part, desc) - - def disable(self, msgid, scope='package', line=None): - """don't output message of the given id""" - assert scope in ('package', 'module') - # handle disable=all by disabling all categories - if msgid == 'all': - for msgid in MSG_TYPES: - self.disable(msgid, scope, line) - return - # msgid is a category? - catid = category_id(msgid) - if catid is not None: - for _msgid in self._msgs_by_category.get(catid): - self.disable(_msgid, scope, line) - return - # msgid is a checker name? - if msgid.lower() in self._checkers: - for checker in self._checkers[msgid.lower()]: - for _msgid in checker.msgs: - self.disable(_msgid, scope, line) - return - # msgid is report id? - if msgid.lower().startswith('rp'): - self.disable_report(msgid) - return - # msgid is a symbolic or numeric msgid. - msg = self.check_message_id(msgid) - if scope == 'module': - assert line > 0 - try: - self._module_msgs_state[msg.msgid][line] = False - except KeyError: - self._module_msgs_state[msg.msgid] = {line: False} - if msgid != 'I0011': - self.add_message('I0011', line=line, args=msg.msgid) - - else: - msgs = self._msgs_state - msgs[msg.msgid] = False - # sync configuration object - self.config.disable_msg = [mid for mid, val in msgs.iteritems() - if not val] - - def enable(self, msgid, scope='package', line=None): - """reenable message of the given id""" - assert scope in ('package', 'module') - catid = category_id(msgid) - # msgid is a category? - if catid is not None: - for msgid in self._msgs_by_category.get(catid): - self.enable(msgid, scope, line) - return - # msgid is a checker name? - if msgid.lower() in self._checkers: - for checker in self._checkers[msgid.lower()]: - for msgid in checker.msgs: - self.enable(msgid, scope, line) - return - # msgid is report id? - if msgid.lower().startswith('rp'): - self.enable_report(msgid) - return - # msgid is a symbolic or numeric msgid. - msg = self.check_message_id(msgid) - if scope == 'module': - assert line > 0 - try: - self._module_msgs_state[msg.msgid][line] = True - except KeyError: - self._module_msgs_state[msg.msgid] = {line: True} - self.add_message('I0012', line=line, args=msg.msgid) - else: - msgs = self._msgs_state - msgs[msg.msgid] = True - # sync configuration object - self.config.enable = [mid for mid, val in msgs.iteritems() if val] - - def check_message_id(self, msgid): - """returns the Message object for this message. - - msgid may be either a numeric or symbolic id. - - Raises UnknownMessage if the message id is not defined. - """ - if msgid in self._messages_by_symbol: - return self._messages_by_symbol[msgid] - msgid = msgid.upper() - try: - return self._messages[msgid] - except KeyError: - raise UnknownMessage('No such message id %s' % msgid) - - def get_msg_display_string(self, msgid): - """Generates a user-consumable representation of a message. - - Can be just the message ID or the ID and the symbol. - """ - if self.config.symbols: - symbol = self.check_message_id(msgid).symbol - if symbol: - msgid += '(%s)' % symbol - return msgid - - def get_message_state_scope(self, msgid, line=None): - """Returns the scope at which a message was enabled/disabled.""" - try: - if line in self._module_msgs_state[msgid]: - return MSG_STATE_SCOPE_MODULE - except (KeyError, TypeError): - return MSG_STATE_SCOPE_CONFIG - - def is_message_enabled(self, msgid, line=None): - """return true if the message associated to the given message id is - enabled - - msgid may be either a numeric or symbolic message id. - """ - if msgid in self._messages_by_symbol: - msgid = self._messages_by_symbol[msgid].msgid - if line is None: - return self._msgs_state.get(msgid, True) - try: - return self._module_msgs_state[msgid][line] - except (KeyError, TypeError): - return self._msgs_state.get(msgid, True) - - def handle_ignored_message(self, state_scope, msgid, line, node, args): - """Report an ignored message. - - state_scope is either MSG_STATE_SCOPE_MODULE or MSG_STATE_SCOPE_CONFIG, - depending on whether the message was disabled locally in the module, - or globally. The other arguments are the same as for add_message. - """ - if state_scope == MSG_STATE_SCOPE_MODULE: - try: - orig_line = self._suppression_mapping[(msgid, line)] - self._ignored_msgs.setdefault((msgid, orig_line), set()).add(line) - except KeyError: - pass - - def add_message(self, msgid, line=None, node=None, args=None): - """add the message corresponding to the given id. - - If provided, msg is expanded using args - - astng checkers should provide the node argument, raw checkers should - provide the line argument. - """ - if line is None and node is not None: - line = node.fromlineno - if hasattr(node, 'col_offset'): - col_offset = node.col_offset # XXX measured in bytes for utf-8, divide by two for chars? - else: - col_offset = None - # should this message be displayed - if not self.is_message_enabled(msgid, line): - self.handle_ignored_message( - self.get_message_state_scope(msgid, line), msgid, line, node, args) - return - # update stats - msg_cat = MSG_TYPES[msgid[0]] - self.msg_status |= MSG_TYPES_STATUS[msgid[0]] - self.stats[msg_cat] += 1 - self.stats['by_module'][self.current_name][msg_cat] += 1 - try: - self.stats['by_msg'][msgid] += 1 - except KeyError: - self.stats['by_msg'][msgid] = 1 - msg = self._messages[msgid].msg - # expand message ? - if args: - msg %= args - # get module and object - if node is None: - module, obj = self.current_name, '' - path = self.current_file - else: - module, obj = get_module_and_frameid(node) - path = node.root().file - # add the message - self.reporter.add_message(msgid, (path, module, obj, line or 1, col_offset or 0), msg) - - def help_message(self, msgids): - """display help messages for the given message identifiers""" - for msgid in msgids: - try: - print self.get_message_help(msgid, True) - print - except UnknownMessage, ex: - print ex - print - continue - - def print_full_documentation(self): - """output a full documentation in ReST format""" - by_checker = {} - for checker in self.get_checkers(): - if checker.name == 'master': - prefix = 'Main ' - print "Options" - print '-------\n' - if checker.options: - for section, options in checker.options_by_section(): - if section is None: - title = 'General options' - else: - title = '%s options' % section.capitalize() - print title - print '~' * len(title) - rest_format_section(sys.stdout, None, options) - print - else: - try: - by_checker[checker.name][0] += checker.options_and_values() - by_checker[checker.name][1].update(checker.msgs) - by_checker[checker.name][2] += checker.reports - except KeyError: - by_checker[checker.name] = [list(checker.options_and_values()), - dict(checker.msgs), - list(checker.reports)] - for checker, (options, msgs, reports) in by_checker.iteritems(): - prefix = '' - title = '%s checker' % checker - print title - print '-' * len(title) - print - if options: - title = 'Options' - print title - print '~' * len(title) - rest_format_section(sys.stdout, None, options) - print - if msgs: - title = ('%smessages' % prefix).capitalize() - print title - print '~' * len(title) - for msgid in sort_msgs(msgs.iterkeys()): - print self.get_message_help(msgid, False) - print - if reports: - title = ('%sreports' % prefix).capitalize() - print title - print '~' * len(title) - for report in reports: - print ':%s: %s' % report[:2] - print - print - - def list_messages(self): - """output full messages list documentation in ReST format""" - msgids = [] - for checker in self.get_checkers(): - for msgid in checker.msgs.iterkeys(): - msgids.append(msgid) - msgids.sort() - for msgid in msgids: - print self.get_message_help(msgid, False) - print - - -class ReportsHandlerMixIn: - """a mix-in class containing all the reports and stats manipulation - related methods for the main lint class - """ - def __init__(self): - self._reports = {} - self._reports_state = {} - - def register_report(self, reportid, r_title, r_cb, checker): - """register a report - - reportid is the unique identifier for the report - r_title the report's title - r_cb the method to call to make the report - checker is the checker defining the report - """ - reportid = reportid.upper() - self._reports.setdefault(checker, []).append( (reportid, r_title, r_cb) ) - - def enable_report(self, reportid): - """disable the report of the given id""" - reportid = reportid.upper() - self._reports_state[reportid] = True - - def disable_report(self, reportid): - """disable the report of the given id""" - reportid = reportid.upper() - self._reports_state[reportid] = False - - def report_is_enabled(self, reportid): - """return true if the report associated to the given identifier is - enabled - """ - return self._reports_state.get(reportid, True) - - def make_reports(self, stats, old_stats): - """render registered reports""" - sect = Section('Report', - '%s statements analysed.'% (self.stats['statement'])) - for checker in self._reports: - for reportid, r_title, r_cb in self._reports[checker]: - if not self.report_is_enabled(reportid): - continue - report_sect = Section(r_title) - try: - r_cb(report_sect, stats, old_stats) - except EmptyReport: - continue - report_sect.report_id = reportid - sect.append(report_sect) - return sect - - def add_stats(self, **kwargs): - """add some stats entries to the statistic dictionary - raise an AssertionError if there is a key conflict - """ - for key, value in kwargs.iteritems(): - if key[-1] == '_': - key = key[:-1] - assert key not in self.stats - self.stats[key] = value - return self.stats - - -def expand_modules(files_or_modules, black_list): - """take a list of files/modules/packages and return the list of tuple - (file, module name) which have to be actually checked - """ - result = [] - errors = [] - for something in files_or_modules: - if exists(something): - # this is a file or a directory - try: - modname = '.'.join(modpath_from_file(something)) - except ImportError: - modname = splitext(basename(something))[0] - if isdir(something): - filepath = join(something, '__init__.py') - else: - filepath = something - else: - # suppose it's a module or package - modname = something - try: - filepath = file_from_modpath(modname.split('.')) - if filepath is None: - errors.append( {'key' : 'F0003', 'mod': modname} ) - continue - except (ImportError, SyntaxError), ex: - # FIXME p3k : the SyntaxError is a Python bug and should be - # removed as soon as possible http://bugs.python.org/issue10588 - errors.append( {'key': 'F0001', 'mod': modname, 'ex': ex} ) - continue - filepath = normpath(filepath) - result.append( {'path': filepath, 'name': modname, - 'basepath': filepath, 'basename': modname} ) - if not (modname.endswith('.__init__') or modname == '__init__') \ - and '__init__.py' in filepath: - for subfilepath in get_module_files(dirname(filepath), black_list): - if filepath == subfilepath: - continue - submodname = '.'.join(modpath_from_file(subfilepath)) - result.append( {'path': subfilepath, 'name': submodname, - 'basepath': filepath, 'basename': modname} ) - return result, errors - - -class PyLintASTWalker(object): - - def __init__(self, linter): - # callbacks per node types - self.nbstatements = 1 - self.visit_events = {} - self.leave_events = {} - self.linter = linter - - def add_checker(self, checker): - """walk to the checker's dir and collect visit and leave methods""" - # XXX : should be possible to merge needed_checkers and add_checker - vcids = set() - lcids = set() - visits = self.visit_events - leaves = self.leave_events - msgs = self.linter._msgs_state - for member in dir(checker): - cid = member[6:] - if cid == 'default': - continue - if member.startswith('visit_'): - v_meth = getattr(checker, member) - # don't use visit_methods with no activated message: - if hasattr(v_meth, 'checks_msgs'): - if not any(msgs.get(m, True) for m in v_meth.checks_msgs): - continue - visits.setdefault(cid, []).append(v_meth) - vcids.add(cid) - elif member.startswith('leave_'): - l_meth = getattr(checker, member) - # don't use leave_methods with no activated message: - if hasattr(l_meth, 'checks_msgs'): - if not any(msgs.get(m, True) for m in l_meth.checks_msgs): - continue - leaves.setdefault(cid, []).append(l_meth) - lcids.add(cid) - visit_default = getattr(checker, 'visit_default', None) - if visit_default: - for cls in nodes.ALL_NODE_CLASSES: - cid = cls.__name__.lower() - if cid not in vcids: - visits.setdefault(cid, []).append(visit_default) - # for now we have no "leave_default" method in Pylint - - def walk(self, astng): - """call visit events of astng checkers for the given node, recurse on - its children, then leave events. - """ - cid = astng.__class__.__name__.lower() - if astng.is_statement: - self.nbstatements += 1 - # generate events for this node on each checker - for cb in self.visit_events.get(cid, ()): - cb(astng) - # recurse on children - for child in astng.get_children(): - self.walk(child) - for cb in self.leave_events.get(cid, ()): - cb(astng) diff --git a/.vim/bundle/python-mode/pylibs/pylama/utils.py b/.vim/bundle/python-mode/pylibs/pylama/utils.py @@ -1,110 +0,0 @@ -import _ast -from os import path as op, environ - -from .mccabe import get_code_complexity -from .pep8 import BaseReport, StyleGuide -from .pyflakes import checker - - -__all__ = 'pep8', 'mccabe', 'pyflakes', 'pylint' - -PYLINT_RC = op.abspath(op.join(op.dirname(__file__), 'pylint.rc')) - - -class PEP8Report(BaseReport): - - def __init__(self, *args, **kwargs): - super(PEP8Report, self).__init__(*args, **kwargs) - self.errors = [] - - def init_file(self, filename, lines, expected, line_offset): - super(PEP8Report, self).init_file( - filename, lines, expected, line_offset) - self.errors = [] - - def error(self, line_number, offset, text, check): - code = super(PEP8Report, self).error( - line_number, offset, text, check) - - self.errors.append(dict( - text=text, - type=code, - col=offset + 1, - lnum=line_number, - )) - - def get_file_results(self): - return self.errors - -P8Style = StyleGuide(reporter=PEP8Report) - - -def pep8(path, **meta): - " PEP8 code checking. " - - return P8Style.input_file(path) - - -def mccabe(path, code=None, complexity=8, **meta): - " MCCabe code checking. " - - return get_code_complexity(code, complexity, filename=path) - - -def pyflakes(path, code=None, **meta): - " PyFlakes code checking. " - - errors = [] - tree = compile(code, path, "exec", _ast.PyCF_ONLY_AST) - w = checker.Checker(tree, path) - w.messages = sorted(w.messages, key=lambda m: m.lineno) - for w in w.messages: - errors.append(dict( - lnum=w.lineno, - text=w.message % w.message_args, - )) - return errors - - -def pylint(path, **meta): - from sys import version_info - if version_info > (2, 8): - import logging - logging.warn("Pylint don't supported python3 and will be disabled.") - return [] - - from .pylint.lint import Run - from .pylint.reporters import BaseReporter - - from .pylint.logilab.astng.builder import MANAGER - MANAGER.astng_cache.clear() - - class Reporter(BaseReporter): - - def __init__(self): - self.errors = [] - BaseReporter.__init__(self) - - def _display(self, layout): - pass - - def add_message(self, msg_id, location, msg): - _, _, line, col = location[1:] - self.errors.append(dict( - lnum=line, - col=col, - text="%s %s" % (msg_id, msg), - type=msg_id[0] - )) - - pylintrc = op.join(environ.get('HOME', ''), '.pylintrc') - defattrs = '-r n' - if not op.exists(pylintrc): - defattrs += ' --rcfile={0}'.format(PYLINT_RC) - attrs = meta.get('pylint', defattrs.split()) - - runner = Run( - [path] + attrs, reporter=Reporter(), exit=False) - return runner.linter.reporter.errors - -# pymode:lint_ignore=W0231 diff --git a/.vim/bundle/python-mode/pylibs/pymode/__init__.py b/.vim/bundle/python-mode/pylibs/pymode/__init__.py diff --git a/.vim/bundle/python-mode/pylibs/pymode/auto.py b/.vim/bundle/python-mode/pylibs/pymode/auto.py @@ -1,18 +0,0 @@ -import vim -from autopep8 import fix_file - - -class Options(): - aggressive = 0 - diff = False - ignore = '' - in_place = True - max_line_length = 79 - pep8_passes = 100 - recursive = False - select = '' - verbose = 0 - - -def fix_current_file(): - fix_file(vim.current.buffer.name, Options) diff --git a/.vim/bundle/python-mode/pylibs/pymode/interface.py b/.vim/bundle/python-mode/pylibs/pymode/interface.py @@ -1,25 +0,0 @@ -import vim - - -def get_option(name): - return get_bvar(name) or get_var(name) - - -def get_var(name): - return vim.eval("g:pymode_%s" % name) - - -def get_bvar(name): - return (int(vim.eval("exists('b:pymode_%s')" % name)) and vim.eval("b:pymode_%s" % name)) or None - - -def get_current_buffer(): - return vim.current.buffer - - -def show_message(message): - vim.command("call pymode#WideMessage('%s')" % message) - - -def command(cmd): - vim.command(cmd) diff --git a/.vim/bundle/python-mode/pylibs/pymode/lint.py b/.vim/bundle/python-mode/pylibs/pymode/lint.py @@ -1,64 +0,0 @@ -import locale - -from pylama.main import run - -from .interface import get_option, get_var, get_current_buffer, command -from .queue import add_task - - -try: - locale.setlocale(locale.LC_CTYPE, "C") -except AttributeError: - pass - - -def check_file(): - checkers = get_option('lint_checker').split(',') - - ignore = set([ - i for i in ( - get_option('lint_ignore').split(',') + - get_var('lint_ignore').split(',')) - if i - ]) - select = set([ - s for s in ( - get_option('lint_select').split(',') + - get_var('lint_select').split(',')) - if i - ]) - - buffer = get_current_buffer() - complexity = int(get_option('lint_mccabe_complexity') or 0) - - add_task(run_checkers, checkers=checkers, ignore=ignore, - title='Code checking', - callback=parse_result, - buffer=buffer, - select=select, - complexity=complexity) - - -def run_checkers(task=None, checkers=None, ignore=None, - buffer=None, select=None, complexity=None): - - buffer = (task and task.buffer) or buffer - filename = buffer.name - result = [] - - pylint_options = '--rcfile={0} -r n'.format(get_var('lint_config')).split() - - result = run(filename, ignore=ignore, select=select, linters=checkers, - pylint=pylint_options, complexity=complexity) - - if task: - task.result = result - task.finished = True - task.done = 100 - - -def parse_result(result, bnum): - command(('let g:qf_list = {0}'.format(repr(result)).replace('\': u', '\': '))) - command('call pymode#lint#Parse({0})'.format(bnum)) - -# pymode:lint_ignore=W0622 diff --git a/.vim/bundle/python-mode/pylibs/pymode/queue.py b/.vim/bundle/python-mode/pylibs/pymode/queue.py @@ -1,60 +0,0 @@ -import threading -from .interface import show_message -import time - - -class Task(threading.Thread): - - def __init__(self, buffer, callback=None, title=None, *args, **kwargs): - self.buffer = buffer - self._stop = threading.Event() - self.result = None - self.callback = callback - self.done = 0 - self.finished = False - self.title = title - threading.Thread.__init__(self, *args, **kwargs) - - def run(self): - " Run tasks. " - self._Thread__target(task=self, *self._Thread__args, **self._Thread__kwargs) - - # Wait for result parsing - while not self.stopped(): - time.sleep(.2) - - def stop(self): - " Stop task. " - self._stop.set() - - def stopped(self): - return self._stop.isSet() - - -def stop_queue(): - " Stop all tasks. " - for thread in threading.enumerate(): - if isinstance(thread, Task): - thread.stop() - show_message('%s stopped.' % thread.title) - - -def add_task(target, callback=None, buffer=None, title=None, *args, **kwargs): - " Add all tasks. " - - task = Task(buffer, title=title, target=target, callback=callback, args=args, kwargs=kwargs) - task.daemon = True - task.start() - - show_message('%s started.' % task.title) - - -def check_task(): - " Check tasks for result. " - for thread in threading.enumerate(): - if isinstance(thread, Task): - if thread.finished: - thread.stop() - thread.callback(thread.result, thread.buffer.number) - else: - show_message('%s %s%%' % (thread.title, thread.done)) diff --git a/.vim/bundle/python-mode/pylibs/rope/__init__.py b/.vim/bundle/python-mode/pylibs/rope/__init__.py @@ -1,17 +0,0 @@ -"""rope, a python refactoring library""" - -INFO = __doc__ -VERSION = '0.9.4' -COPYRIGHT = """\ -Copyright (C) 2006-2012 Ali Gholami Rudi -Copyright (C) 2009-2012 Anton Gritsay - -This program is free software; you can redistribute it and/or modify it -under the terms of GNU General Public License as published by the -Free Software Foundation; either version 2 of the license, or (at your -opinion) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details.""" diff --git a/.vim/bundle/python-mode/pylibs/rope/base/__init__.py b/.vim/bundle/python-mode/pylibs/rope/base/__init__.py @@ -1,8 +0,0 @@ -"""Base rope package - -This package contains rope core modules that are used by other modules -and packages. - -""" - -__all__ = ['project', 'libutils', 'exceptions'] diff --git a/.vim/bundle/python-mode/pylibs/rope/base/arguments.py b/.vim/bundle/python-mode/pylibs/rope/base/arguments.py @@ -1,109 +0,0 @@ -import rope.base.evaluate -from rope.base import ast - - -class Arguments(object): - """A class for evaluating parameters passed to a function - - You can use the `create_arguments` factory. It handles implicit - first arguments. - - """ - - def __init__(self, args, scope): - self.args = args - self.scope = scope - self.instance = None - - def get_arguments(self, parameters): - result = [] - for pyname in self.get_pynames(parameters): - if pyname is None: - result.append(None) - else: - result.append(pyname.get_object()) - return result - - def get_pynames(self, parameters): - result = [None] * max(len(parameters), len(self.args)) - for index, arg in enumerate(self.args): - if isinstance(arg, ast.keyword) and arg.arg in parameters: - result[parameters.index(arg.arg)] = self._evaluate(arg.value) - else: - result[index] = self._evaluate(arg) - return result - - def get_instance_pyname(self): - if self.args: - return self._evaluate(self.args[0]) - - def _evaluate(self, ast_node): - return rope.base.evaluate.eval_node(self.scope, ast_node) - - -def create_arguments(primary, pyfunction, call_node, scope): - """A factory for creating `Arguments`""" - args = list(call_node.args) - args.extend(call_node.keywords) - called = call_node.func - # XXX: Handle constructors - if _is_method_call(primary, pyfunction) and \ - isinstance(called, ast.Attribute): - args.insert(0, called.value) - return Arguments(args, scope) - - -class ObjectArguments(object): - - def __init__(self, pynames): - self.pynames = pynames - - def get_arguments(self, parameters): - result = [] - for pyname in self.pynames: - if pyname is None: - result.append(None) - else: - result.append(pyname.get_object()) - return result - - def get_pynames(self, parameters): - return self.pynames - - def get_instance_pyname(self): - return self.pynames[0] -class MixedArguments(object): - - def __init__(self, pyname, arguments, scope): - """`argumens` is an instance of `Arguments`""" - self.pyname = pyname - self.args = arguments - - def get_pynames(self, parameters): - return [self.pyname] + self.args.get_pynames(parameters[1:]) - - def get_arguments(self, parameters): - result = [] - for pyname in self.get_pynames(parameters): - if pyname is None: - result.append(None) - else: - result.append(pyname.get_object()) - return result - - def get_instance_pyname(self): - return self.pyname - - -def _is_method_call(primary, pyfunction): - if primary is None: - return False - pyobject = primary.get_object() - if isinstance(pyobject.get_type(), rope.base.pyobjects.PyClass) and \ - isinstance(pyfunction, rope.base.pyobjects.PyFunction) and \ - isinstance(pyfunction.parent, rope.base.pyobjects.PyClass): - return True - if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass) and \ - isinstance(pyfunction, rope.base.builtins.BuiltinFunction): - return True - return False diff --git a/.vim/bundle/python-mode/pylibs/rope/base/ast.py b/.vim/bundle/python-mode/pylibs/rope/base/ast.py @@ -1,71 +0,0 @@ -import _ast -from _ast import * - -from rope.base import fscommands - - -def parse(source, filename='<string>'): - # NOTE: the raw string should be given to `compile` function - if isinstance(source, unicode): - source = fscommands.unicode_to_file_data(source) - if '\r' in source: - source = source.replace('\r\n', '\n').replace('\r', '\n') - if not source.endswith('\n'): - source += '\n' - try: - return compile(source, filename, 'exec', _ast.PyCF_ONLY_AST) - except (TypeError, ValueError), e: - error = SyntaxError() - error.lineno = 1 - error.filename = filename - error.msg = str(e) - raise error - - -def walk(node, walker): - """Walk the syntax tree""" - method_name = '_' + node.__class__.__name__ - method = getattr(walker, method_name, None) - if method is not None: - if isinstance(node, _ast.ImportFrom) and node.module is None: - # In python < 2.7 ``node.module == ''`` for relative imports - # but for python 2.7 it is None. Generalizing it to ''. - node.module = '' - return method(node) - for child in get_child_nodes(node): - walk(child, walker) - - -def get_child_nodes(node): - if isinstance(node, _ast.Module): - return node.body - result = [] - if node._fields is not None: - for name in node._fields: - child = getattr(node, name) - if isinstance(child, list): - for entry in child: - if isinstance(entry, _ast.AST): - result.append(entry) - if isinstance(child, _ast.AST): - result.append(child) - return result - - -def call_for_nodes(node, callback, recursive=False): - """If callback returns `True` the child nodes are skipped""" - result = callback(node) - if recursive and not result: - for child in get_child_nodes(node): - call_for_nodes(child, callback, recursive) - - -def get_children(node): - result = [] - if node._fields is not None: - for name in node._fields: - if name in ['lineno', 'col_offset']: - continue - child = getattr(node, name) - result.append(child) - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/base/astutils.py b/.vim/bundle/python-mode/pylibs/rope/base/astutils.py @@ -1,61 +0,0 @@ -from rope.base import ast - - -def get_name_levels(node): - """Return a list of ``(name, level)`` tuples for assigned names - - The `level` is `None` for simple assignments and is a list of - numbers for tuple assignments for example in:: - - a, (b, c) = x - - The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for - `c` is ``[1, 1]``. - - """ - visitor = _NodeNameCollector() - ast.walk(node, visitor) - return visitor.names - - -class _NodeNameCollector(object): - - def __init__(self, levels=None): - self.names = [] - self.levels = levels - self.index = 0 - - def _add_node(self, node): - new_levels = [] - if self.levels is not None: - new_levels = list(self.levels) - new_levels.append(self.index) - self.index += 1 - self._added(node, new_levels) - - def _added(self, node, levels): - if hasattr(node, 'id'): - self.names.append((node.id, levels)) - - def _Name(self, node): - self._add_node(node) - - def _Tuple(self, node): - new_levels = [] - if self.levels is not None: - new_levels = list(self.levels) - new_levels.append(self.index) - self.index += 1 - visitor = _NodeNameCollector(new_levels) - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - self.names.extend(visitor.names) - - def _Subscript(self, node): - self._add_node(node) - - def _Attribute(self, node): - self._add_node(node) - - def _Slice(self, node): - self._add_node(node) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/builtins.py b/.vim/bundle/python-mode/pylibs/rope/base/builtins.py @@ -1,767 +0,0 @@ -"""This module trys to support builtin types and functions.""" -import inspect - -import rope.base.evaluate -from rope.base import pynames, pyobjects, arguments, utils, ast - - -class BuiltinModule(pyobjects.AbstractModule): - - def __init__(self, name, pycore=None, initial={}): - super(BuiltinModule, self).__init__() - self.name = name - self.pycore = pycore - self.initial = initial - - parent = None - - def get_attributes(self): - return self.attributes - - def get_doc(self): - if self.module: - return self.module.__doc__ - - def get_name(self): - return self.name.split('.')[-1] - - @property - @utils.saveit - def attributes(self): - result = _object_attributes(self.module, self) - result.update(self.initial) - if self.pycore is not None: - submodules = self.pycore._builtin_submodules(self.name) - for name, module in submodules.iteritems(): - result[name] = rope.base.builtins.BuiltinName(module) - return result - - @property - @utils.saveit - def module(self): - try: - result = __import__(self.name) - for token in self.name.split('.')[1:]: - result = getattr(result, token, None) - return result - except ImportError: - return - - -class _BuiltinElement(object): - - def __init__(self, builtin, parent=None): - self.builtin = builtin - self._parent = parent - - def get_doc(self): - if self.builtin: - return getattr(self.builtin, '__doc__', None) - - def get_name(self): - if self.builtin: - return getattr(self.builtin, '__name__', None) - - @property - def parent(self): - if self._parent is None: - return builtins - return self._parent - - -class BuiltinClass(_BuiltinElement, pyobjects.AbstractClass): - - def __init__(self, builtin, attributes, parent=None): - _BuiltinElement.__init__(self, builtin, parent) - pyobjects.AbstractClass.__init__(self) - self.initial = attributes - - @utils.saveit - def get_attributes(self): - result = _object_attributes(self.builtin, self) - result.update(self.initial) - return result - - -class BuiltinFunction(_BuiltinElement, pyobjects.AbstractFunction): - - def __init__(self, returned=None, function=None, builtin=None, - argnames=[], parent=None): - _BuiltinElement.__init__(self, builtin, parent) - pyobjects.AbstractFunction.__init__(self) - self.argnames = argnames - self.returned = returned - self.function = function - - def get_returned_object(self, args): - if self.function is not None: - return self.function(_CallContext(self.argnames, args)) - else: - return self.returned - - def get_param_names(self, special_args=True): - return self.argnames - - -class BuiltinUnknown(_BuiltinElement, pyobjects.PyObject): - - def __init__(self, builtin): - super(BuiltinUnknown, self).__init__(pyobjects.get_unknown()) - self.builtin = builtin - self.type = pyobjects.get_unknown() - - def get_name(self): - return getattr(type(self.builtin), '__name__', None) - - @utils.saveit - def get_attributes(self): - return _object_attributes(self.builtin, self) - - -def _object_attributes(obj, parent): - attributes = {} - for name in dir(obj): - if name == 'None': - continue - try: - child = getattr(obj, name) - except AttributeError: - # descriptors are allowed to raise AttributeError - # even if they are in dir() - continue - pyobject = None - if inspect.isclass(child): - pyobject = BuiltinClass(child, {}, parent=parent) - elif inspect.isroutine(child): - pyobject = BuiltinFunction(builtin=child, parent=parent) - else: - pyobject = BuiltinUnknown(builtin=child) - attributes[name] = BuiltinName(pyobject) - return attributes - - -def _create_builtin_type_getter(cls): - def _get_builtin(*args): - if not hasattr(cls, '_generated'): - cls._generated = {} - if args not in cls._generated: - cls._generated[args] = cls(*args) - return cls._generated[args] - return _get_builtin - -def _create_builtin_getter(cls): - type_getter = _create_builtin_type_getter(cls) - def _get_builtin(*args): - return pyobjects.PyObject(type_getter(*args)) - return _get_builtin - - -class _CallContext(object): - - def __init__(self, argnames, args): - self.argnames = argnames - self.args = args - - def _get_scope_and_pyname(self, pyname): - if pyname is not None and isinstance(pyname, pynames.AssignedName): - pymodule, lineno = pyname.get_definition_location() - if pymodule is None: - return None, None - if lineno is None: - lineno = 1 - scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - name = None - while name is None and scope is not None: - for current in scope.get_names(): - if scope[current] is pyname: - name = current - break - else: - scope = scope.parent - return scope, name - return None, None - - def get_argument(self, name): - if self.args: - args = self.args.get_arguments(self.argnames) - return args[self.argnames.index(name)] - - def get_pyname(self, name): - if self.args: - args = self.args.get_pynames(self.argnames) - if name in self.argnames: - return args[self.argnames.index(name)] - - def get_arguments(self, argnames): - if self.args: - return self.args.get_arguments(argnames) - - def get_pynames(self, argnames): - if self.args: - return self.args.get_pynames(argnames) - - def get_per_name(self): - if self.args is None: - return None - pyname = self.args.get_instance_pyname() - scope, name = self._get_scope_and_pyname(pyname) - if name is not None: - pymodule = pyname.get_definition_location()[0] - return pymodule.pycore.object_info.get_per_name(scope, name) - return None - - def save_per_name(self, value): - if self.args is None: - return None - pyname = self.args.get_instance_pyname() - scope, name = self._get_scope_and_pyname(pyname) - if name is not None: - pymodule = pyname.get_definition_location()[0] - pymodule.pycore.object_info.save_per_name(scope, name, value) - - -class _AttributeCollector(object): - - def __init__(self, type): - self.attributes = {} - self.type = type - - def __call__(self, name, returned=None, function=None, - argnames=['self'], check_existence=True): - try: - builtin = getattr(self.type, name) - except AttributeError: - if check_existence: - raise - builtin=None - self.attributes[name] = BuiltinName( - BuiltinFunction(returned=returned, function=function, - argnames=argnames, builtin=builtin)) - - def __setitem__(self, name, value): - self.attributes[name] = value - - -class List(BuiltinClass): - - def __init__(self, holding=None): - self.holding = holding - collector = _AttributeCollector(list) - - collector('__iter__', function=self._iterator_get) - collector('__new__', function=self._new_list) - - # Adding methods - collector('append', function=self._list_add, argnames=['self', 'value']) - collector('__setitem__', function=self._list_add, - argnames=['self', 'index', 'value']) - collector('insert', function=self._list_add, - argnames=['self', 'index', 'value']) - collector('extend', function=self._self_set, - argnames=['self', 'iterable']) - - # Getting methods - collector('__getitem__', function=self._list_get) - collector('pop', function=self._list_get) - collector('__getslice__', function=self._self_get) - - super(List, self).__init__(list, collector.attributes) - - def _new_list(self, args): - return _create_builtin(args, get_list) - - def _list_add(self, context): - if self.holding is not None: - return - holding = context.get_argument('value') - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - def _self_set(self, context): - if self.holding is not None: - return - iterable = context.get_pyname('iterable') - holding = _infer_sequence_for_pyname(iterable) - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - def _list_get(self, context): - if self.holding is not None: - return self.holding - return context.get_per_name() - - def _iterator_get(self, context): - return get_iterator(self._list_get(context)) - - def _self_get(self, context): - return get_list(self._list_get(context)) - - -get_list = _create_builtin_getter(List) -get_list_type = _create_builtin_type_getter(List) - - -class Dict(BuiltinClass): - - def __init__(self, keys=None, values=None): - self.keys = keys - self.values = values - item = get_tuple(self.keys, self.values) - collector = _AttributeCollector(dict) - collector('__new__', function=self._new_dict) - collector('__setitem__', function=self._dict_add) - collector('popitem', function=self._item_get) - collector('pop', function=self._value_get) - collector('get', function=self._key_get) - collector('keys', function=self._key_list) - collector('values', function=self._value_list) - collector('items', function=self._item_list) - collector('copy', function=self._self_get) - collector('__getitem__', function=self._value_get) - collector('__iter__', function=self._key_iter) - collector('update', function=self._self_set) - super(Dict, self).__init__(dict, collector.attributes) - - def _new_dict(self, args): - def do_create(holding=None): - if holding is None: - return get_dict() - type = holding.get_type() - if isinstance(type, Tuple) and len(type.get_holding_objects()) == 2: - return get_dict(*type.get_holding_objects()) - return _create_builtin(args, do_create) - - def _dict_add(self, context): - if self.keys is not None: - return - key, value = context.get_arguments(['self', 'key', 'value'])[1:] - if key is not None and key != pyobjects.get_unknown(): - context.save_per_name(get_tuple(key, value)) - - def _item_get(self, context): - if self.keys is not None: - return get_tuple(self.keys, self.values) - item = context.get_per_name() - if item is None or not isinstance(item.get_type(), Tuple): - return get_tuple(self.keys, self.values) - return item - - def _value_get(self, context): - item = self._item_get(context).get_type() - return item.get_holding_objects()[1] - - def _key_get(self, context): - item = self._item_get(context).get_type() - return item.get_holding_objects()[0] - - def _value_list(self, context): - return get_list(self._value_get(context)) - - def _key_list(self, context): - return get_list(self._key_get(context)) - - def _item_list(self, context): - return get_list(self._item_get(context)) - - def _value_iter(self, context): - return get_iterator(self._value_get(context)) - - def _key_iter(self, context): - return get_iterator(self._key_get(context)) - - def _item_iter(self, context): - return get_iterator(self._item_get(context)) - - def _self_get(self, context): - item = self._item_get(context).get_type() - key, value = item.get_holding_objects()[:2] - return get_dict(key, value) - - def _self_set(self, context): - if self.keys is not None: - return - new_dict = context.get_pynames(['self', 'd'])[1] - if new_dict and isinstance(new_dict.get_object().get_type(), Dict): - args = arguments.ObjectArguments([new_dict]) - items = new_dict.get_object()['popitem'].\ - get_object().get_returned_object(args) - context.save_per_name(items) - else: - holding = _infer_sequence_for_pyname(new_dict) - if holding is not None and isinstance(holding.get_type(), Tuple): - context.save_per_name(holding) - - -get_dict = _create_builtin_getter(Dict) -get_dict_type = _create_builtin_type_getter(Dict) - - -class Tuple(BuiltinClass): - - def __init__(self, *objects): - self.objects = objects - first = None - if objects: - first = objects[0] - attributes = { - '__getitem__': BuiltinName(BuiltinFunction(first)), - '__getslice__': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))), - '__new__': BuiltinName(BuiltinFunction(function=self._new_tuple)), - '__iter__': BuiltinName(BuiltinFunction(get_iterator(first)))} - super(Tuple, self).__init__(tuple, attributes) - - def get_holding_objects(self): - return self.objects - - def _new_tuple(self, args): - return _create_builtin(args, get_tuple) - - -get_tuple = _create_builtin_getter(Tuple) -get_tuple_type = _create_builtin_type_getter(Tuple) - - -class Set(BuiltinClass): - - def __init__(self, holding=None): - self.holding = holding - collector = _AttributeCollector(set) - collector('__new__', function=self._new_set) - - self_methods = ['copy', 'difference', 'intersection', - 'symmetric_difference', 'union'] - for method in self_methods: - collector(method, function=self._self_get) - collector('add', function=self._set_add) - collector('update', function=self._self_set) - collector('update', function=self._self_set) - collector('symmetric_difference_update', function=self._self_set) - collector('difference_update', function=self._self_set) - - collector('pop', function=self._set_get) - collector('__iter__', function=self._iterator_get) - super(Set, self).__init__(set, collector.attributes) - - def _new_set(self, args): - return _create_builtin(args, get_set) - - def _set_add(self, context): - if self.holding is not None: - return - holding = context.get_arguments(['self', 'value'])[1] - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - def _self_set(self, context): - if self.holding is not None: - return - iterable = context.get_pyname('iterable') - holding = _infer_sequence_for_pyname(iterable) - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - def _set_get(self, context): - if self.holding is not None: - return self.holding - return context.get_per_name() - - def _iterator_get(self, context): - return get_iterator(self._set_get(context)) - - def _self_get(self, context): - return get_list(self._set_get(context)) - - -get_set = _create_builtin_getter(Set) -get_set_type = _create_builtin_type_getter(Set) - - -class Str(BuiltinClass): - - def __init__(self): - self_object = pyobjects.PyObject(self) - collector = _AttributeCollector(str) - collector('__iter__', get_iterator(self_object), check_existence=False) - - self_methods = ['__getitem__', '__getslice__', 'capitalize', 'center', - 'decode', 'encode', 'expandtabs', 'join', 'ljust', - 'lower', 'lstrip', 'replace', 'rjust', 'rstrip', 'strip', - 'swapcase', 'title', 'translate', 'upper', 'zfill'] - for method in self_methods: - collector(method, self_object) - - for method in ['rsplit', 'split', 'splitlines']: - collector(method, get_list(self_object)) - - super(Str, self).__init__(str, collector.attributes) - - def get_doc(self): - return str.__doc__ - - -get_str = _create_builtin_getter(Str) -get_str_type = _create_builtin_type_getter(Str) - - -class BuiltinName(pynames.PyName): - - def __init__(self, pyobject): - self.pyobject = pyobject - - def get_object(self): - return self.pyobject - - def get_definition_location(self): - return (None, None) - -class Iterator(pyobjects.AbstractClass): - - def __init__(self, holding=None): - super(Iterator, self).__init__() - self.holding = holding - self.attributes = { - 'next': BuiltinName(BuiltinFunction(self.holding)), - '__iter__': BuiltinName(BuiltinFunction(self))} - - def get_attributes(self): - return self.attributes - - def get_returned_object(self, args): - return self.holding - -get_iterator = _create_builtin_getter(Iterator) - - -class Generator(pyobjects.AbstractClass): - - def __init__(self, holding=None): - super(Generator, self).__init__() - self.holding = holding - self.attributes = { - 'next': BuiltinName(BuiltinFunction(self.holding)), - '__iter__': BuiltinName(BuiltinFunction(get_iterator(self.holding))), - 'close': BuiltinName(BuiltinFunction()), - 'send': BuiltinName(BuiltinFunction()), - 'throw': BuiltinName(BuiltinFunction())} - - def get_attributes(self): - return self.attributes - - def get_returned_object(self, args): - return self.holding - -get_generator = _create_builtin_getter(Generator) - - -class File(BuiltinClass): - - def __init__(self): - self_object = pyobjects.PyObject(self) - str_object = get_str() - str_list = get_list(get_str()) - attributes = {} - def add(name, returned=None, function=None): - builtin = getattr(file, name, None) - attributes[name] = BuiltinName( - BuiltinFunction(returned=returned, function=function, - builtin=builtin)) - add('__iter__', get_iterator(str_object)) - for method in ['next', 'read', 'readline', 'readlines']: - add(method, str_list) - for method in ['close', 'flush', 'lineno', 'isatty', 'seek', 'tell', - 'truncate', 'write', 'writelines']: - add(method) - super(File, self).__init__(file, attributes) - - -get_file = _create_builtin_getter(File) -get_file_type = _create_builtin_type_getter(File) - - -class Property(BuiltinClass): - - def __init__(self, fget=None, fset=None, fdel=None, fdoc=None): - self._fget = fget - self._fdoc = fdoc - attributes = { - 'fget': BuiltinName(BuiltinFunction()), - 'fset': BuiltinName(pynames.UnboundName()), - 'fdel': BuiltinName(pynames.UnboundName()), - '__new__': BuiltinName(BuiltinFunction(function=_property_function))} - super(Property, self).__init__(property, attributes) - - def get_property_object(self, args): - if isinstance(self._fget, pyobjects.AbstractFunction): - return self._fget.get_returned_object(args) - - -def _property_function(args): - parameters = args.get_arguments(['fget', 'fset', 'fdel', 'fdoc']) - return pyobjects.PyObject(Property(parameters[0])) - - -class Lambda(pyobjects.AbstractFunction): - - def __init__(self, node, scope): - super(Lambda, self).__init__() - self.node = node - self.arguments = node.args - self.scope = scope - - def get_returned_object(self, args): - result = rope.base.evaluate.eval_node(self.scope, self.node.body) - if result is not None: - return result.get_object() - else: - return pyobjects.get_unknown() - - def get_module(self): - return self.parent.get_module() - - def get_scope(self): - return self.scope - - def get_kind(self): - return 'lambda' - - def get_ast(self): - return self.node - - def get_attributes(self): - return {} - - def get_name(self): - return 'lambda' - - def get_param_names(self, special_args=True): - result = [node.id for node in self.arguments.args - if isinstance(node, ast.Name)] - if self.arguments.vararg: - result.append('*' + self.arguments.vararg) - if self.arguments.kwarg: - result.append('**' + self.arguments.kwarg) - return result - - @property - def parent(self): - return self.scope.pyobject - - -class BuiltinObject(BuiltinClass): - - def __init__(self): - super(BuiltinObject, self).__init__(object, {}) - - -class BuiltinType(BuiltinClass): - - def __init__(self): - super(BuiltinType, self).__init__(type, {}) - - -def _infer_sequence_for_pyname(pyname): - if pyname is None: - return None - seq = pyname.get_object() - args = arguments.ObjectArguments([pyname]) - if '__iter__' in seq: - obj = seq['__iter__'].get_object() - if not isinstance(obj, pyobjects.AbstractFunction): - return None - iter = obj.get_returned_object(args) - if iter is not None and 'next' in iter: - holding = iter['next'].get_object().\ - get_returned_object(args) - return holding - - -def _create_builtin(args, creator): - passed = args.get_pynames(['sequence'])[0] - if passed is None: - holding = None - else: - holding = _infer_sequence_for_pyname(passed) - if holding is not None: - return creator(holding) - else: - return creator() - - -def _range_function(args): - return get_list() - -def _reversed_function(args): - return _create_builtin(args, get_iterator) - -def _sorted_function(args): - return _create_builtin(args, get_list) - -def _super_function(args): - passed_class, passed_self = args.get_arguments(['type', 'self']) - if passed_self is None: - return passed_class - else: - #pyclass = passed_self.get_type() - pyclass = passed_class - if isinstance(pyclass, pyobjects.AbstractClass): - supers = pyclass.get_superclasses() - if supers: - return pyobjects.PyObject(supers[0]) - return passed_self - -def _zip_function(args): - args = args.get_pynames(['sequence']) - objects = [] - for seq in args: - if seq is None: - holding = None - else: - holding = _infer_sequence_for_pyname(seq) - objects.append(holding) - tuple = get_tuple(*objects) - return get_list(tuple) - -def _enumerate_function(args): - passed = args.get_pynames(['sequence'])[0] - if passed is None: - holding = None - else: - holding = _infer_sequence_for_pyname(passed) - tuple = get_tuple(None, holding) - return get_iterator(tuple) - -def _iter_function(args): - passed = args.get_pynames(['sequence'])[0] - if passed is None: - holding = None - else: - holding = _infer_sequence_for_pyname(passed) - return get_iterator(holding) - -def _input_function(args): - return get_str() - - -_initial_builtins = { - 'list': BuiltinName(get_list_type()), - 'dict': BuiltinName(get_dict_type()), - 'tuple': BuiltinName(get_tuple_type()), - 'set': BuiltinName(get_set_type()), - 'str': BuiltinName(get_str_type()), - 'file': BuiltinName(get_file_type()), - 'open': BuiltinName(get_file_type()), - 'unicode': BuiltinName(get_str_type()), - 'range': BuiltinName(BuiltinFunction(function=_range_function, builtin=range)), - 'reversed': BuiltinName(BuiltinFunction(function=_reversed_function, builtin=reversed)), - 'sorted': BuiltinName(BuiltinFunction(function=_sorted_function, builtin=sorted)), - 'super': BuiltinName(BuiltinFunction(function=_super_function, builtin=super)), - 'property': BuiltinName(BuiltinFunction(function=_property_function, builtin=property)), - 'zip': BuiltinName(BuiltinFunction(function=_zip_function, builtin=zip)), - 'enumerate': BuiltinName(BuiltinFunction(function=_enumerate_function, builtin=enumerate)), - 'object': BuiltinName(BuiltinObject()), - 'type': BuiltinName(BuiltinType()), - 'iter': BuiltinName(BuiltinFunction(function=_iter_function, builtin=iter)), - 'raw_input': BuiltinName(BuiltinFunction(function=_input_function, builtin=raw_input)), - } - -builtins = BuiltinModule('__builtin__', initial=_initial_builtins) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/change.py b/.vim/bundle/python-mode/pylibs/rope/base/change.py @@ -1,448 +0,0 @@ -import datetime -import difflib -import os -import time -import warnings - -import rope.base.fscommands -from rope.base import taskhandle, exceptions, utils - - -class Change(object): - """The base class for changes - - Rope refactorings return `Change` objects. They can be previewed, - committed or undone. - """ - - def do(self, job_set=None): - """Perform the change - - .. note:: Do use this directly. Use `Project.do()` instead. - """ - - def undo(self, job_set=None): - """Perform the change - - .. note:: Do use this directly. Use `History.undo()` instead. - """ - - def get_description(self): - """Return the description of this change - - This can be used for previewing the changes. - """ - return str(self) - - def get_changed_resources(self): - """Return the list of resources that will be changed""" - return [] - - @property - @utils.saveit - def _operations(self): - return _ResourceOperations(self.resource.project) - - -class ChangeSet(Change): - """A collection of `Change` objects - - This class holds a collection of changes. This class provides - these fields: - - * `changes`: the list of changes - * `description`: the goal of these changes - """ - - def __init__(self, description, timestamp=None): - self.changes = [] - self.description = description - self.time = timestamp - - def do(self, job_set=taskhandle.NullJobSet()): - try: - done = [] - for change in self.changes: - change.do(job_set) - done.append(change) - self.time = time.time() - except Exception: - for change in done: - change.undo() - raise - - def undo(self, job_set=taskhandle.NullJobSet()): - try: - done = [] - for change in reversed(self.changes): - change.undo(job_set) - done.append(change) - except Exception: - for change in done: - change.do() - raise - - def add_change(self, change): - self.changes.append(change) - - def get_description(self): - result = [str(self) + ':\n\n\n'] - for change in self.changes: - result.append(change.get_description()) - result.append('\n') - return ''.join(result) - - def __str__(self): - if self.time is not None: - date = datetime.datetime.fromtimestamp(self.time) - if date.date() == datetime.date.today(): - string_date = 'today' - elif date.date() == (datetime.date.today() - datetime.timedelta(1)): - string_date = 'yesterday' - elif date.year == datetime.date.today().year: - string_date = date.strftime('%b %d') - else: - string_date = date.strftime('%d %b, %Y') - string_time = date.strftime('%H:%M:%S') - string_time = '%s %s ' % (string_date, string_time) - return self.description + ' - ' + string_time - return self.description - - def get_changed_resources(self): - result = set() - for change in self.changes: - result.update(change.get_changed_resources()) - return result - - -def _handle_job_set(function): - """A decorator for handling `taskhandle.JobSet`\s - - A decorator for handling `taskhandle.JobSet`\s for `do` and `undo` - methods of `Change`\s. - """ - def call(self, job_set=taskhandle.NullJobSet()): - job_set.started_job(str(self)) - function(self) - job_set.finished_job() - return call - - -class ChangeContents(Change): - """A class to change the contents of a file - - Fields: - - * `resource`: The `rope.base.resources.File` to change - * `new_contents`: What to write in the file - """ - - def __init__(self, resource, new_contents, old_contents=None): - self.resource = resource - # IDEA: Only saving diffs; possible problems when undo/redoing - self.new_contents = new_contents - self.old_contents = old_contents - - @_handle_job_set - def do(self): - if self.old_contents is None: - self.old_contents = self.resource.read() - self._operations.write_file(self.resource, self.new_contents) - - @_handle_job_set - def undo(self): - if self.old_contents is None: - raise exceptions.HistoryError( - 'Undoing a change that is not performed yet!') - self._operations.write_file(self.resource, self.old_contents) - - def __str__(self): - return 'Change <%s>' % self.resource.path - - def get_description(self): - new = self.new_contents - old = self.old_contents - if old is None: - if self.resource.exists(): - old = self.resource.read() - else: - old = '' - result = difflib.unified_diff( - old.splitlines(True), new.splitlines(True), - 'a/' + self.resource.path, 'b/' + self.resource.path) - return ''.join(list(result)) - - def get_changed_resources(self): - return [self.resource] - - -class MoveResource(Change): - """Move a resource to a new location - - Fields: - - * `resource`: The `rope.base.resources.Resource` to move - * `new_resource`: The destination for move; It is the moved - resource not the folder containing that resource. - """ - - def __init__(self, resource, new_location, exact=False): - self.project = resource.project - self.resource = resource - if not exact: - new_location = _get_destination_for_move(resource, new_location) - if resource.is_folder(): - self.new_resource = self.project.get_folder(new_location) - else: - self.new_resource = self.project.get_file(new_location) - - @_handle_job_set - def do(self): - self._operations.move(self.resource, self.new_resource) - - @_handle_job_set - def undo(self): - self._operations.move(self.new_resource, self.resource) - - def __str__(self): - return 'Move <%s>' % self.resource.path - - def get_description(self): - return 'rename from %s\nrename to %s' % (self.resource.path, - self.new_resource.path) - - def get_changed_resources(self): - return [self.resource, self.new_resource] - - -class CreateResource(Change): - """A class to create a resource - - Fields: - - * `resource`: The resource to create - """ - - def __init__(self, resource): - self.resource = resource - - @_handle_job_set - def do(self): - self._operations.create(self.resource) - - @_handle_job_set - def undo(self): - self._operations.remove(self.resource) - - def __str__(self): - return 'Create Resource <%s>' % (self.resource.path) - - def get_description(self): - return 'new file %s' % (self.resource.path) - - def get_changed_resources(self): - return [self.resource] - - def _get_child_path(self, parent, name): - if parent.path == '': - return name - else: - return parent.path + '/' + name - - -class CreateFolder(CreateResource): - """A class to create a folder - - See docs for `CreateResource`. - """ - - def __init__(self, parent, name): - resource = parent.project.get_folder(self._get_child_path(parent, name)) - super(CreateFolder, self).__init__(resource) - - -class CreateFile(CreateResource): - """A class to create a file - - See docs for `CreateResource`. - """ - - def __init__(self, parent, name): - resource = parent.project.get_file(self._get_child_path(parent, name)) - super(CreateFile, self).__init__(resource) - - -class RemoveResource(Change): - """A class to remove a resource - - Fields: - - * `resource`: The resource to be removed - """ - - def __init__(self, resource): - self.resource = resource - - @_handle_job_set - def do(self): - self._operations.remove(self.resource) - - # TODO: Undoing remove operations - @_handle_job_set - def undo(self): - raise NotImplementedError( - 'Undoing `RemoveResource` is not implemented yet.') - - def __str__(self): - return 'Remove <%s>' % (self.resource.path) - - def get_changed_resources(self): - return [self.resource] - - -def count_changes(change): - """Counts the number of basic changes a `Change` will make""" - if isinstance(change, ChangeSet): - result = 0 - for child in change.changes: - result += count_changes(child) - return result - return 1 - -def create_job_set(task_handle, change): - return task_handle.create_jobset(str(change), count_changes(change)) - - -class _ResourceOperations(object): - - def __init__(self, project): - self.project = project - self.fscommands = project.fscommands - self.direct_commands = rope.base.fscommands.FileSystemCommands() - - def _get_fscommands(self, resource): - if self.project.is_ignored(resource): - return self.direct_commands - return self.fscommands - - def write_file(self, resource, contents): - data = rope.base.fscommands.unicode_to_file_data(contents) - fscommands = self._get_fscommands(resource) - fscommands.write(resource.real_path, data) - for observer in list(self.project.observers): - observer.resource_changed(resource) - - def move(self, resource, new_resource): - fscommands = self._get_fscommands(resource) - fscommands.move(resource.real_path, new_resource.real_path) - for observer in list(self.project.observers): - observer.resource_moved(resource, new_resource) - - def create(self, resource): - if resource.is_folder(): - self._create_resource(resource.path, kind='folder') - else: - self._create_resource(resource.path) - for observer in list(self.project.observers): - observer.resource_created(resource) - - def remove(self, resource): - fscommands = self._get_fscommands(resource) - fscommands.remove(resource.real_path) - for observer in list(self.project.observers): - observer.resource_removed(resource) - - def _create_resource(self, file_name, kind='file'): - resource_path = self.project._get_resource_path(file_name) - if os.path.exists(resource_path): - raise exceptions.RopeError('Resource <%s> already exists' - % resource_path) - resource = self.project.get_file(file_name) - if not resource.parent.exists(): - raise exceptions.ResourceNotFoundError( - 'Parent folder of <%s> does not exist' % resource.path) - fscommands = self._get_fscommands(resource) - try: - if kind == 'file': - fscommands.create_file(resource_path) - else: - fscommands.create_folder(resource_path) - except IOError, e: - raise exceptions.RopeError(e) - - -def _get_destination_for_move(resource, destination): - dest_path = resource.project._get_resource_path(destination) - if os.path.isdir(dest_path): - if destination != '': - return destination + '/' + resource.name - else: - return resource.name - return destination - - -class ChangeToData(object): - - def convertChangeSet(self, change): - description = change.description - changes = [] - for child in change.changes: - changes.append(self(child)) - return (description, changes, change.time) - - def convertChangeContents(self, change): - return (change.resource.path, change.new_contents, change.old_contents) - - def convertMoveResource(self, change): - return (change.resource.path, change.new_resource.path) - - def convertCreateResource(self, change): - return (change.resource.path, change.resource.is_folder()) - - def convertRemoveResource(self, change): - return (change.resource.path, change.resource.is_folder()) - - def __call__(self, change): - change_type = type(change) - if change_type in (CreateFolder, CreateFile): - change_type = CreateResource - method = getattr(self, 'convert' + change_type.__name__) - return (change_type.__name__, method(change)) - - -class DataToChange(object): - - def __init__(self, project): - self.project = project - - def makeChangeSet(self, description, changes, time=None): - result = ChangeSet(description, time) - for child in changes: - result.add_change(self(child)) - return result - - def makeChangeContents(self, path, new_contents, old_contents): - resource = self.project.get_file(path) - return ChangeContents(resource, new_contents, old_contents) - - def makeMoveResource(self, old_path, new_path): - resource = self.project.get_file(old_path) - return MoveResource(resource, new_path, exact=True) - - def makeCreateResource(self, path, is_folder): - if is_folder: - resource = self.project.get_folder(path) - else: - resource = self.project.get_file(path) - return CreateResource(resource) - - def makeRemoveResource(self, path, is_folder): - if is_folder: - resource = self.project.get_folder(path) - else: - resource = self.project.get_file(path) - return RemoveResource(resource) - - def __call__(self, data): - method = getattr(self, 'make' + data[0]) - return method(*data[1]) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/codeanalyze.py b/.vim/bundle/python-mode/pylibs/rope/base/codeanalyze.py @@ -1,358 +0,0 @@ -import bisect -import re -import token -import tokenize - - -class ChangeCollector(object): - - def __init__(self, text): - self.text = text - self.changes = [] - - def add_change(self, start, end, new_text=None): - if new_text is None: - new_text = self.text[start:end] - self.changes.append((start, end, new_text)) - - def get_changed(self): - if not self.changes: - return None - def compare_changes(change1, change2): - return cmp(change1[:2], change2[:2]) - self.changes.sort(compare_changes) - pieces = [] - last_changed = 0 - for change in self.changes: - start, end, text = change - pieces.append(self.text[last_changed:start] + text) - last_changed = end - if last_changed < len(self.text): - pieces.append(self.text[last_changed:]) - result = ''.join(pieces) - if result != self.text: - return result - - -class SourceLinesAdapter(object): - """Adapts source to Lines interface - - Note: The creation of this class is expensive. - """ - - def __init__(self, source_code): - self.code = source_code - self.starts = None - self._initialize_line_starts() - - def _initialize_line_starts(self): - self.starts = [] - self.starts.append(0) - try: - i = 0 - while True: - i = self.code.index('\n', i) + 1 - self.starts.append(i) - except ValueError: - pass - self.starts.append(len(self.code) + 1) - - def get_line(self, lineno): - return self.code[self.starts[lineno - 1]: - self.starts[lineno] - 1] - - def length(self): - return len(self.starts) - 1 - - def get_line_number(self, offset): - return bisect.bisect(self.starts, offset) - - def get_line_start(self, lineno): - return self.starts[lineno - 1] - - def get_line_end(self, lineno): - return self.starts[lineno] - 1 - - -class ArrayLinesAdapter(object): - - def __init__(self, lines): - self.lines = lines - - def get_line(self, line_number): - return self.lines[line_number - 1] - - def length(self): - return len(self.lines) - - -class LinesToReadline(object): - - def __init__(self, lines, start): - self.lines = lines - self.current = start - - def readline(self): - if self.current <= self.lines.length(): - self.current += 1 - return self.lines.get_line(self.current - 1) + '\n' - return '' - - def __call__(self): - return self.readline() - - -class _CustomGenerator(object): - - def __init__(self, lines): - self.lines = lines - self.in_string = '' - self.open_count = 0 - self.continuation = False - - def __call__(self): - size = self.lines.length() - result = [] - i = 1 - while i <= size: - while i <= size and not self.lines.get_line(i).strip(): - i += 1 - if i <= size: - start = i - while True: - line = self.lines.get_line(i) - self._analyze_line(line) - if not (self.continuation or self.open_count or - self.in_string) or i == size: - break - i += 1 - result.append((start, i)) - i += 1 - return result - - _main_chars = re.compile(r'[\'|"|#|\\|\[|\]|\{|\}|\(|\)]') - def _analyze_line(self, line): - char = None - for match in self._main_chars.finditer(line): - char = match.group() - i = match.start() - if char in '\'"': - if not self.in_string: - self.in_string = char - if char * 3 == line[i:i + 3]: - self.in_string = char * 3 - elif self.in_string == line[i:i + len(self.in_string)] and \ - not (i > 0 and line[i - 1] == '\\' and - not (i > 1 and line[i - 2] == '\\')): - self.in_string = '' - if self.in_string: - continue - if char == '#': - break - if char in '([{': - self.open_count += 1 - elif char in ')]}': - self.open_count -= 1 - if line and char != '#' and line.endswith('\\'): - self.continuation = True - else: - self.continuation = False - -def custom_generator(lines): - return _CustomGenerator(lines)() - - -class LogicalLineFinder(object): - - def __init__(self, lines): - self.lines = lines - - def logical_line_in(self, line_number): - indents = count_line_indents(self.lines.get_line(line_number)) - tries = 0 - while True: - block_start = get_block_start(self.lines, line_number, indents) - try: - return self._block_logical_line(block_start, line_number) - except IndentationError, e: - tries += 1 - if tries == 5: - raise e - lineno = e.lineno + block_start - 1 - indents = count_line_indents(self.lines.get_line(lineno)) - - def generate_starts(self, start_line=1, end_line=None): - for start, end in self.generate_regions(start_line, end_line): - yield start - - def generate_regions(self, start_line=1, end_line=None): - # XXX: `block_start` should be at a better position! - block_start = 1 - readline = LinesToReadline(self.lines, block_start) - shifted = start_line - block_start + 1 - try: - for start, end in self._logical_lines(readline): - real_start = start + block_start - 1 - real_start = self._first_non_blank(real_start) - if end_line is not None and real_start >= end_line: - break - real_end = end + block_start - 1 - if real_start >= start_line: - yield (real_start, real_end) - except tokenize.TokenError, e: - pass - - def _block_logical_line(self, block_start, line_number): - readline = LinesToReadline(self.lines, block_start) - shifted = line_number - block_start + 1 - region = self._calculate_logical(readline, shifted) - start = self._first_non_blank(region[0] + block_start - 1) - if region[1] is None: - end = self.lines.length() - else: - end = region[1] + block_start - 1 - return start, end - - def _calculate_logical(self, readline, line_number): - last_end = 1 - try: - for start, end in self._logical_lines(readline): - if line_number <= end: - return (start, end) - last_end = end + 1 - except tokenize.TokenError, e: - current = e.args[1][0] - return (last_end, max(last_end, current - 1)) - return (last_end, None) - - def _logical_lines(self, readline): - last_end = 1 - for current_token in tokenize.generate_tokens(readline): - current = current_token[2][0] - if current_token[0] == token.NEWLINE: - yield (last_end, current) - last_end = current + 1 - - def _first_non_blank(self, line_number): - current = line_number - while current < self.lines.length(): - line = self.lines.get_line(current).strip() - if line and not line.startswith('#'): - return current - current += 1 - return current - - -def tokenizer_generator(lines): - return LogicalLineFinder(lines).generate_regions() - - -class CachingLogicalLineFinder(object): - - def __init__(self, lines, generate=custom_generator): - self.lines = lines - self._generate = generate - - _starts = None - @property - def starts(self): - if self._starts is None: - self._init_logicals() - return self._starts - - _ends = None - @property - def ends(self): - if self._ends is None: - self._init_logicals() - return self._ends - - def _init_logicals(self): - """Should initialize _starts and _ends attributes""" - size = self.lines.length() + 1 - self._starts = [None] * size - self._ends = [None] * size - for start, end in self._generate(self.lines): - self._starts[start] = True - self._ends[end] = True - - def logical_line_in(self, line_number): - start = line_number - while start > 0 and not self.starts[start]: - start -= 1 - if start == 0: - try: - start = self.starts.index(True, line_number) - except ValueError: - return (line_number, line_number) - return (start, self.ends.index(True, start)) - - def generate_starts(self, start_line=1, end_line=None): - if end_line is None: - end_line = self.lines.length() - for index in range(start_line, end_line): - if self.starts[index]: - yield index - - -def get_block_start(lines, lineno, maximum_indents=80): - """Approximate block start""" - pattern = get_block_start_patterns() - for i in range(lineno, 0, -1): - match = pattern.search(lines.get_line(i)) - if match is not None and \ - count_line_indents(lines.get_line(i)) <= maximum_indents: - striped = match.string.lstrip() - # Maybe we're in a list comprehension or generator expression - if i > 1 and striped.startswith('if') or striped.startswith('for'): - bracs = 0 - for j in range(i, min(i + 5, lines.length() + 1)): - for c in lines.get_line(j): - if c == '#': - break - if c in '[(': - bracs += 1 - if c in ')]': - bracs -= 1 - if bracs < 0: - break - if bracs < 0: - break - if bracs < 0: - continue - return i - return 1 - - -_block_start_pattern = None - -def get_block_start_patterns(): - global _block_start_pattern - if not _block_start_pattern: - pattern = '^\\s*(((def|class|if|elif|except|for|while|with)\\s)|'\ - '((try|else|finally|except)\\s*:))' - _block_start_pattern = re.compile(pattern, re.M) - return _block_start_pattern - - -def count_line_indents(line): - indents = 0 - for char in line: - if char == ' ': - indents += 1 - elif char == '\t': - indents += 8 - else: - return indents - return 0 - - -def get_string_pattern(): - start = r'(\b[uU]?[rR]?)?' - longstr = r'%s"""(\\.|"(?!"")|\\\n|[^"\\])*"""' % start - shortstr = r'%s"(\\.|[^"\\\n])*"' % start - return '|'.join([longstr, longstr.replace('"', "'"), - shortstr, shortstr.replace('"', "'")]) - -def get_comment_pattern(): - return r'#[^\n]*' diff --git a/.vim/bundle/python-mode/pylibs/rope/base/default_config.py b/.vim/bundle/python-mode/pylibs/rope/base/default_config.py @@ -1,85 +0,0 @@ -# The default ``config.py`` - - -def set_prefs(prefs): - """This function is called before opening the project""" - - # Specify which files and folders to ignore in the project. - # Changes to ignored resources are not added to the history and - # VCSs. Also they are not returned in `Project.get_files()`. - # Note that ``?`` and ``*`` match all characters but slashes. - # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' - # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' - # '.svn': matches 'pkg/.svn' and all of its children - # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' - # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' - prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', - '.hg', '.svn', '_svn', '.git'] - - # Specifies which files should be considered python files. It is - # useful when you have scripts inside your project. Only files - # ending with ``.py`` are considered to be python files by - # default. - #prefs['python_files'] = ['*.py'] - - # Custom source folders: By default rope searches the project - # for finding source folders (folders that should be searched - # for finding modules). You can add paths to that list. Note - # that rope guesses project source folders correctly most of the - # time; use this if you have any problems. - # The folders should be relative to project root and use '/' for - # separating folders regardless of the platform rope is running on. - # 'src/my_source_folder' for instance. - #prefs.add('source_folders', 'src') - - # You can extend python path for looking up modules - #prefs.add('python_path', '~/python/') - - # Should rope save object information or not. - prefs['save_objectdb'] = True - prefs['compress_objectdb'] = False - - # If `True`, rope analyzes each module when it is being saved. - prefs['automatic_soa'] = True - # The depth of calls to follow in static object analysis - prefs['soa_followed_calls'] = 0 - - # If `False` when running modules or unit tests "dynamic object - # analysis" is turned off. This makes them much faster. - prefs['perform_doa'] = True - - # Rope can check the validity of its object DB when running. - prefs['validate_objectdb'] = True - - # How many undos to hold? - prefs['max_history_items'] = 32 - - # Shows whether to save history across sessions. - prefs['save_history'] = True - prefs['compress_history'] = False - - # Set the number spaces used for indenting. According to - # :PEP:`8`, it is best to use 4 spaces. Since most of rope's - # unit-tests use 4 spaces it is more reliable, too. - prefs['indent_size'] = 4 - - # Builtin and c-extension modules that are allowed to be imported - # and inspected by rope. - prefs['extension_modules'] = [] - - # Add all standard c-extensions to extension_modules list. - prefs['import_dynload_stdmods'] = True - - # If `True` modules with syntax errors are considered to be empty. - # The default value is `False`; When `False` syntax errors raise - # `rope.base.exceptions.ModuleSyntaxError` exception. - prefs['ignore_syntax_errors'] = False - - # If `True`, rope ignores unresolvable imports. Otherwise, they - # appear in the importing namespace. - prefs['ignore_bad_imports'] = False - - -def project_opened(project): - """This function is called after opening the project""" - # Do whatever you like here! diff --git a/.vim/bundle/python-mode/pylibs/rope/base/evaluate.py b/.vim/bundle/python-mode/pylibs/rope/base/evaluate.py @@ -1,321 +0,0 @@ -import rope.base.builtins -import rope.base.pynames -import rope.base.pyobjects -from rope.base import ast, astutils, exceptions, pyobjects, arguments, worder - - -BadIdentifierError = exceptions.BadIdentifierError - -def eval_location(pymodule, offset): - """Find the pyname at the offset""" - return eval_location2(pymodule, offset)[1] - - -def eval_location2(pymodule, offset): - """Find the primary and pyname at offset""" - pyname_finder = ScopeNameFinder(pymodule) - return pyname_finder.get_primary_and_pyname_at(offset) - - -def eval_node(scope, node): - """Evaluate a `ast.AST` node and return a PyName - - Return `None` if the expression cannot be evaluated. - """ - return eval_node2(scope, node)[1] - - -def eval_node2(scope, node): - evaluator = StatementEvaluator(scope) - ast.walk(node, evaluator) - return evaluator.old_result, evaluator.result - - -def eval_str(holding_scope, name): - return eval_str2(holding_scope, name)[1] - - -def eval_str2(holding_scope, name): - try: - # parenthesizing for handling cases like 'a_var.\nattr' - node = ast.parse('(%s)' % name) - except SyntaxError: - raise BadIdentifierError('Not a resolvable python identifier selected.') - return eval_node2(holding_scope, node) - - -class ScopeNameFinder(object): - - def __init__(self, pymodule): - self.module_scope = pymodule.get_scope() - self.lines = pymodule.lines - self.worder = worder.Worder(pymodule.source_code, True) - - def _is_defined_in_class_body(self, holding_scope, offset, lineno): - if lineno == holding_scope.get_start() and \ - holding_scope.parent is not None and \ - holding_scope.parent.get_kind() == 'Class' and \ - self.worder.is_a_class_or_function_name_in_header(offset): - return True - if lineno != holding_scope.get_start() and \ - holding_scope.get_kind() == 'Class' and \ - self.worder.is_name_assigned_in_class_body(offset): - return True - return False - - def _is_function_name_in_function_header(self, scope, offset, lineno): - if scope.get_start() <= lineno <= scope.get_body_start() and \ - scope.get_kind() == 'Function' and \ - self.worder.is_a_class_or_function_name_in_header(offset): - return True - return False - - def get_pyname_at(self, offset): - return self.get_primary_and_pyname_at(offset)[1] - - def get_primary_and_pyname_at(self, offset): - lineno = self.lines.get_line_number(offset) - holding_scope = self.module_scope.get_inner_scope_for_line(lineno) - # function keyword parameter - if self.worder.is_function_keyword_parameter(offset): - keyword_name = self.worder.get_word_at(offset) - pyobject = self.get_enclosing_function(offset) - if isinstance(pyobject, pyobjects.PyFunction): - return (None, pyobject.get_parameters().get(keyword_name, None)) - # class body - if self._is_defined_in_class_body(holding_scope, offset, lineno): - class_scope = holding_scope - if lineno == holding_scope.get_start(): - class_scope = holding_scope.parent - name = self.worder.get_primary_at(offset).strip() - try: - return (None, class_scope.pyobject[name]) - except rope.base.exceptions.AttributeNotFoundError: - return (None, None) - # function header - if self._is_function_name_in_function_header(holding_scope, offset, lineno): - name = self.worder.get_primary_at(offset).strip() - return (None, holding_scope.parent[name]) - # from statement module - if self.worder.is_from_statement_module(offset): - module = self.worder.get_primary_at(offset) - module_pyname = self._find_module(module) - return (None, module_pyname) - if self.worder.is_from_aliased(offset): - name = self.worder.get_from_aliased(offset) - else: - name = self.worder.get_primary_at(offset) - return eval_str2(holding_scope, name) - - def get_enclosing_function(self, offset): - function_parens = self.worder.find_parens_start_from_inside(offset) - try: - function_pyname = self.get_pyname_at(function_parens - 1) - except BadIdentifierError: - function_pyname = None - if function_pyname is not None: - pyobject = function_pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - return pyobject - elif isinstance(pyobject, pyobjects.AbstractClass) and \ - '__init__' in pyobject: - return pyobject['__init__'].get_object() - elif '__call__' in pyobject: - return pyobject['__call__'].get_object() - return None - - def _find_module(self, module_name): - dots = 0 - while module_name[dots] == '.': - dots += 1 - return rope.base.pynames.ImportedModule( - self.module_scope.pyobject, module_name[dots:], dots) - - -class StatementEvaluator(object): - - def __init__(self, scope): - self.scope = scope - self.result = None - self.old_result = None - - def _Name(self, node): - self.result = self.scope.lookup(node.id) - - def _Attribute(self, node): - pyname = eval_node(self.scope, node.value) - if pyname is None: - pyname = rope.base.pynames.UnboundName() - self.old_result = pyname - if pyname.get_object() != rope.base.pyobjects.get_unknown(): - try: - self.result = pyname.get_object()[node.attr] - except exceptions.AttributeNotFoundError: - self.result = None - - def _Call(self, node): - primary, pyobject = self._get_primary_and_object_for_node(node.func) - if pyobject is None: - return - def _get_returned(pyobject): - args = arguments.create_arguments(primary, pyobject, - node, self.scope) - return pyobject.get_returned_object(args) - if isinstance(pyobject, rope.base.pyobjects.AbstractClass): - result = None - if '__new__' in pyobject: - new_function = pyobject['__new__'].get_object() - result = _get_returned(new_function) - if result is None or \ - result == rope.base.pyobjects.get_unknown(): - result = rope.base.pyobjects.PyObject(pyobject) - self.result = rope.base.pynames.UnboundName(pyobject=result) - return - - pyfunction = None - if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): - pyfunction = pyobject - elif '__call__' in pyobject: - pyfunction = pyobject['__call__'].get_object() - if pyfunction is not None: - self.result = rope.base.pynames.UnboundName( - pyobject=_get_returned(pyfunction)) - - def _Str(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_str()) - - def _Num(self, node): - type_name = type(node.n).__name__ - self.result = self._get_builtin_name(type_name) - - def _get_builtin_name(self, type_name): - pytype = rope.base.builtins.builtins[type_name].get_object() - return rope.base.pynames.UnboundName( - rope.base.pyobjects.PyObject(pytype)) - - def _BinOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.left)) - - def _BoolOp(self, node): - pyobject = self._get_object_for_node(node.values[0]) - if pyobject is None: - pyobject = self._get_object_for_node(node.values[1]) - self.result = rope.base.pynames.UnboundName(pyobject) - - def _Repr(self, node): - self.result = self._get_builtin_name('str') - - def _UnaryOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.operand)) - - def _Compare(self, node): - self.result = self._get_builtin_name('bool') - - def _Dict(self, node): - keys = None - values = None - if node.keys: - keys = self._get_object_for_node(node.keys[0]) - values = self._get_object_for_node(node.values[0]) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_dict(keys, values)) - - def _List(self, node): - holding = None - if node.elts: - holding = self._get_object_for_node(node.elts[0]) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(holding)) - - def _ListComp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(pyobject)) - - def _GeneratorExp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_iterator(pyobject)) - - def _what_does_comprehension_hold(self, node): - scope = self._make_comprehension_scope(node) - pyname = eval_node(scope, node.elt) - return pyname.get_object() if pyname is not None else None - - def _make_comprehension_scope(self, node): - scope = self.scope - module = scope.pyobject.get_module() - names = {} - for comp in node.generators: - new_names = _get_evaluated_names(comp.target, comp.iter, module, - '.__iter__().next()', node.lineno) - names.update(new_names) - return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names) - - def _Tuple(self, node): - objects = [] - if len(node.elts) < 4: - for stmt in node.elts: - pyobject = self._get_object_for_node(stmt) - objects.append(pyobject) - else: - objects.append(self._get_object_for_node(node.elts[0])) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_tuple(*objects)) - - def _get_object_for_node(self, stmt): - pyname = eval_node(self.scope, stmt) - pyobject = None - if pyname is not None: - pyobject = pyname.get_object() - return pyobject - - def _get_primary_and_object_for_node(self, stmt): - primary, pyname = eval_node2(self.scope, stmt) - pyobject = None - if pyname is not None: - pyobject = pyname.get_object() - return primary, pyobject - - def _Subscript(self, node): - if isinstance(node.slice, ast.Index): - self._call_function(node.value, '__getitem__', - [node.slice.value]) - elif isinstance(node.slice, ast.Slice): - self._call_function(node.value, '__getslice__') - - def _call_function(self, node, function_name, other_args=None): - pyname = eval_node(self.scope, node) - if pyname is not None: - pyobject = pyname.get_object() - else: - return - if function_name in pyobject: - called = pyobject[function_name].get_object() - if not called or not isinstance(called, pyobjects.AbstractFunction): - return - args = [node] - if other_args: - args += other_args - arguments_ = arguments.Arguments(args, self.scope) - self.result = rope.base.pynames.UnboundName( - pyobject=called.get_returned_object(arguments_)) - - def _Lambda(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.Lambda(node, self.scope)) - - -def _get_evaluated_names(targets, assigned, module, evaluation, lineno): - result = {} - for name, levels in astutils.get_name_levels(targets): - assignment = rope.base.pynames.AssignmentValue(assigned, levels, - evaluation) - # XXX: this module should not access `rope.base.pynamesdef`! - pyname = rope.base.pynamesdef.AssignedName(lineno, module) - pyname.assignments.append(assignment) - result[name] = pyname - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/base/exceptions.py b/.vim/bundle/python-mode/pylibs/rope/base/exceptions.py @@ -1,61 +0,0 @@ -class RopeError(Exception): - """Base exception for rope""" - - -class ResourceNotFoundError(RopeError): - """Resource not found exception""" - - -class RefactoringError(RopeError): - """Errors for performing a refactoring""" - - -class InterruptedTaskError(RopeError): - """The task has been interrupted""" - - -class HistoryError(RopeError): - """Errors for history undo/redo operations""" - - -class ModuleNotFoundError(RopeError): - """Module not found exception""" - - -class AttributeNotFoundError(RopeError): - """Attribute not found exception""" - - -class NameNotFoundError(RopeError): - """Name not found exception""" - - -class BadIdentifierError(RopeError): - """The name cannot be resolved""" - - -class ModuleSyntaxError(RopeError): - """Module has syntax errors - - The `filename` and `lineno` fields indicate where the error has - occurred. - - """ - - def __init__(self, filename, lineno, message): - self.filename = filename - self.lineno = lineno - self.message_ = message - super(ModuleSyntaxError, self).__init__( - 'Syntax error in file <%s> line <%s>: %s' % - (filename, lineno, message)) - - -class ModuleDecodeError(RopeError): - """Cannot decode module""" - - def __init__(self, filename, message): - self.filename = filename - self.message_ = message - super(ModuleDecodeError, self).__init__( - 'Cannot decode file <%s>: %s' % (filename, message)) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/fscommands.py b/.vim/bundle/python-mode/pylibs/rope/base/fscommands.py @@ -1,267 +0,0 @@ -"""Project file system commands. - -This modules implements file system operations used by rope. Different -version control systems can be supported by implementing the interface -provided by `FileSystemCommands` class. See `SubversionCommands` and -`MercurialCommands` for example. - -""" -import os -import shutil -import subprocess - - -def create_fscommands(root): - dirlist = os.listdir(root) - commands = {'.hg': MercurialCommands, - '.svn': SubversionCommands, - '.git': GITCommands, - '_svn': SubversionCommands, - '_darcs': DarcsCommands} - for key in commands: - if key in dirlist: - try: - return commands[key](root) - except (ImportError, OSError): - pass - return FileSystemCommands() - - -class FileSystemCommands(object): - - def create_file(self, path): - open(path, 'w').close() - - def create_folder(self, path): - os.mkdir(path) - - def move(self, path, new_location): - shutil.move(path, new_location) - - def remove(self, path): - if os.path.isfile(path): - os.remove(path) - else: - shutil.rmtree(path) - - def write(self, path, data): - file_ = open(path, 'wb') - try: - file_.write(data) - finally: - file_.close() - - -class SubversionCommands(object): - - def __init__(self, *args): - self.normal_actions = FileSystemCommands() - import pysvn - self.client = pysvn.Client() - - def create_file(self, path): - self.normal_actions.create_file(path) - self.client.add(path, force=True) - - def create_folder(self, path): - self.normal_actions.create_folder(path) - self.client.add(path, force=True) - - def move(self, path, new_location): - self.client.move(path, new_location, force=True) - - def remove(self, path): - self.client.remove(path, force=True) - - def write(self, path, data): - self.normal_actions.write(path, data) - - -class MercurialCommands(object): - - def __init__(self, root): - self.hg = self._import_mercurial() - self.normal_actions = FileSystemCommands() - try: - self.ui = self.hg.ui.ui( - verbose=False, debug=False, quiet=True, - interactive=False, traceback=False, report_untrusted=False) - except: - self.ui = self.hg.ui.ui() - self.ui.setconfig('ui', 'interactive', 'no') - self.ui.setconfig('ui', 'debug', 'no') - self.ui.setconfig('ui', 'traceback', 'no') - self.ui.setconfig('ui', 'verbose', 'no') - self.ui.setconfig('ui', 'report_untrusted', 'no') - self.ui.setconfig('ui', 'quiet', 'yes') - - self.repo = self.hg.hg.repository(self.ui, root) - - def _import_mercurial(self): - import mercurial.commands - import mercurial.hg - import mercurial.ui - return mercurial - - def create_file(self, path): - self.normal_actions.create_file(path) - self.hg.commands.add(self.ui, self.repo, path) - - def create_folder(self, path): - self.normal_actions.create_folder(path) - - def move(self, path, new_location): - self.hg.commands.rename(self.ui, self.repo, path, - new_location, after=False) - - def remove(self, path): - self.hg.commands.remove(self.ui, self.repo, path) - - def write(self, path, data): - self.normal_actions.write(path, data) - - -class GITCommands(object): - - def __init__(self, root): - self.root = root - self._do(['version']) - self.normal_actions = FileSystemCommands() - - def create_file(self, path): - self.normal_actions.create_file(path) - self._do(['add', self._in_dir(path)]) - - def create_folder(self, path): - self.normal_actions.create_folder(path) - - def move(self, path, new_location): - self._do(['mv', self._in_dir(path), self._in_dir(new_location)]) - - def remove(self, path): - self._do(['rm', self._in_dir(path)]) - - def write(self, path, data): - # XXX: should we use ``git add``? - self.normal_actions.write(path, data) - - def _do(self, args): - _execute(['git'] + args, cwd=self.root) - - def _in_dir(self, path): - if path.startswith(self.root): - return path[len(self.root) + 1:] - return self.root - - -class DarcsCommands(object): - - def __init__(self, root): - self.root = root - self.normal_actions = FileSystemCommands() - - def create_file(self, path): - self.normal_actions.create_file(path) - self._do(['add', path]) - - def create_folder(self, path): - self.normal_actions.create_folder(path) - self._do(['add', path]) - - def move(self, path, new_location): - self._do(['mv', path, new_location]) - - def remove(self, path): - self.normal_actions.remove(path) - - def write(self, path, data): - self.normal_actions.write(path, data) - - def _do(self, args): - _execute(['darcs'] + args, cwd=self.root) - - -def _execute(args, cwd=None): - process = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE) - process.wait() - return process.returncode - - -def unicode_to_file_data(contents, encoding=None): - if not isinstance(contents, unicode): - return contents - if encoding is None: - encoding = read_str_coding(contents) - if encoding is not None: - return contents.encode(encoding) - try: - return contents.encode() - except UnicodeEncodeError: - return contents.encode('utf-8') - -def file_data_to_unicode(data, encoding=None): - result = _decode_data(data, encoding) - if '\r' in result: - result = result.replace('\r\n', '\n').replace('\r', '\n') - return result - -def _decode_data(data, encoding): - if isinstance(data, unicode): - return data - if encoding is None: - encoding = read_str_coding(data) - if encoding is None: - # there is no encoding tip, we need to guess. - # PEP263 says that "encoding not explicitly defined" means it is ascii, - # but we will use utf8 instead since utf8 fully covers ascii and btw is - # the only non-latin sane encoding. - encoding = 'utf-8' - try: - return data.decode(encoding) - except (UnicodeError, LookupError): - # fallback to latin1: it should never fail - return data.decode('latin1') - - -def read_file_coding(path): - file = open(path, 'b') - count = 0 - result = [] - buffsize = 10 - while True: - current = file.read(10) - if not current: - break - count += current.count('\n') - result.append(current) - file.close() - return _find_coding(''.join(result)) - - -def read_str_coding(source): - try: - first = source.index('\n') + 1 - second = source.index('\n', first) + 1 - except ValueError: - second = len(source) - return _find_coding(source[:second]) - - -def _find_coding(text): - coding = 'coding' - try: - start = text.index(coding) + len(coding) - if text[start] not in '=:': - return - start += 1 - while start < len(text) and text[start].isspace(): - start += 1 - end = start - while end < len(text): - c = text[end] - if not c.isalnum() and c not in '-_': - break - end += 1 - return text[start:end] - except ValueError: - pass diff --git a/.vim/bundle/python-mode/pylibs/rope/base/history.py b/.vim/bundle/python-mode/pylibs/rope/base/history.py @@ -1,235 +0,0 @@ -from rope.base import exceptions, change, taskhandle - - -class History(object): - """A class that holds project history""" - - def __init__(self, project, maxundos=None): - self.project = project - self._undo_list = [] - self._redo_list = [] - self._maxundos = maxundos - self._load_history() - self.project.data_files.add_write_hook(self.write) - self.current_change = None - - def _load_history(self): - if self.save: - result = self.project.data_files.read_data( - 'history', compress=self.compress, import_=True) - if result is not None: - to_change = change.DataToChange(self.project) - for data in result[0]: - self._undo_list.append(to_change(data)) - for data in result[1]: - self._redo_list.append(to_change(data)) - - def do(self, changes, task_handle=taskhandle.NullTaskHandle()): - """Perform the change and add it to the `self.undo_list` - - Note that uninteresting changes (changes to ignored files) - will not be appended to `self.undo_list`. - - """ - try: - self.current_change = changes - changes.do(change.create_job_set(task_handle, changes)) - finally: - self.current_change = None - if self._is_change_interesting(changes): - self.undo_list.append(changes) - self._remove_extra_items() - del self.redo_list[:] - - def _remove_extra_items(self): - if len(self.undo_list) > self.max_undos: - del self.undo_list[0:len(self.undo_list) - self.max_undos] - - def _is_change_interesting(self, changes): - for resource in changes.get_changed_resources(): - if not self.project.is_ignored(resource): - return True - return False - - def undo(self, change=None, drop=False, - task_handle=taskhandle.NullTaskHandle()): - """Redo done changes from the history - - When `change` is `None`, the last done change will be undone. - If change is not `None` it should be an item from - `self.undo_list`; this change and all changes that depend on - it will be undone. In both cases the list of undone changes - will be returned. - - If `drop` is `True`, the undone change will not be appended to - the redo list. - - """ - if not self._undo_list: - raise exceptions.HistoryError('Undo list is empty') - if change is None: - change = self.undo_list[-1] - dependencies = self._find_dependencies(self.undo_list, change) - self._move_front(self.undo_list, dependencies) - self._perform_undos(len(dependencies), task_handle) - result = self.redo_list[-len(dependencies):] - if drop: - del self.redo_list[-len(dependencies):] - return result - - def redo(self, change=None, task_handle=taskhandle.NullTaskHandle()): - """Redo undone changes from the history - - When `change` is `None`, the last undone change will be - redone. If change is not `None` it should be an item from - `self.redo_list`; this change and all changes that depend on - it will be redone. In both cases the list of redone changes - will be returned. - - """ - if not self.redo_list: - raise exceptions.HistoryError('Redo list is empty') - if change is None: - change = self.redo_list[-1] - dependencies = self._find_dependencies(self.redo_list, change) - self._move_front(self.redo_list, dependencies) - self._perform_redos(len(dependencies), task_handle) - return self.undo_list[-len(dependencies):] - - def _move_front(self, change_list, changes): - for change in changes: - change_list.remove(change) - change_list.append(change) - - def _find_dependencies(self, change_list, change): - index = change_list.index(change) - return _FindChangeDependencies(change_list[index:])() - - def _perform_undos(self, count, task_handle): - for i in range(count): - self.current_change = self.undo_list[-1] - try: - job_set = change.create_job_set(task_handle, - self.current_change) - self.current_change.undo(job_set) - finally: - self.current_change = None - self.redo_list.append(self.undo_list.pop()) - - def _perform_redos(self, count, task_handle): - for i in range(count): - self.current_change = self.redo_list[-1] - try: - job_set = change.create_job_set(task_handle, - self.current_change) - self.current_change.do(job_set) - finally: - self.current_change = None - self.undo_list.append(self.redo_list.pop()) - - def contents_before_current_change(self, file): - if self.current_change is None: - return None - result = self._search_for_change_contents([self.current_change], file) - if result is not None: - return result - if file.exists() and not file.is_folder(): - return file.read() - else: - return None - - def _search_for_change_contents(self, change_list, file): - for change_ in reversed(change_list): - if isinstance(change_, change.ChangeSet): - result = self._search_for_change_contents(change_.changes, - file) - if result is not None: - return result - if isinstance(change_, change.ChangeContents) and \ - change_.resource == file: - return change_.old_contents - - def write(self): - if self.save: - data = [] - to_data = change.ChangeToData() - self._remove_extra_items() - data.append([to_data(change_) for change_ in self.undo_list]) - data.append([to_data(change_) for change_ in self.redo_list]) - self.project.data_files.write_data('history', data, - compress=self.compress) - - def get_file_undo_list(self, resource): - result = [] - for change in self.undo_list: - if resource in change.get_changed_resources(): - result.append(change) - return result - - def __str__(self): - return 'History holds %s changes in memory' % \ - (len(self.undo_list) + len(self.redo_list)) - - undo_list = property(lambda self: self._undo_list) - redo_list = property(lambda self: self._redo_list) - - @property - def tobe_undone(self): - """The last done change if available, `None` otherwise""" - if self.undo_list: - return self.undo_list[-1] - - @property - def tobe_redone(self): - """The last undone change if available, `None` otherwise""" - if self.redo_list: - return self.redo_list[-1] - - @property - def max_undos(self): - if self._maxundos is None: - return self.project.prefs.get('max_history_items', 100) - else: - return self._maxundos - - @property - def save(self): - return self.project.prefs.get('save_history', False) - - @property - def compress(self): - return self.project.prefs.get('compress_history', False) - - def clear(self): - """Forget all undo and redo information""" - del self.undo_list[:] - del self.redo_list[:] - - -class _FindChangeDependencies(object): - - def __init__(self, change_list): - self.change = change_list[0] - self.change_list = change_list - self.changed_resources = set(self.change.get_changed_resources()) - - def __call__(self): - result = [self.change] - for change in self.change_list[1:]: - if self._depends_on(change, result): - result.append(change) - self.changed_resources.update(change.get_changed_resources()) - return result - - def _depends_on(self, changes, result): - for resource in changes.get_changed_resources(): - if resource is None: - continue - if resource in self.changed_resources: - return True - for changed in self.changed_resources: - if resource.is_folder() and resource.contains(changed): - return True - if changed.is_folder() and changed.contains(resource): - return True - return False diff --git a/.vim/bundle/python-mode/pylibs/rope/base/libutils.py b/.vim/bundle/python-mode/pylibs/rope/base/libutils.py @@ -1,65 +0,0 @@ -"""A few useful functions for using rope as a library""" -import os.path - -import rope.base.project -import rope.base.pycore -from rope.base import taskhandle - - -def path_to_resource(project, path, type=None): - """Get the resource at path - - You only need to specify `type` if `path` does not exist. It can - be either 'file' or 'folder'. If the type is `None` it is assumed - that the resource already exists. - - Note that this function uses `Project.get_resource()`, - `Project.get_file()`, and `Project.get_folder()` methods. - - """ - project_path = relative(project.address, path) - if project_path is None: - project_path = rope.base.project._realpath(path) - project = rope.base.project.get_no_project() - if type is None: - return project.get_resource(project_path) - if type == 'file': - return project.get_file(project_path) - if type == 'folder': - return project.get_folder(project_path) - return None - -def relative(root, path): - root = rope.base.project._realpath(root).replace(os.path.sep, '/') - path = rope.base.project._realpath(path).replace(os.path.sep, '/') - if path == root: - return '' - if path.startswith(root + '/'): - return path[len(root) + 1:] - -def report_change(project, path, old_content): - """Report that the contents of file at `path` was changed - - The new contents of file is retrieved by reading the file. - - """ - resource = path_to_resource(project, path) - if resource is None: - return - for observer in list(project.observers): - observer.resource_changed(resource) - if project.pycore.automatic_soa: - rope.base.pycore.perform_soa_on_changed_scopes(project, resource, - old_content) - -def analyze_modules(project, task_handle=taskhandle.NullTaskHandle()): - """Perform static object analysis on all python files in the project - - Note that this might be really time consuming. - """ - resources = project.pycore.get_python_files() - job_set = task_handle.create_jobset('Analyzing Modules', len(resources)) - for resource in resources: - job_set.started_job(resource.path) - project.pycore.analyze_module(resource) - job_set.finished_job() diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/__init__.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/__init__.py @@ -1,38 +0,0 @@ -"""Rope object analysis and inference package - -Rope makes some simplifying assumptions about a python program. It -assumes that a program only performs assignments and function calls. -Tracking assignments is simple and `PyName` objects handle that. The -main problem is function calls. Rope uses these two approaches for -obtaining call information: - -* Static object analysis: `rope.base.pycore.PyCore.analyze_module()` - - It can analyze modules to obtain information about functions. This - is done by analyzing function calls in a module or scope. Currently - SOA analyzes the scopes that are changed while saving or when the - user asks to analyze a module. That is mainly because static - analysis is time-consuming. - -* Dynamic object analysis: `rope.base.pycore.PyCore.run_module()` - - When you run a module or your testsuite, when DOA is enabled, it - collects information about parameters passed to and objects returned - from functions. The main problem with this approach is that it is - quite slow; Not when looking up the information but when collecting - them. - -An instance of `rope.base.oi.objectinfo.ObjectInfoManager` can be used -for accessing these information. It saves the data in a -`rope.base.oi.objectdb.ObjectDB` internally. - -Now if our objectdb does not know anything about a function and we -need the value returned by it, static object inference, SOI, comes -into play. It analyzes function body and tries to infer the object -that is returned from it (we usually need the returned value for the -given parameter objects). - -Rope might collect and store information for other `PyName`\s, too. -For instance rope stores the object builtin containers hold. - -""" diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/doa.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/doa.py @@ -1,162 +0,0 @@ -import cPickle as pickle -import marshal -import os -import socket -import subprocess -import sys -import tempfile -import threading - - -class PythonFileRunner(object): - """A class for running python project files""" - - def __init__(self, pycore, file_, args=None, stdin=None, - stdout=None, analyze_data=None): - self.pycore = pycore - self.file = file_ - self.analyze_data = analyze_data - self.observers = [] - self.args = args - self.stdin = stdin - self.stdout = stdout - - def run(self): - """Execute the process""" - env = dict(os.environ) - file_path = self.file.real_path - path_folders = self.pycore.get_source_folders() + \ - self.pycore.get_python_path_folders() - env['PYTHONPATH'] = os.pathsep.join(folder.real_path - for folder in path_folders) - runmod_path = self.pycore.find_module('rope.base.oi.runmod').real_path - self.receiver = None - self._init_data_receiving() - send_info = '-' - if self.receiver: - send_info = self.receiver.get_send_info() - args = [sys.executable, runmod_path, send_info, - self.pycore.project.address, self.file.real_path] - if self.analyze_data is None: - del args[1:4] - if self.args is not None: - args.extend(self.args) - self.process = subprocess.Popen( - executable=sys.executable, args=args, env=env, - cwd=os.path.split(file_path)[0], stdin=self.stdin, - stdout=self.stdout, stderr=self.stdout, close_fds=os.name != 'nt') - - def _init_data_receiving(self): - if self.analyze_data is None: - return - # Disabling FIFO data transfer due to blocking when running - # unittests in the GUI. - # XXX: Handle FIFO data transfer for `rope.ui.testview` - if True or os.name == 'nt': - self.receiver = _SocketReceiver() - else: - self.receiver = _FIFOReceiver() - self.receiving_thread = threading.Thread(target=self._receive_information) - self.receiving_thread.setDaemon(True) - self.receiving_thread.start() - - def _receive_information(self): - #temp = open('/dev/shm/info', 'w') - for data in self.receiver.receive_data(): - self.analyze_data(data) - #temp.write(str(data) + '\n') - #temp.close() - for observer in self.observers: - observer() - - def wait_process(self): - """Wait for the process to finish""" - self.process.wait() - if self.analyze_data: - self.receiving_thread.join() - - def kill_process(self): - """Stop the process""" - if self.process.poll() is not None: - return - try: - if hasattr(self.process, 'terminate'): - self.process.terminate() - elif os.name != 'nt': - os.kill(self.process.pid, 9) - else: - import ctypes - handle = int(self.process._handle) - ctypes.windll.kernel32.TerminateProcess(handle, -1) - except OSError: - pass - - def add_finishing_observer(self, observer): - """Notify this observer when execution finishes""" - self.observers.append(observer) - - -class _MessageReceiver(object): - - def receive_data(self): - pass - - def get_send_info(self): - pass - - -class _SocketReceiver(_MessageReceiver): - - def __init__(self): - self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.data_port = 3037 - while self.data_port < 4000: - try: - self.server_socket.bind(('', self.data_port)) - break - except socket.error, e: - self.data_port += 1 - self.server_socket.listen(1) - - def get_send_info(self): - return str(self.data_port) - - def receive_data(self): - conn, addr = self.server_socket.accept() - self.server_socket.close() - my_file = conn.makefile('r') - while True: - try: - yield pickle.load(my_file) - except EOFError: - break - my_file.close() - conn.close() - - -class _FIFOReceiver(_MessageReceiver): - - def __init__(self): - # XXX: this is insecure and might cause race conditions - self.file_name = self._get_file_name() - os.mkfifo(self.file_name) - - def _get_file_name(self): - prefix = tempfile.gettempdir() + '/__rope_' - i = 0 - while os.path.exists(prefix + str(i).rjust(4, '0')): - i += 1 - return prefix + str(i).rjust(4, '0') - - def get_send_info(self): - return self.file_name - - def receive_data(self): - my_file = open(self.file_name, 'rb') - while True: - try: - yield marshal.load(my_file) - except EOFError: - break - my_file.close() - os.remove(self.file_name) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/memorydb.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/memorydb.py @@ -1,106 +0,0 @@ -from rope.base.oi import objectdb - - -class MemoryDB(objectdb.FileDict): - - def __init__(self, project, persist=None): - self.project = project - self._persist = persist - self.files = self - self._load_files() - self.project.data_files.add_write_hook(self.write) - - def _load_files(self): - self._files = {} - if self.persist: - result = self.project.data_files.read_data( - 'objectdb', compress=self.compress, import_=True) - if result is not None: - self._files = result - - def keys(self): - return self._files.keys() - - def __contains__(self, key): - return key in self._files - - def __getitem__(self, key): - return FileInfo(self._files[key]) - - def create(self, path): - self._files[path] = {} - - def rename(self, file, newfile): - if file not in self._files: - return - self._files[newfile] = self._files[file] - del self[file] - - def __delitem__(self, file): - del self._files[file] - - def write(self): - if self.persist: - self.project.data_files.write_data('objectdb', self._files, - self.compress) - - @property - def compress(self): - return self.project.prefs.get('compress_objectdb', False) - - @property - def persist(self): - if self._persist is not None: - return self._persist - else: - return self.project.prefs.get('save_objectdb', False) - - -class FileInfo(objectdb.FileInfo): - - def __init__(self, scopes): - self.scopes = scopes - - def create_scope(self, key): - self.scopes[key] = ScopeInfo() - - def keys(self): - return self.scopes.keys() - - def __contains__(self, key): - return key in self.scopes - - def __getitem__(self, key): - return self.scopes[key] - - def __delitem__(self, key): - del self.scopes[key] - - -class ScopeInfo(objectdb.ScopeInfo): - - def __init__(self): - self.call_info = {} - self.per_name = {} - - def get_per_name(self, name): - return self.per_name.get(name, None) - - def save_per_name(self, name, value): - self.per_name[name] = value - - def get_returned(self, parameters): - return self.call_info.get(parameters, None) - - def get_call_infos(self): - for args, returned in self.call_info.items(): - yield objectdb.CallInfo(args, returned) - - def add_call(self, parameters, returned): - self.call_info[parameters] = returned - - def __getstate__(self): - return (self.call_info, self.per_name) - - def __setstate__(self, data): - self.call_info, self.per_name = data diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/objectdb.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/objectdb.py @@ -1,175 +0,0 @@ -import UserDict - - -class ObjectDB(object): - - def __init__(self, db, validation): - self.db = db - self.validation = validation - self.observers = [] - self.files = db.files - - def validate_files(self): - for file in list(self.files): - if not self.validation.is_file_valid(file): - del self.files[file] - self._file_removed(file) - - def validate_file(self, file): - if file not in self.files: - return - for key in list(self.files[file]): - if not self.validation.is_scope_valid(file, key): - del self.files[file][key] - - def file_moved(self, file, newfile): - if file not in self.files: - return - self.files.rename(file, newfile) - self._file_removed(file) - self._file_added(newfile) - - def get_files(self): - return self.files.keys() - - def get_returned(self, path, key, args): - scope_info = self._get_scope_info(path, key, readonly=True) - result = scope_info.get_returned(args) - if self.validation.is_value_valid(result): - return result - - def get_pername(self, path, key, name): - scope_info = self._get_scope_info(path, key, readonly=True) - result = scope_info.get_per_name(name) - if self.validation.is_value_valid(result): - return result - - def get_callinfos(self, path, key): - scope_info = self._get_scope_info(path, key, readonly=True) - return scope_info.get_call_infos() - - def add_callinfo(self, path, key, args, returned): - scope_info = self._get_scope_info(path, key, readonly=False) - old_returned = scope_info.get_returned(args) - if self.validation.is_more_valid(returned, old_returned): - scope_info.add_call(args, returned) - - def add_pername(self, path, key, name, value): - scope_info = self._get_scope_info(path, key, readonly=False) - old_value = scope_info.get_per_name(name) - if self.validation.is_more_valid(value, old_value): - scope_info.save_per_name(name, value) - - def add_file_list_observer(self, observer): - self.observers.append(observer) - - def write(self): - self.db.write() - - def _get_scope_info(self, path, key, readonly=True): - if path not in self.files: - if readonly: - return _NullScopeInfo() - self.files.create(path) - self._file_added(path) - if key not in self.files[path]: - if readonly: - return _NullScopeInfo() - self.files[path].create_scope(key) - result = self.files[path][key] - if isinstance(result, dict): - print self.files, self.files[path], self.files[path][key] - return result - - def _file_removed(self, path): - for observer in self.observers: - observer.removed(path) - - def _file_added(self, path): - for observer in self.observers: - observer.added(path) - - def __str__(self): - scope_count = 0 - for file_dict in self.files.values(): - scope_count += len(file_dict) - return 'ObjectDB holds %s file and %s scope infos' % \ - (len(self.files), scope_count) - - -class _NullScopeInfo(object): - - def __init__(self, error_on_write=True): - self.error_on_write = error_on_write - - def get_per_name(self, name): - pass - - def save_per_name(self, name, value): - if self.error_on_write: - raise NotImplementedError() - - def get_returned(self, parameters): - pass - - def get_call_infos(self): - return [] - - def add_call(self, parameters, returned): - if self.error_on_write: - raise NotImplementedError() - - -class FileInfo(UserDict.DictMixin): - - def create_scope(self, key): - pass - - -class FileDict(UserDict.DictMixin): - - def create(self, key): - pass - - def rename(self, key, new_key): - pass - - -class ScopeInfo(object): - - def get_per_name(self, name): - pass - - def save_per_name(self, name, value): - pass - - def get_returned(self, parameters): - pass - - def get_call_infos(self): - pass - - def add_call(self, parameters, returned): - pass - - -class CallInfo(object): - - def __init__(self, args, returned): - self.args = args - self.returned = returned - - def get_parameters(self): - return self.args - - def get_returned(self): - return self.returned - - -class FileListObserver(object): - - def added(self, path): - pass - - def removed(self, path): - pass diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/objectinfo.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/objectinfo.py @@ -1,232 +0,0 @@ -import warnings - -from rope.base import exceptions, resourceobserver -from rope.base.oi import objectdb, memorydb, transform - - -class ObjectInfoManager(object): - """Stores object information - - It uses an instance of `objectdb.ObjectDB` for storing - information. - - """ - - def __init__(self, project): - self.project = project - self.to_textual = transform.PyObjectToTextual(project) - self.to_pyobject = transform.TextualToPyObject(project) - self.doi_to_pyobject = transform.DOITextualToPyObject(project) - self._init_objectdb() - if project.prefs.get('validate_objectdb', False): - self._init_validation() - - def _init_objectdb(self): - dbtype = self.project.get_prefs().get('objectdb_type', None) - persist = None - if dbtype is not None: - warnings.warn( - '"objectdb_type" project config is deprecated;\n' - 'Use "save_objectdb" instead in your project ' - 'config file.\n(".ropeproject/config.py" by default)\n', - DeprecationWarning) - if dbtype != 'memory' and self.project.ropefolder is not None: - persist = True - self.validation = TextualValidation(self.to_pyobject) - db = memorydb.MemoryDB(self.project, persist=persist) - self.objectdb = objectdb.ObjectDB(db, self.validation) - - def _init_validation(self): - self.objectdb.validate_files() - observer = resourceobserver.ResourceObserver( - changed=self._resource_changed, moved=self._resource_moved, - removed=self._resource_moved) - files = [] - for path in self.objectdb.get_files(): - resource = self.to_pyobject.path_to_resource(path) - if resource is not None and resource.project == self.project: - files.append(resource) - self.observer = resourceobserver.FilteredResourceObserver(observer, - files) - self.objectdb.add_file_list_observer(_FileListObserver(self)) - self.project.add_observer(self.observer) - - def _resource_changed(self, resource): - try: - self.objectdb.validate_file( - self.to_textual.resource_to_path(resource)) - except exceptions.ModuleSyntaxError: - pass - - def _resource_moved(self, resource, new_resource=None): - self.observer.remove_resource(resource) - if new_resource is not None: - old = self.to_textual.resource_to_path(resource) - new = self.to_textual.resource_to_path(new_resource) - self.objectdb.file_moved(old, new) - self.observer.add_resource(new_resource) - - def get_returned(self, pyobject, args): - result = self.get_exact_returned(pyobject, args) - if result is not None: - return result - path, key = self._get_scope(pyobject) - if path is None: - return None - for call_info in self.objectdb.get_callinfos(path, key): - returned = call_info.get_returned() - if returned and returned[0] not in ('unknown', 'none'): - result = returned - break - if result is None: - result = returned - if result is not None: - return self.to_pyobject(result) - - def get_exact_returned(self, pyobject, args): - path, key = self._get_scope(pyobject) - if path is not None: - returned = self.objectdb.get_returned( - path, key, self._args_to_textual(pyobject, args)) - if returned is not None: - return self.to_pyobject(returned) - - def _args_to_textual(self, pyfunction, args): - parameters = list(pyfunction.get_param_names(special_args=False)) - arguments = args.get_arguments(parameters)[:len(parameters)] - textual_args = tuple([self.to_textual(arg) - for arg in arguments]) - return textual_args - - def get_parameter_objects(self, pyobject): - path, key = self._get_scope(pyobject) - if path is None: - return None - arg_count = len(pyobject.get_param_names(special_args=False)) - unknowns = arg_count - parameters = [None] * arg_count - for call_info in self.objectdb.get_callinfos(path, key): - args = call_info.get_parameters() - for index, arg in enumerate(args[:arg_count]): - old = parameters[index] - if self.validation.is_more_valid(arg, old): - parameters[index] = arg - if self.validation.is_value_valid(arg): - unknowns -= 1 - if unknowns == 0: - break - if unknowns < arg_count: - return [self.to_pyobject(parameter) - for parameter in parameters] - - def get_passed_objects(self, pyfunction, parameter_index): - path, key = self._get_scope(pyfunction) - if path is None: - return [] - result = [] - for call_info in self.objectdb.get_callinfos(path, key): - args = call_info.get_parameters() - if len(args) > parameter_index: - parameter = self.to_pyobject(args[parameter_index]) - if parameter is not None: - result.append(parameter) - return result - - def doa_data_received(self, data): - def doi_to_normal(textual): - pyobject = self.doi_to_pyobject(textual) - return self.to_textual(pyobject) - function = doi_to_normal(data[0]) - args = tuple([doi_to_normal(textual) for textual in data[1]]) - returned = doi_to_normal(data[2]) - if function[0] == 'defined' and len(function) == 3: - self._save_data(function, args, returned) - - def function_called(self, pyfunction, params, returned=None): - function_text = self.to_textual(pyfunction) - params_text = tuple([self.to_textual(param) - for param in params]) - returned_text = ('unknown',) - if returned is not None: - returned_text = self.to_textual(returned) - self._save_data(function_text, params_text, returned_text) - - def save_per_name(self, scope, name, data): - path, key = self._get_scope(scope.pyobject) - if path is not None: - self.objectdb.add_pername(path, key, name, self.to_textual(data)) - - def get_per_name(self, scope, name): - path, key = self._get_scope(scope.pyobject) - if path is not None: - result = self.objectdb.get_pername(path, key, name) - if result is not None: - return self.to_pyobject(result) - - def _save_data(self, function, args, returned=('unknown',)): - self.objectdb.add_callinfo(function[1], function[2], args, returned) - - def _get_scope(self, pyobject): - resource = pyobject.get_module().get_resource() - if resource is None: - return None, None - textual = self.to_textual(pyobject) - if textual[0] == 'defined': - path = textual[1] - if len(textual) == 3: - key = textual[2] - else: - key = '' - return path, key - return None, None - - def sync(self): - self.objectdb.sync() - - def __str__(self): - return str(self.objectdb) - - -class TextualValidation(object): - - def __init__(self, to_pyobject): - self.to_pyobject = to_pyobject - - def is_value_valid(self, value): - # ???: Should none and unknown be considered valid? - if value is None or value[0] in ('none', 'unknown'): - return False - return self.to_pyobject(value) is not None - - def is_more_valid(self, new, old): - if old is None: - return True - return new[0] not in ('unknown', 'none') - - def is_file_valid(self, path): - return self.to_pyobject.path_to_resource(path) is not None - - def is_scope_valid(self, path, key): - if key == '': - textual = ('defined', path) - else: - textual = ('defined', path, key) - return self.to_pyobject(textual) is not None - - -class _FileListObserver(object): - - def __init__(self, object_info): - self.object_info = object_info - self.observer = self.object_info.observer - self.to_pyobject = self.object_info.to_pyobject - - def removed(self, path): - resource = self.to_pyobject.path_to_resource(path) - if resource is not None: - self.observer.remove_resource(resource) - - def added(self, path): - resource = self.to_pyobject.path_to_resource(path) - if resource is not None: - self.observer.add_resource(resource) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/runmod.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/runmod.py @@ -1,211 +0,0 @@ - -def __rope_start_everything(): - import os - import sys - import socket - import cPickle as pickle - import marshal - import inspect - import types - import threading - - class _MessageSender(object): - - def send_data(self, data): - pass - - class _SocketSender(_MessageSender): - - def __init__(self, port): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect(('127.0.0.1', port)) - self.my_file = s.makefile('w') - - def send_data(self, data): - if not self.my_file.closed: - pickle.dump(data, self.my_file) - - def close(self): - self.my_file.close() - - class _FileSender(_MessageSender): - - def __init__(self, file_name): - self.my_file = open(file_name, 'wb') - - def send_data(self, data): - if not self.my_file.closed: - marshal.dump(data, self.my_file) - - def close(self): - self.my_file.close() - - - def _cached(func): - cache = {} - def newfunc(self, arg): - if arg in cache: - return cache[arg] - result = func(self, arg) - cache[arg] = result - return result - return newfunc - - class _FunctionCallDataSender(object): - - def __init__(self, send_info, project_root): - self.project_root = project_root - if send_info.isdigit(): - self.sender = _SocketSender(int(send_info)) - else: - self.sender = _FileSender(send_info) - - def global_trace(frame, event, arg): - # HACK: Ignoring out->in calls - # This might lose some information - if self._is_an_interesting_call(frame): - return self.on_function_call - sys.settrace(global_trace) - threading.settrace(global_trace) - - def on_function_call(self, frame, event, arg): - if event != 'return': - return - args = [] - returned = ('unknown',) - code = frame.f_code - for argname in code.co_varnames[:code.co_argcount]: - try: - args.append(self._object_to_persisted_form(frame.f_locals[argname])) - except (TypeError, AttributeError): - args.append(('unknown',)) - try: - returned = self._object_to_persisted_form(arg) - except (TypeError, AttributeError): - pass - try: - data = (self._object_to_persisted_form(frame.f_code), - tuple(args), returned) - self.sender.send_data(data) - except (TypeError): - pass - return self.on_function_call - - def _is_an_interesting_call(self, frame): - #if frame.f_code.co_name in ['?', '<module>']: - # return False - #return not frame.f_back or not self._is_code_inside_project(frame.f_back.f_code) - - if not self._is_code_inside_project(frame.f_code) and \ - (not frame.f_back or not self._is_code_inside_project(frame.f_back.f_code)): - return False - return True - - def _is_code_inside_project(self, code): - source = self._path(code.co_filename) - return source is not None and os.path.exists(source) and \ - _realpath(source).startswith(self.project_root) - - @_cached - def _get_persisted_code(self, object_): - source = self._path(object_.co_filename) - if not os.path.exists(source): - raise TypeError('no source') - return ('defined', _realpath(source), str(object_.co_firstlineno)) - - @_cached - def _get_persisted_class(self, object_): - try: - return ('defined', _realpath(inspect.getsourcefile(object_)), - object_.__name__) - except (TypeError, AttributeError): - return ('unknown',) - - def _get_persisted_builtin(self, object_): - if isinstance(object_, (str, unicode)): - return ('builtin', 'str') - if isinstance(object_, list): - holding = None - if len(object_) > 0: - holding = object_[0] - return ('builtin', 'list', self._object_to_persisted_form(holding)) - if isinstance(object_, dict): - keys = None - values = None - if len(object_) > 0: - keys = object_.keys()[0] - values = object_[keys] - return ('builtin', 'dict', - self._object_to_persisted_form(keys), - self._object_to_persisted_form(values)) - if isinstance(object_, tuple): - objects = [] - if len(object_) < 3: - for holding in object_: - objects.append(self._object_to_persisted_form(holding)) - else: - objects.append(self._object_to_persisted_form(object_[0])) - return tuple(['builtin', 'tuple'] + objects) - if isinstance(object_, set): - holding = None - if len(object_) > 0: - for o in object_: - holding = o - break - return ('builtin', 'set', self._object_to_persisted_form(holding)) - return ('unknown',) - - def _object_to_persisted_form(self, object_): - if object_ is None: - return ('none',) - if isinstance(object_, types.CodeType): - return self._get_persisted_code(object_) - if isinstance(object_, types.FunctionType): - return self._get_persisted_code(object_.func_code) - if isinstance(object_, types.MethodType): - return self._get_persisted_code(object_.im_func.func_code) - if isinstance(object_, types.ModuleType): - return self._get_persisted_module(object_) - if isinstance(object_, (str, unicode, list, dict, tuple, set)): - return self._get_persisted_builtin(object_) - if isinstance(object_, (types.TypeType, types.ClassType)): - return self._get_persisted_class(object_) - return ('instance', self._get_persisted_class(type(object_))) - - @_cached - def _get_persisted_module(self, object_): - path = self._path(object_.__file__) - if path and os.path.exists(path): - return ('defined', _realpath(path)) - return ('unknown',) - - def _path(self, path): - if path.endswith('.pyc'): - path = path[:-1] - if path.endswith('.py'): - return path - - def close(self): - self.sender.close() - sys.settrace(None) - - def _realpath(path): - return os.path.realpath(os.path.abspath(os.path.expanduser(path))) - - send_info = sys.argv[1] - project_root = sys.argv[2] - file_to_run = sys.argv[3] - run_globals = globals() - run_globals.update({'__name__': '__main__', - '__builtins__': __builtins__, - '__file__': file_to_run}) - if send_info != '-': - data_sender = _FunctionCallDataSender(send_info, project_root) - del sys.argv[1:4] - execfile(file_to_run, run_globals) - if send_info != '-': - data_sender.close() - - -if __name__ == '__main__': - __rope_start_everything() diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/soa.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/soa.py @@ -1,136 +0,0 @@ -import rope.base.ast -import rope.base.oi.soi -import rope.base.pynames -from rope.base import pyobjects, evaluate, astutils, arguments - - -def analyze_module(pycore, pymodule, should_analyze, - search_subscopes, followed_calls): - """Analyze `pymodule` for static object inference - - Analyzes scopes for collecting object information. The analysis - starts from inner scopes. - - """ - _analyze_node(pycore, pymodule, should_analyze, - search_subscopes, followed_calls) - - -def _analyze_node(pycore, pydefined, should_analyze, - search_subscopes, followed_calls): - if search_subscopes(pydefined): - for scope in pydefined.get_scope().get_scopes(): - _analyze_node(pycore, scope.pyobject, should_analyze, - search_subscopes, followed_calls) - if should_analyze(pydefined): - new_followed_calls = max(0, followed_calls - 1) - return_true = lambda pydefined: True - return_false = lambda pydefined: False - def _follow(pyfunction): - _analyze_node(pycore, pyfunction, return_true, - return_false, new_followed_calls) - if not followed_calls: - _follow = None - visitor = SOAVisitor(pycore, pydefined, _follow) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - - -class SOAVisitor(object): - - def __init__(self, pycore, pydefined, follow_callback=None): - self.pycore = pycore - self.pymodule = pydefined.get_module() - self.scope = pydefined.get_scope() - self.follow = follow_callback - - def _FunctionDef(self, node): - pass - - def _ClassDef(self, node): - pass - - def _Call(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - primary, pyname = evaluate.eval_node2(self.scope, node.func) - if pyname is None: - return - pyfunction = pyname.get_object() - if isinstance(pyfunction, pyobjects.AbstractFunction): - args = arguments.create_arguments(primary, pyfunction, - node, self.scope) - elif isinstance(pyfunction, pyobjects.PyClass): - pyclass = pyfunction - if '__init__' in pyfunction: - pyfunction = pyfunction['__init__'].get_object() - pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) - args = self._args_with_self(primary, pyname, pyfunction, node) - elif '__call__' in pyfunction: - pyfunction = pyfunction['__call__'].get_object() - args = self._args_with_self(primary, pyname, pyfunction, node) - else: - return - self._call(pyfunction, args) - - def _args_with_self(self, primary, self_pyname, pyfunction, node): - base_args = arguments.create_arguments(primary, pyfunction, - node, self.scope) - return arguments.MixedArguments(self_pyname, base_args, self.scope) - - def _call(self, pyfunction, args): - if isinstance(pyfunction, pyobjects.PyFunction): - if self.follow is not None: - before = self._parameter_objects(pyfunction) - self.pycore.object_info.function_called( - pyfunction, args.get_arguments(pyfunction.get_param_names())) - pyfunction._set_parameter_pyobjects(None) - if self.follow is not None: - after = self._parameter_objects(pyfunction) - if after != before: - self.follow(pyfunction) - # XXX: Maybe we should not call every builtin function - if isinstance(pyfunction, rope.base.builtins.BuiltinFunction): - pyfunction.get_returned_object(args) - - def _parameter_objects(self, pyfunction): - result = [] - for i in range(len(pyfunction.get_param_names(False))): - result.append(pyfunction.get_parameter(i)) - return result - - def _Assign(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - for child in node.targets: - rope.base.ast.walk(child, visitor) - nodes.extend(visitor.nodes) - for subscript, levels in nodes: - instance = evaluate.eval_node(self.scope, subscript.value) - args_pynames = [] - args_pynames.append(evaluate.eval_node(self.scope, - subscript.slice.value)) - value = rope.base.oi.soi._infer_assignment( - rope.base.pynames.AssignmentValue(node.value, levels), self.pymodule) - args_pynames.append(rope.base.pynames.UnboundName(value)) - if instance is not None and value is not None: - pyobject = instance.get_object() - if '__setitem__' in pyobject: - pyfunction = pyobject['__setitem__'].get_object() - args = arguments.ObjectArguments([instance] + args_pynames) - self._call(pyfunction, args) - # IDEA: handle `__setslice__`, too - - -class _SOAAssignVisitor(astutils._NodeNameCollector): - - def __init__(self): - super(_SOAAssignVisitor, self).__init__() - self.nodes = [] - - def _added(self, node, levels): - if isinstance(node, rope.base.ast.Subscript) and \ - isinstance(node.slice, rope.base.ast.Index): - self.nodes.append((node, levels)) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/soi.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/soi.py @@ -1,186 +0,0 @@ -"""A module for inferring objects - -For more information see the documentation in `rope.base.oi` -package. - -""" -import rope.base.builtins -import rope.base.pynames -import rope.base.pyobjects -from rope.base import evaluate, utils, arguments - - -_ignore_inferred = utils.ignore_exception( - rope.base.pyobjects.IsBeingInferredError) - - -@_ignore_inferred -def infer_returned_object(pyfunction, args): - """Infer the `PyObject` this `PyFunction` returns after calling""" - object_info = pyfunction.pycore.object_info - result = object_info.get_exact_returned(pyfunction, args) - if result is not None: - return result - result = _infer_returned(pyfunction, args) - if result is not None: - if args and pyfunction.get_module().get_resource() is not None: - params = args.get_arguments( - pyfunction.get_param_names(special_args=False)) - object_info.function_called(pyfunction, params, result) - return result - return object_info.get_returned(pyfunction, args) - -@_ignore_inferred -def infer_parameter_objects(pyfunction): - """Infer the `PyObject`\s of parameters of this `PyFunction`""" - object_info = pyfunction.pycore.object_info - result = object_info.get_parameter_objects(pyfunction) - if result is None: - result = _parameter_objects(pyfunction) - _handle_first_parameter(pyfunction, result) - return result - -def _handle_first_parameter(pyobject, parameters): - kind = pyobject.get_kind() - if parameters is None or kind not in ['method', 'classmethod']: - pass - if not parameters: - if not pyobject.get_param_names(special_args=False): - return - parameters.append(rope.base.pyobjects.get_unknown()) - if kind == 'method': - parameters[0] = rope.base.pyobjects.PyObject(pyobject.parent) - if kind == 'classmethod': - parameters[0] = pyobject.parent - -@_ignore_inferred -def infer_assigned_object(pyname): - if not pyname.assignments: - return - for assignment in reversed(pyname.assignments): - result = _infer_assignment(assignment, pyname.module) - if result is not None: - return result - -def get_passed_objects(pyfunction, parameter_index): - object_info = pyfunction.pycore.object_info - result = object_info.get_passed_objects(pyfunction, - parameter_index) - if not result: - statically_inferred = _parameter_objects(pyfunction) - if len(statically_inferred) > parameter_index: - result.append(statically_inferred[parameter_index]) - return result - -def _infer_returned(pyobject, args): - if args: - # HACK: Setting parameter objects manually - # This is not thread safe and might cause problems if `args` - # does not come from a good call site - pyobject.get_scope().invalidate_data() - pyobject._set_parameter_pyobjects( - args.get_arguments(pyobject.get_param_names(special_args=False))) - scope = pyobject.get_scope() - if not scope._get_returned_asts(): - return - maxtries = 3 - for returned_node in reversed(scope._get_returned_asts()[-maxtries:]): - try: - resulting_pyname = evaluate.eval_node(scope, returned_node) - if resulting_pyname is None: - continue - pyobject = resulting_pyname.get_object() - if pyobject == rope.base.pyobjects.get_unknown(): - continue - if not scope._is_generator(): - return pyobject - else: - return rope.base.builtins.get_generator(pyobject) - except rope.base.pyobjects.IsBeingInferredError: - pass - -def _parameter_objects(pyobject): - params = pyobject.get_param_names(special_args=False) - return [rope.base.pyobjects.get_unknown()] * len(params) - -# handling `rope.base.pynames.AssignmentValue` - -@_ignore_inferred -def _infer_assignment(assignment, pymodule): - result = _follow_pyname(assignment, pymodule) - if result is None: - return None - pyname, pyobject = result - pyobject = _follow_evaluations(assignment, pyname, pyobject) - if pyobject is None: - return None - return _follow_levels(assignment, pyobject) - -def _follow_levels(assignment, pyobject): - for index in assignment.levels: - if isinstance(pyobject.get_type(), rope.base.builtins.Tuple): - holdings = pyobject.get_type().get_holding_objects() - if holdings: - pyobject = holdings[min(len(holdings) - 1, index)] - else: - pyobject = None - elif isinstance(pyobject.get_type(), rope.base.builtins.List): - pyobject = pyobject.get_type().holding - else: - pyobject = None - if pyobject is None: - break - return pyobject - -@_ignore_inferred -def _follow_pyname(assignment, pymodule, lineno=None): - assign_node = assignment.ast_node - if lineno is None: - lineno = _get_lineno_for_node(assign_node) - holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - pyname = evaluate.eval_node(holding_scope, assign_node) - if pyname is not None: - result = pyname.get_object() - if isinstance(result.get_type(), rope.base.builtins.Property) and \ - holding_scope.get_kind() == 'Class': - arg = rope.base.pynames.UnboundName( - rope.base.pyobjects.PyObject(holding_scope.pyobject)) - return pyname, result.get_type().get_property_object( - arguments.ObjectArguments([arg])) - return pyname, result - -@_ignore_inferred -def _follow_evaluations(assignment, pyname, pyobject): - new_pyname = pyname - tokens = assignment.evaluation.split('.') - for token in tokens: - call = token.endswith('()') - if call: - token = token[:-2] - if token: - pyname = new_pyname - new_pyname = _get_attribute(pyobject, token) - if new_pyname is not None: - pyobject = new_pyname.get_object() - if pyobject is not None and call: - if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): - args = arguments.ObjectArguments([pyname]) - pyobject = pyobject.get_returned_object(args) - else: - pyobject = None - if pyobject is None: - break - if pyobject is not None and assignment.assign_type: - return rope.base.pyobjects.PyObject(pyobject) - return pyobject - - -def _get_lineno_for_node(assign_node): - if hasattr(assign_node, 'lineno') and \ - assign_node.lineno is not None: - return assign_node.lineno - return 1 - -def _get_attribute(pyobject, name): - if pyobject is not None and name in pyobject: - return pyobject[name] diff --git a/.vim/bundle/python-mode/pylibs/rope/base/oi/transform.py b/.vim/bundle/python-mode/pylibs/rope/base/oi/transform.py @@ -1,285 +0,0 @@ -"""Provides classes for persisting `PyObject`\s""" -import os -import re - -import rope.base.builtins -from rope.base import exceptions - - -class PyObjectToTextual(object): - """For transforming `PyObject` to textual form - - This can be used for storing `PyObjects` in files. Use - `TextualToPyObject` for converting back. - - """ - - def __init__(self, project): - self.project = project - - def transform(self, pyobject): - """Transform a `PyObject` to textual form""" - if pyobject is None: - return ('none',) - object_type = type(pyobject) - try: - method = getattr(self, object_type.__name__ + '_to_textual') - return method(pyobject) - except AttributeError: - return ('unknown',) - - def __call__(self, pyobject): - return self.transform(pyobject) - - def PyObject_to_textual(self, pyobject): - if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass): - result = self.transform(pyobject.get_type()) - if result[0] == 'defined': - return ('instance', result) - return result - return ('unknown',) - - def PyFunction_to_textual(self, pyobject): - return self._defined_to_textual(pyobject) - - def PyClass_to_textual(self, pyobject): - return self._defined_to_textual(pyobject) - - def _defined_to_textual(self, pyobject): - address = [] - while pyobject.parent is not None: - address.insert(0, pyobject.get_name()) - pyobject = pyobject.parent - return ('defined', self._get_pymodule_path(pyobject.get_module()), - '.'.join(address)) - - def PyModule_to_textual(self, pyobject): - return ('defined', self._get_pymodule_path(pyobject)) - - def PyPackage_to_textual(self, pyobject): - return ('defined', self._get_pymodule_path(pyobject)) - - def List_to_textual(self, pyobject): - return ('builtin', 'list', self.transform(pyobject.holding)) - - def Dict_to_textual(self, pyobject): - return ('builtin', 'dict', self.transform(pyobject.keys), - self.transform(pyobject.values)) - - def Tuple_to_textual(self, pyobject): - objects = [self.transform(holding) - for holding in pyobject.get_holding_objects()] - return tuple(['builtin', 'tuple'] + objects) - - def Set_to_textual(self, pyobject): - return ('builtin', 'set', self.transform(pyobject.holding)) - - def Iterator_to_textual(self, pyobject): - return ('builtin', 'iter', self.transform(pyobject.holding)) - - def Generator_to_textual(self, pyobject): - return ('builtin', 'generator', self.transform(pyobject.holding)) - - def Str_to_textual(self, pyobject): - return ('builtin', 'str') - - def File_to_textual(self, pyobject): - return ('builtin', 'file') - - def BuiltinFunction_to_textual(self, pyobject): - return ('builtin', 'function', pyobject.get_name()) - - def _get_pymodule_path(self, pymodule): - return self.resource_to_path(pymodule.get_resource()) - - def resource_to_path(self, resource): - if resource.project == self.project: - return resource.path - else: - return resource.real_path - - -class TextualToPyObject(object): - """For transforming textual form to `PyObject`""" - - def __init__(self, project, allow_in_project_absolutes=False): - self.project = project - - def __call__(self, textual): - return self.transform(textual) - - def transform(self, textual): - """Transform an object from textual form to `PyObject`""" - if textual is None: - return None - type = textual[0] - try: - method = getattr(self, type + '_to_pyobject') - return method(textual) - except AttributeError: - return None - - def builtin_to_pyobject(self, textual): - name = textual[1] - method = getattr(self, 'builtin_%s_to_pyobject' % textual[1], None) - if method is not None: - return method(textual) - - def builtin_str_to_pyobject(self, textual): - return rope.base.builtins.get_str() - - def builtin_list_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_list(holding) - - def builtin_dict_to_pyobject(self, textual): - keys = self.transform(textual[2]) - values = self.transform(textual[3]) - return rope.base.builtins.get_dict(keys, values) - - def builtin_tuple_to_pyobject(self, textual): - objects = [] - for holding in textual[2:]: - objects.append(self.transform(holding)) - return rope.base.builtins.get_tuple(*objects) - - def builtin_set_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_set(holding) - - def builtin_iter_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_iterator(holding) - - def builtin_generator_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_generator(holding) - - def builtin_file_to_pyobject(self, textual): - return rope.base.builtins.get_file() - - def builtin_function_to_pyobject(self, textual): - if textual[2] in rope.base.builtins.builtins: - return rope.base.builtins.builtins[textual[2]].get_object() - - def unknown_to_pyobject(self, textual): - return None - - def none_to_pyobject(self, textual): - return None - - def _module_to_pyobject(self, textual): - path = textual[1] - return self._get_pymodule(path) - - def _hierarchical_defined_to_pyobject(self, textual): - path = textual[1] - names = textual[2].split('.') - pymodule = self._get_pymodule(path) - pyobject = pymodule - for name in names: - if pyobject is None: - return None - if isinstance(pyobject, rope.base.pyobjects.PyDefinedObject): - try: - pyobject = pyobject.get_scope()[name].get_object() - except exceptions.NameNotFoundError: - return None - else: - return None - return pyobject - - def defined_to_pyobject(self, textual): - if len(textual) == 2 or textual[2] == '': - return self._module_to_pyobject(textual) - else: - return self._hierarchical_defined_to_pyobject(textual) - - def instance_to_pyobject(self, textual): - type = self.transform(textual[1]) - if type is not None: - return rope.base.pyobjects.PyObject(type) - - def _get_pymodule(self, path): - resource = self.path_to_resource(path) - if resource is not None: - return self.project.pycore.resource_to_pyobject(resource) - - def path_to_resource(self, path): - try: - root = self.project.address - if not os.path.isabs(path): - return self.project.get_resource(path) - if path == root or path.startswith(root + os.sep): - # INFO: This is a project file; should not be absolute - return None - import rope.base.project - return rope.base.project.get_no_project().get_resource(path) - except exceptions.ResourceNotFoundError: - return None - - -class DOITextualToPyObject(TextualToPyObject): - """For transforming textual form to `PyObject` - - The textual form DOI uses is different from rope's standard - textual form. The reason is that we cannot find the needed - information by analyzing live objects. This class can be - used to transform DOI textual form to `PyObject` and later - we can convert it to standard textual form using - `TextualToPyObject` class. - - """ - - def _function_to_pyobject(self, textual): - path = textual[1] - lineno = int(textual[2]) - pymodule = self._get_pymodule(path) - if pymodule is not None: - scope = pymodule.get_scope() - inner_scope = scope.get_inner_scope_for_line(lineno) - return inner_scope.pyobject - - def _class_to_pyobject(self, textual): - path, name = textual[1:] - pymodule = self._get_pymodule(path) - if pymodule is None: - return None - module_scope = pymodule.get_scope() - suspected = None - if name in module_scope.get_names(): - suspected = module_scope[name].get_object() - if suspected is not None and \ - isinstance(suspected, rope.base.pyobjects.PyClass): - return suspected - else: - lineno = self._find_occurrence(name, pymodule.get_resource().read()) - if lineno is not None: - inner_scope = module_scope.get_inner_scope_for_line(lineno) - return inner_scope.pyobject - - def defined_to_pyobject(self, textual): - if len(textual) == 2: - return self._module_to_pyobject(textual) - else: - if textual[2].isdigit(): - result = self._function_to_pyobject(textual) - else: - result = self._class_to_pyobject(textual) - if not isinstance(result, rope.base.pyobjects.PyModule): - return result - - def _find_occurrence(self, name, source): - pattern = re.compile(r'^\s*class\s*' + name + r'\b') - lines = source.split('\n') - for i in range(len(lines)): - if pattern.match(lines[i]): - return i + 1 - - def path_to_resource(self, path): - import rope.base.libutils - root = self.project.address - relpath = rope.base.libutils.relative(root, path) - if relpath is not None: - path = relpath - return super(DOITextualToPyObject, self).path_to_resource(path) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/prefs.py b/.vim/bundle/python-mode/pylibs/rope/base/prefs.py @@ -1,41 +0,0 @@ -class Prefs(object): - - def __init__(self): - self.prefs = {} - self.callbacks = {} - - def set(self, key, value): - """Set the value of `key` preference to `value`.""" - if key in self.callbacks: - self.callbacks[key](value) - else: - self.prefs[key] = value - - def add(self, key, value): - """Add an entry to a list preference - - Add `value` to the list of entries for the `key` preference. - - """ - if not key in self.prefs: - self.prefs[key] = [] - self.prefs[key].append(value) - - def get(self, key, default=None): - """Get the value of the key preference""" - return self.prefs.get(key, default) - - def add_callback(self, key, callback): - """Add `key` preference with `callback` function - - Whenever `key` is set the callback is called with the - given `value` as parameter. - - """ - self.callbacks[key] = callback - - def __setitem__(self, key, value): - self.set(key, value) - - def __getitem__(self, key): - return self.get(key) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/project.py b/.vim/bundle/python-mode/pylibs/rope/base/project.py @@ -1,376 +0,0 @@ -import cPickle as pickle -import os -import shutil -import sys -import warnings - -import rope.base.fscommands -from rope.base import exceptions, taskhandle, prefs, history, pycore, utils -from rope.base.resourceobserver import * -from rope.base.resources import File, Folder, _ResourceMatcher - - -class _Project(object): - - def __init__(self, fscommands): - self.observers = [] - self.fscommands = fscommands - self.prefs = prefs.Prefs() - self.data_files = _DataFiles(self) - - def get_resource(self, resource_name): - """Get a resource in a project. - - `resource_name` is the path of a resource in a project. It is - the path of a resource relative to project root. Project root - folder address is an empty string. If the resource does not - exist a `exceptions.ResourceNotFound` exception would be - raised. Use `get_file()` and `get_folder()` when you need to - get nonexistent `Resource`\s. - - """ - path = self._get_resource_path(resource_name) - if not os.path.exists(path): - raise exceptions.ResourceNotFoundError( - 'Resource <%s> does not exist' % resource_name) - elif os.path.isfile(path): - return File(self, resource_name) - elif os.path.isdir(path): - return Folder(self, resource_name) - else: - raise exceptions.ResourceNotFoundError('Unknown resource ' - + resource_name) - - def validate(self, folder): - """Validate files and folders contained in this folder - - It validates all of the files and folders contained in this - folder if some observers are interested in them. - - """ - for observer in list(self.observers): - observer.validate(folder) - - def add_observer(self, observer): - """Register a `ResourceObserver` - - See `FilteredResourceObserver`. - """ - self.observers.append(observer) - - def remove_observer(self, observer): - """Remove a registered `ResourceObserver`""" - if observer in self.observers: - self.observers.remove(observer) - - def do(self, changes, task_handle=taskhandle.NullTaskHandle()): - """Apply the changes in a `ChangeSet` - - Most of the time you call this function for committing the - changes for a refactoring. - """ - self.history.do(changes, task_handle=task_handle) - - def get_pycore(self): - return self.pycore - - def get_file(self, path): - """Get the file with `path` (it may not exist)""" - return File(self, path) - - def get_folder(self, path): - """Get the folder with `path` (it may not exist)""" - return Folder(self, path) - - def is_ignored(self, resource): - return False - - def get_prefs(self): - return self.prefs - - def _get_resource_path(self, name): - pass - - @property - @utils.saveit - def history(self): - return history.History(self) - - @property - @utils.saveit - def pycore(self): - return pycore.PyCore(self) - - def close(self): - warnings.warn('Cannot close a NoProject', - DeprecationWarning, stacklevel=2) - - ropefolder = None - - -class Project(_Project): - """A Project containing files and folders""" - - def __init__(self, projectroot, fscommands=None, - ropefolder='.ropeproject', **prefs): - """A rope project - - :parameters: - - `projectroot`: The address of the root folder of the project - - `fscommands`: Implements the file system operations used - by rope; have a look at `rope.base.fscommands` - - `ropefolder`: The name of the folder in which rope stores - project configurations and data. Pass `None` for not using - such a folder at all. - - `prefs`: Specify project preferences. These values - overwrite config file preferences. - - """ - if projectroot != '/': - projectroot = _realpath(projectroot).rstrip('/\\') - self._address = projectroot - self._ropefolder_name = ropefolder - if not os.path.exists(self._address): - os.mkdir(self._address) - elif not os.path.isdir(self._address): - raise exceptions.RopeError('Project root exists and' - ' is not a directory') - if fscommands is None: - fscommands = rope.base.fscommands.create_fscommands(self._address) - super(Project, self).__init__(fscommands) - self.ignored = _ResourceMatcher() - self.file_list = _FileListCacher(self) - self.prefs.add_callback('ignored_resources', self.ignored.set_patterns) - if ropefolder is not None: - self.prefs['ignored_resources'] = [ropefolder] - self._init_prefs(prefs) - - def get_files(self): - return self.file_list.get_files() - - def _get_resource_path(self, name): - return os.path.join(self._address, *name.split('/')) - - def _init_ropefolder(self): - if self.ropefolder is not None: - if not self.ropefolder.exists(): - self._create_recursively(self.ropefolder) - if not self.ropefolder.has_child('config.py'): - config = self.ropefolder.create_file('config.py') - config.write(self._default_config()) - - def _create_recursively(self, folder): - if folder.parent != self.root and not folder.parent.exists(): - self._create_recursively(folder.parent) - folder.create() - - def _init_prefs(self, prefs): - run_globals = {} - if self.ropefolder is not None: - config = self.get_file(self.ropefolder.path + '/config.py') - run_globals.update({'__name__': '__main__', - '__builtins__': __builtins__, - '__file__': config.real_path}) - if config.exists(): - config = self.ropefolder.get_child('config.py') - execfile(config.real_path, run_globals) - else: - exec(self._default_config(), run_globals) - if 'set_prefs' in run_globals: - run_globals['set_prefs'](self.prefs) - for key, value in prefs.items(): - self.prefs[key] = value - self._init_other_parts() - self._init_ropefolder() - if 'project_opened' in run_globals: - run_globals['project_opened'](self) - - def _default_config(self): - import rope.base.default_config - import inspect - return inspect.getsource(rope.base.default_config) - - def _init_other_parts(self): - # Forcing the creation of `self.pycore` to register observers - self.pycore - - def is_ignored(self, resource): - return self.ignored.does_match(resource) - - def sync(self): - """Closes project open resources""" - self.close() - - def close(self): - """Closes project open resources""" - self.data_files.write() - - def set(self, key, value): - """Set the `key` preference to `value`""" - self.prefs.set(key, value) - - @property - def ropefolder(self): - if self._ropefolder_name is not None: - return self.get_folder(self._ropefolder_name) - - def validate(self, folder=None): - if folder is None: - folder = self.root - super(Project, self).validate(folder) - - root = property(lambda self: self.get_resource('')) - address = property(lambda self: self._address) - - -class NoProject(_Project): - """A null object for holding out of project files. - - This class is singleton use `get_no_project` global function - """ - - def __init__(self): - fscommands = rope.base.fscommands.FileSystemCommands() - super(NoProject, self).__init__(fscommands) - - def _get_resource_path(self, name): - real_name = name.replace('/', os.path.sep) - return _realpath(real_name) - - def get_resource(self, name): - universal_name = _realpath(name).replace(os.path.sep, '/') - return super(NoProject, self).get_resource(universal_name) - - def get_files(self): - return [] - - _no_project = None - - -def get_no_project(): - if NoProject._no_project is None: - NoProject._no_project = NoProject() - return NoProject._no_project - - -class _FileListCacher(object): - - def __init__(self, project): - self.project = project - self.files = None - rawobserver = ResourceObserver( - self._changed, self._invalid, self._invalid, - self._invalid, self._invalid) - self.project.add_observer(rawobserver) - - def get_files(self): - if self.files is None: - self.files = set() - self._add_files(self.project.root) - return self.files - - def _add_files(self, folder): - for child in folder.get_children(): - if child.is_folder(): - self._add_files(child) - elif not self.project.is_ignored(child): - self.files.add(child) - - def _changed(self, resource): - if resource.is_folder(): - self.files = None - - def _invalid(self, resource, new_resource=None): - self.files = None - - -class _DataFiles(object): - - def __init__(self, project): - self.project = project - self.hooks = [] - - def read_data(self, name, compress=False, import_=False): - if self.project.ropefolder is None: - return None - compress = compress and self._can_compress() - opener = self._get_opener(compress) - file = self._get_file(name, compress) - if not compress and import_: - self._import_old_files(name) - if file.exists(): - input = opener(file.real_path, 'rb') - try: - result = [] - try: - while True: - result.append(pickle.load(input)) - except EOFError: - pass - if len(result) == 1: - return result[0] - if len(result) > 1: - return result - finally: - input.close() - - def write_data(self, name, data, compress=False): - if self.project.ropefolder is not None: - compress = compress and self._can_compress() - file = self._get_file(name, compress) - opener = self._get_opener(compress) - output = opener(file.real_path, 'wb') - try: - pickle.dump(data, output, 2) - finally: - output.close() - - def add_write_hook(self, hook): - self.hooks.append(hook) - - def write(self): - for hook in self.hooks: - hook() - - def _can_compress(self): - try: - import gzip - return True - except ImportError: - return False - - def _import_old_files(self, name): - old = self._get_file(name + '.pickle', False) - new = self._get_file(name, False) - if old.exists() and not new.exists(): - shutil.move(old.real_path, new.real_path) - - def _get_opener(self, compress): - if compress: - try: - import gzip - return gzip.open - except ImportError: - pass - return open - - def _get_file(self, name, compress): - path = self.project.ropefolder.path + '/' + name - if compress: - path += '.gz' - return self.project.get_file(path) - - -def _realpath(path): - """Return the real path of `path` - - Is equivalent to ``realpath(abspath(expanduser(path)))``. - - """ - path = path or '' - # there is a bug in cygwin for os.path.abspath() for abs paths - if sys.platform == 'cygwin': - if path[1:3] == ':\\': - return path - return os.path.abspath(os.path.expanduser(path)) - return os.path.realpath(os.path.abspath(os.path.expanduser(path))) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/pycore.py b/.vim/bundle/python-mode/pylibs/rope/base/pycore.py @@ -1,410 +0,0 @@ -import bisect -import difflib -import sys -import warnings - -import rope.base.oi.doa -import rope.base.oi.objectinfo -import rope.base.oi.soa -from rope.base import ast, exceptions, taskhandle, utils, stdmods -from rope.base.exceptions import ModuleNotFoundError -from rope.base.pyobjectsdef import PyModule, PyPackage, PyClass -import rope.base.resources -import rope.base.resourceobserver -from rope.base import builtins - - -class PyCore(object): - - def __init__(self, project): - self.project = project - self._init_resource_observer() - self.cache_observers = [] - self.module_cache = _ModuleCache(self) - self.extension_cache = _ExtensionCache(self) - self.object_info = rope.base.oi.objectinfo.ObjectInfoManager(project) - self._init_python_files() - self._init_automatic_soa() - self._init_source_folders() - - def _init_python_files(self): - self.python_matcher = None - patterns = self.project.prefs.get('python_files', None) - if patterns is not None: - self.python_matcher = rope.base.resources._ResourceMatcher() - self.python_matcher.set_patterns(patterns) - - def _init_resource_observer(self): - callback = self._invalidate_resource_cache - observer = rope.base.resourceobserver.ResourceObserver( - changed=callback, moved=callback, removed=callback) - self.observer = rope.base.resourceobserver.FilteredResourceObserver(observer) - self.project.add_observer(self.observer) - - def _init_source_folders(self): - self._custom_source_folders = [] - for path in self.project.prefs.get('source_folders', []): - folder = self.project.get_resource(path) - self._custom_source_folders.append(folder) - - def _init_automatic_soa(self): - if not self.automatic_soa: - return - callback = self._file_changed_for_soa - observer = rope.base.resourceobserver.ResourceObserver( - changed=callback, moved=callback, removed=callback) - self.project.add_observer(observer) - - @property - def automatic_soa(self): - auto_soa = self.project.prefs.get('automatic_soi', None) - return self.project.prefs.get('automatic_soa', auto_soa) - - def _file_changed_for_soa(self, resource, new_resource=None): - old_contents = self.project.history.\ - contents_before_current_change(resource) - if old_contents is not None: - perform_soa_on_changed_scopes(self.project, resource, old_contents) - - def is_python_file(self, resource): - if resource.is_folder(): - return False - if self.python_matcher is None: - return resource.name.endswith('.py') - return self.python_matcher.does_match(resource) - - def get_module(self, name, folder=None): - """Returns a `PyObject` if the module was found.""" - # check if this is a builtin module - pymod = self._builtin_module(name) - if pymod is not None: - return pymod - module = self.find_module(name, folder) - if module is None: - raise ModuleNotFoundError('Module %s not found' % name) - return self.resource_to_pyobject(module) - - def _builtin_submodules(self, modname): - result = {} - for extension in self.extension_modules: - if extension.startswith(modname + '.'): - name = extension[len(modname) + 1:] - if '.' not in name: - result[name] = self._builtin_module(extension) - return result - - def _builtin_module(self, name): - return self.extension_cache.get_pymodule(name) - - def get_relative_module(self, name, folder, level): - module = self.find_relative_module(name, folder, level) - if module is None: - raise ModuleNotFoundError('Module %s not found' % name) - return self.resource_to_pyobject(module) - - def get_string_module(self, code, resource=None, force_errors=False): - """Returns a `PyObject` object for the given code - - If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is - raised if module has syntax errors. This overrides - ``ignore_syntax_errors`` project config. - - """ - return PyModule(self, code, resource, force_errors=force_errors) - - def get_string_scope(self, code, resource=None): - """Returns a `Scope` object for the given code""" - return self.get_string_module(code, resource).get_scope() - - def _invalidate_resource_cache(self, resource, new_resource=None): - for observer in self.cache_observers: - observer(resource) - - def _find_module_in_folder(self, folder, modname): - module = folder - packages = modname.split('.') - for pkg in packages[:-1]: - if module.is_folder() and module.has_child(pkg): - module = module.get_child(pkg) - else: - return None - if module.is_folder(): - if module.has_child(packages[-1]) and \ - module.get_child(packages[-1]).is_folder(): - return module.get_child(packages[-1]) - elif module.has_child(packages[-1] + '.py') and \ - not module.get_child(packages[-1] + '.py').is_folder(): - return module.get_child(packages[-1] + '.py') - - def get_python_path_folders(self): - import rope.base.project - result = [] - for src in self.project.prefs.get('python_path', []) + sys.path: - try: - src_folder = rope.base.project.get_no_project().get_resource(src) - result.append(src_folder) - except rope.base.exceptions.ResourceNotFoundError: - pass - return result - - def find_module(self, modname, folder=None): - """Returns a resource corresponding to the given module - - returns None if it can not be found - """ - return self._find_module(modname, folder) - - def find_relative_module(self, modname, folder, level): - for i in range(level - 1): - folder = folder.parent - if modname == '': - return folder - else: - return self._find_module_in_folder(folder, modname) - - def _find_module(self, modname, folder=None): - """Return `modname` module resource""" - for src in self.get_source_folders(): - module = self._find_module_in_folder(src, modname) - if module is not None: - return module - for src in self.get_python_path_folders(): - module = self._find_module_in_folder(src, modname) - if module is not None: - return module - if folder is not None: - module = self._find_module_in_folder(folder, modname) - if module is not None: - return module - return None - - # INFO: It was decided not to cache source folders, since: - # - Does not take much time when the root folder contains - # packages, that is most of the time - # - We need a separate resource observer; `self.observer` - # does not get notified about module and folder creations - def get_source_folders(self): - """Returns project source folders""" - if self.project.root is None: - return [] - result = list(self._custom_source_folders) - result.extend(self._find_source_folders(self.project.root)) - return result - - def resource_to_pyobject(self, resource, force_errors=False): - return self.module_cache.get_pymodule(resource, force_errors) - - def get_python_files(self): - """Returns all python files available in the project""" - return [resource for resource in self.project.get_files() - if self.is_python_file(resource)] - - def _is_package(self, folder): - if folder.has_child('__init__.py') and \ - not folder.get_child('__init__.py').is_folder(): - return True - else: - return False - - def _find_source_folders(self, folder): - for resource in folder.get_folders(): - if self._is_package(resource): - return [folder] - result = [] - for resource in folder.get_files(): - if resource.name.endswith('.py'): - result.append(folder) - break - for resource in folder.get_folders(): - result.extend(self._find_source_folders(resource)) - return result - - def run_module(self, resource, args=None, stdin=None, stdout=None): - """Run `resource` module - - Returns a `rope.base.oi.doa.PythonFileRunner` object for - controlling the process. - - """ - perform_doa = self.project.prefs.get('perform_doi', True) - perform_doa = self.project.prefs.get('perform_doa', perform_doa) - receiver = self.object_info.doa_data_received - if not perform_doa: - receiver = None - runner = rope.base.oi.doa.PythonFileRunner( - self, resource, args, stdin, stdout, receiver) - runner.add_finishing_observer(self.module_cache.forget_all_data) - runner.run() - return runner - - def analyze_module(self, resource, should_analyze=lambda py: True, - search_subscopes=lambda py: True, followed_calls=None): - """Analyze `resource` module for static object inference - - This function forces rope to analyze this module to collect - information about function calls. `should_analyze` is a - function that is called with a `PyDefinedObject` argument. If - it returns `True` the element is analyzed. If it is `None` or - returns `False` the element is not analyzed. - - `search_subscopes` is like `should_analyze`; The difference is - that if it returns `False` the sub-scopes are all ignored. - That is it is assumed that `should_analyze` returns `False` - for all of its subscopes. - - `followed_calls` override the value of ``soa_followed_calls`` - project config. - """ - if followed_calls is None: - followed_calls = self.project.prefs.get('soa_followed_calls', 0) - pymodule = self.resource_to_pyobject(resource) - self.module_cache.forget_all_data() - rope.base.oi.soa.analyze_module( - self, pymodule, should_analyze, search_subscopes, followed_calls) - - def get_classes(self, task_handle=taskhandle.NullTaskHandle()): - warnings.warn('`PyCore.get_classes()` is deprecated', - DeprecationWarning, stacklevel=2) - return [] - - def __str__(self): - return str(self.module_cache) + str(self.object_info) - - def modname(self, resource): - if resource.is_folder(): - module_name = resource.name - source_folder = resource.parent - elif resource.name == '__init__.py': - module_name = resource.parent.name - source_folder = resource.parent.parent - else: - module_name = resource.name[:-3] - source_folder = resource.parent - - while source_folder != source_folder.parent and \ - source_folder.has_child('__init__.py'): - module_name = source_folder.name + '.' + module_name - source_folder = source_folder.parent - return module_name - - @property - @utils.cacheit - def extension_modules(self): - result = set(self.project.prefs.get('extension_modules', [])) - if self.project.prefs.get('import_dynload_stdmods', False): - result.update(stdmods.dynload_modules()) - return result - - -class _ModuleCache(object): - - def __init__(self, pycore): - self.pycore = pycore - self.module_map = {} - self.pycore.cache_observers.append(self._invalidate_resource) - self.observer = self.pycore.observer - - def _invalidate_resource(self, resource): - if resource in self.module_map: - self.forget_all_data() - self.observer.remove_resource(resource) - del self.module_map[resource] - - def get_pymodule(self, resource, force_errors=False): - if resource in self.module_map: - return self.module_map[resource] - if resource.is_folder(): - result = PyPackage(self.pycore, resource, - force_errors=force_errors) - else: - result = PyModule(self.pycore, resource=resource, - force_errors=force_errors) - if result.has_errors: - return result - self.module_map[resource] = result - self.observer.add_resource(resource) - return result - - def forget_all_data(self): - for pymodule in self.module_map.values(): - pymodule._forget_concluded_data() - - def __str__(self): - return 'PyCore caches %d PyModules\n' % len(self.module_map) - - -class _ExtensionCache(object): - - def __init__(self, pycore): - self.pycore = pycore - self.extensions = {} - - def get_pymodule(self, name): - if name == '__builtin__': - return builtins.builtins - allowed = self.pycore.extension_modules - if name not in self.extensions and name in allowed: - self.extensions[name] = builtins.BuiltinModule(name, self.pycore) - return self.extensions.get(name) - - -def perform_soa_on_changed_scopes(project, resource, old_contents): - pycore = project.pycore - if resource.exists() and pycore.is_python_file(resource): - try: - new_contents = resource.read() - # detecting changes in new_contents relative to old_contents - detector = _TextChangeDetector(new_contents, old_contents) - def search_subscopes(pydefined): - scope = pydefined.get_scope() - return detector.is_changed(scope.get_start(), scope.get_end()) - def should_analyze(pydefined): - scope = pydefined.get_scope() - start = scope.get_start() - end = scope.get_end() - return detector.consume_changes(start, end) - pycore.analyze_module(resource, should_analyze, search_subscopes) - except exceptions.ModuleSyntaxError: - pass - - -class _TextChangeDetector(object): - - def __init__(self, old, new): - self.old = old - self.new = new - self._set_diffs() - - def _set_diffs(self): - differ = difflib.Differ() - self.lines = [] - lineno = 0 - for line in differ.compare(self.old.splitlines(True), - self.new.splitlines(True)): - if line.startswith(' '): - lineno += 1 - elif line.startswith('-'): - lineno += 1 - self.lines.append(lineno) - - def is_changed(self, start, end): - """Tell whether any of start till end lines have changed - - The end points are inclusive and indices start from 1. - """ - left, right = self._get_changed(start, end) - if left < right: - return True - return False - - def consume_changes(self, start, end): - """Clear the changed status of lines from start till end""" - left, right = self._get_changed(start, end) - if left < right: - del self.lines[left:right] - return left < right - - def _get_changed(self, start, end): - left = bisect.bisect_left(self.lines, start) - right = bisect.bisect_right(self.lines, end) - return left, right diff --git a/.vim/bundle/python-mode/pylibs/rope/base/pynames.py b/.vim/bundle/python-mode/pylibs/rope/base/pynames.py @@ -1,199 +0,0 @@ -import rope.base.pyobjects -from rope.base import exceptions, utils - - -class PyName(object): - """References to `PyObject`\s inside python programs""" - - def get_object(self): - """Return the `PyObject` object referenced by this `PyName`""" - - def get_definition_location(self): - """Return a (module, lineno) tuple""" - - -class DefinedName(PyName): - - def __init__(self, pyobject): - self.pyobject = pyobject - - def get_object(self): - return self.pyobject - - def get_definition_location(self): - return (self.pyobject.get_module(), self.pyobject.get_ast().lineno) - - -class AssignedName(PyName): - """Only a placeholder""" - - -class UnboundName(PyName): - - def __init__(self, pyobject=None): - self.pyobject = pyobject - if self.pyobject is None: - self.pyobject = rope.base.pyobjects.get_unknown() - - def get_object(self): - return self.pyobject - - def get_definition_location(self): - return (None, None) - - -class AssignmentValue(object): - """An assigned expression""" - - def __init__(self, ast_node, levels=None, evaluation='', - assign_type=False): - """The `level` is `None` for simple assignments and is - a list of numbers for tuple assignments for example in:: - - a, (b, c) = x - - The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for - `c` is ``[1, 1]``. - - """ - self.ast_node = ast_node - if levels == None: - self.levels = [] - else: - self.levels = levels - self.evaluation = evaluation - self.assign_type = assign_type - - def get_lineno(self): - return self.ast_node.lineno - - -class EvaluatedName(PyName): - """A name whose object will be evaluated later""" - - def __init__(self, callback, module=None, lineno=None): - self.module = module - self.lineno = lineno - self.callback = callback - self.pyobject = _Inferred(callback, _get_concluded_data(module)) - - def get_object(self): - return self.pyobject.get() - - def get_definition_location(self): - return (self.module, self.lineno) - - def invalidate(self): - """Forget the `PyObject` this `PyName` holds""" - self.pyobject.set(None) - - -class ParameterName(PyName): - """Only a placeholder""" - - -class ImportedModule(PyName): - - def __init__(self, importing_module, module_name=None, - level=0, resource=None): - self.importing_module = importing_module - self.module_name = module_name - self.level = level - self.resource = resource - self.pymodule = _get_concluded_data(self.importing_module) - - def _current_folder(self): - resource = self.importing_module.get_module().get_resource() - if resource is None: - return None - return resource.parent - - def _get_pymodule(self): - if self.pymodule.get() is None: - pycore = self.importing_module.pycore - if self.resource is not None: - self.pymodule.set(pycore.resource_to_pyobject(self.resource)) - elif self.module_name is not None: - try: - if self.level == 0: - pymodule = pycore.get_module(self.module_name, - self._current_folder()) - else: - pymodule = pycore.get_relative_module( - self.module_name, self._current_folder(), self.level) - self.pymodule.set(pymodule) - except exceptions.ModuleNotFoundError: - pass - return self.pymodule.get() - - def get_object(self): - if self._get_pymodule() is None: - return rope.base.pyobjects.get_unknown() - return self._get_pymodule() - - def get_definition_location(self): - pymodule = self._get_pymodule() - if not isinstance(pymodule, rope.base.pyobjects.PyDefinedObject): - return (None, None) - return (pymodule.get_module(), 1) - - -class ImportedName(PyName): - - def __init__(self, imported_module, imported_name): - self.imported_module = imported_module - self.imported_name = imported_name - - def _get_imported_pyname(self): - try: - result = self.imported_module.get_object()[self.imported_name] - if result != self: - return result - except exceptions.AttributeNotFoundError: - pass - return UnboundName() - - @utils.prevent_recursion(rope.base.pyobjects.get_unknown) - def get_object(self): - return self._get_imported_pyname().get_object() - - @utils.prevent_recursion(lambda: (None, None)) - def get_definition_location(self): - return self._get_imported_pyname().get_definition_location() - - -def _get_concluded_data(module): - if module is None: - return rope.base.pyobjects._ConcludedData() - return module._get_concluded_data() - - -def _circular_inference(): - raise rope.base.pyobjects.IsBeingInferredError( - 'Circular Object Inference') - -class _Inferred(object): - - def __init__(self, get_inferred, concluded=None): - self.get_inferred = get_inferred - self.concluded = concluded - if self.concluded is None: - self.temp = None - - @utils.prevent_recursion(_circular_inference) - def get(self, *args, **kwds): - if self.concluded is None or self.concluded.get() is None: - self.set(self.get_inferred(*args, **kwds)) - if self._get() is None: - self.set(rope.base.pyobjects.get_unknown()) - return self._get() - - def set(self, pyobject): - if self.concluded is not None: - self.concluded.set(pyobject) - self.temp = pyobject - - def _get(self): - if self.concluded is not None: - return self.concluded.get() - return self.temp diff --git a/.vim/bundle/python-mode/pylibs/rope/base/pynamesdef.py b/.vim/bundle/python-mode/pylibs/rope/base/pynamesdef.py @@ -1,55 +0,0 @@ -import rope.base.oi.soi -from rope.base import pynames -from rope.base.pynames import * - - -class AssignedName(pynames.AssignedName): - - def __init__(self, lineno=None, module=None, pyobject=None): - self.lineno = lineno - self.module = module - self.assignments = [] - self.pyobject = _Inferred(self._get_inferred, - pynames._get_concluded_data(module)) - self.pyobject.set(pyobject) - - @utils.prevent_recursion(lambda: None) - def _get_inferred(self): - if self.module is not None: - return rope.base.oi.soi.infer_assigned_object(self) - - def get_object(self): - return self.pyobject.get() - - def get_definition_location(self): - """Returns a (module, lineno) tuple""" - if self.lineno is None and self.assignments: - self.lineno = self.assignments[0].get_lineno() - return (self.module, self.lineno) - - def invalidate(self): - """Forget the `PyObject` this `PyName` holds""" - self.pyobject.set(None) - - -class ParameterName(pynames.ParameterName): - - def __init__(self, pyfunction, index): - self.pyfunction = pyfunction - self.index = index - - def get_object(self): - result = self.pyfunction.get_parameter(self.index) - if result is None: - result = rope.base.pyobjects.get_unknown() - return result - - def get_objects(self): - """Returns the list of objects passed as this parameter""" - return rope.base.oi.soi.get_passed_objects( - self.pyfunction, self.index) - - def get_definition_location(self): - return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno) - -_Inferred = pynames._Inferred diff --git a/.vim/bundle/python-mode/pylibs/rope/base/pyobjects.py b/.vim/bundle/python-mode/pylibs/rope/base/pyobjects.py @@ -1,311 +0,0 @@ -from rope.base.fscommands import _decode_data -from rope.base import ast, exceptions, utils - - -class PyObject(object): - - def __init__(self, type_): - if type_ is None: - type_ = self - self.type = type_ - - def get_attributes(self): - if self.type is self: - return {} - return self.type.get_attributes() - - def get_attribute(self, name): - if name not in self.get_attributes(): - raise exceptions.AttributeNotFoundError( - 'Attribute %s not found' % name) - return self.get_attributes()[name] - - def get_type(self): - return self.type - - def __getitem__(self, key): - """The same as ``get_attribute(key)``""" - return self.get_attribute(key) - - def __contains__(self, key): - """The same as ``key in self.get_attributes()``""" - return key in self.get_attributes() - - def __eq__(self, obj): - """Check the equality of two `PyObject`\s - - Currently it is assumed that instances (the direct instances - of `PyObject`, not the instances of its subclasses) are equal - if their types are equal. For every other object like - defineds or builtins rope assumes objects are reference - objects and their identities should match. - - """ - if self.__class__ != obj.__class__: - return False - if type(self) == PyObject: - if self is not self.type: - return self.type == obj.type - else: - return self.type is obj.type - return self is obj - - def __ne__(self, obj): - return not self.__eq__(obj) - - def __hash__(self): - """See docs for `__eq__()` method""" - if type(self) == PyObject and self != self.type: - return hash(self.type) + 1 - else: - return super(PyObject, self).__hash__() - - def __iter__(self): - """The same as ``iter(self.get_attributes())``""" - return iter(self.get_attributes()) - - _types = None - _unknown = None - - @staticmethod - def _get_base_type(name): - if PyObject._types is None: - PyObject._types = {} - base_type = PyObject(None) - PyObject._types['Type'] = base_type - PyObject._types['Module'] = PyObject(base_type) - PyObject._types['Function'] = PyObject(base_type) - PyObject._types['Unknown'] = PyObject(base_type) - return PyObject._types[name] - - -def get_base_type(name): - """Return the base type with name `name`. - - The base types are 'Type', 'Function', 'Module' and 'Unknown'. It - was used to check the type of a `PyObject` but currently its use - is discouraged. Use classes defined in this module instead. - For example instead of - ``pyobject.get_type() == get_base_type('Function')`` use - ``isinstance(pyobject, AbstractFunction)``. - - You can use `AbstractClass` for classes, `AbstractFunction` for - functions, and `AbstractModule` for modules. You can also use - `PyFunction` and `PyClass` for testing if an object is - defined somewhere and rope can access its source. These classes - provide more methods. - - """ - return PyObject._get_base_type(name) - - -def get_unknown(): - """Return a pyobject whose type is unknown - - Note that two unknown objects are equal. So for example you can - write:: - - if pyname.get_object() == get_unknown(): - print 'cannot determine what this pyname holds' - - Rope could have used `None` for indicating unknown objects but - we had to check that in many places. So actually this method - returns a null object. - - """ - if PyObject._unknown is None: - PyObject._unknown = PyObject(get_base_type('Unknown')) - return PyObject._unknown - - -class AbstractClass(PyObject): - - def __init__(self): - super(AbstractClass, self).__init__(get_base_type('Type')) - - def get_name(self): - pass - - def get_doc(self): - pass - - def get_superclasses(self): - return [] - - -class AbstractFunction(PyObject): - - def __init__(self): - super(AbstractFunction, self).__init__(get_base_type('Function')) - - def get_name(self): - pass - - def get_doc(self): - pass - - def get_param_names(self, special_args=True): - return [] - - def get_returned_object(self, args): - return get_unknown() - - -class AbstractModule(PyObject): - - def __init__(self, doc=None): - super(AbstractModule, self).__init__(get_base_type('Module')) - - def get_doc(self): - pass - - def get_resource(self): - pass - - -class PyDefinedObject(object): - """Python defined names that rope can access their sources""" - - def __init__(self, pycore, ast_node, parent): - self.pycore = pycore - self.ast_node = ast_node - self.scope = None - self.parent = parent - self.structural_attributes = None - self.concluded_attributes = self.get_module()._get_concluded_data() - self.attributes = self.get_module()._get_concluded_data() - self.defineds = None - - visitor_class = None - - @utils.prevent_recursion(lambda: {}) - def _get_structural_attributes(self): - if self.structural_attributes is None: - self.structural_attributes = self._create_structural_attributes() - return self.structural_attributes - - @utils.prevent_recursion(lambda: {}) - def _get_concluded_attributes(self): - if self.concluded_attributes.get() is None: - self._get_structural_attributes() - self.concluded_attributes.set(self._create_concluded_attributes()) - return self.concluded_attributes.get() - - def get_attributes(self): - if self.attributes.get() is None: - result = dict(self._get_concluded_attributes()) - result.update(self._get_structural_attributes()) - self.attributes.set(result) - return self.attributes.get() - - def get_attribute(self, name): - if name in self._get_structural_attributes(): - return self._get_structural_attributes()[name] - if name in self._get_concluded_attributes(): - return self._get_concluded_attributes()[name] - raise exceptions.AttributeNotFoundError('Attribute %s not found' % - name) - - def get_scope(self): - if self.scope is None: - self.scope = self._create_scope() - return self.scope - - def get_module(self): - current_object = self - while current_object.parent is not None: - current_object = current_object.parent - return current_object - - def get_doc(self): - if len(self.get_ast().body) > 0: - expr = self.get_ast().body[0] - if isinstance(expr, ast.Expr) and \ - isinstance(expr.value, ast.Str): - docstring = expr.value.s - coding = self.get_module().coding - return _decode_data(docstring, coding) - - def _get_defined_objects(self): - if self.defineds is None: - self._get_structural_attributes() - return self.defineds - - def _create_structural_attributes(self): - if self.visitor_class is None: - return {} - new_visitor = self.visitor_class(self.pycore, self) - for child in ast.get_child_nodes(self.ast_node): - ast.walk(child, new_visitor) - self.defineds = new_visitor.defineds - return new_visitor.names - - def _create_concluded_attributes(self): - return {} - - def get_ast(self): - return self.ast_node - - def _create_scope(self): - pass - - -class PyFunction(PyDefinedObject, AbstractFunction): - """Only a placeholder""" - - -class PyClass(PyDefinedObject, AbstractClass): - """Only a placeholder""" - - -class _ConcludedData(object): - - def __init__(self): - self.data_ = None - - def set(self, data): - self.data_ = data - - def get(self): - return self.data_ - - data = property(get, set) - - def _invalidate(self): - self.data = None - - def __str__(self): - return '<' + str(self.data) + '>' - - -class _PyModule(PyDefinedObject, AbstractModule): - - def __init__(self, pycore, ast_node, resource): - self.resource = resource - self.concluded_data = [] - AbstractModule.__init__(self) - PyDefinedObject.__init__(self, pycore, ast_node, None) - - def _get_concluded_data(self): - new_data = _ConcludedData() - self.concluded_data.append(new_data) - return new_data - - def _forget_concluded_data(self): - for data in self.concluded_data: - data._invalidate() - - def get_resource(self): - return self.resource - - -class PyModule(_PyModule): - """Only a placeholder""" - - -class PyPackage(_PyModule): - """Only a placeholder""" - - -class IsBeingInferredError(exceptions.RopeError): - pass diff --git a/.vim/bundle/python-mode/pylibs/rope/base/pyobjectsdef.py b/.vim/bundle/python-mode/pylibs/rope/base/pyobjectsdef.py @@ -1,537 +0,0 @@ -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.builtins -import rope.base.oi.soi -import rope.base.pyscopes -from rope.base import (pynamesdef as pynames, exceptions, ast, - astutils, pyobjects, fscommands, arguments, utils) -from rope.base.pyobjects import * - - -class PyFunction(pyobjects.PyFunction): - - def __init__(self, pycore, ast_node, parent): - AbstractFunction.__init__(self) - PyDefinedObject.__init__(self, pycore, ast_node, parent) - self.arguments = self.ast_node.args - self.parameter_pyobjects = pynames._Inferred( - self._infer_parameters, self.get_module()._get_concluded_data()) - self.returned = pynames._Inferred(self._infer_returned) - self.parameter_pynames = None - - def _create_structural_attributes(self): - return {} - - def _create_concluded_attributes(self): - return {} - - def _create_scope(self): - return rope.base.pyscopes.FunctionScope(self.pycore, self, - _FunctionVisitor) - - def _infer_parameters(self): - pyobjects = rope.base.oi.soi.infer_parameter_objects(self) - self._handle_special_args(pyobjects) - return pyobjects - - def _infer_returned(self, args=None): - return rope.base.oi.soi.infer_returned_object(self, args) - - def _handle_special_args(self, pyobjects): - if len(pyobjects) == len(self.arguments.args): - if self.arguments.vararg: - pyobjects.append(rope.base.builtins.get_list()) - if self.arguments.kwarg: - pyobjects.append(rope.base.builtins.get_dict()) - - def _set_parameter_pyobjects(self, pyobjects): - if pyobjects is not None: - self._handle_special_args(pyobjects) - self.parameter_pyobjects.set(pyobjects) - - def get_parameters(self): - if self.parameter_pynames is None: - result = {} - for index, name in enumerate(self.get_param_names()): - # TODO: handle tuple parameters - result[name] = pynames.ParameterName(self, index) - self.parameter_pynames = result - return self.parameter_pynames - - def get_parameter(self, index): - if index < len(self.parameter_pyobjects.get()): - return self.parameter_pyobjects.get()[index] - - def get_returned_object(self, args): - return self.returned.get(args) - - def get_name(self): - return self.get_ast().name - - def get_param_names(self, special_args=True): - # TODO: handle tuple parameters - result = [node.id for node in self.arguments.args - if isinstance(node, ast.Name)] - if special_args: - if self.arguments.vararg: - result.append(self.arguments.vararg) - if self.arguments.kwarg: - result.append(self.arguments.kwarg) - return result - - def get_kind(self): - """Get function type - - It returns one of 'function', 'method', 'staticmethod' or - 'classmethod' strs. - - """ - scope = self.parent.get_scope() - if isinstance(self.parent, PyClass): - for decorator in self.decorators: - pyname = rope.base.evaluate.eval_node(scope, decorator) - if pyname == rope.base.builtins.builtins['staticmethod']: - return 'staticmethod' - if pyname == rope.base.builtins.builtins['classmethod']: - return 'classmethod' - return 'method' - return 'function' - - @property - def decorators(self): - try: - return getattr(self.ast_node, 'decorator_list') - except AttributeError: - return getattr(self.ast_node, 'decorators', None) - - -class PyClass(pyobjects.PyClass): - - def __init__(self, pycore, ast_node, parent): - self.visitor_class = _ClassVisitor - AbstractClass.__init__(self) - PyDefinedObject.__init__(self, pycore, ast_node, parent) - self.parent = parent - self._superclasses = self.get_module()._get_concluded_data() - - def get_superclasses(self): - if self._superclasses.get() is None: - self._superclasses.set(self._get_bases()) - return self._superclasses.get() - - def get_name(self): - return self.get_ast().name - - def _create_concluded_attributes(self): - result = {} - for base in reversed(self.get_superclasses()): - result.update(base.get_attributes()) - return result - - def _get_bases(self): - result = [] - for base_name in self.ast_node.bases: - base = rope.base.evaluate.eval_node(self.parent.get_scope(), - base_name) - if base is not None and \ - base.get_object().get_type() == get_base_type('Type'): - result.append(base.get_object()) - return result - - def _create_scope(self): - return rope.base.pyscopes.ClassScope(self.pycore, self) - - -class PyModule(pyobjects.PyModule): - - def __init__(self, pycore, source=None, - resource=None, force_errors=False): - ignore = pycore.project.prefs.get('ignore_syntax_errors', False) - syntax_errors = force_errors or not ignore - self.has_errors = False - try: - source, node = self._init_source(pycore, source, resource) - except exceptions.ModuleSyntaxError: - self.has_errors = True - if syntax_errors: - raise - else: - source = '\n' - node = ast.parse('\n') - self.source_code = source - self.star_imports = [] - self.visitor_class = _GlobalVisitor - self.coding = fscommands.read_str_coding(self.source_code) - super(PyModule, self).__init__(pycore, node, resource) - - def _init_source(self, pycore, source_code, resource): - filename = 'string' - if resource: - filename = resource.path - try: - if source_code is None: - source_bytes = resource.read_bytes() - source_code = fscommands.file_data_to_unicode(source_bytes) - else: - if isinstance(source_code, unicode): - source_bytes = fscommands.unicode_to_file_data(source_code) - else: - source_bytes = source_code - ast_node = ast.parse(source_bytes, filename=filename) - except SyntaxError, e: - raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) - except UnicodeDecodeError, e: - raise exceptions.ModuleSyntaxError(filename, 1, '%s' % (e.reason)) - return source_code, ast_node - - @utils.prevent_recursion(lambda: {}) - def _create_concluded_attributes(self): - result = {} - for star_import in self.star_imports: - result.update(star_import.get_names()) - return result - - def _create_scope(self): - return rope.base.pyscopes.GlobalScope(self.pycore, self) - - @property - @utils.saveit - def lines(self): - """A `SourceLinesAdapter`""" - return rope.base.codeanalyze.SourceLinesAdapter(self.source_code) - - @property - @utils.saveit - def logical_lines(self): - """A `LogicalLinesFinder`""" - return rope.base.codeanalyze.CachingLogicalLineFinder(self.lines) - - -class PyPackage(pyobjects.PyPackage): - - def __init__(self, pycore, resource=None, force_errors=False): - self.resource = resource - init_dot_py = self._get_init_dot_py() - if init_dot_py is not None: - ast_node = pycore.resource_to_pyobject( - init_dot_py, force_errors=force_errors).get_ast() - else: - ast_node = ast.parse('\n') - super(PyPackage, self).__init__(pycore, ast_node, resource) - - def _create_structural_attributes(self): - result = {} - modname = self.pycore.modname(self.resource) - extension_submodules = self.pycore._builtin_submodules(modname) - for name, module in extension_submodules.iteritems(): - result[name] = rope.base.builtins.BuiltinName(module) - if self.resource is None: - return result - for name, resource in self._get_child_resources().items(): - result[name] = pynames.ImportedModule(self, resource=resource) - return result - - def _create_concluded_attributes(self): - result = {} - init_dot_py = self._get_init_dot_py() - if init_dot_py: - init_object = self.pycore.resource_to_pyobject(init_dot_py) - result.update(init_object.get_attributes()) - return result - - def _get_child_resources(self): - result = {} - for child in self.resource.get_children(): - if child.is_folder(): - result[child.name] = child - elif child.name.endswith('.py') and \ - child.name != '__init__.py': - name = child.name[:-3] - result[name] = child - return result - - def _get_init_dot_py(self): - if self.resource is not None and self.resource.has_child('__init__.py'): - return self.resource.get_child('__init__.py') - else: - return None - - def _create_scope(self): - return self.get_module().get_scope() - - def get_module(self): - init_dot_py = self._get_init_dot_py() - if init_dot_py: - return self.pycore.resource_to_pyobject(init_dot_py) - return self - - -class _AssignVisitor(object): - - def __init__(self, scope_visitor): - self.scope_visitor = scope_visitor - self.assigned_ast = None - - def _Assign(self, node): - self.assigned_ast = node.value - for child_node in node.targets: - ast.walk(child_node, self) - - def _assigned(self, name, assignment=None): - self.scope_visitor._assigned(name, assignment) - - def _Name(self, node): - assignment = None - if self.assigned_ast is not None: - assignment = pynames.AssignmentValue(self.assigned_ast) - self._assigned(node.id, assignment) - - def _Tuple(self, node): - names = astutils.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: - assignment = pynames.AssignmentValue(self.assigned_ast, levels) - self._assigned(name, assignment) - - def _Attribute(self, node): - pass - - def _Subscript(self, node): - pass - - def _Slice(self, node): - pass - - -class _ScopeVisitor(object): - - def __init__(self, pycore, owner_object): - self.pycore = pycore - self.owner_object = owner_object - self.names = {} - self.defineds = [] - - def get_module(self): - if self.owner_object is not None: - return self.owner_object.get_module() - else: - return None - - def _ClassDef(self, node): - pyclass = PyClass(self.pycore, node, self.owner_object) - self.names[node.name] = pynames.DefinedName(pyclass) - self.defineds.append(pyclass) - - def _FunctionDef(self, node): - pyfunction = PyFunction(self.pycore, node, self.owner_object) - for decorator in pyfunction.decorators: - if isinstance(decorator, ast.Name) and decorator.id == 'property': - if isinstance(self, _ClassVisitor): - type_ = rope.base.builtins.Property(pyfunction) - arg = pynames.UnboundName(PyObject(self.owner_object)) - def _eval(type_=type_, arg=arg): - return type_.get_property_object( - arguments.ObjectArguments([arg])) - self.names[node.name] = pynames.EvaluatedName( - _eval, module=self.get_module(), lineno=node.lineno) - break - else: - self.names[node.name] = pynames.DefinedName(pyfunction) - self.defineds.append(pyfunction) - - def _Assign(self, node): - ast.walk(node, _AssignVisitor(self)) - - def _AugAssign(self, node): - pass - - def _For(self, node): - names = self._update_evaluated(node.target, node.iter, - '.__iter__().next()') - for child in node.body + node.orelse: - ast.walk(child, self) - - def _assigned(self, name, assignment): - pyname = self.names.get(name, None) - if pyname is None: - pyname = pynames.AssignedName(module=self.get_module()) - if isinstance(pyname, pynames.AssignedName): - if assignment is not None: - pyname.assignments.append(assignment) - self.names[name] = pyname - - def _update_evaluated(self, targets, assigned, - evaluation= '', eval_type=False): - result = {} - names = astutils.get_name_levels(targets) - for name, levels in names: - assignment = pynames.AssignmentValue(assigned, levels, - evaluation, eval_type) - self._assigned(name, assignment) - return result - - def _With(self, node): - if node.optional_vars: - self._update_evaluated(node.optional_vars, - node.context_expr, '.__enter__()') - for child in node.body: - ast.walk(child, self) - - def _excepthandler(self, node): - if node.name is not None and isinstance(node.name, ast.Name): - type_node = node.type - if isinstance(node.type, ast.Tuple) and type_node.elts: - type_node = type_node.elts[0] - self._update_evaluated(node.name, type_node, eval_type=True) - for child in node.body: - ast.walk(child, self) - - def _ExceptHandler(self, node): - self._excepthandler(node) - - def _Import(self, node): - for import_pair in node.names: - module_name = import_pair.name - alias = import_pair.asname - first_package = module_name.split('.')[0] - if alias is not None: - imported = pynames.ImportedModule(self.get_module(), - module_name) - if not self._is_ignored_import(imported): - self.names[alias] = imported - else: - imported = pynames.ImportedModule(self.get_module(), - first_package) - if not self._is_ignored_import(imported): - self.names[first_package] = imported - - def _ImportFrom(self, node): - level = 0 - if node.level: - level = node.level - imported_module = pynames.ImportedModule(self.get_module(), - node.module, level) - if self._is_ignored_import(imported_module): - return - if len(node.names) == 1 and node.names[0].name == '*': - if isinstance(self.owner_object, PyModule): - self.owner_object.star_imports.append( - StarImport(imported_module)) - else: - for imported_name in node.names: - imported = imported_name.name - alias = imported_name.asname - if alias is not None: - imported = alias - self.names[imported] = pynames.ImportedName(imported_module, - imported_name.name) - - def _is_ignored_import(self, imported_module): - if not self.pycore.project.prefs.get('ignore_bad_imports', False): - return False - return not isinstance(imported_module.get_object(), AbstractModule) - - def _Global(self, node): - module = self.get_module() - for name in node.names: - if module is not None: - try: - pyname = module[name] - except exceptions.AttributeNotFoundError: - pyname = pynames.AssignedName(node.lineno) - self.names[name] = pyname - - -class _GlobalVisitor(_ScopeVisitor): - - def __init__(self, pycore, owner_object): - super(_GlobalVisitor, self).__init__(pycore, owner_object) - - -class _ClassVisitor(_ScopeVisitor): - - def __init__(self, pycore, owner_object): - super(_ClassVisitor, self).__init__(pycore, owner_object) - - def _FunctionDef(self, node): - _ScopeVisitor._FunctionDef(self, node) - if len(node.args.args) > 0: - first = node.args.args[0] - if isinstance(first, ast.Name): - new_visitor = _ClassInitVisitor(self, first.id) - for child in ast.get_child_nodes(node): - ast.walk(child, new_visitor) - - -class _FunctionVisitor(_ScopeVisitor): - - def __init__(self, pycore, owner_object): - super(_FunctionVisitor, self).__init__(pycore, owner_object) - self.returned_asts = [] - self.generator = False - - def _Return(self, node): - if node.value is not None: - self.returned_asts.append(node.value) - - def _Yield(self, node): - if node.value is not None: - self.returned_asts.append(node.value) - self.generator = True - - -class _ClassInitVisitor(_AssignVisitor): - - def __init__(self, scope_visitor, self_name): - super(_ClassInitVisitor, self).__init__(scope_visitor) - self.self_name = self_name - - def _Attribute(self, node): - if not isinstance(node.ctx, ast.Store): - return - if isinstance(node.value, ast.Name) and \ - node.value.id == self.self_name: - if node.attr not in self.scope_visitor.names: - self.scope_visitor.names[node.attr] = pynames.AssignedName( - lineno=node.lineno, module=self.scope_visitor.get_module()) - if self.assigned_ast is not None: - pyname = self.scope_visitor.names[node.attr] - if isinstance(pyname, pynames.AssignedName): - pyname.assignments.append( - pynames.AssignmentValue(self.assigned_ast)) - - def _Tuple(self, node): - if not isinstance(node.ctx, ast.Store): - return - for child in ast.get_child_nodes(node): - ast.walk(child, self) - - def _Name(self, node): - pass - - def _FunctionDef(self, node): - pass - - def _ClassDef(self, node): - pass - - def _For(self, node): - pass - - def _With(self, node): - pass - - -class StarImport(object): - - def __init__(self, imported_module): - self.imported_module = imported_module - - def get_names(self): - result = {} - imported = self.imported_module.get_object() - for name in imported: - if not name.startswith('_'): - result[name] = pynames.ImportedName(self.imported_module, name) - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/base/pyscopes.py b/.vim/bundle/python-mode/pylibs/rope/base/pyscopes.py @@ -1,313 +0,0 @@ -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.pynames -from rope.base import ast, exceptions, utils - - -class Scope(object): - - def __init__(self, pycore, pyobject, parent_scope): - self.pycore = pycore - self.pyobject = pyobject - self.parent = parent_scope - - def get_names(self): - """Return the names defined or imported in this scope""" - return self.pyobject.get_attributes() - - def get_defined_names(self): - """Return the names defined in this scope""" - return self.pyobject._get_structural_attributes() - - def get_name(self, name): - """Return name `PyName` defined in this scope""" - if name not in self.get_names(): - raise exceptions.NameNotFoundError('name %s not found' % name) - return self.get_names()[name] - - def __getitem__(self, key): - """The same as ``get_name(key)``""" - return self.get_name(key) - - def __contains__(self, key): - """The same as ``key in self.get_names()``""" - return key in self.get_names() - - @utils.saveit - def get_scopes(self): - """Return the subscopes of this scope - - The returned scopes should be sorted by the order they appear. - """ - return self._create_scopes() - - def lookup(self, name): - if name in self.get_names(): - return self.get_names()[name] - if self.parent is not None: - return self.parent._propagated_lookup(name) - return None - - def get_propagated_names(self): - """Return the visible names of this scope - - Return the names defined in this scope that are visible from - scopes containing this scope. This method returns the same - dictionary returned by `get_names()` except for `ClassScope` - which returns an empty dict. - """ - return self.get_names() - - def _propagated_lookup(self, name): - if name in self.get_propagated_names(): - return self.get_propagated_names()[name] - if self.parent is not None: - return self.parent._propagated_lookup(name) - return None - - def _create_scopes(self): - return [pydefined.get_scope() - for pydefined in self.pyobject._get_defined_objects()] - - def _get_global_scope(self): - current = self - while current.parent is not None: - current = current.parent - return current - - def get_start(self): - return self.pyobject.get_ast().lineno - - def get_body_start(self): - body = self.pyobject.get_ast().body - if body: - return body[0].lineno - return self.get_start() - - def get_end(self): - pymodule = self._get_global_scope().pyobject - return pymodule.logical_lines.logical_line_in(self.logical_end)[1] - - @utils.saveit - def get_logical_end(self): - global_scope = self._get_global_scope() - return global_scope._scope_finder.find_scope_end(self) - - start = property(get_start) - end = property(get_end) - logical_end = property(get_logical_end) - - def get_kind(self): - pass - - -class GlobalScope(Scope): - - def __init__(self, pycore, module): - super(GlobalScope, self).__init__(pycore, module, None) - self.names = module._get_concluded_data() - - def get_start(self): - return 1 - - def get_kind(self): - return 'Module' - - def get_name(self, name): - try: - return self.pyobject[name] - except exceptions.AttributeNotFoundError: - if name in self.builtin_names: - return self.builtin_names[name] - raise exceptions.NameNotFoundError('name %s not found' % name) - - def get_names(self): - if self.names.get() is None: - result = dict(self.builtin_names) - result.update(super(GlobalScope, self).get_names()) - self.names.set(result) - return self.names.get() - - def get_inner_scope_for_line(self, lineno, indents=None): - return self._scope_finder.get_holding_scope(self, lineno, indents) - - def get_inner_scope_for_offset(self, offset): - return self._scope_finder.get_holding_scope_for_offset(self, offset) - - @property - @utils.saveit - def _scope_finder(self): - return _HoldingScopeFinder(self.pyobject) - - @property - def builtin_names(self): - return rope.base.builtins.builtins.get_attributes() - - -class FunctionScope(Scope): - - def __init__(self, pycore, pyobject, visitor): - super(FunctionScope, self).__init__(pycore, pyobject, - pyobject.parent.get_scope()) - self.names = None - self.returned_asts = None - self.is_generator = None - self.defineds = None - self.visitor = visitor - - def _get_names(self): - if self.names is None: - self._visit_function() - return self.names - - def _visit_function(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) - for n in ast.get_child_nodes(self.pyobject.get_ast()): - ast.walk(n, new_visitor) - self.names = new_visitor.names - self.names.update(self.pyobject.get_parameters()) - self.returned_asts = new_visitor.returned_asts - self.is_generator = new_visitor.generator - self.defineds = new_visitor.defineds - - def _get_returned_asts(self): - if self.names is None: - self._visit_function() - return self.returned_asts - - def _is_generator(self): - if self.is_generator is None: - self._get_returned_asts() - return self.is_generator - - def get_names(self): - return self._get_names() - - def _create_scopes(self): - if self.defineds is None: - self._visit_function() - return [pydefined.get_scope() for pydefined in self.defineds] - - def get_kind(self): - return 'Function' - - def invalidate_data(self): - for pyname in self.get_names().values(): - if isinstance(pyname, (rope.base.pynames.AssignedName, - rope.base.pynames.EvaluatedName)): - pyname.invalidate() - - -class ClassScope(Scope): - - def __init__(self, pycore, pyobject): - super(ClassScope, self).__init__(pycore, pyobject, - pyobject.parent.get_scope()) - - def get_kind(self): - return 'Class' - - def get_propagated_names(self): - return {} - - -class _HoldingScopeFinder(object): - - def __init__(self, pymodule): - self.pymodule = pymodule - - def get_indents(self, lineno): - return rope.base.codeanalyze.count_line_indents( - self.lines.get_line(lineno)) - - def _get_scope_indents(self, scope): - return self.get_indents(scope.get_start()) - - def get_holding_scope(self, module_scope, lineno, line_indents=None): - if line_indents is None: - line_indents = self.get_indents(lineno) - current_scope = module_scope - new_scope = current_scope - while new_scope is not None and \ - (new_scope.get_kind() == 'Module' or - self._get_scope_indents(new_scope) <= line_indents): - current_scope = new_scope - if current_scope.get_start() == lineno and \ - current_scope.get_kind() != 'Module': - return current_scope - new_scope = None - for scope in current_scope.get_scopes(): - if scope.get_start() <= lineno: - if lineno <= scope.get_end(): - new_scope = scope - break - else: - break - return current_scope - - def _is_empty_line(self, lineno): - line = self.lines.get_line(lineno) - return line.strip() == '' or line.lstrip().startswith('#') - - def _get_body_indents(self, scope): - return self.get_indents(scope.get_body_start()) - - def get_holding_scope_for_offset(self, scope, offset): - return self.get_holding_scope( - scope, self.lines.get_line_number(offset)) - - def find_scope_end(self, scope): - if not scope.parent: - return self.lines.length() - end = scope.pyobject.get_ast().body[-1].lineno - scope_start = self.pymodule.logical_lines.logical_line_in(scope.start) - if scope_start[1] >= end: - # handling one-liners - body_indents = self._get_scope_indents(scope) + 4 - else: - body_indents = self._get_body_indents(scope) - for l in self.logical_lines.generate_starts( - min(end + 1, self.lines.length()), self.lines.length() + 1): - if not self._is_empty_line(l): - if self.get_indents(l) < body_indents: - return end - else: - end = l - return end - - @property - def lines(self): - return self.pymodule.lines - - @property - def code(self): - return self.pymodule.source_code - - @property - def logical_lines(self): - return self.pymodule.logical_lines - -class TemporaryScope(Scope): - """Currently used for list comprehensions and generator expressions - - These scopes do not appear in the `get_scopes()` method of their - parent scopes. - """ - - def __init__(self, pycore, parent_scope, names): - super(TemporaryScope, self).__init__( - pycore, parent_scope.pyobject, parent_scope) - self.names = names - - def get_names(self): - return self.names - - def get_defined_names(self): - return self.names - - def _create_scopes(self): - return [] - - def get_kind(self): - return 'Temporary' diff --git a/.vim/bundle/python-mode/pylibs/rope/base/resourceobserver.py b/.vim/bundle/python-mode/pylibs/rope/base/resourceobserver.py @@ -1,271 +0,0 @@ -import os - - -class ResourceObserver(object): - """Provides the interface for observing resources - - `ResourceObserver`\s can be registered using `Project. - add_observer()`. But most of the time `FilteredResourceObserver` - should be used. `ResourceObserver`\s report all changes passed - to them and they don't report changes to all resources. For - example if a folder is removed, it only calls `removed()` for that - folder and not its contents. You can use - `FilteredResourceObserver` if you are interested in changes only - to a list of resources. And you want changes to be reported on - individual resources. - - """ - - def __init__(self, changed=None, moved=None, created=None, - removed=None, validate=None): - self.changed = changed - self.moved = moved - self.created = created - self.removed = removed - self._validate = validate - - def resource_changed(self, resource): - """It is called when the resource changes""" - if self.changed is not None: - self.changed(resource) - - def resource_moved(self, resource, new_resource): - """It is called when a resource is moved""" - if self.moved is not None: - self.moved(resource, new_resource) - - def resource_created(self, resource): - """Is called when a new resource is created""" - if self.created is not None: - self.created(resource) - - def resource_removed(self, resource): - """Is called when a new resource is removed""" - if self.removed is not None: - self.removed(resource) - - def validate(self, resource): - """Validate the existence of this resource and its children. - - This function is called when rope need to update its resource - cache about the files that might have been changed or removed - by other processes. - - """ - if self._validate is not None: - self._validate(resource) - - -class FilteredResourceObserver(object): - """A useful decorator for `ResourceObserver` - - Most resource observers have a list of resources and are - interested only in changes to those files. This class satisfies - this need. It dispatches resource changed and removed messages. - It performs these tasks: - - * Changes to files and folders are analyzed to check whether any - of the interesting resources are changed or not. If they are, - it reports these changes to `resource_observer` passed to the - constructor. - * When a resource is removed it checks whether any of the - interesting resources are contained in that folder and reports - them to `resource_observer`. - * When validating a folder it validates all of the interesting - files in that folder. - - Since most resource observers are interested in a list of - resources that change over time, `add_resource` and - `remove_resource` might be useful. - - """ - - def __init__(self, resource_observer, initial_resources=None, - timekeeper=None): - self.observer = resource_observer - self.resources = {} - if timekeeper is not None: - self.timekeeper = timekeeper - else: - self.timekeeper = ChangeIndicator() - if initial_resources is not None: - for resource in initial_resources: - self.add_resource(resource) - - def add_resource(self, resource): - """Add a resource to the list of interesting resources""" - if resource.exists(): - self.resources[resource] = self.timekeeper.get_indicator(resource) - else: - self.resources[resource] = None - - def remove_resource(self, resource): - """Add a resource to the list of interesting resources""" - if resource in self.resources: - del self.resources[resource] - - def clear_resources(self): - """Removes all registered resources""" - self.resources.clear() - - def resource_changed(self, resource): - changes = _Changes() - self._update_changes_caused_by_changed(changes, resource) - self._perform_changes(changes) - - def _update_changes_caused_by_changed(self, changes, changed): - if changed in self.resources: - changes.add_changed(changed) - if self._is_parent_changed(changed): - changes.add_changed(changed.parent) - - def _update_changes_caused_by_moved(self, changes, resource, - new_resource=None): - if resource in self.resources: - changes.add_removed(resource, new_resource) - if new_resource in self.resources: - changes.add_created(new_resource) - if resource.is_folder(): - for file in list(self.resources): - if resource.contains(file): - new_file = self._calculate_new_resource( - resource, new_resource, file) - changes.add_removed(file, new_file) - if self._is_parent_changed(resource): - changes.add_changed(resource.parent) - if new_resource is not None: - if self._is_parent_changed(new_resource): - changes.add_changed(new_resource.parent) - - def _is_parent_changed(self, child): - return child.parent in self.resources - - def resource_moved(self, resource, new_resource): - changes = _Changes() - self._update_changes_caused_by_moved(changes, resource, new_resource) - self._perform_changes(changes) - - def resource_created(self, resource): - changes = _Changes() - self._update_changes_caused_by_created(changes, resource) - self._perform_changes(changes) - - def _update_changes_caused_by_created(self, changes, resource): - if resource in self.resources: - changes.add_created(resource) - if self._is_parent_changed(resource): - changes.add_changed(resource.parent) - - def resource_removed(self, resource): - changes = _Changes() - self._update_changes_caused_by_moved(changes, resource) - self._perform_changes(changes) - - def _perform_changes(self, changes): - for resource in changes.changes: - self.observer.resource_changed(resource) - self.resources[resource] = self.timekeeper.get_indicator(resource) - for resource, new_resource in changes.moves.items(): - self.resources[resource] = None - if new_resource is not None: - self.observer.resource_moved(resource, new_resource) - else: - self.observer.resource_removed(resource) - for resource in changes.creations: - self.observer.resource_created(resource) - self.resources[resource] = self.timekeeper.get_indicator(resource) - - def validate(self, resource): - changes = _Changes() - for file in self._search_resource_moves(resource): - if file in self.resources: - self._update_changes_caused_by_moved(changes, file) - for file in self._search_resource_changes(resource): - if file in self.resources: - self._update_changes_caused_by_changed(changes, file) - for file in self._search_resource_creations(resource): - if file in self.resources: - changes.add_created(file) - self._perform_changes(changes) - - def _search_resource_creations(self, resource): - creations = set() - if resource in self.resources and resource.exists() and \ - self.resources[resource] is None: - creations.add(resource) - if resource.is_folder(): - for file in self.resources: - if file.exists() and resource.contains(file) and \ - self.resources[file] is None: - creations.add(file) - return creations - - def _search_resource_moves(self, resource): - all_moved = set() - if resource in self.resources and not resource.exists(): - all_moved.add(resource) - if resource.is_folder(): - for file in self.resources: - if resource.contains(file): - if not file.exists(): - all_moved.add(file) - moved = set(all_moved) - for folder in [file for file in all_moved if file.is_folder()]: - if folder in moved: - for file in list(moved): - if folder.contains(file): - moved.remove(file) - return moved - - def _search_resource_changes(self, resource): - changed = set() - if resource in self.resources and self._is_changed(resource): - changed.add(resource) - if resource.is_folder(): - for file in self.resources: - if file.exists() and resource.contains(file): - if self._is_changed(file): - changed.add(file) - return changed - - def _is_changed(self, resource): - if self.resources[resource] is None: - return False - return self.resources[resource] != self.timekeeper.get_indicator(resource) - - def _calculate_new_resource(self, main, new_main, resource): - if new_main is None: - return None - diff = resource.path[len(main.path):] - return resource.project.get_resource(new_main.path + diff) - - -class ChangeIndicator(object): - - def get_indicator(self, resource): - """Return the modification time and size of a `Resource`.""" - path = resource.real_path - # on dos, mtime does not change for a folder when files are added - if os.name != 'posix' and os.path.isdir(path): - return (os.path.getmtime(path), - len(os.listdir(path)), - os.path.getsize(path)) - return (os.path.getmtime(path), - os.path.getsize(path)) - - -class _Changes(object): - - def __init__(self): - self.changes = set() - self.creations = set() - self.moves = {} - - def add_changed(self, resource): - self.changes.add(resource) - - def add_removed(self, resource, new_resource=None): - self.moves[resource] = new_resource - - def add_created(self, resource): - self.creations.add(resource) diff --git a/.vim/bundle/python-mode/pylibs/rope/base/resources.py b/.vim/bundle/python-mode/pylibs/rope/base/resources.py @@ -1,211 +0,0 @@ -import os -import re - -import rope.base.change -import rope.base.fscommands -from rope.base import exceptions - - -class Resource(object): - """Represents files and folders in a project""" - - def __init__(self, project, path): - self.project = project - self._path = path - - def move(self, new_location): - """Move resource to `new_location`""" - self._perform_change(rope.base.change.MoveResource(self, new_location), - 'Moving <%s> to <%s>' % (self.path, new_location)) - - def remove(self): - """Remove resource from the project""" - self._perform_change(rope.base.change.RemoveResource(self), - 'Removing <%s>' % self.path) - - def is_folder(self): - """Return true if the resource is a folder""" - - def create(self): - """Create this resource""" - - def exists(self): - return os.path.exists(self.real_path) - - @property - def parent(self): - parent = '/'.join(self.path.split('/')[0:-1]) - return self.project.get_folder(parent) - - @property - def path(self): - """Return the path of this resource relative to the project root - - The path is the list of parent directories separated by '/' followed - by the resource name. - """ - return self._path - - @property - def name(self): - """Return the name of this resource""" - return self.path.split('/')[-1] - - @property - def real_path(self): - """Return the file system path of this resource""" - return self.project._get_resource_path(self.path) - - def __eq__(self, obj): - return self.__class__ == obj.__class__ and self.path == obj.path - - def __ne__(self, obj): - return not self.__eq__(obj) - - def __hash__(self): - return hash(self.path) - - def _perform_change(self, change_, description): - changes = rope.base.change.ChangeSet(description) - changes.add_change(change_) - self.project.do(changes) - - -class File(Resource): - """Represents a file""" - - def __init__(self, project, name): - super(File, self).__init__(project, name) - - def read(self): - data = self.read_bytes() - try: - return rope.base.fscommands.file_data_to_unicode(data) - except UnicodeDecodeError, e: - raise exceptions.ModuleDecodeError(self.path, e.reason) - - def read_bytes(self): - return open(self.real_path, 'rb').read() - - def write(self, contents): - try: - if contents == self.read(): - return - except IOError: - pass - self._perform_change(rope.base.change.ChangeContents(self, contents), - 'Writing file <%s>' % self.path) - - def is_folder(self): - return False - - def create(self): - self.parent.create_file(self.name) - - -class Folder(Resource): - """Represents a folder""" - - def __init__(self, project, name): - super(Folder, self).__init__(project, name) - - def is_folder(self): - return True - - def get_children(self): - """Return the children of this folder""" - result = [] - for name in os.listdir(self.real_path): - try: - child = self.get_child(name) - except exceptions.ResourceNotFoundError: - continue - if not self.project.is_ignored(child): - result.append(self.get_child(name)) - return result - - def create_file(self, file_name): - self._perform_change( - rope.base.change.CreateFile(self, file_name), - 'Creating file <%s>' % self._get_child_path(file_name)) - return self.get_child(file_name) - - def create_folder(self, folder_name): - self._perform_change( - rope.base.change.CreateFolder(self, folder_name), - 'Creating folder <%s>' % self._get_child_path(folder_name)) - return self.get_child(folder_name) - - def _get_child_path(self, name): - if self.path: - return self.path + '/' + name - else: - return name - - def get_child(self, name): - return self.project.get_resource(self._get_child_path(name)) - - def has_child(self, name): - try: - self.get_child(name) - return True - except exceptions.ResourceNotFoundError: - return False - - def get_files(self): - return [resource for resource in self.get_children() - if not resource.is_folder()] - - def get_folders(self): - return [resource for resource in self.get_children() - if resource.is_folder()] - - def contains(self, resource): - if self == resource: - return False - return self.path == '' or resource.path.startswith(self.path + '/') - - def create(self): - self.parent.create_folder(self.name) - - -class _ResourceMatcher(object): - - def __init__(self): - self.patterns = [] - self._compiled_patterns = [] - - def set_patterns(self, patterns): - """Specify which resources to match - - `patterns` is a `list` of `str`\s that can contain ``*`` and - ``?`` signs for matching resource names. - - """ - self._compiled_patterns = None - self.patterns = patterns - - def _add_pattern(self, pattern): - re_pattern = pattern.replace('.', '\\.').\ - replace('*', '[^/]*').replace('?', '[^/]').\ - replace('//', '/(.*/)?') - re_pattern = '^(.*/)?' + re_pattern + '(/.*)?$' - self.compiled_patterns.append(re.compile(re_pattern)) - - def does_match(self, resource): - for pattern in self.compiled_patterns: - if pattern.match(resource.path): - return True - path = os.path.join(resource.project.address, - *resource.path.split('/')) - if os.path.islink(path): - return True - return False - - @property - def compiled_patterns(self): - if self._compiled_patterns is None: - self._compiled_patterns = [] - for pattern in self.patterns: - self._add_pattern(pattern) - return self._compiled_patterns diff --git a/.vim/bundle/python-mode/pylibs/rope/base/simplify.py b/.vim/bundle/python-mode/pylibs/rope/base/simplify.py @@ -1,55 +0,0 @@ -"""A module to ease code analysis - -This module is here to help source code analysis. -""" -import re - -from rope.base import codeanalyze, utils - - -@utils.cached(7) -def real_code(source): - """Simplify `source` for analysis - - It replaces: - - * comments with spaces - * strs with a new str filled with spaces - * implicit and explicit continuations with spaces - * tabs and semicolons with spaces - - The resulting code is a lot easier to analyze if we are interested - only in offsets. - """ - collector = codeanalyze.ChangeCollector(source) - for start, end in ignored_regions(source): - if source[start] == '#': - replacement = ' ' * (end - start) - else: - replacement = '"%s"' % (' ' * (end - start - 2)) - collector.add_change(start, end, replacement) - source = collector.get_changed() or source - collector = codeanalyze.ChangeCollector(source) - parens = 0 - for match in _parens.finditer(source): - i = match.start() - c = match.group() - if c in '({[': - parens += 1 - if c in ')}]': - parens -= 1 - if c == '\n' and parens > 0: - collector.add_change(i, i + 1, ' ') - source = collector.get_changed() or source - return source.replace('\\\n', ' ').replace('\t', ' ').replace(';', '\n') - - -@utils.cached(7) -def ignored_regions(source): - """Return ignored regions like strings and comments in `source` """ - return [(match.start(), match.end()) for match in _str.finditer(source)] - - -_str = re.compile('%s|%s' % (codeanalyze.get_comment_pattern(), - codeanalyze.get_string_pattern())) -_parens = re.compile(r'[\({\[\]}\)\n]') diff --git a/.vim/bundle/python-mode/pylibs/rope/base/stdmods.py b/.vim/bundle/python-mode/pylibs/rope/base/stdmods.py @@ -1,40 +0,0 @@ -import os -import sys - -from rope.base import utils - - -def _stdlib_path(): - import distutils.sysconfig - return distutils.sysconfig.get_python_lib(standard_lib=True) - -@utils.cached(1) -def standard_modules(): - return python_modules() | dynload_modules() - -@utils.cached(1) -def python_modules(): - result = set() - lib_path = _stdlib_path() - if os.path.exists(lib_path): - for name in os.listdir(lib_path): - path = os.path.join(lib_path, name) - if os.path.isdir(path): - if '-' not in name: - result.add(name) - else: - if name.endswith('.py'): - result.add(name[:-3]) - return result - -@utils.cached(1) -def dynload_modules(): - result = set(sys.builtin_module_names) - dynload_path = os.path.join(_stdlib_path(), 'lib-dynload') - if os.path.exists(dynload_path): - for name in os.listdir(dynload_path): - path = os.path.join(dynload_path, name) - if os.path.isfile(path): - if name.endswith('.so') or name.endswith('.dll'): - result.add(os.path.splitext(name)[0]) - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/base/taskhandle.py b/.vim/bundle/python-mode/pylibs/rope/base/taskhandle.py @@ -1,133 +0,0 @@ -import warnings - -from rope.base import exceptions - - -class TaskHandle(object): - - def __init__(self, name='Task', interrupts=True): - """Construct a TaskHandle - - If `interrupts` is `False` the task won't be interrupted by - calling `TaskHandle.stop()`. - - """ - self.name = name - self.interrupts = interrupts - self.stopped = False - self.job_sets = [] - self.observers = [] - - def stop(self): - """Interrupts the refactoring""" - if self.interrupts: - self.stopped = True - self._inform_observers() - - def current_jobset(self): - """Return the current `JobSet`""" - if self.job_sets: - return self.job_sets[-1] - - def add_observer(self, observer): - """Register an observer for this task handle - - The observer is notified whenever the task is stopped or - a job gets finished. - - """ - self.observers.append(observer) - - def is_stopped(self): - return self.stopped - - def get_jobsets(self): - return self.job_sets - - def create_jobset(self, name='JobSet', count=None): - result = JobSet(self, name=name, count=count) - self.job_sets.append(result) - self._inform_observers() - return result - - def _inform_observers(self): - for observer in list(self.observers): - observer() - - -class JobSet(object): - - def __init__(self, handle, name, count): - self.handle = handle - self.name = name - self.count = count - self.done = 0 - self.job_name = None - - def started_job(self, name): - self.check_status() - self.job_name = name - self.handle._inform_observers() - - def finished_job(self): - self.check_status() - self.done += 1 - self.handle._inform_observers() - self.job_name = None - - def check_status(self): - if self.handle.is_stopped(): - raise exceptions.InterruptedTaskError() - - def get_active_job_name(self): - return self.job_name - - def get_percent_done(self): - if self.count is not None and self.count > 0: - percent = self.done * 100 // self.count - return min(percent, 100) - - def get_name(self): - return self.name - - -class NullTaskHandle(object): - - def __init__(self): - pass - - def is_stopped(self): - return False - - def stop(self): - pass - - def create_jobset(self, *args, **kwds): - return NullJobSet() - - def get_jobsets(self): - return [] - - def add_observer(self, observer): - pass - - -class NullJobSet(object): - - def started_job(self, name): - pass - - def finished_job(self): - pass - - def check_status(self): - pass - - def get_active_job_name(self): - pass - - def get_percent_done(self): - pass - - def get_name(self): - pass diff --git a/.vim/bundle/python-mode/pylibs/rope/base/utils.py b/.vim/bundle/python-mode/pylibs/rope/base/utils.py @@ -1,78 +0,0 @@ -import warnings - - -def saveit(func): - """A decorator that caches the return value of a function""" - - name = '_' + func.__name__ - def _wrapper(self, *args, **kwds): - if not hasattr(self, name): - setattr(self, name, func(self, *args, **kwds)) - return getattr(self, name) - return _wrapper - -cacheit = saveit - -def prevent_recursion(default): - """A decorator that returns the return value of `default` in recursions""" - def decorator(func): - name = '_calling_%s_' % func.__name__ - def newfunc(self, *args, **kwds): - if getattr(self, name, False): - return default() - setattr(self, name, True) - try: - return func(self, *args, **kwds) - finally: - setattr(self, name, False) - return newfunc - return decorator - - -def ignore_exception(exception_class): - """A decorator that ignores `exception_class` exceptions""" - def _decorator(func): - def newfunc(*args, **kwds): - try: - return func(*args, **kwds) - except exception_class: - pass - return newfunc - return _decorator - - -def deprecated(message=None): - """A decorator for deprecated functions""" - def _decorator(func, message=message): - if message is None: - message = '%s is deprecated' % func.__name__ - def newfunc(*args, **kwds): - warnings.warn(message, DeprecationWarning, stacklevel=2) - return func(*args, **kwds) - return newfunc - return _decorator - - -def cached(count): - """A caching decorator based on parameter objects""" - def decorator(func): - return _Cached(func, count) - return decorator - -class _Cached(object): - - def __init__(self, func, count): - self.func = func - self.cache = [] - self.count = count - - def __call__(self, *args, **kwds): - key = (args, kwds) - for cached_key, cached_result in self.cache: - if cached_key == key: - return cached_result - result = self.func(*args, **kwds) - self.cache.append((key, result)) - if len(self.cache) > self.count: - del self.cache[0] - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/base/worder.py b/.vim/bundle/python-mode/pylibs/rope/base/worder.py @@ -1,524 +0,0 @@ -import bisect -import keyword - -import rope.base.simplify - - -def get_name_at(resource, offset): - source_code = resource.read() - word_finder = Worder(source_code) - return word_finder.get_word_at(offset) - - -class Worder(object): - """A class for finding boundaries of words and expressions - - Note that in these methods, offset should be the index of the - character not the index of the character after it. - """ - - def __init__(self, code, handle_ignores=False): - simplified = rope.base.simplify.real_code(code) - self.code_finder = _RealFinder(simplified, code) - self.handle_ignores = handle_ignores - self.code = code - - def _init_ignores(self): - ignores = rope.base.simplify.ignored_regions(self.code) - self.dumb_finder = _RealFinder(self.code, self.code) - self.starts = [ignored[0] for ignored in ignores] - self.ends = [ignored[1] for ignored in ignores] - - def _context_call(self, name, offset): - if self.handle_ignores: - if not hasattr(self, 'starts'): - self._init_ignores() - start = bisect.bisect(self.starts, offset) - if start > 0 and offset < self.ends[start - 1]: - return getattr(self.dumb_finder, name)(offset) - return getattr(self.code_finder, name)(offset) - - def get_primary_at(self, offset): - return self._context_call('get_primary_at', offset) - - def get_word_at(self, offset): - return self._context_call('get_word_at', offset) - - def get_primary_range(self, offset): - return self._context_call('get_primary_range', offset) - - def get_splitted_primary_before(self, offset): - return self._context_call('get_splitted_primary_before', offset) - - def get_word_range(self, offset): - return self._context_call('get_word_range', offset) - - def is_function_keyword_parameter(self, offset): - return self.code_finder.is_function_keyword_parameter(offset) - - def is_a_class_or_function_name_in_header(self, offset): - return self.code_finder.is_a_class_or_function_name_in_header(offset) - - def is_from_statement_module(self, offset): - return self.code_finder.is_from_statement_module(offset) - - def is_from_aliased(self, offset): - return self.code_finder.is_from_aliased(offset) - - def find_parens_start_from_inside(self, offset): - return self.code_finder.find_parens_start_from_inside(offset) - - def is_a_name_after_from_import(self, offset): - return self.code_finder.is_a_name_after_from_import(offset) - - def is_from_statement(self, offset): - return self.code_finder.is_from_statement(offset) - - def get_from_aliased(self, offset): - return self.code_finder.get_from_aliased(offset) - - def is_import_statement(self, offset): - return self.code_finder.is_import_statement(offset) - - def is_assigned_here(self, offset): - return self.code_finder.is_assigned_here(offset) - - def is_a_function_being_called(self, offset): - return self.code_finder.is_a_function_being_called(offset) - - def get_word_parens_range(self, offset): - return self.code_finder.get_word_parens_range(offset) - - def is_name_assigned_in_class_body(self, offset): - return self.code_finder.is_name_assigned_in_class_body(offset) - - def is_on_function_call_keyword(self, offset): - return self.code_finder.is_on_function_call_keyword(offset) - - def _find_parens_start(self, offset): - return self.code_finder._find_parens_start(offset) - - def get_parameters(self, first, last): - return self.code_finder.get_parameters(first, last) - - def get_from_module(self, offset): - return self.code_finder.get_from_module(offset) - - def is_assigned_in_a_tuple_assignment(self, offset): - return self.code_finder.is_assigned_in_a_tuple_assignment(offset) - - def get_assignment_type(self, offset): - return self.code_finder.get_assignment_type(offset) - - def get_function_and_args_in_header(self, offset): - return self.code_finder.get_function_and_args_in_header(offset) - - def get_lambda_and_args(self, offset): - return self.code_finder.get_lambda_and_args(offset) - - def find_function_offset(self, offset): - return self.code_finder.find_function_offset(offset) - - -class _RealFinder(object): - - def __init__(self, code, raw): - self.code = code - self.raw = raw - - def _find_word_start(self, offset): - current_offset = offset - while current_offset >= 0 and self._is_id_char(current_offset): - current_offset -= 1 - return current_offset + 1 - - def _find_word_end(self, offset): - while offset + 1 < len(self.code) and self._is_id_char(offset + 1): - offset += 1 - return offset - - def _find_last_non_space_char(self, offset): - while offset >= 0 and self.code[offset].isspace(): - if self.code[offset] == '\n': - return offset - offset -= 1 - return max(-1, offset) - - def get_word_at(self, offset): - offset = self._get_fixed_offset(offset) - return self.raw[self._find_word_start(offset): - self._find_word_end(offset) + 1] - - def _get_fixed_offset(self, offset): - if offset >= len(self.code): - return offset - 1 - if not self._is_id_char(offset): - if offset > 0 and self._is_id_char(offset - 1): - return offset - 1 - if offset < len(self.code) - 1 and self._is_id_char(offset + 1): - return offset + 1 - return offset - - def _is_id_char(self, offset): - return self.code[offset].isalnum() or self.code[offset] == '_' - - def _find_string_start(self, offset): - kind = self.code[offset] - try: - return self.code.rindex(kind, 0, offset) - except ValueError: - return 0 - - def _find_parens_start(self, offset): - offset = self._find_last_non_space_char(offset - 1) - while offset >= 0 and self.code[offset] not in '[({': - if self.code[offset] not in ':,': - offset = self._find_primary_start(offset) - offset = self._find_last_non_space_char(offset - 1) - return offset - - def _find_atom_start(self, offset): - old_offset = offset - if self.code[offset] == '\n': - return offset + 1 - if self.code[offset].isspace(): - offset = self._find_last_non_space_char(offset) - if self.code[offset] in '\'"': - return self._find_string_start(offset) - if self.code[offset] in ')]}': - return self._find_parens_start(offset) - if self._is_id_char(offset): - return self._find_word_start(offset) - return old_offset - - def _find_primary_without_dot_start(self, offset): - """It tries to find the undotted primary start - - It is different from `self._get_atom_start()` in that it - follows function calls, too; such as in ``f(x)``. - - """ - last_atom = offset - offset = self._find_last_non_space_char(last_atom) - while offset > 0 and self.code[offset] in ')]': - last_atom = self._find_parens_start(offset) - offset = self._find_last_non_space_char(last_atom - 1) - if offset >= 0 and (self.code[offset] in '"\'})]' or - self._is_id_char(offset)): - atom_start = self._find_atom_start(offset) - if not keyword.iskeyword(self.code[atom_start:offset + 1]): - return atom_start - return last_atom - - def _find_primary_start(self, offset): - if offset >= len(self.code): - offset = len(self.code) - 1 - if self.code[offset] != '.': - offset = self._find_primary_without_dot_start(offset) - else: - offset = offset + 1 - while offset > 0: - prev = self._find_last_non_space_char(offset - 1) - if offset <= 0 or self.code[prev] != '.': - break - offset = self._find_primary_without_dot_start(prev - 1) - if not self._is_id_char(offset): - break - - return offset - - def get_primary_at(self, offset): - offset = self._get_fixed_offset(offset) - start, end = self.get_primary_range(offset) - return self.raw[start:end].strip() - - def get_splitted_primary_before(self, offset): - """returns expression, starting, starting_offset - - This function is used in `rope.codeassist.assist` function. - """ - if offset == 0: - return ('', '', 0) - end = offset - 1 - word_start = self._find_atom_start(end) - real_start = self._find_primary_start(end) - if self.code[word_start:offset].strip() == '': - word_start = end - if self.code[end].isspace(): - word_start = end - if self.code[real_start:word_start].strip() == '': - real_start = word_start - if real_start == word_start == end and not self._is_id_char(end): - return ('', '', offset) - if real_start == word_start: - return ('', self.raw[word_start:offset], word_start) - else: - if self.code[end] == '.': - return (self.raw[real_start:end], '', offset) - last_dot_position = word_start - if self.code[word_start] != '.': - last_dot_position = self._find_last_non_space_char(word_start - 1) - last_char_position = self._find_last_non_space_char(last_dot_position - 1) - if self.code[word_start].isspace(): - word_start = offset - return (self.raw[real_start:last_char_position + 1], - self.raw[word_start:offset], word_start) - - def _get_line_start(self, offset): - try: - return self.code.rindex('\n', 0, offset + 1) - except ValueError: - return 0 - - def _get_line_end(self, offset): - try: - return self.code.index('\n', offset) - except ValueError: - return len(self.code) - - def is_name_assigned_in_class_body(self, offset): - word_start = self._find_word_start(offset - 1) - word_end = self._find_word_end(offset) + 1 - if '.' in self.code[word_start:word_end]: - return False - line_start = self._get_line_start(word_start) - line = self.code[line_start:word_start].strip() - return not line and self.get_assignment_type(offset) == '=' - - def is_a_class_or_function_name_in_header(self, offset): - word_start = self._find_word_start(offset - 1) - line_start = self._get_line_start(word_start) - prev_word = self.code[line_start:word_start].strip() - return prev_word in ['def', 'class'] - - def _find_first_non_space_char(self, offset): - if offset >= len(self.code): - return len(self.code) - while offset < len(self.code) and self.code[offset].isspace(): - if self.code[offset] == '\n': - return offset - offset += 1 - return offset - - def is_a_function_being_called(self, offset): - word_end = self._find_word_end(offset) + 1 - next_char = self._find_first_non_space_char(word_end) - return next_char < len(self.code) and \ - self.code[next_char] == '(' and \ - not self.is_a_class_or_function_name_in_header(offset) - - def _find_import_end(self, start): - return self._get_line_end(start) - - def is_import_statement(self, offset): - try: - last_import = self.code.rindex('import ', 0, offset) - except ValueError: - return False - return self._find_import_end(last_import + 7) >= offset - - def is_from_statement(self, offset): - try: - last_from = self.code.rindex('from ', 0, offset) - from_import = self.code.index(' import ', last_from) - from_names = from_import + 8 - except ValueError: - return False - from_names = self._find_first_non_space_char(from_names) - return self._find_import_end(from_names) >= offset - - def is_from_statement_module(self, offset): - if offset >= len(self.code) - 1: - return False - stmt_start = self._find_primary_start(offset) - line_start = self._get_line_start(stmt_start) - prev_word = self.code[line_start:stmt_start].strip() - return prev_word == 'from' - - def is_a_name_after_from_import(self, offset): - try: - if len(self.code) > offset and self.code[offset] == '\n': - line_start = self._get_line_start(offset - 1) - else: - line_start = self._get_line_start(offset) - last_from = self.code.rindex('from ', line_start, offset) - from_import = self.code.index(' import ', last_from) - from_names = from_import + 8 - except ValueError: - return False - if from_names - 1 > offset: - return False - return self._find_import_end(from_names) >= offset - - def get_from_module(self, offset): - try: - last_from = self.code.rindex('from ', 0, offset) - import_offset = self.code.index(' import ', last_from) - end = self._find_last_non_space_char(import_offset) - return self.get_primary_at(end) - except ValueError: - pass - - def is_from_aliased(self, offset): - if not self.is_a_name_after_from_import(offset): - return False - try: - end = self._find_word_end(offset) - as_end = min(self._find_word_end(end + 1), len(self.code)) - as_start = self._find_word_start(as_end) - if self.code[as_start:as_end + 1] == 'as': - return True - except ValueError: - return False - - def get_from_aliased(self, offset): - try: - end = self._find_word_end(offset) - as_ = self._find_word_end(end + 1) - alias = self._find_word_end(as_ + 1) - start = self._find_word_start(alias) - return self.raw[start:alias + 1] - except ValueError: - pass - - def is_function_keyword_parameter(self, offset): - word_end = self._find_word_end(offset) - if word_end + 1 == len(self.code): - return False - next_char = self._find_first_non_space_char(word_end + 1) - equals = self.code[next_char:next_char + 2] - if equals == '==' or not equals.startswith('='): - return False - word_start = self._find_word_start(offset) - prev_char = self._find_last_non_space_char(word_start - 1) - return prev_char - 1 >= 0 and self.code[prev_char] in ',(' - - def is_on_function_call_keyword(self, offset): - stop = self._get_line_start(offset) - if self._is_id_char(offset): - offset = self._find_word_start(offset) - 1 - offset = self._find_last_non_space_char(offset) - if offset <= stop or self.code[offset] not in '(,': - return False - parens_start = self.find_parens_start_from_inside(offset) - return stop < parens_start - - def find_parens_start_from_inside(self, offset): - stop = self._get_line_start(offset) - opens = 1 - while offset > stop: - if self.code[offset] == '(': - break - if self.code[offset] != ',': - offset = self._find_primary_start(offset) - offset -= 1 - return max(stop, offset) - - def is_assigned_here(self, offset): - return self.get_assignment_type(offset) is not None - - def get_assignment_type(self, offset): - # XXX: does not handle tuple assignments - word_end = self._find_word_end(offset) - next_char = self._find_first_non_space_char(word_end + 1) - single = self.code[next_char:next_char + 1] - double = self.code[next_char:next_char + 2] - triple = self.code[next_char:next_char + 3] - if double not in ('==', '<=', '>=', '!='): - for op in [single, double, triple]: - if op.endswith('='): - return op - - def get_primary_range(self, offset): - start = self._find_primary_start(offset) - end = self._find_word_end(offset) + 1 - return (start, end) - - def get_word_range(self, offset): - offset = max(0, offset) - start = self._find_word_start(offset) - end = self._find_word_end(offset) + 1 - return (start, end) - - def get_word_parens_range(self, offset, opening='(', closing=')'): - end = self._find_word_end(offset) - start_parens = self.code.index(opening, end) - index = start_parens - open_count = 0 - while index < len(self.code): - if self.code[index] == opening: - open_count += 1 - if self.code[index] == closing: - open_count -= 1 - if open_count == 0: - return (start_parens, index + 1) - index += 1 - return (start_parens, index) - - def get_parameters(self, first, last): - keywords = [] - args = [] - current = self._find_last_non_space_char(last - 1) - while current > first: - primary_start = current - current = self._find_primary_start(current) - while current != first and self.code[current] not in '=,': - current = self._find_last_non_space_char(current - 1) - primary = self.raw[current + 1:primary_start + 1].strip() - if self.code[current] == '=': - primary_start = current - 1 - current -= 1 - while current != first and self.code[current] not in ',': - current = self._find_last_non_space_char(current - 1) - param_name = self.raw[current + 1:primary_start + 1].strip() - keywords.append((param_name, primary)) - else: - args.append(primary) - current = self._find_last_non_space_char(current - 1) - args.reverse() - keywords.reverse() - return args, keywords - - def is_assigned_in_a_tuple_assignment(self, offset): - start = self._get_line_start(offset) - end = self._get_line_end(offset) - primary_start = self._find_primary_start(offset) - primary_end = self._find_word_end(offset) - - prev_char_offset = self._find_last_non_space_char(primary_start - 1) - next_char_offset = self._find_first_non_space_char(primary_end + 1) - next_char = prev_char = '' - if prev_char_offset >= start: - prev_char = self.code[prev_char_offset] - if next_char_offset < end: - next_char = self.code[next_char_offset] - try: - equals_offset = self.code.index('=', start, end) - except ValueError: - return False - if prev_char not in '(,' and next_char not in ',)': - return False - parens_start = self.find_parens_start_from_inside(offset) - # XXX: only handling (x, y) = value - return offset < equals_offset and \ - self.code[start:parens_start].strip() == '' - - def get_function_and_args_in_header(self, offset): - offset = self.find_function_offset(offset) - lparens, rparens = self.get_word_parens_range(offset) - return self.raw[offset:rparens + 1] - - def find_function_offset(self, offset, definition='def '): - while True: - offset = self.code.index(definition, offset) - if offset == 0 or not self._is_id_char(offset - 1): - break - offset += 1 - def_ = offset + 4 - return self._find_first_non_space_char(def_) - - def get_lambda_and_args(self, offset): - offset = self.find_function_offset(offset, definition = 'lambda ') - lparens, rparens = self.get_word_parens_range(offset, opening=' ', closing=':') - return self.raw[offset:rparens + 1] - diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/__init__.py b/.vim/bundle/python-mode/pylibs/rope/contrib/__init__.py @@ -1,7 +0,0 @@ -"""rope IDE tools package - -This package contains modules that can be used in IDEs -but do not depend on the UI. So these modules will be used -by `rope.ui` modules. - -""" diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/autoimport.py b/.vim/bundle/python-mode/pylibs/rope/contrib/autoimport.py @@ -1,217 +0,0 @@ -import re - -from rope.base import (exceptions, pynames, resourceobserver, - taskhandle, pyobjects, builtins, resources) -from rope.refactor import importutils - - -class AutoImport(object): - """A class for finding the module that provides a name - - This class maintains a cache of global names in python modules. - Note that this cache is not accurate and might be out of date. - - """ - - def __init__(self, project, observe=True, underlined=False): - """Construct an AutoImport object - - If `observe` is `True`, listen for project changes and update - the cache. - - If `underlined` is `True`, underlined names are cached, too. - """ - self.project = project - self.underlined = underlined - self.names = project.data_files.read_data('globalnames') - if self.names is None: - self.names = {} - project.data_files.add_write_hook(self._write) - # XXX: using a filtered observer - observer = resourceobserver.ResourceObserver( - changed=self._changed, moved=self._moved, removed=self._removed) - if observe: - project.add_observer(observer) - - def import_assist(self, starting): - """Return a list of ``(name, module)`` tuples - - This function tries to find modules that have a global name - that starts with `starting`. - """ - # XXX: breaking if gave up! use generators - result = [] - for module in self.names: - for global_name in self.names[module]: - if global_name.startswith(starting): - result.append((global_name, module)) - return result - - def get_modules(self, name): - """Return the list of modules that have global `name`""" - result = [] - for module in self.names: - if name in self.names[module]: - result.append(module) - return result - - def get_all_names(self): - """Return the list of all cached global names""" - result = set() - for module in self.names: - result.update(set(self.names[module])) - return result - - def get_name_locations(self, name): - """Return a list of ``(resource, lineno)`` tuples""" - result = [] - pycore = self.project.pycore - for module in self.names: - if name in self.names[module]: - try: - pymodule = pycore.get_module(module) - if name in pymodule: - pyname = pymodule[name] - module, lineno = pyname.get_definition_location() - if module is not None: - resource = module.get_module().get_resource() - if resource is not None and lineno is not None: - result.append((resource, lineno)) - except exceptions.ModuleNotFoundError: - pass - return result - - def generate_cache(self, resources=None, underlined=None, - task_handle=taskhandle.NullTaskHandle()): - """Generate global name cache for project files - - If `resources` is a list of `rope.base.resource.File`\s, only - those files are searched; otherwise all python modules in the - project are cached. - - """ - if resources is None: - resources = self.project.pycore.get_python_files() - job_set = task_handle.create_jobset( - 'Generatig autoimport cache', len(resources)) - for file in resources: - job_set.started_job('Working on <%s>' % file.path) - self.update_resource(file, underlined) - job_set.finished_job() - - def generate_modules_cache(self, modules, underlined=None, - task_handle=taskhandle.NullTaskHandle()): - """Generate global name cache for modules listed in `modules`""" - job_set = task_handle.create_jobset( - 'Generatig autoimport cache for modules', len(modules)) - for modname in modules: - job_set.started_job('Working on <%s>' % modname) - if modname.endswith('.*'): - mod = self.project.pycore.find_module(modname[:-2]) - if mod: - for sub in submodules(mod): - self.update_resource(sub, underlined) - else: - self.update_module(modname, underlined) - job_set.finished_job() - - def clear_cache(self): - """Clear all entries in global-name cache - - It might be a good idea to use this function before - regenerating global names. - - """ - self.names.clear() - - def find_insertion_line(self, code): - """Guess at what line the new import should be inserted""" - match = re.search(r'^(def|class)\s+', code) - if match is not None: - code = code[:match.start()] - try: - pymodule = self.project.pycore.get_string_module(code) - except exceptions.ModuleSyntaxError: - return 1 - testmodname = '__rope_testmodule_rope' - importinfo = importutils.NormalImport(((testmodname, None),)) - module_imports = importutils.get_module_imports( - self.project.pycore, pymodule) - module_imports.add_import(importinfo) - code = module_imports.get_changed_source() - offset = code.index(testmodname) - lineno = code.count('\n', 0, offset) + 1 - return lineno - - def update_resource(self, resource, underlined=None): - """Update the cache for global names in `resource`""" - try: - pymodule = self.project.pycore.resource_to_pyobject(resource) - modname = self._module_name(resource) - self._add_names(pymodule, modname, underlined) - except exceptions.ModuleSyntaxError: - pass - - def update_module(self, modname, underlined=None): - """Update the cache for global names in `modname` module - - `modname` is the name of a module. - """ - try: - pymodule = self.project.pycore.get_module(modname) - self._add_names(pymodule, modname, underlined) - except exceptions.ModuleNotFoundError: - pass - - def _module_name(self, resource): - return self.project.pycore.modname(resource) - - def _add_names(self, pymodule, modname, underlined): - if underlined is None: - underlined = self.underlined - globals = [] - if isinstance(pymodule, pyobjects.PyDefinedObject): - attributes = pymodule._get_structural_attributes() - else: - attributes = pymodule.get_attributes() - for name, pyname in attributes.items(): - if not underlined and name.startswith('_'): - continue - if isinstance(pyname, (pynames.AssignedName, pynames.DefinedName)): - globals.append(name) - if isinstance(pymodule, builtins.BuiltinModule): - globals.append(name) - self.names[modname] = globals - - def _write(self): - self.project.data_files.write_data('globalnames', self.names) - - def _changed(self, resource): - if not resource.is_folder(): - self.update_resource(resource) - - def _moved(self, resource, newresource): - if not resource.is_folder(): - modname = self._module_name(resource) - if modname in self.names: - del self.names[modname] - self.update_resource(newresource) - - def _removed(self, resource): - if not resource.is_folder(): - modname = self._module_name(resource) - if modname in self.names: - del self.names[modname] - - -def submodules(mod): - if isinstance(mod, resources.File): - if mod.name.endswith('.py') and mod.name != '__init__.py': - return set([mod]) - return set() - if not mod.has_child('__init__.py'): - return set() - result = set([mod]) - for child in mod.get_children(): - result |= submodules(child) - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/changestack.py b/.vim/bundle/python-mode/pylibs/rope/contrib/changestack.py @@ -1,52 +0,0 @@ -"""For performing many refactorings as a single command - -`changestack` module can be used to perform many refactorings on top -of each other as one bigger command. It can be used like:: - - stack = ChangeStack(project, 'my big command') - - #.. - stack.push(refactoring1.get_changes()) - #.. - stack.push(refactoring2.get_changes()) - #.. - stack.push(refactoringX.get_changes()) - - stack.pop_all() - changes = stack.merged() - -Now `changes` can be previewed or performed as before. -""" - -from rope.base import change - - -class ChangeStack(object): - - def __init__(self, project, description='merged changes'): - self.project = project - self.description = description - self.stack = [] - - def push(self, changes): - self.stack.append(changes) - self.project.do(changes) - - def pop_all(self): - for i in range(len(self.stack)): - self.project.history.undo(drop=True) - - def merged(self): - result = change.ChangeSet(self.description) - for changes in self.stack: - for c in self._basic_changes(changes): - result.add_change(c) - return result - - def _basic_changes(self, changes): - if isinstance(changes, change.ChangeSet): - for child in changes.changes: - for atom in self._basic_changes(child): - yield atom - else: - yield changes diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/codeassist.py b/.vim/bundle/python-mode/pylibs/rope/contrib/codeassist.py @@ -1,647 +0,0 @@ -import keyword -import sys -import warnings - -import rope.base.codeanalyze -import rope.base.evaluate -from rope.base import pyobjects, pyobjectsdef, pynames, builtins, exceptions, worder -from rope.base.codeanalyze import SourceLinesAdapter -from rope.contrib import fixsyntax -from rope.refactor import functionutils - - -def code_assist(project, source_code, offset, resource=None, - templates=None, maxfixes=1, later_locals=True): - """Return python code completions as a list of `CodeAssistProposal`\s - - `resource` is a `rope.base.resources.Resource` object. If - provided, relative imports are handled. - - `maxfixes` is the maximum number of errors to fix if the code has - errors in it. - - If `later_locals` is `False` names defined in this scope and after - this line is ignored. - - """ - if templates is not None: - warnings.warn('Codeassist no longer supports templates', - DeprecationWarning, stacklevel=2) - assist = _PythonCodeAssist( - project, source_code, offset, resource=resource, - maxfixes=maxfixes, later_locals=later_locals) - return assist() - - -def starting_offset(source_code, offset): - """Return the offset in which the completion should be inserted - - Usually code assist proposals should be inserted like:: - - completion = proposal.name - result = (source_code[:starting_offset] + - completion + source_code[offset:]) - - Where starting_offset is the offset returned by this function. - - """ - word_finder = worder.Worder(source_code, True) - expression, starting, starting_offset = \ - word_finder.get_splitted_primary_before(offset) - return starting_offset - - -def get_doc(project, source_code, offset, resource=None, maxfixes=1): - """Get the pydoc""" - fixer = fixsyntax.FixSyntax(project.pycore, source_code, - resource, maxfixes) - pymodule = fixer.get_pymodule() - pyname = fixer.pyname_at(offset) - if pyname is None: - return None - pyobject = pyname.get_object() - return PyDocExtractor().get_doc(pyobject) - - -def get_calltip(project, source_code, offset, resource=None, - maxfixes=1, ignore_unknown=False, remove_self=False): - """Get the calltip of a function - - The format of the returned string is - ``module_name.holding_scope_names.function_name(arguments)``. For - classes `__init__()` and for normal objects `__call__()` function - is used. - - Note that the offset is on the function itself *not* after the its - open parenthesis. (Actually it used to be the other way but it - was easily confused when string literals were involved. So I - decided it is better for it not to try to be too clever when it - cannot be clever enough). You can use a simple search like:: - - offset = source_code.rindex('(', 0, offset) - 1 - - to handle simple situations. - - If `ignore_unknown` is `True`, `None` is returned for functions - without source-code like builtins and extensions. - - If `remove_self` is `True`, the first parameter whose name is self - will be removed for methods. - """ - fixer = fixsyntax.FixSyntax(project.pycore, source_code, - resource, maxfixes) - pymodule = fixer.get_pymodule() - pyname = fixer.pyname_at(offset) - if pyname is None: - return None - pyobject = pyname.get_object() - return PyDocExtractor().get_calltip(pyobject, ignore_unknown, remove_self) - - -def get_definition_location(project, source_code, offset, - resource=None, maxfixes=1): - """Return the definition location of the python name at `offset` - - Return a (`rope.base.resources.Resource`, lineno) tuple. If no - `resource` is given and the definition is inside the same module, - the first element of the returned tuple would be `None`. If the - location cannot be determined ``(None, None)`` is returned. - - """ - fixer = fixsyntax.FixSyntax(project.pycore, source_code, - resource, maxfixes) - pymodule = fixer.get_pymodule() - pyname = fixer.pyname_at(offset) - if pyname is not None: - module, lineno = pyname.get_definition_location() - if module is not None: - return module.get_module().get_resource(), lineno - return (None, None) - - -def find_occurrences(*args, **kwds): - import rope.contrib.findit - warnings.warn('Use `rope.contrib.findit.find_occurrences()` instead', - DeprecationWarning, stacklevel=2) - return rope.contrib.findit.find_occurrences(*args, **kwds) - - -class CompletionProposal(object): - """A completion proposal - - The `scope` instance variable shows where proposed name came from - and can be 'global', 'local', 'builtin', 'attribute', 'keyword', - 'imported', 'parameter_keyword'. - - The `type` instance variable shows the approximate type of the - proposed object and can be 'instance', 'class', 'function', 'module', - and `None`. - - All possible relations between proposal's `scope` and `type` are shown - in the table below (different scopes in rows and types in columns): - - | instance | class | function | module | None - local | + | + | + | + | - global | + | + | + | + | - builtin | + | + | + | | - attribute | + | + | + | + | - imported | + | + | + | + | - keyword | | | | | + - parameter_keyword | | | | | + - - """ - - def __init__(self, name, scope, pyname=None): - self.name = name - self.pyname = pyname - self.scope = self._get_scope(scope) - - def __str__(self): - return '%s (%s, %s)' % (self.name, self.scope, self.type) - - def __repr__(self): - return str(self) - - @property - def parameters(self): - """The names of the parameters the function takes. - - Returns None if this completion is not a function. - """ - pyname = self.pyname - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - if isinstance(pyname, pynames.DefinedName): - pyobject = pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - return pyobject.get_param_names() - - @property - def type(self): - pyname = self.pyname - if isinstance(pyname, builtins.BuiltinName): - pyobject = pyname.get_object() - if isinstance(pyobject, builtins.BuiltinFunction): - return 'function' - elif isinstance(pyobject, builtins.BuiltinClass): - clsobj = pyobject.builtin - return 'class' - elif isinstance(pyobject, builtins.BuiltinObject) or \ - isinstance(pyobject, builtins.BuiltinName): - return 'instance' - elif isinstance(pyname, pynames.ImportedModule): - return 'module' - elif isinstance(pyname, pynames.ImportedName) or \ - isinstance(pyname, pynames.DefinedName): - pyobject = pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - return 'function' - if isinstance(pyobject, pyobjects.AbstractClass): - return 'class' - return 'instance' - - def _get_scope(self, scope): - if isinstance(self.pyname, builtins.BuiltinName): - return 'builtin' - if isinstance(self.pyname, pynames.ImportedModule) or \ - isinstance(self.pyname, pynames.ImportedName): - return 'imported' - return scope - - def get_doc(self): - """Get the proposed object's docstring. - - Returns None if it can not be get. - """ - if not self.pyname: - return None - pyobject = self.pyname.get_object() - if not hasattr(pyobject, 'get_doc'): - return None - return self.pyname.get_object().get_doc() - - @property - def kind(self): - warnings.warn("the proposal's `kind` property is deprecated, " \ - "use `scope` instead") - return self.scope - - -# leaved for backward compatibility -CodeAssistProposal = CompletionProposal - - -class NamedParamProposal(CompletionProposal): - """A parameter keyword completion proposal - - Holds reference to ``_function`` -- the function which - parameter ``name`` belongs to. This allows to determine - default value for this parameter. - """ - def __init__(self, name, function): - self.argname = name - name = '%s=' % name - super(NamedParamProposal, self).__init__(name, 'parameter_keyword') - self._function = function - - def get_default(self): - """Get a string representation of a param's default value. - - Returns None if there is no default value for this param. - """ - definfo = functionutils.DefinitionInfo.read(self._function) - for arg, default in definfo.args_with_defaults: - if self.argname == arg: - return default - return None - - -def sorted_proposals(proposals, scopepref=None, typepref=None): - """Sort a list of proposals - - Return a sorted list of the given `CodeAssistProposal`\s. - - `scopepref` can be a list of proposal scopes. Defaults to - ``['parameter_keyword', 'local', 'global', 'imported', - 'attribute', 'builtin', 'keyword']``. - - `typepref` can be a list of proposal types. Defaults to - ``['class', 'function', 'instance', 'module', None]``. - (`None` stands for completions with no type like keywords.) - """ - sorter = _ProposalSorter(proposals, scopepref, typepref) - return sorter.get_sorted_proposal_list() - - -def starting_expression(source_code, offset): - """Return the expression to complete""" - word_finder = worder.Worder(source_code, True) - expression, starting, starting_offset = \ - word_finder.get_splitted_primary_before(offset) - if expression: - return expression + '.' + starting - return starting - - -def default_templates(): - warnings.warn('default_templates() is deprecated.', - DeprecationWarning, stacklevel=2) - return {} - - -class _PythonCodeAssist(object): - - def __init__(self, project, source_code, offset, resource=None, - maxfixes=1, later_locals=True): - self.project = project - self.pycore = self.project.pycore - self.code = source_code - self.resource = resource - self.maxfixes = maxfixes - self.later_locals = later_locals - self.word_finder = worder.Worder(source_code, True) - self.expression, self.starting, self.offset = \ - self.word_finder.get_splitted_primary_before(offset) - - keywords = keyword.kwlist - - def _find_starting_offset(self, source_code, offset): - current_offset = offset - 1 - while current_offset >= 0 and (source_code[current_offset].isalnum() or - source_code[current_offset] in '_'): - current_offset -= 1; - return current_offset + 1 - - def _matching_keywords(self, starting): - result = [] - for kw in self.keywords: - if kw.startswith(starting): - result.append(CompletionProposal(kw, 'keyword')) - return result - - def __call__(self): - if self.offset > len(self.code): - return [] - completions = list(self._code_completions().values()) - if self.expression.strip() == '' and self.starting.strip() != '': - completions.extend(self._matching_keywords(self.starting)) - return completions - - def _dotted_completions(self, module_scope, holding_scope): - result = {} - found_pyname = rope.base.evaluate.eval_str(holding_scope, - self.expression) - if found_pyname is not None: - element = found_pyname.get_object() - compl_scope = 'attribute' - if isinstance(element, (pyobjectsdef.PyModule, - pyobjectsdef.PyPackage)): - compl_scope = 'imported' - for name, pyname in element.get_attributes().items(): - if name.startswith(self.starting): - result[name] = CompletionProposal(name, compl_scope, pyname) - return result - - def _undotted_completions(self, scope, result, lineno=None): - if scope.parent != None: - self._undotted_completions(scope.parent, result) - if lineno is None: - names = scope.get_propagated_names() - else: - names = scope.get_names() - for name, pyname in names.items(): - if name.startswith(self.starting): - compl_scope = 'local' - if scope.get_kind() == 'Module': - compl_scope = 'global' - if lineno is None or self.later_locals or \ - not self._is_defined_after(scope, pyname, lineno): - result[name] = CompletionProposal(name, compl_scope, - pyname) - - def _from_import_completions(self, pymodule): - module_name = self.word_finder.get_from_module(self.offset) - if module_name is None: - return {} - pymodule = self._find_module(pymodule, module_name) - result = {} - for name in pymodule: - if name.startswith(self.starting): - result[name] = CompletionProposal(name, scope='global', - pyname=pymodule[name]) - return result - - def _find_module(self, pymodule, module_name): - dots = 0 - while module_name[dots] == '.': - dots += 1 - pyname = pynames.ImportedModule(pymodule, - module_name[dots:], dots) - return pyname.get_object() - - def _is_defined_after(self, scope, pyname, lineno): - location = pyname.get_definition_location() - if location is not None and location[1] is not None: - if location[0] == scope.pyobject.get_module() and \ - lineno <= location[1] <= scope.get_end(): - return True - - def _code_completions(self): - lineno = self.code.count('\n', 0, self.offset) + 1 - fixer = fixsyntax.FixSyntax(self.pycore, self.code, - self.resource, self.maxfixes) - pymodule = fixer.get_pymodule() - module_scope = pymodule.get_scope() - code = pymodule.source_code - lines = code.split('\n') - result = {} - start = fixsyntax._logical_start(lines, lineno) - indents = fixsyntax._get_line_indents(lines[start - 1]) - inner_scope = module_scope.get_inner_scope_for_line(start, indents) - if self.word_finder.is_a_name_after_from_import(self.offset): - return self._from_import_completions(pymodule) - if self.expression.strip() != '': - result.update(self._dotted_completions(module_scope, inner_scope)) - else: - result.update(self._keyword_parameters(module_scope.pyobject, - inner_scope)) - self._undotted_completions(inner_scope, result, lineno=lineno) - return result - - def _keyword_parameters(self, pymodule, scope): - offset = self.offset - if offset == 0: - return {} - word_finder = worder.Worder(self.code, True) - lines = SourceLinesAdapter(self.code) - lineno = lines.get_line_number(offset) - if word_finder.is_on_function_call_keyword(offset - 1): - name_finder = rope.base.evaluate.ScopeNameFinder(pymodule) - function_parens = word_finder.\ - find_parens_start_from_inside(offset - 1) - primary = word_finder.get_primary_at(function_parens - 1) - try: - function_pyname = rope.base.evaluate.\ - eval_str(scope, primary) - except exceptions.BadIdentifierError, e: - return {} - if function_pyname is not None: - pyobject = function_pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - pass - elif isinstance(pyobject, pyobjects.AbstractClass) and \ - '__init__' in pyobject: - pyobject = pyobject['__init__'].get_object() - elif '__call__' in pyobject: - pyobject = pyobject['__call__'].get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - param_names = [] - param_names.extend( - pyobject.get_param_names(special_args=False)) - result = {} - for name in param_names: - if name.startswith(self.starting): - result[name + '='] = NamedParamProposal( - name, pyobject - ) - return result - return {} - - -class _ProposalSorter(object): - """Sort a list of code assist proposals""" - - def __init__(self, code_assist_proposals, scopepref=None, typepref=None): - self.proposals = code_assist_proposals - if scopepref is None: - scopepref = ['parameter_keyword', 'local', 'global', 'imported', - 'attribute', 'builtin', 'keyword'] - self.scopepref = scopepref - if typepref is None: - typepref = ['class', 'function', 'instance', 'module', None] - self.typerank = dict((type, index) - for index, type in enumerate(typepref)) - - def get_sorted_proposal_list(self): - """Return a list of `CodeAssistProposal`""" - proposals = {} - for proposal in self.proposals: - proposals.setdefault(proposal.scope, []).append(proposal) - result = [] - for scope in self.scopepref: - scope_proposals = proposals.get(scope, []) - scope_proposals = [proposal for proposal in scope_proposals - if proposal.type in self.typerank] - scope_proposals.sort(self._proposal_cmp) - result.extend(scope_proposals) - return result - - def _proposal_cmp(self, proposal1, proposal2): - if proposal1.type != proposal2.type: - return cmp(self.typerank.get(proposal1.type, 100), - self.typerank.get(proposal2.type, 100)) - return self._compare_underlined_names(proposal1.name, - proposal2.name) - - def _compare_underlined_names(self, name1, name2): - def underline_count(name): - result = 0 - while result < len(name) and name[result] == '_': - result += 1 - return result - underline_count1 = underline_count(name1) - underline_count2 = underline_count(name2) - if underline_count1 != underline_count2: - return cmp(underline_count1, underline_count2) - return cmp(name1, name2) - - -class PyDocExtractor(object): - - def get_doc(self, pyobject): - if isinstance(pyobject, pyobjects.AbstractFunction): - return self._get_function_docstring(pyobject) - elif isinstance(pyobject, pyobjects.AbstractClass): - return self._get_class_docstring(pyobject) - elif isinstance(pyobject, pyobjects.AbstractModule): - return self._trim_docstring(pyobject.get_doc()) - return None - - def get_calltip(self, pyobject, ignore_unknown=False, remove_self=False): - try: - if isinstance(pyobject, pyobjects.AbstractClass): - pyobject = pyobject['__init__'].get_object() - if not isinstance(pyobject, pyobjects.AbstractFunction): - pyobject = pyobject['__call__'].get_object() - except exceptions.AttributeNotFoundError: - return None - if ignore_unknown and not isinstance(pyobject, pyobjects.PyFunction): - return - if isinstance(pyobject, pyobjects.AbstractFunction): - result = self._get_function_signature(pyobject, add_module=True) - if remove_self and self._is_method(pyobject): - return result.replace('(self)', '()').replace('(self, ', '(') - return result - - def _get_class_docstring(self, pyclass): - contents = self._trim_docstring(pyclass.get_doc(), 2) - supers = [super.get_name() for super in pyclass.get_superclasses()] - doc = 'class %s(%s):\n\n' % (pyclass.get_name(), ', '.join(supers)) + contents - - if '__init__' in pyclass: - init = pyclass['__init__'].get_object() - if isinstance(init, pyobjects.AbstractFunction): - doc += '\n\n' + self._get_single_function_docstring(init) - return doc - - def _get_function_docstring(self, pyfunction): - functions = [pyfunction] - if self._is_method(pyfunction): - functions.extend(self._get_super_methods(pyfunction.parent, - pyfunction.get_name())) - return '\n\n'.join([self._get_single_function_docstring(function) - for function in functions]) - - def _is_method(self, pyfunction): - return isinstance(pyfunction, pyobjects.PyFunction) and \ - isinstance(pyfunction.parent, pyobjects.PyClass) - - def _get_single_function_docstring(self, pyfunction): - signature = self._get_function_signature(pyfunction) - docs = self._trim_docstring(pyfunction.get_doc(), indents=2) - return signature + ':\n\n' + docs - - def _get_super_methods(self, pyclass, name): - result = [] - for super_class in pyclass.get_superclasses(): - if name in super_class: - function = super_class[name].get_object() - if isinstance(function, pyobjects.AbstractFunction): - result.append(function) - result.extend(self._get_super_methods(super_class, name)) - return result - - def _get_function_signature(self, pyfunction, add_module=False): - location = self._location(pyfunction, add_module) - if isinstance(pyfunction, pyobjects.PyFunction): - info = functionutils.DefinitionInfo.read(pyfunction) - return location + info.to_string() - else: - return '%s(%s)' % (location + pyfunction.get_name(), - ', '.join(pyfunction.get_param_names())) - - def _location(self, pyobject, add_module=False): - location = [] - parent = pyobject.parent - while parent and not isinstance(parent, pyobjects.AbstractModule): - location.append(parent.get_name()) - location.append('.') - parent = parent.parent - if add_module: - if isinstance(pyobject, pyobjects.PyFunction): - module = pyobject.get_module() - location.insert(0, self._get_module(pyobject)) - if isinstance(parent, builtins.BuiltinModule): - location.insert(0, parent.get_name() + '.') - return ''.join(location) - - def _get_module(self, pyfunction): - module = pyfunction.get_module() - if module is not None: - resource = module.get_resource() - if resource is not None: - return pyfunction.pycore.modname(resource) + '.' - return '' - - def _trim_docstring(self, docstring, indents=0): - """The sample code from :PEP:`257`""" - if not docstring: - return '' - # Convert tabs to spaces (following normal Python rules) - # and split into a list of lines: - lines = docstring.expandtabs().splitlines() - # Determine minimum indentation (first line doesn't count): - indent = sys.maxint - for line in lines[1:]: - stripped = line.lstrip() - if stripped: - indent = min(indent, len(line) - len(stripped)) - # Remove indentation (first line is special): - trimmed = [lines[0].strip()] - if indent < sys.maxint: - for line in lines[1:]: - trimmed.append(line[indent:].rstrip()) - # Strip off trailing and leading blank lines: - while trimmed and not trimmed[-1]: - trimmed.pop() - while trimmed and not trimmed[0]: - trimmed.pop(0) - # Return a single string: - return '\n'.join((' ' * indents + line for line in trimmed)) - - -# Deprecated classes - -class TemplateProposal(CodeAssistProposal): - def __init__(self, name, template): - warnings.warn('TemplateProposal is deprecated.', - DeprecationWarning, stacklevel=2) - super(TemplateProposal, self).__init__(name, 'template') - self.template = template - - -class Template(object): - - def __init__(self, template): - self.template = template - warnings.warn('Template is deprecated.', - DeprecationWarning, stacklevel=2) - - def variables(self): - return [] - - def substitute(self, mapping): - return self.template - - def get_cursor_location(self, mapping): - return len(self.template) diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/finderrors.py b/.vim/bundle/python-mode/pylibs/rope/contrib/finderrors.py @@ -1,91 +0,0 @@ -"""Finding bad name and attribute accesses - -`find_errors` function can be used to find possible bad name and -attribute accesses. As an example:: - - errors = find_errors(project, project.get_resource('mod.py')) - for error in errors: - print '%s: %s' % (error.lineno, error.error) - -prints possible errors for ``mod.py`` file. - -TODO: - -* use task handles -* reporting names at most once -* attributes of extension modules that don't appear in - extension_modules project config can be ignored -* not calling `PyScope.get_inner_scope_for_line()` if it is a - bottleneck; needs profiling -* not reporting occurrences where rope cannot infer the object -* rope saves multiple objects for some of the names in its objectdb - use all of them not to give false positives -* ... ;-) - -""" -from rope.base import ast, evaluate, pyobjects - - -def find_errors(project, resource): - """Find possible bad name and attribute accesses - - It returns a list of `Error`\s. - """ - pymodule = project.pycore.resource_to_pyobject(resource) - finder = _BadAccessFinder(pymodule) - ast.walk(pymodule.get_ast(), finder) - return finder.errors - - -class _BadAccessFinder(object): - - def __init__(self, pymodule): - self.pymodule = pymodule - self.scope = pymodule.get_scope() - self.errors = [] - - def _Name(self, node): - if isinstance(node.ctx, (ast.Store, ast.Param)): - return - scope = self.scope.get_inner_scope_for_line(node.lineno) - pyname = scope.lookup(node.id) - if pyname is None: - self._add_error(node, 'Unresolved variable') - elif self._is_defined_after(scope, pyname, node.lineno): - self._add_error(node, 'Defined later') - - def _Attribute(self, node): - if not isinstance(node.ctx, ast.Store): - scope = self.scope.get_inner_scope_for_line(node.lineno) - pyname = evaluate.eval_node(scope, node.value) - if pyname is not None and \ - pyname.get_object() != pyobjects.get_unknown(): - if node.attr not in pyname.get_object(): - self._add_error(node, 'Unresolved attribute') - ast.walk(node.value, self) - - def _add_error(self, node, msg): - if isinstance(node, ast.Attribute): - name = node.attr - else: - name = node.id - if name != 'None': - error = Error(node.lineno, msg + ' ' + name) - self.errors.append(error) - - def _is_defined_after(self, scope, pyname, lineno): - location = pyname.get_definition_location() - if location is not None and location[1] is not None: - if location[0] == self.pymodule and \ - lineno <= location[1] <= scope.get_end(): - return True - - -class Error(object): - - def __init__(self, lineno, error): - self.lineno = lineno - self.error = error - - def __str__(self): - return '%s: %s' % (self.lineno, self.error) diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/findit.py b/.vim/bundle/python-mode/pylibs/rope/contrib/findit.py @@ -1,110 +0,0 @@ -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.pyobjects -from rope.base import taskhandle, exceptions, worder -from rope.contrib import fixsyntax -from rope.refactor import occurrences - - -def find_occurrences(project, resource, offset, unsure=False, resources=None, - in_hierarchy=False, task_handle=taskhandle.NullTaskHandle()): - """Return a list of `Location`\s - - If `unsure` is `True`, possible matches are returned, too. You - can use `Location.unsure` to see which are unsure occurrences. - `resources` can be a list of `rope.base.resource.File`\s that - should be searched for occurrences; if `None` all python files - in the project are searched. - - """ - name = worder.get_name_at(resource, offset) - this_pymodule = project.pycore.resource_to_pyobject(resource) - primary, pyname = rope.base.evaluate.eval_location2( - this_pymodule, offset) - def is_match(occurrence): - return unsure - finder = occurrences.create_finder( - project.pycore, name, pyname, unsure=is_match, - in_hierarchy=in_hierarchy, instance=primary) - if resources is None: - resources = project.pycore.get_python_files() - job_set = task_handle.create_jobset('Finding Occurrences', - count=len(resources)) - return _find_locations(finder, resources, job_set) - - -def find_implementations(project, resource, offset, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Find the places a given method is overridden. - - Finds the places a method is implemented. Returns a list of - `Location`\s. - """ - name = worder.get_name_at(resource, offset) - this_pymodule = project.pycore.resource_to_pyobject(resource) - pyname = rope.base.evaluate.eval_location(this_pymodule, offset) - if pyname is not None: - pyobject = pyname.get_object() - if not isinstance(pyobject, rope.base.pyobjects.PyFunction) or \ - pyobject.get_kind() != 'method': - raise exceptions.BadIdentifierError('Not a method!') - else: - raise exceptions.BadIdentifierError('Cannot resolve the identifier!') - def is_defined(occurrence): - if not occurrence.is_defined(): - return False - def not_self(occurrence): - if occurrence.get_pyname().get_object() == pyname.get_object(): - return False - filters = [is_defined, not_self, - occurrences.InHierarchyFilter(pyname, True)] - finder = occurrences.Finder(project.pycore, name, filters=filters) - if resources is None: - resources = project.pycore.get_python_files() - job_set = task_handle.create_jobset('Finding Implementations', - count=len(resources)) - return _find_locations(finder, resources, job_set) - - -def find_definition(project, code, offset, resource=None, maxfixes=1): - """Return the definition location of the python name at `offset` - - A `Location` object is returned if the definition location can be - determined, otherwise ``None`` is returned. - """ - fixer = fixsyntax.FixSyntax(project.pycore, code, resource, maxfixes) - main_module = fixer.get_pymodule() - pyname = fixer.pyname_at(offset) - if pyname is not None: - module, lineno = pyname.get_definition_location() - name = rope.base.worder.Worder(code).get_word_at(offset) - if lineno is not None: - start = module.lines.get_line_start(lineno) - def check_offset(occurrence): - if occurrence.offset < start: - return False - pyname_filter = occurrences.PyNameFilter(pyname) - finder = occurrences.Finder(project.pycore, name, - [check_offset, pyname_filter]) - for occurrence in finder.find_occurrences(pymodule=module): - return Location(occurrence) - - -class Location(object): - - def __init__(self, occurrence): - self.resource = occurrence.resource - self.region = occurrence.get_word_range() - self.offset = self.region[0] - self.unsure = occurrence.is_unsure() - self.lineno = occurrence.lineno - - -def _find_locations(finder, resources, job_set): - result = [] - for resource in resources: - job_set.started_job(resource.path) - for occurrence in finder.find_occurrences(resource): - result.append(Location(occurrence)) - job_set.finished_job() - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/fixmodnames.py b/.vim/bundle/python-mode/pylibs/rope/contrib/fixmodnames.py @@ -1,69 +0,0 @@ -"""Fix the name of modules - -This module is useful when you want to rename many of the modules in -your project. That can happen specially when you want to change their -naming style. - -For instance:: - - fixer = FixModuleNames(project) - changes = fixer.get_changes(fixer=str.lower) - project.do(changes) - -Here it renames all modules and packages to use lower-cased chars. -You can tell it to use any other style by using the ``fixer`` -argument. - -""" -from rope.base import change, taskhandle -from rope.contrib import changestack -from rope.refactor import rename - - -class FixModuleNames(object): - - def __init__(self, project): - self.project = project - - def get_changes(self, fixer=str.lower, - task_handle=taskhandle.NullTaskHandle()): - """Fix module names - - `fixer` is a function that takes and returns a `str`. Given - the name of a module, it should return the fixed name. - - """ - stack = changestack.ChangeStack(self.project, 'Fixing module names') - jobset = task_handle.create_jobset('Fixing module names', - self._count_fixes(fixer) + 1) - try: - while True: - for resource in self._tobe_fixed(fixer): - jobset.started_job(resource.path) - renamer = rename.Rename(self.project, resource) - changes = renamer.get_changes(fixer(self._name(resource))) - stack.push(changes) - jobset.finished_job() - break - else: - break - finally: - jobset.started_job('Reverting to original state') - stack.pop_all() - jobset.finished_job() - return stack.merged() - - def _count_fixes(self, fixer): - return len(list(self._tobe_fixed(fixer))) - - def _tobe_fixed(self, fixer): - for resource in self.project.pycore.get_python_files(): - modname = self._name(resource) - if modname != fixer(modname): - yield resource - - def _name(self, resource): - modname = resource.name.rsplit('.', 1)[0] - if modname == '__init__': - modname = resource.parent.name - return modname diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/fixsyntax.py b/.vim/bundle/python-mode/pylibs/rope/contrib/fixsyntax.py @@ -1,178 +0,0 @@ -import rope.base.codeanalyze -import rope.base.evaluate -from rope.base import worder, exceptions, utils -from rope.base.codeanalyze import ArrayLinesAdapter, LogicalLineFinder - - -class FixSyntax(object): - - def __init__(self, pycore, code, resource, maxfixes=1): - self.pycore = pycore - self.code = code - self.resource = resource - self.maxfixes = maxfixes - - @utils.saveit - def get_pymodule(self): - """Get a `PyModule`""" - errors = [] - code = self.code - tries = 0 - while True: - try: - if tries == 0 and self.resource is not None and \ - self.resource.read() == code: - return self.pycore.resource_to_pyobject(self.resource, - force_errors=True) - return self.pycore.get_string_module( - code, resource=self.resource, force_errors=True) - except exceptions.ModuleSyntaxError, e: - if tries < self.maxfixes: - tries += 1 - self.commenter.comment(e.lineno) - code = '\n'.join(self.commenter.lines) - errors.append(' * line %s: %s ... fixed' % (e.lineno, - e.message_)) - else: - errors.append(' * line %s: %s ... raised!' % (e.lineno, - e.message_)) - new_message = ('\nSyntax errors in file %s:\n' % e.filename) \ - + '\n'.join(errors) - raise exceptions.ModuleSyntaxError(e.filename, e.lineno, - new_message) - - @property - @utils.saveit - def commenter(self): - return _Commenter(self.code) - - def pyname_at(self, offset): - pymodule = self.get_pymodule() - def old_pyname(): - word_finder = worder.Worder(self.code, True) - expression = word_finder.get_primary_at(offset) - expression = expression.replace('\\\n', ' ').replace('\n', ' ') - lineno = self.code.count('\n', 0, offset) - scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - return rope.base.evaluate.eval_str(scope, expression) - new_code = pymodule.source_code - def new_pyname(): - newoffset = self.commenter.transfered_offset(offset) - return rope.base.evaluate.eval_location(pymodule, newoffset) - if new_code.startswith(self.code[:offset + 1]): - return new_pyname() - result = old_pyname() - if result is None: - return new_pyname() - return result - - -class _Commenter(object): - - def __init__(self, code): - self.code = code - self.lines = self.code.split('\n') - self.lines.append('\n') - self.origs = range(len(self.lines) + 1) - self.diffs = [0] * (len(self.lines) + 1) - - def comment(self, lineno): - start = _logical_start(self.lines, lineno, check_prev=True) - 1 - # using self._get_stmt_end() instead of self._get_block_end() - # to lower commented lines - end = self._get_stmt_end(start) - indents = _get_line_indents(self.lines[start]) - if 0 < start: - last_lineno = self._last_non_blank(start - 1) - last_line = self.lines[last_lineno] - if last_line.rstrip().endswith(':'): - indents = _get_line_indents(last_line) + 4 - self._set(start, ' ' * indents + 'pass') - for line in range(start + 1, end + 1): - self._set(line, self.lines[start]) - self._fix_incomplete_try_blocks(lineno, indents) - - def transfered_offset(self, offset): - lineno = self.code.count('\n', 0, offset) - diff = sum(self.diffs[:lineno]) - return offset + diff - - def _last_non_blank(self, start): - while start > 0 and self.lines[start].strip() == '': - start -= 1 - return start - - def _get_block_end(self, lineno): - end_line = lineno - base_indents = _get_line_indents(self.lines[lineno]) - for i in range(lineno + 1, len(self.lines)): - if _get_line_indents(self.lines[i]) >= base_indents: - end_line = i - else: - break - return end_line - - def _get_stmt_end(self, lineno): - end_line = lineno - base_indents = _get_line_indents(self.lines[lineno]) - for i in range(lineno + 1, len(self.lines)): - if _get_line_indents(self.lines[i]) <= base_indents: - return i - 1 - return lineno - - def _fix_incomplete_try_blocks(self, lineno, indents): - block_start = lineno - last_indents = current_indents = indents - while block_start > 0: - block_start = rope.base.codeanalyze.get_block_start( - ArrayLinesAdapter(self.lines), block_start) - 1 - if self.lines[block_start].strip().startswith('try:'): - indents = _get_line_indents(self.lines[block_start]) - if indents > last_indents: - continue - last_indents = indents - block_end = self._find_matching_deindent(block_start) - line = self.lines[block_end].strip() - if not (line.startswith('finally:') or - line.startswith('except ') or - line.startswith('except:')): - self._insert(block_end, ' ' * indents + 'finally:') - self._insert(block_end + 1, ' ' * indents + ' pass') - - def _find_matching_deindent(self, line_number): - indents = _get_line_indents(self.lines[line_number]) - current_line = line_number + 1 - while current_line < len(self.lines): - line = self.lines[current_line] - if not line.strip().startswith('#') and not line.strip() == '': - # HACK: We should have used logical lines here - if _get_line_indents(self.lines[current_line]) <= indents: - return current_line - current_line += 1 - return len(self.lines) - 1 - - def _set(self, lineno, line): - self.diffs[self.origs[lineno]] += len(line) - len(self.lines[lineno]) - self.lines[lineno] = line - - def _insert(self, lineno, line): - self.diffs[self.origs[lineno]] += len(line) + 1 - self.origs.insert(lineno, self.origs[lineno]) - self.lines.insert(lineno, line) - -def _logical_start(lines, lineno, check_prev=False): - logical_finder = LogicalLineFinder(ArrayLinesAdapter(lines)) - if check_prev: - prev = lineno - 1 - while prev > 0: - start, end = logical_finder.logical_line_in(prev) - if end is None or start <= lineno < end: - return start - if start <= prev: - break - prev -= 1 - return logical_finder.logical_line_in(lineno)[0] - - -def _get_line_indents(line): - return rope.base.codeanalyze.count_line_indents(line) diff --git a/.vim/bundle/python-mode/pylibs/rope/contrib/generate.py b/.vim/bundle/python-mode/pylibs/rope/contrib/generate.py @@ -1,355 +0,0 @@ -import rope.base.evaluate -from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze -from rope.refactor import sourceutils, importutils, functionutils, suites - - -def create_generate(kind, project, resource, offset): - """A factory for creating `Generate` objects - - `kind` can be 'variable', 'function', 'class', 'module' or - 'package'. - - """ - generate = eval('Generate' + kind.title()) - return generate(project, resource, offset) - - -def create_module(project, name, sourcefolder=None): - """Creates a module and returns a `rope.base.resources.File`""" - if sourcefolder is None: - sourcefolder = project.root - packages = name.split('.') - parent = sourcefolder - for package in packages[:-1]: - parent = parent.get_child(package) - return parent.create_file(packages[-1] + '.py') - -def create_package(project, name, sourcefolder=None): - """Creates a package and returns a `rope.base.resources.Folder`""" - if sourcefolder is None: - sourcefolder = project.root - packages = name.split('.') - parent = sourcefolder - for package in packages[:-1]: - parent = parent.get_child(package) - made_packages = parent.create_folder(packages[-1]) - made_packages.create_file('__init__.py') - return made_packages - - -class _Generate(object): - - def __init__(self, project, resource, offset): - self.project = project - self.resource = resource - self.info = self._generate_info(project, resource, offset) - self.name = self.info.get_name() - self._check_exceptional_conditions() - - def _generate_info(self, project, resource, offset): - return _GenerationInfo(project.pycore, resource, offset) - - def _check_exceptional_conditions(self): - if self.info.element_already_exists(): - raise exceptions.RefactoringError( - 'Element <%s> already exists.' % self.name) - if not self.info.primary_is_found(): - raise exceptions.RefactoringError( - 'Cannot determine the scope <%s> should be defined in.' % self.name) - - def get_changes(self): - changes = change.ChangeSet('Generate %s <%s>' % - (self._get_element_kind(), self.name)) - indents = self.info.get_scope_indents() - blanks = self.info.get_blank_lines() - base_definition = sourceutils.fix_indentation(self._get_element(), indents) - definition = '\n' * blanks[0] + base_definition + '\n' * blanks[1] - - resource = self.info.get_insertion_resource() - start, end = self.info.get_insertion_offsets() - - collector = codeanalyze.ChangeCollector(resource.read()) - collector.add_change(start, end, definition) - changes.add_change(change.ChangeContents( - resource, collector.get_changed())) - return changes - - def get_location(self): - return (self.info.get_insertion_resource(), - self.info.get_insertion_lineno()) - - def _get_element_kind(self): - raise NotImplementedError() - - def _get_element(self): - raise NotImplementedError() - - -class GenerateFunction(_Generate): - - def _generate_info(self, project, resource, offset): - return _FunctionGenerationInfo(project.pycore, resource, offset) - - def _get_element(self): - decorator = '' - args = [] - if self.info.is_static_method(): - decorator = '@staticmethod\n' - if self.info.is_method() or self.info.is_constructor() or \ - self.info.is_instance(): - args.append('self') - args.extend(self.info.get_passed_args()) - definition = '%sdef %s(%s):\n pass\n' % (decorator, self.name, - ', '.join(args)) - return definition - - def _get_element_kind(self): - return 'Function' - - -class GenerateVariable(_Generate): - - def _get_element(self): - return '%s = None\n' % self.name - - def _get_element_kind(self): - return 'Variable' - - -class GenerateClass(_Generate): - - def _get_element(self): - return 'class %s(object):\n pass\n' % self.name - - def _get_element_kind(self): - return 'Class' - - -class GenerateModule(_Generate): - - def get_changes(self): - package = self.info.get_package() - changes = change.ChangeSet('Generate Module <%s>' % self.name) - new_resource = self.project.get_file('%s/%s.py' % (package.path, self.name)) - if new_resource.exists(): - raise exceptions.RefactoringError( - 'Module <%s> already exists' % new_resource.path) - changes.add_change(change.CreateResource(new_resource)) - changes.add_change(_add_import_to_module( - self.project.pycore, self.resource, new_resource)) - return changes - - def get_location(self): - package = self.info.get_package() - return (package.get_child('%s.py' % self.name) , 1) - - -class GeneratePackage(_Generate): - - def get_changes(self): - package = self.info.get_package() - changes = change.ChangeSet('Generate Package <%s>' % self.name) - new_resource = self.project.get_folder('%s/%s' % (package.path, self.name)) - if new_resource.exists(): - raise exceptions.RefactoringError( - 'Package <%s> already exists' % new_resource.path) - changes.add_change(change.CreateResource(new_resource)) - changes.add_change(_add_import_to_module( - self.project.pycore, self.resource, new_resource)) - child = self.project.get_folder(package.path + '/' + self.name) - changes.add_change(change.CreateFile(child, '__init__.py')) - return changes - - def get_location(self): - package = self.info.get_package() - child = package.get_child(self.name) - return (child.get_child('__init__.py') , 1) - - -def _add_import_to_module(pycore, resource, imported): - pymodule = pycore.resource_to_pyobject(resource) - import_tools = importutils.ImportTools(pycore) - module_imports = import_tools.module_imports(pymodule) - module_name = pycore.modname(imported) - new_import = importutils.NormalImport(((module_name, None), )) - module_imports.add_import(new_import) - return change.ChangeContents(resource, module_imports.get_changed_source()) - - -class _GenerationInfo(object): - - def __init__(self, pycore, resource, offset): - self.pycore = pycore - self.resource = resource - self.offset = offset - self.source_pymodule = self.pycore.resource_to_pyobject(resource) - finder = rope.base.evaluate.ScopeNameFinder(self.source_pymodule) - self.primary, self.pyname = finder.get_primary_and_pyname_at(offset) - self._init_fields() - - def _init_fields(self): - self.source_scope = self._get_source_scope() - self.goal_scope = self._get_goal_scope() - self.goal_pymodule = self._get_goal_module(self.goal_scope) - - def _get_goal_scope(self): - if self.primary is None: - return self._get_source_scope() - pyobject = self.primary.get_object() - if isinstance(pyobject, pyobjects.PyDefinedObject): - return pyobject.get_scope() - elif isinstance(pyobject.get_type(), pyobjects.PyClass): - return pyobject.get_type().get_scope() - - def _get_goal_module(self, scope): - if scope is None: - return - while scope.parent is not None: - scope = scope.parent - return scope.pyobject - - def _get_source_scope(self): - module_scope = self.source_pymodule.get_scope() - lineno = self.source_pymodule.lines.get_line_number(self.offset) - return module_scope.get_inner_scope_for_line(lineno) - - def get_insertion_lineno(self): - lines = self.goal_pymodule.lines - if self.goal_scope == self.source_scope: - line_finder = self.goal_pymodule.logical_lines - lineno = lines.get_line_number(self.offset) - lineno = line_finder.logical_line_in(lineno)[0] - root = suites.ast_suite_tree(self.goal_scope.pyobject.get_ast()) - suite = root.find_suite(lineno) - indents = sourceutils.get_indents(lines, lineno) - while self.get_scope_indents() < indents: - lineno = suite.get_start() - indents = sourceutils.get_indents(lines, lineno) - suite = suite.parent - return lineno - else: - return min(self.goal_scope.get_end() + 1, lines.length()) - - def get_insertion_resource(self): - return self.goal_pymodule.get_resource() - - def get_insertion_offsets(self): - if self.goal_scope.get_kind() == 'Class': - start, end = sourceutils.get_body_region(self.goal_scope.pyobject) - if self.goal_pymodule.source_code[start:end].strip() == 'pass': - return start, end - lines = self.goal_pymodule.lines - start = lines.get_line_start(self.get_insertion_lineno()) - return (start, start) - - def get_scope_indents(self): - if self.goal_scope.get_kind() == 'Module': - return 0 - return sourceutils.get_indents(self.goal_pymodule.lines, - self.goal_scope.get_start()) + 4 - - def get_blank_lines(self): - if self.goal_scope.get_kind() == 'Module': - base_blanks = 2 - if self.goal_pymodule.source_code.strip() == '': - base_blanks = 0 - if self.goal_scope.get_kind() == 'Class': - base_blanks = 1 - if self.goal_scope.get_kind() == 'Function': - base_blanks = 0 - if self.goal_scope == self.source_scope: - return (0, base_blanks) - return (base_blanks, 0) - - def get_package(self): - primary = self.primary - if self.primary is None: - return self.pycore.get_source_folders()[0] - if isinstance(primary.get_object(), pyobjects.PyPackage): - return primary.get_object().get_resource() - raise exceptions.RefactoringError( - 'A module/package can be only created in a package.') - - def primary_is_found(self): - return self.goal_scope is not None - - def element_already_exists(self): - if self.pyname is None or isinstance(self.pyname, pynames.UnboundName): - return False - return self.get_name() in self.goal_scope.get_defined_names() - - def get_name(self): - return worder.get_name_at(self.resource, self.offset) - - -class _FunctionGenerationInfo(_GenerationInfo): - - def _get_goal_scope(self): - if self.is_constructor(): - return self.pyname.get_object().get_scope() - if self.is_instance(): - return self.pyname.get_object().get_type().get_scope() - if self.primary is None: - return self._get_source_scope() - pyobject = self.primary.get_object() - if isinstance(pyobject, pyobjects.PyDefinedObject): - return pyobject.get_scope() - elif isinstance(pyobject.get_type(), pyobjects.PyClass): - return pyobject.get_type().get_scope() - - def element_already_exists(self): - if self.pyname is None or isinstance(self.pyname, pynames.UnboundName): - return False - return self.get_name() in self.goal_scope.get_defined_names() - - def is_static_method(self): - return self.primary is not None and \ - isinstance(self.primary.get_object(), pyobjects.PyClass) - - def is_method(self): - return self.primary is not None and \ - isinstance(self.primary.get_object().get_type(), pyobjects.PyClass) - - def is_constructor(self): - return self.pyname is not None and \ - isinstance(self.pyname.get_object(), pyobjects.PyClass) - - def is_instance(self): - if self.pyname is None: - return False - pyobject = self.pyname.get_object() - return isinstance(pyobject.get_type(), pyobjects.PyClass) - - def get_name(self): - if self.is_constructor(): - return '__init__' - if self.is_instance(): - return '__call__' - return worder.get_name_at(self.resource, self.offset) - - def get_passed_args(self): - result = [] - source = self.source_pymodule.source_code - finder = worder.Worder(source) - if finder.is_a_function_being_called(self.offset): - start, end = finder.get_primary_range(self.offset) - parens_start, parens_end = finder.get_word_parens_range(end - 1) - call = source[start:parens_end] - parser = functionutils._FunctionParser(call, False) - args, keywords = parser.get_parameters() - for arg in args: - if self._is_id(arg): - result.append(arg) - else: - result.append('arg%d' % len(result)) - for name, value in keywords: - result.append(name) - return result - - def _is_id(self, arg): - def id_or_underline(c): - return c.isalpha() or c == '_' - for c in arg: - if not id_or_underline(c) and not c.isdigit(): - return False - return id_or_underline(arg[0]) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/__init__.py b/.vim/bundle/python-mode/pylibs/rope/refactor/__init__.py @@ -1,55 +0,0 @@ -"""rope refactor package - -This package contains modules that perform python refactorings. -Refactoring classes perform refactorings in 4 steps: - -1. Collect some data for performing the refactoring and use them - to construct a refactoring class. Like:: - - renamer = Rename(project, resource, offset) - -2. Some refactorings give you useful information about the - refactoring after their construction. Like:: - - print(renamer.get_old_name()) - -3. Give the refactoring class more information about how to - perform the refactoring and get the changes this refactoring is - going to make. This is done by calling `get_changes` method of the - refactoring class. Like:: - - changes = renamer.get_changes(new_name) - -4. You can commit the changes. Like:: - - project.do(changes) - -These steps are like the steps IDEs usually do for performing a -refactoring. These are the things an IDE does in each step: - -1. Construct a refactoring object by giving it information like - resource, offset and ... . Some of the refactoring problems (like - performing rename refactoring on language keywords) can be reported - here. -2. Print some information about the refactoring and ask the user - about the information that are necessary for completing the - refactoring (like new name). -3. Call the `get_changes` by passing it information asked from - the user (if necessary) and get and preview the changes returned by - it. -4. perform the refactoring. - -From ``0.5m5`` release the `get_changes()` method of some time- -consuming refactorings take an optional `rope.base.taskhandle. -TaskHandle` parameter. You can use this object for stopping or -monitoring the progress of refactorings. - -""" -from rope.refactor.importutils import ImportOrganizer -from rope.refactor.topackage import ModuleToPackage - - -__all__ = ['rename', 'move', 'inline', 'extract', 'restructure', 'topackage', - 'importutils', 'usefunction', 'change_signature', - 'encapsulate_field', 'introduce_factory', 'introduce_parameter', - 'localtofield', 'method_object', 'multiproject'] diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/change_signature.py b/.vim/bundle/python-mode/pylibs/rope/refactor/change_signature.py @@ -1,342 +0,0 @@ -import copy - -import rope.base.exceptions -from rope.base import pyobjects, taskhandle, evaluate, worder, codeanalyze, utils -from rope.base.change import ChangeContents, ChangeSet -from rope.refactor import occurrences, functionutils - - -class ChangeSignature(object): - - def __init__(self, project, resource, offset): - self.pycore = project.pycore - self.resource = resource - self.offset = offset - self._set_name_and_pyname() - if self.pyname is None or self.pyname.get_object() is None or \ - not isinstance(self.pyname.get_object(), pyobjects.PyFunction): - raise rope.base.exceptions.RefactoringError( - 'Change method signature should be performed on functions') - - def _set_name_and_pyname(self): - self.name = worder.get_name_at(self.resource, self.offset) - this_pymodule = self.pycore.resource_to_pyobject(self.resource) - self.primary, self.pyname = evaluate.eval_location2( - this_pymodule, self.offset) - if self.pyname is None: - return - pyobject = self.pyname.get_object() - if isinstance(pyobject, pyobjects.PyClass) and \ - '__init__' in pyobject: - self.pyname = pyobject['__init__'] - self.name = '__init__' - pyobject = self.pyname.get_object() - self.others = None - if self.name == '__init__' and \ - isinstance(pyobject, pyobjects.PyFunction) and \ - isinstance(pyobject.parent, pyobjects.PyClass): - pyclass = pyobject.parent - self.others = (pyclass.get_name(), - pyclass.parent[pyclass.get_name()]) - - def _change_calls(self, call_changer, in_hierarchy=None, resources=None, - handle=taskhandle.NullTaskHandle()): - if resources is None: - resources = self.pycore.get_python_files() - changes = ChangeSet('Changing signature of <%s>' % self.name) - job_set = handle.create_jobset('Collecting Changes', len(resources)) - finder = occurrences.create_finder( - self.pycore, self.name, self.pyname, instance=self.primary, - in_hierarchy=in_hierarchy and self.is_method()) - if self.others: - name, pyname = self.others - constructor_finder = occurrences.create_finder( - self.pycore, name, pyname, only_calls=True) - finder = _MultipleFinders([finder, constructor_finder]) - for file in resources: - job_set.started_job(file.path) - change_calls = _ChangeCallsInModule( - self.pycore, finder, file, call_changer) - changed_file = change_calls.get_changed_module() - if changed_file is not None: - changes.add_change(ChangeContents(file, changed_file)) - job_set.finished_job() - return changes - - def get_args(self): - """Get function arguments. - - Return a list of ``(name, default)`` tuples for all but star - and double star arguments. For arguments that don't have a - default, `None` will be used. - """ - return self._definfo().args_with_defaults - - def is_method(self): - pyfunction = self.pyname.get_object() - return isinstance(pyfunction.parent, pyobjects.PyClass) - - @utils.deprecated('Use `ChangeSignature.get_args()` instead') - def get_definition_info(self): - return self._definfo() - - def _definfo(self): - return functionutils.DefinitionInfo.read(self.pyname.get_object()) - - @utils.deprecated() - def normalize(self): - changer = _FunctionChangers( - self.pyname.get_object(), self.get_definition_info(), - [ArgumentNormalizer()]) - return self._change_calls(changer) - - @utils.deprecated() - def remove(self, index): - changer = _FunctionChangers( - self.pyname.get_object(), self.get_definition_info(), - [ArgumentRemover(index)]) - return self._change_calls(changer) - - @utils.deprecated() - def add(self, index, name, default=None, value=None): - changer = _FunctionChangers( - self.pyname.get_object(), self.get_definition_info(), - [ArgumentAdder(index, name, default, value)]) - return self._change_calls(changer) - - @utils.deprecated() - def inline_default(self, index): - changer = _FunctionChangers( - self.pyname.get_object(), self.get_definition_info(), - [ArgumentDefaultInliner(index)]) - return self._change_calls(changer) - - @utils.deprecated() - def reorder(self, new_ordering): - changer = _FunctionChangers( - self.pyname.get_object(), self.get_definition_info(), - [ArgumentReorderer(new_ordering)]) - return self._change_calls(changer) - - def get_changes(self, changers, in_hierarchy=False, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Get changes caused by this refactoring - - `changers` is a list of `_ArgumentChanger`\s. If `in_hierarchy` - is `True` the changers are applyed to all matching methods in - the class hierarchy. - `resources` can be a list of `rope.base.resource.File`\s that - should be searched for occurrences; if `None` all python files - in the project are searched. - - """ - function_changer = _FunctionChangers(self.pyname.get_object(), - self._definfo(), changers) - return self._change_calls(function_changer, in_hierarchy, - resources, task_handle) - - -class _FunctionChangers(object): - - def __init__(self, pyfunction, definition_info, changers=None): - self.pyfunction = pyfunction - self.definition_info = definition_info - self.changers = changers - self.changed_definition_infos = self._get_changed_definition_infos() - - def _get_changed_definition_infos(self): - result = [] - definition_info = self.definition_info - result.append(definition_info) - for changer in self.changers: - definition_info = copy.deepcopy(definition_info) - changer.change_definition_info(definition_info) - result.append(definition_info) - return result - - def change_definition(self, call): - return self.changed_definition_infos[-1].to_string() - - def change_call(self, primary, pyname, call): - call_info = functionutils.CallInfo.read( - primary, pyname, self.definition_info, call) - mapping = functionutils.ArgumentMapping(self.definition_info, call_info) - - for definition_info, changer in zip(self.changed_definition_infos, self.changers): - changer.change_argument_mapping(definition_info, mapping) - - return mapping.to_call_info(self.changed_definition_infos[-1]).to_string() - - -class _ArgumentChanger(object): - - def change_definition_info(self, definition_info): - pass - - def change_argument_mapping(self, definition_info, argument_mapping): - pass - - -class ArgumentNormalizer(_ArgumentChanger): - pass - - -class ArgumentRemover(_ArgumentChanger): - - def __init__(self, index): - self.index = index - - def change_definition_info(self, call_info): - if self.index < len(call_info.args_with_defaults): - del call_info.args_with_defaults[self.index] - elif self.index == len(call_info.args_with_defaults) and \ - call_info.args_arg is not None: - call_info.args_arg = None - elif (self.index == len(call_info.args_with_defaults) and - call_info.args_arg is None and call_info.keywords_arg is not None) or \ - (self.index == len(call_info.args_with_defaults) + 1 and - call_info.args_arg is not None and call_info.keywords_arg is not None): - call_info.keywords_arg = None - - def change_argument_mapping(self, definition_info, mapping): - if self.index < len(definition_info.args_with_defaults): - name = definition_info.args_with_defaults[0] - if name in mapping.param_dict: - del mapping.param_dict[name] - - -class ArgumentAdder(_ArgumentChanger): - - def __init__(self, index, name, default=None, value=None): - self.index = index - self.name = name - self.default = default - self.value = value - - def change_definition_info(self, definition_info): - for pair in definition_info.args_with_defaults: - if pair[0] == self.name: - raise rope.base.exceptions.RefactoringError( - 'Adding duplicate parameter: <%s>.' % self.name) - definition_info.args_with_defaults.insert(self.index, - (self.name, self.default)) - - def change_argument_mapping(self, definition_info, mapping): - if self.value is not None: - mapping.param_dict[self.name] = self.value - - -class ArgumentDefaultInliner(_ArgumentChanger): - - def __init__(self, index): - self.index = index - self.remove = False - - def change_definition_info(self, definition_info): - if self.remove: - definition_info.args_with_defaults[self.index] = \ - (definition_info.args_with_defaults[self.index][0], None) - - def change_argument_mapping(self, definition_info, mapping): - default = definition_info.args_with_defaults[self.index][1] - name = definition_info.args_with_defaults[self.index][0] - if default is not None and name not in mapping.param_dict: - mapping.param_dict[name] = default - - -class ArgumentReorderer(_ArgumentChanger): - - def __init__(self, new_order, autodef=None): - """Construct an `ArgumentReorderer` - - Note that the `new_order` is a list containing the new - position of parameters; not the position each parameter - is going to be moved to. (changed in ``0.5m4``) - - For example changing ``f(a, b, c)`` to ``f(c, a, b)`` - requires passing ``[2, 0, 1]`` and *not* ``[1, 2, 0]``. - - The `autodef` (automatic default) argument, forces rope to use - it as a default if a default is needed after the change. That - happens when an argument without default is moved after - another that has a default value. Note that `autodef` should - be a string or `None`; the latter disables adding automatic - default. - - """ - self.new_order = new_order - self.autodef = autodef - - def change_definition_info(self, definition_info): - new_args = list(definition_info.args_with_defaults) - for new_index, index in enumerate(self.new_order): - new_args[new_index] = definition_info.args_with_defaults[index] - seen_default = False - for index, (arg, default) in enumerate(list(new_args)): - if default is not None: - seen_default = True - if seen_default and default is None and self.autodef is not None: - new_args[index] = (arg, self.autodef) - definition_info.args_with_defaults = new_args - - -class _ChangeCallsInModule(object): - - def __init__(self, pycore, occurrence_finder, resource, call_changer): - self.pycore = pycore - self.occurrence_finder = occurrence_finder - self.resource = resource - self.call_changer = call_changer - - def get_changed_module(self): - word_finder = worder.Worder(self.source) - change_collector = codeanalyze.ChangeCollector(self.source) - for occurrence in self.occurrence_finder.find_occurrences(self.resource): - if not occurrence.is_called() and not occurrence.is_defined(): - continue - start, end = occurrence.get_primary_range() - begin_parens, end_parens = word_finder.get_word_parens_range(end - 1) - if occurrence.is_called(): - primary, pyname = occurrence.get_primary_and_pyname() - changed_call = self.call_changer.change_call( - primary, pyname, self.source[start:end_parens]) - else: - changed_call = self.call_changer.change_definition( - self.source[start:end_parens]) - if changed_call is not None: - change_collector.add_change(start, end_parens, changed_call) - return change_collector.get_changed() - - @property - @utils.saveit - def pymodule(self): - return self.pycore.resource_to_pyobject(self.resource) - - @property - @utils.saveit - def source(self): - if self.resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - @property - @utils.saveit - def lines(self): - return self.pymodule.lines - - -class _MultipleFinders(object): - - def __init__(self, finders): - self.finders = finders - - def find_occurrences(self, resource=None, pymodule=None): - all_occurrences = [] - for finder in self.finders: - all_occurrences.extend(finder.find_occurrences(resource, pymodule)) - all_occurrences.sort(self._cmp_occurrences) - return all_occurrences - - def _cmp_occurrences(self, o1, o2): - return cmp(o1.get_primary_range(), o2.get_primary_range()) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/encapsulate_field.py b/.vim/bundle/python-mode/pylibs/rope/refactor/encapsulate_field.py @@ -1,202 +0,0 @@ -from rope.base import pynames, taskhandle, evaluate, exceptions, worder, utils -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import sourceutils, occurrences - - -class EncapsulateField(object): - - def __init__(self, project, resource, offset): - self.pycore = project.pycore - self.name = worder.get_name_at(resource, offset) - this_pymodule = self.pycore.resource_to_pyobject(resource) - self.pyname = evaluate.eval_location(this_pymodule, offset) - if not self._is_an_attribute(self.pyname): - raise exceptions.RefactoringError( - 'Encapsulate field should be performed on class attributes.') - self.resource = self.pyname.get_definition_location()[0].get_resource() - - def get_changes(self, getter=None, setter=None, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Get the changes this refactoring makes - - If `getter` is not `None`, that will be the name of the - getter, otherwise ``get_${field_name}`` will be used. The - same is true for `setter` and if it is None set_${field_name} is - used. - - `resources` can be a list of `rope.base.resource.File`\s that - the refactoring should be applied on; if `None` all python - files in the project are searched. - - """ - if resources is None: - resources = self.pycore.get_python_files() - changes = ChangeSet('Encapsulate field <%s>' % self.name) - job_set = task_handle.create_jobset('Collecting Changes', - len(resources)) - if getter is None: - getter = 'get_' + self.name - if setter is None: - setter = 'set_' + self.name - renamer = GetterSetterRenameInModule( - self.pycore, self.name, self.pyname, getter, setter) - for file in resources: - job_set.started_job(file.path) - if file == self.resource: - result = self._change_holding_module(changes, renamer, - getter, setter) - changes.add_change(ChangeContents(self.resource, result)) - else: - result = renamer.get_changed_module(file) - if result is not None: - changes.add_change(ChangeContents(file, result)) - job_set.finished_job() - return changes - - def get_field_name(self): - """Get the name of the field to be encapsulated""" - return self.name - - def _is_an_attribute(self, pyname): - if pyname is not None and isinstance(pyname, pynames.AssignedName): - pymodule, lineno = self.pyname.get_definition_location() - scope = pymodule.get_scope().\ - get_inner_scope_for_line(lineno) - if scope.get_kind() == 'Class': - return pyname in scope.get_names().values() - parent = scope.parent - if parent is not None and parent.get_kind() == 'Class': - return pyname in parent.get_names().values() - return False - - def _get_defining_class_scope(self): - defining_scope = self._get_defining_scope() - if defining_scope.get_kind() == 'Function': - defining_scope = defining_scope.parent - return defining_scope - - def _get_defining_scope(self): - pymodule, line = self.pyname.get_definition_location() - return pymodule.get_scope().get_inner_scope_for_line(line) - - def _change_holding_module(self, changes, renamer, getter, setter): - pymodule = self.pycore.resource_to_pyobject(self.resource) - class_scope = self._get_defining_class_scope() - defining_object = self._get_defining_scope().pyobject - start, end = sourceutils.get_body_region(defining_object) - - new_source = renamer.get_changed_module(pymodule=pymodule, - skip_start=start, skip_end=end) - if new_source is not None: - pymodule = self.pycore.get_string_module(new_source, self.resource) - class_scope = pymodule.get_scope().\ - get_inner_scope_for_line(class_scope.get_start()) - indents = sourceutils.get_indent(self.pycore) * ' ' - getter = 'def %s(self):\n%sreturn self.%s' % \ - (getter, indents, self.name) - setter = 'def %s(self, value):\n%sself.%s = value' % \ - (setter, indents, self.name) - new_source = sourceutils.add_methods(pymodule, class_scope, - [getter, setter]) - return new_source - - -class GetterSetterRenameInModule(object): - - def __init__(self, pycore, name, pyname, getter, setter): - self.pycore = pycore - self.name = name - self.finder = occurrences.create_finder(pycore, name, pyname) - self.getter = getter - self.setter = setter - - def get_changed_module(self, resource=None, pymodule=None, - skip_start=0, skip_end=0): - change_finder = _FindChangesForModule(self, resource, pymodule, - skip_start, skip_end) - return change_finder.get_changed_module() - - -class _FindChangesForModule(object): - - def __init__(self, finder, resource, pymodule, skip_start, skip_end): - self.pycore = finder.pycore - self.finder = finder.finder - self.getter = finder.getter - self.setter = finder.setter - self.resource = resource - self.pymodule = pymodule - self.last_modified = 0 - self.last_set = None - self.set_index = None - self.skip_start = skip_start - self.skip_end = skip_end - - def get_changed_module(self): - result = [] - for occurrence in self.finder.find_occurrences(self.resource, - self.pymodule): - start, end = occurrence.get_word_range() - if self.skip_start <= start < self.skip_end: - continue - self._manage_writes(start, result) - result.append(self.source[self.last_modified:start]) - if self._is_assigned_in_a_tuple_assignment(occurrence): - raise exceptions.RefactoringError( - 'Cannot handle tuple assignments in encapsulate field.') - if occurrence.is_written(): - assignment_type = self.worder.get_assignment_type(start) - if assignment_type == '=': - result.append(self.setter + '(') - else: - var_name = self.source[occurrence.get_primary_range()[0]: - start] + self.getter + '()' - result.append(self.setter + '(' + var_name - + ' %s ' % assignment_type[:-1]) - current_line = self.lines.get_line_number(start) - start_line, end_line = self.pymodule.logical_lines.\ - logical_line_in(current_line) - self.last_set = self.lines.get_line_end(end_line) - end = self.source.index('=', end) + 1 - self.set_index = len(result) - else: - result.append(self.getter + '()') - self.last_modified = end - if self.last_modified != 0: - self._manage_writes(len(self.source), result) - result.append(self.source[self.last_modified:]) - return ''.join(result) - return None - - def _manage_writes(self, offset, result): - if self.last_set is not None and self.last_set <= offset: - result.append(self.source[self.last_modified:self.last_set]) - set_value = ''.join(result[self.set_index:]).strip() - del result[self.set_index:] - result.append(set_value + ')') - self.last_modified = self.last_set - self.last_set = None - - def _is_assigned_in_a_tuple_assignment(self, occurance): - offset = occurance.get_word_range()[0] - return self.worder.is_assigned_in_a_tuple_assignment(offset) - - @property - @utils.saveit - def source(self): - if self.resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - @property - @utils.saveit - def lines(self): - if self.pymodule is None: - self.pymodule = self.pycore.resource_to_pyobject(self.resource) - return self.pymodule.lines - - @property - @utils.saveit - def worder(self): - return worder.Worder(self.source) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/extract.py b/.vim/bundle/python-mode/pylibs/rope/refactor/extract.py @@ -1,789 +0,0 @@ -import re - -from rope.base import ast, codeanalyze -from rope.base.change import ChangeSet, ChangeContents -from rope.base.exceptions import RefactoringError -from rope.refactor import (sourceutils, similarfinder, - patchedast, suites, usefunction) - - -# Extract refactoring has lots of special cases. I tried to split it -# to smaller parts to make it more manageable: -# -# _ExtractInfo: holds information about the refactoring; it is passed -# to the parts that need to have information about the refactoring -# -# _ExtractCollector: merely saves all of the information necessary for -# performing the refactoring. -# -# _DefinitionLocationFinder: finds where to insert the definition. -# -# _ExceptionalConditionChecker: checks for exceptional conditions in -# which the refactoring cannot be applied. -# -# _ExtractMethodParts: generates the pieces of code (like definition) -# needed for performing extract method. -# -# _ExtractVariableParts: like _ExtractMethodParts for variables. -# -# _ExtractPerformer: Uses above classes to collect refactoring -# changes. -# -# There are a few more helper functions and classes used by above -# classes. -class _ExtractRefactoring(object): - - def __init__(self, project, resource, start_offset, end_offset, - variable=False): - self.project = project - self.pycore = project.pycore - self.resource = resource - self.start_offset = self._fix_start(resource.read(), start_offset) - self.end_offset = self._fix_end(resource.read(), end_offset) - - def _fix_start(self, source, offset): - while offset < len(source) and source[offset].isspace(): - offset += 1 - return offset - - def _fix_end(self, source, offset): - while offset > 0 and source[offset - 1].isspace(): - offset -= 1 - return offset - - def get_changes(self, extracted_name, similar=False, global_=False): - """Get the changes this refactoring makes - - :parameters: - - `similar`: if `True`, similar expressions/statements are also - replaced. - - `global_`: if `True`, the extracted method/variable will - be global. - - """ - info = _ExtractInfo( - self.project, self.resource, self.start_offset, self.end_offset, - extracted_name, variable=self.kind == 'variable', - similar=similar, make_global=global_) - new_contents = _ExtractPerformer(info).extract() - changes = ChangeSet('Extract %s <%s>' % (self.kind, - extracted_name)) - changes.add_change(ChangeContents(self.resource, new_contents)) - return changes - - -class ExtractMethod(_ExtractRefactoring): - - def __init__(self, *args, **kwds): - super(ExtractMethod, self).__init__(*args, **kwds) - - kind = 'method' - - -class ExtractVariable(_ExtractRefactoring): - - def __init__(self, *args, **kwds): - kwds = dict(kwds) - kwds['variable'] = True - super(ExtractVariable, self).__init__(*args, **kwds) - - kind = 'variable' - - -class _ExtractInfo(object): - """Holds information about the extract to be performed""" - - def __init__(self, project, resource, start, end, new_name, - variable, similar, make_global): - self.pycore = project.pycore - self.resource = resource - self.pymodule = self.pycore.resource_to_pyobject(resource) - self.global_scope = self.pymodule.get_scope() - self.source = self.pymodule.source_code - self.lines = self.pymodule.lines - self.new_name = new_name - self.variable = variable - self.similar = similar - self._init_parts(start, end) - self._init_scope() - self.make_global = make_global - - def _init_parts(self, start, end): - self.region = (self._choose_closest_line_end(start), - self._choose_closest_line_end(end, end=True)) - - start = self.logical_lines.logical_line_in( - self.lines.get_line_number(self.region[0]))[0] - end = self.logical_lines.logical_line_in( - self.lines.get_line_number(self.region[1]))[1] - self.region_lines = (start, end) - - self.lines_region = (self.lines.get_line_start(self.region_lines[0]), - self.lines.get_line_end(self.region_lines[1])) - - @property - def logical_lines(self): - return self.pymodule.logical_lines - - def _init_scope(self): - start_line = self.region_lines[0] - scope = self.global_scope.get_inner_scope_for_line(start_line) - if scope.get_kind() != 'Module' and scope.get_start() == start_line: - scope = scope.parent - self.scope = scope - self.scope_region = self._get_scope_region(self.scope) - - def _get_scope_region(self, scope): - return (self.lines.get_line_start(scope.get_start()), - self.lines.get_line_end(scope.get_end()) + 1) - - def _choose_closest_line_end(self, offset, end=False): - lineno = self.lines.get_line_number(offset) - line_start = self.lines.get_line_start(lineno) - line_end = self.lines.get_line_end(lineno) - if self.source[line_start:offset].strip() == '': - if end: - return line_start - 1 - else: - return line_start - elif self.source[offset:line_end].strip() == '': - return min(line_end, len(self.source)) - return offset - - @property - def one_line(self): - return self.region != self.lines_region and \ - (self.logical_lines.logical_line_in(self.region_lines[0]) == - self.logical_lines.logical_line_in(self.region_lines[1])) - - @property - def global_(self): - return self.scope.parent is None - - @property - def method(self): - return self.scope.parent is not None and \ - self.scope.parent.get_kind() == 'Class' - - @property - def indents(self): - return sourceutils.get_indents(self.pymodule.lines, - self.region_lines[0]) - - @property - def scope_indents(self): - if self.global_: - return 0 - return sourceutils.get_indents(self.pymodule.lines, - self.scope.get_start()) - - @property - def extracted(self): - return self.source[self.region[0]:self.region[1]] - - _returned = None - @property - def returned(self): - """Does the extracted piece contain return statement""" - if self._returned is None: - node = _parse_text(self.extracted) - self._returned = usefunction._returns_last(node) - return self._returned - - -class _ExtractCollector(object): - """Collects information needed for performing the extract""" - - def __init__(self, info): - self.definition = None - self.body_pattern = None - self.checks = {} - self.replacement_pattern = None - self.matches = None - self.replacements = None - self.definition_location = None - - -class _ExtractPerformer(object): - - def __init__(self, info): - self.info = info - _ExceptionalConditionChecker()(self.info) - - def extract(self): - extract_info = self._collect_info() - content = codeanalyze.ChangeCollector(self.info.source) - definition = extract_info.definition - lineno, indents = extract_info.definition_location - offset = self.info.lines.get_line_start(lineno) - indented = sourceutils.fix_indentation(definition, indents) - content.add_change(offset, offset, indented) - self._replace_occurrences(content, extract_info) - return content.get_changed() - - def _replace_occurrences(self, content, extract_info): - for match in extract_info.matches: - replacement = similarfinder.CodeTemplate( - extract_info.replacement_pattern) - mapping = {} - for name in replacement.get_names(): - node = match.get_ast(name) - if node: - start, end = patchedast.node_region(match.get_ast(name)) - mapping[name] = self.info.source[start:end] - else: - mapping[name] = name - region = match.get_region() - content.add_change(region[0], region[1], - replacement.substitute(mapping)) - - def _collect_info(self): - extract_collector = _ExtractCollector(self.info) - self._find_definition(extract_collector) - self._find_matches(extract_collector) - self._find_definition_location(extract_collector) - return extract_collector - - def _find_matches(self, collector): - regions = self._where_to_search() - finder = similarfinder.SimilarFinder(self.info.pymodule) - matches = [] - for start, end in regions: - matches.extend((finder.get_matches(collector.body_pattern, - collector.checks, start, end))) - collector.matches = matches - - def _where_to_search(self): - if self.info.similar: - if self.info.make_global or self.info.global_: - return [(0, len(self.info.pymodule.source_code))] - if self.info.method and not self.info.variable: - class_scope = self.info.scope.parent - regions = [] - method_kind = _get_function_kind(self.info.scope) - for scope in class_scope.get_scopes(): - if method_kind == 'method' and \ - _get_function_kind(scope) != 'method': - continue - start = self.info.lines.get_line_start(scope.get_start()) - end = self.info.lines.get_line_end(scope.get_end()) - regions.append((start, end)) - return regions - else: - if self.info.variable: - return [self.info.scope_region] - else: - return [self.info._get_scope_region(self.info.scope.parent)] - else: - return [self.info.region] - - def _find_definition_location(self, collector): - matched_lines = [] - for match in collector.matches: - start = self.info.lines.get_line_number(match.get_region()[0]) - start_line = self.info.logical_lines.logical_line_in(start)[0] - matched_lines.append(start_line) - location_finder = _DefinitionLocationFinder(self.info, matched_lines) - collector.definition_location = (location_finder.find_lineno(), - location_finder.find_indents()) - - def _find_definition(self, collector): - if self.info.variable: - parts = _ExtractVariableParts(self.info) - else: - parts = _ExtractMethodParts(self.info) - collector.definition = parts.get_definition() - collector.body_pattern = parts.get_body_pattern() - collector.replacement_pattern = parts.get_replacement_pattern() - collector.checks = parts.get_checks() - - -class _DefinitionLocationFinder(object): - - def __init__(self, info, matched_lines): - self.info = info - self.matched_lines = matched_lines - # This only happens when subexpressions cannot be matched - if not matched_lines: - self.matched_lines.append(self.info.region_lines[0]) - - def find_lineno(self): - if self.info.variable and not self.info.make_global: - return self._get_before_line() - if self.info.make_global or self.info.global_: - toplevel = self._find_toplevel(self.info.scope) - ast = self.info.pymodule.get_ast() - newlines = sorted(self.matched_lines + [toplevel.get_end() + 1]) - return suites.find_visible(ast, newlines) - return self._get_after_scope() - - def _find_toplevel(self, scope): - toplevel = scope - if toplevel.parent is not None: - while toplevel.parent.parent is not None: - toplevel = toplevel.parent - return toplevel - - def find_indents(self): - if self.info.variable and not self.info.make_global: - return sourceutils.get_indents(self.info.lines, - self._get_before_line()) - else: - if self.info.global_ or self.info.make_global: - return 0 - return self.info.scope_indents - - def _get_before_line(self): - ast = self.info.scope.pyobject.get_ast() - return suites.find_visible(ast, self.matched_lines) - - def _get_after_scope(self): - return self.info.scope.get_end() + 1 - - -class _ExceptionalConditionChecker(object): - - def __call__(self, info): - self.base_conditions(info) - if info.one_line: - self.one_line_conditions(info) - else: - self.multi_line_conditions(info) - - def base_conditions(self, info): - if info.region[1] > info.scope_region[1]: - raise RefactoringError('Bad region selected for extract method') - end_line = info.region_lines[1] - end_scope = info.global_scope.get_inner_scope_for_line(end_line) - if end_scope != info.scope and end_scope.get_end() != end_line: - raise RefactoringError('Bad region selected for extract method') - try: - extracted = info.source[info.region[0]:info.region[1]] - if info.one_line: - extracted = '(%s)' % extracted - if _UnmatchedBreakOrContinueFinder.has_errors(extracted): - raise RefactoringError('A break/continue without having a ' - 'matching for/while loop.') - except SyntaxError: - raise RefactoringError('Extracted piece should ' - 'contain complete statements.') - - def one_line_conditions(self, info): - if self._is_region_on_a_word(info): - raise RefactoringError('Should extract complete statements.') - if info.variable and not info.one_line: - raise RefactoringError('Extract variable should not ' - 'span multiple lines.') - - def multi_line_conditions(self, info): - node = _parse_text(info.source[info.region[0]:info.region[1]]) - count = usefunction._return_count(node) - if count > 1: - raise RefactoringError('Extracted piece can have only one ' - 'return statement.') - if usefunction._yield_count(node): - raise RefactoringError('Extracted piece cannot ' - 'have yield statements.') - if count == 1 and not usefunction._returns_last(node): - raise RefactoringError('Return should be the last statement.') - if info.region != info.lines_region: - raise RefactoringError('Extracted piece should ' - 'contain complete statements.') - - def _is_region_on_a_word(self, info): - if info.region[0] > 0 and self._is_on_a_word(info, info.region[0] - 1) or \ - self._is_on_a_word(info, info.region[1] - 1): - return True - - def _is_on_a_word(self, info, offset): - prev = info.source[offset] - if not (prev.isalnum() or prev == '_') or \ - offset + 1 == len(info.source): - return False - next = info.source[offset + 1] - return next.isalnum() or next == '_' - - -class _ExtractMethodParts(object): - - def __init__(self, info): - self.info = info - self.info_collector = self._create_info_collector() - - def get_definition(self): - if self.info.global_: - return '\n%s\n' % self._get_function_definition() - else: - return '\n%s' % self._get_function_definition() - - def get_replacement_pattern(self): - variables = [] - variables.extend(self._find_function_arguments()) - variables.extend(self._find_function_returns()) - return similarfinder.make_pattern(self._get_call(), variables) - - def get_body_pattern(self): - variables = [] - variables.extend(self._find_function_arguments()) - variables.extend(self._find_function_returns()) - variables.extend(self._find_temps()) - return similarfinder.make_pattern(self._get_body(), variables) - - def _get_body(self): - result = sourceutils.fix_indentation(self.info.extracted, 0) - if self.info.one_line: - result = '(%s)' % result - return result - - def _find_temps(self): - return usefunction.find_temps(self.info.pycore.project, - self._get_body()) - - def get_checks(self): - if self.info.method and not self.info.make_global: - if _get_function_kind(self.info.scope) == 'method': - class_name = similarfinder._pydefined_to_str( - self.info.scope.parent.pyobject) - return {self._get_self_name(): 'type=' + class_name} - return {} - - def _create_info_collector(self): - zero = self.info.scope.get_start() - 1 - start_line = self.info.region_lines[0] - zero - end_line = self.info.region_lines[1] - zero - info_collector = _FunctionInformationCollector(start_line, end_line, - self.info.global_) - body = self.info.source[self.info.scope_region[0]: - self.info.scope_region[1]] - node = _parse_text(body) - ast.walk(node, info_collector) - return info_collector - - def _get_function_definition(self): - args = self._find_function_arguments() - returns = self._find_function_returns() - result = [] - if self.info.method and not self.info.make_global and \ - _get_function_kind(self.info.scope) != 'method': - result.append('@staticmethod\n') - result.append('def %s:\n' % self._get_function_signature(args)) - unindented_body = self._get_unindented_function_body(returns) - indents = sourceutils.get_indent(self.info.pycore) - function_body = sourceutils.indent_lines(unindented_body, indents) - result.append(function_body) - definition = ''.join(result) - - return definition + '\n' - - def _get_function_signature(self, args): - args = list(args) - prefix = '' - if self._extracting_method(): - self_name = self._get_self_name() - if self_name is None: - raise RefactoringError('Extracting a method from a function ' - 'with no self argument.') - if self_name in args: - args.remove(self_name) - args.insert(0, self_name) - return prefix + self.info.new_name + \ - '(%s)' % self._get_comma_form(args) - - def _extracting_method(self): - return self.info.method and not self.info.make_global and \ - _get_function_kind(self.info.scope) == 'method' - - def _get_self_name(self): - param_names = self.info.scope.pyobject.get_param_names() - if param_names: - return param_names[0] - - def _get_function_call(self, args): - prefix = '' - if self.info.method and not self.info.make_global: - if _get_function_kind(self.info.scope) == 'method': - self_name = self._get_self_name() - if self_name in args: - args.remove(self_name) - prefix = self_name + '.' - else: - prefix = self.info.scope.parent.pyobject.get_name() + '.' - return prefix + '%s(%s)' % (self.info.new_name, - self._get_comma_form(args)) - - def _get_comma_form(self, names): - result = '' - if names: - result += names[0] - for name in names[1:]: - result += ', ' + name - return result - - def _get_call(self): - if self.info.one_line: - args = self._find_function_arguments() - return self._get_function_call(args) - args = self._find_function_arguments() - returns = self._find_function_returns() - call_prefix = '' - if returns: - call_prefix = self._get_comma_form(returns) + ' = ' - if self.info.returned: - call_prefix = 'return ' - return call_prefix + self._get_function_call(args) - - def _find_function_arguments(self): - # if not make_global, do not pass any global names; they are - # all visible. - if self.info.global_ and not self.info.make_global: - return () - if not self.info.one_line: - result = (self.info_collector.prewritten & - self.info_collector.read) - result |= (self.info_collector.prewritten & - self.info_collector.postread & - (self.info_collector.maybe_written - - self.info_collector.written)) - return list(result) - start = self.info.region[0] - if start == self.info.lines_region[0]: - start = start + re.search('\S', self.info.extracted).start() - function_definition = self.info.source[start:self.info.region[1]] - read = _VariableReadsAndWritesFinder.find_reads_for_one_liners( - function_definition) - return list(self.info_collector.prewritten.intersection(read)) - - def _find_function_returns(self): - if self.info.one_line or self.info.returned: - return [] - written = self.info_collector.written | \ - self.info_collector.maybe_written - return list(written & self.info_collector.postread) - - def _get_unindented_function_body(self, returns): - if self.info.one_line: - return 'return ' + _join_lines(self.info.extracted) - extracted_body = self.info.extracted - unindented_body = sourceutils.fix_indentation(extracted_body, 0) - if returns: - unindented_body += '\nreturn %s' % self._get_comma_form(returns) - return unindented_body - - -class _ExtractVariableParts(object): - - def __init__(self, info): - self.info = info - - def get_definition(self): - result = self.info.new_name + ' = ' + \ - _join_lines(self.info.extracted) + '\n' - return result - - def get_body_pattern(self): - return '(%s)' % self.info.extracted.strip() - - def get_replacement_pattern(self): - return self.info.new_name - - def get_checks(self): - return {} - - -class _FunctionInformationCollector(object): - - def __init__(self, start, end, is_global): - self.start = start - self.end = end - self.is_global = is_global - self.prewritten = set() - self.maybe_written = set() - self.written = set() - self.read = set() - self.postread = set() - self.postwritten = set() - self.host_function = True - self.conditional = False - - def _read_variable(self, name, lineno): - if self.start <= lineno <= self.end: - if name not in self.written: - self.read.add(name) - if self.end < lineno: - if name not in self.postwritten: - self.postread.add(name) - - def _written_variable(self, name, lineno): - if self.start <= lineno <= self.end: - if self.conditional: - self.maybe_written.add(name) - else: - self.written.add(name) - if self.start > lineno: - self.prewritten.add(name) - if self.end < lineno: - self.postwritten.add(name) - - def _FunctionDef(self, node): - if not self.is_global and self.host_function: - self.host_function = False - for name in _get_argnames(node.args): - self._written_variable(name, node.lineno) - for child in node.body: - ast.walk(child, self) - else: - self._written_variable(node.name, node.lineno) - visitor = _VariableReadsAndWritesFinder() - for child in node.body: - ast.walk(child, visitor) - for name in visitor.read - visitor.written: - self._read_variable(name, node.lineno) - - def _Name(self, node): - if isinstance(node.ctx, (ast.Store, ast.AugStore)): - self._written_variable(node.id, node.lineno) - if not isinstance(node.ctx, ast.Store): - self._read_variable(node.id, node.lineno) - - def _Assign(self, node): - ast.walk(node.value, self) - for child in node.targets: - ast.walk(child, self) - - def _ClassDef(self, node): - self._written_variable(node.name, node.lineno) - - def _handle_conditional_node(self, node): - self.conditional = True - try: - for child in ast.get_child_nodes(node): - ast.walk(child, self) - finally: - self.conditional = False - - def _If(self, node): - self._handle_conditional_node(node) - - def _While(self, node): - self._handle_conditional_node(node) - - def _For(self, node): - self._handle_conditional_node(node) - - - -def _get_argnames(arguments): - result = [node.id for node in arguments.args - if isinstance(node, ast.Name)] - if arguments.vararg: - result.append(arguments.vararg) - if arguments.kwarg: - result.append(arguments.kwarg) - return result - - -class _VariableReadsAndWritesFinder(object): - - def __init__(self): - self.written = set() - self.read = set() - - def _Name(self, node): - if isinstance(node.ctx, (ast.Store, ast.AugStore)): - self.written.add(node.id) - if not isinstance(node, ast.Store): - self.read.add(node.id) - - def _FunctionDef(self, node): - self.written.add(node.name) - visitor = _VariableReadsAndWritesFinder() - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - self.read.update(visitor.read - visitor.written) - - def _Class(self, node): - self.written.add(node.name) - - @staticmethod - def find_reads_and_writes(code): - if code.strip() == '': - return set(), set() - if isinstance(code, unicode): - code = code.encode('utf-8') - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() - ast.walk(node, visitor) - return visitor.read, visitor.written - - @staticmethod - def find_reads_for_one_liners(code): - if code.strip() == '': - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() - ast.walk(node, visitor) - return visitor.read - - -class _UnmatchedBreakOrContinueFinder(object): - - def __init__(self): - self.error = False - self.loop_count = 0 - - def _For(self, node): - self.loop_encountered(node) - - def _While(self, node): - self.loop_encountered(node) - - def loop_encountered(self, node): - self.loop_count += 1 - for child in node.body: - ast.walk(child, self) - self.loop_count -= 1 - if node.orelse: - ast.walk(node.orelse, self) - - def _Break(self, node): - self.check_loop() - - def _Continue(self, node): - self.check_loop() - - def check_loop(self): - if self.loop_count < 1: - self.error = True - - def _FunctionDef(self, node): - pass - - def _ClassDef(self, node): - pass - - @staticmethod - def has_errors(code): - if code.strip() == '': - return False - node = _parse_text(code) - visitor = _UnmatchedBreakOrContinueFinder() - ast.walk(node, visitor) - return visitor.error - -def _get_function_kind(scope): - return scope.pyobject.get_kind() - - -def _parse_text(body): - body = sourceutils.fix_indentation(body, 0) - node = ast.parse(body) - return node - -def _join_lines(code): - lines = [] - for line in code.splitlines(): - if line.endswith('\\'): - lines.append(line[:-1].strip()) - else: - lines.append(line.strip()) - return ' '.join(lines) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/functionutils.py b/.vim/bundle/python-mode/pylibs/rope/refactor/functionutils.py @@ -1,222 +0,0 @@ -import rope.base.exceptions -import rope.base.pyobjects -from rope.base.builtins import Lambda -from rope.base import worder - - -class DefinitionInfo(object): - - def __init__(self, function_name, is_method, args_with_defaults, - args_arg, keywords_arg): - self.function_name = function_name - self.is_method = is_method - self.args_with_defaults = args_with_defaults - self.args_arg = args_arg - self.keywords_arg = keywords_arg - - def to_string(self): - return '%s(%s)' % (self.function_name, self.arguments_to_string()) - - def arguments_to_string(self, from_index=0): - params = [] - for arg, default in self.args_with_defaults: - if default is not None: - params.append('%s=%s' % (arg, default)) - else: - params.append(arg) - if self.args_arg is not None: - params.append('*' + self.args_arg) - if self.keywords_arg: - params.append('**' + self.keywords_arg) - return ', '.join(params[from_index:]) - - @staticmethod - def _read(pyfunction, code): - scope = pyfunction.get_scope() - parent = scope.parent - parameter_names = pyfunction.get_param_names() - kind = pyfunction.get_kind() - is_method = kind == 'method' - is_lambda = kind == 'lambda' - info = _FunctionParser(code, is_method, is_lambda) - args, keywords = info.get_parameters() - args_arg = None - keywords_arg = None - if args and args[-1].startswith('**'): - keywords_arg = args[-1][2:] - del args[-1] - if args and args[-1].startswith('*'): - args_arg = args[-1][1:] - del args[-1] - args_with_defaults = [(name, None) for name in args] - args_with_defaults.extend(keywords) - return DefinitionInfo(info.get_function_name(), is_method, - args_with_defaults, args_arg, keywords_arg) - - @staticmethod - def read(pyfunction): - pymodule = pyfunction.get_module() - word_finder = worder.Worder(pymodule.source_code) - lineno = pyfunction.get_ast().lineno - start = pymodule.lines.get_line_start(lineno) - if isinstance(pyfunction, Lambda): - call = word_finder.get_lambda_and_args(start) - else: - call = word_finder.get_function_and_args_in_header(start) - return DefinitionInfo._read(pyfunction, call) - - -class CallInfo(object): - - def __init__(self, function_name, args, keywords, args_arg, - keywords_arg, implicit_arg, constructor): - self.function_name = function_name - self.args = args - self.keywords = keywords - self.args_arg = args_arg - self.keywords_arg = keywords_arg - self.implicit_arg = implicit_arg - self.constructor = constructor - - def to_string(self): - function = self.function_name - if self.implicit_arg: - function = self.args[0] + '.' + self.function_name - params = [] - start = 0 - if self.implicit_arg or self.constructor: - start = 1 - if self.args[start:]: - params.extend(self.args[start:]) - if self.keywords: - params.extend(['%s=%s' % (name, value) for name, value in self.keywords]) - if self.args_arg is not None: - params.append('*' + self.args_arg) - if self.keywords_arg: - params.append('**' + self.keywords_arg) - return '%s(%s)' % (function, ', '.join(params)) - - @staticmethod - def read(primary, pyname, definition_info, code): - is_method_call = CallInfo._is_method_call(primary, pyname) - is_constructor = CallInfo._is_class(pyname) - is_classmethod = CallInfo._is_classmethod(pyname) - info = _FunctionParser(code, is_method_call or is_classmethod) - args, keywords = info.get_parameters() - args_arg = None - keywords_arg = None - if args and args[-1].startswith('**'): - keywords_arg = args[-1][2:] - del args[-1] - if args and args[-1].startswith('*'): - args_arg = args[-1][1:] - del args[-1] - if is_constructor: - args.insert(0, definition_info.args_with_defaults[0][0]) - return CallInfo(info.get_function_name(), args, keywords, args_arg, - keywords_arg, is_method_call or is_classmethod, - is_constructor) - - @staticmethod - def _is_method_call(primary, pyname): - return primary is not None and \ - isinstance(primary.get_object().get_type(), - rope.base.pyobjects.PyClass) and \ - CallInfo._is_method(pyname) - - @staticmethod - def _is_class(pyname): - return pyname is not None and \ - isinstance(pyname.get_object(), - rope.base.pyobjects.PyClass) - - @staticmethod - def _is_method(pyname): - if pyname is not None and \ - isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction): - return pyname.get_object().get_kind() == 'method' - return False - - @staticmethod - def _is_classmethod(pyname): - if pyname is not None and \ - isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction): - return pyname.get_object().get_kind() == 'classmethod' - return False - - -class ArgumentMapping(object): - - def __init__(self, definition_info, call_info): - self.call_info = call_info - self.param_dict = {} - self.keyword_args = [] - self.args_arg = [] - for index, value in enumerate(call_info.args): - if index < len(definition_info.args_with_defaults): - name = definition_info.args_with_defaults[index][0] - self.param_dict[name] = value - else: - self.args_arg.append(value) - for name, value in call_info.keywords: - index = -1 - for pair in definition_info.args_with_defaults: - if pair[0] == name: - self.param_dict[name] = value - break - else: - self.keyword_args.append((name, value)) - - def to_call_info(self, definition_info): - args = [] - keywords = [] - for index in range(len(definition_info.args_with_defaults)): - name = definition_info.args_with_defaults[index][0] - if name in self.param_dict: - args.append(self.param_dict[name]) - else: - for i in range(index, len(definition_info.args_with_defaults)): - name = definition_info.args_with_defaults[i][0] - if name in self.param_dict: - keywords.append((name, self.param_dict[name])) - break - args.extend(self.args_arg) - keywords.extend(self.keyword_args) - return CallInfo(self.call_info.function_name, args, keywords, - self.call_info.args_arg, self.call_info.keywords_arg, - self.call_info.implicit_arg, self.call_info.constructor) - - -class _FunctionParser(object): - - def __init__(self, call, implicit_arg, is_lambda=False): - self.call = call - self.implicit_arg = implicit_arg - self.word_finder = worder.Worder(self.call) - if is_lambda: - self.last_parens = self.call.rindex(':') - else: - self.last_parens = self.call.rindex(')') - self.first_parens = self.word_finder._find_parens_start(self.last_parens) - - def get_parameters(self): - args, keywords = self.word_finder.get_parameters(self.first_parens, - self.last_parens) - if self.is_called_as_a_method(): - instance = self.call[:self.call.rindex('.', 0, self.first_parens)] - args.insert(0, instance.strip()) - return args, keywords - - def get_instance(self): - if self.is_called_as_a_method(): - return self.word_finder.get_primary_at( - self.call.rindex('.', 0, self.first_parens) - 1) - - def get_function_name(self): - if self.is_called_as_a_method(): - return self.word_finder.get_word_at(self.first_parens - 1) - else: - return self.word_finder.get_primary_at(self.first_parens - 1) - - def is_called_as_a_method(self): - return self.implicit_arg and '.' in self.call[:self.first_parens] diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/__init__.py b/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/__init__.py @@ -1,299 +0,0 @@ -"""A package for handling imports - -This package provides tools for modifying module imports after -refactorings or as a separate task. - -""" -import rope.base.evaluate -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import occurrences, rename -from rope.refactor.importutils import module_imports, actions -from rope.refactor.importutils.importinfo import NormalImport, FromImport -import rope.base.codeanalyze - - -class ImportOrganizer(object): - """Perform some import-related commands - - Each method returns a `rope.base.change.Change` object. - - """ - - def __init__(self, project): - self.project = project - self.pycore = project.pycore - self.import_tools = ImportTools(self.pycore) - - def organize_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.organize_imports, resource, offset) - - def expand_star_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.expand_stars, resource, offset) - - def froms_to_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.froms_to_imports, resource, offset) - - def relatives_to_absolutes(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.relatives_to_absolutes, resource, offset) - - def handle_long_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.handle_long_imports, resource, offset) - - def _perform_command_on_import_tools(self, method, resource, offset): - pymodule = self.pycore.resource_to_pyobject(resource) - before_performing = pymodule.source_code - import_filter = None - if offset is not None: - import_filter = self._line_filter( - pymodule.lines.get_line_number(offset)) - result = method(pymodule, import_filter=import_filter) - if result is not None and result != before_performing: - changes = ChangeSet(method.__name__.replace('_', ' ') + - ' in <%s>' % resource.path) - changes.add_change(ChangeContents(resource, result)) - return changes - - def _line_filter(self, lineno): - def import_filter(import_stmt): - return import_stmt.start_line <= lineno < import_stmt.end_line - return import_filter - - -class ImportTools(object): - - def __init__(self, pycore): - self.pycore = pycore - - def get_import(self, resource): - """The import statement for `resource`""" - module_name = self.pycore.modname(resource) - return NormalImport(((module_name, None), )) - - def get_from_import(self, resource, name): - """The from import statement for `name` in `resource`""" - module_name = self.pycore.modname(resource) - names = [] - if isinstance(name, list): - names = [(imported, None) for imported in name] - else: - names = [(name, None),] - return FromImport(module_name, 0, tuple(names)) - - def module_imports(self, module, imports_filter=None): - return module_imports.ModuleImports(self.pycore, module, - imports_filter) - - def froms_to_imports(self, pymodule, import_filter=None): - pymodule = self._clean_up_imports(pymodule, import_filter) - module_imports = self.module_imports(pymodule, import_filter) - for import_stmt in module_imports.imports: - if import_stmt.readonly or \ - not self._is_transformable_to_normal(import_stmt.import_info): - continue - pymodule = self._from_to_normal(pymodule, import_stmt) - - # Adding normal imports in place of froms - module_imports = self.module_imports(pymodule, import_filter) - for import_stmt in module_imports.imports: - if not import_stmt.readonly and \ - self._is_transformable_to_normal(import_stmt.import_info): - import_stmt.import_info = \ - NormalImport(((import_stmt.import_info.module_name, None),)) - module_imports.remove_duplicates() - return module_imports.get_changed_source() - - def expand_stars(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - module_imports.expand_stars() - return module_imports.get_changed_source() - - def _from_to_normal(self, pymodule, import_stmt): - resource = pymodule.get_resource() - from_import = import_stmt.import_info - module_name = from_import.module_name - for name, alias in from_import.names_and_aliases: - imported = name - if alias is not None: - imported = alias - occurrence_finder = occurrences.create_finder( - self.pycore, imported, pymodule[imported], imports=False) - source = rename.rename_in_module( - occurrence_finder, module_name + '.' + name, - pymodule=pymodule, replace_primary=True) - if source is not None: - pymodule = self.pycore.get_string_module(source, resource) - return pymodule - - def _clean_up_imports(self, pymodule, import_filter): - resource = pymodule.get_resource() - module_with_imports = self.module_imports(pymodule, import_filter) - module_with_imports.expand_stars() - source = module_with_imports.get_changed_source() - if source is not None: - pymodule = self.pycore.get_string_module(source, resource) - source = self.relatives_to_absolutes(pymodule) - if source is not None: - pymodule = self.pycore.get_string_module(source, resource) - - module_with_imports = self.module_imports(pymodule, import_filter) - module_with_imports.remove_duplicates() - module_with_imports.remove_unused_imports() - source = module_with_imports.get_changed_source() - if source is not None: - pymodule = self.pycore.get_string_module(source, resource) - return pymodule - - def relatives_to_absolutes(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - to_be_absolute_list = module_imports.get_relative_to_absolute_list() - for name, absolute_name in to_be_absolute_list: - pymodule = self._rename_in_module(pymodule, name, absolute_name) - module_imports = self.module_imports(pymodule, import_filter) - module_imports.get_relative_to_absolute_list() - source = module_imports.get_changed_source() - if source is None: - source = pymodule.source_code - return source - - def _is_transformable_to_normal(self, import_info): - if not isinstance(import_info, FromImport): - return False - return True - - def organize_imports(self, pymodule, - unused=True, duplicates=True, - selfs=True, sort=True, import_filter=None): - if unused or duplicates: - module_imports = self.module_imports(pymodule, import_filter) - if unused: - module_imports.remove_unused_imports() - if duplicates: - module_imports.remove_duplicates() - source = module_imports.get_changed_source() - if source is not None: - pymodule = self.pycore.get_string_module( - source, pymodule.get_resource()) - if selfs: - pymodule = self._remove_self_imports(pymodule, import_filter) - if sort: - return self.sort_imports(pymodule, import_filter) - else: - return pymodule.source_code - - def _remove_self_imports(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - to_be_fixed, to_be_renamed = module_imports.get_self_import_fix_and_rename_list() - for name in to_be_fixed: - try: - pymodule = self._rename_in_module(pymodule, name, '', till_dot=True) - except ValueError: - # There is a self import with direct access to it - return pymodule - for name, new_name in to_be_renamed: - pymodule = self._rename_in_module(pymodule, name, new_name) - module_imports = self.module_imports(pymodule, import_filter) - module_imports.get_self_import_fix_and_rename_list() - source = module_imports.get_changed_source() - if source is not None: - pymodule = self.pycore.get_string_module(source, pymodule.get_resource()) - return pymodule - - def _rename_in_module(self, pymodule, name, new_name, till_dot=False): - old_name = name.split('.')[-1] - old_pyname = rope.base.evaluate.eval_str(pymodule.get_scope(), name) - occurrence_finder = occurrences.create_finder( - self.pycore, old_name, old_pyname, imports=False) - changes = rope.base.codeanalyze.ChangeCollector(pymodule.source_code) - for occurrence in occurrence_finder.find_occurrences(pymodule=pymodule): - start, end = occurrence.get_primary_range() - if till_dot: - new_end = pymodule.source_code.index('.', end) + 1 - space = pymodule.source_code[end:new_end - 1].strip() - if not space == '': - for c in space: - if not c.isspace() and c not in '\\': - raise ValueError() - end = new_end - changes.add_change(start, end, new_name) - source = changes.get_changed() - if source is not None: - pymodule = self.pycore.get_string_module(source, pymodule.get_resource()) - return pymodule - - def sort_imports(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - module_imports.sort_imports() - return module_imports.get_changed_source() - - def handle_long_imports(self, pymodule, maxdots=2, maxlength=27, - import_filter=None): - # IDEA: `maxdots` and `maxlength` can be specified in project config - # adding new from imports - module_imports = self.module_imports(pymodule, import_filter) - to_be_fixed = module_imports.handle_long_imports(maxdots, maxlength) - # performing the renaming - pymodule = self.pycore.get_string_module( - module_imports.get_changed_source(), - resource=pymodule.get_resource()) - for name in to_be_fixed: - pymodule = self._rename_in_module(pymodule, name, - name.split('.')[-1]) - # organizing imports - return self.organize_imports(pymodule, selfs=False, sort=False, - import_filter=import_filter) - - -def get_imports(pycore, pydefined): - """A shortcut for getting the `ImportInfo`\s used in a scope""" - pymodule = pydefined.get_module() - module = module_imports.ModuleImports(pycore, pymodule) - if pymodule == pydefined: - return [stmt.import_info for stmt in module.imports] - return module.get_used_imports(pydefined) - - -def get_module_imports(pycore, pymodule): - """A shortcut for creating a `module_imports.ModuleImports` object""" - return module_imports.ModuleImports(pycore, pymodule) - - -def add_import(pycore, pymodule, module_name, name=None): - imports = get_module_imports(pycore, pymodule) - candidates = [] - names = [] - # from mod import name - if name is not None: - from_import = FromImport(module_name, 0, [(name, None)]) - names.append(name) - candidates.append(from_import) - # from pkg import mod - if '.' in module_name: - pkg, mod = module_name.rsplit('.', 1) - candidates.append(FromImport(pkg, 0, [(mod, None)])) - if name: - names.append(mod + '.' + name) - else: - names.append(mod) - # import mod - normal_import = NormalImport([(module_name, None)]) - if name: - names.append(module_name + '.' + name) - else: - names.append(module_name) - - candidates.append(normal_import) - - visitor = actions.AddingVisitor(pycore, candidates) - selected_import = normal_import - for import_statement in imports.imports: - if import_statement.accept(visitor): - selected_import = visitor.import_info - break - imports.add_import(selected_import) - imported_name = names[candidates.index(selected_import)] - return imports.get_changed_source(), imported_name diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/actions.py b/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/actions.py @@ -1,359 +0,0 @@ -import os -import sys - -from rope.base import pyobjects, exceptions, stdmods -from rope.refactor import occurrences -from rope.refactor.importutils import importinfo - - -class ImportInfoVisitor(object): - - def dispatch(self, import_): - try: - method_name = 'visit' + import_.import_info.__class__.__name__ - method = getattr(self, method_name) - return method(import_, import_.import_info) - except exceptions.ModuleNotFoundError: - pass - - def visitEmptyImport(self, import_stmt, import_info): - pass - - def visitNormalImport(self, import_stmt, import_info): - pass - - def visitFromImport(self, import_stmt, import_info): - pass - - -class RelativeToAbsoluteVisitor(ImportInfoVisitor): - - def __init__(self, pycore, current_folder): - self.to_be_absolute = [] - self.pycore = pycore - self.folder = current_folder - self.context = importinfo.ImportContext(pycore, current_folder) - - def visitNormalImport(self, import_stmt, import_info): - self.to_be_absolute.extend(self._get_relative_to_absolute_list(import_info)) - new_pairs = [] - for name, alias in import_info.names_and_aliases: - resource = self.pycore.find_module(name, folder=self.folder) - if resource is None: - new_pairs.append((name, alias)) - continue - absolute_name = self.pycore.modname(resource) - new_pairs.append((absolute_name, alias)) - if not import_info._are_name_and_alias_lists_equal( - new_pairs, import_info.names_and_aliases): - import_stmt.import_info = importinfo.NormalImport(new_pairs) - - def _get_relative_to_absolute_list(self, import_info): - result = [] - for name, alias in import_info.names_and_aliases: - if alias is not None: - continue - resource = self.pycore.find_module(name, folder=self.folder) - if resource is None: - continue - absolute_name = self.pycore.modname(resource) - if absolute_name != name: - result.append((name, absolute_name)) - return result - - def visitFromImport(self, import_stmt, import_info): - resource = import_info.get_imported_resource(self.context) - if resource is None: - return None - absolute_name = self.pycore.modname(resource) - if import_info.module_name != absolute_name: - import_stmt.import_info = importinfo.FromImport( - absolute_name, 0, import_info.names_and_aliases) - - -class FilteringVisitor(ImportInfoVisitor): - - def __init__(self, pycore, folder, can_select): - self.to_be_absolute = [] - self.pycore = pycore - self.can_select = self._transform_can_select(can_select) - self.context = importinfo.ImportContext(pycore, folder) - - def _transform_can_select(self, can_select): - def can_select_name_and_alias(name, alias): - imported = name - if alias is not None: - imported = alias - return can_select(imported) - return can_select_name_and_alias - - def visitNormalImport(self, import_stmt, import_info): - new_pairs = [] - for name, alias in import_info.names_and_aliases: - if self.can_select(name, alias): - new_pairs.append((name, alias)) - return importinfo.NormalImport(new_pairs) - - def visitFromImport(self, import_stmt, import_info): - if _is_future(import_info): - return import_info - new_pairs = [] - if import_info.is_star_import(): - for name in import_info.get_imported_names(self.context): - if self.can_select(name, None): - new_pairs.append(import_info.names_and_aliases[0]) - break - else: - for name, alias in import_info.names_and_aliases: - if self.can_select(name, alias): - new_pairs.append((name, alias)) - return importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs) - - -class RemovingVisitor(ImportInfoVisitor): - - def __init__(self, pycore, folder, can_select): - self.to_be_absolute = [] - self.pycore = pycore - self.filtering = FilteringVisitor(pycore, folder, can_select) - - def dispatch(self, import_): - result = self.filtering.dispatch(import_) - if result is not None: - import_.import_info = result - - -class AddingVisitor(ImportInfoVisitor): - """A class for adding imports - - Given a list of `ImportInfo`\s, it tries to add each import to the - module and returns `True` and gives up when an import can be added - to older ones. - - """ - - def __init__(self, pycore, import_list): - self.pycore = pycore - self.import_list = import_list - self.import_info = None - - def dispatch(self, import_): - for import_info in self.import_list: - self.import_info = import_info - if ImportInfoVisitor.dispatch(self, import_): - return True - - # TODO: Handle adding relative and absolute imports - def visitNormalImport(self, import_stmt, import_info): - if not isinstance(self.import_info, import_info.__class__): - return False - # Adding ``import x`` and ``import x.y`` that results ``import x.y`` - if len(import_info.names_and_aliases) == \ - len(self.import_info.names_and_aliases) == 1: - imported1 = import_info.names_and_aliases[0] - imported2 = self.import_info.names_and_aliases[0] - if imported1[1] == imported2[1] is None: - if imported1[0].startswith(imported2[0] + '.'): - return True - if imported2[0].startswith(imported1[0] + '.'): - import_stmt.import_info = self.import_info - return True - # Multiple imports using a single import statement is discouraged - # so we won't bother adding them. - if self.import_info._are_name_and_alias_lists_equal( - import_info.names_and_aliases, self.import_info.names_and_aliases): - return True - - def visitFromImport(self, import_stmt, import_info): - if isinstance(self.import_info, import_info.__class__) and \ - import_info.module_name == self.import_info.module_name and \ - import_info.level == self.import_info.level: - if import_info.is_star_import(): - return True - if self.import_info.is_star_import(): - import_stmt.import_info = self.import_info - return True - new_pairs = list(import_info.names_and_aliases) - for pair in self.import_info.names_and_aliases: - if pair not in new_pairs: - new_pairs.append(pair) - import_stmt.import_info = importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs) - return True - - -class ExpandStarsVisitor(ImportInfoVisitor): - - def __init__(self, pycore, folder, can_select): - self.pycore = pycore - self.filtering = FilteringVisitor(pycore, folder, can_select) - self.context = importinfo.ImportContext(pycore, folder) - - def visitNormalImport(self, import_stmt, import_info): - self.filtering.dispatch(import_stmt) - - def visitFromImport(self, import_stmt, import_info): - if import_info.is_star_import(): - new_pairs = [] - for name in import_info.get_imported_names(self.context): - new_pairs.append((name, None)) - new_import = importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs) - import_stmt.import_info = \ - self.filtering.visitFromImport(None, new_import) - else: - self.filtering.dispatch(import_stmt) - - -class SelfImportVisitor(ImportInfoVisitor): - - def __init__(self, pycore, current_folder, resource): - self.pycore = pycore - self.folder = current_folder - self.resource = resource - self.to_be_fixed = set() - self.to_be_renamed = set() - self.context = importinfo.ImportContext(pycore, current_folder) - - def visitNormalImport(self, import_stmt, import_info): - new_pairs = [] - for name, alias in import_info.names_and_aliases: - resource = self.pycore.find_module(name, folder=self.folder) - if resource is not None and resource == self.resource: - imported = name - if alias is not None: - imported = alias - self.to_be_fixed.add(imported) - else: - new_pairs.append((name, alias)) - if not import_info._are_name_and_alias_lists_equal( - new_pairs, import_info.names_and_aliases): - import_stmt.import_info = importinfo.NormalImport(new_pairs) - - def visitFromImport(self, import_stmt, import_info): - resource = import_info.get_imported_resource(self.context) - if resource is None: - return - if resource == self.resource: - self._importing_names_from_self(import_info, import_stmt) - return - pymodule = self.pycore.resource_to_pyobject(resource) - new_pairs = [] - for name, alias in import_info.names_and_aliases: - try: - result = pymodule[name].get_object() - if isinstance(result, pyobjects.PyModule) and \ - result.get_resource() == self.resource: - imported = name - if alias is not None: - imported = alias - self.to_be_fixed.add(imported) - else: - new_pairs.append((name, alias)) - except exceptions.AttributeNotFoundError: - new_pairs.append((name, alias)) - if not import_info._are_name_and_alias_lists_equal( - new_pairs, import_info.names_and_aliases): - import_stmt.import_info = importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs) - - def _importing_names_from_self(self, import_info, import_stmt): - if not import_info.is_star_import(): - for name, alias in import_info.names_and_aliases: - if alias is not None: - self.to_be_renamed.add((alias, name)) - import_stmt.empty_import() - - -class SortingVisitor(ImportInfoVisitor): - - def __init__(self, pycore, current_folder): - self.pycore = pycore - self.folder = current_folder - self.standard = set() - self.third_party = set() - self.in_project = set() - self.future = set() - self.context = importinfo.ImportContext(pycore, current_folder) - - def visitNormalImport(self, import_stmt, import_info): - if import_info.names_and_aliases: - name, alias = import_info.names_and_aliases[0] - resource = self.pycore.find_module( - name, folder=self.folder) - self._check_imported_resource(import_stmt, resource, name) - - def visitFromImport(self, import_stmt, import_info): - resource = import_info.get_imported_resource(self.context) - self._check_imported_resource(import_stmt, resource, - import_info.module_name) - - def _check_imported_resource(self, import_stmt, resource, imported_name): - info = import_stmt.import_info - if resource is not None and resource.project == self.pycore.project: - self.in_project.add(import_stmt) - elif _is_future(info): - self.future.add(import_stmt) - elif imported_name.split('.')[0] in stdmods.standard_modules(): - self.standard.add(import_stmt) - else: - self.third_party.add(import_stmt) - - -class LongImportVisitor(ImportInfoVisitor): - - def __init__(self, current_folder, pycore, maxdots, maxlength): - self.maxdots = maxdots - self.maxlength = maxlength - self.to_be_renamed = set() - self.current_folder = current_folder - self.pycore = pycore - self.new_imports = [] - - def visitNormalImport(self, import_stmt, import_info): - new_pairs = [] - for name, alias in import_info.names_and_aliases: - if alias is None and self._is_long(name): - self.to_be_renamed.add(name) - last_dot = name.rindex('.') - from_ = name[:last_dot] - imported = name[last_dot + 1:] - self.new_imports.append( - importinfo.FromImport(from_, 0, ((imported, None), ))) - - def _is_long(self, name): - return name.count('.') > self.maxdots or \ - ('.' in name and len(name) > self.maxlength) - - -class RemovePyNameVisitor(ImportInfoVisitor): - - def __init__(self, pycore, pymodule, pyname, folder): - self.pymodule = pymodule - self.pyname = pyname - self.context = importinfo.ImportContext(pycore, folder) - - def visitFromImport(self, import_stmt, import_info): - new_pairs = [] - if not import_info.is_star_import(): - for name, alias in import_info.names_and_aliases: - try: - pyname = self.pymodule[alias or name] - if occurrences.same_pyname(self.pyname, pyname): - continue - except exceptions.AttributeNotFoundError: - pass - new_pairs.append((name, alias)) - return importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs) - - def dispatch(self, import_): - result = ImportInfoVisitor.dispatch(self, import_) - if result is not None: - import_.import_info = result - - -def _is_future(info): - return isinstance(info, importinfo.FromImport) and \ - info.module_name == '__future__' diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/importinfo.py b/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/importinfo.py @@ -1,201 +0,0 @@ -class ImportStatement(object): - """Represent an import in a module - - `readonly` attribute controls whether this import can be changed - by import actions or not. - - """ - - def __init__(self, import_info, start_line, end_line, - main_statement=None, blank_lines=0): - self.start_line = start_line - self.end_line = end_line - self.readonly = False - self.main_statement = main_statement - self._import_info = None - self.import_info = import_info - self._is_changed = False - self.new_start = None - self.blank_lines = blank_lines - - def _get_import_info(self): - return self._import_info - - def _set_import_info(self, new_import): - if not self.readonly and \ - new_import is not None and not new_import == self._import_info: - self._is_changed = True - self._import_info = new_import - - import_info = property(_get_import_info, _set_import_info) - - def get_import_statement(self): - if self._is_changed or self.main_statement is None: - return self.import_info.get_import_statement() - else: - return self.main_statement - - def empty_import(self): - self.import_info = ImportInfo.get_empty_import() - - def move(self, lineno, blank_lines=0): - self.new_start = lineno - self.blank_lines = blank_lines - - def get_old_location(self): - return self.start_line, self.end_line - - def get_new_start(self): - return self.new_start - - def is_changed(self): - return self._is_changed or (self.new_start is not None or - self.new_start != self.start_line) - - def accept(self, visitor): - return visitor.dispatch(self) - - -class ImportInfo(object): - - def get_imported_primaries(self, context): - pass - - def get_imported_names(self, context): - return [primary.split('.')[0] - for primary in self.get_imported_primaries(context)] - - def get_import_statement(self): - pass - - def is_empty(self): - pass - - def __hash__(self): - return hash(self.get_import_statement()) - - def _are_name_and_alias_lists_equal(self, list1, list2): - if len(list1) != len(list2): - return False - for pair1, pair2 in zip(list1, list2): - if pair1 != pair2: - return False - return True - - def __eq__(self, obj): - return isinstance(obj, self.__class__) and \ - self.get_import_statement() == obj.get_import_statement() - - def __ne__(self, obj): - return not self.__eq__(obj) - - @staticmethod - def get_empty_import(): - return EmptyImport() - - -class NormalImport(ImportInfo): - - def __init__(self, names_and_aliases): - self.names_and_aliases = names_and_aliases - - def get_imported_primaries(self, context): - result = [] - for name, alias in self.names_and_aliases: - if alias: - result.append(alias) - else: - result.append(name) - return result - - def get_import_statement(self): - result = 'import ' - for name, alias in self.names_and_aliases: - result += name - if alias: - result += ' as ' + alias - result += ', ' - return result[:-2] - - def is_empty(self): - return len(self.names_and_aliases) == 0 - - -class FromImport(ImportInfo): - - def __init__(self, module_name, level, names_and_aliases): - self.module_name = module_name - self.level = level - self.names_and_aliases = names_and_aliases - - def get_imported_primaries(self, context): - if self.names_and_aliases[0][0] == '*': - module = self.get_imported_module(context) - return [name for name in module - if not name.startswith('_')] - result = [] - for name, alias in self.names_and_aliases: - if alias: - result.append(alias) - else: - result.append(name) - return result - - def get_imported_resource(self, context): - """Get the imported resource - - Returns `None` if module was not found. - """ - if self.level == 0: - return context.pycore.find_module( - self.module_name, folder=context.folder) - else: - return context.pycore.find_relative_module( - self.module_name, context.folder, self.level) - - def get_imported_module(self, context): - """Get the imported `PyModule` - - Raises `rope.base.exceptions.ModuleNotFoundError` if module - could not be found. - """ - if self.level == 0: - return context.pycore.get_module( - self.module_name, context.folder) - else: - return context.pycore.get_relative_module( - self.module_name, context.folder, self.level) - - def get_import_statement(self): - result = 'from ' + '.' * self.level + self.module_name + ' import ' - for name, alias in self.names_and_aliases: - result += name - if alias: - result += ' as ' + alias - result += ', ' - return result[:-2] - - def is_empty(self): - return len(self.names_and_aliases) == 0 - - def is_star_import(self): - return len(self.names_and_aliases) > 0 and \ - self.names_and_aliases[0][0] == '*' - - -class EmptyImport(ImportInfo): - - names_and_aliases = [] - - def is_empty(self): - return True - - def get_imported_primaries(self, context): - return [] - - -class ImportContext(object): - - def __init__(self, pycore, folder): - self.pycore = pycore - self.folder = folder diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/module_imports.py b/.vim/bundle/python-mode/pylibs/rope/refactor/importutils/module_imports.py @@ -1,455 +0,0 @@ -import rope.base.pynames -from rope.base import ast, utils -from rope.refactor.importutils import importinfo -from rope.refactor.importutils import actions - - -class ModuleImports(object): - - def __init__(self, pycore, pymodule, import_filter=None): - self.pycore = pycore - self.pymodule = pymodule - self.separating_lines = 0 - self.filter = import_filter - - @property - @utils.saveit - def imports(self): - finder = _GlobalImportFinder(self.pymodule, self.pycore) - result = finder.find_import_statements() - self.separating_lines = finder.get_separating_line_count() - if self.filter is not None: - for import_stmt in result: - if not self.filter(import_stmt): - import_stmt.readonly = True - return result - - def _get_unbound_names(self, defined_pyobject): - visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) - ast.walk(self.pymodule.get_ast(), visitor) - return visitor.unbound - - def remove_unused_imports(self): - can_select = _OneTimeSelector(self._get_unbound_names(self.pymodule)) - visitor = actions.RemovingVisitor( - self.pycore, self._current_folder(), can_select) - for import_statement in self.imports: - import_statement.accept(visitor) - - def get_used_imports(self, defined_pyobject): - result = [] - can_select = _OneTimeSelector(self._get_unbound_names(defined_pyobject)) - visitor = actions.FilteringVisitor( - self.pycore, self._current_folder(), can_select) - for import_statement in self.imports: - new_import = import_statement.accept(visitor) - if new_import is not None and not new_import.is_empty(): - result.append(new_import) - return result - - def get_changed_source(self): - imports = self.imports - after_removing = self._remove_imports(imports) - imports = [stmt for stmt in imports - if not stmt.import_info.is_empty()] - - first_non_blank = self._first_non_blank_line(after_removing, 0) - first_import = self._first_import_line() - 1 - result = [] - # Writing module docs - result.extend(after_removing[first_non_blank:first_import]) - # Writing imports - sorted_imports = sorted(imports, self._compare_import_locations) - for stmt in sorted_imports: - start = self._get_import_location(stmt) - if stmt != sorted_imports[0]: - result.append('\n' * stmt.blank_lines) - result.append(stmt.get_import_statement() + '\n') - if sorted_imports and first_non_blank < len(after_removing): - result.append('\n' * self.separating_lines) - - # Writing the body - first_after_imports = self._first_non_blank_line(after_removing, - first_import) - result.extend(after_removing[first_after_imports:]) - return ''.join(result) - - def _get_import_location(self, stmt): - start = stmt.get_new_start() - if start is None: - start = stmt.get_old_location()[0] - return start - - def _compare_import_locations(self, stmt1, stmt2): - def get_location(stmt): - if stmt.get_new_start() is not None: - return stmt.get_new_start() - else: - return stmt.get_old_location()[0] - return cmp(get_location(stmt1), get_location(stmt2)) - - def _remove_imports(self, imports): - lines = self.pymodule.source_code.splitlines(True) - after_removing = [] - last_index = 0 - for stmt in imports: - start, end = stmt.get_old_location() - after_removing.extend(lines[last_index:start - 1]) - last_index = end - 1 - for i in range(start, end): - after_removing.append('') - after_removing.extend(lines[last_index:]) - return after_removing - - def _first_non_blank_line(self, lines, lineno): - result = lineno - for line in lines[lineno:]: - if line.strip() == '': - result += 1 - else: - break - return result - - def add_import(self, import_info): - visitor = actions.AddingVisitor(self.pycore, [import_info]) - for import_statement in self.imports: - if import_statement.accept(visitor): - break - else: - lineno = self._get_new_import_lineno() - blanks = self._get_new_import_blanks() - self.imports.append(importinfo.ImportStatement( - import_info, lineno, lineno, - blank_lines=blanks)) - - def _get_new_import_blanks(self): - return 0 - - def _get_new_import_lineno(self): - if self.imports: - return self.imports[-1].end_line - return 1 - - def filter_names(self, can_select): - visitor = actions.RemovingVisitor( - self.pycore, self._current_folder(), can_select) - for import_statement in self.imports: - import_statement.accept(visitor) - - def expand_stars(self): - can_select = _OneTimeSelector(self._get_unbound_names(self.pymodule)) - visitor = actions.ExpandStarsVisitor( - self.pycore, self._current_folder(), can_select) - for import_statement in self.imports: - import_statement.accept(visitor) - - def remove_duplicates(self): - added_imports = [] - for import_stmt in self.imports: - visitor = actions.AddingVisitor(self.pycore, - [import_stmt.import_info]) - for added_import in added_imports: - if added_import.accept(visitor): - import_stmt.empty_import() - else: - added_imports.append(import_stmt) - - def get_relative_to_absolute_list(self): - visitor = rope.refactor.importutils.actions.RelativeToAbsoluteVisitor( - self.pycore, self._current_folder()) - for import_stmt in self.imports: - if not import_stmt.readonly: - import_stmt.accept(visitor) - return visitor.to_be_absolute - - def get_self_import_fix_and_rename_list(self): - visitor = rope.refactor.importutils.actions.SelfImportVisitor( - self.pycore, self._current_folder(), self.pymodule.get_resource()) - for import_stmt in self.imports: - if not import_stmt.readonly: - import_stmt.accept(visitor) - return visitor.to_be_fixed, visitor.to_be_renamed - - def _current_folder(self): - return self.pymodule.get_resource().parent - - def sort_imports(self): - # IDEA: Sort from import list - visitor = actions.SortingVisitor(self.pycore, self._current_folder()) - for import_statement in self.imports: - import_statement.accept(visitor) - in_projects = sorted(visitor.in_project, self._compare_imports) - third_party = sorted(visitor.third_party, self._compare_imports) - standards = sorted(visitor.standard, self._compare_imports) - future = sorted(visitor.future, self._compare_imports) - blank_lines = 0 - last_index = self._first_import_line() - last_index = self._move_imports(future, last_index, 0) - last_index = self._move_imports(standards, last_index, 1) - last_index = self._move_imports(third_party, last_index, 1) - last_index = self._move_imports(in_projects, last_index, 1) - self.separating_lines = 2 - - def _first_import_line(self): - nodes = self.pymodule.get_ast().body - lineno = 0 - if self.pymodule.get_doc() is not None: - lineno = 1 - if len(nodes) > lineno: - lineno = self.pymodule.logical_lines.logical_line_in( - nodes[lineno].lineno)[0] - else: - lineno = self.pymodule.lines.length() - while lineno > 1: - line = self.pymodule.lines.get_line(lineno - 1) - if line.strip() == '': - lineno -= 1 - else: - break - return lineno - - def _compare_imports(self, stmt1, stmt2): - str1 = stmt1.get_import_statement() - str2 = stmt2.get_import_statement() - if str1.startswith('from ') and not str2.startswith('from '): - return 1 - if not str1.startswith('from ') and str2.startswith('from '): - return -1 - return cmp(str1, str2) - - def _move_imports(self, imports, index, blank_lines): - if imports: - imports[0].move(index, blank_lines) - index += 1 - if len(imports) > 1: - for stmt in imports[1:]: - stmt.move(index) - index += 1 - return index - - def handle_long_imports(self, maxdots, maxlength): - visitor = actions.LongImportVisitor( - self._current_folder(), self.pycore, maxdots, maxlength) - for import_statement in self.imports: - if not import_statement.readonly: - import_statement.accept(visitor) - for import_info in visitor.new_imports: - self.add_import(import_info) - return visitor.to_be_renamed - - def remove_pyname(self, pyname): - """Removes pyname when imported in ``from mod import x``""" - visitor = actions.RemovePyNameVisitor(self.pycore, self.pymodule, - pyname, self._current_folder()) - for import_stmt in self.imports: - import_stmt.accept(visitor) - - -class _OneTimeSelector(object): - - def __init__(self, names): - self.names = names - self.selected_names = set() - - def __call__(self, imported_primary): - if self._can_name_be_added(imported_primary): - for name in self._get_dotted_tokens(imported_primary): - self.selected_names.add(name) - return True - return False - - def _get_dotted_tokens(self, imported_primary): - tokens = imported_primary.split('.') - for i in range(len(tokens)): - yield '.'.join(tokens[:i + 1]) - - def _can_name_be_added(self, imported_primary): - for name in self._get_dotted_tokens(imported_primary): - if name in self.names and name not in self.selected_names: - return True - return False - - -class _UnboundNameFinder(object): - - def __init__(self, pyobject): - self.pyobject = pyobject - - def _visit_child_scope(self, node): - pyobject = self.pyobject.get_module().get_scope().\ - get_inner_scope_for_line(node.lineno).pyobject - visitor = _LocalUnboundNameFinder(pyobject, self) - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - - def _FunctionDef(self, node): - self._visit_child_scope(node) - - def _ClassDef(self, node): - self._visit_child_scope(node) - - def _Name(self, node): - if self._get_root()._is_node_interesting(node) and \ - not self.is_bound(node.id): - self.add_unbound(node.id) - - def _Attribute(self, node): - result = [] - while isinstance(node, ast.Attribute): - result.append(node.attr) - node = node.value - if isinstance(node, ast.Name): - result.append(node.id) - primary = '.'.join(reversed(result)) - if self._get_root()._is_node_interesting(node) and \ - not self.is_bound(primary): - self.add_unbound(primary) - else: - ast.walk(node, self) - - def _get_root(self): - pass - - def is_bound(self, name, propagated=False): - pass - - def add_unbound(self, name): - pass - - -class _GlobalUnboundNameFinder(_UnboundNameFinder): - - def __init__(self, pymodule, wanted_pyobject): - super(_GlobalUnboundNameFinder, self).__init__(pymodule) - self.unbound = set() - self.names = set() - for name, pyname in pymodule._get_structural_attributes().items(): - if not isinstance(pyname, (rope.base.pynames.ImportedName, - rope.base.pynames.ImportedModule)): - self.names.add(name) - wanted_scope = wanted_pyobject.get_scope() - self.start = wanted_scope.get_start() - self.end = wanted_scope.get_end() + 1 - - def _get_root(self): - return self - - def is_bound(self, primary, propagated=False): - name = primary.split('.')[0] - if name in self.names: - return True - return False - - def add_unbound(self, name): - names = name.split('.') - for i in range(len(names)): - self.unbound.add('.'.join(names[:i + 1])) - - def _is_node_interesting(self, node): - return self.start <= node.lineno < self.end - - -class _LocalUnboundNameFinder(_UnboundNameFinder): - - def __init__(self, pyobject, parent): - super(_LocalUnboundNameFinder, self).__init__(pyobject) - self.parent = parent - - def _get_root(self): - return self.parent._get_root() - - def is_bound(self, primary, propagated=False): - name = primary.split('.')[0] - if propagated: - names = self.pyobject.get_scope().get_propagated_names() - else: - names = self.pyobject.get_scope().get_names() - if name in names or self.parent.is_bound(name, propagated=True): - return True - return False - - def add_unbound(self, name): - self.parent.add_unbound(name) - - -class _GlobalImportFinder(object): - - def __init__(self, pymodule, pycore): - self.current_folder = None - if pymodule.get_resource(): - self.current_folder = pymodule.get_resource().parent - self.pymodule = pymodule - self.pycore = pycore - self.imports = [] - self.pymodule = pymodule - self.lines = self.pymodule.lines - - def visit_import(self, node, end_line): - start_line = node.lineno - import_statement = importinfo.ImportStatement( - importinfo.NormalImport(self._get_names(node.names)), - start_line, end_line, self._get_text(start_line, end_line), - blank_lines=self._count_empty_lines_before(start_line)) - self.imports.append(import_statement) - - def _count_empty_lines_before(self, lineno): - result = 0 - for current in range(lineno - 1, 0, -1): - line = self.lines.get_line(current) - if line.strip() == '': - result += 1 - else: - break - return result - - def _count_empty_lines_after(self, lineno): - result = 0 - for current in range(lineno + 1, self.lines.length()): - line = self.lines.get_line(current) - if line.strip() == '': - result += 1 - else: - break - return result - - def get_separating_line_count(self): - if not self.imports: - return 0 - return self._count_empty_lines_after(self.imports[-1].end_line - 1) - - def _get_text(self, start_line, end_line): - result = [] - for index in range(start_line, end_line): - result.append(self.lines.get_line(index)) - return '\n'.join(result) - - def visit_from(self, node, end_line): - level = 0 - if node.level: - level = node.level - import_info = importinfo.FromImport( - node.module or '', # see comment at rope.base.ast.walk - level, self._get_names(node.names)) - start_line = node.lineno - self.imports.append(importinfo.ImportStatement( - import_info, node.lineno, end_line, - self._get_text(start_line, end_line), - blank_lines=self._count_empty_lines_before(start_line))) - - def _get_names(self, alias_names): - result = [] - for alias in alias_names: - result.append((alias.name, alias.asname)) - return result - - def find_import_statements(self): - nodes = self.pymodule.get_ast().body - for index, node in enumerate(nodes): - if isinstance(node, (ast.Import, ast.ImportFrom)): - lines = self.pymodule.logical_lines - end_line = lines.logical_line_in(node.lineno)[1] + 1 - if isinstance(node, ast.Import): - self.visit_import(node, end_line) - if isinstance(node, ast.ImportFrom): - self.visit_from(node, end_line) - return self.imports diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/inline.py b/.vim/bundle/python-mode/pylibs/rope/refactor/inline.py @@ -1,615 +0,0 @@ -# Known Bugs when inlining a function/method -# The values passed to function are inlined using _inlined_variable. -# This may cause two problems, illustrated in the examples below -# -# def foo(var1): -# var1 = var1*10 -# return var1 -# -# If a call to foo(20) is inlined, the result of inlined function is 20, -# but it should be 200. -# -# def foo(var1): -# var2 = var1*10 -# return var2 -# -# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 -# but it should be 200. - -import re - -import rope.base.exceptions -import rope.refactor.functionutils -from rope.base import (pynames, pyobjects, codeanalyze, - taskhandle, evaluate, worder, utils) -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import (occurrences, rename, sourceutils, - importutils, move, change_signature) - -def unique_prefix(): - n = 0 - while True: - yield "__" + str(n) + "__" - n += 1 - -def create_inline(project, resource, offset): - """Create a refactoring object for inlining - - Based on `resource` and `offset` it returns an instance of - `InlineMethod`, `InlineVariable` or `InlineParameter`. - - """ - pycore = project.pycore - pyname = _get_pyname(pycore, resource, offset) - message = 'Inline refactoring should be performed on ' \ - 'a method, local variable or parameter.' - if pyname is None: - raise rope.base.exceptions.RefactoringError(message) - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - if isinstance(pyname, pynames.AssignedName): - return InlineVariable(project, resource, offset) - if isinstance(pyname, pynames.ParameterName): - return InlineParameter(project, resource, offset) - if isinstance(pyname.get_object(), pyobjects.PyFunction): - return InlineMethod(project, resource, offset) - else: - raise rope.base.exceptions.RefactoringError(message) - - -class _Inliner(object): - - def __init__(self, project, resource, offset): - self.project = project - self.pycore = project.pycore - self.pyname = _get_pyname(self.pycore, resource, offset) - range_finder = worder.Worder(resource.read()) - self.region = range_finder.get_primary_range(offset) - self.name = range_finder.get_word_at(offset) - self.offset = offset - self.original = resource - - def get_changes(self, *args, **kwds): - pass - - def get_kind(self): - """Return either 'variable', 'method' or 'parameter'""" - - -class InlineMethod(_Inliner): - - def __init__(self, *args, **kwds): - super(InlineMethod, self).__init__(*args, **kwds) - self.pyfunction = self.pyname.get_object() - self.pymodule = self.pyfunction.get_module() - self.resource = self.pyfunction.get_module().get_resource() - self.occurrence_finder = occurrences.create_finder( - self.pycore, self.name, self.pyname) - self.normal_generator = _DefinitionGenerator(self.project, - self.pyfunction) - self._init_imports() - - def _init_imports(self): - body = sourceutils.get_body(self.pyfunction) - body, imports = move.moving_code_with_imports( - self.pycore, self.resource, body) - self.imports = imports - self.others_generator = _DefinitionGenerator( - self.project, self.pyfunction, body=body) - - def _get_scope_range(self): - scope = self.pyfunction.get_scope() - lines = self.pymodule.lines - logicals = self.pymodule.logical_lines - start_line = scope.get_start() - if self.pyfunction.decorators: - decorators = self.pyfunction.decorators - if hasattr(decorators[0], 'lineno'): - start_line = decorators[0].lineno - start_offset = lines.get_line_start(start_line) - end_offset = min(lines.get_line_end(scope.end) + 1, - len(self.pymodule.source_code)) - return (start_offset, end_offset) - - def get_changes(self, remove=True, only_current=False, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Get the changes this refactoring makes - - If `remove` is `False` the definition will not be removed. If - `only_current` is `True`, the the current occurrence will be - inlined, only. - """ - changes = ChangeSet('Inline method <%s>' % self.name) - if resources is None: - resources = self.pycore.get_python_files() - if only_current: - resources = [self.original] - if remove: - resources.append(self.resource) - job_set = task_handle.create_jobset('Collecting Changes', - len(resources)) - for file in resources: - job_set.started_job(file.path) - if file == self.resource: - changes.add_change(self._defining_file_changes( - changes, remove=remove, only_current=only_current)) - else: - aim = None - if only_current and self.original == file: - aim = self.offset - handle = _InlineFunctionCallsForModuleHandle( - self.pycore, file, self.others_generator, aim) - result = move.ModuleSkipRenamer( - self.occurrence_finder, file, handle).get_changed_module() - if result is not None: - result = _add_imports(self.pycore, result, - file, self.imports) - if remove: - result = _remove_from(self.pycore, self.pyname, - result, file) - changes.add_change(ChangeContents(file, result)) - job_set.finished_job() - return changes - - def _get_removed_range(self): - scope = self.pyfunction.get_scope() - lines = self.pymodule.lines - logical = self.pymodule.logical_lines - start_line = scope.get_start() - start, end = self._get_scope_range() - end_line = scope.get_end() - for i in range(end_line + 1, lines.length()): - if lines.get_line(i).strip() == '': - end_line = i - else: - break - end = min(lines.get_line_end(end_line) + 1, - len(self.pymodule.source_code)) - return (start, end) - - def _defining_file_changes(self, changes, remove, only_current): - start_offset, end_offset = self._get_removed_range() - aim = None - if only_current: - if self.resource == self.original: - aim = self.offset - else: - # we don't want to change any of them - aim = len(self.resource.read()) + 100 - handle = _InlineFunctionCallsForModuleHandle( - self.pycore, self.resource, - self.normal_generator, aim_offset=aim) - replacement = None - if remove: - replacement = self._get_method_replacement() - result = move.ModuleSkipRenamer( - self.occurrence_finder, self.resource, handle, start_offset, - end_offset, replacement).get_changed_module() - return ChangeContents(self.resource, result) - - def _get_method_replacement(self): - if self._is_the_last_method_of_a_class(): - indents = sourceutils.get_indents( - self.pymodule.lines, self.pyfunction.get_scope().get_start()) - return ' ' * indents + 'pass\n' - return '' - - def _is_the_last_method_of_a_class(self): - pyclass = self.pyfunction.parent - if not isinstance(pyclass, pyobjects.PyClass): - return False - class_start, class_end = sourceutils.get_body_region(pyclass) - source = self.pymodule.source_code - lines = self.pymodule.lines - func_start, func_end = self._get_scope_range() - if source[class_start:func_start].strip() == '' and \ - source[func_end:class_end].strip() == '': - return True - return False - - def get_kind(self): - return 'method' - - -class InlineVariable(_Inliner): - - def __init__(self, *args, **kwds): - super(InlineVariable, self).__init__(*args, **kwds) - self.pymodule = self.pyname.get_definition_location()[0] - self.resource = self.pymodule.get_resource() - self._check_exceptional_conditions() - self._init_imports() - - def _check_exceptional_conditions(self): - if len(self.pyname.assignments) != 1: - raise rope.base.exceptions.RefactoringError( - 'Local variable should be assigned once for inlining.') - - def get_changes(self, remove=True, only_current=False, resources=None, - task_handle=taskhandle.NullTaskHandle()): - if resources is None: - if rename._is_local(self.pyname): - resources = [self.resource] - else: - resources = self.pycore.get_python_files() - if only_current: - resources = [self.original] - if remove and self.original != self.resource: - resources.append(self.resource) - changes = ChangeSet('Inline variable <%s>' % self.name) - jobset = task_handle.create_jobset('Calculating changes', - len(resources)) - - for resource in resources: - jobset.started_job(resource.path) - if resource == self.resource: - source = self._change_main_module(remove, only_current) - changes.add_change(ChangeContents(self.resource, source)) - else: - result = self._change_module(resource, remove, only_current) - if result is not None: - result = _add_imports(self.pycore, result, - resource, self.imports) - changes.add_change(ChangeContents(resource, result)) - jobset.finished_job() - return changes - - def _change_main_module(self, remove, only_current): - region = None - if only_current and self.original == self.resource: - region = self.region - return _inline_variable(self.pycore, self.pymodule, self.pyname, - self.name, remove=remove, region=region) - - def _init_imports(self): - vardef = _getvardef(self.pymodule, self.pyname) - self.imported, self.imports = move.moving_code_with_imports( - self.pycore, self.resource, vardef) - - def _change_module(self, resource, remove, only_current): - filters = [occurrences.NoImportsFilter(), - occurrences.PyNameFilter(self.pyname)] - if only_current and resource == self.original: - def check_aim(occurrence): - start, end = occurrence.get_primary_range() - if self.offset < start or end < self.offset: - return False - filters.insert(0, check_aim) - finder = occurrences.Finder(self.pycore, self.name, filters=filters) - changed = rename.rename_in_module( - finder, self.imported, resource=resource, replace_primary=True) - if changed and remove: - changed = _remove_from(self.pycore, self.pyname, changed, resource) - return changed - - def get_kind(self): - return 'variable' - - -class InlineParameter(_Inliner): - - def __init__(self, *args, **kwds): - super(InlineParameter, self).__init__(*args, **kwds) - resource, offset = self._function_location() - index = self.pyname.index - self.changers = [change_signature.ArgumentDefaultInliner(index)] - self.signature = change_signature.ChangeSignature(self.project, - resource, offset) - - def _function_location(self): - pymodule, lineno = self.pyname.get_definition_location() - resource = pymodule.get_resource() - start = pymodule.lines.get_line_start(lineno) - word_finder = worder.Worder(pymodule.source_code) - offset = word_finder.find_function_offset(start) - return resource, offset - - def get_changes(self, **kwds): - """Get the changes needed by this refactoring - - See `rope.refactor.change_signature.ChangeSignature.get_changes()` - for arguments. - """ - return self.signature.get_changes(self.changers, **kwds) - - def get_kind(self): - return 'parameter' - - -def _join_lines(lines): - definition_lines = [] - for unchanged_line in lines: - line = unchanged_line.strip() - if line.endswith('\\'): - line = line[:-1].strip() - definition_lines.append(line) - joined = ' '.join(definition_lines) - return joined - - -class _DefinitionGenerator(object): - unique_prefix = unique_prefix() - def __init__(self, project, pyfunction, body=None): - self.pycore = project.pycore - self.pyfunction = pyfunction - self.pymodule = pyfunction.get_module() - self.resource = self.pymodule.get_resource() - self.definition_info = self._get_definition_info() - self.definition_params = self._get_definition_params() - self._calculated_definitions = {} - if body is not None: - self.body = body - else: - self.body = sourceutils.get_body(self.pyfunction) - - def _get_definition_info(self): - return rope.refactor.functionutils.DefinitionInfo.read(self.pyfunction) - - def _get_definition_params(self): - definition_info = self.definition_info - paramdict = dict([pair for pair in definition_info.args_with_defaults]) - if definition_info.args_arg is not None or \ - definition_info.keywords_arg is not None: - raise rope.base.exceptions.RefactoringError( - 'Cannot inline functions with list and keyword arguements.') - if self.pyfunction.get_kind() == 'classmethod': - paramdict[definition_info.args_with_defaults[0][0]] = \ - self.pyfunction.parent.get_name() - return paramdict - - def get_function_name(self): - return self.pyfunction.get_name() - - def get_definition(self, primary, pyname, call, host_vars=[],returns=False): - # caching already calculated definitions - return self._calculate_definition(primary, pyname, call, - host_vars, returns) - - def _calculate_header(self, primary, pyname, call): - # A header is created which initializes parameters - # to the values passed to the function. - call_info = rope.refactor.functionutils.CallInfo.read( - primary, pyname, self.definition_info, call) - paramdict = self.definition_params - mapping = rope.refactor.functionutils.ArgumentMapping( - self.definition_info, call_info) - for param_name, value in mapping.param_dict.items(): - paramdict[param_name] = value - header = '' - to_be_inlined = [] - mod = self.pycore.get_string_module(self.body) - all_names = mod.get_scope().get_names() - assigned_names = [name for name in all_names if - isinstance(all_names[name], rope.base.pynamesdef.AssignedName)] - for name, value in paramdict.items(): - if name != value and value is not None: - header += name + ' = ' + value.replace('\n', ' ') + '\n' - to_be_inlined.append(name) - return header, to_be_inlined - - def _calculate_definition(self, primary, pyname, call, host_vars, returns): - - header, to_be_inlined = self._calculate_header(primary, pyname, call) - - source = header + self.body - mod = self.pycore.get_string_module(source) - name_dict = mod.get_scope().get_names() - all_names = [x for x in name_dict if - not isinstance(name_dict[x], rope.base.builtins.BuiltinName)] - - # If there is a name conflict, all variable names - # inside the inlined function are renamed - if len(set(all_names).intersection(set(host_vars))) > 0: - - prefix = _DefinitionGenerator.unique_prefix.next() - guest = self.pycore.get_string_module(source, self.resource) - - to_be_inlined = [prefix+item for item in to_be_inlined] - for item in all_names: - pyname = guest[item] - occurrence_finder = occurrences.create_finder( - self.pycore, item, pyname) - source = rename.rename_in_module(occurrence_finder, - prefix+item, pymodule=guest) - guest = self.pycore.get_string_module(source, self.resource) - - #parameters not reassigned inside the functions are now inlined. - for name in to_be_inlined: - pymodule = self.pycore.get_string_module(source, self.resource) - pyname = pymodule[name] - source = _inline_variable(self.pycore, pymodule, pyname, name) - - return self._replace_returns_with(source, returns) - - def _replace_returns_with(self, source, returns): - result = [] - returned = None - last_changed = 0 - for match in _DefinitionGenerator._get_return_pattern().finditer(source): - for key, value in match.groupdict().items(): - if value and key == 'return': - result.append(source[last_changed:match.start('return')]) - if returns: - self._check_nothing_after_return(source, - match.end('return')) - returned = _join_lines( - source[match.end('return'): len(source)].splitlines()) - last_changed = len(source) - else: - current = match.end('return') - while current < len(source) and source[current] in ' \t': - current += 1 - last_changed = current - if current == len(source) or source[current] == '\n': - result.append('pass') - result.append(source[last_changed:]) - return ''.join(result), returned - - def _check_nothing_after_return(self, source, offset): - lines = codeanalyze.SourceLinesAdapter(source) - lineno = lines.get_line_number(offset) - logical_lines = codeanalyze.LogicalLineFinder(lines) - lineno = logical_lines.logical_line_in(lineno)[1] - if source[lines.get_line_end(lineno):len(source)].strip() != '': - raise rope.base.exceptions.RefactoringError( - 'Cannot inline functions with statements after return statement.') - - @classmethod - def _get_return_pattern(cls): - if not hasattr(cls, '_return_pattern'): - def named_pattern(name, list_): - return "(?P<%s>" % name + "|".join(list_) + ")" - comment_pattern = named_pattern('comment', [r'#[^\n]*']) - string_pattern = named_pattern('string', - [codeanalyze.get_string_pattern()]) - return_pattern = r'\b(?P<return>return)\b' - cls._return_pattern = re.compile(comment_pattern + "|" + - string_pattern + "|" + - return_pattern) - return cls._return_pattern - - -class _InlineFunctionCallsForModuleHandle(object): - - def __init__(self, pycore, resource, - definition_generator, aim_offset=None): - """Inlines occurrences - - If `aim` is not `None` only the occurrences that intersect - `aim` offset will be inlined. - - """ - self.pycore = pycore - self.generator = definition_generator - self.resource = resource - self.aim = aim_offset - - def occurred_inside_skip(self, change_collector, occurrence): - if not occurrence.is_defined(): - raise rope.base.exceptions.RefactoringError( - 'Cannot inline functions that reference themselves') - - def occurred_outside_skip(self, change_collector, occurrence): - start, end = occurrence.get_primary_range() - # we remove out of date imports later - if occurrence.is_in_import_statement(): - return - # the function is referenced outside an import statement - if not occurrence.is_called(): - raise rope.base.exceptions.RefactoringError( - 'Reference to inlining function other than function call' - ' in <file: %s, offset: %d>' % (self.resource.path, start)) - if self.aim is not None and (self.aim < start or self.aim > end): - return - end_parens = self._find_end_parens(self.source, end - 1) - lineno = self.lines.get_line_number(start) - start_line, end_line = self.pymodule.logical_lines.\ - logical_line_in(lineno) - line_start = self.lines.get_line_start(start_line) - line_end = self.lines.get_line_end(end_line) - - - returns = self.source[line_start:start].strip() != '' or \ - self.source[end_parens:line_end].strip() != '' - indents = sourceutils.get_indents(self.lines, start_line) - primary, pyname = occurrence.get_primary_and_pyname() - - host = self.pycore.resource_to_pyobject(self.resource) - scope = host.scope.get_inner_scope_for_line(lineno) - definition, returned = self.generator.get_definition( - primary, pyname, self.source[start:end_parens], scope.get_names(), returns=returns) - - end = min(line_end + 1, len(self.source)) - change_collector.add_change(line_start, end, - sourceutils.fix_indentation(definition, indents)) - if returns: - name = returned - if name is None: - name = 'None' - change_collector.add_change( - line_end, end, self.source[line_start:start] + name + - self.source[end_parens:end]) - - def _find_end_parens(self, source, offset): - finder = worder.Worder(source) - return finder.get_word_parens_range(offset)[1] - - @property - @utils.saveit - def pymodule(self): - return self.pycore.resource_to_pyobject(self.resource) - - @property - @utils.saveit - def source(self): - if self.resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - @property - @utils.saveit - def lines(self): - return self.pymodule.lines - - -def _inline_variable(pycore, pymodule, pyname, name, - remove=True, region=None): - definition = _getvardef(pymodule, pyname) - start, end = _assigned_lineno(pymodule, pyname) - - occurrence_finder = occurrences.create_finder(pycore, name, pyname) - changed_source = rename.rename_in_module( - occurrence_finder, definition, pymodule=pymodule, - replace_primary=True, writes=False, region=region) - if changed_source is None: - changed_source = pymodule.source_code - if remove: - lines = codeanalyze.SourceLinesAdapter(changed_source) - source = changed_source[:lines.get_line_start(start)] + \ - changed_source[lines.get_line_end(end) + 1:] - else: - source = changed_source - return source - -def _getvardef(pymodule, pyname): - assignment = pyname.assignments[0] - lines = pymodule.lines - start, end = _assigned_lineno(pymodule, pyname) - definition_with_assignment = _join_lines( - [lines.get_line(n) for n in range(start, end + 1)]) - if assignment.levels: - raise rope.base.exceptions.RefactoringError( - 'Cannot inline tuple assignments.') - definition = definition_with_assignment[definition_with_assignment.\ - index('=') + 1:].strip() - return definition - -def _assigned_lineno(pymodule, pyname): - definition_line = pyname.assignments[0].ast_node.lineno - return pymodule.logical_lines.logical_line_in(definition_line) - -def _add_imports(pycore, source, resource, imports): - if not imports: - return source - pymodule = pycore.get_string_module(source, resource) - module_import = importutils.get_module_imports(pycore, pymodule) - for import_info in imports: - module_import.add_import(import_info) - source = module_import.get_changed_source() - pymodule = pycore.get_string_module(source, resource) - import_tools = importutils.ImportTools(pycore) - return import_tools.organize_imports(pymodule, unused=False, sort=False) - -def _get_pyname(pycore, resource, offset): - pymodule = pycore.resource_to_pyobject(resource) - pyname = evaluate.eval_location(pymodule, offset) - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - return pyname - -def _remove_from(pycore, pyname, source, resource): - pymodule = pycore.get_string_module(source, resource) - module_import = importutils.get_module_imports(pycore, pymodule) - module_import.remove_pyname(pyname) - return module_import.get_changed_source() diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/introduce_factory.py b/.vim/bundle/python-mode/pylibs/rope/refactor/introduce_factory.py @@ -1,133 +0,0 @@ -import rope.base.exceptions -import rope.base.pyobjects -from rope.base import taskhandle, evaluate -from rope.base.change import (ChangeSet, ChangeContents) -from rope.refactor import rename, occurrences, sourceutils, importutils - - -class IntroduceFactory(object): - - def __init__(self, project, resource, offset): - self.pycore = project.pycore - self.offset = offset - - this_pymodule = self.pycore.resource_to_pyobject(resource) - self.old_pyname = evaluate.eval_location(this_pymodule, offset) - if self.old_pyname is None or not isinstance(self.old_pyname.get_object(), - rope.base.pyobjects.PyClass): - raise rope.base.exceptions.RefactoringError( - 'Introduce factory should be performed on a class.') - self.old_name = self.old_pyname.get_object().get_name() - self.pymodule = self.old_pyname.get_object().get_module() - self.resource = self.pymodule.get_resource() - - def get_changes(self, factory_name, global_factory=False, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Get the changes this refactoring makes - - `factory_name` indicates the name of the factory function to - be added. If `global_factory` is `True` the factory will be - global otherwise a static method is added to the class. - - `resources` can be a list of `rope.base.resource.File`\s that - this refactoring should be applied on; if `None` all python - files in the project are searched. - - """ - if resources is None: - resources = self.pycore.get_python_files() - changes = ChangeSet('Introduce factory method <%s>' % factory_name) - job_set = task_handle.create_jobset('Collecting Changes', - len(resources)) - self._change_module(resources, changes, factory_name, - global_factory, job_set) - return changes - - def get_name(self): - """Return the name of the class""" - return self.old_name - - def _change_module(self, resources, changes, - factory_name, global_, job_set): - if global_: - replacement = '__rope_factory_%s_' % factory_name - else: - replacement = self._new_function_name(factory_name, global_) - - for file_ in resources: - job_set.started_job(file_.path) - if file_ == self.resource: - self._change_resource(changes, factory_name, global_) - job_set.finished_job() - continue - changed_code = self._rename_occurrences(file_, replacement, - global_) - if changed_code is not None: - if global_: - new_pymodule = self.pycore.get_string_module(changed_code, - self.resource) - modname = self.pycore.modname(self.resource) - changed_code, imported = importutils.add_import( - self.pycore, new_pymodule, modname, factory_name) - changed_code = changed_code.replace(replacement, imported) - changes.add_change(ChangeContents(file_, changed_code)) - job_set.finished_job() - - def _change_resource(self, changes, factory_name, global_): - class_scope = self.old_pyname.get_object().get_scope() - source_code = self._rename_occurrences( - self.resource, self._new_function_name(factory_name, - global_), global_) - if source_code is None: - source_code = self.pymodule.source_code - else: - self.pymodule = self.pycore.get_string_module( - source_code, resource=self.resource) - lines = self.pymodule.lines - start = self._get_insertion_offset(class_scope, lines) - result = source_code[:start] - result += self._get_factory_method(lines, class_scope, - factory_name, global_) - result += source_code[start:] - changes.add_change(ChangeContents(self.resource, result)) - - def _get_insertion_offset(self, class_scope, lines): - start_line = class_scope.get_end() - if class_scope.get_scopes(): - start_line = class_scope.get_scopes()[-1].get_end() - start = lines.get_line_end(start_line) + 1 - return start - - def _get_factory_method(self, lines, class_scope, - factory_name, global_): - unit_indents = ' ' * sourceutils.get_indent(self.pycore) - if global_: - if self._get_scope_indents(lines, class_scope) > 0: - raise rope.base.exceptions.RefactoringError( - 'Cannot make global factory method for nested classes.') - return ('\ndef %s(*args, **kwds):\n%sreturn %s(*args, **kwds)\n' % - (factory_name, unit_indents, self.old_name)) - unindented_factory = \ - ('@staticmethod\ndef %s(*args, **kwds):\n' % factory_name + - '%sreturn %s(*args, **kwds)\n' % (unit_indents, self.old_name)) - indents = self._get_scope_indents(lines, class_scope) + \ - sourceutils.get_indent(self.pycore) - return '\n' + sourceutils.indent_lines(unindented_factory, indents) - - def _get_scope_indents(self, lines, scope): - return sourceutils.get_indents(lines, scope.get_start()) - - def _new_function_name(self, factory_name, global_): - if global_: - return factory_name - else: - return self.old_name + '.' + factory_name - - def _rename_occurrences(self, file_, changed_name, global_factory): - finder = occurrences.create_finder(self.pycore, self.old_name, - self.old_pyname, only_calls=True) - result = rename.rename_in_module(finder, changed_name, resource=file_, - replace_primary=global_factory) - return result - -IntroduceFactoryRefactoring = IntroduceFactory diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/introduce_parameter.py b/.vim/bundle/python-mode/pylibs/rope/refactor/introduce_parameter.py @@ -1,95 +0,0 @@ -import rope.base.change -from rope.base import exceptions, evaluate, worder, codeanalyze -from rope.refactor import functionutils, sourceutils, occurrences - - -class IntroduceParameter(object): - """Introduce parameter refactoring - - This refactoring adds a new parameter to a function and replaces - references to an expression in it with the new parameter. - - The parameter finding part is different from finding similar - pieces in extract refactorings. In this refactoring parameters - are found based on the object they reference to. For instance - in:: - - class A(object): - var = None - - class B(object): - a = A() - - b = B() - a = b.a - - def f(a): - x = b.a.var + a.var - - using this refactoring on ``a.var`` with ``p`` as the new - parameter name, will result in:: - - def f(p=a.var): - x = p + p - - """ - - def __init__(self, project, resource, offset): - self.pycore = project.pycore - self.resource = resource - self.offset = offset - self.pymodule = self.pycore.resource_to_pyobject(self.resource) - scope = self.pymodule.get_scope().get_inner_scope_for_offset(offset) - if scope.get_kind() != 'Function': - raise exceptions.RefactoringError( - 'Introduce parameter should be performed inside functions') - self.pyfunction = scope.pyobject - self.name, self.pyname = self._get_name_and_pyname() - if self.pyname is None: - raise exceptions.RefactoringError( - 'Cannot find the definition of <%s>' % self.name) - - def _get_primary(self): - word_finder = worder.Worder(self.resource.read()) - return word_finder.get_primary_at(self.offset) - - def _get_name_and_pyname(self): - return (worder.get_name_at(self.resource, self.offset), - evaluate.eval_location(self.pymodule, self.offset)) - - def get_changes(self, new_parameter): - definition_info = functionutils.DefinitionInfo.read(self.pyfunction) - definition_info.args_with_defaults.append((new_parameter, - self._get_primary())) - collector = codeanalyze.ChangeCollector(self.resource.read()) - header_start, header_end = self._get_header_offsets() - body_start, body_end = sourceutils.get_body_region(self.pyfunction) - collector.add_change(header_start, header_end, - definition_info.to_string()) - self._change_function_occurances(collector, body_start, - body_end, new_parameter) - changes = rope.base.change.ChangeSet('Introduce parameter <%s>' % - new_parameter) - change = rope.base.change.ChangeContents(self.resource, - collector.get_changed()) - changes.add_change(change) - return changes - - def _get_header_offsets(self): - lines = self.pymodule.lines - start_line = self.pyfunction.get_scope().get_start() - end_line = self.pymodule.logical_lines.\ - logical_line_in(start_line)[1] - start = lines.get_line_start(start_line) - end = lines.get_line_end(end_line) - start = self.pymodule.source_code.find('def', start) + 4 - end = self.pymodule.source_code.rfind(':', start, end) - return start, end - - def _change_function_occurances(self, collector, function_start, - function_end, new_name): - finder = occurrences.create_finder(self.pycore, self.name, self.pyname) - for occurrence in finder.find_occurrences(resource=self.resource): - start, end = occurrence.get_primary_range() - if function_start <= start < function_end: - collector.add_change(start, end, new_name) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/localtofield.py b/.vim/bundle/python-mode/pylibs/rope/refactor/localtofield.py @@ -1,50 +0,0 @@ -from rope.base import pynames, evaluate, exceptions, worder -from rope.refactor.rename import Rename - - -class LocalToField(object): - - def __init__(self, project, resource, offset): - self.project = project - self.pycore = project.pycore - self.resource = resource - self.offset = offset - - def get_changes(self): - name = worder.get_name_at(self.resource, self.offset) - this_pymodule = self.pycore.resource_to_pyobject(self.resource) - pyname = evaluate.eval_location(this_pymodule, self.offset) - if not self._is_a_method_local(pyname): - raise exceptions.RefactoringError( - 'Convert local variable to field should be performed on \n' - 'a local variable of a method.') - - pymodule, lineno = pyname.get_definition_location() - function_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - # Not checking redefinition - #self._check_redefinition(name, function_scope) - - new_name = self._get_field_name(function_scope.pyobject, name) - changes = Rename(self.project, self.resource, self.offset).\ - get_changes(new_name, resources=[self.resource]) - return changes - - def _check_redefinition(self, name, function_scope): - class_scope = function_scope.parent - if name in class_scope.pyobject: - raise exceptions.RefactoringError( - 'The field %s already exists' % name) - - def _get_field_name(self, pyfunction, name): - self_name = pyfunction.get_param_names()[0] - new_name = self_name + '.' + name - return new_name - - def _is_a_method_local(self, pyname): - pymodule, lineno = pyname.get_definition_location() - holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - parent = holding_scope.parent - return isinstance(pyname, pynames.AssignedName) and \ - pyname in holding_scope.get_names().values() and \ - holding_scope.get_kind() == 'Function' and \ - parent is not None and parent.get_kind() == 'Class' diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/method_object.py b/.vim/bundle/python-mode/pylibs/rope/refactor/method_object.py @@ -1,87 +0,0 @@ -import warnings - -from rope.base import pyobjects, exceptions, change, evaluate, codeanalyze -from rope.refactor import sourceutils, occurrences, rename - - -class MethodObject(object): - - def __init__(self, project, resource, offset): - self.pycore = project.pycore - this_pymodule = self.pycore.resource_to_pyobject(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - if pyname is None or not isinstance(pyname.get_object(), - pyobjects.PyFunction): - raise exceptions.RefactoringError( - 'Replace method with method object refactoring should be ' - 'performed on a function.') - self.pyfunction = pyname.get_object() - self.pymodule = self.pyfunction.get_module() - self.resource = self.pymodule.get_resource() - - def get_new_class(self, name): - body = sourceutils.fix_indentation( - self._get_body(), sourceutils.get_indent(self.pycore) * 2) - return 'class %s(object):\n\n%s%sdef __call__(self):\n%s' % \ - (name, self._get_init(), - ' ' * sourceutils.get_indent(self.pycore), body) - - def get_changes(self, classname=None, new_class_name=None): - if new_class_name is not None: - warnings.warn( - 'new_class_name parameter is deprecated; use classname', - DeprecationWarning, stacklevel=2) - classname = new_class_name - collector = codeanalyze.ChangeCollector(self.pymodule.source_code) - start, end = sourceutils.get_body_region(self.pyfunction) - indents = sourceutils.get_indents( - self.pymodule.lines, self.pyfunction.get_scope().get_start()) + \ - sourceutils.get_indent(self.pycore) - new_contents = ' ' * indents + 'return %s(%s)()\n' % \ - (classname, ', '.join(self._get_parameter_names())) - collector.add_change(start, end, new_contents) - insertion = self._get_class_insertion_point() - collector.add_change(insertion, insertion, - '\n\n' + self.get_new_class(classname)) - changes = change.ChangeSet('Replace method with method object refactoring') - changes.add_change(change.ChangeContents(self.resource, - collector.get_changed())) - return changes - - def _get_class_insertion_point(self): - current = self.pyfunction - while current.parent != self.pymodule: - current = current.parent - end = self.pymodule.lines.get_line_end(current.get_scope().get_end()) - return min(end + 1, len(self.pymodule.source_code)) - - def _get_body(self): - body = sourceutils.get_body(self.pyfunction) - for param in self._get_parameter_names(): - body = param + ' = None\n' + body - pymod = self.pycore.get_string_module(body, self.resource) - pyname = pymod[param] - finder = occurrences.create_finder(self.pycore, param, pyname) - result = rename.rename_in_module(finder, 'self.' + param, - pymodule=pymod) - body = result[result.index('\n') + 1:] - return body - - def _get_init(self): - params = self._get_parameter_names() - indents = ' ' * sourceutils.get_indent(self.pycore) - if not params: - return '' - header = indents + 'def __init__(self' - body = '' - for arg in params: - new_name = arg - if arg == 'self': - new_name = 'host' - header += ', %s' % new_name - body += indents * 2 + 'self.%s = %s\n' % (arg, new_name) - header += '):' - return '%s\n%s\n' % (header, body) - - def _get_parameter_names(self): - return self.pyfunction.get_param_names() diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/move.py b/.vim/bundle/python-mode/pylibs/rope/refactor/move.py @@ -1,629 +0,0 @@ -"""A module containing classes for move refactoring - -`create_move()` is a factory for creating move refactoring objects -based on inputs. - -""" -from rope.base import pyobjects, codeanalyze, exceptions, pynames, taskhandle, evaluate, worder -from rope.base.change import ChangeSet, ChangeContents, MoveResource -from rope.refactor import importutils, rename, occurrences, sourceutils, functionutils - - -def create_move(project, resource, offset=None): - """A factory for creating Move objects - - Based on `resource` and `offset`, return one of `MoveModule`, - `MoveGlobal` or `MoveMethod` for performing move refactoring. - - """ - if offset is None: - return MoveModule(project, resource) - this_pymodule = project.pycore.resource_to_pyobject(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - if pyname is None: - raise exceptions.RefactoringError( - 'Move only works on classes, functions, modules and methods.') - pyobject = pyname.get_object() - if isinstance(pyobject, pyobjects.PyModule) or \ - isinstance(pyobject, pyobjects.PyPackage): - return MoveModule(project, pyobject.get_resource()) - if isinstance(pyobject, pyobjects.PyFunction) and \ - isinstance(pyobject.parent, pyobjects.PyClass): - return MoveMethod(project, resource, offset) - if isinstance(pyobject, pyobjects.PyDefinedObject) and \ - isinstance(pyobject.parent, pyobjects.PyModule): - return MoveGlobal(project, resource, offset) - raise exceptions.RefactoringError( - 'Move only works on global classes/functions, modules and methods.') - - -class MoveMethod(object): - """For moving methods - - It makes a new method in the destination class and changes - the body of the old method to call the new method. You can - inline the old method to change all of its occurrences. - - """ - - def __init__(self, project, resource, offset): - self.project = project - self.pycore = project.pycore - this_pymodule = self.pycore.resource_to_pyobject(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - self.method_name = worder.get_name_at(resource, offset) - self.pyfunction = pyname.get_object() - if self.pyfunction.get_kind() != 'method': - raise exceptions.RefactoringError('Only normal methods' - ' can be moved.') - - def get_changes(self, dest_attr, new_name=None, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Return the changes needed for this refactoring - - Parameters: - - - `dest_attr`: the name of the destination attribute - - `new_name`: the name of the new method; if `None` uses - the old name - - `resources` can be a list of `rope.base.resources.File`\s to - apply this refactoring on. If `None`, the restructuring - will be applied to all python files. - - """ - changes = ChangeSet('Moving method <%s>' % self.method_name) - if resources is None: - resources = self.pycore.get_python_files() - if new_name is None: - new_name = self.get_method_name() - resource1, start1, end1, new_content1 = \ - self._get_changes_made_by_old_class(dest_attr, new_name) - collector1 = codeanalyze.ChangeCollector(resource1.read()) - collector1.add_change(start1, end1, new_content1) - - resource2, start2, end2, new_content2 = \ - self._get_changes_made_by_new_class(dest_attr, new_name) - if resource1 == resource2: - collector1.add_change(start2, end2, new_content2) - else: - collector2 = codeanalyze.ChangeCollector(resource2.read()) - collector2.add_change(start2, end2, new_content2) - result = collector2.get_changed() - import_tools = importutils.ImportTools(self.pycore) - new_imports = self._get_used_imports(import_tools) - if new_imports: - goal_pymodule = self.pycore.get_string_module(result, - resource2) - result = _add_imports_to_module( - import_tools, goal_pymodule, new_imports) - if resource2 in resources: - changes.add_change(ChangeContents(resource2, result)) - - if resource1 in resources: - changes.add_change(ChangeContents(resource1, - collector1.get_changed())) - return changes - - def get_method_name(self): - return self.method_name - - def _get_used_imports(self, import_tools): - return importutils.get_imports(self.pycore, self.pyfunction) - - def _get_changes_made_by_old_class(self, dest_attr, new_name): - pymodule = self.pyfunction.get_module() - indents = self._get_scope_indents(self.pyfunction) - body = 'return self.%s.%s(%s)\n' % (dest_attr, new_name, - self._get_passed_arguments_string()) - region = sourceutils.get_body_region(self.pyfunction) - return (pymodule.get_resource(), region[0], region[1], - sourceutils.fix_indentation(body, indents)) - - def _get_scope_indents(self, pyobject): - pymodule = pyobject.get_module() - return sourceutils.get_indents( - pymodule.lines, pyobject.get_scope().get_start()) + \ - sourceutils.get_indent(self.pycore) - - def _get_changes_made_by_new_class(self, dest_attr, new_name): - old_pyclass = self.pyfunction.parent - if dest_attr not in old_pyclass: - raise exceptions.RefactoringError( - 'Destination attribute <%s> not found' % dest_attr) - pyclass = old_pyclass[dest_attr].get_object().get_type() - if not isinstance(pyclass, pyobjects.PyClass): - raise exceptions.RefactoringError( - 'Unknown class type for attribute <%s>' % dest_attr) - pymodule = pyclass.get_module() - resource = pyclass.get_module().get_resource() - start, end = sourceutils.get_body_region(pyclass) - pre_blanks = '\n' - if pymodule.source_code[start:end].strip() != 'pass': - pre_blanks = '\n\n' - start = end - indents = self._get_scope_indents(pyclass) - body = pre_blanks + sourceutils.fix_indentation( - self.get_new_method(new_name), indents) - return resource, start, end, body - - def get_new_method(self, name): - return '%s\n%s' % ( - self._get_new_header(name), - sourceutils.fix_indentation(self._get_body(), - sourceutils.get_indent(self.pycore))) - - def _get_unchanged_body(self): - return sourceutils.get_body(self.pyfunction) - - def _get_body(self, host='host'): - self_name = self._get_self_name() - body = self_name + ' = None\n' + self._get_unchanged_body() - pymodule = self.pycore.get_string_module(body) - finder = occurrences.create_finder( - self.pycore, self_name, pymodule[self_name]) - result = rename.rename_in_module(finder, host, pymodule=pymodule) - if result is None: - result = body - return result[result.index('\n') + 1:] - - def _get_self_name(self): - return self.pyfunction.get_param_names()[0] - - def _get_new_header(self, name): - header = 'def %s(self' % name - if self._is_host_used(): - header += ', host' - definition_info = functionutils.DefinitionInfo.read(self.pyfunction) - others = definition_info.arguments_to_string(1) - if others: - header += ', ' + others - return header + '):' - - def _get_passed_arguments_string(self): - result = '' - if self._is_host_used(): - result = 'self' - definition_info = functionutils.DefinitionInfo.read(self.pyfunction) - others = definition_info.arguments_to_string(1) - if others: - if result: - result += ', ' - result += others - return result - - def _is_host_used(self): - return self._get_body('__old_self') != self._get_unchanged_body() - - -class MoveGlobal(object): - """For moving global function and classes""" - - def __init__(self, project, resource, offset): - self.pycore = project.pycore - this_pymodule = self.pycore.resource_to_pyobject(resource) - self.old_pyname = evaluate.eval_location(this_pymodule, offset) - self.old_name = self.old_pyname.get_object().get_name() - pymodule = self.old_pyname.get_object().get_module() - self.source = pymodule.get_resource() - self.tools = _MoveTools(self.pycore, self.source, - self.old_pyname, self.old_name) - self.import_tools = self.tools.import_tools - self._check_exceptional_conditions() - - def _check_exceptional_conditions(self): - if self.old_pyname is None or \ - not isinstance(self.old_pyname.get_object(), pyobjects.PyDefinedObject): - raise exceptions.RefactoringError( - 'Move refactoring should be performed on a class/function.') - moving_pyobject = self.old_pyname.get_object() - if not self._is_global(moving_pyobject): - raise exceptions.RefactoringError( - 'Move refactoring should be performed on a global class/function.') - - def _is_global(self, pyobject): - return pyobject.get_scope().parent == pyobject.get_module().get_scope() - - def get_changes(self, dest, resources=None, - task_handle=taskhandle.NullTaskHandle()): - if resources is None: - resources = self.pycore.get_python_files() - if dest is None or not dest.exists(): - raise exceptions.RefactoringError( - 'Move destination does not exist.') - if dest.is_folder() and dest.has_child('__init__.py'): - dest = dest.get_child('__init__.py') - if dest.is_folder(): - raise exceptions.RefactoringError( - 'Move destination for non-modules should not be folders.') - if self.source == dest: - raise exceptions.RefactoringError( - 'Moving global elements to the same module.') - return self._calculate_changes(dest, resources, task_handle) - - def _calculate_changes(self, dest, resources, task_handle): - changes = ChangeSet('Moving global <%s>' % self.old_name) - job_set = task_handle.create_jobset('Collecting Changes', - len(resources)) - for file_ in resources: - job_set.started_job(file_.path) - if file_ == self.source: - changes.add_change(self._source_module_changes(dest)) - elif file_ == dest: - changes.add_change(self._dest_module_changes(dest)) - elif self.tools.occurs_in_module(resource=file_): - pymodule = self.pycore.resource_to_pyobject(file_) - # Changing occurrences - placeholder = '__rope_renaming_%s_' % self.old_name - source = self.tools.rename_in_module(placeholder, - resource=file_) - should_import = source is not None - # Removing out of date imports - pymodule = self.tools.new_pymodule(pymodule, source) - source = self.tools.remove_old_imports(pymodule) - # Adding new import - if should_import: - pymodule = self.tools.new_pymodule(pymodule, source) - source, imported = importutils.add_import( - self.pycore, pymodule, self._new_modname(dest), self.old_name) - source = source.replace(placeholder, imported) - source = self.tools.new_source(pymodule, source) - if source != file_.read(): - changes.add_change(ChangeContents(file_, source)) - job_set.finished_job() - return changes - - def _source_module_changes(self, dest): - placeholder = '__rope_moving_%s_' % self.old_name - handle = _ChangeMoveOccurrencesHandle(placeholder) - occurrence_finder = occurrences.create_finder( - self.pycore, self.old_name, self.old_pyname) - start, end = self._get_moving_region() - renamer = ModuleSkipRenamer(occurrence_finder, self.source, - handle, start, end) - source = renamer.get_changed_module() - if handle.occurred: - pymodule = self.pycore.get_string_module(source, self.source) - # Adding new import - source, imported = importutils.add_import( - self.pycore, pymodule, self._new_modname(dest), self.old_name) - source = source.replace(placeholder, imported) - return ChangeContents(self.source, source) - - def _new_modname(self, dest): - return self.pycore.modname(dest) - - def _dest_module_changes(self, dest): - # Changing occurrences - pymodule = self.pycore.resource_to_pyobject(dest) - source = self.tools.rename_in_module(self.old_name, pymodule) - pymodule = self.tools.new_pymodule(pymodule, source) - - moving, imports = self._get_moving_element_with_imports() - source = self.tools.remove_old_imports(pymodule) - pymodule = self.tools.new_pymodule(pymodule, source) - pymodule, has_changed = self._add_imports2(pymodule, imports) - - module_with_imports = self.import_tools.module_imports(pymodule) - source = pymodule.source_code - lineno = 0 - if module_with_imports.imports: - lineno = module_with_imports.imports[-1].end_line - 1 - else: - while lineno < pymodule.lines.length() and \ - pymodule.lines.get_line(lineno + 1).lstrip().startswith('#'): - lineno += 1 - if lineno > 0: - cut = pymodule.lines.get_line_end(lineno) + 1 - result = source[:cut] + '\n\n' + moving + source[cut:] - else: - result = moving + source - - # Organizing imports - source = result - pymodule = self.pycore.get_string_module(source, dest) - source = self.import_tools.organize_imports(pymodule, sort=False, - unused=False) - return ChangeContents(dest, source) - - def _get_moving_element_with_imports(self): - return moving_code_with_imports( - self.pycore, self.source, self._get_moving_element()) - - def _get_module_with_imports(self, source_code, resource): - pymodule = self.pycore.get_string_module(source_code, resource) - return self.import_tools.module_imports(pymodule) - - def _get_moving_element(self): - start, end = self._get_moving_region() - moving = self.source.read()[start:end] - return moving.rstrip() + '\n' - - def _get_moving_region(self): - pymodule = self.pycore.resource_to_pyobject(self.source) - lines = pymodule.lines - scope = self.old_pyname.get_object().get_scope() - start = lines.get_line_start(scope.get_start()) - end_line = scope.get_end() - while end_line < lines.length() and \ - lines.get_line(end_line + 1).strip() == '': - end_line += 1 - end = min(lines.get_line_end(end_line) + 1, len(pymodule.source_code)) - return start, end - - def _add_imports2(self, pymodule, new_imports): - source = self.tools.add_imports(pymodule, new_imports) - if source is None: - return pymodule, False - else: - resource = pymodule.get_resource() - pymodule = self.pycore.get_string_module(source, resource) - return pymodule, True - - -class MoveModule(object): - """For moving modules and packages""" - - def __init__(self, project, resource): - self.project = project - self.pycore = project.pycore - if not resource.is_folder() and resource.name == '__init__.py': - resource = resource.parent - if resource.is_folder() and not resource.has_child('__init__.py'): - raise exceptions.RefactoringError( - 'Cannot move non-package folder.') - dummy_pymodule = self.pycore.get_string_module('') - self.old_pyname = pynames.ImportedModule(dummy_pymodule, - resource=resource) - self.source = self.old_pyname.get_object().get_resource() - if self.source.is_folder(): - self.old_name = self.source.name - else: - self.old_name = self.source.name[:-3] - self.tools = _MoveTools(self.pycore, self.source, - self.old_pyname, self.old_name) - self.import_tools = self.tools.import_tools - - def get_changes(self, dest, resources=None, - task_handle=taskhandle.NullTaskHandle()): - moving_pyobject = self.old_pyname.get_object() - if resources is None: - resources = self.pycore.get_python_files() - if dest is None or not dest.is_folder(): - raise exceptions.RefactoringError( - 'Move destination for modules should be packages.') - return self._calculate_changes(dest, resources, task_handle) - - def _calculate_changes(self, dest, resources, task_handle): - changes = ChangeSet('Moving module <%s>' % self.old_name) - job_set = task_handle.create_jobset('Collecting changes', - len(resources)) - for module in resources: - job_set.started_job(module.path) - if module == self.source: - self._change_moving_module(changes, dest) - else: - source = self._change_occurrences_in_module(dest, - resource=module) - if source is not None: - changes.add_change(ChangeContents(module, source)) - job_set.finished_job() - if self.project == self.source.project: - changes.add_change(MoveResource(self.source, dest.path)) - return changes - - def _new_modname(self, dest): - destname = self.pycore.modname(dest) - if destname: - return destname + '.' + self.old_name - return self.old_name - - def _new_import(self, dest): - return importutils.NormalImport([(self._new_modname(dest), None)]) - - def _change_moving_module(self, changes, dest): - if not self.source.is_folder(): - pymodule = self.pycore.resource_to_pyobject(self.source) - source = self.import_tools.relatives_to_absolutes(pymodule) - pymodule = self.tools.new_pymodule(pymodule, source) - source = self._change_occurrences_in_module(dest, pymodule) - source = self.tools.new_source(pymodule, source) - if source != self.source.read(): - changes.add_change(ChangeContents(self.source, source)) - - def _change_occurrences_in_module(self, dest, pymodule=None, - resource=None): - if not self.tools.occurs_in_module(pymodule=pymodule, - resource=resource): - return - if pymodule is None: - pymodule = self.pycore.resource_to_pyobject(resource) - new_name = self._new_modname(dest) - new_import = self._new_import(dest) - source = self.tools.rename_in_module( - new_name, imports=True, pymodule=pymodule, resource=resource) - should_import = self.tools.occurs_in_module( - pymodule=pymodule, resource=resource, imports=False) - pymodule = self.tools.new_pymodule(pymodule, source) - source = self.tools.remove_old_imports(pymodule) - if should_import: - pymodule = self.tools.new_pymodule(pymodule, source) - source = self.tools.add_imports(pymodule, [new_import]) - source = self.tools.new_source(pymodule, source) - if source != pymodule.resource.read(): - return source - - -class _ChangeMoveOccurrencesHandle(object): - - def __init__(self, new_name): - self.new_name = new_name - self.occurred = False - - def occurred_inside_skip(self, change_collector, occurrence): - pass - - def occurred_outside_skip(self, change_collector, occurrence): - start, end = occurrence.get_primary_range() - change_collector.add_change(start, end, self.new_name) - self.occurred = True - - -class _MoveTools(object): - - def __init__(self, pycore, source, pyname, old_name): - self.pycore = pycore - self.source = source - self.old_pyname = pyname - self.old_name = old_name - self.import_tools = importutils.ImportTools(self.pycore) - - def remove_old_imports(self, pymodule): - old_source = pymodule.source_code - module_with_imports = self.import_tools.module_imports(pymodule) - class CanSelect(object): - changed = False - old_name = self.old_name - old_pyname = self.old_pyname - def __call__(self, name): - try: - if name == self.old_name and \ - pymodule[name].get_object() == \ - self.old_pyname.get_object(): - self.changed = True - return False - except exceptions.AttributeNotFoundError: - pass - return True - can_select = CanSelect() - module_with_imports.filter_names(can_select) - new_source = module_with_imports.get_changed_source() - if old_source != new_source: - return new_source - - def rename_in_module(self, new_name, pymodule=None, - imports=False, resource=None): - occurrence_finder = self._create_finder(imports) - source = rename.rename_in_module( - occurrence_finder, new_name, replace_primary=True, - pymodule=pymodule, resource=resource) - return source - - def occurs_in_module(self, pymodule=None, resource=None, imports=True): - finder = self._create_finder(imports) - for occurrence in finder.find_occurrences(pymodule=pymodule, - resource=resource): - return True - return False - - def _create_finder(self, imports): - return occurrences.create_finder(self.pycore, self.old_name, - self.old_pyname, imports=imports) - - def new_pymodule(self, pymodule, source): - if source is not None: - return self.pycore.get_string_module( - source, pymodule.get_resource()) - return pymodule - - def new_source(self, pymodule, source): - if source is None: - return pymodule.source_code - return source - - def add_imports(self, pymodule, new_imports): - return _add_imports_to_module(self.import_tools, pymodule, new_imports) - - -def _add_imports_to_module(import_tools, pymodule, new_imports): - module_with_imports = import_tools.module_imports(pymodule) - for new_import in new_imports: - module_with_imports.add_import(new_import) - return module_with_imports.get_changed_source() - - -def moving_code_with_imports(pycore, resource, source): - import_tools = importutils.ImportTools(pycore) - pymodule = pycore.get_string_module(source, resource) - origin = pycore.resource_to_pyobject(resource) - - imports = [] - for stmt in import_tools.module_imports(origin).imports: - imports.append(stmt.import_info) - - back_names = [] - for name in origin: - if name not in pymodule: - back_names.append(name) - imports.append(import_tools.get_from_import(resource, back_names)) - - source = _add_imports_to_module(import_tools, pymodule, imports) - pymodule = pycore.get_string_module(source, resource) - - source = import_tools.relatives_to_absolutes(pymodule) - pymodule = pycore.get_string_module(source, resource) - source = import_tools.organize_imports(pymodule, selfs=False) - pymodule = pycore.get_string_module(source, resource) - - # extracting imports after changes - module_imports = import_tools.module_imports(pymodule) - imports = [import_stmt.import_info - for import_stmt in module_imports.imports] - start = 1 - if module_imports.imports: - start = module_imports.imports[-1].end_line - lines = codeanalyze.SourceLinesAdapter(source) - while start < lines.length() and not lines.get_line(start).strip(): - start += 1 - moving = source[lines.get_line_start(start):] - return moving, imports - - -class ModuleSkipRenamerHandle(object): - - def occurred_outside_skip(self, change_collector, occurrence): - pass - - def occurred_inside_skip(self, change_collector, occurrence): - pass - - -class ModuleSkipRenamer(object): - """Rename occurrences in a module - - This class can be used when you want to treat a region in a file - separately from other parts when renaming. - - """ - - def __init__(self, occurrence_finder, resource, handle=None, - skip_start=0, skip_end=0, replacement=''): - """Constructor - - if replacement is `None` the region is not changed. Otherwise - it is replaced with `replacement`. - - """ - self.occurrence_finder = occurrence_finder - self.resource = resource - self.skip_start = skip_start - self.skip_end = skip_end - self.replacement = replacement - self.handle = handle - if self.handle is None: - self.handle = ModuleSkipHandle() - - def get_changed_module(self): - source = self.resource.read() - change_collector = codeanalyze.ChangeCollector(source) - if self.replacement is not None: - change_collector.add_change(self.skip_start, self.skip_end, - self.replacement) - for occurrence in self.occurrence_finder.find_occurrences(self.resource): - start, end = occurrence.get_primary_range() - if self.skip_start <= start < self.skip_end: - self.handle.occurred_inside_skip(change_collector, occurrence) - else: - self.handle.occurred_outside_skip(change_collector, occurrence) - result = change_collector.get_changed() - if result is not None and result != source: - return result diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/multiproject.py b/.vim/bundle/python-mode/pylibs/rope/refactor/multiproject.py @@ -1,78 +0,0 @@ -"""This module can be used for performing cross-project refactorings - -See the "cross-project refactorings" section of ``docs/library.txt`` -file. - -""" - -from rope.base import resources, project, libutils - - -class MultiProjectRefactoring(object): - - def __init__(self, refactoring, projects, addpath=True): - """Create a multiproject proxy for the main refactoring - - `projects` are other project. - - """ - self.refactoring = refactoring - self.projects = projects - self.addpath = addpath - - def __call__(self, project, *args, **kwds): - """Create the refactoring""" - return _MultiRefactoring(self.refactoring, self.projects, - self.addpath, project, *args, **kwds) - - -class _MultiRefactoring(object): - - def __init__(self, refactoring, other_projects, addpath, - project, *args, **kwds): - self.refactoring = refactoring - self.projects = [project] + other_projects - for other_project in other_projects: - for folder in self.project.pycore.get_source_folders(): - other_project.get_prefs().add('python_path', folder.real_path) - self.refactorings = [] - for other in self.projects: - args, kwds = self._resources_for_args(other, args, kwds) - self.refactorings.append( - self.refactoring(other, *args, **kwds)) - - def get_all_changes(self, *args, **kwds): - """Get a project to changes dict""" - result = [] - for project, refactoring in zip(self.projects, self.refactorings): - args, kwds = self._resources_for_args(project, args, kwds) - result.append((project, refactoring.get_changes(*args, **kwds))) - return result - - def __getattr__(self, name): - return getattr(self.main_refactoring, name) - - def _resources_for_args(self, project, args, kwds): - newargs = [self._change_project_resource(project, arg) for arg in args] - newkwds = dict((name, self._change_project_resource(project, value)) - for name, value in kwds.items()) - return newargs, newkwds - - def _change_project_resource(self, project, obj): - if isinstance(obj, resources.Resource) and \ - obj.project != project: - return libutils.path_to_resource(project, obj.real_path) - return obj - - @property - def project(self): - return self.projects[0] - - @property - def main_refactoring(self): - return self.refactorings[0] - - -def perform(project_changes): - for project, changes in project_changes: - project.do(changes) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/occurrences.py b/.vim/bundle/python-mode/pylibs/rope/refactor/occurrences.py @@ -1,334 +0,0 @@ -import re - -import rope.base.pynames -from rope.base import pynames, pyobjects, codeanalyze, evaluate, exceptions, utils, worder - - -class Finder(object): - """For finding occurrences of a name - - The constructor takes a `filters` argument. It should be a list - of functions that take a single argument. For each possible - occurrence, these functions are called in order with the an - instance of `Occurrence`: - - * If it returns `None` other filters are tried. - * If it returns `True`, the occurrence will be a match. - * If it returns `False`, the occurrence will be skipped. - * If all of the filters return `None`, it is skipped also. - - """ - - def __init__(self, pycore, name, filters=[lambda o: True], docs=False): - self.pycore = pycore - self.name = name - self.docs = docs - self.filters = filters - self._textual_finder = _TextualFinder(name, docs=docs) - - def find_occurrences(self, resource=None, pymodule=None): - """Generate `Occurrence` instances""" - tools = _OccurrenceToolsCreator(self.pycore, resource=resource, - pymodule=pymodule, docs=self.docs) - for offset in self._textual_finder.find_offsets(tools.source_code): - occurrence = Occurrence(tools, offset) - for filter in self.filters: - result = filter(occurrence) - if result is None: - continue - if result: - yield occurrence - break - - -def create_finder(pycore, name, pyname, only_calls=False, imports=True, - unsure=None, docs=False, instance=None, in_hierarchy=False): - """A factory for `Finder` - - Based on the arguments it creates a list of filters. `instance` - argument is needed only when you want implicit interfaces to be - considered. - - """ - pynames = set([pyname]) - filters = [] - if only_calls: - filters.append(CallsFilter()) - if not imports: - filters.append(NoImportsFilter()) - if isinstance(instance, rope.base.pynames.ParameterName): - for pyobject in instance.get_objects(): - try: - pynames.add(pyobject[name]) - except exceptions.AttributeNotFoundError: - pass - for pyname in pynames: - filters.append(PyNameFilter(pyname)) - if in_hierarchy: - filters.append(InHierarchyFilter(pyname)) - if unsure: - filters.append(UnsureFilter(unsure)) - return Finder(pycore, name, filters=filters, docs=docs) - - -class Occurrence(object): - - def __init__(self, tools, offset): - self.tools = tools - self.offset = offset - self.resource = tools.resource - - @utils.saveit - def get_word_range(self): - return self.tools.word_finder.get_word_range(self.offset) - - @utils.saveit - def get_primary_range(self): - return self.tools.word_finder.get_primary_range(self.offset) - - @utils.saveit - def get_pyname(self): - try: - return self.tools.name_finder.get_pyname_at(self.offset) - except exceptions.BadIdentifierError: - pass - - @utils.saveit - def get_primary_and_pyname(self): - try: - return self.tools.name_finder.get_primary_and_pyname_at(self.offset) - except exceptions.BadIdentifierError: - pass - - @utils.saveit - def is_in_import_statement(self): - return (self.tools.word_finder.is_from_statement(self.offset) or - self.tools.word_finder.is_import_statement(self.offset)) - - def is_called(self): - return self.tools.word_finder.is_a_function_being_called(self.offset) - - def is_defined(self): - return self.tools.word_finder.is_a_class_or_function_name_in_header(self.offset) - - def is_a_fixed_primary(self): - return self.tools.word_finder.is_a_class_or_function_name_in_header(self.offset) or \ - self.tools.word_finder.is_a_name_after_from_import(self.offset) - - def is_written(self): - return self.tools.word_finder.is_assigned_here(self.offset) - - def is_unsure(self): - return unsure_pyname(self.get_pyname()) - - @property - @utils.saveit - def lineno(self): - offset = self.get_word_range()[0] - return self.tools.pymodule.lines.get_line_number(offset) - - -def same_pyname(expected, pyname): - """Check whether `expected` and `pyname` are the same""" - if expected is None or pyname is None: - return False - if expected == pyname: - return True - if type(expected) not in (pynames.ImportedModule, pynames.ImportedName) and \ - type(pyname) not in (pynames.ImportedModule, pynames.ImportedName): - return False - return expected.get_definition_location() == pyname.get_definition_location() and \ - expected.get_object() == pyname.get_object() - -def unsure_pyname(pyname, unbound=True): - """Return `True` if we don't know what this name references""" - if pyname is None: - return True - if unbound and not isinstance(pyname, pynames.UnboundName): - return False - if pyname.get_object() == pyobjects.get_unknown(): - return True - - -class PyNameFilter(object): - """For finding occurrences of a name""" - - def __init__(self, pyname): - self.pyname = pyname - - def __call__(self, occurrence): - if same_pyname(self.pyname, occurrence.get_pyname()): - return True - - -class InHierarchyFilter(object): - """For finding occurrences of a name""" - - def __init__(self, pyname, implementations_only=False): - self.pyname = pyname - self.impl_only = implementations_only - self.pyclass = self._get_containing_class(pyname) - if self.pyclass is not None: - self.name = pyname.get_object().get_name() - self.roots = self._get_root_classes(self.pyclass, self.name) - else: - self.roots = None - - def __call__(self, occurrence): - if self.roots is None: - return - pyclass = self._get_containing_class(occurrence.get_pyname()) - if pyclass is not None: - roots = self._get_root_classes(pyclass, self.name) - if self.roots.intersection(roots): - return True - - def _get_containing_class(self, pyname): - if isinstance(pyname, pynames.DefinedName): - scope = pyname.get_object().get_scope() - parent = scope.parent - if parent is not None and parent.get_kind() == 'Class': - return parent.pyobject - - def _get_root_classes(self, pyclass, name): - if self.impl_only and pyclass == self.pyclass: - return set([pyclass]) - result = set() - for superclass in pyclass.get_superclasses(): - if name in superclass: - result.update(self._get_root_classes(superclass, name)) - if not result: - return set([pyclass]) - return result - - -class UnsureFilter(object): - - def __init__(self, unsure): - self.unsure = unsure - - def __call__(self, occurrence): - if occurrence.is_unsure() and self.unsure(occurrence): - return True - - -class NoImportsFilter(object): - - def __call__(self, occurrence): - if occurrence.is_in_import_statement(): - return False - - -class CallsFilter(object): - - def __call__(self, occurrence): - if not occurrence.is_called(): - return False - - -class _TextualFinder(object): - - def __init__(self, name, docs=False): - self.name = name - self.docs = docs - self.comment_pattern = _TextualFinder.any('comment', [r'#[^\n]*']) - self.string_pattern = _TextualFinder.any( - 'string', [codeanalyze.get_string_pattern()]) - self.pattern = self._get_occurrence_pattern(self.name) - - def find_offsets(self, source): - if not self._fast_file_query(source): - return - if self.docs: - searcher = self._normal_search - else: - searcher = self._re_search - for matched in searcher(source): - yield matched - - def _re_search(self, source): - for match in self.pattern.finditer(source): - for key, value in match.groupdict().items(): - if value and key == 'occurrence': - yield match.start(key) - - def _normal_search(self, source): - current = 0 - while True: - try: - found = source.index(self.name, current) - current = found + len(self.name) - if (found == 0 or not self._is_id_char(source[found - 1])) and \ - (current == len(source) or not self._is_id_char(source[current])): - yield found - except ValueError: - break - - def _is_id_char(self, c): - return c.isalnum() or c == '_' - - def _fast_file_query(self, source): - try: - source.index(self.name) - return True - except ValueError: - return False - - def _get_source(self, resource, pymodule): - if resource is not None: - return resource.read() - else: - return pymodule.source_code - - def _get_occurrence_pattern(self, name): - occurrence_pattern = _TextualFinder.any('occurrence', - ['\\b' + name + '\\b']) - pattern = re.compile(occurrence_pattern + '|' + self.comment_pattern + - '|' + self.string_pattern) - return pattern - - @staticmethod - def any(name, list_): - return '(?P<%s>' % name + '|'.join(list_) + ')' - - -class _OccurrenceToolsCreator(object): - - def __init__(self, pycore, resource=None, pymodule=None, docs=False): - self.pycore = pycore - self.__resource = resource - self.__pymodule = pymodule - self.docs = docs - - @property - @utils.saveit - def name_finder(self): - return evaluate.ScopeNameFinder(self.pymodule) - - @property - @utils.saveit - def source_code(self): - if self.__resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - @property - @utils.saveit - def word_finder(self): - return worder.Worder(self.source_code, self.docs) - - @property - @utils.saveit - def resource(self): - if self.__resource is not None: - return self.__resource - if self.__pymodule is not None: - return self.__pymodule.resource - - @property - @utils.saveit - def pymodule(self): - if self.__pymodule is not None: - return self.__pymodule - return self.pycore.resource_to_pyobject(self.resource) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/patchedast.py b/.vim/bundle/python-mode/pylibs/rope/refactor/patchedast.py @@ -1,734 +0,0 @@ -import collections -import re -import warnings - -from rope.base import ast, codeanalyze, exceptions - - -def get_patched_ast(source, sorted_children=False): - """Adds ``region`` and ``sorted_children`` fields to nodes - - Adds ``sorted_children`` field only if `sorted_children` is True. - - """ - return patch_ast(ast.parse(source), source, sorted_children) - - -def patch_ast(node, source, sorted_children=False): - """Patches the given node - - After calling, each node in `node` will have a new field named - `region` that is a tuple containing the start and end offsets - of the code that generated it. - - If `sorted_children` is true, a `sorted_children` field will - be created for each node, too. It is a list containing child - nodes as well as whitespaces and comments that occur between - them. - - """ - if hasattr(node, 'region'): - return node - walker = _PatchingASTWalker(source, children=sorted_children) - ast.call_for_nodes(node, walker) - return node - - -def node_region(patched_ast_node): - """Get the region of a patched ast node""" - return patched_ast_node.region - - -def write_ast(patched_ast_node): - """Extract source form a patched AST node with `sorted_children` field - - If the node is patched with sorted_children turned off you can use - `node_region` function for obtaining code using module source code. - """ - result = [] - for child in patched_ast_node.sorted_children: - if isinstance(child, ast.AST): - result.append(write_ast(child)) - else: - result.append(child) - return ''.join(result) - - -class MismatchedTokenError(exceptions.RopeError): - pass - - -class _PatchingASTWalker(object): - - def __init__(self, source, children=False): - self.source = _Source(source) - self.children = children - self.lines = codeanalyze.SourceLinesAdapter(source) - self.children_stack = [] - - Number = object() - String = object() - - def __call__(self, node): - method = getattr(self, '_' + node.__class__.__name__, None) - if method is not None: - return method(node) - # ???: Unknown node; what should we do here? - warnings.warn('Unknown node type <%s>; please report!' - % node.__class__.__name__, RuntimeWarning) - node.region = (self.source.offset, self.source.offset) - if self.children: - node.sorted_children = ast.get_children(node) - - def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): - if hasattr(node, 'region'): - # ???: The same node was seen twice; what should we do? - warnings.warn( - 'Node <%s> has been already patched; please report!' % - node.__class__.__name__, RuntimeWarning) - return - base_children = collections.deque(base_children) - self.children_stack.append(base_children) - children = collections.deque() - formats = [] - suspected_start = self.source.offset - start = suspected_start - first_token = True - while base_children: - child = base_children.popleft() - if child is None: - continue - offset = self.source.offset - if isinstance(child, ast.AST): - ast.call_for_nodes(child, self) - token_start = child.region[0] - else: - if child is self.String: - region = self.source.consume_string( - end=self._find_next_statement_start()) - elif child is self.Number: - region = self.source.consume_number() - elif child == '!=': - # INFO: This has been added to handle deprecated ``<>`` - region = self.source.consume_not_equal() - else: - region = self.source.consume(child) - child = self.source[region[0]:region[1]] - token_start = region[0] - if not first_token: - formats.append(self.source[offset:token_start]) - if self.children: - children.append(self.source[offset:token_start]) - else: - first_token = False - start = token_start - if self.children: - children.append(child) - start = self._handle_parens(children, start, formats) - if eat_parens: - start = self._eat_surrounding_parens( - children, suspected_start, start) - if eat_spaces: - if self.children: - children.appendleft(self.source[0:start]) - end_spaces = self.source[self.source.offset:] - self.source.consume(end_spaces) - if self.children: - children.append(end_spaces) - start = 0 - if self.children: - node.sorted_children = children - node.region = (start, self.source.offset) - self.children_stack.pop() - - def _handle_parens(self, children, start, formats): - """Changes `children` and returns new start""" - opens, closes = self._count_needed_parens(formats) - old_end = self.source.offset - new_end = None - for i in range(closes): - new_end = self.source.consume(')')[1] - if new_end is not None: - if self.children: - children.append(self.source[old_end:new_end]) - new_start = start - for i in range(opens): - new_start = self.source.rfind_token('(', 0, new_start) - if new_start != start: - if self.children: - children.appendleft(self.source[new_start:start]) - start = new_start - return start - - def _eat_surrounding_parens(self, children, suspected_start, start): - index = self.source.rfind_token('(', suspected_start, start) - if index is not None: - old_start = start - old_offset = self.source.offset - start = index - if self.children: - children.appendleft(self.source[start + 1:old_start]) - children.appendleft('(') - token_start, token_end = self.source.consume(')') - if self.children: - children.append(self.source[old_offset:token_start]) - children.append(')') - return start - - def _count_needed_parens(self, children): - start = 0 - opens = 0 - for child in children: - if not isinstance(child, basestring): - continue - if child == '' or child[0] in '\'"': - continue - index = 0 - while index < len(child): - if child[index] == ')': - if opens > 0: - opens -= 1 - else: - start += 1 - if child[index] == '(': - opens += 1 - if child[index] == '#': - try: - index = child.index('\n', index) - except ValueError: - break - index += 1 - return start, opens - - def _find_next_statement_start(self): - for children in reversed(self.children_stack): - for child in children: - if isinstance(child, ast.stmt): - return child.col_offset \ - + self.lines.get_line_start(child.lineno) - return len(self.source.source) - - _operators = {'And': 'and', 'Or': 'or', 'Add': '+', 'Sub': '-', 'Mult': '*', - 'Div': '/', 'Mod': '%', 'Pow': '**', 'LShift': '<<', - 'RShift': '>>', 'BitOr': '|', 'BitAnd': '&', 'BitXor': '^', - 'FloorDiv': '//', 'Invert': '~', 'Not': 'not', 'UAdd': '+', - 'USub': '-', 'Eq': '==', 'NotEq': '!=', 'Lt': '<', - 'LtE': '<=', 'Gt': '>', 'GtE': '>=', 'Is': 'is', - 'IsNot': 'is not', 'In': 'in', 'NotIn': 'not in'} - - def _get_op(self, node): - return self._operators[node.__class__.__name__].split(' ') - - def _Attribute(self, node): - self._handle(node, [node.value, '.', node.attr]) - - def _Assert(self, node): - children = ['assert', node.test] - if node.msg: - children.append(',') - children.append(node.msg) - self._handle(node, children) - - def _Assign(self, node): - children = self._child_nodes(node.targets, '=') - children.append('=') - children.append(node.value) - self._handle(node, children) - - def _AugAssign(self, node): - children = [node.target] - children.extend(self._get_op(node.op)) - children.extend(['=', node.value]) - self._handle(node, children) - - def _Repr(self, node): - self._handle(node, ['`', node.value, '`']) - - def _BinOp(self, node): - children = [node.left] + self._get_op(node.op) + [node.right] - self._handle(node, children) - - def _BoolOp(self, node): - self._handle(node, self._child_nodes(node.values, - self._get_op(node.op)[0])) - - def _Break(self, node): - self._handle(node, ['break']) - - def _Call(self, node): - children = [node.func, '('] - args = list(node.args) + node.keywords - children.extend(self._child_nodes(args, ',')) - if node.starargs is not None: - if args: - children.append(',') - children.extend(['*', node.starargs]) - if node.kwargs is not None: - if args or node.starargs is not None: - children.append(',') - children.extend(['**', node.kwargs]) - children.append(')') - self._handle(node, children) - - def _ClassDef(self, node): - children = [] - if getattr(node, 'decorator_list', None): - for decorator in node.decorator_list: - children.append('@') - children.append(decorator) - children.extend(['class', node.name]) - if node.bases: - children.append('(') - children.extend(self._child_nodes(node.bases, ',')) - children.append(')') - children.append(':') - children.extend(node.body) - self._handle(node, children) - - def _Compare(self, node): - children = [] - children.append(node.left) - for op, expr in zip(node.ops, node.comparators): - children.extend(self._get_op(op)) - children.append(expr) - self._handle(node, children) - - def _Delete(self, node): - self._handle(node, ['del'] + self._child_nodes(node.targets, ',')) - - def _Num(self, node): - self._handle(node, [self.Number]) - - def _Str(self, node): - self._handle(node, [self.String]) - - def _Continue(self, node): - self._handle(node, ['continue']) - - def _Dict(self, node): - children = [] - children.append('{') - if node.keys: - for index, (key, value) in enumerate(zip(node.keys, node.values)): - children.extend([key, ':', value]) - if index < len(node.keys) - 1: - children.append(',') - children.append('}') - self._handle(node, children) - - def _Ellipsis(self, node): - self._handle(node, ['...']) - - def _Expr(self, node): - self._handle(node, [node.value]) - - def _Exec(self, node): - children = [] - children.extend(['exec', node.body]) - if node.globals: - children.extend(['in', node.globals]) - if node.locals: - children.extend([',', node.locals]) - self._handle(node, children) - - def _ExtSlice(self, node): - children = [] - for index, dim in enumerate(node.dims): - if index > 0: - children.append(',') - children.append(dim) - self._handle(node, children) - - def _For(self, node): - children = ['for', node.target, 'in', node.iter, ':'] - children.extend(node.body) - if node.orelse: - children.extend(['else', ':']) - children.extend(node.orelse) - self._handle(node, children) - - def _ImportFrom(self, node): - children = ['from'] - if node.level: - children.append('.' * node.level) - children.extend([node.module or '', # see comment at rope.base.ast.walk - 'import']) - children.extend(self._child_nodes(node.names, ',')) - self._handle(node, children) - - def _alias(self, node): - children = [node.name] - if node.asname: - children.extend(['as', node.asname]) - self._handle(node, children) - - def _FunctionDef(self, node): - children = [] - try: - decorators = getattr(node, 'decorator_list') - except AttributeError: - decorators = getattr(node, 'decorators', None) - if decorators: - for decorator in decorators: - children.append('@') - children.append(decorator) - children.extend(['def', node.name, '(', node.args]) - children.extend([')', ':']) - children.extend(node.body) - self._handle(node, children) - - def _arguments(self, node): - children = [] - args = list(node.args) - defaults = [None] * (len(args) - len(node.defaults)) + list(node.defaults) - for index, (arg, default) in enumerate(zip(args, defaults)): - if index > 0: - children.append(',') - self._add_args_to_children(children, arg, default) - if node.vararg is not None: - if args: - children.append(',') - children.extend(['*', node.vararg]) - if node.kwarg is not None: - if args or node.vararg is not None: - children.append(',') - children.extend(['**', node.kwarg]) - self._handle(node, children) - - def _add_args_to_children(self, children, arg, default): - if isinstance(arg, (list, tuple)): - self._add_tuple_parameter(children, arg) - else: - children.append(arg) - if default is not None: - children.append('=') - children.append(default) - - def _add_tuple_parameter(self, children, arg): - children.append('(') - for index, token in enumerate(arg): - if index > 0: - children.append(',') - if isinstance(token, (list, tuple)): - self._add_tuple_parameter(children, token) - else: - children.append(token) - children.append(')') - - def _GeneratorExp(self, node): - children = [node.elt] - children.extend(node.generators) - self._handle(node, children, eat_parens=True) - - def _comprehension(self, node): - children = ['for', node.target, 'in', node.iter] - if node.ifs: - for if_ in node.ifs: - children.append('if') - children.append(if_) - self._handle(node, children) - - def _Global(self, node): - children = self._child_nodes(node.names, ',') - children.insert(0, 'global') - self._handle(node, children) - - def _If(self, node): - if self._is_elif(node): - children = ['elif'] - else: - children = ['if'] - children.extend([node.test, ':']) - children.extend(node.body) - if node.orelse: - if len(node.orelse) == 1 and self._is_elif(node.orelse[0]): - pass - else: - children.extend(['else', ':']) - children.extend(node.orelse) - self._handle(node, children) - - def _is_elif(self, node): - if not isinstance(node, ast.If): - return False - offset = self.lines.get_line_start(node.lineno) + node.col_offset - word = self.source[offset:offset + 4] - # XXX: This is a bug; the offset does not point to the first - alt_word = self.source[offset - 5:offset - 1] - return 'elif' in (word, alt_word) - - def _IfExp(self, node): - return self._handle(node, [node.body, 'if', node.test, - 'else', node.orelse]) - - def _Import(self, node): - children = ['import'] - children.extend(self._child_nodes(node.names, ',')) - self._handle(node, children) - - def _keyword(self, node): - self._handle(node, [node.arg, '=', node.value]) - - def _Lambda(self, node): - self._handle(node, ['lambda', node.args, ':', node.body]) - - def _List(self, node): - self._handle(node, ['['] + self._child_nodes(node.elts, ',') + [']']) - - def _ListComp(self, node): - children = ['[', node.elt] - children.extend(node.generators) - children.append(']') - self._handle(node, children) - - def _Module(self, node): - self._handle(node, list(node.body), eat_spaces=True) - - def _Name(self, node): - self._handle(node, [node.id]) - - def _Pass(self, node): - self._handle(node, ['pass']) - - def _Print(self, node): - children = ['print'] - if node.dest: - children.extend(['>>', node.dest]) - if node.values: - children.append(',') - children.extend(self._child_nodes(node.values, ',')) - if not node.nl: - children.append(',') - self._handle(node, children) - - def _Raise(self, node): - children = ['raise'] - if node.type: - children.append(node.type) - if node.inst: - children.append(',') - children.append(node.inst) - if node.tback: - children.append(',') - children.append(node.tback) - self._handle(node, children) - - def _Return(self, node): - children = ['return'] - if node.value: - children.append(node.value) - self._handle(node, children) - - def _Sliceobj(self, node): - children = [] - for index, slice in enumerate(node.nodes): - if index > 0: - children.append(':') - if slice: - children.append(slice) - self._handle(node, children) - - def _Index(self, node): - self._handle(node, [node.value]) - - def _Subscript(self, node): - self._handle(node, [node.value, '[', node.slice, ']']) - - def _Slice(self, node): - children = [] - if node.lower: - children.append(node.lower) - children.append(':') - if node.upper: - children.append(node.upper) - if node.step: - children.append(':') - children.append(node.step) - self._handle(node, children) - - def _TryFinally(self, node): - children = [] - if len(node.body) != 1 or not isinstance(node.body[0], ast.TryExcept): - children.extend(['try', ':']) - children.extend(node.body) - children.extend(['finally', ':']) - children.extend(node.finalbody) - self._handle(node, children) - - def _TryExcept(self, node): - children = ['try', ':'] - children.extend(node.body) - children.extend(node.handlers) - if node.orelse: - children.extend(['else', ':']) - children.extend(node.orelse) - self._handle(node, children) - - def _ExceptHandler(self, node): - self._excepthandler(node) - - def _excepthandler(self, node): - children = ['except'] - if node.type: - children.append(node.type) - if node.name: - children.extend([',', node.name]) - children.append(':') - children.extend(node.body) - self._handle(node, children) - - def _Tuple(self, node): - if node.elts: - self._handle(node, self._child_nodes(node.elts, ','), - eat_parens=True) - else: - self._handle(node, ['(', ')']) - - def _UnaryOp(self, node): - children = self._get_op(node.op) - children.append(node.operand) - self._handle(node, children) - - def _Yield(self, node): - children = ['yield'] - if node.value: - children.append(node.value) - self._handle(node, children) - - def _While(self, node): - children = ['while', node.test, ':'] - children.extend(node.body) - if node.orelse: - children.extend(['else', ':']) - children.extend(node.orelse) - self._handle(node, children) - - def _With(self, node): - children = ['with', node.context_expr] - if node.optional_vars: - children.extend(['as', node.optional_vars]) - children.append(':') - children.extend(node.body) - self._handle(node, children) - - def _child_nodes(self, nodes, separator): - children = [] - for index, child in enumerate(nodes): - children.append(child) - if index < len(nodes) - 1: - children.append(separator) - return children - - -class _Source(object): - - def __init__(self, source): - self.source = source - self.offset = 0 - - def consume(self, token): - try: - while True: - new_offset = self.source.index(token, self.offset) - if self._good_token(token, new_offset): - break - else: - self._skip_comment() - except (ValueError, TypeError): - raise MismatchedTokenError( - 'Token <%s> at %s cannot be matched' % - (token, self._get_location())) - self.offset = new_offset + len(token) - return (new_offset, self.offset) - - def consume_string(self, end=None): - if _Source._string_pattern is None: - original = codeanalyze.get_string_pattern() - pattern = r'(%s)((\s|\\\n|#[^\n]*\n)*(%s))*' % \ - (original, original) - _Source._string_pattern = re.compile(pattern) - repattern = _Source._string_pattern - return self._consume_pattern(repattern, end) - - def consume_number(self): - if _Source._number_pattern is None: - _Source._number_pattern = re.compile( - self._get_number_pattern()) - repattern = _Source._number_pattern - return self._consume_pattern(repattern) - - def consume_not_equal(self): - if _Source._not_equals_pattern is None: - _Source._not_equals_pattern = re.compile(r'<>|!=') - repattern = _Source._not_equals_pattern - return self._consume_pattern(repattern) - - def _good_token(self, token, offset, start=None): - """Checks whether consumed token is in comments""" - if start is None: - start = self.offset - try: - comment_index = self.source.rindex('#', start, offset) - except ValueError: - return True - try: - new_line_index = self.source.rindex('\n', start, offset) - except ValueError: - return False - return comment_index < new_line_index - - def _skip_comment(self): - self.offset = self.source.index('\n', self.offset + 1) - - def _get_location(self): - lines = self.source[:self.offset].split('\n') - return (len(lines), len(lines[-1])) - - def _consume_pattern(self, repattern, end=None): - while True: - if end is None: - end = len(self.source) - match = repattern.search(self.source, self.offset, end) - if self._good_token(match.group(), match.start()): - break - else: - self._skip_comment() - self.offset = match.end() - return match.start(), match.end() - - def till_token(self, token): - new_offset = self.source.index(token, self.offset) - return self[self.offset:new_offset] - - def rfind_token(self, token, start, end): - index = start - while True: - try: - index = self.source.rindex(token, start, end) - if self._good_token(token, index, start=start): - return index - else: - end = index - except ValueError: - return None - - def from_offset(self, offset): - return self[offset:self.offset] - - def find_backwards(self, pattern, offset): - return self.source.rindex(pattern, 0, offset) - - def __getitem__(self, index): - return self.source[index] - - def __getslice__(self, i, j): - return self.source[i:j] - - def _get_number_pattern(self): - # HACK: It is merely an approaximation and does the job - integer = r'(0|0x)?[\da-fA-F]+[lL]?' - return r'(%s(\.\d*)?|(\.\d+))([eE][-+]?\d*)?[jJ]?' % integer - - _string_pattern = None - _number_pattern = None - _not_equals_pattern = None diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/rename.py b/.vim/bundle/python-mode/pylibs/rope/refactor/rename.py @@ -1,216 +0,0 @@ -import warnings - -from rope.base import exceptions, pyobjects, pynames, taskhandle, evaluate, worder, codeanalyze -from rope.base.change import ChangeSet, ChangeContents, MoveResource -from rope.refactor import occurrences, sourceutils - - -class Rename(object): - """A class for performing rename refactoring - - It can rename everything: classes, functions, modules, packages, - methods, variables and keyword arguments. - - """ - - def __init__(self, project, resource, offset=None): - """If `offset` is None, the `resource` itself will be renamed""" - self.project = project - self.pycore = project.pycore - self.resource = resource - if offset is not None: - self.old_name = worder.get_name_at(self.resource, offset) - this_pymodule = self.pycore.resource_to_pyobject(self.resource) - self.old_instance, self.old_pyname = \ - evaluate.eval_location2(this_pymodule, offset) - if self.old_pyname is None: - raise exceptions.RefactoringError( - 'Rename refactoring should be performed' - ' on resolvable python identifiers.') - else: - if not resource.is_folder() and resource.name == '__init__.py': - resource = resource.parent - dummy_pymodule = self.pycore.get_string_module('') - self.old_instance = None - self.old_pyname = pynames.ImportedModule(dummy_pymodule, - resource=resource) - if resource.is_folder(): - self.old_name = resource.name - else: - self.old_name = resource.name[:-3] - - def get_old_name(self): - return self.old_name - - def get_changes(self, new_name, in_file=None, in_hierarchy=False, - unsure=None, docs=False, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Get the changes needed for this refactoring - - Parameters: - - - `in_hierarchy`: when renaming a method this keyword forces - to rename all matching methods in the hierarchy - - `docs`: when `True` rename refactoring will rename - occurrences in comments and strings where the name is - visible. Setting it will make renames faster, too. - - `unsure`: decides what to do about unsure occurrences. - If `None`, they are ignored. Otherwise `unsure` is - called with an instance of `occurrence.Occurrence` as - parameter. If it returns `True`, the occurrence is - considered to be a match. - - `resources` can be a list of `rope.base.resources.File`\s to - apply this refactoring on. If `None`, the restructuring - will be applied to all python files. - - `in_file`: this argument has been deprecated; use - `resources` instead. - - """ - if unsure in (True, False): - warnings.warn( - 'unsure parameter should be a function that returns ' - 'True or False', DeprecationWarning, stacklevel=2) - def unsure_func(value=unsure): - return value - unsure = unsure_func - if in_file is not None: - warnings.warn( - '`in_file` argument has been deprecated; use `resources` ' - 'instead. ', DeprecationWarning, stacklevel=2) - if in_file: - resources = [self.resource] - if _is_local(self.old_pyname): - resources = [self.resource] - if resources is None: - resources = self.pycore.get_python_files() - changes = ChangeSet('Renaming <%s> to <%s>' % - (self.old_name, new_name)) - finder = occurrences.create_finder( - self.pycore, self.old_name, self.old_pyname, unsure=unsure, - docs=docs, instance=self.old_instance, - in_hierarchy=in_hierarchy and self.is_method()) - job_set = task_handle.create_jobset('Collecting Changes', len(resources)) - for file_ in resources: - job_set.started_job(file_.path) - new_content = rename_in_module(finder, new_name, resource=file_) - if new_content is not None: - changes.add_change(ChangeContents(file_, new_content)) - job_set.finished_job() - if self._is_renaming_a_module(): - resource = self.old_pyname.get_object().get_resource() - if self._is_allowed_to_move(resources, resource): - self._rename_module(resource, new_name, changes) - return changes - - def _is_allowed_to_move(self, resources, resource): - if resource.is_folder(): - try: - return resource.get_child('__init__.py') in resources - except exceptions.ResourceNotFoundError: - return False - else: - return resource in resources - - def _is_renaming_a_module(self): - if isinstance(self.old_pyname.get_object(), pyobjects.AbstractModule): - return True - return False - - def is_method(self): - pyname = self.old_pyname - return isinstance(pyname, pynames.DefinedName) and \ - isinstance(pyname.get_object(), pyobjects.PyFunction) and \ - isinstance(pyname.get_object().parent, pyobjects.PyClass) - - def _rename_module(self, resource, new_name, changes): - if not resource.is_folder(): - new_name = new_name + '.py' - parent_path = resource.parent.path - if parent_path == '': - new_location = new_name - else: - new_location = parent_path + '/' + new_name - changes.add_change(MoveResource(resource, new_location)) - - -class ChangeOccurrences(object): - """A class for changing the occurrences of a name in a scope - - This class replaces the occurrences of a name. Note that it only - changes the scope containing the offset passed to the constructor. - What's more it does not have any side-effects. That is for - example changing occurrences of a module does not rename the - module; it merely replaces the occurrences of that module in a - scope with the given expression. This class is useful for - performing many custom refactorings. - - """ - - def __init__(self, project, resource, offset): - self.pycore = project.pycore - self.resource = resource - self.offset = offset - self.old_name = worder.get_name_at(resource, offset) - self.pymodule = self.pycore.resource_to_pyobject(self.resource) - self.old_pyname = evaluate.eval_location(self.pymodule, offset) - - def get_old_name(self): - word_finder = worder.Worder(self.resource.read()) - return word_finder.get_primary_at(self.offset) - - def _get_scope_offset(self): - lines = self.pymodule.lines - scope = self.pymodule.get_scope().\ - get_inner_scope_for_line(lines.get_line_number(self.offset)) - start = lines.get_line_start(scope.get_start()) - end = lines.get_line_end(scope.get_end()) - return start, end - - def get_changes(self, new_name, only_calls=False, reads=True, writes=True): - changes = ChangeSet('Changing <%s> occurrences to <%s>' % - (self.old_name, new_name)) - scope_start, scope_end = self._get_scope_offset() - finder = occurrences.create_finder( - self.pycore, self.old_name, self.old_pyname, - imports=False, only_calls=only_calls) - new_contents = rename_in_module( - finder, new_name, pymodule=self.pymodule, replace_primary=True, - region=(scope_start, scope_end), reads=reads, writes=writes) - if new_contents is not None: - changes.add_change(ChangeContents(self.resource, new_contents)) - return changes - - -def rename_in_module(occurrences_finder, new_name, resource=None, pymodule=None, - replace_primary=False, region=None, reads=True, writes=True): - """Returns the changed source or `None` if there is no changes""" - if resource is not None: - source_code = resource.read() - else: - source_code = pymodule.source_code - change_collector = codeanalyze.ChangeCollector(source_code) - for occurrence in occurrences_finder.find_occurrences(resource, pymodule): - if replace_primary and occurrence.is_a_fixed_primary(): - continue - if replace_primary: - start, end = occurrence.get_primary_range() - else: - start, end = occurrence.get_word_range() - if (not reads and not occurrence.is_written()) or \ - (not writes and occurrence.is_written()): - continue - if region is None or region[0] <= start < region[1]: - change_collector.add_change(start, end, new_name) - return change_collector.get_changed() - -def _is_local(pyname): - module, lineno = pyname.get_definition_location() - if lineno is None: - return False - scope = module.get_scope().get_inner_scope_for_line(lineno) - if isinstance(pyname, pynames.DefinedName) and \ - scope.get_kind() in ('Function', 'Class'): - scope = scope.parent - return scope.get_kind() == 'Function' and \ - pyname in scope.get_names().values() and \ - isinstance(pyname, pynames.AssignedName) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/restructure.py b/.vim/bundle/python-mode/pylibs/rope/refactor/restructure.py @@ -1,307 +0,0 @@ -import warnings - -from rope.base import change, taskhandle, builtins, ast, codeanalyze -from rope.refactor import patchedast, similarfinder, sourceutils -from rope.refactor.importutils import module_imports - - -class Restructure(object): - """A class to perform python restructurings - - A restructuring transforms pieces of code matching `pattern` to - `goal`. In the `pattern` wildcards can appear. Wildcards match - some piece of code based on their kind and arguments that are - passed to them through `args`. - - `args` is a dictionary of wildcard names to wildcard arguments. - If the argument is a tuple, the first item of the tuple is - considered to be the name of the wildcard to use; otherwise the - "default" wildcard is used. For getting the list arguments a - wildcard supports, see the pydoc of the wildcard. (see - `rope.refactor.wildcard.DefaultWildcard` for the default - wildcard.) - - `wildcards` is the list of wildcard types that can appear in - `pattern`. See `rope.refactor.wildcards`. If a wildcard does not - specify its kind (by using a tuple in args), the wildcard named - "default" is used. So there should be a wildcard with "default" - name in `wildcards`. - - `imports` is the list of imports that changed modules should - import. Note that rope handles duplicate imports and does not add - the import if it already appears. - - Example #1:: - - pattern ${pyobject}.get_attribute(${name}) - goal ${pyobject}[${name}] - args pyobject: instance=rope.base.pyobjects.PyObject - - Example #2:: - - pattern ${name} in ${pyobject}.get_attributes() - goal ${name} in {pyobject} - args pyobject: instance=rope.base.pyobjects.PyObject - - Example #3:: - - pattern ${pycore}.create_module(${project}.root, ${name}) - goal generate.create_module(${project}, ${name}) - - imports - from rope.contrib import generate - - args - pycore: type=rope.base.pycore.PyCore - project: type=rope.base.project.Project - - Example #4:: - - pattern ${pow}(${param1}, ${param2}) - goal ${param1} ** ${param2} - args pow: name=mod.pow, exact - - Example #5:: - - pattern ${inst}.longtask(${p1}, ${p2}) - goal - ${inst}.subtask1(${p1}) - ${inst}.subtask2(${p2}) - args - inst: type=mod.A,unsure - - """ - - def __init__(self, project, pattern, goal, args=None, - imports=None, wildcards=None): - """Construct a restructuring - - See class pydoc for more info about the arguments. - - """ - self.pycore = project.pycore - self.pattern = pattern - self.goal = goal - self.args = args - if self.args is None: - self.args = {} - self.imports = imports - if self.imports is None: - self.imports = [] - self.wildcards = wildcards - self.template = similarfinder.CodeTemplate(self.goal) - - def get_changes(self, checks=None, imports=None, resources=None, - task_handle=taskhandle.NullTaskHandle()): - """Get the changes needed by this restructuring - - `resources` can be a list of `rope.base.resources.File`\s to - apply the restructuring on. If `None`, the restructuring will - be applied to all python files. - - `checks` argument has been deprecated. Use the `args` argument - of the constructor. The usage of:: - - strchecks = {'obj1.type': 'mod.A', 'obj2': 'mod.B', - 'obj3.object': 'mod.C'} - checks = restructuring.make_checks(strchecks) - - can be replaced with:: - - args = {'obj1': 'type=mod.A', 'obj2': 'name=mod.B', - 'obj3': 'object=mod.C'} - - where obj1, obj2 and obj3 are wildcard names that appear - in restructuring pattern. - - """ - if checks is not None: - warnings.warn( - 'The use of checks parameter is deprecated; ' - 'use the args parameter of the constructor instead.', - DeprecationWarning, stacklevel=2) - for name, value in checks.items(): - self.args[name] = similarfinder._pydefined_to_str(value) - if imports is not None: - warnings.warn( - 'The use of imports parameter is deprecated; ' - 'use imports parameter of the constructor, instead.', - DeprecationWarning, stacklevel=2) - self.imports = imports - changes = change.ChangeSet('Restructuring <%s> to <%s>' % - (self.pattern, self.goal)) - if resources is not None: - files = [resource for resource in resources - if self.pycore.is_python_file(resource)] - else: - files = self.pycore.get_python_files() - job_set = task_handle.create_jobset('Collecting Changes', len(files)) - for resource in files: - job_set.started_job(resource.path) - pymodule = self.pycore.resource_to_pyobject(resource) - finder = similarfinder.SimilarFinder(pymodule, - wildcards=self.wildcards) - matches = list(finder.get_matches(self.pattern, self.args)) - computer = self._compute_changes(matches, pymodule) - result = computer.get_changed() - if result is not None: - imported_source = self._add_imports(resource, result, - self.imports) - changes.add_change(change.ChangeContents(resource, - imported_source)) - job_set.finished_job() - return changes - - def _compute_changes(self, matches, pymodule): - return _ChangeComputer( - pymodule.source_code, pymodule.get_ast(), - pymodule.lines, self.template, matches) - - def _add_imports(self, resource, source, imports): - if not imports: - return source - import_infos = self._get_import_infos(resource, imports) - pymodule = self.pycore.get_string_module(source, resource) - imports = module_imports.ModuleImports(self.pycore, pymodule) - for import_info in import_infos: - imports.add_import(import_info) - return imports.get_changed_source() - - def _get_import_infos(self, resource, imports): - pymodule = self.pycore.get_string_module('\n'.join(imports), - resource) - imports = module_imports.ModuleImports(self.pycore, pymodule) - return [imports.import_info - for imports in imports.imports] - - def make_checks(self, string_checks): - """Convert str to str dicts to str to PyObject dicts - - This function is here to ease writing a UI. - - """ - checks = {} - for key, value in string_checks.items(): - is_pyname = not key.endswith('.object') and \ - not key.endswith('.type') - evaluated = self._evaluate(value, is_pyname=is_pyname) - if evaluated is not None: - checks[key] = evaluated - return checks - - def _evaluate(self, code, is_pyname=True): - attributes = code.split('.') - pyname = None - if attributes[0] in ('__builtin__', '__builtins__'): - class _BuiltinsStub(object): - def get_attribute(self, name): - return builtins.builtins[name] - pyobject = _BuiltinsStub() - else: - pyobject = self.pycore.get_module(attributes[0]) - for attribute in attributes[1:]: - pyname = pyobject[attribute] - if pyname is None: - return None - pyobject = pyname.get_object() - return pyname if is_pyname else pyobject - - -def replace(code, pattern, goal): - """used by other refactorings""" - finder = similarfinder.RawSimilarFinder(code) - matches = list(finder.get_matches(pattern)) - ast = patchedast.get_patched_ast(code) - lines = codeanalyze.SourceLinesAdapter(code) - template = similarfinder.CodeTemplate(goal) - computer = _ChangeComputer(code, ast, lines, template, matches) - result = computer.get_changed() - if result is None: - return code - return result - - -class _ChangeComputer(object): - - def __init__(self, code, ast, lines, goal, matches): - self.source = code - self.goal = goal - self.matches = matches - self.ast = ast - self.lines = lines - self.matched_asts = {} - self._nearest_roots = {} - if self._is_expression(): - for match in self.matches: - self.matched_asts[match.ast] = match - - def get_changed(self): - if self._is_expression(): - result = self._get_node_text(self.ast) - if result == self.source: - return None - return result - else: - collector = codeanalyze.ChangeCollector(self.source) - last_end = -1 - for match in self.matches: - start, end = match.get_region() - if start < last_end: - if not self._is_expression(): - continue - last_end = end - replacement = self._get_matched_text(match) - collector.add_change(start, end, replacement) - return collector.get_changed() - - def _is_expression(self): - return self.matches and isinstance(self.matches[0], - similarfinder.ExpressionMatch) - - def _get_matched_text(self, match): - mapping = {} - for name in self.goal.get_names(): - node = match.get_ast(name) - if node is None: - raise similarfinder.BadNameInCheckError( - 'Unknown name <%s>' % name) - force = self._is_expression() and match.ast == node - mapping[name] = self._get_node_text(node, force) - unindented = self.goal.substitute(mapping) - return self._auto_indent(match.get_region()[0], unindented) - - def _get_node_text(self, node, force=False): - if not force and node in self.matched_asts: - return self._get_matched_text(self.matched_asts[node]) - start, end = patchedast.node_region(node) - main_text = self.source[start:end] - collector = codeanalyze.ChangeCollector(main_text) - for node in self._get_nearest_roots(node): - sub_start, sub_end = patchedast.node_region(node) - collector.add_change(sub_start - start, sub_end - start, - self._get_node_text(node)) - result = collector.get_changed() - if result is None: - return main_text - return result - - def _auto_indent(self, offset, text): - lineno = self.lines.get_line_number(offset) - indents = sourceutils.get_indents(self.lines, lineno) - result = [] - for index, line in enumerate(text.splitlines(True)): - if index != 0 and line.strip(): - result.append(' ' * indents) - result.append(line) - return ''.join(result) - - def _get_nearest_roots(self, node): - if node not in self._nearest_roots: - result = [] - for child in ast.get_child_nodes(node): - if child in self.matched_asts: - result.append(child) - else: - result.extend(self._get_nearest_roots(child)) - self._nearest_roots[node] = result - return self._nearest_roots[node] diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/similarfinder.py b/.vim/bundle/python-mode/pylibs/rope/refactor/similarfinder.py @@ -1,362 +0,0 @@ -"""This module can be used for finding similar code""" -import re - -import rope.refactor.wildcards -from rope.base import codeanalyze, evaluate, exceptions, ast, builtins -from rope.refactor import (patchedast, sourceutils, occurrences, - wildcards, importutils) - - -class BadNameInCheckError(exceptions.RefactoringError): - pass - - -class SimilarFinder(object): - """`SimilarFinder` can be used to find similar pieces of code - - See the notes in the `rope.refactor.restructure` module for more - info. - - """ - - def __init__(self, pymodule, wildcards=None): - """Construct a SimilarFinder""" - self.source = pymodule.source_code - self.raw_finder = RawSimilarFinder( - pymodule.source_code, pymodule.get_ast(), self._does_match) - self.pymodule = pymodule - if wildcards is None: - self.wildcards = {} - for wildcard in [rope.refactor.wildcards. - DefaultWildcard(pymodule.pycore.project)]: - self.wildcards[wildcard.get_name()] = wildcard - else: - self.wildcards = wildcards - - def get_matches(self, code, args={}, start=0, end=None): - self.args = args - if end is None: - end = len(self.source) - skip_region = None - if 'skip' in args.get('', {}): - resource, region = args['']['skip'] - if resource == self.pymodule.get_resource(): - skip_region = region - return self.raw_finder.get_matches(code, start=start, end=end, - skip=skip_region) - - def get_match_regions(self, *args, **kwds): - for match in self.get_matches(*args, **kwds): - yield match.get_region() - - def _does_match(self, node, name): - arg = self.args.get(name, '') - kind = 'default' - if isinstance(arg, (tuple, list)): - kind = arg[0] - arg = arg[1] - suspect = wildcards.Suspect(self.pymodule, node, name) - return self.wildcards[kind].matches(suspect, arg) - - -class RawSimilarFinder(object): - """A class for finding similar expressions and statements""" - - def __init__(self, source, node=None, does_match=None): - if node is None: - node = ast.parse(source) - if does_match is None: - self.does_match = self._simple_does_match - else: - self.does_match = does_match - self._init_using_ast(node, source) - - def _simple_does_match(self, node, name): - return isinstance(node, (ast.expr, ast.Name)) - - def _init_using_ast(self, node, source): - self.source = source - self._matched_asts = {} - if not hasattr(node, 'region'): - patchedast.patch_ast(node, source) - self.ast = node - - def get_matches(self, code, start=0, end=None, skip=None): - """Search for `code` in source and return a list of `Match`\es - - `code` can contain wildcards. ``${name}`` matches normal - names and ``${?name} can match any expression. You can use - `Match.get_ast()` for getting the node that has matched a - given pattern. - - """ - if end is None: - end = len(self.source) - for match in self._get_matched_asts(code): - match_start, match_end = match.get_region() - if start <= match_start and match_end <= end: - if skip is not None and (skip[0] < match_end and - skip[1] > match_start): - continue - yield match - - def _get_matched_asts(self, code): - if code not in self._matched_asts: - wanted = self._create_pattern(code) - matches = _ASTMatcher(self.ast, wanted, - self.does_match).find_matches() - self._matched_asts[code] = matches - return self._matched_asts[code] - - def _create_pattern(self, expression): - expression = self._replace_wildcards(expression) - node = ast.parse(expression) - # Getting Module.Stmt.nodes - nodes = node.body - if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): - # Getting Discard.expr - wanted = nodes[0].value - else: - wanted = nodes - return wanted - - def _replace_wildcards(self, expression): - ropevar = _RopeVariable() - template = CodeTemplate(expression) - mapping = {} - for name in template.get_names(): - mapping[name] = ropevar.get_var(name) - return template.substitute(mapping) - - -class _ASTMatcher(object): - - def __init__(self, body, pattern, does_match): - """Searches the given pattern in the body AST. - - body is an AST node and pattern can be either an AST node or - a list of ASTs nodes - """ - self.body = body - self.pattern = pattern - self.matches = None - self.ropevar = _RopeVariable() - self.matches_callback = does_match - - def find_matches(self): - if self.matches is None: - self.matches = [] - ast.call_for_nodes(self.body, self._check_node, recursive=True) - return self.matches - - def _check_node(self, node): - if isinstance(self.pattern, list): - self._check_statements(node) - else: - self._check_expression(node) - - def _check_expression(self, node): - mapping = {} - if self._match_nodes(self.pattern, node, mapping): - self.matches.append(ExpressionMatch(node, mapping)) - - def _check_statements(self, node): - for child in ast.get_children(node): - if isinstance(child, (list, tuple)): - self.__check_stmt_list(child) - - def __check_stmt_list(self, nodes): - for index in range(len(nodes)): - if len(nodes) - index >= len(self.pattern): - current_stmts = nodes[index:index + len(self.pattern)] - mapping = {} - if self._match_stmts(current_stmts, mapping): - self.matches.append(StatementMatch(current_stmts, mapping)) - - def _match_nodes(self, expected, node, mapping): - if isinstance(expected, ast.Name): - if self.ropevar.is_var(expected.id): - return self._match_wildcard(expected, node, mapping) - if not isinstance(expected, ast.AST): - return expected == node - if expected.__class__ != node.__class__: - return False - - children1 = self._get_children(expected) - children2 = self._get_children(node) - if len(children1) != len(children2): - return False - for child1, child2 in zip(children1, children2): - if isinstance(child1, ast.AST): - if not self._match_nodes(child1, child2, mapping): - return False - elif isinstance(child1, (list, tuple)): - if not isinstance(child2, (list, tuple)) or \ - len(child1) != len(child2): - return False - for c1, c2 in zip(child1, child2): - if not self._match_nodes(c1, c2, mapping): - return False - else: - if child1 != child2: - return False - return True - - def _get_children(self, node): - """Return not `ast.expr_context` children of `node`""" - children = ast.get_children(node) - return [child for child in children - if not isinstance(child, ast.expr_context)] - - def _match_stmts(self, current_stmts, mapping): - if len(current_stmts) != len(self.pattern): - return False - for stmt, expected in zip(current_stmts, self.pattern): - if not self._match_nodes(expected, stmt, mapping): - return False - return True - - def _match_wildcard(self, node1, node2, mapping): - name = self.ropevar.get_base(node1.id) - if name not in mapping: - if self.matches_callback(node2, name): - mapping[name] = node2 - return True - return False - else: - return self._match_nodes(mapping[name], node2, {}) - - -class Match(object): - - def __init__(self, mapping): - self.mapping = mapping - - def get_region(self): - """Returns match region""" - - def get_ast(self, name): - """Return the ast node that has matched rope variables""" - return self.mapping.get(name, None) - - -class ExpressionMatch(Match): - - def __init__(self, ast, mapping): - super(ExpressionMatch, self).__init__(mapping) - self.ast = ast - - def get_region(self): - return self.ast.region - - -class StatementMatch(Match): - - def __init__(self, ast_list, mapping): - super(StatementMatch, self).__init__(mapping) - self.ast_list = ast_list - - def get_region(self): - return self.ast_list[0].region[0], self.ast_list[-1].region[1] - - -class CodeTemplate(object): - - def __init__(self, template): - self.template = template - self._find_names() - - def _find_names(self): - self.names = {} - for match in CodeTemplate._get_pattern().finditer(self.template): - if 'name' in match.groupdict() and \ - match.group('name') is not None: - start, end = match.span('name') - name = self.template[start + 2:end - 1] - if name not in self.names: - self.names[name] = [] - self.names[name].append((start, end)) - - def get_names(self): - return self.names.keys() - - def substitute(self, mapping): - collector = codeanalyze.ChangeCollector(self.template) - for name, occurrences in self.names.items(): - for region in occurrences: - collector.add_change(region[0], region[1], mapping[name]) - result = collector.get_changed() - if result is None: - return self.template - return result - - _match_pattern = None - - @classmethod - def _get_pattern(cls): - if cls._match_pattern is None: - pattern = codeanalyze.get_comment_pattern() + '|' + \ - codeanalyze.get_string_pattern() + '|' + \ - r'(?P<name>\$\{[^\s\$\}]*\})' - cls._match_pattern = re.compile(pattern) - return cls._match_pattern - - -class _RopeVariable(object): - """Transform and identify rope inserted wildcards""" - - _normal_prefix = '__rope__variable_normal_' - _any_prefix = '__rope__variable_any_' - - def get_var(self, name): - if name.startswith('?'): - return self._get_any(name) - else: - return self._get_normal(name) - - def is_var(self, name): - return self._is_normal(name) or self._is_var(name) - - def get_base(self, name): - if self._is_normal(name): - return name[len(self._normal_prefix):] - if self._is_var(name): - return '?' + name[len(self._any_prefix):] - - def _get_normal(self, name): - return self._normal_prefix + name - - def _get_any(self, name): - return self._any_prefix + name[1:] - - def _is_normal(self, name): - return name.startswith(self._normal_prefix) - - def _is_var(self, name): - return name.startswith(self._any_prefix) - - -def make_pattern(code, variables): - variables = set(variables) - collector = codeanalyze.ChangeCollector(code) - def does_match(node, name): - return isinstance(node, ast.Name) and node.id == name - finder = RawSimilarFinder(code, does_match=does_match) - for variable in variables: - for match in finder.get_matches('${%s}' % variable): - start, end = match.get_region() - collector.add_change(start, end, '${%s}' % variable) - result = collector.get_changed() - return result if result is not None else code - - -def _pydefined_to_str(pydefined): - address = [] - if isinstance(pydefined, (builtins.BuiltinClass, builtins.BuiltinFunction)): - return '__builtins__.' + pydefined.get_name() - else: - while pydefined.parent is not None: - address.insert(0, pydefined.get_name()) - pydefined = pydefined.parent - module_name = pydefined.pycore.modname(pydefined.resource) - return '.'.join(module_name.split('.') + address) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/sourceutils.py b/.vim/bundle/python-mode/pylibs/rope/refactor/sourceutils.py @@ -1,92 +0,0 @@ -from rope.base import ast, codeanalyze - - -def get_indents(lines, lineno): - return codeanalyze.count_line_indents(lines.get_line(lineno)) - - -def find_minimum_indents(source_code): - result = 80 - lines = source_code.split('\n') - for line in lines: - if line.strip() == '': - continue - result = min(result, codeanalyze.count_line_indents(line)) - return result - - -def indent_lines(source_code, amount): - if amount == 0: - return source_code - lines = source_code.splitlines(True) - result = [] - for l in lines: - if l.strip() == '': - result.append('\n') - continue - if amount < 0: - indents = codeanalyze.count_line_indents(l) - result.append(max(0, indents + amount) * ' ' + l.lstrip()) - else: - result.append(' ' * amount + l) - return ''.join(result) - - -def fix_indentation(code, new_indents): - """Change the indentation of `code` to `new_indents`""" - min_indents = find_minimum_indents(code) - return indent_lines(code, new_indents - min_indents) - - -def add_methods(pymodule, class_scope, methods_sources): - source_code = pymodule.source_code - lines = pymodule.lines - insertion_line = class_scope.get_end() - if class_scope.get_scopes(): - insertion_line = class_scope.get_scopes()[-1].get_end() - insertion_offset = lines.get_line_end(insertion_line) - methods = '\n\n' + '\n\n'.join(methods_sources) - indented_methods = fix_indentation( - methods, get_indents(lines, class_scope.get_start()) + - get_indent(pymodule.pycore)) - result = [] - result.append(source_code[:insertion_offset]) - result.append(indented_methods) - result.append(source_code[insertion_offset:]) - return ''.join(result) - - -def get_body(pyfunction): - """Return unindented function body""" - scope = pyfunction.get_scope() - pymodule = pyfunction.get_module() - start, end = get_body_region(pyfunction) - return fix_indentation(pymodule.source_code[start:end], 0) - - -def get_body_region(defined): - """Return the start and end offsets of function body""" - scope = defined.get_scope() - pymodule = defined.get_module() - lines = pymodule.lines - node = defined.get_ast() - start_line = node.lineno - if defined.get_doc() is None: - start_line = node.body[0].lineno - elif len(node.body) > 1: - start_line = node.body[1].lineno - start = lines.get_line_start(start_line) - scope_start = pymodule.logical_lines.logical_line_in(scope.start) - if scope_start[1] >= start_line: - # a one-liner! - # XXX: what if colon appears in a string - start = pymodule.source_code.index(':', start) + 1 - while pymodule.source_code[start].isspace(): - start += 1 - end = min(lines.get_line_end(scope.end) + 1, len(pymodule.source_code)) - return start, end - - -def get_indent(pycore): - project = pycore.project - return project.prefs.get('indent_size', 4) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/suites.py b/.vim/bundle/python-mode/pylibs/rope/refactor/suites.py @@ -1,142 +0,0 @@ -from rope.base import ast - - -def find_visible(node, lines): - """Return the line which is visible from all `lines`""" - root = ast_suite_tree(node) - return find_visible_for_suite(root, lines) - - -def find_visible_for_suite(root, lines): - if len(lines) == 1: - return lines[0] - line1 = lines[0] - line2 = find_visible_for_suite(root, lines[1:]) - suite1 = root.find_suite(line1) - suite2 = root.find_suite(line2) - def valid(suite): - return suite is not None and not suite.ignored - if valid(suite1) and not valid(suite2): - return line1 - if not valid(suite1) and valid(suite2): - return line2 - if not valid(suite1) and not valid(suite2): - return None - while suite1 != suite2 and suite1.parent != suite2.parent: - if suite1._get_level() < suite2._get_level(): - line2 = suite2.get_start() - suite2 = suite2.parent - elif suite1._get_level() > suite2._get_level(): - line1 = suite1.get_start() - suite1 = suite1.parent - else: - line1 = suite1.get_start() - line2 = suite2.get_start() - suite1 = suite1.parent - suite2 = suite2.parent - if suite1 == suite2: - return min(line1, line2) - return min(suite1.get_start(), suite2.get_start()) - - -def ast_suite_tree(node): - if hasattr(node, 'lineno'): - lineno = node.lineno - else: - lineno = 1 - return Suite(node.body, lineno) - - -class Suite(object): - - def __init__(self, child_nodes, lineno, parent=None, ignored=False): - self.parent = parent - self.lineno = lineno - self.child_nodes = child_nodes - self._children = None - self.ignored = ignored - - def get_start(self): - if self.parent is None: - if self.child_nodes: - return self.local_start() - else: - return 1 - return self.lineno - - def get_children(self): - if self._children is None: - walker = _SuiteWalker(self) - for child in self.child_nodes: - ast.walk(child, walker) - self._children = walker.suites - return self._children - - def local_start(self): - return self.child_nodes[0].lineno - - def local_end(self): - end = self.child_nodes[-1].lineno - if self.get_children(): - end = max(end, self.get_children()[-1].local_end()) - return end - - def find_suite(self, line): - if line is None: - return None - for child in self.get_children(): - if child.local_start() <= line <= child.local_end(): - return child.find_suite(line) - return self - - def _get_level(self): - if self.parent is None: - return 0 - return self.parent._get_level() + 1 - - -class _SuiteWalker(object): - - def __init__(self, suite): - self.suite = suite - self.suites = [] - - def _If(self, node): - self._add_if_like_node(node) - - def _For(self, node): - self._add_if_like_node(node) - - def _While(self, node): - self._add_if_like_node(node) - - def _With(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - - def _TryFinally(self, node): - if len(node.finalbody) == 1 and \ - isinstance(node.body[0], ast.TryExcept): - self._TryExcept(node.body[0]) - else: - self.suites.append(Suite(node.body, node.lineno, self.suite)) - self.suites.append(Suite(node.finalbody, node.lineno, self.suite)) - - def _TryExcept(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - for handler in node.handlers: - self.suites.append(Suite(handler.body, node.lineno, self.suite)) - if node.orelse: - self.suites.append(Suite(node.orelse, node.lineno, self.suite)) - - def _add_if_like_node(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - if node.orelse: - self.suites.append(Suite(node.orelse, node.lineno, self.suite)) - - def _FunctionDef(self, node): - self.suites.append(Suite(node.body, node.lineno, - self.suite, ignored=True)) - - def _ClassDef(self, node): - self.suites.append(Suite(node.body, node.lineno, - self.suite, ignored=True)) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/topackage.py b/.vim/bundle/python-mode/pylibs/rope/refactor/topackage.py @@ -1,32 +0,0 @@ -import rope.refactor.importutils -from rope.base.change import ChangeSet, ChangeContents, MoveResource, CreateFolder - - -class ModuleToPackage(object): - - def __init__(self, project, resource): - self.project = project - self.pycore = project.pycore - self.resource = resource - - def get_changes(self): - changes = ChangeSet('Transform <%s> module to package' % - self.resource.path) - new_content = self._transform_relatives_to_absolute(self.resource) - if new_content is not None: - changes.add_change(ChangeContents(self.resource, new_content)) - parent = self.resource.parent - name = self.resource.name[:-3] - changes.add_change(CreateFolder(parent, name)) - parent_path = parent.path + '/' - if not parent.path: - parent_path = '' - new_path = parent_path + '%s/__init__.py' % name - if self.resource.project == self.project: - changes.add_change(MoveResource(self.resource, new_path)) - return changes - - def _transform_relatives_to_absolute(self, resource): - pymodule = self.pycore.resource_to_pyobject(resource) - import_tools = rope.refactor.importutils.ImportTools(self.pycore) - return import_tools.relatives_to_absolutes(pymodule) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/usefunction.py b/.vim/bundle/python-mode/pylibs/rope/refactor/usefunction.py @@ -1,171 +0,0 @@ -from rope.base import (change, taskhandle, evaluate, - exceptions, pyobjects, pynames, ast) -from rope.refactor import restructure, sourceutils, similarfinder, importutils - - -class UseFunction(object): - """Try to use a function wherever possible""" - - def __init__(self, project, resource, offset): - self.project = project - self.offset = offset - this_pymodule = project.pycore.resource_to_pyobject(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - if pyname is None: - raise exceptions.RefactoringError('Unresolvable name selected') - self.pyfunction = pyname.get_object() - if not isinstance(self.pyfunction, pyobjects.PyFunction) or \ - not isinstance(self.pyfunction.parent, pyobjects.PyModule): - raise exceptions.RefactoringError( - 'Use function works for global functions, only.') - self.resource = self.pyfunction.get_module().get_resource() - self._check_returns() - - def _check_returns(self): - node = self.pyfunction.get_ast() - if _yield_count(node): - raise exceptions.RefactoringError('Use function should not ' - 'be used on generators.') - returns = _return_count(node) - if returns > 1: - raise exceptions.RefactoringError('usefunction: Function has more ' - 'than one return statement.') - if returns == 1 and not _returns_last(node): - raise exceptions.RefactoringError('usefunction: return should ' - 'be the last statement.') - - def get_changes(self, resources=None, - task_handle=taskhandle.NullTaskHandle()): - if resources is None: - resources = self.project.pycore.get_python_files() - changes = change.ChangeSet('Using function <%s>' % - self.pyfunction.get_name()) - if self.resource in resources: - newresources = list(resources) - newresources.remove(self.resource) - for c in self._restructure(newresources, task_handle).changes: - changes.add_change(c) - if self.resource in resources: - for c in self._restructure([self.resource], task_handle, - others=False).changes: - changes.add_change(c) - return changes - - def get_function_name(self): - return self.pyfunction.get_name() - - def _restructure(self, resources, task_handle, others=True): - body = self._get_body() - pattern = self._make_pattern() - goal = self._make_goal(import_=others) - imports = None - if others: - imports = ['import %s' % self._module_name()] - - body_region = sourceutils.get_body_region(self.pyfunction) - args_value = {'skip': (self.resource, body_region)} - args = {'': args_value} - - restructuring = restructure.Restructure( - self.project, pattern, goal, args=args, imports=imports) - return restructuring.get_changes(resources=resources, - task_handle=task_handle) - - def _find_temps(self): - return find_temps(self.project, self._get_body()) - - def _module_name(self): - return self.project.pycore.modname(self.resource) - - def _make_pattern(self): - params = self.pyfunction.get_param_names() - body = self._get_body() - body = restructure.replace(body, 'return', 'pass') - wildcards = list(params) - wildcards.extend(self._find_temps()) - if self._does_return(): - if self._is_expression(): - replacement = '${%s}' % self._rope_returned - else: - replacement = '%s = ${%s}' % (self._rope_result, - self._rope_returned) - body = restructure.replace( - body, 'return ${%s}' % self._rope_returned, - replacement) - wildcards.append(self._rope_result) - return similarfinder.make_pattern(body, wildcards) - - def _get_body(self): - return sourceutils.get_body(self.pyfunction) - - def _make_goal(self, import_=False): - params = self.pyfunction.get_param_names() - function_name = self.pyfunction.get_name() - if import_: - function_name = self._module_name() + '.' + function_name - goal = '%s(%s)' % (function_name, - ', ' .join(('${%s}' % p) for p in params)) - if self._does_return() and not self._is_expression(): - goal = '${%s} = %s' % (self._rope_result, goal) - return goal - - def _does_return(self): - body = self._get_body() - removed_return = restructure.replace(body, 'return ${result}', '') - return removed_return != body - - def _is_expression(self): - return len(self.pyfunction.get_ast().body) == 1 - - _rope_result = '_rope__result' - _rope_returned = '_rope__returned' - - -def find_temps(project, code): - code = 'def f():\n' + sourceutils.indent_lines(code, 4) - pymodule = project.pycore.get_string_module(code) - result = [] - function_scope = pymodule.get_scope().get_scopes()[0] - for name, pyname in function_scope.get_names().items(): - if isinstance(pyname, pynames.AssignedName): - result.append(name) - return result - - -def _returns_last(node): - return node.body and isinstance(node.body[-1], ast.Return) - -def _yield_count(node): - visitor = _ReturnOrYieldFinder() - visitor.start_walking(node) - return visitor.yields - -def _return_count(node): - visitor = _ReturnOrYieldFinder() - visitor.start_walking(node) - return visitor.returns - -class _ReturnOrYieldFinder(object): - - def __init__(self): - self.returns = 0 - self.yields = 0 - - def _Return(self, node): - self.returns += 1 - - def _Yield(self, node): - self.yields += 1 - - def _FunctionDef(self, node): - pass - - def _ClassDef(self, node): - pass - - def start_walking(self, node): - nodes = [node] - if isinstance(node, ast.FunctionDef): - nodes = ast.get_child_nodes(node) - for child in nodes: - ast.walk(child, self) diff --git a/.vim/bundle/python-mode/pylibs/rope/refactor/wildcards.py b/.vim/bundle/python-mode/pylibs/rope/refactor/wildcards.py @@ -1,176 +0,0 @@ -from rope.base import ast, evaluate, builtins, pyobjects -from rope.refactor import patchedast, occurrences - - -class Wildcard(object): - - def get_name(self): - """Return the name of this wildcard""" - - def matches(self, suspect, arg): - """Return `True` if `suspect` matches this wildcard""" - - -class Suspect(object): - - def __init__(self, pymodule, node, name): - self.name = name - self.pymodule = pymodule - self.node = node - - -class DefaultWildcard(object): - """The default restructuring wildcard - - The argument passed to this wildcard is in the - ``key1=value1,key2=value2,...`` format. Possible keys are: - - * name - for checking the reference - * type - for checking the type - * object - for checking the object - * instance - for checking types but similar to builtin isinstance - * exact - matching only occurrences with the same name as the wildcard - * unsure - matching unsure occurrences - - """ - - def __init__(self, project): - self.project = project - - def get_name(self): - return 'default' - - def matches(self, suspect, arg=''): - args = parse_arg(arg) - - if not self._check_exact(args, suspect): - return False - if not self._check_object(args, suspect): - return False - return True - - def _check_object(self, args, suspect): - kind = None - expected = None - unsure = args.get('unsure', False) - for check in ['name', 'object', 'type', 'instance']: - if check in args: - kind = check - expected = args[check] - if expected is not None: - checker = _CheckObject(self.project, expected, - kind, unsure=unsure) - return checker(suspect.pymodule, suspect.node) - return True - - def _check_exact(self, args, suspect): - node = suspect.node - if args.get('exact'): - if not isinstance(node, ast.Name) or not node.id == suspect.name: - return False - else: - if not isinstance(node, ast.expr): - return False - return True - - -def parse_arg(arg): - if isinstance(arg, dict): - return arg - result = {} - tokens = arg.split(',') - for token in tokens: - if '=' in token: - parts = token.split('=', 1) - result[parts[0].strip()] = parts[1].strip() - else: - result[token.strip()] = True - return result - - -class _CheckObject(object): - - def __init__(self, project, expected, kind='object', unsure=False): - self.project = project - self.kind = kind - self.unsure = unsure - self.expected = self._evaluate(expected) - - def __call__(self, pymodule, node): - pyname = self._evaluate_node(pymodule, node) - if pyname is None or self.expected is None: - return self.unsure - if self._unsure_pyname(pyname, unbound=self.kind=='name'): - return True - if self.kind == 'name': - return self._same_pyname(self.expected, pyname) - else: - pyobject = pyname.get_object() - if self.kind == 'object': - objects = [pyobject] - if self.kind == 'type': - objects = [pyobject.get_type()] - if self.kind == 'instance': - objects = [pyobject] - objects.extend(self._get_super_classes(pyobject)) - objects.extend(self._get_super_classes(pyobject.get_type())) - for pyobject in objects: - if self._same_pyobject(self.expected.get_object(), pyobject): - return True - return False - - def _get_super_classes(self, pyobject): - result = [] - if isinstance(pyobject, pyobjects.AbstractClass): - for superclass in pyobject.get_superclasses(): - result.append(superclass) - result.extend(self._get_super_classes(superclass)) - return result - - def _same_pyobject(self, expected, pyobject): - return expected == pyobject - - def _same_pyname(self, expected, pyname): - return occurrences.same_pyname(expected, pyname) - - def _unsure_pyname(self, pyname, unbound=True): - return self.unsure and occurrences.unsure_pyname(pyname, unbound) - - def _split_name(self, name): - parts = name.split('.') - expression, kind = parts[0], parts[-1] - if len(parts) == 1: - kind = 'name' - return expression, kind - - def _evaluate_node(self, pymodule, node): - scope = pymodule.get_scope().get_inner_scope_for_line(node.lineno) - expression = node - if isinstance(expression, ast.Name) and \ - isinstance(expression.ctx, ast.Store): - start, end = patchedast.node_region(expression) - text = pymodule.source_code[start:end] - return evaluate.eval_str(scope, text) - else: - return evaluate.eval_node(scope, expression) - - def _evaluate(self, code): - attributes = code.split('.') - pyname = None - if attributes[0] in ('__builtin__', '__builtins__'): - class _BuiltinsStub(object): - def get_attribute(self, name): - return builtins.builtins[name] - def __getitem__(self, name): - return builtins.builtins[name] - def __contains__(self, name): - return name in builtins.builtins - pyobject = _BuiltinsStub() - else: - pyobject = self.project.pycore.get_module(attributes[0]) - for attribute in attributes[1:]: - pyname = pyobject[attribute] - if pyname is None: - return None - pyobject = pyname.get_object() - return pyname diff --git a/.vim/bundle/python-mode/pylibs/ropemode/__init__.py b/.vim/bundle/python-mode/pylibs/ropemode/__init__.py @@ -1,16 +0,0 @@ -"""ropemode, a helper for using rope refactoring library in IDEs""" - -INFO = __doc__ -VERSION = '0.2' -COPYRIGHT = """\ -Copyright (C) 2007-2012 Ali Gholami Rudi - -This program is free software; you can redistribute it and/or modify it -under the terms of GNU General Public License as published by the -Free Software Foundation; either version 2 of the license, or (at your -opinion) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details.""" diff --git a/.vim/bundle/python-mode/pylibs/ropemode/decorators.py b/.vim/bundle/python-mode/pylibs/ropemode/decorators.py @@ -1,98 +0,0 @@ -import traceback - -from rope.base import exceptions - - -class Logger(object): - - message = None - only_short = False - - def __call__(self, message, short=None): - if short is None or not self.only_short: - self._show(message) - if short is not None: - self._show(short) - - def _show(self, message): - if self.message is None: - print message - else: - self.message(message) - -logger = Logger() - - -def lisphook(func): - def newfunc(*args, **kwds): - try: - func(*args, **kwds) - except Exception, e: - trace = str(traceback.format_exc()) - short = 'Ignored an exception in ropemode hook: %s' % \ - _exception_message(e) - logger(trace, short) - newfunc.lisp = None - newfunc.__name__ = func.__name__ - newfunc.__doc__ = func.__doc__ - return newfunc - - -def lispfunction(func): - func.lisp = None - return func - - -input_exceptions = (exceptions.RefactoringError, - exceptions.ModuleSyntaxError, - exceptions.BadIdentifierError) - -def _exception_handler(func): - def newfunc(*args, **kwds): - try: - return func(*args, **kwds) - except exceptions.RopeError, e: - short = None - if isinstance(e, input_exceptions): - short = _exception_message(e) - logger(str(traceback.format_exc()), short) - newfunc.__name__ = func.__name__ - newfunc.__doc__ = func.__doc__ - return newfunc - -def _exception_message(e): - return '%s: %s' % (e.__class__.__name__, str(e)) - -def rope_hook(hook): - def decorator(func): - func = lisphook(func) - func.name = func.__name__ - func.kind = 'hook' - func.hook = hook - return func - return decorator - - -def local_command(key=None, prefix=False, shortcut=None, name=None): - def decorator(func, name=name): - func = _exception_handler(func) - func.kind = 'local' - func.prefix = prefix - func.local_key = key - func.shortcut_key = shortcut - if name is None: - name = func.__name__ - func.name = name - return func - return decorator - - -def global_command(key=None, prefix=False): - def decorator(func): - func = _exception_handler(func) - func.kind = 'global' - func.prefix = prefix - func.global_key = key - func.name = func.__name__ - return func - return decorator diff --git a/.vim/bundle/python-mode/pylibs/ropemode/dialog.py b/.vim/bundle/python-mode/pylibs/ropemode/dialog.py @@ -1,97 +0,0 @@ -class Data(object): - - def __init__(self, prompt=None, default=None, values=None, - kind=None, decode=None): - self.prompt = prompt - self.default = default - self.values = values - self.kind = kind - self._decode = decode - - def decode(self, value): - if self._decode: - return self._decode(value) - return value - - -class Boolean(Data): - - def __init__(self, prompt=None, default=False): - Data.__init__(self, prompt, self._encode(default), - [self._encode(True), self._encode(False)]) - - def _encode(self, value): - if value: - return 'yes' - return 'no' - - def decode(self, value): - if value.lower() in ('yes', '1', 'true'): - return True - return False - - -def show_dialog(askdata, actions, confs={}, optionals={}, initial_asking=True): - result = {} - if initial_asking: - for name, conf in confs.items(): - result[name] = askdata(conf) - actions.append('batchset') - names = list(actions) - names.extend(optionals.keys()) - names.extend(confs.keys()) - base_question = Data('Choose what to do: ', - default=actions[0], values=names) - batchset_question = Data('Batch sets: ') - while True: - response = askdata(base_question) - if response == '': - response = base_question.default - elif response == 'batchset': - sets = askdata(batchset_question) - for key, value in _parse_batchset(sets).items(): - if key.endswith(':'): - key = key[:-1] - if key in names: - conf = confs.get(key, optionals.get(key)) - result[key] = value - elif response in actions: - break - else: - if response in confs: - conf = confs[response] - else: - conf = optionals[response] - oldvalue = result.get(response, None) - result[response] = askdata(conf, starting=oldvalue) - decoded = {} - all_confs = dict(confs) - all_confs.update(optionals) - for key in all_confs: - conf = all_confs.get(key) - if key in result: - decoded[key] = conf.decode(result[key]) - else: - decoded[key] = conf.decode(conf.default) - return response, decoded - - -def _parse_batchset(sets): - result = [] - multiline = False - for line in sets.splitlines(True): - if line[0].isspace(): - if multiline: - result[-1][1] += line[1:] - else: - if not line.strip(): - continue - multiline= False - tokens = line.split(None, 1) - value = '' - if len(tokens) > 1: - result.append([tokens[0], tokens[1].rstrip('\r\n')]) - else: - multiline = True - result.append([tokens[0], '']) - return dict(result) diff --git a/.vim/bundle/python-mode/pylibs/ropemode/environment.py b/.vim/bundle/python-mode/pylibs/ropemode/environment.py @@ -1,104 +0,0 @@ -class Environment(object): - - def ask(self, prompt, default=None, starting=None): - pass - - def ask_values(self, prompt, values, default=None, starting=None): - pass - - def ask_directory(self, prompt, default=None, starting=None): - pass - - def ask_completion(self, prompt, values, starting=None): - pass - - def message(self, message): - pass - - def yes_or_no(self, prompt): - pass - - def y_or_n(self, prompt): - pass - - def get(self, name, default=None): - pass - - def get_offset(self): - pass - - def get_text(self): - pass - - def get_region(self): - pass - - def filename(self): - pass - - def is_modified(self): - pass - - def goto_line(self, lineno): - pass - - def insert_line(self, line, lineno): - pass - - def insert(self, text): - pass - - def delete(self, start, end): - pass - - def filenames(self): - pass - - def save_files(self, filenames): - pass - - def reload_files(self, filenames, moves={}): - pass - - def find_file(self, filename, readonly=False, other=False): - pass - - def create_progress(self, name): - pass - - def current_word(self): - pass - - def push_mark(self): - pass - - def pop_mark(self): - pass - - def prefix_value(self, prefix): - pass - - def show_occurrences(self, locations): - pass - - def show_doc(self, docs, altview=False): - pass - - def preview_changes(self, diffs): - pass - - def local_command(self, name, callback, key=None, prefix=False): - pass - - def global_command(self, name, callback, key=None, prefix=False): - pass - - def add_hook(self, name, callback, hook): - pass - - def _completion_text(self, proposal): - return proposal.name - - def _completion_data(self, proposal): - return self._completion_text(proposal) - diff --git a/.vim/bundle/python-mode/pylibs/ropemode/filter.py b/.vim/bundle/python-mode/pylibs/ropemode/filter.py @@ -1,39 +0,0 @@ -from rope.base import exceptions - - -def resources(project, rules): - """Find python files in the `project` matching `rules` - - `rules` is a multi-line `str`; each line starts with either a '+' - or '-'. Each '+' means include the file (or its children if it's - a folder) that comes after it. '-' has the same meaning for - exclusion. - - """ - all = set(project.pycore.get_python_files()) - files = None - for line in rules.splitlines(): - if not line.strip(): - continue - first, path = (line[0], line[1:]) - if first not in '+-': - continue - try: - resource = project.get_resource(path.strip()) - except exceptions.ResourceNotFoundError: - continue - if resource.is_folder(): - matches = set(filter(lambda item: resource.contains(item), all)) - else: - matches = set([resource]) - if first == '+': - if files is None: - files = set() - files.update(matches) - if first == '-': - if files is None: - files = set(all) - files -= matches - if files is None: - return all - return files diff --git a/.vim/bundle/python-mode/pylibs/ropemode/interface.py b/.vim/bundle/python-mode/pylibs/ropemode/interface.py @@ -1,706 +0,0 @@ -import os - -import rope.base.change -from rope.base import libutils, utils, exceptions -from rope.contrib import codeassist, generate, autoimport, findit - -from ropemode import refactor, decorators, dialog - - -class RopeMode(object): - - def __init__(self, env): - self.project = None - self.old_content = None - self.env = env - self._assist = None - - self._prepare_refactorings() - self.autoimport = None - - for attrname in dir(self): - attr = getattr(self, attrname) - if not callable(attr): - continue - kind = getattr(attr, 'kind', None) - if kind == 'local': - key = getattr(attr, 'local_key', None) - prefix = getattr(attr, 'prefix', None) - self.env.local_command(attrname, attr, key, prefix) - if kind == 'global': - key = getattr(attr, 'global_key', None) - prefix = getattr(attr, 'prefix', None) - self.env.global_command(attrname, attr, key, prefix) - if kind == 'hook': - hook = getattr(attr, 'hook', None) - self.env.add_hook(attrname, attr, hook) - - def _prepare_refactorings(self): - for name in dir(refactor): - if not name.startswith('_') and name != 'Refactoring': - attr = getattr(refactor, name) - if isinstance(attr, type) and \ - issubclass(attr, refactor.Refactoring): - refname = self._refactoring_name(attr) - - @decorators.local_command(attr.key, 'P', None, refname) - def do_refactor(prefix, self=self, refactoring=attr): - initial_asking = prefix is None - refactoring(self, self.env).show(initial_asking=initial_asking) - setattr(self, refname, do_refactor) - - @staticmethod - def _refactoring_name(refactoring): - return refactor.refactoring_name(refactoring) - - @decorators.rope_hook('before_save') - def before_save_actions(self): - if self.project is not None: - if not self._is_python_file(self.env.filename()): - return - resource = self._get_resource() - if resource.exists(): - self.old_content = resource.read() - else: - self.old_content = '' - - @decorators.rope_hook('after_save') - def after_save_actions(self): - if self.project is not None and self.old_content is not None: - libutils.report_change(self.project, self.env.filename(), - self.old_content) - self.old_content = None - - @decorators.rope_hook('exit') - def exiting_actions(self): - if self.project is not None: - self.close_project() - - @decorators.global_command('o') - def open_project(self, root=None): - if not root: - if self.env.get('auto_project'): - root = self.env.get_cur_dir() - else: - root = self.env.ask_directory('Rope project root folder: ') - if self.project is not None: - self.close_project() - address = rope.base.project._realpath(os.path.join(root, - '.ropeproject')) - if not os.path.exists(address) and not self.env.get('auto_project'): - if not self.env.y_or_n('Project not exists in %s, create one?' % root): - self.env.message("Project creation aborted") - return - progress = self.env.create_progress('Opening [%s] project' % root) - self.project = rope.base.project.Project(root) - if self.env.get('enable_autoimport'): - underlined = self.env.get('autoimport_underlineds') - self.autoimport = autoimport.AutoImport(self.project, - underlined=underlined) - progress.done() - - @decorators.global_command('k') - def close_project(self): - if self.project is not None: - progress = self.env.create_progress('Closing [%s] project' % - self.project.address) - self.project.close() - self.project = None - progress.done() - - @decorators.global_command() - def write_project(self): - if self.project is not None: - progress = self.env.create_progress( - 'Writing [%s] project data to disk' % self.project.address) - self.project.sync() - progress.done() - - @decorators.global_command('u') - def undo(self): - self._check_project() - change = self.project.history.tobe_undone - if change is None: - self.env.message('Nothing to undo!') - return - if self.env.y_or_n('Undo [%s]? ' % str(change)): - def undo(handle): - for changes in self.project.history.undo(task_handle=handle): - self._reload_buffers(changes, undo=True) - refactor.runtask(self.env, undo, 'Undo refactoring', - interrupts=False) - - @decorators.global_command('r') - def redo(self): - self._check_project() - change = self.project.history.tobe_redone - if change is None: - self.env.message('Nothing to redo!') - return - if self.env.y_or_n('Redo [%s]? ' % str(change)): - def redo(handle): - for changes in self.project.history.redo(task_handle=handle): - self._reload_buffers(changes) - refactor.runtask(self.env, redo, 'Redo refactoring', - interrupts=False) - - @decorators.local_command('a g', shortcut='C-c g') - def goto_definition(self): - definition = self._base_definition_location() - if definition: - self.env.push_mark() - self._goto_location(definition[0], definition[1]) - else: - self.env.message('Cannot find the definition!') - - @decorators.local_command() - def pop_mark(self): - self.env.pop_mark() - - @decorators.local_command() - def definition_location(self): - definition = self._base_definition_location() - if definition: - return str(definition[0].real_path), definition[1] - return None - - def _base_definition_location(self): - self._check_project() - resource, offset = self._get_location() - maxfixes = self.env.get('codeassist_maxfixes') - try: - definition = codeassist.get_definition_location( - self.project, self._get_text(), offset, resource, maxfixes) - except exceptions.BadIdentifierError: - return None - if tuple(definition) != (None, None): - return definition - return None - - @decorators.local_command('a d', 'P', 'C-c d') - def show_doc(self, prefix): - self._check_project() - self._base_show_doc(prefix, self._base_get_doc(codeassist.get_doc)) - - @decorators.local_command() - def get_calltip(self): - self._check_project() - def _get_doc(project, text, offset, *args, **kwds): - try: - offset = text.rindex('(', 0, offset) - 1 - except ValueError: - return None - return codeassist.get_calltip(project, text, offset, *args, **kwds) - return self._base_get_doc(_get_doc) - - @decorators.local_command('a c', 'P') - def show_calltip(self, prefix): - self._base_show_doc(prefix, self.get_calltip()) - - def _base_show_doc(self, prefix, docs): - if docs: - self.env.show_doc(docs, prefix) - else: - self.env.message('No docs available!') - - @decorators.local_command() - def get_doc(self): - self._check_project() - return self._base_get_doc(codeassist.get_doc) - - def _base_get_doc(self, get_doc): - maxfixes = self.env.get('codeassist_maxfixes') - text = self._get_text() - offset = self.env.get_offset() - try: - return get_doc(self.project, text, offset, - self.resource, maxfixes) - except exceptions.BadIdentifierError: - return None - - def _get_text(self): - resource = self.resource - if not self.env.is_modified() and resource is not None: - return resource.read() - return self.env.get_text() - - def _base_findit(self, do_find, optionals, get_kwds): - self._check_project() - self._save_buffers() - resource, offset = self._get_location() - - action, values = dialog.show_dialog( - self._askdata, ['search', 'cancel'], optionals=optionals) - if action == 'search': - kwds = get_kwds(values) - def calculate(handle): - resources = refactor._resources(self.project, - values.get('resources')) - return do_find(self.project, resource, offset, - resources=resources, task_handle=handle, **kwds) - result = refactor.runtask(self.env, calculate, 'Find Occurrences') - locations = [Location(location) for location in result] - self.env.show_occurrences(locations) - - @decorators.local_command('a f', shortcut='C-c f') - def find_occurrences(self): - optionals = { - 'unsure': dialog.Data('Find uncertain occurrences: ', - default='no', values=['yes', 'no']), - 'resources': dialog.Data('Files to search: '), - 'in_hierarchy': dialog.Data( - 'Rename methods in class hierarchy: ', - default='no', values=['yes', 'no'])} - def get_kwds(values): - return {'unsure': values.get('unsure') == 'yes', - 'in_hierarchy': values.get('in_hierarchy') == 'yes'} - self._base_findit(findit.find_occurrences, optionals, get_kwds) - - @decorators.local_command('a i') - def find_implementations(self): - optionals = {'resources': dialog.Data('Files to search: ')} - def get_kwds(values): - return {} - self._base_findit(findit.find_implementations, optionals, get_kwds) - - @decorators.local_command('a /', 'P', 'M-/') - def code_assist(self, prefix): - _CodeAssist(self, self.env).code_assist(prefix) - - @decorators.local_command('a ?', 'P', 'M-?') - def lucky_assist(self, prefix): - _CodeAssist(self, self.env).lucky_assist(prefix) - - @decorators.local_command(prefix='P') - def omni_complete(self, prefix): - self._assist.omni_complete(prefix) - - def _find_start(self): - self._assist = _CodeAssist(self, self.env) - start = (self.env.cursor[1] - self.env.get_offset() - + self._assist.starting_offset) - self.env._command('let g:pymode_offset = %s' % start) - - @decorators.local_command('a') - def auto_import(self): - _CodeAssist(self, self.env).auto_import() - - @decorators.local_command() - def completions(self): - return _CodeAssist(self, self.env).completions() - - @decorators.local_command() - def extended_completions(self): - return _CodeAssist(self, self.env).extended_completions() - - def _check_autoimport(self): - self._check_project() - if self.autoimport is None: - self.env.message('autoimport is disabled; ' - 'see `enable_autoimport\' variable') - return False - return True - - @decorators.global_command('g') - def generate_autoimport_cache(self): - if not self._check_autoimport(): - return - modules = self.env.get('autoimport_modules') - modules = [ m if isinstance(m, basestring) else m.value() for m in modules ] - - def generate(handle): - self.autoimport.generate_cache(task_handle=handle) - self.autoimport.generate_modules_cache(modules, task_handle=handle) - - refactor.runtask(self.env, generate, 'Generate autoimport cache') - self.write_project() - - @decorators.global_command('f', 'P') - def find_file(self, prefix): - file = self._base_find_file(prefix) - if file is not None: - self.env.find_file(file.real_path) - - @decorators.global_command('4 f', 'P') - def find_file_other_window(self, prefix): - file = self._base_find_file(prefix) - if file is not None: - self.env.find_file(file.real_path, other=True) - - def _base_find_file(self, prefix): - self._check_project() - if prefix: - files = self.project.pycore.get_python_files() - else: - files = self.project.get_files() - return self._ask_file(files) - - def _ask_file(self, files): - names = [] - for file in files: - names.append('<'.join(reversed(file.path.split('/')))) - result = self.env.ask_values('Rope Find File: ', names) - if result is not None: - path = '/'.join(reversed(result.split('<'))) - file = self.project.get_file(path) - return file - self.env.message('No file selected') - - @decorators.local_command('a j') - def jump_to_global(self): - if not self._check_autoimport(): - return - all_names = list(self.autoimport.get_all_names()) - name = self.env.ask_values('Global name: ', all_names) - result = dict(self.autoimport.get_name_locations(name)) - if len(result) == 1: - resource = list(result.keys())[0] - else: - resource = self._ask_file(result.keys()) - if resource: - self._goto_location(resource, result[resource]) - - @decorators.global_command('c') - def project_config(self): - self._check_project() - if self.project.ropefolder is not None: - config = self.project.ropefolder.get_child('config.py') - self.env.find_file(config.real_path) - else: - self.env.message('No rope project folder found') - - @decorators.global_command('n m') - def create_module(self): - def callback(sourcefolder, name): - return generate.create_module(self.project, name, sourcefolder) - self._create('module', callback) - - @decorators.global_command('n p') - def create_package(self): - def callback(sourcefolder, name): - folder = generate.create_package(self.project, name, sourcefolder) - return folder.get_child('__init__.py') - self._create('package', callback) - - @decorators.global_command('n f') - def create_file(self): - def callback(parent, name): - return parent.create_file(name) - self._create('file', callback, 'parent') - - @decorators.global_command('n d') - def create_directory(self): - def callback(parent, name): - parent.create_folder(name) - self._create('directory', callback, 'parent') - - @decorators.local_command() - def analyze_module(self): - """Perform static object analysis on this module""" - self._check_project() - self.project.pycore.analyze_module(self.resource) - - @decorators.global_command() - def analyze_modules(self): - """Perform static object analysis on all project modules""" - self._check_project() - def _analyze_modules(handle): - libutils.analyze_modules(self.project, task_handle=handle) - refactor.runtask(self.env, _analyze_modules, 'Analyze project modules') - - @decorators.local_command() - def run_module(self): - """Run and perform dynamic object analysis on this module""" - self._check_project() - process = self.project.pycore.run_module(self.resource) - try: - process.wait_process() - finally: - process.kill_process() - - def _create(self, name, callback, parentname='source'): - self._check_project() - confs = {'name': dialog.Data(name.title() + ' name: ')} - parentname = parentname + 'folder' - optionals = {parentname: dialog.Data( - parentname.title() + ' Folder: ', - default=self.project.address, kind='directory')} - action, values = dialog.show_dialog( - self._askdata, ['perform', 'cancel'], confs, optionals) - if action == 'perform': - parent = libutils.path_to_resource( - self.project, values.get(parentname, self.project.address)) - resource = callback(parent, values['name']) - if resource: - self.env.find_file(resource.real_path) - - def _goto_location(self, resource, lineno): - if resource: - self.env.find_file(str(resource.real_path), - other=self.env.get('goto_def_newwin')) - if lineno: - self.env.goto_line(lineno) - - def _get_location(self): - offset = self.env.get_offset() - return self.resource, offset - - def _get_resource(self, filename=None): - if filename is None: - filename = self.env.filename() - if filename is None or self.project is None: - return - resource = libutils.path_to_resource(self.project, filename, 'file') - return resource - - @property - def resource(self): - """the current resource - - Returns `None` when file does not exist. - """ - resource = self._get_resource() - if resource and resource.exists(): - return resource - - @decorators.global_command() - def get_project_root(self): - if self.project is not None: - return self.project.root.real_path - else: - return None - - def _check_project(self): - if self.project is None: - if self.env.get('guess_project'): - self.open_project(self._guess_project()) - else: - self.open_project() - else: - self.project.validate(self.project.root) - - def _guess_project(self): - cwd = self.env.filename() - if cwd is not None: - while True: - ropefolder = os.path.join(cwd, '.ropeproject') - if os.path.exists(ropefolder) and os.path.isdir(ropefolder): - return cwd - newcwd = os.path.dirname(cwd) - if newcwd == cwd: - break - cwd = newcwd - - def _reload_buffers(self, changes, undo=False): - self._reload_buffers_for_changes( - changes.get_changed_resources(), - self._get_moved_resources(changes, undo)) - - def _reload_buffers_for_changes(self, changed, moved={}): - filenames = [resource.real_path for resource in changed] - moved = dict([(resource.real_path, moved[resource].real_path) - for resource in moved]) - self.env.reload_files(filenames, moved) - - def _get_moved_resources(self, changes, undo=False): - result = {} - if isinstance(changes, rope.base.change.ChangeSet): - for change in changes.changes: - result.update(self._get_moved_resources(change)) - if isinstance(changes, rope.base.change.MoveResource): - result[changes.resource] = changes.new_resource - if undo: - return dict([(value, key) for key, value in result.items()]) - return result - - def _save_buffers(self, only_current=False): - if only_current: - filenames = [self.env.filename()] - else: - filenames = self.env.filenames() - pythons = [] - for filename in filenames: - if self._is_python_file(filename): - pythons.append(filename) - self.env.save_files(pythons) - - def _is_python_file(self, path): - resource = self._get_resource(path) - return (resource is not None and - resource.project == self.project and - self.project.pycore.is_python_file(resource)) - - def _askdata(self, data, starting=None): - ask_func = self.env.ask - ask_args = {'prompt': data.prompt, 'starting': starting, - 'default': data.default} - if data.values: - ask_func = self.env.ask_values - ask_args['values'] = data.values - elif data.kind == 'directory': - ask_func = self.env.ask_directory - return ask_func(**ask_args) - - -class Location(object): - def __init__(self, location): - self.location = location - self.filename = location.resource.real_path - self.offset = location.offset - self.note = '' - if location.unsure: - self.note = '?' - - @property - def lineno(self): - if hasattr(self.location, 'lineno'): - return self.location.lineno - return self.location.resource.read().count('\n', 0, self.offset) + 1 - - -class _CodeAssist(object): - - def __init__(self, interface, env): - self.interface = interface - self.env = env - - def code_assist(self, prefix): - proposals = self._calculate_proposals() - if prefix is not None: - arg = self.env.prefix_value(prefix) - if arg == 0: - arg = len(proposals) - common_start = self._calculate_prefix(proposals[:arg]) - self.env.insert(common_start[self.offset - self.starting_offset:]) - self._starting = common_start - self._offset = self.starting_offset + len(common_start) - prompt = 'Completion for %s: ' % self.expression - proposals = map(self.env._completion_data, proposals) - result = self.env.ask_completion(prompt, proposals, self.starting) - if result is not None: - self._apply_assist(result) - - def omni_complete(self, prefix): - proposals = self._calculate_proposals() - proposals = self.env._update_proposals(proposals) - command = u'let g:pythoncomplete_completions = [%s]' % proposals - self.env._command(command, encode=True) - - def lucky_assist(self, prefix): - proposals = self._calculate_proposals() - selected = 0 - if prefix is not None: - selected = self.env.prefix_value(prefix) - if 0 <= selected < len(proposals): - result = self.env._completion_text(proposals[selected]) - else: - self.env.message('Not enough proposals!') - return - self._apply_assist(result) - - def auto_import(self): - if not self.interface._check_autoimport(): - return - - if not self.autoimport.names and self.env.get('autoimport_generate'): - self.interface.generate_autoimport_cache() - - name = self.env.current_word() - modules = self.autoimport.get_modules(name) - if modules: - if len(modules) == 1: - module = modules[0] - else: - module = self.env.ask_values( - 'Which module to import: ', modules) - self._insert_import(name, module) - else: - self.env.message('Global name %s not found!' % name) - - def completions(self): - proposals = self._calculate_proposals() - prefix = self.offset - self.starting_offset - return [self.env._completion_text(proposal)[prefix:] - for proposal in proposals] - - def extended_completions(self): - proposals = self._calculate_proposals() - prefix = self.offset - self.starting_offset - return [[proposal.name[prefix:], proposal.get_doc(), - proposal.type] for proposal in proposals] - - def _apply_assist(self, assist): - if ' : ' in assist: - name, module = assist.rsplit(' : ', 1) - self.env.delete(self.starting_offset + 1, self.offset + 1) - self.env.insert(name) - self._insert_import(name, module) - else: - self.env.delete(self.starting_offset + 1, self.offset + 1) - self.env.insert(assist) - - def _calculate_proposals(self): - self.interface._check_project() - resource = self.interface.resource - maxfixes = self.env.get('codeassist_maxfixes') - proposals = codeassist.code_assist( - self.interface.project, self.source, self.offset, - resource, maxfixes=maxfixes) - if self.env.get('sorted_completions', True): - proposals = codeassist.sorted_proposals(proposals) - if self.autoimport is not None: - if self.starting.strip() and '.' not in self.expression: - import_assists = self.autoimport.import_assist(self.starting) - for assist in import_assists: - p = codeassist.CompletionProposal(' : '.join(assist), - 'autoimport') - proposals.append(p) - return proposals - - def _insert_import(self, name, module): - lineno = self.autoimport.find_insertion_line(self.source) - line = 'from %s import %s' % (module, name) - self.env.insert_line(line, lineno) - - def _calculate_prefix(self, proposals): - if not proposals: - return '' - prefix = self.env._completion_text(proposals[0]) - for proposal in proposals: - common = 0 - name = self.env._completion_text(proposal) - for c1, c2 in zip(prefix, name): - if c1 != c2 or ' ' in (c1, c2): - break - common += 1 - prefix = prefix[:common] - return prefix - - @property - @utils.cacheit - def offset(self): - return self.env.get_offset() - - @property - @utils.cacheit - def source(self): - return self.interface._get_text() - - @property - @utils.cacheit - def starting_offset(self): - return codeassist.starting_offset(self.source, self.offset) - - @property - @utils.cacheit - def starting(self): - return self.source[self.starting_offset:self.offset] - - @property - @utils.cacheit - def expression(self): - return codeassist.starting_expression(self.source, self.offset) - - @property - def autoimport(self): - return self.interface.autoimport diff --git a/.vim/bundle/python-mode/pylibs/ropemode/refactor.py b/.vim/bundle/python-mode/pylibs/ropemode/refactor.py @@ -1,494 +0,0 @@ -import re - -import rope.base.change -import rope.contrib.generate -import rope.refactor.change_signature -import rope.refactor.extract -import rope.refactor.inline -import rope.refactor.introduce_factory -import rope.refactor.method_object -import rope.refactor.move -import rope.refactor.rename -import rope.refactor.restructure -import rope.refactor.usefunction -from rope.base import taskhandle - -from ropemode import dialog, filter as file_filter - - -class Refactoring(object): - key = None - confs = {} - optionals = {} - saveall = True - - def __init__(self, interface, env): - self.interface = interface - self.env = env - - def show(self, initial_asking=True): - self.interface._check_project() - self.interface._save_buffers(only_current=not self.saveall) - self._create_refactoring() - action, result = dialog.show_dialog( - self.interface._askdata, ['perform', 'preview', 'cancel'], - self._get_confs(), self._get_optionals(), - initial_asking=initial_asking) - if action == 'cancel': - self.env.message('Cancelled!') - return - def calculate(handle): - return self._calculate_changes(result, handle) - name = 'Calculating %s changes' % self.name - changes = runtask(self.env, calculate, name=name) - if action == 'perform': - self._perform(changes) - if action == 'preview': - if changes is not None: - diffs = changes.get_description() - if self.env.preview_changes(diffs): - self._perform(changes) - else: - self.env.message('Thrown away!') - else: - self.env.message('No changes!') - - @property - def project(self): - return self.interface.project - - @property - def resource(self): - return self.interface._get_resource() - - @property - def offset(self): - return self.env.get_offset() - - @property - def region(self): - return self.env.get_region() - - @property - def name(self): - return refactoring_name(self.__class__) - - def _calculate_changes(self, option_values, task_handle): - pass - - def _create_refactoring(self): - pass - - def _done(self): - pass - - def _perform(self, changes): - if changes is None: - self.env.message('No changes!') - return - def perform(handle, self=self, changes=changes): - self.project.do(changes, task_handle=handle) - self.interface._reload_buffers(changes) - self._done() - runtask(self.env, perform, 'Making %s changes' % self.name, - interrupts=False) - self.env.message(str(changes.description) + ' finished') - - def _get_confs(self): - return self.confs - - def _get_optionals(self): - return self.optionals - - @property - def resources_option(self): - return dialog.Data('Files to apply this refactoring on: ', - decode=self._decode_resources) - - def _decode_resources(self, value): - return _resources(self.project, value) - - -class Rename(Refactoring): - key = 'r' - saveall = True - - def _create_refactoring(self): - self.renamer = rope.refactor.rename.Rename( - self.project, self.resource, self.offset) - - def _calculate_changes(self, values, task_handle): - return self.renamer.get_changes(task_handle=task_handle, **values) - - def _get_optionals(self): - opts = {} - opts['docs'] = dialog.Boolean('Search comments and docs: ', True) - if self.renamer.is_method(): - opts['in_hierarchy'] = dialog.Boolean('Rename methods in ' - 'class hierarchy: ') - opts['resources'] = self.resources_option - opts['unsure'] = dialog.Data('Unsure occurrences: ', - decode=self._decode_unsure, - values=['ignore', 'match'], - default='ignore') - return opts - - def _get_confs(self): - oldname = str(self.renamer.get_old_name()) - return {'new_name': dialog.Data('New name: ', default=oldname)} - - def _decode_unsure(self, value): - unsure = value == 'match' - return lambda occurrence: unsure - - -class RenameCurrentModule(Rename): - key = '1 r' - offset = None - - -class Restructure(Refactoring): - key = 'x' - confs = {'pattern': dialog.Data('Restructuring pattern: '), - 'goal': dialog.Data('Restructuring goal: ')} - - def _calculate_changes(self, values, task_handle): - restructuring = rope.refactor.restructure.Restructure( - self.project, values['pattern'], values['goal'], - args=values['args'], imports=values['imports']) - return restructuring.get_changes(resources=values['resources'], - task_handle=task_handle) - - def _get_optionals(self): - return { - 'args': dialog.Data('Arguments: ', decode=self._decode_args), - 'imports': dialog.Data('Imports: ', decode=self._decode_imports), - 'resources': self.resources_option} - - def _decode_args(self, value): - if value: - args = {} - for raw_check in value.split('\n'): - if raw_check: - key, value = raw_check.split(':', 1) - args[key.strip()] = value.strip() - return args - - def _decode_imports(self, value): - if value: - return [line.strip() for line in value.split('\n')] - - -class UseFunction(Refactoring): - key = 'u' - - def _create_refactoring(self): - self.user = rope.refactor.usefunction.UseFunction( - self.project, self.resource, self.offset) - - def _calculate_changes(self, values, task_handle): - return self.user.get_changes(task_handle=task_handle, **values) - - def _get_optionals(self): - return {'resources': self.resources_option} - - -class Move(Refactoring): - key = 'v' - - def _create_refactoring(self): - self.mover = rope.refactor.move.create_move(self.project, - self.resource, - self.offset) - - def _calculate_changes(self, values, task_handle): - destination = values['destination'] - resources = values.get('resources', None) - if isinstance(self.mover, rope.refactor.move.MoveGlobal): - return self._move_global(destination, resources, task_handle) - if isinstance(self.mover, rope.refactor.move.MoveModule): - return self._move_module(destination, resources, task_handle) - if isinstance(self.mover, rope.refactor.move.MoveMethod): - return self._move_method(destination, resources, task_handle) - - def _move_global(self, dest, resources, handle): - destination = self.project.pycore.find_module(dest) - return self.mover.get_changes( - destination, resources=resources, task_handle=handle) - - def _move_method(self, dest, resources, handle): - return self.mover.get_changes( - dest, self.mover.get_method_name(), - resources=resources, task_handle=handle) - - def _move_module(self, dest, resources, handle): - destination = self.project.pycore.find_module(dest) - return self.mover.get_changes( - destination, resources=resources, task_handle=handle) - - def _get_confs(self): - if isinstance(self.mover, rope.refactor.move.MoveGlobal): - prompt = 'Destination module: ' - if isinstance(self.mover, rope.refactor.move.MoveModule): - prompt = 'Destination package: ' - if isinstance(self.mover, rope.refactor.move.MoveMethod): - prompt = 'Destination attribute: ' - return {'destination': dialog.Data(prompt)} - - def _get_optionals(self): - return {'resources': self.resources_option} - - -class MoveCurrentModule(Move): - key = '1 v' - offset = None - - -class ModuleToPackage(Refactoring): - key = '1 p' - saveall = False - - def _create_refactoring(self): - self.packager = rope.refactor.ModuleToPackage( - self.project, self.resource) - - def _calculate_changes(self, values, task_handle): - return self.packager.get_changes() - - -class Inline(Refactoring): - key = 'i' - - def _create_refactoring(self): - self.inliner = rope.refactor.inline.create_inline( - self.project, self.resource, self.offset) - - def _calculate_changes(self, values, task_handle): - return self.inliner.get_changes(task_handle=task_handle, **values) - - def _get_optionals(self): - opts = {'resources': self.resources_option} - if self.inliner.get_kind() == 'parameter': - opts['in_hierarchy'] = dialog.Boolean( - 'Apply on all matching methods in class hierarchy: ', False) - else: - opts['remove'] = dialog.Boolean('Remove the definition: ', True) - opts['only_current'] = dialog.Boolean('Inline this ' - 'occurrence only: ') - return opts - - -class _Extract(Refactoring): - saveall = False - optionals = {'similar': dialog.Boolean('Extract similar pieces: ', True), - 'global_': dialog.Boolean('Make global: ')} - kind = None - constructor = rope.refactor.extract.ExtractVariable - - def __init__(self, *args): - super(_Extract, self).__init__(*args) - self.extractor = None - - def _create_refactoring(self): - start, end = self.region - self.extractor = self.constructor(self.project, - self.resource, start, end) - - def _calculate_changes(self, values, task_handle): - similar = values.get('similar') - global_ = values.get('global_') - return self.extractor.get_changes(values['name'], similar=similar, - global_=global_) - - def _get_confs(self): - return {'name': dialog.Data('Extracted %s name: ' % self.kind)} - - -class ExtractVariable(_Extract): - key = 'l' - kind = 'variable' - constructor = rope.refactor.extract.ExtractVariable - - -class ExtractMethod(_Extract): - key = 'm' - kind = 'method' - constructor = rope.refactor.extract.ExtractMethod - - -class OrganizeImports(Refactoring): - key = 'o' - saveall = False - - def _create_refactoring(self): - self.organizer = rope.refactor.ImportOrganizer(self.project) - - def _calculate_changes(self, values, task_handle): - return self.organizer.organize_imports(self.resource) - - -class MethodObject(Refactoring): - saveall = False - confs = {'classname': dialog.Data('New class name: ', - default='_ExtractedClass')} - - def _create_refactoring(self): - self.objecter = rope.refactor.method_object.MethodObject( - self.project, self.resource, self.offset) - - def _calculate_changes(self, values, task_handle): - classname = values.get('classname') - return self.objecter.get_changes(classname) - - -class IntroduceFactory(Refactoring): - saveall = True - key = 'f' - - def _create_refactoring(self): - self.factory = rope.refactor.introduce_factory.IntroduceFactory( - self.project, self.resource, self.offset) - - def _calculate_changes(self, values, task_handle): - return self.factory.get_changes(task_handle=task_handle, **values) - - def _get_confs(self): - default = 'create_%s' % self.factory.old_name.lower() - return {'factory_name': dialog.Data('Factory name: ', default)} - - def _get_optionals(self): - return {'global_factory': dialog.Boolean('Make global: ', True), - 'resources': self.resources_option} - - -class ChangeSignature(Refactoring): - saveall = True - key = 's' - - def _create_refactoring(self): - self.changer = rope.refactor.change_signature.ChangeSignature( - self.project, self.resource, self.offset) - - def _calculate_changes(self, values, task_handle): - signature = values.get('signature') - args = re.sub(r'[\s\(\)]+', '', signature).split(',') - olds = [arg[0] for arg in self._get_args()] - - changers = [] - for arg in list(olds): - if arg in args: - continue - changers.append(rope.refactor.change_signature. - ArgumentRemover(olds.index(arg))) - olds.remove(arg) - - order = [] - for index, arg in enumerate(args): - if arg not in olds: - changers.append(rope.refactor.change_signature. - ArgumentAdder(index, arg)) - olds.insert(index, arg) - order.append(olds.index(arg)) - changers.append(rope.refactor.change_signature. - ArgumentReorderer(order, autodef='None')) - - del values['signature'] - return self.changer.get_changes(changers, task_handle=task_handle, - **values) - - def _get_args(self): - if hasattr(self.changer, 'get_args'): - return self.changer.get_args() - return self.changer.get_definition_info().args_with_defaults - - def _get_confs(self): - args = [] - for arg, default in self._get_args(): - args.append(arg) - signature = '(' + ', '.join(args) + ')' - return {'signature': dialog.Data('Change the signature: ', - default=signature)} - - def _get_optionals(self): - opts = {'resources': self.resources_option} - if self.changer.is_method(): - opts['in_hierarchy'] = dialog.Boolean('Rename methods in ' - 'class hierarchy: ') - return opts - - -class _GenerateElement(Refactoring): - - def _create_refactoring(self): - kind = self.name.split('_')[-1] - self.generator = rope.contrib.generate.create_generate( - kind, self.project, self.resource, self.offset) - - def _calculate_changes(self, values, task_handle): - return self.generator.get_changes() - - def _done(self): - resource, lineno = self.generator.get_location() - self.interface._goto_location(resource, lineno) - - -class GenerateVariable(_GenerateElement): - key = 'n v' - - -class GenerateFunction(_GenerateElement): - key = 'n f' - - -class GenerateClass(_GenerateElement): - key = 'n c' - - -class GenerateModule(_GenerateElement): - key = 'n m' - - -class GeneratePackage(_GenerateElement): - key = 'n p' - - -def refactoring_name(refactoring): - classname = refactoring.__name__ - result = [] - for c in classname: - if result and c.isupper(): - result.append('_') - result.append(c.lower()) - name = ''.join(result) - return name - -def _resources(project, text): - if text is None or text.strip() == '': - return None - return file_filter.resources(project, text) - - -def runtask(env, command, name, interrupts=True): - return RunTask(env, command, name, interrupts)() - -class RunTask(object): - - def __init__(self, env, task, name, interrupts=True): - self.env = env - self.task = task - self.name = name - self.interrupts = interrupts - - def __call__(self): - handle = taskhandle.TaskHandle(name=self.name) - progress = self.env.create_progress(self.name) - def update_progress(): - jobset = handle.current_jobset() - if jobset: - percent = jobset.get_percent_done() - if percent is not None: - progress.update(percent) - handle.add_observer(update_progress) - result = self.task(handle) - progress.done() - return result diff --git a/.vim/bundle/python-mode/pylibs/ropemode/tests/__init__.py b/.vim/bundle/python-mode/pylibs/ropemode/tests/__init__.py diff --git a/.vim/bundle/python-mode/pylibs/ropemode/tests/decorators_test.py b/.vim/bundle/python-mode/pylibs/ropemode/tests/decorators_test.py @@ -1,48 +0,0 @@ -#!/usr/bin/env python -import os -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) - -import unittest - -from ropemode.decorators import Logger - - -class LoggerTests(unittest.TestCase): - def test_Logger_called_with_no_args_doesnt_raise_TypeError(self): - """ - When not initialized with a message display method, Logger - prints the message to stdout without raising an exception. - """ - logger = Logger() - try: - logger("a message") - except TypeError: - self.fail("logger raised TypeError unexpectedly") - - -class LoggerMessageHandlerTests(unittest.TestCase): - def setUp(self): - self.message = "" - self.logger = Logger() - self.logger.message = self._echo - - def _echo(self, message): - self.message += message - - def test_message_handler_with_no_short_message(self): - """Test that message handler is called""" - self.logger("a message") - self.assertEqual(self.message, "a message") - - def test_only_short_True(self): - """Test that only_short=True prints only the short message""" - self.logger.only_short = True - self.logger("a long message", "a short message") - self.assertEqual(self.message, "a short message") - - def test_only_short_False(self): - """Test that only_short=False prints both messages""" - self.logger.only_short = False - self.logger("a long message", "a short message") - self.assertEqual(self.message, "a long messagea short message") diff --git a/.vim/bundle/python-mode/pylibs/ropevim.py b/.vim/bundle/python-mode/pylibs/ropevim.py @@ -1,453 +0,0 @@ -"""ropevim, a vim mode for using rope refactoring library""" -import glob -import os -import tempfile -import re - -from ropemode import decorators -from ropemode import environment -from ropemode import interface - -import vim - -# Gobal var to be able to shutup output -_rope_quiet = False - - -class VimUtils(environment.Environment): - - def __init__(self, *args, **kwargs): - super(VimUtils, self).__init__(*args, **kwargs) - self.completeopt = vim.eval('&completeopt') - self.preview = 'preview' in self.completeopt - - def ask(self, prompt, default=None, starting=None): - if starting is None: - starting = '' - if default is not None: - prompt = prompt + '[{0}] '.format(default) - result = call('input("{0}", "{1}")'.format(prompt, starting)) - if default is not None and result == '': - return default - return result - - def ask_values(self, prompt, values, default=None, - starting=None, show_values=None): - if show_values or (show_values is None and len(values) < 14): - self._print_values(values) - if default is not None: - prompt = prompt + '[{0}] '.format(default) - starting = starting or '' - _completer.values = values - answer = call( - 'input("{0}", "{1}", "customlist,RopeValueCompleter")'.format( - prompt, starting - ) - ) - if answer is None: - if 'cancel' in values: - return 'cancel' - return - if default is not None and not answer: - return default - if answer.isdigit() and 0 <= int(answer) < len(values): - return values[int(answer)] - return answer - - def _print_values(self, values): - numbered = [] - for index, value in enumerate(values): - numbered.append('%s. %s' % (index, str(value))) - echo('\n'.join(numbered) + '\n') - - def ask_directory(self, prompt, default=None, starting=None): - return call('input("{0}", ".", "dir")'.format(prompt)) - - def _update_proposals(self, values): - self.completeopt = vim.eval('&completeopt') - self.preview = 'preview' in self.completeopt - - if not self.get('extended_complete'): - return u','.join(u"'{0}'".format(self._completion_text(proposal)) - for proposal in values) - - return u','.join(self._extended_completion(proposal) - for proposal in values) - - def _command(self, command, encode=False): - if encode: - command = command.encode(self._get_encoding()) - vim.command(command) - - def ask_completion(self, prompt, values, starting=None): - if self.get('vim_completion') and 'i' in call('mode()'): - proposals = self._update_proposals(values) - col = int(call('col(".")')) - if starting: - col -= len(starting) - self._command(u'call complete({0}, [{1}])'.format(col, proposals), - encode=True) - return None - - return self.ask_values(prompt, values, starting=starting, - show_values=False) - - def message(self, message): - echo(message) - - def yes_or_no(self, prompt): - return self.ask_values(prompt, ['yes', 'no']) == 'yes' - - def y_or_n(self, prompt): - return self.yes_or_no(prompt) - - def get(self, name, default=None): - vimname = 'g:pymode_rope_{0}'.format(name) - if str(vim.eval('exists("{0}")'.format(vimname))) == '0': - return default - result = vim.eval(vimname) - if isinstance(result, str) and result.isdigit(): - return int(result) - return result - - def get_offset(self): - result = self._position_to_offset(*self.cursor) - return result - - @staticmethod - def _get_encoding(): - return vim.eval('&encoding') or 'utf-8' - - def _encode_line(self, line): - return line.encode(self._get_encoding()) - - def _decode_line(self, line): - return line.decode(self._get_encoding()) - - def _position_to_offset(self, lineno, colno): - result = min(colno, len(self.buffer[lineno - 1]) + 1) - for line in self.buffer[:lineno - 1]: - line = self._decode_line(line) - result += len(line) + 1 - return result - - def get_text(self): - return self._decode_line('\n'.join(self.buffer)) + u'\n' - - def get_region(self): - start = self._position_to_offset(*self.buffer.mark('<')) - end = self._position_to_offset(*self.buffer.mark('>')) - return start, end - - @property - def buffer(self): - return vim.current.buffer - - def _get_cursor(self): - lineno, col = vim.current.window.cursor - line = self._decode_line(vim.current.line[:col]) - col = len(line) - return (lineno, col) - - def _set_cursor(self, cursor): - lineno, col = cursor - line = self._decode_line(vim.current.line) - line = self._encode_line(line[:col]) - col = len(line) - vim.current.window.cursor = (lineno, col) - - cursor = property(_get_cursor, _set_cursor) - - @staticmethod - def get_cur_dir(): - return vim.eval('getcwd()') - - def filename(self): - return self.buffer.name - - def is_modified(self): - return vim.eval('&modified') - - def goto_line(self, lineno): - self.cursor = (lineno, 0) - - def insert_line(self, line, lineno): - self.buffer[lineno - 1:lineno - 1] = [line] - - def insert(self, text): - lineno, colno = self.cursor - line = self.buffer[lineno - 1] - self.buffer[lineno - 1] = line[:colno] + text + line[colno:] - self.cursor = (lineno, colno + len(text)) - - def delete(self, start, end): - lineno1, colno1 = self._offset_to_position(start - 1) - lineno2, colno2 = self._offset_to_position(end - 1) - lineno, colno = self.cursor - if lineno1 == lineno2: - line = self.buffer[lineno1 - 1] - self.buffer[lineno1 - 1] = line[:colno1] + line[colno2:] - if lineno == lineno1 and colno >= colno1: - diff = colno2 - colno1 - self.cursor = (lineno, max(0, colno - diff)) - - def _offset_to_position(self, offset): - text = self.get_text() - lineno = text.count('\n', 0, offset) + 1 - try: - colno = offset - text.rindex('\n', 0, offset) - 1 - except ValueError: - colno = offset - return lineno, colno - - def filenames(self): - result = [] - for buffer in vim.buffers: - if buffer.name: - result.append(buffer.name) - return result - - def save_files(self, filenames): - vim.command('wall') - - def reload_files(self, filenames, moves={}): - initial = self.filename() - for filename in filenames: - self.find_file(moves.get(filename, filename), force=True) - if initial: - self.find_file(initial) - - def find_file(self, filename, readonly=False, other=False, force=False): - if filename != self.filename() or force: - if other: - vim.command(other) - filename = '\\ '.join(s.rstrip() for s in filename.split()) - vim.command('e %s' % filename) - if readonly: - vim.command('set nomodifiable') - - def create_progress(self, name): - return VimProgress(name) - - def current_word(self): - return vim.eval('expand("<cword>")') - - def push_mark(self): - vim.command('mark `') - - def prefix_value(self, prefix): - return prefix - - def show_occurrences(self, locations): - self._quickfixdefs(locations) - vim.command('cwindow') - - def _quickfixdefs(self, locations): - filename = os.path.join(tempfile.gettempdir(), tempfile.mktemp()) - try: - self._writedefs(locations, filename) - vim.command('let old_errorfile = &errorfile') - vim.command('let old_errorformat = &errorformat') - vim.command('set errorformat=%f:%l:\ %m') - vim.command('cfile ' + filename) - vim.command('let &errorformat = old_errorformat') - vim.command('let &errorfile = old_errorfile') - finally: - os.remove(filename) - - def _writedefs(self, locations, filename): - tofile = open(filename, 'w') - try: - for location in locations: - err = '%s:%d: - %s\n' % (location.filename, - location.lineno, location.note) - echo(err) - tofile.write(err) - finally: - tofile.close() - - def show_doc(self, docs, altview=False): - if docs: - vim.command( - 'call pymode#ShowStr("{0}")'.format(docs.replace('"', '\\"')) - ) - - def preview_changes(self, diffs): - echo(diffs) - return self.y_or_n('Do the changes? ') - - def local_command(self, name, callback, key=None, prefix=False): - self._add_command(name, callback, key, prefix, - prekey=self.get('local_prefix')) - - def global_command(self, name, callback, key=None, prefix=False): - self._add_command(name, callback, key, prefix, - prekey=self.get('global_prefix')) - - def add_hook(self, name, callback, hook): - mapping = {'before_save': 'FileWritePre,BufWritePre', - 'after_save': 'FileWritePost,BufWritePost', - 'exit': 'VimLeave'} - self._add_function(name, callback) - vim.command( - 'autocmd {0} *.py call {1}()'.format( - mapping[hook], _vim_name(name) - ) - ) - - def _add_command(self, name, callback, key, prefix, prekey): - self._add_function(name, callback, prefix) - vim.command( - 'command! -range {0} call {1}()'.format( - _vim_name(name), _vim_name(name) - ) - ) - if key is not None: - key = prekey + key.replace(' ', '') - vim.command( - 'noremap {0} :call {1}()<cr>'.format(key, _vim_name(name)) - ) - - def _add_function(self, name, callback, prefix=False): - globals()[name] = callback - arg = 'None' if prefix else '' - vim.command( - 'function! {0}()\n' - 'python ropevim.{1}({2})\n' - 'endfunction\n'.format(_vim_name(name), name, arg) - ) - - def _completion_data(self, proposal): - return proposal - - _docstring_re = re.compile('^[\s\t\n]*([^\n]*)') - - def _extended_completion(self, proposal): - # we are using extended complete and return dicts instead of strings. - # `ci` means "completion item". see `:help complete-items` - word, _, menu = map(lambda x: x.strip(), proposal.name.partition(':')) - ci = dict( - word=word, - info='', - kind=''.join( - s if s not in 'aeyuo' else '' for s in proposal.type)[:3], - menu=menu or '') - - if proposal.scope == 'parameter_keyword': - default = proposal.get_default() - ci["menu"] += '*' if default is None else '= {0}'.format(default) - - if self.preview and not ci['menu']: - doc = proposal.get_doc() - ci['info'] = self._docstring_re.match(doc).group(1) if doc else '' - - return self._conv(ci) - - def _conv(self, obj): - if isinstance(obj, dict): - return u'{' + u','.join([ - u"{0}:{1}".format(self._conv(key), self._conv(value)) - for key, value in obj.iteritems()]) + u'}' - return u'"{0}"'.format(str(obj).replace(u'"', u'\\"')) - - -def _vim_name(name): - tokens = name.split('_') - newtokens = ['Rope'] + [token.title() for token in tokens] - return ''.join(newtokens) - - -class VimProgress(object): - - def __init__(self, name): - self.name = name - self.last = 0 - status('{0} ... '.format(self.name)) - - def update(self, percent): - try: - vim.eval('getchar(0)') - except vim.error: - raise KeyboardInterrupt( - 'Task {0} was interrupted!'.format(self.name) - ) - if percent > self.last + 4: - status('{0} ... {1}%'.format(self.name, percent)) - self.last = percent - - def done(self): - status('{0} ... done'.format(self.name)) - - -def echo(message): - if isinstance(message, unicode): - message = message.encode(vim.eval('&encoding')) - print message - - -def status(message): - if _rope_quiet: - return - - if isinstance(message, unicode): - message = message.encode(vim.eval('&encoding')) - vim.command('redraw | echon "{0}"'.format(message)) - - -def call(command): - return vim.eval(command) - - -class _ValueCompleter(object): - - def __init__(self): - self.values = [] - vim.command('python import vim') - vim.command('function! RopeValueCompleter(A, L, P)\n' - 'python args = [vim.eval("a:" + p) for p in "ALP"]\n' - 'python ropevim._completer(*args)\n' - 'return s:completions\n' - 'endfunction\n') - - def __call__(self, arg_lead, cmd_line, cursor_pos): - # don't know if self.values can be empty but better safe then sorry - if self.values: - if not isinstance(self.values[0], basestring): - result = [proposal.name for proposal in self.values - if proposal.name.startswith(arg_lead)] - else: - result = [proposal for proposal in self.values - if proposal.startswith(arg_lead)] - vim.command('let s:completions = {0}'.format(result)) - - -class RopeMode(interface.RopeMode): - @decorators.global_command('o') - def open_project(self, root=None, quiet=False): - global _rope_quiet - _rope_quiet = quiet - - super(RopeMode, self).open_project(root=root) - rope_project_dir = os.path.join(self.project.address, '.ropeproject') - vimfiles = glob.glob(os.path.join(rope_project_dir, '*.vim')) - - if not vimfiles: - return - - txt = 'Sourcing vim files under \'.ropeproject/\'' - progress = self.env.create_progress(txt) - for idx, vimfile in enumerate(sorted(vimfiles)): - progress.name = txt + ' ({0})'.format(os.path.basename(vimfile)) - vim.command(':silent source {0}'.format(vimfile)) - progress.update(idx * 100 / len(vimfiles)) - - progress.name = txt - progress.done() - -decorators.logger.message = echo -decorators.logger.only_short = True - -_completer = _ValueCompleter() - -_env = VimUtils() -_interface = RopeMode(env=_env) diff --git a/.vim/bundle/python-mode/pylint.ini b/.vim/bundle/python-mode/pylint.ini @@ -1,25 +0,0 @@ -[MESSAGES CONTROL] -# Disable the message(s) with the given id(s). -# http://pylint-messages.wikidot.com/all-codes -# -# C0103: Invalid name "%s" (should match %s) -# C0111: Missing docstring -# E1101: %s %r has no %r member -# R0901: Too many ancestors (%s/%s) -# R0902: Too many instance attributes (%s/%s) -# R0903: Too few public methods (%s/%s) -# R0904: Too many public methods (%s/%s) -# R0913: Too many arguments (%s/%s) -# R0915: Too many statements (%s/%s) -# W0141: Used builtin function %r -# W0142: Used * or ** magic -# W0221: Arguments number differs from %s method -# W0232: Class has no __init__ method -# W0401: Wildcard import %s -# W0613: Unused argument %r -# W0631: Using possibly undefined loop variable %r -# -disable = C0103,C0111,E1101,R0901,R0902,R0903,R0904,R0913,R0915,W0141,W0142,W0221,W0232,W0401,W0613,W0631 - -[TYPECHECK] -generated-members = REQUEST,acl_users,aq_parent,objects,DoesNotExist,_meta,status_code,content,context diff --git a/.vim/bundle/python-mode/syntax/pyrex.vim b/.vim/bundle/python-mode/syntax/pyrex.vim @@ -1,71 +0,0 @@ -" Vim syntax file -" Language: Pyrex -" Maintainer: John Tyree -" Last Change: 2012 Nov 06 - -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") - finish -endif - -" Read the Python syntax to start with -if version < 600 - so <sfile>:p:h/python.vim -else - runtime! syntax/python.vim - unlet b:current_syntax -endif - -" Pyrex extentions -syn keyword pyrexStatement nogil inline typedef ctypedef sizeof -syn keyword pyrexType Py_ssize_t int long short float double char object void -" Here we want slightly different behavior depending on whether we're declaring -" variables or functions. c[p]def should work on the top level as a keyword, but -" should ALSO work to identify functions and classes. -syn match pyrexStatement "\<cp\?def\>" -syn match pyrexStatement "\<cp\?def\>[^=]*(\@=" contains=pythonStatement,pyrexStatement,pythonFunction,pyrexType skipwhite -syn keyword pyrexType signed unsigned -syn keyword pyrexStructure struct union enum -syn keyword pyrexInclude include cimport -syn keyword pyrexAccess public private property readonly extern -" If someome wants Python's built-ins highlighted probably he -" also wants Pyrex's built-ins highlighted -if exists("python_highlight_builtins") || exists("pyrex_highlight_builtins") - syn keyword pyrexBuiltin NULL -endif - -" This deletes "from" from the keywords and re-adds it as a -" match with lower priority than pyrexForFrom -syn clear pythonInclude -syn keyword pythonInclude import -syn match pythonInclude "\<from\>" - -" With "for[^:]*\zsfrom" VIM does not match "for" anymore, so -" I used the slower "\@<=" form -syn match pyrexForFrom "\(\<for\>[^:]*\)\@<=\<from\>" - -" Default highlighting -if version >= 508 || !exists("did_pyrex_syntax_inits") - if version < 508 - let did_pyrex_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink pyrexStatement Statement - HiLink pyrexType Type - HiLink pyrexStructure Structure - HiLink pyrexInclude PreCondit - HiLink pyrexAccess pyrexStatement - if exists("python_highlight_builtins") || exists("pyrex_highlight_builtins") - HiLink pyrexBuiltin Function - endif - HiLink pyrexForFrom Statement - - delcommand HiLink -endif - -let b:current_syntax = "pyrex" diff --git a/.vim/bundle/python-mode/syntax/python.vim b/.vim/bundle/python-mode/syntax/python.vim @@ -1,298 +0,0 @@ -" vim: ft=vim:fdm=marker -" -runtime ftplugin/python/init-pymode.vim - -" DESC: Disable script loading -if !pymode#Option('syntax') || pymode#Default('b:current_syntax', 'python') - finish -endif - -" For version 5.x: Clear all syntax items -if version < 600 - syntax clear -endif - -" Highlight all -call pymode#Default('g:pymode_syntax_all', 1) - -" Keywords {{{ -" ============ - - syn keyword pythonStatement break continue del - syn keyword pythonStatement exec return - syn keyword pythonStatement pass raise - syn keyword pythonStatement global assert - syn keyword pythonStatement lambda yield - syn keyword pythonStatement with as - syn keyword pythonStatement def class nextgroup=pythonFunction skipwhite - syn match pythonFunction "[a-zA-Z_][a-zA-Z0-9_]*" display contained - syn keyword pythonRepeat for while - syn keyword pythonConditional if elif else - syn keyword pythonInclude import from - syn keyword pythonException try except finally - syn keyword pythonOperator and in is not or - - if !pymode#Default("g:pymode_syntax_print_as_function", 0) || !g:pymode_syntax_print_as_function - syn keyword pythonStatement print - endif - -" }}} - - -" Decorators {{{ -" ============== - - syn match pythonDecorator "@" display nextgroup=pythonDottedName skipwhite - syn match pythonDottedName "[a-zA-Z_][a-zA-Z0-9_]*\(\.[a-zA-Z_][a-zA-Z0-9_]*\)*" display contained - syn match pythonDot "\." display containedin=pythonDottedName - -" }}} - - -" Comments {{{ -" ============ - - syn match pythonComment "#.*$" display contains=pythonTodo,@Spell - syn match pythonRun "\%^#!.*$" - syn match pythonCoding "\%^.*\(\n.*\)\?#.*coding[:=]\s*[0-9A-Za-z-_.]\+.*$" - syn keyword pythonTodo TODO FIXME XXX contained - -" }}} - - -" Errors {{{ -" ========== - - syn match pythonError "\<\d\+\D\+\>" display - syn match pythonError "[$?]" display - syn match pythonError "[&|]\{2,}" display - syn match pythonError "[=]\{3,}" display - - " Indent errors (mix space and tabs) - if !pymode#Default('g:pymode_syntax_indent_errors', g:pymode_syntax_all) || g:pymode_syntax_indent_errors - syn match pythonIndentError "^\s*\( \t\|\t \)\s*\S"me=e-1 display - endif - - " Trailing space errors - if !pymode#Default('g:pymode_syntax_space_errors', g:pymode_syntax_all) || g:pymode_syntax_space_errors - syn match pythonSpaceError "\s\+$" display - endif - -" }}} - - -" Strings {{{ -" =========== - - syn region pythonString start=+[bB]\='+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonEscape,pythonEscapeError,@Spell - syn region pythonString start=+[bB]\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonEscape,pythonEscapeError,@Spell - syn region pythonString start=+[bB]\="""+ end=+"""+ keepend contains=pythonEscape,pythonEscapeError,pythonDocTest2,pythonSpaceError,@Spell - syn region pythonString start=+[bB]\='''+ end=+'''+ keepend contains=pythonEscape,pythonEscapeError,pythonDocTest,pythonSpaceError,@Spell - - syn match pythonEscape +\\[abfnrtv'"\\]+ display contained - syn match pythonEscape "\\\o\o\=\o\=" display contained - syn match pythonEscapeError "\\\o\{,2}[89]" display contained - syn match pythonEscape "\\x\x\{2}" display contained - syn match pythonEscapeError "\\x\x\=\X" display contained - syn match pythonEscape "\\$" - - " Unicode - syn region pythonUniString start=+[uU]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,@Spell - syn region pythonUniString start=+[uU]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,@Spell - syn region pythonUniString start=+[uU]"""+ end=+"""+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,pythonDocTest2,pythonSpaceError,@Spell - syn region pythonUniString start=+[uU]'''+ end=+'''+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,pythonDocTest,pythonSpaceError,@Spell - - syn match pythonUniEscape "\\u\x\{4}" display contained - syn match pythonUniEscapeError "\\u\x\{,3}\X" display contained - syn match pythonUniEscape "\\U\x\{8}" display contained - syn match pythonUniEscapeError "\\U\x\{,7}\X" display contained - syn match pythonUniEscape "\\N{[A-Z ]\+}" display contained - syn match pythonUniEscapeError "\\N{[^A-Z ]\+}" display contained - - " Raw strings - syn region pythonRawString start=+[rR]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonRawEscape,@Spell - syn region pythonRawString start=+[rR]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonRawEscape,@Spell - syn region pythonRawString start=+[rR]"""+ end=+"""+ keepend contains=pythonDocTest2,pythonSpaceError,@Spell - syn region pythonRawString start=+[rR]'''+ end=+'''+ keepend contains=pythonDocTest,pythonSpaceError,@Spell - - syn match pythonRawEscape +\\['"]+ display transparent contained - - " Unicode raw strings - syn region pythonUniRawString start=+[uU][rR]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonRawEscape,pythonUniRawEscape,pythonUniRawEscapeError,@Spell - syn region pythonUniRawString start=+[uU][rR]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonRawEscape,pythonUniRawEscape,pythonUniRawEscapeError,@Spell - syn region pythonUniRawString start=+[uU][rR]"""+ end=+"""+ keepend contains=pythonUniRawEscape,pythonUniRawEscapeError,pythonDocTest2,pythonSpaceError,@Spell - syn region pythonUniRawString start=+[uU][rR]'''+ end=+'''+ keepend contains=pythonUniRawEscape,pythonUniRawEscapeError,pythonDocTest,pythonSpaceError,@Spell - - syn match pythonUniRawEscape "\([^\\]\(\\\\\)*\)\@<=\\u\x\{4}" display contained - syn match pythonUniRawEscapeError "\([^\\]\(\\\\\)*\)\@<=\\u\x\{,3}\X" display contained - - " String formatting - if !pymode#Default('g:pymode_syntax_string_formatting', g:pymode_syntax_all) || g:pymode_syntax_string_formatting - syn match pythonStrFormatting "%\(([^)]\+)\)\=[-#0 +]*\d*\(\.\d\+\)\=[hlL]\=[diouxXeEfFgGcrs%]" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString - syn match pythonStrFormatting "%[-#0 +]*\(\*\|\d\+\)\=\(\.\(\*\|\d\+\)\)\=[hlL]\=[diouxXeEfFgGcrs%]" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString - endif - - " Str.format syntax - if !pymode#Default('g:pymode_syntax_string_format', g:pymode_syntax_all) || g:pymode_syntax_string_format - syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString - syn match pythonStrFormat "{\([a-zA-Z_][a-zA-Z0-9_]*\|\d\+\)\(\.[a-zA-Z_][a-zA-Z0-9_]*\|\[\(\d\+\|[^!:\}]\+\)\]\)*\(![rs]\)\=\(:\({\([a-zA-Z_][a-zA-Z0-9_]*\|\d\+\)}\|\([^}]\=[<>=^]\)\=[ +-]\=#\=0\=\d*\(\.\d\+\)\=[bcdeEfFgGnoxX%]\=\)\=\)\=}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString - endif - - " String templates - if !pymode#Default('g:pymode_syntax_string_templates', g:pymode_syntax_all) || g:pymode_syntax_string_templates - syn match pythonStrTemplate "\$\$" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString - syn match pythonStrTemplate "\${[a-zA-Z_][a-zA-Z0-9_]*}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString - syn match pythonStrTemplate "\$[a-zA-Z_][a-zA-Z0-9_]*" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString - endif - - " DocTests - if !pymode#Default('g:pymode_syntax_doctests', g:pymode_syntax_all) || g:pymode_syntax_doctests - syn region pythonDocTest start="^\s*>>>" end=+'''+he=s-1 end="^\s*$" contained - syn region pythonDocTest2 start="^\s*>>>" end=+"""+he=s-1 end="^\s*$" contained - endif - -" }}} - -" Numbers {{{ -" =========== - - syn match pythonHexError "\<0[xX]\x*[g-zG-Z]\x*[lL]\=\>" display - syn match pythonHexNumber "\<0[xX]\x\+[lL]\=\>" display - syn match pythonOctNumber "\<0[oO]\o\+[lL]\=\>" display - syn match pythonBinNumber "\<0[bB][01]\+[lL]\=\>" display - syn match pythonNumber "\<\d\+[lLjJ]\=\>" display - syn match pythonFloat "\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>" display - syn match pythonFloat "\<\d\+[eE][+-]\=\d\+[jJ]\=\>" display - syn match pythonFloat "\<\d\+\.\d*\([eE][+-]\=\d\+\)\=[jJ]\=" display - syn match pythonOctError "\<0[oO]\=\o*[8-9]\d*[lL]\=\>" display - syn match pythonBinError "\<0[bB][01]*[2-9]\d*[lL]\=\>" display - -" }}} - -" Builtins {{{ -" ============ - - " Builtin objects and types - if !pymode#Default('g:pymode_syntax_builtin_objs', g:pymode_syntax_all) || g:pymode_syntax_builtin_objs - syn keyword pythonBuiltinObj True False Ellipsis None NotImplemented - syn keyword pythonBuiltinObj __debug__ __doc__ __file__ __name__ __package__ - syn keyword pythonBuiltinObj self - endif - - " Builtin functions - if !pymode#Default('g:pymode_syntax_builtin_funcs', g:pymode_syntax_all) || g:pymode_syntax_builtin_funcs - syn keyword pythonBuiltinFunc __import__ abs all any apply - syn keyword pythonBuiltinFunc basestring bin bool buffer bytearray bytes callable - syn keyword pythonBuiltinFunc chr classmethod cmp coerce compile complex - syn keyword pythonBuiltinFunc delattr dict dir divmod enumerate eval - syn keyword pythonBuiltinFunc execfile file filter float format frozenset getattr - syn keyword pythonBuiltinFunc globals hasattr hash help hex id - syn keyword pythonBuiltinFunc input int intern isinstance - syn keyword pythonBuiltinFunc issubclass iter len list locals long map max - syn keyword pythonBuiltinFunc min next object oct open ord - syn keyword pythonBuiltinFunc pow property range - syn keyword pythonBuiltinFunc raw_input reduce reload repr - syn keyword pythonBuiltinFunc reversed round set setattr - syn keyword pythonBuiltinFunc slice sorted staticmethod str sum super tuple - syn keyword pythonBuiltinFunc type unichr unicode vars xrange zip - - if pymode#Default('g:pymode_syntax_print_as_function', 0) && g:pymode_syntax_print_as_function - syn keyword pythonBuiltinFunc print - endif - - endif - - " Builtin exceptions and warnings - if !pymode#Default('g:pymode_syntax_highlight_exceptions', g:pymode_syntax_all) || 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 NotImplementedError OSError OverflowError - syn keyword pythonExClass ReferenceError RuntimeError StopIteration - syn keyword pythonExClass 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 WindowsError ZeroDivisionError - syn keyword pythonExClass Warning UserWarning BytesWarning DeprecationWarning - syn keyword pythonExClass PendingDepricationWarning SyntaxWarning - syn keyword pythonExClass RuntimeWarning FutureWarning - syn keyword pythonExClass ImportWarning UnicodeWarning - endif - -" }}} - - -if !pymode#Default('g:pymode_syntax_slow_sync', 0) || g:pymode_syntax_slow_sync - syn sync minlines=2000 -else - " This is fast but code inside triple quoted strings screws it up. It - " is impossible to fix because the only way to know if you are inside a - " triple quoted string is to start from the beginning of the file. - syn sync match pythonSync grouphere NONE "):$" - syn sync maxlines=200 -endif - -" Highlight {{{ -" ============= - - hi def link pythonStatement Statement - hi def link pythonInclude Include - hi def link pythonFunction Function - hi def link pythonConditional Conditional - hi def link pythonRepeat Repeat - hi def link pythonException Exception - hi def link pythonOperator Operator - - hi def link pythonDecorator Define - hi def link pythonDottedName Function - hi def link pythonDot Normal - - hi def link pythonComment Comment - hi def link pythonCoding Special - hi def link pythonRun Special - hi def link pythonTodo Todo - - hi def link pythonError Error - hi def link pythonIndentError Error - hi def link pythonSpaceError Error - - hi def link pythonString String - hi def link pythonUniString String - hi def link pythonRawString String - hi def link pythonUniRawString String - - hi def link pythonEscape Special - hi def link pythonEscapeError Error - hi def link pythonUniEscape Special - hi def link pythonUniEscapeError Error - hi def link pythonUniRawEscape Special - hi def link pythonUniRawEscapeError Error - - hi def link pythonStrFormatting Special - hi def link pythonStrFormat Special - hi def link pythonStrTemplate Special - - hi def link pythonDocTest Special - hi def link pythonDocTest2 Special - - hi def link pythonNumber Number - hi def link pythonHexNumber Number - hi def link pythonOctNumber Number - hi def link pythonBinNumber Number - hi def link pythonFloat Float - hi def link pythonOctError Error - hi def link pythonHexError Error - hi def link pythonBinError Error - - hi def link pythonBuiltinObj Structure - hi def link pythonBuiltinFunc Function - - hi def link pythonExClass Structure - -" }}}