Adding new stuff
This commit is contained in:
parent
131691e143
commit
6c0a9f5b29
718 changed files with 0 additions and 0 deletions
11
vim-plugins/python-mode/.bumpversion.cfg
Normal file
11
vim-plugins/python-mode/.bumpversion.cfg
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[bumpversion]
|
||||
commit = True
|
||||
current_version = 0.9.0
|
||||
files = plugin/pymode.vim
|
||||
tag = True
|
||||
tag_name = {new_version}
|
||||
|
||||
[bumpversion:file:doc/pymode.txt]
|
||||
search = Version: {current_version}
|
||||
replace = Version: {new_version}
|
||||
|
||||
1
vim-plugins/python-mode/.ruby-gemset
Normal file
1
vim-plugins/python-mode/.ruby-gemset
Normal file
|
|
@ -0,0 +1 @@
|
|||
vim-flavor
|
||||
1
vim-plugins/python-mode/.ruby-version
Normal file
1
vim-plugins/python-mode/.ruby-version
Normal file
|
|
@ -0,0 +1 @@
|
|||
ruby-1.9.3
|
||||
6
vim-plugins/python-mode/.travis.yml
Normal file
6
vim-plugins/python-mode/.travis.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
language: ruby
|
||||
python: "2.7"
|
||||
rvm:
|
||||
- 1.9.3
|
||||
script:
|
||||
- make travis
|
||||
64
vim-plugins/python-mode/AUTHORS
Normal file
64
vim-plugins/python-mode/AUTHORS
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
Maintainers:
|
||||
|
||||
* Kirill Klenov <horneds@gmail.com>
|
||||
* Bryce Guinta (https://github.com/brycepg)
|
||||
|
||||
|
||||
Contributors:
|
||||
|
||||
* Alvin Francis (http://github.com/alvinfrancis);
|
||||
* Andriy Kohut (https://github.com/andriykohut)
|
||||
* Anler Hp (http://github.com/ikame);
|
||||
* Anton Parkhomenko (http://github.com/chuwy);
|
||||
* Ashley Hewson (http://github.com/ashleyh);
|
||||
* Benjamin Ruston (http://github.com/bruston);
|
||||
* Boris Filippov (http://github.com/frenzykryger);
|
||||
* Brad Mease (http://github.com/bmease)
|
||||
* Brendan Maguire (https://github.com/brendanmaguire)
|
||||
* Daniel Hahler (http://github.com/blueyed)
|
||||
* David Vogt (http://github.com/winged);
|
||||
* Denis Kasak (http://github.com/dkasak);
|
||||
* Dimitrios Semitsoglou-Tsiapos (https://github.com/dset0x);
|
||||
* Dirk Wallenstein (http://github.com/dirkwallenstein);
|
||||
* Florent Xicluna (http://github.com/florentx);
|
||||
* Fredrik Henrysson (http://github.com/fhenrysson);
|
||||
* Igor Guerrero (http://github.com/igorgue);
|
||||
* Jacob Niehus (https://github.com/wilywampa)
|
||||
* Jason Harvey (http://github.com/alienth)
|
||||
* Jay Rainey (https://github.com/jawrainey)
|
||||
* Jonathan McCall (http://github.com/Jonnymcc);
|
||||
* Kevin Deldycke (http://github.com/kdeldycke);
|
||||
* Kurtis Rader (https://github.com/krader1961);
|
||||
* Lawrence Akka (https://github.com/lawrenceakka);
|
||||
* Lowe Thiderman (http://github.com/thiderman);
|
||||
* Martin Brochhaus (http://github.com/mbrochh);
|
||||
* Matt Dodge (https://github.com/mattdodge);
|
||||
* Matthew Moses (http://github.com/mlmoses);
|
||||
* Maxim (https://github.com/mpyatishev);
|
||||
* Mel Boyce (http://github.com/syngin);
|
||||
* Mohammed (http://github.com/mbadran);
|
||||
* Naoya Inada (http://github.com/naoina);
|
||||
* Nate Zhang (https://github.com/natezhang93);
|
||||
* Paweł Korzeniewski (https://github.com/korzeniewskipl);
|
||||
* Pedro Algarvio (http://github.com/s0undt3ch);
|
||||
* Phillip Cloud (http://github.com/cpcloud);
|
||||
* Piet Delport (http://github.com/pjdelport);
|
||||
* Robert David Grant (http://github.com/bgrant);
|
||||
* Robin Schneider (https://github.com/ypid);
|
||||
* Ronald Andreu Kaiser (http://github.com/cathoderay);;
|
||||
* Samir Benmendil (https://github.com/Ram-Z);
|
||||
* Sorin Ionescu (sorin-ionescu);
|
||||
* Steve Losh (http://github.com/sjl);
|
||||
* Tommy Allen (https://github.com/tweekmonster);
|
||||
* Tony Narlock (https://github.com/tony);
|
||||
* Tyler Fenby (https://github.com/TFenby);
|
||||
* Vincent Driessen (https://github.com/nvie);
|
||||
* Wang Feng (https://github.com/mapler);
|
||||
* Wayne Ye (https://github.com/WayneYe);
|
||||
* Wes Turner (https://github.com/westurner);
|
||||
* bendavis78 (https://github.com/bendavis78);
|
||||
* fwuzju (https://github.com/fwuzju);
|
||||
* lee (https://github.com/loyalpartner);
|
||||
* nixon (https://github.com/nixon);
|
||||
* sphaugh (https://github.com/sphaugh);
|
||||
* tramchamploo (https://github.com/tramchamploo);
|
||||
165
vim-plugins/python-mode/COPYING
Normal file
165
vim-plugins/python-mode/COPYING
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
356
vim-plugins/python-mode/Changelog.rst
Normal file
356
vim-plugins/python-mode/Changelog.rst
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
* Pylama updated to version 5.0.5
|
||||
* Rope libs updated
|
||||
* Add wdb to debugger list in breakpoint cmd
|
||||
* Add 'pymode_options_max_line_length' option
|
||||
* Add ability to set related checker options `:help pymode-lint-options`
|
||||
Options added: 'pymode_lint_options_pep8', 'pymode_lint_options_pep257',
|
||||
'pymode_lint_options_mccabe', 'pymode_lint_options_pyflakes',
|
||||
'pymode_lint_options_pylint'
|
||||
* Highlight comments inside class/function arg lists
|
||||
* Don't fold single line def
|
||||
* Don't skip a line when the first docstring contains text
|
||||
* Add Python documentation vertical display option
|
||||
* Rope: correct refactoring function calls
|
||||
|
||||
|
||||
## 2014-06-11 0.8.1
|
||||
-------------------
|
||||
* Pylama updated to version 3.3.2
|
||||
* Get fold's expression symbol from &fillchars;
|
||||
* Fixed error when setting g:pymode_breakpoint_cmd (expobrain);
|
||||
* Fixed code running;
|
||||
* Ability to override rope project root and .ropeproject folder
|
||||
* Added path argument to `PymodeRopeNewProject` which skips prompt
|
||||
* Disable `pymode_rope_lookup_project` by default
|
||||
* Options added:
|
||||
'pymode_rope_project_root', 'pymode_rope_ropefolder'
|
||||
|
||||
|
||||
## 2013-12-04 0.7.8b
|
||||
--------------------
|
||||
* Update indentation support;
|
||||
* Python3 support;
|
||||
* Removed pymode modeline support;
|
||||
* Disabled async code checking support;
|
||||
* Options changes:
|
||||
'pymode_doc_key' -> 'pymode_doc_bind'
|
||||
'pymode_run_key' -> 'pymode_run_bind'
|
||||
'pymode_breakpoint_key' -> 'pymode_breakpoint_bind'
|
||||
'pymode_breakpoint_template' -> 'pymode_breakpoint_cmd'
|
||||
'pymode_lint_write' -> 'pymode_lint_on_write'
|
||||
'pymode_lint_onfly' -> 'pymode_lint_on_fly'
|
||||
'pymode_lint_checker' -> 'pymode_lint_checkers'
|
||||
'pymode_lint_minheight' -> 'pymode_quickfix_minheight'
|
||||
'pymode_lint_maxheight' -> 'pymode_quickfix_maxheight'
|
||||
'pymode_rope_autocomplete_map' -> 'pymode_rope_completion_bind'
|
||||
'pymode_rope_enable_autoimport' -> 'pymode_rope_autoimport'
|
||||
|
||||
* Options removed:
|
||||
|
||||
'pymode_lint_hold', 'pymode_lint_config', 'pymode_lint_jump',
|
||||
'pymode_lint_signs_always_visible', 'pymode_rope_extended_complete',
|
||||
'pymode_rope_auto_project', 'pymode_rope_autoimport_generate',
|
||||
'pymode_rope_autoimport_underlines', 'pymode_rope_codeassist_maxfixes',
|
||||
'pymode_rope_sorted_completions', 'pymode_rope_extended_complete',
|
||||
'pymode_rope_confirm_saving', 'pymode_rope_global_prefix',
|
||||
'pymode_rope_local_prefix', 'pymode_rope_vim_completion',
|
||||
'pymode_rope_guess_project', 'pymode_rope_goto_def_newwin',
|
||||
'pymode_rope_always_show_complete_menu'
|
||||
|
||||
* Options added:
|
||||
'pymode_rope_regenerate_on_write', 'pymode_rope_completion',
|
||||
'pymode_rope_complete_on_dot', 'pymode_lint_sort',
|
||||
'pymode_rope_lookup_project', 'pymode_lint_unmodified'
|
||||
|
||||
* Commands added:
|
||||
'PymodeVirtualenv'
|
||||
|
||||
* Commands changed:
|
||||
'PyDoc' -> 'PymodeDoc'
|
||||
'Pyrun' -> 'PymodeRun'
|
||||
'PyLintToggle' -> 'PymodeLintToggle'
|
||||
'PyLint' -> 'PymodeLint'
|
||||
'PyLintAuto' -> 'PymodeLintAuto'
|
||||
'RopeOpenProject' -> 'PymodeRopeNewProject'
|
||||
'RopeUndo' -> 'PymodeRopeUndo'
|
||||
'RopeRedo' -> 'PymodeRopeRedo'
|
||||
'RopeRenameCurrentModule' -> 'PymodeRopeRenameModule'
|
||||
'RopeModuleToPackage' -> 'PymodeRopeModuleToPackage'
|
||||
'RopeGenerateAutoimportCache' -> 'PymodeRopeRegenerate'
|
||||
'RopeOrgamizeImports' -> 'PymodeRopeAutoImport'
|
||||
|
||||
* Commands removed:
|
||||
'PyLintCheckerToggle', 'RopeCloseProject', 'RopeProjectConfig',
|
||||
'RopeRename', 'RopeCreate<...>', 'RopeWriteProject', 'RopeRename',
|
||||
'RopeExtractVariable', 'RopeExtractMethod', 'RopeInline', 'RopeMove',
|
||||
'RopeRestructure', 'RopeUseFunction', 'RopeIntroduceFactory',
|
||||
'RopeChangeSignature', 'RopeMoveCurrentModule',
|
||||
'RopeGenerate<...>', 'RopeAnalizeModule', 'RopeAutoImport',
|
||||
|
||||
|
||||
## 2013-10-29 0.6.19
|
||||
--------------------
|
||||
* Added `g:pymode_rope_autocomplete_map` option;
|
||||
* Removed `g:pymode_rope_map_space` option;
|
||||
* Added PEP257 checker;
|
||||
* Support 'pudb' in breakpoints;
|
||||
* Pyrun can now operate on a range of lines, and does not need to save (c) lawrenceakka
|
||||
* Update pylama to version 1.5.0
|
||||
* Add a set of `g:pymode_lint_*_symbol` options (c) kdeldycke;
|
||||
* Support virtualenv for python3 (c) mlmoses;
|
||||
|
||||
## 2013-05-15 0.6.18
|
||||
--------------------
|
||||
* Fixed autopep8 (`PyLintAuto`) command;
|
||||
* Fix error on non-ascii characters in docstrings;
|
||||
* Update python syntax;
|
||||
|
||||
## 2013-05-03 0.6.17
|
||||
--------------------
|
||||
* Update `Pylint` to version 0.28.0;
|
||||
* Update `pyflakes` to version 0.7.3;
|
||||
* Fixed `lint_ignore` options bug;
|
||||
* Fixed encoding problems when code running;
|
||||
|
||||
## 2013-04-26 0.6.16
|
||||
--------------------
|
||||
* Improvement folding (thanks @alvinfrancis);
|
||||
|
||||
## 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
|
||||
3
vim-plugins/python-mode/Gemfile
Normal file
3
vim-plugins/python-mode/Gemfile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'vim-flavor', '~> 1.1'
|
||||
90
vim-plugins/python-mode/Makefile
Normal file
90
vim-plugins/python-mode/Makefile
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
PYMODE = $(CURDIR)/pymode
|
||||
LIBS = $(PYMODE)/libs
|
||||
PYLAMA = $(LIBS)/pylama
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
find $(CURDIR) -name "*.pyc" -delete
|
||||
rm -rf $(CURDIR)/build
|
||||
rm -rf *.deb
|
||||
|
||||
VERSION?=minor
|
||||
# target: release - Bump version
|
||||
release:
|
||||
git fetch origin
|
||||
git checkout master
|
||||
git rebase
|
||||
git merge develop
|
||||
bumpversion $(VERSION)
|
||||
git checkout develop
|
||||
git rebase
|
||||
git merge master
|
||||
git push origin develop master
|
||||
git push --tags
|
||||
|
||||
.PHONY: minor
|
||||
minor: release
|
||||
|
||||
.PHONY: patch
|
||||
patch:
|
||||
make release VERSION=patch
|
||||
|
||||
.PHONY: major
|
||||
major:
|
||||
make release VERSION=major
|
||||
|
||||
# Temporary disable rope tests on Travis
|
||||
.PHONY: travis
|
||||
travis:
|
||||
rake test
|
||||
|
||||
.PHONY: test t
|
||||
test:
|
||||
bundle install
|
||||
rm -rf $(CURDIR)/.ropeproject
|
||||
rake test
|
||||
t: test
|
||||
|
||||
.PHONY: pylama
|
||||
pylama:
|
||||
rm -rf $(PYLAMA)
|
||||
make $(PYLAMA)
|
||||
make $(PYLAMA)/lint/pylama_pylint
|
||||
|
||||
.PHONY: rope
|
||||
rope:
|
||||
@git clone https://github.com/python-rope/rope.git $(CURDIR)/_/rope
|
||||
@rm -rf $(CURDIR)/pymode/libs/rope
|
||||
@cp -r $(CURDIR)/_/rope/rope $(CURDIR)/pymode/libs/.
|
||||
|
||||
$(PYLAMA):
|
||||
cp -r $$PRJDIR/pylama/pylama $(PYLAMA)
|
||||
|
||||
$(PYLAMA)/lint/pylama_pylint:
|
||||
cp -r $$PRJDIR/pylama/plugins/pylama_pylint/pylama_pylint/ $(PYLAMA)/lint/pylama_pylint
|
||||
|
||||
$(CURDIR)/build:
|
||||
mkdir -p $(CURDIR)/build/usr/share/vim/addons
|
||||
mkdir -p $(CURDIR)/build/usr/share/vim/registry
|
||||
cp -r after autoload doc ftplugin plugin pymode syntax $(CURDIR)/build/usr/share/vim/addons/.
|
||||
cp -r python-mode.yaml $(CURDIR)/build/usr/share/vim/registry/.
|
||||
|
||||
PACKAGE_VERSION?=$(shell git describe --tags `git rev-list master --tags --max-count=1`)
|
||||
PACKAGE_NAME="vim-python-mode"
|
||||
PACKAGE_MAINTAINER="Kirill Klenov <horneds@gmail.com>"
|
||||
PACKAGE_URL=http://github.com/klen/python-mode
|
||||
deb: clean $(CURDIR)/build
|
||||
@fpm -s dir -t deb -a all \
|
||||
-n $(PACKAGE_NAME) \
|
||||
-v $(PACKAGE_VERSION) \
|
||||
-m $(PACKAGE_MAINTAINER) \
|
||||
--url $(PACKAGE_URL) \
|
||||
--license "GNU lesser general public license" \
|
||||
--description "Vim-Swissknife for python" \
|
||||
--deb-user root \
|
||||
--deb-group root \
|
||||
-C $(CURDIR)/build \
|
||||
-d "python2.7" \
|
||||
-d "vim-addon-manager" \
|
||||
usr
|
||||
@mv *.deb ~/Dropbox/projects/deb/load
|
||||
367
vim-plugins/python-mode/README.rst
Normal file
367
vim-plugins/python-mode/README.rst
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
|logo| Python-mode, Python in VIM
|
||||
#################################
|
||||
|
||||
.. image:: https://travis-ci.org/klen/python-mode.png?branch=develop
|
||||
:target: https://travis-ci.org/klen/python-mode
|
||||
|
||||
-----
|
||||
|
||||
*The project needs contributors*
|
||||
|
||||
** Python-mode Slack Channel is here: https://python-mode.herokuapp.com/ **
|
||||
|
||||
-----
|
||||
|
||||
|
|
||||
| Src: https://github.com/klen/python-mode
|
||||
| Homepage: https://klen.github.io/python-mode/
|
||||
| Docs: https://github.com/klen/python-mode/blob/develop/doc/pymode.txt
|
||||
|
|
||||
|
||||
Python-mode is a vim plugin that helps you to create python code very quickly
|
||||
by utilizing libraries including
|
||||
`pylint`_, `rope`_, pydoc_, `pyflakes`_, `pep8`_, `autopep8`_,
|
||||
`pep257`_ and `mccabe`_
|
||||
for features like static analysis, refactoring, folding, completion,
|
||||
documentation, and more.
|
||||
|
||||
The plugin contains all you need to develop python applications in Vim.
|
||||
|
||||
There is no need to install `pylint`_, `rope`_
|
||||
or any other `Python Libraries`_ on your system.
|
||||
|
||||
- Support Python version 2.6+ and 3.2+
|
||||
- Syntax highlighting
|
||||
- Virtualenv support
|
||||
- Run python code (``<leader>r``)
|
||||
- Add/remove breakpoints (``<leader>b``)
|
||||
- Improved Python indentation
|
||||
- Python folding
|
||||
- Python motions and operators (``]]``, ``3[[``, ``]]M``, ``vaC``, ``viM``,
|
||||
``daC``, ``ciM``, ...)
|
||||
- Code checking (pylint_, pyflakes_, pylama_, ...) that can be run
|
||||
simultaneously (``:PymodeLint``)
|
||||
- Autofix PEP8 errors (``:PymodeLintAuto``)
|
||||
- Search in python documentation (``K``)
|
||||
- Code refactoring <rope refactoring library> (rope_)
|
||||
- Strong code completion (rope_)
|
||||
- Go to definition (``<C-c>g`` for `:RopeGotoDefinition`)
|
||||
- And more, more ...
|
||||
|
||||
See (very old) screencast here: http://www.youtube.com/watch?v=67OZNp9Z0CQ
|
||||
(sorry for quality, this is my first screencast) Another old presentation here:
|
||||
http://www.youtube.com/watch?v=YhqsjUUHj6g
|
||||
|
||||
**To read python-mode documentation in Vim, see** ``:help pymode``
|
||||
|
||||
|
||||
.. contents::
|
||||
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- VIM >= 7.3 (mostly features needed `+python` or `+python3` support)
|
||||
(also ``--with-features=big`` if you want ``g:pymode_lint_signs``)
|
||||
|
||||
|
||||
How to install
|
||||
==============
|
||||
|
||||
Using pathogen (recommended)
|
||||
----------------------------
|
||||
::
|
||||
|
||||
% cd ~/.vim
|
||||
% mkdir -p bundle && cd bundle
|
||||
% git clone https://github.com/klen/python-mode.git
|
||||
|
||||
- Enable `pathogen <https://github.com/tpope/vim-pathogen>`_
|
||||
in your ``~/.vimrc``: ::
|
||||
|
||||
" Pathogen load
|
||||
filetype off
|
||||
|
||||
call pathogen#infect()
|
||||
call pathogen#helptags()
|
||||
|
||||
filetype plugin indent on
|
||||
syntax on
|
||||
|
||||
|
||||
Manually
|
||||
--------
|
||||
::
|
||||
|
||||
% git clone https://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 to use python-mode.
|
||||
|
||||
|
||||
Debian packages
|
||||
---------------
|
||||
|Repository URL: https://klen.github.io/python-mode/deb/
|
||||
|
||||
Install with commands:
|
||||
|
||||
::
|
||||
|
||||
add-apt-repository https://klen.github.io/python-mode/deb main
|
||||
apt-get update
|
||||
apt-get install vim-python-mode
|
||||
|
||||
If you are getting the message: "The following signatures couldn't be verified because the public key is not available": ::
|
||||
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B5DF65307000E266
|
||||
|
||||
`vim-python-mode` using `vim-addons`, so after installation just enable
|
||||
`python-mode` with command: ::
|
||||
|
||||
vim-addons install python-mode
|
||||
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
|
||||
If your python-mode doesn't work:
|
||||
|
||||
1. Load Vim with only python-mode enabled (use `debug.vim` from pymode): ::
|
||||
|
||||
vim -u <path_to_pymode>/debug.vim
|
||||
|
||||
And try to repeat your case. If no error occurs, seems like problem isn't in the
|
||||
plugin.
|
||||
|
||||
2. Type `:PymodeTroubleshooting`
|
||||
|
||||
And fix any warnings or copy the output and send it to me. (For example, by
|
||||
creating a `new github issue <https://github.com/klen/python-mode/issues/new>`_
|
||||
if one does not already exist for the problem).
|
||||
|
||||
|
||||
Customization
|
||||
=============
|
||||
|
||||
You can override the default key bindings by redefining them in your `.vimrc`, for example: ::
|
||||
|
||||
" Override go-to.definition key shortcut to Ctrl-]
|
||||
let g:pymode_rope_goto_definition_bind = "<C-]>"
|
||||
|
||||
" Override run current python file key shortcut to Ctrl-Shift-e
|
||||
let g:pymode_run_bind = "<C-S-e>"
|
||||
|
||||
" Override view python doc key shortcut to Ctrl-Shift-d
|
||||
let g:pymode_doc_bind = "<C-S-d>"
|
||||
|
||||
|
||||
Frequent Problems
|
||||
=================
|
||||
|
||||
Read this section before opening an issue on the tracker.
|
||||
|
||||
Python 3 Syntax
|
||||
---------------
|
||||
|
||||
By default python-mode uses python 2 syntax checking. To enable python 3
|
||||
syntax checking (e.g. for async) add::
|
||||
|
||||
let g:pymode_python = 'python3'
|
||||
|
||||
To your vimrc or exrc file
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
Documentation is available in your vim ``:help pymode``
|
||||
|
||||
|
||||
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
|
||||
============
|
||||
|
||||
* Kirill Klenov (horneds@gmail.com)
|
||||
* Bryce Guinta (https://github.com/brycepg)
|
||||
|
||||
Also see the `AUTHORS` file.
|
||||
|
||||
Development of python-mode happens at github:
|
||||
https://github.com/klen/python-mode
|
||||
|
||||
Please make a pull request to `development` branch and add yourself to
|
||||
`AUTHORS`.
|
||||
|
||||
Source Links
|
||||
===================
|
||||
- `doc/pymode.txt
|
||||
<https://github.com/klen/python-mode/blob/develop/doc/pymode.txt>`__
|
||||
-- ``:help pymode``
|
||||
- `plugin/pymode.vim
|
||||
<https://github.com/klen/python-mode/blob/develop/plugin/pymode.vim>`__
|
||||
-- python-mode VIM plugin
|
||||
- `syntax/python.vim
|
||||
<https://github.com/klen/python-mode/blob/develop/syntax/python.vim>`__
|
||||
-- python-mode ``python.vim`` VIM syntax
|
||||
- `syntax/pyrex.vim
|
||||
<https://github.com/klen/python-mode/blob/develop/syntax/pyrex.vim>`__
|
||||
-- ``pyrex.vim`` VIM syntax (pyrex, Cython)
|
||||
- `t/
|
||||
<https://github.com/klen/python-mode/tree/develop/t>`__
|
||||
-- ``*.vim`` more python-mode VIM configuration
|
||||
- `pymode/
|
||||
<https://github.com/klen/python-mode/tree/develop/pymode>`__
|
||||
-- ``*.py`` -- python-mode Python module
|
||||
- `pymode/libs/
|
||||
<https://github.com/klen/python-mode/tree/develop/pymode/libs>`__
|
||||
-- ``*.py`` -- `Python Libraries <#python-libraries>`__
|
||||
|
||||
|
||||
Python Libraries
|
||||
------------------
|
||||
Vendored Python modules are located
|
||||
mostly in
|
||||
`pymode/libs/ <https://github.com/klen/python-mode/tree/develop/pymode/libs>`__.
|
||||
|
||||
|
||||
======
|
||||
rope
|
||||
======
|
||||
| PyPI: https://pypi.python.org/pypi/rope
|
||||
| Src: https://github.com/python-rope/rope
|
||||
| Docs: https://github.com/python-rope/rope/blob/master/docs/overview.rst
|
||||
| Docs: https://github.com/python-rope/rope/blob/master/docs/library.rst
|
||||
|
||||
========================
|
||||
ropemode
|
||||
========================
|
||||
| PyPI: https://pypi.python.org/pypi/ropemode
|
||||
| Src: https://github.com/python-rope/ropemode
|
||||
|
||||
=========
|
||||
ropevim
|
||||
=========
|
||||
| PyPI: https://pypi.python.org/pypi/ropevim
|
||||
| Src: https://github.com/python-rope/ropevim
|
||||
| Docs: https://github.com/python-rope/ropevim/blob/master/doc/ropevim.txt
|
||||
|
||||
=======
|
||||
pylama
|
||||
=======
|
||||
| PyPI: https://pypi.python.org/pypi/pylama
|
||||
| Src: https://github.com/klen/pylama
|
||||
|
||||
========
|
||||
pylint
|
||||
========
|
||||
| PyPI: https://pypi.python.org/pypi/pylint
|
||||
| Src: https://bitbucket.org/logilab/pylint
|
||||
| Homepage: http://www.pylint.org/
|
||||
| Docs: http://docs.pylint.org/
|
||||
| Docs: http://docs.pylint.org/message-control.html
|
||||
| Docs: http://docs.pylint.org/faq.html#message-control
|
||||
| ErrCodes: http://pylint-messages.wikidot.com/all-codes
|
||||
| ErrCodes: http://pylint-messages.wikidot.com/all-messages
|
||||
|
||||
==========
|
||||
pyflakes
|
||||
==========
|
||||
| PyPI: https://pypi.python.org/pypi/pyflakes
|
||||
| Src: https://github.com/pyflakes/pyflakes
|
||||
| ErrCodes: https://flake8.readthedocs.org/en/latest/warnings.html
|
||||
|
||||
======
|
||||
pep8
|
||||
======
|
||||
| PyPI: https://pypi.python.org/pypi/pep8
|
||||
| Src: http://github.com/jcrocholl/pep8
|
||||
| PEP 8: http://www.python.org/dev/peps/pep-0008/
|
||||
| PEP 8: http://legacy.python.org/dev/peps/pep-0008/
|
||||
| Docs: https://pep8.readthedocs.org/en/latest/
|
||||
| Docs: https://pep8.readthedocs.org/en/latest/intro.html#configuration
|
||||
| ErrCodes: https://pep8.readthedocs.org/en/latest/intro.html#error-codes
|
||||
|
||||
=========
|
||||
autopep8
|
||||
=========
|
||||
| PyPI: https://pypi.python.org/pypi/autopep8
|
||||
| Src: https://github.com/hhatto/autopep8
|
||||
|
||||
=======
|
||||
pep257
|
||||
=======
|
||||
| PyPI: https://pypi.python.org/pypi/pep257
|
||||
| Src: http://github.com/GreenSteam/pep257
|
||||
| Docs: https://pep257.readthedocs.org/en/latest/
|
||||
| PEP 257: http://www.python.org/dev/peps/pep-0257/
|
||||
| ErrCodes: https://pep257.readthedocs.org/en/latest/error_codes.html
|
||||
|
||||
=======
|
||||
mccabe
|
||||
=======
|
||||
| PyPI: https://pypi.python.org/pypi/mccabe
|
||||
| Src: https://github.com/flintwork/mccabe
|
||||
| Docs: https://en.wikipedia.org/wiki/Cyclomatic_complexity
|
||||
|
||||
|
||||
Vim Libraries
|
||||
---------------
|
||||
Vendored Vim modules are located mostly in ``t/``.
|
||||
|
||||
======================
|
||||
Python syntax for vim
|
||||
======================
|
||||
| Src: http://www.hlabs.spb.ru/vim/python.vim
|
||||
|
||||
|
||||
=====================
|
||||
PEP8 VIM indentation
|
||||
=====================
|
||||
| Src: http://github.com/hynek/vim-python-pep8-indent
|
||||
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright © 2013-2015 Kirill Klenov (klen_)
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Licensed under a `GNU lesser general public license`_.
|
||||
|
||||
If you like this plugin, I would very appreciated if you kindly send me a postcard :)
|
||||
My address is here: "Russia, 143500, MO, Istra, pos. Severny 8-3" to "Kirill Klenov".
|
||||
**Thanks for support!**
|
||||
|
||||
.. _GNU lesser general public license: http://www.gnu.org/copyleft/lesser.html
|
||||
.. _klen: https://klen.github.com/
|
||||
.. _pydoc: http://docs.python.org/library/pydoc.html
|
||||
.. _pathogen: https://github.com/tpope/vim-pathogen
|
||||
.. _rope_: https://pypi.python.org/pypi/rope
|
||||
.. _pylama_: https://github.com/klen/pylama
|
||||
.. _pylint_: https://bitbucket.org/logilab/pylint
|
||||
.. _pyflakes_: https://pypi.python.org/pypi/pyflakes
|
||||
.. _autopep8_: https://github.com/hhatto/autopep8
|
||||
.. _pep257_: http://github.com/GreenSteam/pep257
|
||||
.. _mccabe_: https://github.com/flintwork/mccabe
|
||||
.. _pythonvim: http://www.hlabs.spb.ru/vim/python.vim
|
||||
.. _pep8_: http://github.com/jcrocholl/pep8
|
||||
.. _pep8indent: http://github.com/hynek/vim-python-pep8-indent
|
||||
.. |logo| image:: https://raw.github.com/klen/python-mode/develop/logo.png
|
||||
11
vim-plugins/python-mode/Rakefile
Normal file
11
vim-plugins/python-mode/Rakefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env rake
|
||||
|
||||
task :ci => [:dump, :test]
|
||||
|
||||
task :dump do
|
||||
sh 'vim --version'
|
||||
end
|
||||
|
||||
task :test do
|
||||
sh 'bundle exec vim-flavor test'
|
||||
end
|
||||
1
vim-plugins/python-mode/after/ftplugin/pyrex.vim
Normal file
1
vim-plugins/python-mode/after/ftplugin/pyrex.vim
Normal file
|
|
@ -0,0 +1 @@
|
|||
runtime after/ftplugin/python.vim
|
||||
58
vim-plugins/python-mode/after/ftplugin/python.vim
Normal file
58
vim-plugins/python-mode/after/ftplugin/python.vim
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
if !g:pymode
|
||||
finish
|
||||
endif
|
||||
|
||||
if g:pymode_motion
|
||||
|
||||
if !&magic
|
||||
if g:pymode_warning
|
||||
call pymode#error("Pymode motion requires `&magic` option. Enable them or disable g:pymode_motion")
|
||||
endif
|
||||
finish
|
||||
endif
|
||||
|
||||
nnoremap <buffer> ]] :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', '')<CR>
|
||||
nnoremap <buffer> [[ :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', 'b')<CR>
|
||||
nnoremap <buffer> ]C :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', '')<CR>
|
||||
nnoremap <buffer> [C :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', 'b')<CR>
|
||||
nnoremap <buffer> ]M :<C-U>call pymode#motion#move('^<Bslash>s*def<Bslash>s', '')<CR>
|
||||
nnoremap <buffer> [M :<C-U>call pymode#motion#move('^<Bslash>s*def<Bslash>s', 'b')<CR>
|
||||
|
||||
onoremap <buffer> ]] :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', '')<CR>
|
||||
onoremap <buffer> [[ :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', 'b')<CR>
|
||||
onoremap <buffer> ]C :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', '')<CR>
|
||||
onoremap <buffer> [C :<C-U>call pymode#motion#move('<Bslash>v^(class<bar>def)<Bslash>s', 'b')<CR>
|
||||
onoremap <buffer> ]M :<C-U>call pymode#motion#move('^<Bslash>s*def<Bslash>s', '')<CR>
|
||||
onoremap <buffer> [M :<C-U>call pymode#motion#move('^<Bslash>s*def<Bslash>s', 'b')<CR>
|
||||
|
||||
vnoremap <buffer> ]] :call pymode#motion#vmove('<Bslash>v^(class<bar>def)<Bslash>s', '')<CR>
|
||||
vnoremap <buffer> [[ :call pymode#motion#vmove('<Bslash>v^(class<bar>def)<Bslash>s', 'b')<CR>
|
||||
vnoremap <buffer> ]M :call pymode#motion#vmove('^<Bslash>s*def<Bslash>s', '')<CR>
|
||||
vnoremap <buffer> [M :call pymode#motion#vmove('^<Bslash>s*def<Bslash>s', 'b')<CR>
|
||||
|
||||
onoremap <buffer> C :<C-U>call pymode#motion#select('^<Bslash>s*class<Bslash>s', 0)<CR>
|
||||
onoremap <buffer> aC :<C-U>call pymode#motion#select('^<Bslash>s*class<Bslash>s', 0)<CR>
|
||||
onoremap <buffer> iC :<C-U>call pymode#motion#select('^<Bslash>s*class<Bslash>s', 1)<CR>
|
||||
vnoremap <buffer> aC :<C-U>call pymode#motion#select('^<Bslash>s*class<Bslash>s', 0)<CR>
|
||||
vnoremap <buffer> iC :<C-U>call pymode#motion#select('^<Bslash>s*class<Bslash>s', 1)<CR>
|
||||
|
||||
onoremap <buffer> M :<C-U>call pymode#motion#select('^<Bslash>s*def<Bslash>s', 0)<CR>
|
||||
onoremap <buffer> aM :<C-U>call pymode#motion#select('^<Bslash>s*def<Bslash>s', 0)<CR>
|
||||
onoremap <buffer> iM :<C-U>call pymode#motion#select('^<Bslash>s*def<Bslash>s', 1)<CR>
|
||||
vnoremap <buffer> aM :<C-U>call pymode#motion#select('^<Bslash>s*def<Bslash>s', 0)<CR>
|
||||
vnoremap <buffer> iM :<C-U>call pymode#motion#select('^<Bslash>s*def<Bslash>s', 1)<CR>
|
||||
|
||||
endif
|
||||
|
||||
if g:pymode_rope && g:pymode_rope_completion
|
||||
|
||||
setlocal omnifunc=pymode#rope#completions
|
||||
|
||||
if g:pymode_rope_completion_bind != ""
|
||||
exe "inoremap <silent> <buffer> " . g:pymode_rope_completion_bind . " <C-R>=pymode#rope#complete(0)<CR>"
|
||||
if tolower(g:pymode_rope_completion_bind) == '<c-space>'
|
||||
exe "inoremap <silent> <buffer> <Nul> <C-R>=pymode#rope#complete(0)<CR>"
|
||||
endif
|
||||
end
|
||||
|
||||
end
|
||||
1
vim-plugins/python-mode/after/indent/pyrex.vim
Normal file
1
vim-plugins/python-mode/after/indent/pyrex.vim
Normal file
|
|
@ -0,0 +1 @@
|
|||
runtime after/indent/python.vim
|
||||
13
vim-plugins/python-mode/after/indent/python.vim
Normal file
13
vim-plugins/python-mode/after/indent/python.vim
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
if !g:pymode || !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#get_indent(v:lnum)
|
||||
setlocal indentkeys=!^F,o,O,<:>,0),0],0},=elif,=except
|
||||
133
vim-plugins/python-mode/autoload/pymode.vim
Normal file
133
vim-plugins/python-mode/autoload/pymode.vim
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
" Pymode core functions
|
||||
|
||||
" DESC: Check variable and set default value if it not exists
|
||||
fun! pymode#default(name, default) "{{{
|
||||
if !exists(a:name)
|
||||
let {a:name} = a:default
|
||||
return 0
|
||||
endif
|
||||
return 1
|
||||
endfunction "}}}
|
||||
|
||||
" DESC: Import python libs
|
||||
fun! pymode#init(plugin_root, paths) "{{{
|
||||
|
||||
PymodePython import sys, vim
|
||||
PymodePython sys.path.insert(0, vim.eval('a:plugin_root'))
|
||||
PymodePython sys.path = vim.eval('a:paths') + sys.path
|
||||
|
||||
endfunction "}}}
|
||||
|
||||
" DESC: Show wide message
|
||||
fun! pymode#wide_message(msg) "{{{
|
||||
let x=&ruler | let y=&showcmd
|
||||
set noruler noshowcmd
|
||||
redraw
|
||||
echohl Debug | echo strpart("[Pymode] " . a:msg, 0, &columns-1) | echohl none
|
||||
let &ruler=x | let &showcmd=y
|
||||
endfunction "}}}
|
||||
|
||||
" DESC: Show error
|
||||
fun! pymode#error(msg) "{{{
|
||||
execute "normal \<Esc>"
|
||||
echohl ErrorMsg
|
||||
echomsg "[Pymode]: error: " . a:msg
|
||||
echohl None
|
||||
endfunction "}}}
|
||||
|
||||
" DESC: Open quickfix window
|
||||
fun! pymode#quickfix_open(onlyRecognized, maxHeight, minHeight, jumpError) "{{{
|
||||
let numErrors = len(filter(getqflist(), 'v:val.valid'))
|
||||
let numOthers = len(getqflist()) - numErrors
|
||||
if numErrors > 0 || (!a:onlyRecognized && numOthers > 0)
|
||||
let num = winnr()
|
||||
botright copen
|
||||
exe max([min([line("$"), a:maxHeight]), a:minHeight]) . "wincmd _"
|
||||
if a:jumpError
|
||||
cc
|
||||
elseif num != winnr()
|
||||
wincmd p
|
||||
endif
|
||||
else
|
||||
cclose
|
||||
endif
|
||||
redraw
|
||||
if numOthers > 0
|
||||
call pymode#wide_message(printf('Quickfix: %d(+%d)', numErrors, numOthers))
|
||||
elseif numErrors > 0
|
||||
call pymode#wide_message(printf('Quickfix: %d', numErrors))
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
" DESC: Open temp buffer.
|
||||
fun! pymode#tempbuffer_open(name) "{{{
|
||||
pclose
|
||||
exe "botright 8new " . a:name
|
||||
setlocal buftype=nofile bufhidden=delete noswapfile nowrap previewwindow
|
||||
redraw
|
||||
endfunction "}}}
|
||||
|
||||
" DESC: Remove unused whitespaces
|
||||
fun! pymode#trim_whitespaces() "{{{
|
||||
if g:pymode_trim_whitespaces
|
||||
let cursor_pos = getpos('.')
|
||||
silent! %s/\s\+$//
|
||||
call setpos('.', cursor_pos)
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#save() "{{{
|
||||
if &modifiable && &modified
|
||||
try
|
||||
noautocmd write
|
||||
catch /E212/
|
||||
call pymode#error("File modified and I can't save it. Please save it manually.")
|
||||
return 0
|
||||
endtry
|
||||
endif
|
||||
return expand('%') != ''
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#reload_buf_by_nr(nr) "{{{
|
||||
let cur = bufnr("")
|
||||
try
|
||||
exe "buffer " . a:nr
|
||||
catch /E86/
|
||||
return
|
||||
endtry
|
||||
exe "e!"
|
||||
exe "buffer " . cur
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#buffer_pre_write() "{{{
|
||||
let b:pymode_modified = &modified
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#buffer_post_write() "{{{
|
||||
if g:pymode_rope
|
||||
if g:pymode_rope_regenerate_on_write && b:pymode_modified
|
||||
call pymode#debug('regenerate')
|
||||
call pymode#rope#regenerate()
|
||||
endif
|
||||
endif
|
||||
if g:pymode_lint
|
||||
if g:pymode_lint_unmodified || (g:pymode_lint_on_write && b:pymode_modified)
|
||||
call pymode#debug('check code')
|
||||
call pymode#lint#check()
|
||||
endif
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#debug(msg) "{{{
|
||||
if g:pymode_debug
|
||||
let g:pymode_debug += 1
|
||||
echom string(g:pymode_debug) . ': ' . string(a:msg)
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#quit() "{{{
|
||||
augroup pymode
|
||||
au! * <buffer>
|
||||
augroup END
|
||||
endfunction "}}}
|
||||
51
vim-plugins/python-mode/autoload/pymode/breakpoint.vim
Normal file
51
vim-plugins/python-mode/autoload/pymode/breakpoint.vim
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
fun! pymode#breakpoint#init() "{{{
|
||||
|
||||
if !g:pymode_breakpoint
|
||||
return
|
||||
endif
|
||||
|
||||
if g:pymode_breakpoint_cmd == ''
|
||||
let g:pymode_breakpoint_cmd = 'import pdb; pdb.set_trace() # XXX BREAKPOINT'
|
||||
|
||||
if g:pymode_python == 'disable'
|
||||
return
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
PymodePython << EOF
|
||||
|
||||
from imp import find_module
|
||||
|
||||
for module in ('wdb', 'pudb', 'ipdb'):
|
||||
try:
|
||||
find_module(module)
|
||||
vim.command('let g:pymode_breakpoint_cmd = "import %s; %s.set_trace() # XXX BREAKPOINT"' % (module, module))
|
||||
break
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
EOF
|
||||
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#breakpoint#operate(lnum) "{{{
|
||||
let line = getline(a:lnum)
|
||||
if strridx(line, g:pymode_breakpoint_cmd) != -1
|
||||
normal dd
|
||||
else
|
||||
let plnum = prevnonblank(a:lnum)
|
||||
if &expandtab
|
||||
let indents = repeat(' ', indent(plnum))
|
||||
else
|
||||
let indents = repeat("\t", plnum / &shiftwidth)
|
||||
endif
|
||||
|
||||
call append(line('.')-1, indents.g:pymode_breakpoint_cmd)
|
||||
normal k
|
||||
endif
|
||||
|
||||
" Save file without any events
|
||||
call pymode#save()
|
||||
|
||||
endfunction "}}}
|
||||
37
vim-plugins/python-mode/autoload/pymode/doc.vim
Normal file
37
vim-plugins/python-mode/autoload/pymode/doc.vim
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
" Python-mode search by documentation
|
||||
"
|
||||
PymodePython import pymode
|
||||
|
||||
fun! pymode#doc#find() "{{{
|
||||
" Extract the 'word' at the cursor, expanding leftwards across identifiers
|
||||
" and the . operator, and rightwards across the identifier only.
|
||||
"
|
||||
" For example:
|
||||
" import xml.dom.minidom
|
||||
" ^ !
|
||||
"
|
||||
" With the cursor at ^ this returns 'xml'; at ! it returns 'xml.dom'.
|
||||
let l:line = getline(".")
|
||||
let l:pre = l:line[:col(".") - 1]
|
||||
let l:suf = l:line[col("."):]
|
||||
let word = matchstr(pre, "[A-Za-z0-9_.]*$") . matchstr(suf, "^[A-Za-z0-9_]*")
|
||||
call pymode#doc#show(word)
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#doc#show(word) "{{{
|
||||
if a:word == ''
|
||||
call pymode#error("No name/symbol under cursor!")
|
||||
return 0
|
||||
endif
|
||||
|
||||
call pymode#tempbuffer_open('__doc__')
|
||||
PymodePython pymode.get_documentation()
|
||||
setlocal nomodifiable
|
||||
setlocal nomodified
|
||||
setlocal filetype=rst
|
||||
if g:pymode_doc_vertical
|
||||
wincmd L
|
||||
endif
|
||||
wincmd p
|
||||
|
||||
endfunction "}}}
|
||||
274
vim-plugins/python-mode/autoload/pymode/folding.vim
Normal file
274
vim-plugins/python-mode/autoload/pymode/folding.vim
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
" Python-mode folding functions
|
||||
|
||||
" Notice that folding is based on single line so complex regular expressions
|
||||
" that take previous line into consideration are not fit for the job.
|
||||
|
||||
" Regex definitions for correct folding
|
||||
let s:def_regex = g:pymode_folding_regex
|
||||
let s:blank_regex = '^\s*$'
|
||||
" Spyder, a very popular IDE for python has a template which includes
|
||||
" '@author:' ; thus the regex below.
|
||||
let s:decorator_regex = '^\s*@\(author:\)\@!'
|
||||
let s:doc_begin_regex = '^\s*[uU]\=\%("""\|''''''\)'
|
||||
let s:doc_end_regex = '\%("""\|''''''\)\s*$'
|
||||
" This one is needed for the while loop to count for opening and closing
|
||||
" docstrings.
|
||||
let s:doc_general_regex = '\%("""\|''''''\)'
|
||||
let s:doc_line_regex = '^\s*[uU]\=\("""\|''''''\).\+\1\s*$'
|
||||
let s:symbol = matchstr(&fillchars, 'fold:\zs.') " handles multibyte characters
|
||||
if s:symbol == ''
|
||||
let s:symbol = ' '
|
||||
endif
|
||||
" ''''''''
|
||||
|
||||
|
||||
fun! pymode#folding#text() " {{{
|
||||
let fs = v:foldstart
|
||||
while getline(fs) !~ s:def_regex && getline(fs) !~ s:doc_begin_regex
|
||||
let fs = nextnonblank(fs + 1)
|
||||
endwhile
|
||||
if getline(fs) =~ s:doc_end_regex && getline(fs) =~ s:doc_begin_regex
|
||||
let fs = nextnonblank(fs + 1)
|
||||
endif
|
||||
let line = getline(fs)
|
||||
|
||||
let has_numbers = &number || &relativenumber
|
||||
let nucolwidth = &fdc + has_numbers * &numberwidth
|
||||
let windowwidth = winwidth(0) - nucolwidth - 6
|
||||
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 line = substitute(line, '[uU]\=\%("""\|''''''\)', '', '')
|
||||
let fillcharcount = windowwidth - len(line) - len(foldedlinecount) + 1
|
||||
return line . ' ' . repeat(s:symbol, fillcharcount) . ' ' . foldedlinecount
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#folding#expr(lnum) "{{{
|
||||
|
||||
let line = getline(a:lnum)
|
||||
let indent = indent(a:lnum)
|
||||
let prev_line = getline(a:lnum - 1)
|
||||
let next_line = getline(a:lnum + 1)
|
||||
|
||||
" Decorators {{{
|
||||
if line =~ s:decorator_regex
|
||||
return ">".(indent / &shiftwidth + 1)
|
||||
endif "}}}
|
||||
|
||||
" Definition {{{
|
||||
if line =~ s:def_regex
|
||||
" If indent of this line is greater or equal than line below
|
||||
" and previous non blank line does not end with : (that is, is not a
|
||||
" definition)
|
||||
" Keep the same indentation
|
||||
if indent(a:lnum) >= indent(a:lnum+1) && getline(prevnonblank(a:lnum)) !~ ':\s*$'
|
||||
return '='
|
||||
endif
|
||||
" Check if last decorator is before the last def
|
||||
let decorated = 0
|
||||
let lnum = a:lnum - 1
|
||||
while lnum > 0
|
||||
if getline(lnum) =~ s:def_regex
|
||||
break
|
||||
elseif getline(lnum) =~ s:decorator_regex
|
||||
let decorated = 1
|
||||
break
|
||||
endif
|
||||
let lnum -= 1
|
||||
endwhile
|
||||
if decorated
|
||||
return '='
|
||||
else
|
||||
return ">".(indent / &shiftwidth + 1)
|
||||
endif
|
||||
endif "}}}
|
||||
|
||||
" Docstrings {{{
|
||||
|
||||
" TODO: A while loop now counts the number of open and closed folding in
|
||||
" order to determine if it is a closing or opening folding.
|
||||
" It is working but looks like it is an overkill.
|
||||
|
||||
" Notice that an effect of this is that other docstring matches will not
|
||||
" be one liners.
|
||||
if line =~ s:doc_line_regex
|
||||
return "="
|
||||
endif
|
||||
|
||||
if line =~ s:doc_begin_regex
|
||||
" echom 'just entering'
|
||||
if s:Is_opening_folding(a:lnum)
|
||||
" echom 'entering at line ' . a:lnum
|
||||
return ">".(indent / &shiftwidth + 1)
|
||||
endif
|
||||
endif
|
||||
if line =~ s:doc_end_regex
|
||||
if !s:Is_opening_folding(a:lnum)
|
||||
" echom 'leaving at line ' . a:lnum
|
||||
return "<".(indent / &shiftwidth + 1)
|
||||
endif
|
||||
endif "}}}
|
||||
|
||||
" Nested Definitions {{{
|
||||
" Handle nested defs but only for files shorter than
|
||||
" g:pymode_folding_nest_limit lines due to performance concerns
|
||||
if line('$') < g:pymode_folding_nest_limit && indent(prevnonblank(a:lnum))
|
||||
let curpos = getpos('.')
|
||||
try
|
||||
let last_block = s:BlockStart(a:lnum)
|
||||
let last_block_indent = indent(last_block)
|
||||
|
||||
" Check if last class/def is not indented and therefore can't be
|
||||
" nested.
|
||||
if last_block_indent
|
||||
call cursor(a:lnum, 0)
|
||||
let next_def = searchpos(s:def_regex, 'nW')[0]
|
||||
let next_def_indent = next_def ? indent(next_def) : -1
|
||||
let last_block_end = s:BlockEnd(last_block)
|
||||
|
||||
" If the next def has greater indent than the previous def, it
|
||||
" is nested one level deeper and will have its own fold. If
|
||||
" the class/def containing the current line is on the first
|
||||
" line it can't be nested, and if this block ends on the last
|
||||
" line, it contains no trailing code that should not be
|
||||
" folded. Finally, if the next non-blank line after the end of
|
||||
" the previous def is less indented than the previous def, it
|
||||
" is not part of the same fold as that def. Otherwise, we know
|
||||
" the current line is at the end of a nested def.
|
||||
if next_def_indent <= last_block_indent && last_block > 1 && last_block_end < line('$')
|
||||
\ && indent(nextnonblank(last_block_end)) >= last_block_indent
|
||||
|
||||
" Include up to one blank line in the fold
|
||||
if getline(last_block_end) =~ s:blank_regex
|
||||
let fold_end = min([prevnonblank(last_block_end - 1), last_block_end]) + 1
|
||||
else
|
||||
let fold_end = last_block_end
|
||||
endif
|
||||
if a:lnum == fold_end
|
||||
return 's1'
|
||||
else
|
||||
return '='
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
finally
|
||||
call setpos('.', curpos)
|
||||
endtry
|
||||
endif " }}}
|
||||
|
||||
" Blank Line {{{
|
||||
if line =~ s:blank_regex
|
||||
if prev_line =~ s:blank_regex
|
||||
if indent(a:lnum + 1) == 0 && next_line !~ s:blank_regex && next_line !~ s:doc_general_regex
|
||||
if s:Is_opening_folding(a:lnum)
|
||||
" echom a:lnum
|
||||
return "="
|
||||
else
|
||||
" echom "not " . a:lnum
|
||||
return 0
|
||||
endif
|
||||
endif
|
||||
return -1
|
||||
else
|
||||
return '='
|
||||
endif
|
||||
endif " }}}
|
||||
|
||||
return '='
|
||||
|
||||
endfunction "}}}
|
||||
|
||||
fun! s:BlockStart(lnum) "{{{
|
||||
" Note: Make sure to reset cursor position after using this function.
|
||||
call cursor(a:lnum, 0)
|
||||
|
||||
" In case the end of the block is indented to a higher level than the def
|
||||
" statement plus one shiftwidth, we need to find the indent level at the
|
||||
" bottom of that if/for/try/while/etc. block.
|
||||
let last_def = searchpos(s:def_regex, 'bcnW')[0]
|
||||
if last_def
|
||||
let last_def_indent = indent(last_def)
|
||||
call cursor(last_def, 0)
|
||||
let next_stmt_at_def_indent = searchpos('\v^\s{'.last_def_indent.'}[^[:space:]#]', 'nW')[0]
|
||||
else
|
||||
let next_stmt_at_def_indent = -1
|
||||
endif
|
||||
|
||||
" Now find the class/def one shiftwidth lower than the start of the
|
||||
" aforementioned indent block.
|
||||
if next_stmt_at_def_indent && next_stmt_at_def_indent < a:lnum
|
||||
let max_indent = max([indent(next_stmt_at_def_indent) - &shiftwidth, 0])
|
||||
else
|
||||
let max_indent = max([indent(prevnonblank(a:lnum)) - &shiftwidth, 0])
|
||||
endif
|
||||
return searchpos('\v^\s{,'.max_indent.'}(def |class )\w', 'bcnW')[0]
|
||||
endfunction "}}}
|
||||
|
||||
fun! s:BlockEnd(lnum) "{{{
|
||||
" Note: Make sure to reset cursor position after using this function.
|
||||
call cursor(a:lnum, 0)
|
||||
return searchpos('\v^\s{,'.indent('.').'}\S', 'nW')[0] - 1
|
||||
endfunction "}}}
|
||||
|
||||
function! s:Is_opening_folding(lnum) "{{{
|
||||
" Helper function to see if docstring is opening or closing
|
||||
|
||||
" Cache the result so the loop runs only once per change
|
||||
if get(b:, 'fold_changenr', -1) == changenr()
|
||||
return b:fold_cache[a:lnum] "If odd then it is an opening
|
||||
else
|
||||
let b:fold_changenr = changenr()
|
||||
let b:fold_cache = []
|
||||
endif
|
||||
|
||||
let number_of_folding = 0 " To be analized if odd/even to inform if it is opening or closing.
|
||||
let has_open_docstring = 0 " To inform is already has an open docstring.
|
||||
let extra_docstrings = 0 " To help skipping ''' and """ which are not docstrings
|
||||
|
||||
" The idea of this part of the function is to identify real docstrings and
|
||||
" not just triple quotes (that could be a regular string).
|
||||
"
|
||||
" Iterater over all lines from the start until current line (inclusive)
|
||||
for i in range(1, line('$'))
|
||||
call add(b:fold_cache, number_of_folding % 2)
|
||||
|
||||
let i_line = getline(i)
|
||||
|
||||
if i_line =~ s:doc_line_regex
|
||||
" echom "case 00 on line " . i
|
||||
continue
|
||||
endif
|
||||
|
||||
if i_line =~ s:doc_begin_regex && ! has_open_docstring
|
||||
" echom "case 01 on line " . i
|
||||
" This causes the loop to continue if there is a triple quote which
|
||||
" is not a docstring.
|
||||
if extra_docstrings > 0
|
||||
let extra_docstrings = extra_docstrings - 1
|
||||
continue
|
||||
else
|
||||
let has_open_docstring = 1
|
||||
let number_of_folding = number_of_folding + 1
|
||||
endif
|
||||
" If it is an end doc and has an open docstring.
|
||||
elseif i_line =~ s:doc_end_regex && has_open_docstring
|
||||
" echom "case 02 on line " . i
|
||||
let has_open_docstring = 0
|
||||
let number_of_folding = number_of_folding + 1
|
||||
|
||||
elseif i_line =~ s:doc_general_regex
|
||||
" echom "extra docstrings on line " . i
|
||||
let extra_docstrings = extra_docstrings + 1
|
||||
endif
|
||||
endfor
|
||||
|
||||
call add(b:fold_cache, number_of_folding % 2)
|
||||
|
||||
return b:fold_cache[a:lnum]
|
||||
endfunction "}}}
|
||||
|
||||
" vim: fdm=marker:fdl=0
|
||||
186
vim-plugins/python-mode/autoload/pymode/indent.vim
Normal file
186
vim-plugins/python-mode/autoload/pymode/indent.vim
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
" 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 Domain
|
||||
|
||||
|
||||
function! pymode#indent#get_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, find the first indentation that is a
|
||||
" multiple of four and will distinguish itself from next logical line.
|
||||
if pline =~ '\\$'
|
||||
let maybe_indent = indent(sslnum) + &sw
|
||||
let control_structure = '^\s*\(if\|while\|for\s.*\sin\|except\)\s*'
|
||||
if match(getline(sslnum), control_structure) != -1
|
||||
" add extra indent to avoid E125
|
||||
return maybe_indent + &sw
|
||||
else
|
||||
" control structure not found
|
||||
return maybe_indent
|
||||
endif
|
||||
endif
|
||||
|
||||
" If the previous line ended with a colon and is not a comment, indent
|
||||
" relative to statement start.
|
||||
if 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\\|doctest"'
|
||||
|
||||
" 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 " }}}
|
||||
101
vim-plugins/python-mode/autoload/pymode/lint.vim
Normal file
101
vim-plugins/python-mode/autoload/pymode/lint.vim
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
PymodePython from pymode.lint import code_check
|
||||
|
||||
call pymode#tools#signs#init()
|
||||
call pymode#tools#loclist#init()
|
||||
|
||||
|
||||
fun! pymode#lint#auto() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython from pymode import auto
|
||||
PymodePython auto()
|
||||
cclose
|
||||
call g:PymodeSigns.clear()
|
||||
edit
|
||||
call pymode#wide_message("AutoPep8 done.")
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#lint#show_errormessage() "{{{
|
||||
let loclist = g:PymodeLocList.current()
|
||||
if loclist.is_empty()
|
||||
return
|
||||
endif
|
||||
|
||||
let l = line('.')
|
||||
if l == b:pymode_error_line
|
||||
return
|
||||
endif
|
||||
let b:pymode_error_line = l
|
||||
if has_key(loclist._messages, l)
|
||||
call pymode#wide_message(loclist._messages[l])
|
||||
else
|
||||
echo
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#lint#toggle() "{{{
|
||||
let g:pymode_lint = g:pymode_lint ? 0 : 1
|
||||
if g:pymode_lint
|
||||
call pymode#wide_message("Code checking is enabled.")
|
||||
else
|
||||
call pymode#wide_message("Code checking is disabled.")
|
||||
end
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#lint#check() "{{{
|
||||
" DESC: Run checkers on current file.
|
||||
"
|
||||
let loclist = g:PymodeLocList.current()
|
||||
|
||||
let b:pymode_error_line = -1
|
||||
|
||||
call loclist.clear()
|
||||
|
||||
call pymode#wide_message('Code checking is running ...')
|
||||
|
||||
PymodePython code_check()
|
||||
|
||||
if loclist.is_empty()
|
||||
call pymode#wide_message('Code checking is completed. No errors found.')
|
||||
endif
|
||||
|
||||
call g:PymodeSigns.refresh(loclist)
|
||||
|
||||
call loclist.show()
|
||||
|
||||
call pymode#lint#show_errormessage()
|
||||
call pymode#wide_message('Found errors and warnings: ' . len(loclist._loclist))
|
||||
|
||||
endfunction " }}}
|
||||
|
||||
|
||||
fun! pymode#lint#tick_queue() "{{{
|
||||
|
||||
python import time
|
||||
python print time.time()
|
||||
|
||||
if mode() == 'i'
|
||||
if col('.') == 1
|
||||
call feedkeys("\<Right>\<Left>", "n")
|
||||
else
|
||||
call feedkeys("\<Left>\<Right>", "n")
|
||||
endif
|
||||
else
|
||||
call feedkeys("f\e", "n")
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#lint#stop() "{{{
|
||||
au! pymode CursorHold <buffer>
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#lint#start() "{{{
|
||||
au! pymode CursorHold <buffer> call pymode#lint#tick_queue()
|
||||
call pymode#lint#tick_queue()
|
||||
endfunction "}}}
|
||||
97
vim-plugins/python-mode/autoload/pymode/motion.vim
Normal file
97
vim-plugins/python-mode/autoload/pymode/motion.vim
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
" 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 = s:BlockStart(orig[0], a:pattern)
|
||||
if getline(snum) !~ a:pattern
|
||||
return 0
|
||||
endif
|
||||
let enum = s:BlockEnd(snum, indent(snum))
|
||||
while cnt
|
||||
let lnum = search(a:pattern, 'nW')
|
||||
if lnum
|
||||
let enum = s: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 "}}}
|
||||
|
||||
|
||||
fun! s: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! s: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 "}}}
|
||||
" vim: fdm=marker:fdl=0
|
||||
185
vim-plugins/python-mode/autoload/pymode/rope.vim
Normal file
185
vim-plugins/python-mode/autoload/pymode/rope.vim
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
" Python-mode Rope support
|
||||
"
|
||||
PymodePython from pymode import rope
|
||||
|
||||
call pymode#tools#loclist#init()
|
||||
|
||||
|
||||
fun! pymode#rope#completions(findstart, base)
|
||||
PymodePython rope.completions()
|
||||
endfunction
|
||||
|
||||
fun! pymode#rope#complete(dot)
|
||||
if pumvisible()
|
||||
return "\<C-n>"
|
||||
end
|
||||
if a:dot
|
||||
PymodePython rope.complete(True)
|
||||
else
|
||||
PymodePython rope.complete()
|
||||
end
|
||||
return pumvisible() ? "\<C-p>\<Down>" : ""
|
||||
endfunction
|
||||
|
||||
fun! pymode#rope#complete_on_dot() "{{{
|
||||
if !exists("*synstack")
|
||||
return ""
|
||||
end
|
||||
for group in map(synstack(line('.'), col('.') - 1), 'synIDattr(v:val, "name")')
|
||||
for name in ['pythonString', 'pythonComment', 'pythonNumber', 'pythonDocstring']
|
||||
if group == name
|
||||
return ""
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
if g:pymode_rope_autoimport_import_after_complete
|
||||
PymodePython rope.complete_check()
|
||||
endif
|
||||
return pymode#rope#complete(1)
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#goto_definition()
|
||||
PymodePython rope.goto()
|
||||
endfunction
|
||||
|
||||
|
||||
fun! pymode#rope#organize_imports()
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
call pymode#wide_message('Organize imports ... ')
|
||||
PymodePython rope.organize_imports()
|
||||
endfunction
|
||||
|
||||
|
||||
fun! pymode#rope#find_it()
|
||||
let loclist = g:PymodeLocList.current()
|
||||
let loclist._title = "Occurrences"
|
||||
call pymode#wide_message('Finding Occurrences ...')
|
||||
PymodePython rope.find_it()
|
||||
call loclist.show()
|
||||
endfunction
|
||||
|
||||
|
||||
fun! pymode#rope#show_doc()
|
||||
let l:output = []
|
||||
|
||||
PymodePython rope.show_doc()
|
||||
|
||||
if !empty(l:output)
|
||||
call pymode#tempbuffer_open('__doc____rope__')
|
||||
call append(0, l:output)
|
||||
setlocal nomodifiable
|
||||
setlocal nomodified
|
||||
setlocal filetype=rst
|
||||
wincmd p
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
fun! pymode#rope#regenerate() "{{{
|
||||
call pymode#wide_message('Regenerate Rope cache ... ')
|
||||
PymodePython rope.regenerate()
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#rope#new(...) "{{{
|
||||
PymodePython rope.new()
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! pymode#rope#rename() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.RenameRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#rename_module() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.RenameRefactoring(True).run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#extract_method() range "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.ExtractMethodRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#extract_variable() range "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.ExtractVariableRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#undo() "{{{
|
||||
PymodePython rope.undo()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#redo() "{{{
|
||||
PymodePython rope.redo()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#inline() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.InlineRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#move() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.MoveRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#signature() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.ChangeSignatureRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#use_function() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.UseFunctionRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#module_to_package() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.ModuleToPackageRefactoring().run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#autoimport(word) "{{{
|
||||
PymodePython rope.autoimport()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#generate_function() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.GenerateElementRefactoring('function').run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#generate_class() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.GenerateElementRefactoring('class').run()
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#rope#generate_package() "{{{
|
||||
if !pymode#save()
|
||||
return 0
|
||||
endif
|
||||
PymodePython rope.GenerateElementRefactoring('package').run()
|
||||
endfunction "}}}
|
||||
99
vim-plugins/python-mode/autoload/pymode/run.vim
Normal file
99
vim-plugins/python-mode/autoload/pymode/run.vim
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
" The following lines set Vim's errorformat variable, to allow the
|
||||
" quickfix window to show Python tracebacks properly. It is much
|
||||
" easier to use let than set, because set requires many more
|
||||
" characters to be escaped. This is much easier to read and
|
||||
" maintain. % escapes are still needed however before any regex meta
|
||||
" characters. Hence \S (non-whitespace) becomes %\S etc. Note that
|
||||
" * becomes %#, so .* (match any character) becomes %.%# Commas must
|
||||
" also be escaped, with a backslash (\,). See the Vim help on
|
||||
" quickfix for details.
|
||||
"
|
||||
" Python errors are multi-lined. They often start with 'Traceback', so
|
||||
" we want to capture that (with +G) and show it in the quickfix window
|
||||
" because it explains the order of error messages.
|
||||
let s:efm = '%+GTraceback%.%#,'
|
||||
|
||||
" The error message itself starts with a line with 'File' in it. There
|
||||
" are a couple of variations, and we need to process a line beginning
|
||||
" with whitespace followed by File, the filename in "", a line number,
|
||||
" and optional further text. %E here indicates the start of a multi-line
|
||||
" error message. The %\C at the end means that a case-sensitive search is
|
||||
" required.
|
||||
let s:efm .= '%E File "%f"\, line %l\,%m%\C,'
|
||||
let s:efm .= '%E File "%f"\, line %l%\C,'
|
||||
|
||||
" The possible continutation lines are idenitifed to Vim by %C. We deal
|
||||
" with these in order of most to least specific to ensure a proper
|
||||
" match. A pointer (^) identifies the column in which the error occurs
|
||||
" (but will not be entirely accurate due to indention of Python code).
|
||||
let s:efm .= '%C%p^,'
|
||||
|
||||
" Any text, indented by more than two spaces contain useful information.
|
||||
" We want this to appear in the quickfix window, hence %+.
|
||||
let s:efm .= '%+C %.%#,'
|
||||
let s:efm .= '%+C %.%#,'
|
||||
|
||||
" The last line (%Z) does not begin with any whitespace. We use a zero
|
||||
" width lookahead (\&) to check this. The line contains the error
|
||||
" message itself (%m)
|
||||
let s:efm .= '%Z%\S%\&%m,'
|
||||
|
||||
" We can ignore any other lines (%-G)
|
||||
let s:efm .= '%-G%.%#'
|
||||
|
||||
PymodePython from pymode.run import run_code
|
||||
|
||||
|
||||
" DESC: Run python code
|
||||
fun! pymode#run#code_run(line1, line2) "{{{
|
||||
|
||||
let l:output = []
|
||||
let l:traceback = []
|
||||
call setqflist([])
|
||||
|
||||
call pymode#wide_message("Code running ...")
|
||||
|
||||
try
|
||||
|
||||
PymodePython run_code()
|
||||
|
||||
if len(l:output)
|
||||
call pymode#tempbuffer_open('__run__')
|
||||
call append(line('$'), l:output)
|
||||
normal dd
|
||||
wincmd p
|
||||
else
|
||||
call pymode#wide_message("No output.")
|
||||
endif
|
||||
|
||||
cexpr ""
|
||||
|
||||
let l:_efm = &efm
|
||||
|
||||
let &efm = s:efm
|
||||
|
||||
cgetexpr(l:traceback)
|
||||
|
||||
" If a range is run (starting other than at line 1), fix the reported error line numbers for
|
||||
" the current buffer
|
||||
if a:line1 > 1
|
||||
let qflist = getqflist()
|
||||
for i in qflist
|
||||
if i.bufnr == bufnr("")
|
||||
let i.lnum = i.lnum - 1 + a:line1
|
||||
endif
|
||||
endfor
|
||||
call setqflist(qflist)
|
||||
endif
|
||||
|
||||
call pymode#quickfix_open(0, g:pymode_quickfix_maxheight, g:pymode_quickfix_maxheight, 0)
|
||||
|
||||
let &efm = l:_efm
|
||||
|
||||
catch /E234/
|
||||
|
||||
echohl Error | echo "Run-time error." | echohl none
|
||||
|
||||
endtry
|
||||
|
||||
endfunction "}}}
|
||||
81
vim-plugins/python-mode/autoload/pymode/tools/loclist.vim
Normal file
81
vim-plugins/python-mode/autoload/pymode/tools/loclist.vim
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
let g:PymodeLocList= {}
|
||||
|
||||
|
||||
fun! pymode#tools#loclist#init() "{{{
|
||||
return
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeLocList.init(raw_list) "{{{
|
||||
let obj = copy(self)
|
||||
let loc_list = filter(copy(a:raw_list), 'v:val["valid"] == 1')
|
||||
call obj.clear()
|
||||
let obj._title = 'CodeCheck'
|
||||
return obj
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeLocList.current() "{{{
|
||||
if !exists("b:pymode_loclist")
|
||||
let b:pymode_loclist = g:PymodeLocList.init([])
|
||||
endif
|
||||
return b:pymode_loclist
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeLocList.is_empty() "{{{
|
||||
return empty(self._loclist)
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeLocList.clear() "{{{
|
||||
let self._loclist = []
|
||||
let self._messages = {}
|
||||
let self._name = expand('%:t')
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeLocList.extend(raw_list) "{{{
|
||||
call extend(self._loclist, a:raw_list)
|
||||
for issue in a:raw_list
|
||||
let self._messages[issue.lnum] = issue.text
|
||||
endfor
|
||||
return self
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeLocList.filter(filters) "{{{
|
||||
let loclist = []
|
||||
for error in self._loclist
|
||||
let passes_filters = 1
|
||||
for key in keys(a:filters)
|
||||
if get(error, key, '') !=? a:filters[key]
|
||||
let passes_filters = 0
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
if passes_filters
|
||||
call add(loclist, error)
|
||||
endif
|
||||
|
||||
endfor
|
||||
return loclist
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeLocList.show() "{{{
|
||||
call setloclist(0, self._loclist)
|
||||
if self.is_empty()
|
||||
lclose
|
||||
elseif g:pymode_lint_cwindow
|
||||
let num = winnr()
|
||||
lopen
|
||||
setl nowrap
|
||||
execute max([min([line("$"), g:pymode_quickfix_maxheight]), g:pymode_quickfix_minheight]) . "wincmd _"
|
||||
if num != winnr()
|
||||
call setwinvar(winnr(), 'quickfix_title', self._title . ' <' . self._name . '>')
|
||||
exe num . "wincmd w"
|
||||
endif
|
||||
end
|
||||
endfunction "}}}
|
||||
57
vim-plugins/python-mode/autoload/pymode/tools/signs.vim
Normal file
57
vim-plugins/python-mode/autoload/pymode/tools/signs.vim
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
let g:PymodeSigns = {}
|
||||
|
||||
|
||||
fun! pymode#tools#signs#init() "{{{
|
||||
call g:PymodeSigns.setup()
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeSigns.enabled() "{{{
|
||||
return (g:pymode_lint_signs && has('signs'))
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeSigns.setup() "{{{
|
||||
if self.enabled()
|
||||
execute 'sign define PymodeW text=' . g:pymode_lint_todo_symbol . " texthl=Todo"
|
||||
execute 'sign define PymodeD text=' . g:pymode_lint_docs_symbol . " texthl=String"
|
||||
execute 'sign define PymodeC text=' . g:pymode_lint_comment_symbol . " texthl=Comment"
|
||||
execute 'sign define PymodeR text=' . g:pymode_lint_visual_symbol . " texthl=Visual"
|
||||
execute 'sign define PymodeE text=' . g:pymode_lint_error_symbol . " texthl=Error"
|
||||
execute 'sign define PymodeI text=' . g:pymode_lint_info_symbol . " texthl=Info"
|
||||
execute 'sign define PymodeF text=' . g:pymode_lint_pyflakes_symbol . " texthl=Info"
|
||||
endif
|
||||
let self._sign_ids = []
|
||||
let self._next_id = 10000
|
||||
let self._messages = {}
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeSigns.refresh(loclist) "{{{
|
||||
if self.enabled()
|
||||
call self.clear()
|
||||
call self.place(a:loclist)
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeSigns.clear() "{{{
|
||||
let ids = copy(self._sign_ids)
|
||||
for i in ids
|
||||
execute "sign unplace " . i
|
||||
call remove(self._sign_ids, index(self._sign_ids, i))
|
||||
endfor
|
||||
endfunction "}}}
|
||||
|
||||
|
||||
fun! g:PymodeSigns.place(loclist) "{{{
|
||||
let seen = {}
|
||||
for issue in a:loclist._loclist
|
||||
if !has_key(seen, issue.lnum)
|
||||
let seen[issue.lnum] = 1
|
||||
call add(self._sign_ids, self._next_id)
|
||||
execute printf('sign place %d line=%d name=%s buffer=%d', self._next_id, issue.lnum, "Pymode".issue.type[0], issue.bufnr)
|
||||
let self._next_id += 1
|
||||
endif
|
||||
endfor
|
||||
endfunction "}}}
|
||||
89
vim-plugins/python-mode/autoload/pymode/troubleshooting.vim
Normal file
89
vim-plugins/python-mode/autoload/pymode/troubleshooting.vim
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
" 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
|
||||
|
||||
if !pymode#default('g:pymode_init', 1)
|
||||
call pymode#init(expand('<sfile>:p:h'), g:pymode_paths)
|
||||
call pymode#virtualenv#init()
|
||||
call pymode#breakpoint#init()
|
||||
endif
|
||||
|
||||
call append('0', ['Pymode diagnostic',
|
||||
\ '===================',
|
||||
\ 'VIM:' . v:version . ', OS: ' . os .', multi_byte:' . has('multi_byte') . ', pymode: ' . g:pymode_version . ', pymode-python: ' . g:pymode_python,
|
||||
\ ''])
|
||||
|
||||
if !exists('#filetypeplugin')
|
||||
call append('$', ['WARNING: ', 'Python-mode required :filetype plugin indent on', ''])
|
||||
endif
|
||||
|
||||
call append('$', ['+python: ' . has('python')])
|
||||
call append('$', ['+python3: ' . has('python3'), ''])
|
||||
|
||||
if g:pymode_python == 'disable'
|
||||
|
||||
if !has('python') && !has('python3')
|
||||
|
||||
call append('$', ['WARNING: Python-mode required vim compiled with +python or +python3.',
|
||||
\ '"lint, rope, run, doc, virtualenv" features disabled.', ''])
|
||||
|
||||
else
|
||||
|
||||
call append('$', ['WARNING: Python is disabled by `pymode_python` option.',
|
||||
\ '"lint, rope, run, doc, virtualenv" features disabled.', ''])
|
||||
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
call append('$', 'VIM python paths:')
|
||||
call append('$', '-----------------')
|
||||
PymodePython << EOF
|
||||
import vim
|
||||
vim.command('let l:output = %s' % repr(sys.path))
|
||||
EOF
|
||||
call append('$', output)
|
||||
call append('$', '')
|
||||
|
||||
endif
|
||||
|
||||
call append('$', 'Pymode variables:')
|
||||
call append('$', '-------------------')
|
||||
call append('$', 'let pymode = ' . string(g:pymode))
|
||||
call append('$', 'let pymode_breakpoint = ' . string(g:pymode_breakpoint))
|
||||
call append('$', 'let pymode_breakpoint_bind = ' . string(g:pymode_breakpoint_bind))
|
||||
call append('$', 'let pymode_doc = ' . string(g:pymode_doc))
|
||||
call append('$', 'let pymode_doc_bind = ' . string(g:pymode_doc_bind))
|
||||
call append('$', 'let pymode_folding = ' . string(g:pymode_folding))
|
||||
call append('$', 'let pymode_indent = ' . string(g:pymode_indent))
|
||||
call append('$', 'let pymode_lint = ' . string(g:pymode_lint))
|
||||
call append('$', 'let pymode_lint_checkers = ' . string(g:pymode_lint_checkers))
|
||||
call append('$', 'let pymode_lint_cwindow = ' . string(g:pymode_lint_cwindow))
|
||||
call append('$', 'let pymode_lint_ignore = ' . string(g:pymode_lint_ignore))
|
||||
call append('$', 'let pymode_lint_message = ' . string(g:pymode_lint_message))
|
||||
call append('$', 'let pymode_lint_on_fly = ' . string(g:pymode_lint_on_fly))
|
||||
call append('$', 'let pymode_lint_on_write = ' . string(g:pymode_lint_on_write))
|
||||
call append('$', 'let pymode_lint_select = ' . string(g:pymode_lint_select))
|
||||
call append('$', 'let pymode_lint_signs = ' . string(g:pymode_lint_signs))
|
||||
call append('$', 'let pymode_motion = ' . string(g:pymode_motion))
|
||||
call append('$', 'let pymode_options = ' . string(g:pymode_options))
|
||||
call append('$', 'let pymode_paths = ' . string(g:pymode_paths))
|
||||
call append('$', 'let pymode_quickfix_maxheight = ' . string(g:pymode_quickfix_maxheight))
|
||||
call append('$', 'let pymode_quickfix_minheight = ' . string(g:pymode_quickfix_minheight))
|
||||
call append('$', 'let pymode_rope = ' . string(g:pymode_rope))
|
||||
call append('$', 'let pymode_run = ' . string(g:pymode_run))
|
||||
call append('$', 'let pymode_run_bind = ' . string(g:pymode_run_bind))
|
||||
call append('$', 'let pymode_trim_whitespaces = ' . string(g:pymode_trim_whitespaces))
|
||||
call append('$', 'let pymode_virtualenv = ' . string(g:pymode_virtualenv))
|
||||
call append('$', 'let pymode_virtualenv_enabled = ' . string(g:pymode_virtualenv_enabled))
|
||||
call append('$', 'let pymode_virtualenv_path = ' . string(g:pymode_virtualenv_path))
|
||||
|
||||
endfunction "}}}
|
||||
17
vim-plugins/python-mode/autoload/pymode/virtualenv.vim
Normal file
17
vim-plugins/python-mode/autoload/pymode/virtualenv.vim
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
" Support virtualenv
|
||||
"
|
||||
PymodePython from pymode.virtualenv import enable_virtualenv
|
||||
|
||||
fun! pymode#virtualenv#init() "{{{
|
||||
if !g:pymode_virtualenv || g:pymode_virtualenv_path == ""
|
||||
return
|
||||
endif
|
||||
|
||||
PymodePython enable_virtualenv()
|
||||
|
||||
endfunction "}}}
|
||||
|
||||
fun! pymode#virtualenv#activate(path) "{{{
|
||||
let g:pymode_virtualenv_path = a:path
|
||||
call pymode#virtualenv#init()
|
||||
endfunction "}}}
|
||||
13
vim-plugins/python-mode/debug.vim
Normal file
13
vim-plugins/python-mode/debug.vim
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
" Use this settings for testing the plugin.
|
||||
" Run vim with command
|
||||
"
|
||||
" $ vim -u debug.py
|
||||
"
|
||||
" Only python-mode will be loaded.
|
||||
|
||||
|
||||
execute('set rtp+='. expand('<sfile>:p:h'))
|
||||
set rtp -=$HOME/.vim
|
||||
set rtp -=$HOME/.vim/after
|
||||
set nocp
|
||||
syntax enable
|
||||
796
vim-plugins/python-mode/doc/pymode.txt
Normal file
796
vim-plugins/python-mode/doc/pymode.txt
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
*pymode.txt* *python-mode.txt* *pymode* *python-mode*
|
||||
|
||||
____ _ _ ____ _ _ _____ _ _ __ __ _____ ____ ____ ~
|
||||
( _ \( \/ )(_ _)( )_( )( _ )( \( )___( \/ )( _ )( _ \( ___) ~
|
||||
)___/ \ / )( ) _ ( )(_)( ) ((___)) ( )(_)( )(_) ))__) ~
|
||||
(__) (__) (__) (_) (_)(_____)(_)\_) (_/\/\_)(_____)(____/(____) ~
|
||||
|
||||
|
||||
Version: 0.9.0
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *pymode-contents*
|
||||
|
||||
1.Intro.......................................................|pymode-intro|
|
||||
2.Common functionality.......................................|pymode-common|
|
||||
2.1 Python version...............................|pymode-python-version|
|
||||
2.2 Python indentation...................................|pymode-indent|
|
||||
2.3 Python folding......................................|pymode-folding|
|
||||
2.4 Vim motion...........................................|pymode-motion|
|
||||
2.5 Show documentation............................|pymode-documentation|
|
||||
2.6 Support virtualenv...............................|pymode-virtualenv|
|
||||
2.7 Run code................................................|pymode-run|
|
||||
2.8 Breakpoints.....................................|pymode-breakpoints|
|
||||
3. Code checking...............................................|pymode-lint|
|
||||
3.1 Code checkers options..........................|pymode-lint-options|
|
||||
4. Rope support................................................|pymode-rope|
|
||||
4.1 Code completion..................................|pymode-completion|
|
||||
4.2 Find definition.................................|pymode-rope-findit|
|
||||
4.3 Refactoring................................|pymode-rope-refactoring|
|
||||
4.4 Undo/Redo changes.................................|pymode-rope-undo|
|
||||
5. Syntax....................................................|pymode-syntax|
|
||||
6.FAQ...........................................................|pymode-faq|
|
||||
7.Credits...................................................|pymode-credits|
|
||||
8.License...................................................|pymode-license|
|
||||
|
||||
==============================================================================
|
||||
1. Intro ~
|
||||
*pymode-intro*
|
||||
|
||||
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.
|
||||
|
||||
Python-mode contains all you need to develop python applications in Vim.
|
||||
|
||||
Features: *pymode-features*
|
||||
|
||||
- Support Python version 2.6+ and 3.2+
|
||||
- Syntax highlighting
|
||||
- Virtualenv support
|
||||
- Run python code (``<leader>r``)
|
||||
- Add/remove breakpoints (``<leader>b``)
|
||||
- Improved Python indentation
|
||||
- Python folding
|
||||
- Python motions and operators (``]]``, ``3[[``, ``]]M``, ``vaC``, ``viM``,
|
||||
``daC``, ``ciM``, ...)
|
||||
- Code checking (pylint_, pyflakes_, pylama_, ...) that can be run
|
||||
simultaneously (``:PymodeLint``)
|
||||
- Autofix PEP8 errors (``:PymodeLintAuto``)
|
||||
- Search in python documentation (``K``)
|
||||
- Code refactoring <rope refactoring library> (rope_)
|
||||
- Strong code completion (rope_)
|
||||
- Go to definition (``<C-c>g`` for `:RopeGotoDefinition`)
|
||||
- And more, more ...
|
||||
|
||||
|
||||
==============================================================================
|
||||
2. Common functionality ~
|
||||
*pymode-common*
|
||||
|
||||
This script provides the following options that can customizes the behavior of
|
||||
PythonMode. These options should be set in your |vimrc|.
|
||||
|
||||
Below shows the default values.
|
||||
|
||||
|
||||
Turn on the whole plugin *'g:pymode'*
|
||||
>
|
||||
let g:pymode = 1
|
||||
|
||||
Turn off plugin's warnings *'g:pymode_warnings'*
|
||||
>
|
||||
let g:pymode_warnings = 1
|
||||
|
||||
Add paths to `sys.path` *'g:pymode_paths'*
|
||||
Value is list of path's strings.
|
||||
>
|
||||
let g:pymode_paths = []
|
||||
|
||||
Trim unused white spaces on save *'g:pymode_trim_whitespaces'*
|
||||
>
|
||||
let g:pymode_trim_whitespaces = 1
|
||||
|
||||
Setup default python options *'g:pymode_options'*
|
||||
>
|
||||
let g:pymode_options = 1
|
||||
|
||||
If this option is set to 1, pymode will enable the following options for
|
||||
python buffers: >
|
||||
|
||||
setlocal complete+=t
|
||||
setlocal formatoptions-=t
|
||||
if v:version > 702 && !&relativenumber
|
||||
setlocal number
|
||||
endif
|
||||
setlocal nowrap
|
||||
setlocal textwidth=79
|
||||
setlocal commentstring=#%s
|
||||
setlocal define=^\s*\\(def\\\\|class\\)
|
||||
|
||||
Setup max line length *'g:pymode_options_max_line_length'*
|
||||
>
|
||||
let g:pymode_options_max_line_length = 79
|
||||
|
||||
Enable colorcolumn display at max_line_length *'g:pymode_options_colorcolumn'*
|
||||
>
|
||||
let g:pymode_options_colorcolumn = 1
|
||||
|
||||
Setup pymode |quickfix| window
|
||||
|
||||
*'g:pymode_quickfix_maxheight'* *'g:pymode_quickfix_minheight'*
|
||||
>
|
||||
let g:pymode_quickfix_minheight = 3
|
||||
let g:pymode_quickfix_maxheight = 6
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.1. Python version ~
|
||||
*pymode-python-version*
|
||||
|
||||
By default pymode looks for current python version supported in your Vim.
|
||||
You could choose prefer version, but value will be tested on loading.
|
||||
|
||||
*'g:pymode_python'*
|
||||
>
|
||||
let g:pymode_python = 'python'
|
||||
|
||||
Values are `python`, `python3`, `disable`. If value set to `disable` most
|
||||
python-features of **pymode** will be disabled.
|
||||
|
||||
Set value to `python3` if you are working with python3 projects. You could use
|
||||
|exrc|
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.2 Python indentation ~
|
||||
*pymode-indent*
|
||||
|
||||
Pymode supports PEP8-compatible python indent.
|
||||
Enable pymode indentation *'g:pymode_indent'*
|
||||
>
|
||||
let g:pymode_indent = 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.3 Python folding ~
|
||||
*pymode-folding*
|
||||
|
||||
Fast and usual python folding in Vim.
|
||||
Enable pymode folding *'g:pymode_folding'*
|
||||
>
|
||||
let g:pymode_folding = 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.4 Vim motion ~
|
||||
*pymode-motion*
|
||||
|
||||
Support Vim motion (See |operator|) for python objects (such as functions,
|
||||
class and methods).
|
||||
|
||||
`C` — means class
|
||||
`M` — means method or function
|
||||
*pymode-motion-keys*
|
||||
|
||||
================ ============================
|
||||
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)
|
||||
================ ============================
|
||||
|
||||
Enable pymode-motion *'g:pymode_motion'*
|
||||
>
|
||||
let g:pymode_motion = 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.5 Show documentation ~
|
||||
*pymode-documentation*
|
||||
|
||||
Pymode could show documentation for current word by `pydoc`.
|
||||
|
||||
Commands:
|
||||
*:PymodeDoc* <args> — show documentation
|
||||
|
||||
Turns on the documentation script *'g:pymode_doc'*
|
||||
>
|
||||
let g:pymode_doc = 1
|
||||
|
||||
Bind keys to show documentation for current word (selection)
|
||||
*'g:pymode_doc_bind'*
|
||||
>
|
||||
let g:pymode_doc_bind = 'K'
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.6 Support virtualenv ~
|
||||
*pymode-virtualenv*
|
||||
|
||||
Commands:
|
||||
*:PymodeVirtualenv* <path> -- Activate virtualenv (path can be absolute or
|
||||
relative to current working directory)
|
||||
|
||||
Enable automatic virtualenv detection *'g:pymode_virtualenv'*
|
||||
>
|
||||
let g:pymode_virtualenv = 1
|
||||
|
||||
Set path to virtualenv manually *'g:pymode_virtualenv_path'*
|
||||
>
|
||||
let g:pymode_virtualenv_path = $VIRTUAL_ENV
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.7 Run code ~
|
||||
*pymode-run*
|
||||
|
||||
Commands:
|
||||
*:PymodeRun* -- Run current buffer or selection
|
||||
|
||||
Turn on the run code script *'g:pymode_run'*
|
||||
>
|
||||
let g:pymode_run = 1
|
||||
|
||||
Binds keys to run python code *'g:pymode_run_bind'*
|
||||
>
|
||||
let g:pymode_run_bind = '<leader>r'
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2.8 Breakpoints ~
|
||||
*pymode-breakpoints*
|
||||
|
||||
Pymode automatically detects available debugger (like pdb, ipdb, pudb) and user
|
||||
can set/unset breakpoint with one key and without code checking and etc.
|
||||
|
||||
Enable functionality *'g:pymode_breakpoint'*
|
||||
>
|
||||
let g:pymode_breakpoint = 1
|
||||
|
||||
Bind keys
|
||||
>
|
||||
let g:pymode_breakpoint_bind = '<leader>b'
|
||||
|
||||
Manually set breakpoint command (leave empty for automatic detection)
|
||||
>
|
||||
let g:pymode_breakpoint_cmd = ''
|
||||
|
||||
|
||||
==============================================================================
|
||||
3. Code checking ~
|
||||
*pymode-lint*
|
||||
|
||||
Pymode supports `pylint`, `pep257`, `pep8`, `pyflakes`, `mccabe` code
|
||||
checkers. You could run several similar checkers.
|
||||
|
||||
Pymode uses Pylama library for code checking. Many options like skip
|
||||
files, errors and etc could be defined in `pylama.ini` file or modelines.
|
||||
Check Pylama documentation for details.
|
||||
|
||||
Pylint options (ex. disable messages) may be defined in `$HOME/pylint.rc`
|
||||
See pylint documentation.
|
||||
|
||||
Commands:
|
||||
*:PymodeLint* -- Check code in current buffer
|
||||
*:PymodeLintToggle* -- Toggle code checking
|
||||
*:PymodeLintAuto* -- Fix PEP8 errors in current buffer automatically
|
||||
|
||||
Turn on code checking *'g:pymode_lint'*
|
||||
>
|
||||
let g:pymode_lint = 1
|
||||
|
||||
Check code on every save (if file has been modified) *'g:pymode_lint_on_write'*
|
||||
>
|
||||
let g:pymode_lint_on_write = 1
|
||||
|
||||
Check code on every save (every) *'g:pymode_lint_unmodified'*
|
||||
>
|
||||
let g:pymode_lint_unmodified = 0
|
||||
|
||||
Check code when editing (on the fly) *'g:pymode_lint_on_fly'*
|
||||
>
|
||||
let g:pymode_lint_on_fly = 0
|
||||
|
||||
Show error message if cursor placed at the error line *'g:pymode_lint_message'*
|
||||
>
|
||||
let g:pymode_lint_message = 1
|
||||
|
||||
Default code checkers (you could set several) *'g:pymode_lint_checkers'*
|
||||
>
|
||||
let g:pymode_lint_checkers = ['pyflakes', 'pep8', 'mccabe']
|
||||
|
||||
Values may be chosen from: `pylint`, `pep8`, `mccabe`, `pep257`, `pyflakes`.
|
||||
|
||||
Skip errors and warnings *'g:pymode_lint_ignore'*
|
||||
E.g. "E501,W002", "E2,W" (Skip all Warnings and Errors that starts with E2) and etc
|
||||
>
|
||||
let g:pymode_lint_ignore = "E501,W"
|
||||
|
||||
Select some error or warnings. *'g:pymode_lint_select'*
|
||||
By example you disable all warnings starting from 'W', but want to see warning
|
||||
'W0011' and warning 'W430'
|
||||
>
|
||||
let g:pymode_lint_select = "E501,W0011,W430"
|
||||
|
||||
Sort errors by relevance *'g:pymode_lint_sort'*
|
||||
If not empty, errors will be sort by defined relevance
|
||||
E.g. let g:pymode_lint_sort = ['E', 'C', 'I'] " Errors first 'E',
|
||||
after them 'C' and ...
|
||||
>
|
||||
let g:pymode_lint_sort = []
|
||||
|
||||
Auto open cwindow (quickfix) if any errors have been found
|
||||
*'g:pymode_lint_cwindow'*
|
||||
>
|
||||
let g:pymode_lint_cwindow = 1
|
||||
|
||||
Place error |signs| *'g:pymode_signs'*
|
||||
>
|
||||
let g:pymode_lint_signs = 1
|
||||
|
||||
Definitions for |signs|
|
||||
>
|
||||
let g:pymode_lint_todo_symbol = 'WW'
|
||||
let g:pymode_lint_comment_symbol = 'CC'
|
||||
let g:pymode_lint_visual_symbol = 'RR'
|
||||
let g:pymode_lint_error_symbol = 'EE'
|
||||
let g:pymode_lint_info_symbol = 'II'
|
||||
let g:pymode_lint_pyflakes_symbol = 'FF'
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.1 Set code checkers options ~
|
||||
*pymode-lint-options*
|
||||
|
||||
Pymode has the ability to set code checkers options from pymode variables:
|
||||
|
||||
Set PEP8 options *'g:pymode_lint_options_pep8'*
|
||||
>
|
||||
let g:pymode_lint_options_pep8 =
|
||||
\ {'max_line_length': g:pymode_options_max_line_length})
|
||||
|
||||
See https://pep8.readthedocs.org/en/1.4.6/intro.html#configuration for more
|
||||
info.
|
||||
|
||||
Set Pyflakes options *'g:pymode_lint_options_pyflakes'*
|
||||
>
|
||||
let g:pymode_lint_options_pyflakes = { 'builtins': '_' }
|
||||
|
||||
Set mccabe options *'g:pymode_lint_options_mccabe'*
|
||||
>
|
||||
let g:pymode_lint_options_mccabe = { 'complexity': 12 }
|
||||
|
||||
Set pep257 options *'g:pymode_lint_options_pep257'*
|
||||
>
|
||||
let g:pymode_lint_options_pep257 = {}
|
||||
|
||||
Set pylint options *'g:pymode_lint_options_pylint'*
|
||||
>
|
||||
let g:pymode_lint_options_pylint =
|
||||
\ {'max-line-length': g:pymode_options_max_line_length})
|
||||
|
||||
See http://docs.pylint.org/features.html#options for more info.
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
3. Rope support ~
|
||||
*pymode-rope*
|
||||
|
||||
Pymode supports Rope refactoring operations, code completion and code assists.
|
||||
|
||||
Commands:
|
||||
|:PymodeRopeAutoImport| -- Resolve import for element under cursor
|
||||
|:PymodeRopeModuleToPackage| -- Convert current module to package
|
||||
|:PymodeRopeNewProject| -- Open new Rope project in current working directory
|
||||
|:PymodeRopeRedo| -- Redo changes from last refactoring
|
||||
|:PymodeRopeRegenerate| -- Regenerate the project cache
|
||||
|:PymodeRopeRenameModule| -- Rename current module
|
||||
|:PymodeRopeUndo| -- Undo changes from last refactoring
|
||||
|
||||
|
||||
Turn on the rope script *'g:pymode_rope'*
|
||||
>
|
||||
let g:pymode_rope = 1
|
||||
|
||||
.ropeproject Folder ~
|
||||
*.ropeproject*
|
||||
|
||||
*:PymodeRopeNewProject* [<path>] -- Open new Rope project in the given path
|
||||
*:PymodeRopeRegenerate* -- Regenerate the project cache
|
||||
|
||||
Rope uses a folder inside projects for holding project configuration and data.
|
||||
Its default name is `.ropeproject`. It is recommended that you do not add the
|
||||
.ropeproject folder to version control system.
|
||||
|
||||
Currently it is used for things such as:
|
||||
|
||||
* The config.py file in this folder contains project configuration. Have
|
||||
a look at the default config.py file (which is created when it
|
||||
does not exist) for more information.
|
||||
* It can be used for saving project history, so that the next time you open the
|
||||
project you can undo past changes.
|
||||
* It can be used to save information about object inferences.
|
||||
* It can be used to save a global name cache, which is used for auto-import.
|
||||
|
||||
By default, if `.ropeproject` is not found in the current directory, rope will
|
||||
look recursively for it in parent folders.
|
||||
|
||||
Warning: If rope finds `.ropeproject` in a parent dir, it will use it with
|
||||
all its child directories, which may slow scanning down (because of many,
|
||||
possibly unrelated, files)
|
||||
|
||||
Enable searching for |.ropeproject| in parent directories
|
||||
*'g:pymode_rope_lookup_project'*
|
||||
>
|
||||
let g:pymode_rope_lookup_project = 0
|
||||
|
||||
You can also manually set the rope project directory. If not specified rope will
|
||||
use the current directory.
|
||||
*'g:pymode_rope_project_root'*
|
||||
>
|
||||
let g:pymode_rope_project_root = ""
|
||||
|
||||
|
||||
The location of the `.ropeproject` folder may also be overridden if you wish to
|
||||
keep it outside of your project root. The rope library treats this folder as a
|
||||
project resource, so the path will always be relative to your project root (a
|
||||
leading '/' will be ignored). You may use `'..'` path segments to place the
|
||||
folder outside of your project root.
|
||||
*'g:pymode_rope_ropefolder'*
|
||||
>
|
||||
let g:pymode_rope_ropefolder='.ropeproject'
|
||||
|
||||
|
||||
|
||||
Show documentation for element under cursor ~
|
||||
|
||||
Show documentation for object under cursor. *'g:pymode_rope_show_doc_bind'*
|
||||
Leave empty to disable the key binding.
|
||||
>
|
||||
let g:pymode_rope_show_doc_bind = '<C-c>d'
|
||||
|
||||
Regenerate project cache on every save (if file has been modified)
|
||||
>
|
||||
let g:pymode_rope_regenerate_on_write = 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
4.1 Completion ~
|
||||
*pymode-completion*
|
||||
|
||||
By default you can use <Ctrl-Space> for autocompletion. The first entry will
|
||||
be automatically selected and you can press <Return> to insert the entry in
|
||||
your code. <C-X><C-O> and <C-P>/<C-N> works too.
|
||||
|
||||
Autocompletion is also called by typing a period in |Insert| mode by default.
|
||||
|
||||
|
||||
Turn on code completion support in the plugin *'g:pymode_rope_completion'*
|
||||
>
|
||||
let g:pymode_rope_completion = 1
|
||||
|
||||
Turn on autocompletion when typing a period
|
||||
*'g:pymode_rope_complete_on_dot'*
|
||||
>
|
||||
let g:pymode_rope_complete_on_dot = 1
|
||||
|
||||
Keymap for autocomplete *'g:pymode_rope_completion_bind'*
|
||||
>
|
||||
let g:pymode_rope_completion_bind = '<C-Space>'
|
||||
|
||||
Extended autocompletion (rope could complete objects which have not been
|
||||
imported) from project *'g:pymode_rope_autoimport'*
|
||||
>
|
||||
let g:pymode_rope_autoimport = 0
|
||||
|
||||
Load modules to autoimport by default *'g:pymode_rope_autoimport_modules'*
|
||||
>
|
||||
let g:pymode_rope_autoimport_modules = ['os', 'shutil', 'datetime']
|
||||
|
||||
Offer to unresolved import object after completion.
|
||||
>
|
||||
let g:pymode_rope_autoimport_import_after_complete = 0
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
4.2 Find definition ~
|
||||
*pymode-rope-findit*
|
||||
|
||||
By default when you press *<C-C>g* on any object in your code you will be moved
|
||||
to definition.
|
||||
Leave empty for disable key binding. *'g:pymode_rope_goto_definition_bind'*
|
||||
>
|
||||
let g:pymode_rope_goto_definition_bind = '<C-c>g'
|
||||
|
||||
Command for open window when definition has been found
|
||||
Values are (`e`, `new`, `vnew`) *'g:pymode_rope_goto_definition_cmd'*
|
||||
>
|
||||
let g:pymode_rope_goto_definition_cmd = 'new'
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
4.3 Refactoring ~
|
||||
*pymode-rope-refactoring*
|
||||
|
||||
Rename method/function/class/variable in the project ~
|
||||
|
||||
Pymode can rename everything: classes, functions, modules, packages, methods,
|
||||
variables and keyword arguments.
|
||||
|
||||
Keymap for rename method/function/class/variables under cursor
|
||||
*'g:pymode_rope_rename_bind'*
|
||||
>
|
||||
let g:pymode_rope_rename_bind = '<C-c>rr'
|
||||
|
||||
|
||||
Rename a current module/package ~
|
||||
|
||||
*:PymodeRopeRenameModule* -- Rename current module
|
||||
|
||||
Keymap for rename current module *'g:pymode_rope_rename_module_bind'*
|
||||
>
|
||||
let g:pymode_rope_rename_module_bind = '<C-c>r1r'
|
||||
|
||||
|
||||
Imports ~
|
||||
|
||||
*:PymodeRopeAutoImport* -- Resolve import for element under cursor
|
||||
|
||||
Organize imports sorts imports, too. It does that according to PEP8. Unused
|
||||
imports will be dropped.
|
||||
Keymap *'g:pymode_rope_organize_imports_bind'*
|
||||
>
|
||||
let g:pymode_rope_organize_imports_bind = '<C-c>ro'
|
||||
|
||||
Insert import for current word under cursor *'g:pymode_rope_autoimport_bind'*
|
||||
Should be enabled |'g:pymode_rope_autoimport'|
|
||||
>
|
||||
let g:pymode_rope_autoimport_bind = '<C-c>ra'
|
||||
|
||||
|
||||
Convert module to package ~
|
||||
*'g:pymode_rope_module_to_package_bind'*
|
||||
|
||||
*:PymodeRopeModuleToPackage* -- convert current module to package
|
||||
|
||||
Keybinding:
|
||||
>
|
||||
let g:pymode_rope_module_to_package_bind = '<C-c>r1p'
|
||||
|
||||
|
||||
Extract method/variable ~
|
||||
*pymode-rope-extract*
|
||||
|
||||
Extract method/variable from selected lines.
|
||||
|
||||
*'g:pymode_rope_extract_method_bind'*
|
||||
*'g:pymode_rope_extract_variable_bind'*
|
||||
>
|
||||
let g:pymode_rope_extract_method_bind = '<C-c>rm'
|
||||
let g:pymode_rope_extract_variable_bind = '<C-c>rl'
|
||||
|
||||
|
||||
Use function ~
|
||||
*pymode-rope-use*
|
||||
|
||||
It tries to find the places in which a function can be used and changes the
|
||||
code to call it instead.
|
||||
>
|
||||
let g:pymode_rope_use_function_bind = '<C-c>ru'
|
||||
|
||||
|
||||
Move method/fields ~
|
||||
*pymode-rope-move*
|
||||
|
||||
It happens when you perform move refactoring on a method of a class. In this
|
||||
refactoring, a method of a class is moved to the class of one of its
|
||||
attributes. The old method will call the new method. If you want to change all
|
||||
of the occurrences of the old method to use the new method you can inline it
|
||||
afterwards.
|
||||
>
|
||||
let g:pymode_rope_move_bind = '<C-c>rv'
|
||||
|
||||
Change function signature ~
|
||||
>
|
||||
let g:pymode_rope_change_signature_bind = '<C-c>rs'
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
4.4 Undo/Redo changes ~
|
||||
*pymode-rope-undo*
|
||||
*pymode-rope-redo*
|
||||
|
||||
Commands:
|
||||
|
||||
*:PymodeRopeUndo* -- Undo last changes in the project
|
||||
*:PymodeRopeRedo* -- Redo last changes in the project
|
||||
|
||||
|
||||
==============================================================================
|
||||
5. Syntax ~
|
||||
*pymode-syntax*
|
||||
|
||||
Turn on pymode syntax *'g:pymode_syntax'*
|
||||
>
|
||||
let g:pymode_syntax = 1
|
||||
|
||||
Slower syntax synchronization that is better at handling code blocks in
|
||||
docstrings. Consider disabling this on slower hardware.
|
||||
*'g:pymode_syntax_slow_sync'*
|
||||
>
|
||||
let g:pymode_syntax_slow_sync = 1
|
||||
|
||||
Enable all python highlights *'g:pymode_syntax_all'*
|
||||
>
|
||||
let g:pymode_syntax_all = 1
|
||||
|
||||
Highlight "print" as a function *'g:pymode_syntax_print_as_function'*
|
||||
>
|
||||
let g:pymode_syntax_print_as_function = 0
|
||||
|
||||
Highlight "async/await" keywords *'g:pymode_syntax_highlight_async_await'*
|
||||
>
|
||||
let g:pymode_syntax_highlight_async_await = g:pymode_syntax_all
|
||||
|
||||
Highlight '=' operator *'g:pymode_syntax_highlight_equal_operator'*
|
||||
>
|
||||
let g:pymode_syntax_highlight_equal_operator = g:pymode_syntax_all
|
||||
|
||||
Highlight '*' operator *'g:pymode_syntax_highlight_stars_operator'*
|
||||
>
|
||||
let g:pymode_syntax_highlight_stars_operator = g:pymode_syntax_all
|
||||
|
||||
Highlight 'self' keyword *'g:pymode_syntax_highlight_self'*
|
||||
>
|
||||
let g:pymode_syntax_highlight_self = g:pymode_syntax_all
|
||||
|
||||
Highlight indent's errors *'g:pymode_syntax_indent_errors'*
|
||||
>
|
||||
let g:pymode_syntax_indent_errors = g:pymode_syntax_all
|
||||
|
||||
Highlight space's errors *'g:pymode_syntax_space_errors'*
|
||||
>
|
||||
let g:pymode_syntax_space_errors = g:pymode_syntax_all
|
||||
|
||||
Highlight string formatting *'g:pymode_syntax_string_formatting'*
|
||||
*'g:pymode_syntax_string_format'*
|
||||
*'g:pymode_syntax_string_templates'*
|
||||
*'g:pymode_syntax_doctests'*
|
||||
>
|
||||
let g:pymode_syntax_string_formatting = g:pymode_syntax_all
|
||||
let g:pymode_syntax_string_format = g:pymode_syntax_all
|
||||
let g:pymode_syntax_string_templates = g:pymode_syntax_all
|
||||
let g:pymode_syntax_doctests = g:pymode_syntax_all
|
||||
|
||||
Highlight builtin objects (True, False, ...) *'g:pymode_syntax_builtin_objs'*
|
||||
>
|
||||
let g:pymode_syntax_builtin_objs = g:pymode_syntax_all
|
||||
|
||||
Highlight builtin types (str, list, ...) *'g:pymode_syntax_builtin_types'*
|
||||
>
|
||||
let g:pymode_syntax_builtin_types = g:pymode_syntax_all
|
||||
|
||||
Highlight exceptions (TypeError, ValueError, ...)
|
||||
*'g:pymode_syntax_highlight_exceptions'*
|
||||
>
|
||||
let g:pymode_syntax_highlight_exceptions = g:pymode_syntax_all
|
||||
|
||||
Highlight docstrings as pythonDocstring (otherwise as pythonString)
|
||||
*'g:pymode_syntax_docstrings'*
|
||||
>
|
||||
let g:pymode_syntax_docstrings = g:pymode_syntax_all
|
||||
|
||||
|
||||
==============================================================================
|
||||
6. FAQ ~
|
||||
*pymode-faq*
|
||||
|
||||
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 *pymode-rope-slow*
|
||||
----------------------------
|
||||
|
||||
Rope creates a project-level service directory in |.ropeproject|
|
||||
|
||||
If ``.ropeproject`` is not found in the current directory, rope will walk
|
||||
upwards looking for a ``.ropeproject`` in every dir of the parent path. If
|
||||
rope finds ``.ropeproject`` in a parent dir, it sets the project for all child
|
||||
dirs and the scan may be slow for so many dirs and files.
|
||||
|
||||
Solutions:
|
||||
|
||||
- Delete `.ropeproject` from the parent dir to make rope create `.ropeproject`
|
||||
in the current dir.
|
||||
- Run ``:PymodeRopeNewProject`` to make rope create ``.ropeproject`` in the
|
||||
current dir.
|
||||
- Set |'g:pymode_rope_lookup_project'| to 0 for prevent searching in parent
|
||||
dirs.
|
||||
|
||||
You may also set |'g:pymode_rope_project_root'| to manually specify the project
|
||||
root path.
|
||||
|
||||
|
||||
|
||||
Pylint check is very slow
|
||||
-------------------------
|
||||
|
||||
In some projects pylint may check slowly, because it also scans imported
|
||||
modules if possible. Try using another code checker: see
|
||||
|'g:pymode_lint_checkers'|.
|
||||
|
||||
You may set |exrc| and |secure| in your |vimrc| to auto-set custom settings
|
||||
from `.vimrc` from your projects directories.
|
||||
|
||||
|
||||
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
|
||||
<
|
||||
|
||||
==============================================================================
|
||||
7. Credits ~
|
||||
*pymode-credits*
|
||||
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
|
||||
|
||||
|
||||
==============================================================================
|
||||
8. License ~
|
||||
*pymode-license*
|
||||
|
||||
Python-mode is released under the GNU lesser general public license.
|
||||
See: http://www.gnu.org/copyleft/lesser.html
|
||||
|
||||
If you like this plugin, I would very appreciated if you kindly send me a postcard :)
|
||||
|
||||
My address is: "Russia, 143500, MO, Istra, pos. Severny 8-3" to "Kirill Klenov".
|
||||
Thanks for your support!
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
1
vim-plugins/python-mode/ftplugin/pyrex.vim
Normal file
1
vim-plugins/python-mode/ftplugin/pyrex.vim
Normal file
|
|
@ -0,0 +1 @@
|
|||
runtime ftplugin/python/pymode.vim
|
||||
212
vim-plugins/python-mode/ftplugin/python/pymode.vim
Normal file
212
vim-plugins/python-mode/ftplugin/python/pymode.vim
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
if !g:pymode || pymode#default('b:pymode', 1)
|
||||
finish
|
||||
endif
|
||||
|
||||
if g:pymode_python == 'disable'
|
||||
|
||||
if g:pymode_warning
|
||||
call pymode#error("Pymode requires vim compiled with +python. Most of features will be disabled.")
|
||||
endif
|
||||
|
||||
finish
|
||||
|
||||
else
|
||||
|
||||
|
||||
let b:pymode_modified = &modified
|
||||
|
||||
" Init paths
|
||||
if !pymode#default('g:pymode_init', 1)
|
||||
|
||||
call pymode#init(expand('<sfile>:p:h:h:h'), g:pymode_paths)
|
||||
call pymode#virtualenv#init()
|
||||
call pymode#breakpoint#init()
|
||||
|
||||
PymodePython from pymode.utils import patch_paths
|
||||
PymodePython patch_paths()
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
command! -buffer -nargs=1 PymodeVirtualenv call pymode#virtualenv#activate(<args>)
|
||||
|
||||
" Setup events for pymode
|
||||
au! pymode BufWritePre <buffer> call pymode#buffer_pre_write()
|
||||
au! pymode BufWritePost <buffer> call pymode#buffer_post_write()
|
||||
|
||||
" Run python code
|
||||
if g:pymode_run
|
||||
|
||||
command! -buffer -nargs=0 -range=% PymodeRun call pymode#run#code_run(<f-line1>, <f-line2>)
|
||||
|
||||
exe "nnoremap <silent> <buffer> " g:pymode_run_bind ":PymodeRun<CR>"
|
||||
exe "vnoremap <silent> <buffer> " g:pymode_run_bind ":PymodeRun<CR>"
|
||||
|
||||
endif
|
||||
|
||||
" Add/remove breakpoints
|
||||
if g:pymode_breakpoint
|
||||
|
||||
exe "nnoremap <silent> <buffer> " g:pymode_breakpoint_bind ":call pymode#breakpoint#operate(line('.'))<CR>"
|
||||
|
||||
endif
|
||||
|
||||
" Python folding
|
||||
if g:pymode_folding
|
||||
|
||||
setlocal foldmethod=expr
|
||||
setlocal foldexpr=pymode#folding#expr(v:lnum)
|
||||
setlocal foldtext=pymode#folding#text()
|
||||
|
||||
endif
|
||||
|
||||
" Remove unused whitespaces
|
||||
if g:pymode_trim_whitespaces
|
||||
au BufWritePre <buffer> call pymode#trim_whitespaces()
|
||||
endif
|
||||
|
||||
" Custom options
|
||||
if g:pymode_options
|
||||
setlocal complete+=t
|
||||
setlocal formatoptions-=t
|
||||
if v:version > 702 && !&relativenumber
|
||||
setlocal number
|
||||
endif
|
||||
setlocal nowrap
|
||||
exe "setlocal textwidth=" . g:pymode_options_max_line_length
|
||||
if g:pymode_options_colorcolumn && exists('+colorcolumn')
|
||||
setlocal colorcolumn=+1
|
||||
endif
|
||||
setlocal commentstring=#%s
|
||||
setlocal define=^\s*\\(def\\\\|class\\)
|
||||
endif
|
||||
|
||||
if g:pymode_lint
|
||||
|
||||
command! -buffer -nargs=0 PymodeLintAuto :call pymode#lint#auto()
|
||||
command! -buffer -nargs=0 PymodeLintToggle :call pymode#lint#toggle()
|
||||
command! -buffer -nargs=0 PymodeLint :call pymode#lint#check()
|
||||
|
||||
if v:version > 703 || (v:version == 703 && has('patch544'))
|
||||
au! QuitPre <buffer> call pymode#quit()
|
||||
else
|
||||
au! pymode BufWinLeave * silent! lclose
|
||||
endif
|
||||
|
||||
let b:pymode_error_line = -1
|
||||
|
||||
if g:pymode_lint_on_fly
|
||||
au! pymode InsertLeave <buffer> PymodeLint
|
||||
endif
|
||||
|
||||
if g:pymode_lint_message
|
||||
au! pymode CursorMoved <buffer>
|
||||
au! pymode CursorMoved <buffer> call pymode#lint#show_errormessage()
|
||||
endif
|
||||
|
||||
" Disabled for current release
|
||||
if g:pymode_lint_async
|
||||
" let &l:updatetime = g:pymode_lint_async_updatetime
|
||||
" au! BufEnter <buffer> call pymode#lint#start()
|
||||
" au! BufLeave <buffer> call pymode#lint#stop()
|
||||
end
|
||||
|
||||
endif
|
||||
|
||||
" Show python documentation
|
||||
if g:pymode_doc
|
||||
|
||||
" Set commands
|
||||
command! -buffer -nargs=1 PymodeDoc call pymode#doc#show("<args>")
|
||||
|
||||
" Set keys
|
||||
exe "nnoremap <silent> <buffer> " g:pymode_doc_bind ":call pymode#doc#find()<CR>"
|
||||
exe "vnoremap <silent> <buffer> " g:pymode_doc_bind ":<C-U>call pymode#doc#show(@*)<CR>"
|
||||
|
||||
end
|
||||
|
||||
" Rope support
|
||||
if g:pymode_rope
|
||||
|
||||
if g:pymode_rope_goto_definition_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_goto_definition_bind . " :call pymode#rope#goto_definition()<CR>"
|
||||
endif
|
||||
if g:pymode_rope_show_doc_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_show_doc_bind . " :call pymode#rope#show_doc()<CR>"
|
||||
end
|
||||
if g:pymode_rope_find_it_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_find_it_bind . " :call pymode#rope#find_it()<CR>"
|
||||
end
|
||||
if g:pymode_rope_organize_imports_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_organize_imports_bind . " :call pymode#rope#organize_imports()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_rename_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_rename_bind . " :call pymode#rope#rename()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_rename_module_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_rename_module_bind . " :call pymode#rope#rename_module()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_extract_method_bind != ""
|
||||
exe "vnoremap <silent> <buffer> " . g:pymode_rope_extract_method_bind . " :call pymode#rope#extract_method()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_extract_variable_bind != ""
|
||||
exe "vnoremap <silent> <buffer> " . g:pymode_rope_extract_variable_bind . " :call pymode#rope#extract_variable()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_inline_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_inline_bind . " :call pymode#rope#inline()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_move_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_move_bind . " :call pymode#rope#move()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_change_signature_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_change_signature_bind . " :call pymode#rope#signature()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_use_function_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_use_function_bind . " :call pymode#rope#use_function()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_generate_function_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_generate_function_bind . " :call pymode#rope#generate_function()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_generate_package_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_generate_package_bind . " :call pymode#rope#generate_package()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_generate_class_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_generate_class_bind . " :call pymode#rope#generate_class()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_module_to_package_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_module_to_package_bind . " :call pymode#rope#module_to_package()<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_autoimport_bind != ""
|
||||
exe "noremap <silent> <buffer> " . g:pymode_rope_autoimport_bind . " :PymodeRopeAutoImport<CR>"
|
||||
end
|
||||
|
||||
if g:pymode_rope_completion && g:pymode_rope_complete_on_dot
|
||||
inoremap <silent> <buffer> . .<C-R>=pymode#rope#complete_on_dot()<CR>
|
||||
end
|
||||
|
||||
command! -buffer -nargs=? PymodeRopeNewProject call pymode#rope#new(<f-args>)
|
||||
command! -buffer PymodeRopeUndo call pymode#rope#undo()
|
||||
command! -buffer PymodeRopeRedo call pymode#rope#redo()
|
||||
command! -buffer PymodeRopeRenameModule call pymode#rope#rename_module()
|
||||
command! -buffer PymodeRopeModuleToPackage call pymode#rope#module_to_package()
|
||||
command! -buffer PymodeRopeRegenerate call pymode#rope#regenerate()
|
||||
|
||||
if g:pymode_rope_autoimport
|
||||
command! -buffer PymodeRopeAutoImport call pymode#rope#autoimport(expand('<cword>'))
|
||||
end
|
||||
|
||||
end
|
||||
BIN
vim-plugins/python-mode/logo.png
Normal file
BIN
vim-plugins/python-mode/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
316
vim-plugins/python-mode/plugin/pymode.vim
Normal file
316
vim-plugins/python-mode/plugin/pymode.vim
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
" vi: fdl=1
|
||||
let g:pymode_version = "0.9.0"
|
||||
|
||||
com! PymodeVersion echomsg "Current python-mode version: " . g:pymode_version
|
||||
com! PymodeTroubleshooting call pymode#troubleshooting#test()
|
||||
|
||||
" Enable pymode by default :)
|
||||
call pymode#default('g:pymode', 1)
|
||||
call pymode#default('g:pymode_debug', 0)
|
||||
|
||||
" DESC: Disable script loading
|
||||
if !g:pymode || &cp
|
||||
finish
|
||||
endif
|
||||
|
||||
" Pymode needs
|
||||
filetype plugin on
|
||||
|
||||
" OPTIONS: {{{
|
||||
|
||||
" Vim Python interpreter. Set to 'disable' for remove python features.
|
||||
call pymode#default('g:pymode_python', '')
|
||||
|
||||
" Disable pymode warnings
|
||||
call pymode#default('g:pymode_warning', 1)
|
||||
|
||||
" Additional python paths
|
||||
call pymode#default('g:pymode_paths', [])
|
||||
|
||||
" Python documentation support
|
||||
call pymode#default('g:pymode_doc', 1)
|
||||
call pymode#default('g:pymode_doc_bind', 'K')
|
||||
|
||||
" Enable/Disable pymode PEP8 indentation
|
||||
call pymode#default("g:pymode_indent", 1)
|
||||
|
||||
" Enable/disable pymode folding for pyfiles.
|
||||
call pymode#default("g:pymode_folding", 1)
|
||||
" Maximum file length to check for nested class/def statements
|
||||
call pymode#default("g:pymode_folding_nest_limit", 1000)
|
||||
" Change for folding customization (by example enable fold for 'if', 'for')
|
||||
call pymode#default("g:pymode_folding_regex", '^\s*\%(class\|def\|async\s\+def\) .\+\(:\s\+\w\)\@!')
|
||||
|
||||
" Enable/disable python motion operators
|
||||
call pymode#default("g:pymode_motion", 1)
|
||||
|
||||
" Auto remove unused whitespaces on save
|
||||
call pymode#default("g:pymode_trim_whitespaces", 1)
|
||||
|
||||
" Set recomended python options
|
||||
call pymode#default("g:pymode_options", 1)
|
||||
call pymode#default("g:pymode_options_max_line_length", 80)
|
||||
call pymode#default("g:pymode_options_colorcolumn", 1)
|
||||
|
||||
" Enable/disable vertical display of python documentation
|
||||
call pymode#default("g:pymode_doc_vertical", 0)
|
||||
|
||||
" Minimal height of pymode quickfix window
|
||||
call pymode#default('g:pymode_quickfix_maxheight', 6)
|
||||
|
||||
" Maximal height of pymode quickfix window
|
||||
call pymode#default('g:pymode_quickfix_minheight', 3)
|
||||
|
||||
" LOAD VIRTUALENV {{{
|
||||
"
|
||||
" Enable virtualenv support
|
||||
call pymode#default('g:pymode_virtualenv', 1)
|
||||
|
||||
" Get path to virtualenv (by default take from shell)
|
||||
call pymode#default('g:pymode_virtualenv_path', $VIRTUAL_ENV)
|
||||
|
||||
" Service variable (don't set it manually)
|
||||
call pymode#default('g:pymode_virtualenv_enabled', '')
|
||||
|
||||
" }}}
|
||||
|
||||
" RUN PYTHON {{{
|
||||
"
|
||||
" Enable code running support
|
||||
call pymode#default('g:pymode_run', 1)
|
||||
|
||||
" Key's map for run python code
|
||||
call pymode#default('g:pymode_run_bind', '<leader>r')
|
||||
|
||||
" }}}
|
||||
|
||||
" CHECK CODE {{{
|
||||
"
|
||||
" Code checking
|
||||
call pymode#default('g:pymode_lint', 1)
|
||||
|
||||
" Check code asynchronously
|
||||
call pymode#default('g:pymode_lint_async', 1)
|
||||
call pymode#default('g:pymode_lint_async_updatetime', 1000)
|
||||
|
||||
" Check code every save if file has been modified
|
||||
call pymode#default("g:pymode_lint_on_write", 1)
|
||||
|
||||
" Check code every save (every)
|
||||
call pymode#default("g:pymode_lint_unmodified", 0)
|
||||
|
||||
" Check code on fly
|
||||
call pymode#default("g:pymode_lint_on_fly", 0)
|
||||
|
||||
" Show message about error in command line
|
||||
call pymode#default("g:pymode_lint_message", 1)
|
||||
|
||||
" Choices are: pylint, pyflakes, pep8, mccabe
|
||||
call pymode#default("g:pymode_lint_checkers", ['pyflakes', 'pep8', 'mccabe'])
|
||||
|
||||
" Skip errors and warnings (e.g. E4,W)
|
||||
call pymode#default("g:pymode_lint_ignore", "")
|
||||
|
||||
" Select errors and warnings (e.g. E4,W)
|
||||
call pymode#default("g:pymode_lint_select", "")
|
||||
|
||||
" Auto open cwindow if any errors has been finded
|
||||
call pymode#default("g:pymode_lint_cwindow", 1)
|
||||
|
||||
" If not emply, errors will be sort by defined relevance
|
||||
" E.g. let g:pymode_lint_sort = ['E', 'C', 'I'] " Errors first 'E',
|
||||
" after them 'C' and ...
|
||||
call pymode#default("g:pymode_lint_sort", [])
|
||||
|
||||
" Place error signs
|
||||
call pymode#default("g:pymode_lint_signs", 1)
|
||||
|
||||
" Symbol's definitions
|
||||
call pymode#default("g:pymode_lint_todo_symbol", "WW")
|
||||
call pymode#default("g:pymode_lint_docs_symbol", "DD")
|
||||
call pymode#default("g:pymode_lint_comment_symbol", "CC")
|
||||
call pymode#default("g:pymode_lint_visual_symbol", "RR")
|
||||
call pymode#default("g:pymode_lint_error_symbol", "EE")
|
||||
call pymode#default("g:pymode_lint_info_symbol", "II")
|
||||
call pymode#default("g:pymode_lint_pyflakes_symbol", "FF")
|
||||
|
||||
" Code checkers options
|
||||
call pymode#default("g:pymode_lint_options_pep8",
|
||||
\ {'max_line_length': g:pymode_options_max_line_length})
|
||||
|
||||
call pymode#default("g:pymode_lint_options_pylint",
|
||||
\ {'max-line-length': g:pymode_options_max_line_length})
|
||||
|
||||
call pymode#default("g:pymode_lint_options_mccabe",
|
||||
\ {'complexity': 12})
|
||||
|
||||
call pymode#default("g:pymode_lint_options_pep257", {})
|
||||
call pymode#default("g:pymode_lint_options_pyflakes", { 'builtins': '_' })
|
||||
|
||||
|
||||
" }}}
|
||||
|
||||
" SET/UNSET BREAKPOINTS {{{
|
||||
"
|
||||
|
||||
" Create/remove breakpoints
|
||||
call pymode#default('g:pymode_breakpoint', 1)
|
||||
|
||||
" Key's map for add/remove breakpoint
|
||||
call pymode#default('g:pymode_breakpoint_bind', '<leader>b')
|
||||
|
||||
" Default pattern for making breakpoints. Leave this empty for auto search available debuggers (pdb, ipdb, ...)
|
||||
call pymode#default('g:pymode_breakpoint_cmd', '')
|
||||
|
||||
" }}}
|
||||
|
||||
" ROPE (refactoring, codeassist) {{{
|
||||
"
|
||||
" Rope support
|
||||
call pymode#default('g:pymode_rope', 1)
|
||||
|
||||
" System plugin variable
|
||||
call pymode#default('g:pymode_rope_current', '')
|
||||
|
||||
" Configurable rope project root
|
||||
call pymode#default('g:pymode_rope_project_root', '')
|
||||
|
||||
" Configurable rope project folder (always relative to project root)
|
||||
call pymode#default('g:pymode_rope_ropefolder', '.ropeproject')
|
||||
|
||||
" If project hasnt been finded in current working directory, look at parents directory
|
||||
call pymode#default('g:pymode_rope_lookup_project', 0)
|
||||
|
||||
" Enable Rope completion
|
||||
call pymode#default('g:pymode_rope_completion', 1)
|
||||
|
||||
" Complete keywords from not imported modules (could make completion slower)
|
||||
" Enable autoimport used modules
|
||||
call pymode#default('g:pymode_rope_autoimport', 0)
|
||||
|
||||
" Offer to import object after complete (if that not be imported before)
|
||||
call pymode#default('g:pymode_rope_autoimport_import_after_complete', 0)
|
||||
|
||||
" Autoimported modules
|
||||
call pymode#default('g:pymode_rope_autoimport_modules', ['os', 'shutil', 'datetime'])
|
||||
|
||||
" Bind keys to autoimport module for object under cursor
|
||||
call pymode#default('g:pymode_rope_autoimport_bind', '<C-c>ra')
|
||||
|
||||
" Automatic completion on dot
|
||||
call pymode#default('g:pymode_rope_complete_on_dot', 1)
|
||||
|
||||
" Bind keys for autocomplete (leave empty for disable)
|
||||
call pymode#default('g:pymode_rope_completion_bind', '<C-Space>')
|
||||
|
||||
" Bind keys for goto definition (leave empty for disable)
|
||||
call pymode#default('g:pymode_rope_goto_definition_bind', '<C-c>g')
|
||||
|
||||
" set command for open definition (e, new, vnew)
|
||||
call pymode#default('g:pymode_rope_goto_definition_cmd', 'new')
|
||||
|
||||
" Bind keys for show documentation (leave empty for disable)
|
||||
call pymode#default('g:pymode_rope_show_doc_bind', '<C-c>d')
|
||||
|
||||
" Bind keys for find occurencies (leave empty for disable)
|
||||
call pymode#default('g:pymode_rope_find_it_bind', '<C-c>f')
|
||||
|
||||
" Bind keys for organize imports (leave empty for disable)
|
||||
call pymode#default('g:pymode_rope_organize_imports_bind', '<C-c>ro')
|
||||
|
||||
" Bind keys for rename variable/method/class in the project (leave empty for disable)
|
||||
call pymode#default('g:pymode_rope_rename_bind', '<C-c>rr')
|
||||
|
||||
" Bind keys for rename module
|
||||
call pymode#default('g:pymode_rope_rename_module_bind', '<C-c>r1r')
|
||||
|
||||
" Bind keys for convert module to package
|
||||
call pymode#default('g:pymode_rope_module_to_package_bind', '<C-c>r1p')
|
||||
|
||||
" Creates a new function or method (depending on the context) from the selected lines
|
||||
call pymode#default('g:pymode_rope_extract_method_bind', '<C-c>rm')
|
||||
|
||||
" Creates a variable from the selected lines
|
||||
call pymode#default('g:pymode_rope_extract_variable_bind', '<C-c>rl')
|
||||
|
||||
" Inline refactoring
|
||||
call pymode#default('g:pymode_rope_inline_bind', '<C-c>ri')
|
||||
|
||||
" Move refactoring
|
||||
call pymode#default('g:pymode_rope_move_bind', '<C-c>rv')
|
||||
|
||||
" Generate function
|
||||
call pymode#default('g:pymode_rope_generate_function_bind', '<C-c>rnf')
|
||||
|
||||
" Generate class
|
||||
call pymode#default('g:pymode_rope_generate_class_bind', '<C-c>rnc')
|
||||
|
||||
" Generate package
|
||||
call pymode#default('g:pymode_rope_generate_package_bind', '<C-c>rnp')
|
||||
|
||||
" Change signature
|
||||
call pymode#default('g:pymode_rope_change_signature_bind', '<C-c>rs')
|
||||
|
||||
" Tries to find the places in which a function can be used and changes the
|
||||
" code to call it instead
|
||||
call pymode#default('g:pymode_rope_use_function_bind', '<C-c>ru')
|
||||
|
||||
" Regenerate project cache on every save
|
||||
call pymode#default('g:pymode_rope_regenerate_on_write', 1)
|
||||
|
||||
" }}}
|
||||
|
||||
" }}}
|
||||
|
||||
" Prepare to plugin loading
|
||||
if &compatible
|
||||
set nocompatible
|
||||
endif
|
||||
filetype plugin on
|
||||
|
||||
" Disable python-related functionality
|
||||
" let g:pymode_python = 'disable'
|
||||
" let g:pymode_python = 'python3'
|
||||
|
||||
" UltiSnips Fixes
|
||||
if !len(g:pymode_python)
|
||||
if exists('g:_uspy') && g:_uspy == ':py'
|
||||
let g:pymode_python = 'python'
|
||||
elseif exists('g:_uspy') && g:_uspy == ':py3'
|
||||
let g:pymode_python = 'python3'
|
||||
elseif has("python")
|
||||
let g:pymode_python = 'python'
|
||||
elseif has("python3")
|
||||
let g:pymode_python = 'python3'
|
||||
else
|
||||
let g:pymode_python = 'disable'
|
||||
endif
|
||||
endif
|
||||
|
||||
if g:pymode_python == 'python'
|
||||
|
||||
command! -nargs=1 PymodePython python <args>
|
||||
let g:UltiSnipsUsePythonVersion = 2
|
||||
|
||||
elseif g:pymode_python == 'python3'
|
||||
|
||||
command! -nargs=1 PymodePython python3 <args>
|
||||
let g:UltiSnipsUsePythonVersion = 3
|
||||
|
||||
else
|
||||
|
||||
let g:pymode_doc = 0
|
||||
let g:pymode_lint = 0
|
||||
let g:pymode_path = 0
|
||||
let g:pymode_rope = 0
|
||||
let g:pymode_run = 0
|
||||
let g:pymode_virtualenv = 0
|
||||
|
||||
command! -nargs=1 PymodePython echo <args>
|
||||
|
||||
endif
|
||||
|
||||
|
||||
command! PymodeVersion echomsg "Pymode version: " . g:pymode_version . " interpreter: " . g:pymode_python . " lint: " . g:pymode_lint . " rope: " . g:pymode_rope
|
||||
|
||||
augroup pymode
|
||||
8
vim-plugins/python-mode/pylama.ini
Normal file
8
vim-plugins/python-mode/pylama.ini
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[pylama]
|
||||
linters=pep8,pyflakes,pylint
|
||||
|
||||
[pylama:pymode/libs*]
|
||||
skip=1
|
||||
|
||||
[pylama:pylint]
|
||||
disable=E1120,E1130,E1103,W1401,F0001
|
||||
37
vim-plugins/python-mode/pymode/__init__.py
Normal file
37
vim-plugins/python-mode/pymode/__init__.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
""" Pymode support functions. """
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
import vim # noqa
|
||||
|
||||
|
||||
def auto():
|
||||
""" Fix PEP8 erorrs in current buffer. """
|
||||
from .autopep8 import fix_file
|
||||
|
||||
class Options(object):
|
||||
aggressive = 2
|
||||
diff = False
|
||||
experimental = True
|
||||
ignore = vim.eval('g:pymode_lint_ignore')
|
||||
in_place = True
|
||||
indent_size = int(vim.eval('&tabstop'))
|
||||
line_range = None
|
||||
max_line_length = int(vim.eval('g:pymode_options_max_line_length'))
|
||||
pep8_passes = 100
|
||||
recursive = False
|
||||
select = vim.eval('g:pymode_lint_select')
|
||||
verbose = 0
|
||||
|
||||
fix_file(vim.current.buffer.name, Options)
|
||||
|
||||
|
||||
def get_documentation():
|
||||
""" Search documentation and append to current buffer. """
|
||||
from ._compat import StringIO
|
||||
|
||||
sys.stdout, _ = StringIO(), sys.stdout
|
||||
help(vim.eval('a:word'))
|
||||
sys.stdout, out = _, sys.stdout.getvalue()
|
||||
vim.current.buffer.append(str(out).splitlines(), 0)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
vim-plugins/python-mode/pymode/__pycache__/lint.cpython-35.pyc
Normal file
BIN
vim-plugins/python-mode/pymode/__pycache__/lint.cpython-35.pyc
Normal file
Binary file not shown.
BIN
vim-plugins/python-mode/pymode/__pycache__/rope.cpython-35.pyc
Normal file
BIN
vim-plugins/python-mode/pymode/__pycache__/rope.cpython-35.pyc
Normal file
Binary file not shown.
BIN
vim-plugins/python-mode/pymode/__pycache__/run.cpython-35.pyc
Normal file
BIN
vim-plugins/python-mode/pymode/__pycache__/run.cpython-35.pyc
Normal file
Binary file not shown.
BIN
vim-plugins/python-mode/pymode/__pycache__/utils.cpython-35.pyc
Normal file
BIN
vim-plugins/python-mode/pymode/__pycache__/utils.cpython-35.pyc
Normal file
Binary file not shown.
Binary file not shown.
98
vim-plugins/python-mode/pymode/_compat.py
Normal file
98
vim-plugins/python-mode/pymode/_compat.py
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
""" Compatibility.
|
||||
|
||||
Some py2/py3 compatibility support based on a stripped down
|
||||
version of six so we don't have to depend on a specific version
|
||||
of it.
|
||||
|
||||
:copyright: (c) 2014 by Armin Ronacher.
|
||||
:license: BSD
|
||||
"""
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
_identity = lambda x: x
|
||||
|
||||
|
||||
if not PY2:
|
||||
text_type = str
|
||||
string_types = (str,)
|
||||
integer_types = (int, )
|
||||
|
||||
iterkeys = lambda d: iter(d.keys())
|
||||
itervalues = lambda d: iter(d.values())
|
||||
iteritems = lambda d: iter(d.items())
|
||||
|
||||
from io import StringIO
|
||||
from queue import Queue # noqa
|
||||
|
||||
def reraise(tp, value, tb=None):
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
|
||||
implements_to_string = _identity
|
||||
|
||||
else:
|
||||
text_type = unicode
|
||||
string_types = (str, unicode)
|
||||
integer_types = (int, long)
|
||||
|
||||
iterkeys = lambda d: d.iterkeys()
|
||||
itervalues = lambda d: d.itervalues()
|
||||
iteritems = lambda d: d.iteritems()
|
||||
|
||||
from cStringIO import StringIO
|
||||
from Queue import Queue
|
||||
|
||||
exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
|
||||
|
||||
def implements_to_string(cls):
|
||||
cls.__unicode__ = cls.__str__
|
||||
cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
|
||||
return cls
|
||||
|
||||
|
||||
def with_metaclass(meta, *bases):
|
||||
# This requires a bit of explanation: the basic idea is to make a
|
||||
# dummy metaclass for one level of class instantiation that replaces
|
||||
# itself with the actual metaclass. Because of internal type checks
|
||||
# we also need to make sure that we downgrade the custom metaclass
|
||||
# for one level to something closer to type (that's why __call__ and
|
||||
# __init__ comes back from type etc.).
|
||||
#
|
||||
# This has the advantage over six.with_metaclass in that it does not
|
||||
# introduce dummy classes into the final MRO.
|
||||
class metaclass(meta):
|
||||
__call__ = type.__call__
|
||||
__init__ = type.__init__
|
||||
def __new__(cls, name, this_bases, d):
|
||||
if this_bases is None:
|
||||
return type.__new__(cls, name, (), d)
|
||||
return meta(name, bases, d)
|
||||
return metaclass('temporary_class', None, {})
|
||||
|
||||
|
||||
# Certain versions of pypy have a bug where clearing the exception stack
|
||||
# breaks the __exit__ function in a very peculiar way. This is currently
|
||||
# true for pypy 2.2.1 for instance. The second level of exception blocks
|
||||
# is necessary because pypy seems to forget to check if an exception
|
||||
# happend until the next bytecode instruction?
|
||||
BROKEN_PYPY_CTXMGR_EXIT = False
|
||||
if hasattr(sys, 'pypy_version_info'):
|
||||
class _Mgr(object):
|
||||
def __enter__(self):
|
||||
return self
|
||||
def __exit__(self, *args):
|
||||
sys.exc_clear()
|
||||
try:
|
||||
try:
|
||||
with _Mgr():
|
||||
raise AssertionError()
|
||||
except:
|
||||
raise
|
||||
except TypeError:
|
||||
BROKEN_PYPY_CTXMGR_EXIT = True
|
||||
except AssertionError:
|
||||
pass
|
||||
|
||||
# pylama:skip=1
|
||||
6
vim-plugins/python-mode/pymode/async.py
Normal file
6
vim-plugins/python-mode/pymode/async.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
""" Python-mode async support. """
|
||||
|
||||
from ._compat import Queue
|
||||
|
||||
|
||||
RESULTS = Queue()
|
||||
3654
vim-plugins/python-mode/pymode/autopep8.py
Normal file
3654
vim-plugins/python-mode/pymode/autopep8.py
Normal file
File diff suppressed because it is too large
Load diff
249
vim-plugins/python-mode/pymode/environment.py
Normal file
249
vim-plugins/python-mode/pymode/environment.py
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
"""Define interfaces."""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import json
|
||||
import os.path
|
||||
import time
|
||||
import vim # noqa
|
||||
|
||||
from ._compat import PY2
|
||||
|
||||
|
||||
class VimPymodeEnviroment(object):
|
||||
|
||||
"""Vim User interface."""
|
||||
|
||||
prefix = '[Pymode]'
|
||||
|
||||
def __init__(self):
|
||||
"""Init VIM environment."""
|
||||
self.current = vim.current
|
||||
self.options = dict(encoding=vim.eval('&enc'))
|
||||
self.options['debug'] = self.var('g:pymode_debug', True)
|
||||
|
||||
@property
|
||||
def curdir(self):
|
||||
"""Return current working directory."""
|
||||
return self.var('getcwd()')
|
||||
|
||||
@property
|
||||
def curbuf(self):
|
||||
"""Return current buffer."""
|
||||
return self.current.buffer
|
||||
|
||||
@property
|
||||
def cursor(self):
|
||||
"""Return current window position.
|
||||
|
||||
:return tuple: (row, col)
|
||||
|
||||
"""
|
||||
return self.current.window.cursor
|
||||
|
||||
@property
|
||||
def source(self):
|
||||
"""Return source of current buffer."""
|
||||
return "\n".join(self.lines)
|
||||
|
||||
@property
|
||||
def lines(self):
|
||||
"""Iterate by lines in current file.
|
||||
|
||||
:return list:
|
||||
|
||||
"""
|
||||
if not PY2:
|
||||
return self.curbuf
|
||||
|
||||
return [l.decode(self.options.get('encoding')) for l in self.curbuf]
|
||||
|
||||
@staticmethod
|
||||
def var(name, to_bool=False, silence=False):
|
||||
"""Get vim variable.
|
||||
|
||||
:return vimobj:
|
||||
|
||||
"""
|
||||
try:
|
||||
value = vim.eval(name)
|
||||
except vim.error:
|
||||
if silence:
|
||||
return None
|
||||
raise
|
||||
|
||||
if to_bool:
|
||||
try:
|
||||
value = bool(int(value))
|
||||
except ValueError:
|
||||
value = value
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def message(msg, history=False):
|
||||
"""Show message to user.
|
||||
|
||||
:return: :None
|
||||
|
||||
"""
|
||||
if history:
|
||||
return vim.command('echom "%s"' % str(msg))
|
||||
|
||||
return vim.command('call pymode#wide_message("%s")' % str(msg))
|
||||
|
||||
def user_input(self, msg, default=''):
|
||||
"""Return user input or default.
|
||||
|
||||
:return str:
|
||||
|
||||
"""
|
||||
msg = '%s %s ' % (self.prefix, msg)
|
||||
|
||||
if default != '':
|
||||
msg += '[%s] ' % default
|
||||
|
||||
try:
|
||||
vim.command('echohl Debug')
|
||||
input_str = vim.eval('input("%s> ")' % msg)
|
||||
vim.command('echohl none')
|
||||
except KeyboardInterrupt:
|
||||
input_str = ''
|
||||
|
||||
return input_str or default
|
||||
|
||||
def user_confirm(self, msg, yes=False):
|
||||
"""Get user confirmation.
|
||||
|
||||
:return bool:
|
||||
|
||||
"""
|
||||
default = 'yes' if yes else 'no'
|
||||
action = self.user_input(msg, default)
|
||||
return action and 'yes'.startswith(action)
|
||||
|
||||
def user_input_choices(self, msg, *options):
|
||||
"""Get one of many options.
|
||||
|
||||
:return str: A choosen option
|
||||
|
||||
"""
|
||||
choices = ['%s %s' % (self.prefix, msg)]
|
||||
choices += [
|
||||
"%s. %s" % (num, opt) for num, opt in enumerate(options, 1)]
|
||||
try:
|
||||
input_str = int(
|
||||
vim.eval('inputlist(%s)' % self.prepare_value(choices)))
|
||||
except (KeyboardInterrupt, ValueError):
|
||||
input_str = 0
|
||||
|
||||
if not input_str:
|
||||
self.message('Cancelled!')
|
||||
return False
|
||||
|
||||
try:
|
||||
return options[input_str - 1]
|
||||
except (IndexError, ValueError):
|
||||
self.error('Invalid option: %s' % input_str)
|
||||
return self.user_input_choices(msg, *options)
|
||||
|
||||
@staticmethod
|
||||
def error(msg):
|
||||
"""Show error to user."""
|
||||
vim.command('call pymode#error("%s")' % str(msg))
|
||||
|
||||
def debug(self, msg, *args):
|
||||
"""Print debug information."""
|
||||
if self.options.get('debug'):
|
||||
print("%s %s [%s]" % (
|
||||
int(time.time()), msg, ', '.join([str(a) for a in args])))
|
||||
|
||||
def stop(self, value=None):
|
||||
"""Break Vim function."""
|
||||
cmd = 'return'
|
||||
if value is not None:
|
||||
cmd += ' ' + self.prepare_value(value)
|
||||
vim.command(cmd)
|
||||
|
||||
def catch_exceptions(self, func):
|
||||
"""Decorator. Make execution more silence.
|
||||
|
||||
:return func:
|
||||
|
||||
"""
|
||||
def _wrapper(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except (Exception, vim.error) as e: # noqa
|
||||
if self.options.get('debug'):
|
||||
raise
|
||||
self.error(e)
|
||||
return None
|
||||
return _wrapper
|
||||
|
||||
def run(self, name, *args):
|
||||
"""Run vim function."""
|
||||
vim.command('call %s(%s)' % (name, ", ".join([
|
||||
self.prepare_value(a) for a in args
|
||||
])))
|
||||
|
||||
def let(self, name, value):
|
||||
"""Set variable."""
|
||||
cmd = 'let %s = %s' % (name, self.prepare_value(value))
|
||||
self.debug(cmd)
|
||||
vim.command(cmd)
|
||||
|
||||
def prepare_value(self, value, dumps=True):
|
||||
"""Decode bstr to vim encoding.
|
||||
|
||||
:return unicode string:
|
||||
|
||||
"""
|
||||
if dumps:
|
||||
value = json.dumps(value)
|
||||
|
||||
if PY2:
|
||||
value = value.decode('utf-8').encode(self.options.get('encoding'))
|
||||
|
||||
return value
|
||||
|
||||
def get_offset_params(self, cursor=None, base=""):
|
||||
"""Calculate current offset.
|
||||
|
||||
:return tuple: (source, offset)
|
||||
|
||||
"""
|
||||
row, col = cursor or env.cursor
|
||||
source = ""
|
||||
offset = 0
|
||||
for i, line in enumerate(self.lines, 1):
|
||||
if i == row:
|
||||
source += line[:col] + base
|
||||
offset = len(source)
|
||||
source += line[col:]
|
||||
else:
|
||||
source += line
|
||||
source += '\n'
|
||||
env.debug('Get offset', base or None, row, col, offset)
|
||||
return source, offset
|
||||
|
||||
@staticmethod
|
||||
def goto_line(line):
|
||||
"""Go to line."""
|
||||
vim.command('normal %sggzz' % line)
|
||||
|
||||
def goto_file(self, path, cmd='e', force=False):
|
||||
"""Open file by path."""
|
||||
if force or os.path.abspath(path) != self.curbuf.name:
|
||||
self.debug('read', path)
|
||||
if ' ' in path and os.name == 'posix':
|
||||
path = path.replace(' ', '\\ ')
|
||||
vim.command("%s %s" % (cmd, path))
|
||||
|
||||
@staticmethod
|
||||
def goto_buffer(bufnr):
|
||||
"""Open buffer."""
|
||||
if str(bufnr) != '-1':
|
||||
vim.command('buffer %s' % bufnr)
|
||||
|
||||
|
||||
env = VimPymodeEnviroment()
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
16
vim-plugins/python-mode/pymode/libs/_markerlib/__init__.py
Normal file
16
vim-plugins/python-mode/pymode/libs/_markerlib/__init__.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
try:
|
||||
import ast
|
||||
from _markerlib.markers import default_environment, compile, interpret
|
||||
except ImportError:
|
||||
if 'ast' in globals():
|
||||
raise
|
||||
def default_environment():
|
||||
return {}
|
||||
def compile(marker):
|
||||
def marker_fn(environment=None, override=None):
|
||||
# 'empty markers are True' heuristic won't install extra deps.
|
||||
return not marker.strip()
|
||||
marker_fn.__doc__ = marker
|
||||
return marker_fn
|
||||
def interpret(marker, environment=None, override=None):
|
||||
return compile(marker)()
|
||||
119
vim-plugins/python-mode/pymode/libs/_markerlib/markers.py
Normal file
119
vim-plugins/python-mode/pymode/libs/_markerlib/markers.py
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Interpret PEP 345 environment markers.
|
||||
|
||||
EXPR [in|==|!=|not in] EXPR [or|and] ...
|
||||
|
||||
where EXPR belongs to any of those:
|
||||
|
||||
python_version = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||
python_full_version = sys.version.split()[0]
|
||||
os.name = os.name
|
||||
sys.platform = sys.platform
|
||||
platform.version = platform.version()
|
||||
platform.machine = platform.machine()
|
||||
platform.python_implementation = platform.python_implementation()
|
||||
a free string, like '2.6', or 'win32'
|
||||
"""
|
||||
|
||||
__all__ = ['default_environment', 'compile', 'interpret']
|
||||
|
||||
import ast
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import weakref
|
||||
|
||||
_builtin_compile = compile
|
||||
|
||||
try:
|
||||
from platform import python_implementation
|
||||
except ImportError:
|
||||
if os.name == "java":
|
||||
# Jython 2.5 has ast module, but not platform.python_implementation() function.
|
||||
def python_implementation():
|
||||
return "Jython"
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
# restricted set of variables
|
||||
_VARS = {'sys.platform': sys.platform,
|
||||
'python_version': '%s.%s' % sys.version_info[:2],
|
||||
# FIXME parsing sys.platform is not reliable, but there is no other
|
||||
# way to get e.g. 2.7.2+, and the PEP is defined with sys.version
|
||||
'python_full_version': sys.version.split(' ', 1)[0],
|
||||
'os.name': os.name,
|
||||
'platform.version': platform.version(),
|
||||
'platform.machine': platform.machine(),
|
||||
'platform.python_implementation': python_implementation(),
|
||||
'extra': None # wheel extension
|
||||
}
|
||||
|
||||
for var in list(_VARS.keys()):
|
||||
if '.' in var:
|
||||
_VARS[var.replace('.', '_')] = _VARS[var]
|
||||
|
||||
def default_environment():
|
||||
"""Return copy of default PEP 385 globals dictionary."""
|
||||
return dict(_VARS)
|
||||
|
||||
class ASTWhitelist(ast.NodeTransformer):
|
||||
def __init__(self, statement):
|
||||
self.statement = statement # for error messages
|
||||
|
||||
ALLOWED = (ast.Compare, ast.BoolOp, ast.Attribute, ast.Name, ast.Load, ast.Str)
|
||||
# Bool operations
|
||||
ALLOWED += (ast.And, ast.Or)
|
||||
# Comparison operations
|
||||
ALLOWED += (ast.Eq, ast.Gt, ast.GtE, ast.In, ast.Is, ast.IsNot, ast.Lt, ast.LtE, ast.NotEq, ast.NotIn)
|
||||
|
||||
def visit(self, node):
|
||||
"""Ensure statement only contains allowed nodes."""
|
||||
if not isinstance(node, self.ALLOWED):
|
||||
raise SyntaxError('Not allowed in environment markers.\n%s\n%s' %
|
||||
(self.statement,
|
||||
(' ' * node.col_offset) + '^'))
|
||||
return ast.NodeTransformer.visit(self, node)
|
||||
|
||||
def visit_Attribute(self, node):
|
||||
"""Flatten one level of attribute access."""
|
||||
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def parse_marker(marker):
|
||||
tree = ast.parse(marker, mode='eval')
|
||||
new_tree = ASTWhitelist(marker).generic_visit(tree)
|
||||
return new_tree
|
||||
|
||||
def compile_marker(parsed_marker):
|
||||
return _builtin_compile(parsed_marker, '<environment marker>', 'eval',
|
||||
dont_inherit=True)
|
||||
|
||||
_cache = weakref.WeakValueDictionary()
|
||||
|
||||
def compile(marker):
|
||||
"""Return compiled marker as a function accepting an environment dict."""
|
||||
try:
|
||||
return _cache[marker]
|
||||
except KeyError:
|
||||
pass
|
||||
if not marker.strip():
|
||||
def marker_fn(environment=None, override=None):
|
||||
""""""
|
||||
return True
|
||||
else:
|
||||
compiled_marker = compile_marker(parse_marker(marker))
|
||||
def marker_fn(environment=None, override=None):
|
||||
"""override updates environment"""
|
||||
if override is None:
|
||||
override = {}
|
||||
if environment is None:
|
||||
environment = default_environment()
|
||||
environment.update(override)
|
||||
return eval(compiled_marker, environment)
|
||||
marker_fn.__doc__ = marker
|
||||
_cache[marker] = marker_fn
|
||||
return _cache[marker]
|
||||
|
||||
def interpret(marker, environment=None):
|
||||
return compile(marker)(environment)
|
||||
131
vim-plugins/python-mode/pymode/libs/astroid/__init__.py
Normal file
131
vim-plugins/python-mode/pymode/libs/astroid/__init__.py
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. 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 astroid ;) 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 astroid 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 astroid trees
|
||||
"""
|
||||
__doctype__ = "restructuredtext en"
|
||||
|
||||
import sys
|
||||
import re
|
||||
from operator import attrgetter
|
||||
|
||||
# WARNING: internal imports order matters !
|
||||
|
||||
# make all exception classes accessible from astroid package
|
||||
from astroid.exceptions import *
|
||||
|
||||
# make all node classes accessible from astroid package
|
||||
from astroid.nodes import *
|
||||
|
||||
# trigger extra monkey-patching
|
||||
from astroid import inference
|
||||
|
||||
# more stuff available
|
||||
from astroid import raw_building
|
||||
from astroid.bases import YES, Instance, BoundMethod, UnboundMethod
|
||||
from astroid.node_classes import are_exclusive, unpack_infer
|
||||
from astroid.scoped_nodes import builtin_lookup
|
||||
|
||||
# make a manager instance (borg) as well as Project and Package classes
|
||||
# accessible from astroid package
|
||||
from astroid.manager import AstroidManager, Project
|
||||
MANAGER = AstroidManager()
|
||||
del AstroidManager
|
||||
|
||||
# transform utilities (filters and decorator)
|
||||
|
||||
class AsStringRegexpPredicate(object):
|
||||
"""Class to be used as predicate that may be given to `register_transform`
|
||||
|
||||
First argument is a regular expression that will be searched against the `as_string`
|
||||
representation of the node onto which it's applied.
|
||||
|
||||
If specified, the second argument is an `attrgetter` expression that will be
|
||||
applied on the node first to get the actual node on which `as_string` should
|
||||
be called.
|
||||
|
||||
WARNING: This can be fairly slow, as it has to convert every AST node back
|
||||
to Python code; you should consider examining the AST directly instead.
|
||||
"""
|
||||
def __init__(self, regexp, expression=None):
|
||||
self.regexp = re.compile(regexp)
|
||||
self.expression = expression
|
||||
|
||||
def __call__(self, node):
|
||||
if self.expression is not None:
|
||||
node = attrgetter(self.expression)(node)
|
||||
return self.regexp.search(node.as_string())
|
||||
|
||||
def inference_tip(infer_function):
|
||||
"""Given an instance specific inference function, return a function to be
|
||||
given to MANAGER.register_transform to set this inference function.
|
||||
|
||||
Typical usage
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
MANAGER.register_transform(CallFunc, inference_tip(infer_named_tuple),
|
||||
predicate)
|
||||
"""
|
||||
def transform(node, infer_function=infer_function):
|
||||
node._explicit_inference = infer_function
|
||||
return node
|
||||
return transform
|
||||
|
||||
|
||||
def register_module_extender(manager, module_name, get_extension_mod):
|
||||
def transform(node):
|
||||
extension_module = get_extension_mod()
|
||||
for name, obj in extension_module.locals.items():
|
||||
node.locals[name] = obj
|
||||
|
||||
manager.register_transform(Module, transform, lambda n: n.name == module_name)
|
||||
|
||||
|
||||
# load brain plugins
|
||||
from os import listdir
|
||||
from os.path import join, dirname
|
||||
BRAIN_MODULES_DIR = join(dirname(__file__), 'brain')
|
||||
if BRAIN_MODULES_DIR not in sys.path:
|
||||
# add it to the end of the list so user path take precedence
|
||||
sys.path.append(BRAIN_MODULES_DIR)
|
||||
# load modules in this directory
|
||||
for module in listdir(BRAIN_MODULES_DIR):
|
||||
if module.endswith('.py'):
|
||||
__import__(module[:-3])
|
||||
42
vim-plugins/python-mode/pymode/libs/astroid/__pkginfo__.py
Normal file
42
vim-plugins/python-mode/pymode/libs/astroid/__pkginfo__.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""astroid packaging information"""
|
||||
distname = 'astroid'
|
||||
|
||||
modname = 'astroid'
|
||||
|
||||
numversion = (1, 3, 8)
|
||||
version = '.'.join([str(num) for num in numversion])
|
||||
|
||||
install_requires = ['logilab-common>=0.63.0', 'six']
|
||||
|
||||
license = 'LGPL'
|
||||
|
||||
author = 'Logilab'
|
||||
author_email = 'pylint-dev@lists.logilab.org'
|
||||
mailinglist = "mailto://%s" % author_email
|
||||
web = 'http://bitbucket.org/logilab/astroid'
|
||||
|
||||
description = "A abstract syntax tree for Python with inference support."
|
||||
|
||||
classifiers = ["Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 3",
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
499
vim-plugins/python-mode/pymode/libs/astroid/as_string.py
Normal file
499
vim-plugins/python-mode/pymode/libs/astroid/as_string.py
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""This module renders Astroid nodes as string:
|
||||
|
||||
* :func:`to_code` function return equivalent (hopefuly valid) python string
|
||||
|
||||
* :func:`dump` function return an internal representation of nodes found
|
||||
in the tree, useful for debugging or understanding the tree structure
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
INDENT = ' ' # 4 spaces ; keep indentation variable
|
||||
|
||||
|
||||
def dump(node, ids=False):
|
||||
"""print a nice astroid tree representation.
|
||||
|
||||
:param ids: if true, we also print the ids (usefull for debugging)
|
||||
"""
|
||||
result = []
|
||||
_repr_tree(node, result, ids=ids)
|
||||
return "\n".join(result)
|
||||
|
||||
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, '_astroid_fields'): # not a astroid 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._astroid_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)
|
||||
|
||||
|
||||
class AsStringVisitor(object):
|
||||
"""Visitor to render an Astroid node as a valid python code 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 astroid.Function node as string"""
|
||||
return node.format_args()
|
||||
|
||||
def visit_assattr(self, node):
|
||||
"""return an astroid.AssAttr node as string"""
|
||||
return self.visit_getattr(node)
|
||||
|
||||
def visit_assert(self, node):
|
||||
"""return an astroid.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 astroid.AssName node as string"""
|
||||
return node.name
|
||||
|
||||
def visit_assign(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.Backquote node as string"""
|
||||
return '`%s`' % node.value.accept(self)
|
||||
|
||||
def visit_binop(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.Break node as string"""
|
||||
return 'break'
|
||||
|
||||
def visit_callfunc(self, node):
|
||||
"""return an astroid.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 astroid.Class node as string"""
|
||||
decorate = node.decorators and node.decorators.accept(self) or ''
|
||||
bases = ', '.join([n.accept(self) for n in node.bases])
|
||||
if sys.version_info[0] == 2:
|
||||
bases = bases and '(%s)' % bases or ''
|
||||
else:
|
||||
metaclass = node.metaclass()
|
||||
if metaclass and not node.has_metaclass_hack():
|
||||
if bases:
|
||||
bases = '(%s, metaclass=%s)' % (bases, metaclass.name)
|
||||
else:
|
||||
bases = '(metaclass=%s)' % metaclass.name
|
||||
else:
|
||||
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 astroid.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 astroid.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 astroid.Const node as string"""
|
||||
return repr(node.value)
|
||||
|
||||
def visit_continue(self, node):
|
||||
"""return an astroid.Continue node as string"""
|
||||
return 'continue'
|
||||
|
||||
def visit_delete(self, node): # XXX check if correct
|
||||
"""return an astroid.Delete node as string"""
|
||||
return 'del %s' % ', '.join([child.accept(self)
|
||||
for child in node.targets])
|
||||
|
||||
def visit_delattr(self, node):
|
||||
"""return an astroid.DelAttr node as string"""
|
||||
return self.visit_getattr(node)
|
||||
|
||||
def visit_delname(self, node):
|
||||
"""return an astroid.DelName node as string"""
|
||||
return node.name
|
||||
|
||||
def visit_decorators(self, node):
|
||||
"""return an astroid.Decorators node as string"""
|
||||
return '@%s\n' % '\n@'.join([item.accept(self) for item in node.nodes])
|
||||
|
||||
def visit_dict(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.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 astroid.Ellipsis node as string"""
|
||||
return '...'
|
||||
|
||||
def visit_empty(self, node):
|
||||
"""return an Empty node as string"""
|
||||
return ''
|
||||
|
||||
def visit_exec(self, node):
|
||||
"""return an astroid.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 astroid.ExtSlice node as string"""
|
||||
return ','.join([dim.accept(self) for dim in node.dims])
|
||||
|
||||
def visit_for(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.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 astroid.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 astroid.Getattr node as string"""
|
||||
return '%s.%s' % (node.expr.accept(self), node.attrname)
|
||||
|
||||
def visit_global(self, node):
|
||||
"""return an astroid.Global node as string"""
|
||||
return 'global %s' % ', '.join(node.names)
|
||||
|
||||
def visit_if(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.Import node as string"""
|
||||
return 'import %s' % _import_string(node.names)
|
||||
|
||||
def visit_keyword(self, node):
|
||||
"""return an astroid.Keyword node as string"""
|
||||
return '%s=%s' % (node.arg, node.value.accept(self))
|
||||
|
||||
def visit_lambda(self, node):
|
||||
"""return an astroid.Lambda node as string"""
|
||||
return 'lambda %s: %s' % (node.args.accept(self),
|
||||
node.body.accept(self))
|
||||
|
||||
def visit_list(self, node):
|
||||
"""return an astroid.List node as string"""
|
||||
return '[%s]' % ', '.join([child.accept(self) for child in node.elts])
|
||||
|
||||
def visit_listcomp(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.Name node as string"""
|
||||
return node.name
|
||||
|
||||
def visit_pass(self, node):
|
||||
"""return an astroid.Pass node as string"""
|
||||
return 'pass'
|
||||
|
||||
def visit_print(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.Return node as string"""
|
||||
if node.value:
|
||||
return 'return %s' % node.value.accept(self)
|
||||
else:
|
||||
return 'return'
|
||||
|
||||
def visit_index(self, node):
|
||||
"""return a astroid.Index node as string"""
|
||||
return node.value.accept(self)
|
||||
|
||||
def visit_set(self, node):
|
||||
"""return an astroid.Set node as string"""
|
||||
return '{%s}' % ', '.join([child.accept(self) for child in node.elts])
|
||||
|
||||
def visit_setcomp(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.Subscript node as string"""
|
||||
return '%s[%s]' % (node.value.accept(self), node.slice.accept(self))
|
||||
|
||||
def visit_tryexcept(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.Tuple node as string"""
|
||||
if len(node.elts) == 1:
|
||||
return '(%s, )' % node.elts[0].accept(self)
|
||||
return '(%s)' % ', '.join([child.accept(self) for child in node.elts])
|
||||
|
||||
def visit_unaryop(self, node):
|
||||
"""return an astroid.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 astroid.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 astroid.With node as string"""
|
||||
items = ', '.join(('(%s)' % expr.accept(self)) +
|
||||
(vars and ' as (%s)' % (vars.accept(self)) or '')
|
||||
for expr, vars in node.items)
|
||||
return 'with %s:\n%s' % (items, self._stmt_list(node.body))
|
||||
|
||||
def visit_yield(self, node):
|
||||
"""yield an ast.Yield node as string"""
|
||||
yi_val = node.value and (" " + node.value.accept(self)) or ""
|
||||
expr = 'yield' + yi_val
|
||||
if node.parent.is_statement:
|
||||
return expr
|
||||
else:
|
||||
return "(%s)" % (expr,)
|
||||
|
||||
|
||||
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 astroid.Nonlocal node as string"""
|
||||
return 'nonlocal %s' % ', '.join(node.names)
|
||||
|
||||
def visit_raise(self, node):
|
||||
"""return an astroid.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)
|
||||
|
||||
def visit_yieldfrom(self, node):
|
||||
""" Return an astroid.YieldFrom node as string. """
|
||||
yi_val = node.value and (" " + node.value.accept(self)) or ""
|
||||
expr = 'yield from' + yi_val
|
||||
if node.parent.is_statement:
|
||||
return expr
|
||||
else:
|
||||
return "(%s)" % (expr,)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
AsStringVisitor = AsStringVisitor3k
|
||||
|
||||
# this visitor is stateless, thus it can be reused
|
||||
to_code = AsStringVisitor()
|
||||
|
||||
86
vim-plugins/python-mode/pymode/libs/astroid/astpeephole.py
Normal file
86
vim-plugins/python-mode/pymode/libs/astroid/astpeephole.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
||||
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
||||
#
|
||||
# This file is part of astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""Small AST optimizations."""
|
||||
|
||||
import _ast
|
||||
|
||||
from astroid import nodes
|
||||
|
||||
|
||||
__all__ = ('ASTPeepholeOptimizer', )
|
||||
|
||||
|
||||
try:
|
||||
_TYPES = (_ast.Str, _ast.Bytes)
|
||||
except AttributeError:
|
||||
_TYPES = (_ast.Str, )
|
||||
|
||||
|
||||
class ASTPeepholeOptimizer(object):
|
||||
"""Class for applying small optimizations to generate new AST."""
|
||||
|
||||
def optimize_binop(self, node):
|
||||
"""Optimize BinOps with string Const nodes on the lhs.
|
||||
|
||||
This fixes an infinite recursion crash, where multiple
|
||||
strings are joined using the addition operator. With a
|
||||
sufficient number of such strings, astroid will fail
|
||||
with a maximum recursion limit exceeded. The
|
||||
function will return a Const node with all the strings
|
||||
already joined.
|
||||
Return ``None`` if no AST node can be obtained
|
||||
through optimization.
|
||||
"""
|
||||
ast_nodes = []
|
||||
current = node
|
||||
while isinstance(current, _ast.BinOp):
|
||||
# lhs must be a BinOp with the addition operand.
|
||||
if not isinstance(current.left, _ast.BinOp):
|
||||
return
|
||||
if (not isinstance(current.left.op, _ast.Add)
|
||||
or not isinstance(current.op, _ast.Add)):
|
||||
return
|
||||
|
||||
# rhs must a str / bytes.
|
||||
if not isinstance(current.right, _TYPES):
|
||||
return
|
||||
|
||||
ast_nodes.append(current.right.s)
|
||||
current = current.left
|
||||
|
||||
if (isinstance(current, _ast.BinOp)
|
||||
and isinstance(current.left, _TYPES)
|
||||
and isinstance(current.right, _TYPES)):
|
||||
# Stop early if we are at the last BinOp in
|
||||
# the operation
|
||||
ast_nodes.append(current.right.s)
|
||||
ast_nodes.append(current.left.s)
|
||||
break
|
||||
|
||||
if not ast_nodes:
|
||||
return
|
||||
|
||||
# If we have inconsistent types, bail out.
|
||||
known = type(ast_nodes[0])
|
||||
if any(type(element) is not known
|
||||
for element in ast_nodes[1:]):
|
||||
return
|
||||
|
||||
value = known().join(reversed(ast_nodes))
|
||||
newnode = nodes.Const(value)
|
||||
return newnode
|
||||
652
vim-plugins/python-mode/pymode/libs/astroid/bases.py
Normal file
652
vim-plugins/python-mode/pymode/libs/astroid/bases.py
Normal file
|
|
@ -0,0 +1,652 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. 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"
|
||||
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
|
||||
from logilab.common.decorators import cachedproperty
|
||||
|
||||
from astroid.exceptions import (InferenceError, AstroidError, NotFoundError,
|
||||
UnresolvableName, UseInferenceDefault)
|
||||
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
BUILTINS = 'builtins'
|
||||
else:
|
||||
BUILTINS = '__builtin__'
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
"""a simple proxy object"""
|
||||
|
||||
_proxied = None # proxied object may be set by class or by instance
|
||||
|
||||
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', 'infered')
|
||||
|
||||
def __init__(self, path=None, infered=None):
|
||||
self.path = path or set()
|
||||
self.lookupname = None
|
||||
self.callcontext = None
|
||||
self.boundnode = None
|
||||
self.infered = infered or {}
|
||||
|
||||
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, infered=self.infered)
|
||||
clone.callcontext = self.callcontext
|
||||
clone.boundnode = self.boundnode
|
||||
return clone
|
||||
|
||||
def cache_generator(self, key, generator):
|
||||
results = []
|
||||
for result in generator:
|
||||
results.append(result)
|
||||
yield result
|
||||
|
||||
self.infered[key] = tuple(results)
|
||||
return
|
||||
|
||||
@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"""
|
||||
if not context:
|
||||
context = InferenceContext()
|
||||
try:
|
||||
# avoid recursively inferring the same attr on the same class
|
||||
|
||||
context.push((self._proxied, name))
|
||||
# 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 + '.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):
|
||||
if node is YES:
|
||||
continue
|
||||
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):
|
||||
infer = caller.args[0].infer() if caller.args else []
|
||||
return ((x is YES and x or Instance(x)) for x in 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.
|
||||
|
||||
Proxied class is set once for all in raw_building.
|
||||
"""
|
||||
def callable(self):
|
||||
return False
|
||||
|
||||
def pytype(self):
|
||||
return '%s.generator' % BUILTINS
|
||||
|
||||
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 Astroid 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:
|
||||
_astroid_fields = ()
|
||||
# instance specific inference function infer(node, context)
|
||||
_explicit_inference = None
|
||||
|
||||
def infer(self, context=None, **kwargs):
|
||||
"""main interface to the interface system, return a generator on infered
|
||||
values.
|
||||
|
||||
If the instance has some explicit inference function set, it will be
|
||||
called instead of the default interface.
|
||||
"""
|
||||
if self._explicit_inference is not None:
|
||||
# explicit_inference is not bound, give it self explicitly
|
||||
try:
|
||||
return self._explicit_inference(self, context, **kwargs)
|
||||
except UseInferenceDefault:
|
||||
pass
|
||||
|
||||
if not context:
|
||||
return self._infer(context, **kwargs)
|
||||
|
||||
key = (self, context.lookupname,
|
||||
context.callcontext, context.boundnode)
|
||||
if key in context.infered:
|
||||
return iter(context.infered[key])
|
||||
|
||||
return context.cache_generator(key, self._infer(context, **kwargs))
|
||||
|
||||
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 0x%x>' % (self.__class__.__name__,
|
||||
self._repr_name(),
|
||||
self.fromlineno,
|
||||
self.root().name,
|
||||
id(self))
|
||||
|
||||
|
||||
def accept(self, visitor):
|
||||
func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
|
||||
return func(self)
|
||||
|
||||
def get_children(self):
|
||||
for field in self._astroid_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._astroid_fields[::-1]:
|
||||
attr = getattr(self, field)
|
||||
if not attr: # None or empty listy / tuple
|
||||
continue
|
||||
if attr.__class__ in (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._astroid_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 find %s in %s\'s children'
|
||||
raise AstroidError(msg % (repr(child), repr(self)))
|
||||
|
||||
def locate_child(self, child):
|
||||
"""return a 2-uple (child attribute name, sequence or node)"""
|
||||
for field in self._astroid_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 find %s in %s\'s children'
|
||||
raise AstroidError(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]
|
||||
|
||||
# these are lazy because they're relatively expensive to compute for every
|
||||
# single node, and they rarely get looked at
|
||||
|
||||
@cachedproperty
|
||||
def fromlineno(self):
|
||||
if self.lineno is None:
|
||||
return self._fixed_source_line()
|
||||
else:
|
||||
return self.lineno
|
||||
|
||||
@cachedproperty
|
||||
def tolineno(self):
|
||||
if not self._astroid_fields:
|
||||
# can't have children
|
||||
lastchild = None
|
||||
else:
|
||||
lastchild = self.last_child()
|
||||
if lastchild is None:
|
||||
return self.fromlineno
|
||||
else:
|
||||
return lastchild.tolineno
|
||||
|
||||
# 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 = next(_node.get_children())
|
||||
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):
|
||||
from astroid.as_string import to_code
|
||||
return to_code(self)
|
||||
|
||||
def repr_tree(self, ids=False):
|
||||
from astroid.as_string import dump
|
||||
return dump(self)
|
||||
|
||||
|
||||
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]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,245 @@
|
|||
"""Astroid hooks for various builtins."""
|
||||
|
||||
import sys
|
||||
from functools import partial
|
||||
from textwrap import dedent
|
||||
|
||||
import six
|
||||
from astroid import (MANAGER, UseInferenceDefault,
|
||||
inference_tip, YES, InferenceError, UnresolvableName)
|
||||
from astroid import nodes
|
||||
from astroid.builder import AstroidBuilder
|
||||
|
||||
|
||||
def _extend_str(class_node, rvalue):
|
||||
"""function to extend builtin str/unicode class"""
|
||||
# TODO(cpopa): this approach will make astroid to believe
|
||||
# that some arguments can be passed by keyword, but
|
||||
# unfortunately, strings and bytes don't accept keyword arguments.
|
||||
code = dedent('''
|
||||
class whatever(object):
|
||||
def join(self, iterable):
|
||||
return {rvalue}
|
||||
def replace(self, old, new, count=None):
|
||||
return {rvalue}
|
||||
def format(self, *args, **kwargs):
|
||||
return {rvalue}
|
||||
def encode(self, encoding='ascii', errors=None):
|
||||
return ''
|
||||
def decode(self, encoding='ascii', errors=None):
|
||||
return u''
|
||||
def capitalize(self):
|
||||
return {rvalue}
|
||||
def title(self):
|
||||
return {rvalue}
|
||||
def lower(self):
|
||||
return {rvalue}
|
||||
def upper(self):
|
||||
return {rvalue}
|
||||
def swapcase(self):
|
||||
return {rvalue}
|
||||
def index(self, sub, start=None, end=None):
|
||||
return 0
|
||||
def find(self, sub, start=None, end=None):
|
||||
return 0
|
||||
def count(self, sub, start=None, end=None):
|
||||
return 0
|
||||
def strip(self, chars=None):
|
||||
return {rvalue}
|
||||
def lstrip(self, chars=None):
|
||||
return {rvalue}
|
||||
def rstrip(self, chars=None):
|
||||
return {rvalue}
|
||||
def rjust(self, width, fillchar=None):
|
||||
return {rvalue}
|
||||
def center(self, width, fillchar=None):
|
||||
return {rvalue}
|
||||
def ljust(self, width, fillchar=None):
|
||||
return {rvalue}
|
||||
''')
|
||||
code = code.format(rvalue=rvalue)
|
||||
fake = AstroidBuilder(MANAGER).string_build(code)['whatever']
|
||||
for method in fake.mymethods():
|
||||
class_node.locals[method.name] = [method]
|
||||
method.parent = class_node
|
||||
|
||||
def extend_builtins(class_transforms):
|
||||
from astroid.bases import BUILTINS
|
||||
builtin_ast = MANAGER.astroid_cache[BUILTINS]
|
||||
for class_name, transform in class_transforms.items():
|
||||
transform(builtin_ast[class_name])
|
||||
|
||||
if sys.version_info > (3, 0):
|
||||
extend_builtins({'bytes': partial(_extend_str, rvalue="b''"),
|
||||
'str': partial(_extend_str, rvalue="''")})
|
||||
else:
|
||||
extend_builtins({'str': partial(_extend_str, rvalue="''"),
|
||||
'unicode': partial(_extend_str, rvalue="u''")})
|
||||
|
||||
|
||||
def register_builtin_transform(transform, builtin_name):
|
||||
"""Register a new transform function for the given *builtin_name*.
|
||||
|
||||
The transform function must accept two parameters, a node and
|
||||
an optional context.
|
||||
"""
|
||||
def _transform_wrapper(node, context=None):
|
||||
result = transform(node, context=context)
|
||||
if result:
|
||||
result.parent = node
|
||||
result.lineno = node.lineno
|
||||
result.col_offset = node.col_offset
|
||||
return iter([result])
|
||||
|
||||
MANAGER.register_transform(nodes.CallFunc,
|
||||
inference_tip(_transform_wrapper),
|
||||
lambda n: (isinstance(n.func, nodes.Name) and
|
||||
n.func.name == builtin_name))
|
||||
|
||||
|
||||
def _generic_inference(node, context, node_type, transform):
|
||||
args = node.args
|
||||
if not args:
|
||||
return node_type()
|
||||
if len(node.args) > 1:
|
||||
raise UseInferenceDefault()
|
||||
|
||||
arg, = args
|
||||
transformed = transform(arg)
|
||||
if not transformed:
|
||||
try:
|
||||
infered = next(arg.infer(context=context))
|
||||
except (InferenceError, StopIteration):
|
||||
raise UseInferenceDefault()
|
||||
if infered is YES:
|
||||
raise UseInferenceDefault()
|
||||
transformed = transform(infered)
|
||||
if not transformed or transformed is YES:
|
||||
raise UseInferenceDefault()
|
||||
return transformed
|
||||
|
||||
|
||||
def _generic_transform(arg, klass, iterables, build_elts):
|
||||
if isinstance(arg, klass):
|
||||
return arg
|
||||
elif isinstance(arg, iterables):
|
||||
if not all(isinstance(elt, nodes.Const)
|
||||
for elt in arg.elts):
|
||||
# TODO(cpopa): Don't support heterogenous elements.
|
||||
# Not yet, though.
|
||||
raise UseInferenceDefault()
|
||||
elts = [elt.value for elt in arg.elts]
|
||||
elif isinstance(arg, nodes.Dict):
|
||||
if not all(isinstance(elt[0], nodes.Const)
|
||||
for elt in arg.items):
|
||||
raise UseInferenceDefault()
|
||||
elts = [item[0].value for item in arg.items]
|
||||
elif (isinstance(arg, nodes.Const) and
|
||||
isinstance(arg.value, (six.string_types, six.binary_type))):
|
||||
elts = arg.value
|
||||
else:
|
||||
return
|
||||
return klass(elts=build_elts(elts))
|
||||
|
||||
|
||||
def _infer_builtin(node, context,
|
||||
klass=None, iterables=None,
|
||||
build_elts=None):
|
||||
transform_func = partial(
|
||||
_generic_transform,
|
||||
klass=klass,
|
||||
iterables=iterables,
|
||||
build_elts=build_elts)
|
||||
|
||||
return _generic_inference(node, context, klass, transform_func)
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
infer_tuple = partial(
|
||||
_infer_builtin,
|
||||
klass=nodes.Tuple,
|
||||
iterables=(nodes.List, nodes.Set),
|
||||
build_elts=tuple)
|
||||
|
||||
infer_list = partial(
|
||||
_infer_builtin,
|
||||
klass=nodes.List,
|
||||
iterables=(nodes.Tuple, nodes.Set),
|
||||
build_elts=list)
|
||||
|
||||
infer_set = partial(
|
||||
_infer_builtin,
|
||||
klass=nodes.Set,
|
||||
iterables=(nodes.List, nodes.Tuple),
|
||||
build_elts=set)
|
||||
|
||||
|
||||
def _get_elts(arg, context):
|
||||
is_iterable = lambda n: isinstance(n,
|
||||
(nodes.List, nodes.Tuple, nodes.Set))
|
||||
try:
|
||||
infered = next(arg.infer(context))
|
||||
except (InferenceError, UnresolvableName):
|
||||
raise UseInferenceDefault()
|
||||
if isinstance(infered, nodes.Dict):
|
||||
items = infered.items
|
||||
elif is_iterable(infered):
|
||||
items = []
|
||||
for elt in infered.elts:
|
||||
# If an item is not a pair of two items,
|
||||
# then fallback to the default inference.
|
||||
# Also, take in consideration only hashable items,
|
||||
# tuples and consts. We are choosing Names as well.
|
||||
if not is_iterable(elt):
|
||||
raise UseInferenceDefault()
|
||||
if len(elt.elts) != 2:
|
||||
raise UseInferenceDefault()
|
||||
if not isinstance(elt.elts[0],
|
||||
(nodes.Tuple, nodes.Const, nodes.Name)):
|
||||
raise UseInferenceDefault()
|
||||
items.append(tuple(elt.elts))
|
||||
else:
|
||||
raise UseInferenceDefault()
|
||||
return items
|
||||
|
||||
def infer_dict(node, context=None):
|
||||
"""Try to infer a dict call to a Dict node.
|
||||
|
||||
The function treats the following cases:
|
||||
|
||||
* dict()
|
||||
* dict(mapping)
|
||||
* dict(iterable)
|
||||
* dict(iterable, **kwargs)
|
||||
* dict(mapping, **kwargs)
|
||||
* dict(**kwargs)
|
||||
|
||||
If a case can't be infered, we'll fallback to default inference.
|
||||
"""
|
||||
has_keywords = lambda args: all(isinstance(arg, nodes.Keyword)
|
||||
for arg in args)
|
||||
if not node.args and not node.kwargs:
|
||||
# dict()
|
||||
return nodes.Dict()
|
||||
elif has_keywords(node.args) and node.args:
|
||||
# dict(a=1, b=2, c=4)
|
||||
items = [(nodes.Const(arg.arg), arg.value) for arg in node.args]
|
||||
elif (len(node.args) >= 2 and
|
||||
has_keywords(node.args[1:])):
|
||||
# dict(some_iterable, b=2, c=4)
|
||||
elts = _get_elts(node.args[0], context)
|
||||
keys = [(nodes.Const(arg.arg), arg.value) for arg in node.args[1:]]
|
||||
items = elts + keys
|
||||
elif len(node.args) == 1:
|
||||
items = _get_elts(node.args[0], context)
|
||||
else:
|
||||
raise UseInferenceDefault()
|
||||
|
||||
empty = nodes.Dict()
|
||||
empty.items = items
|
||||
return empty
|
||||
|
||||
# Builtins inference
|
||||
register_builtin_transform(infer_tuple, 'tuple')
|
||||
register_builtin_transform(infer_set, 'set')
|
||||
register_builtin_transform(infer_list, 'list')
|
||||
register_builtin_transform(infer_dict, 'dict')
|
||||
155
vim-plugins/python-mode/pymode/libs/astroid/brain/py2gi.py
Normal file
155
vim-plugins/python-mode/pymode/libs/astroid/brain/py2gi.py
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
"""Astroid hooks for the Python 2 GObject introspection bindings.
|
||||
|
||||
Helps with understanding everything imported from 'gi.repository'
|
||||
"""
|
||||
|
||||
import inspect
|
||||
import itertools
|
||||
import sys
|
||||
import re
|
||||
|
||||
from astroid import MANAGER, AstroidBuildingException
|
||||
from astroid.builder import AstroidBuilder
|
||||
|
||||
|
||||
_inspected_modules = {}
|
||||
|
||||
_identifier_re = r'^[A-Za-z_]\w*$'
|
||||
|
||||
def _gi_build_stub(parent):
|
||||
"""
|
||||
Inspect the passed module recursively and build stubs for functions,
|
||||
classes, etc.
|
||||
"""
|
||||
classes = {}
|
||||
functions = {}
|
||||
constants = {}
|
||||
methods = {}
|
||||
for name in dir(parent):
|
||||
if name.startswith("__"):
|
||||
continue
|
||||
|
||||
# Check if this is a valid name in python
|
||||
if not re.match(_identifier_re, name):
|
||||
continue
|
||||
|
||||
try:
|
||||
obj = getattr(parent, name)
|
||||
except:
|
||||
continue
|
||||
|
||||
if inspect.isclass(obj):
|
||||
classes[name] = obj
|
||||
elif (inspect.isfunction(obj) or
|
||||
inspect.isbuiltin(obj)):
|
||||
functions[name] = obj
|
||||
elif (inspect.ismethod(obj) or
|
||||
inspect.ismethoddescriptor(obj)):
|
||||
methods[name] = obj
|
||||
elif type(obj) in [int, str]:
|
||||
constants[name] = obj
|
||||
elif (str(obj).startswith("<flags") or
|
||||
str(obj).startswith("<enum ") or
|
||||
str(obj).startswith("<GType ") or
|
||||
inspect.isdatadescriptor(obj)):
|
||||
constants[name] = 0
|
||||
elif callable(obj):
|
||||
# Fall back to a function for anything callable
|
||||
functions[name] = obj
|
||||
else:
|
||||
# Assume everything else is some manner of constant
|
||||
constants[name] = 0
|
||||
|
||||
ret = ""
|
||||
|
||||
if constants:
|
||||
ret += "# %s contants\n\n" % parent.__name__
|
||||
for name in sorted(constants):
|
||||
if name[0].isdigit():
|
||||
# GDK has some busted constant names like
|
||||
# Gdk.EventType.2BUTTON_PRESS
|
||||
continue
|
||||
|
||||
val = constants[name]
|
||||
|
||||
strval = str(val)
|
||||
if type(val) is str:
|
||||
strval = '"%s"' % str(val).replace("\\", "\\\\")
|
||||
ret += "%s = %s\n" % (name, strval)
|
||||
|
||||
if ret:
|
||||
ret += "\n\n"
|
||||
if functions:
|
||||
ret += "# %s functions\n\n" % parent.__name__
|
||||
for name in sorted(functions):
|
||||
func = functions[name]
|
||||
ret += "def %s(*args, **kwargs):\n" % name
|
||||
ret += " pass\n"
|
||||
|
||||
if ret:
|
||||
ret += "\n\n"
|
||||
if methods:
|
||||
ret += "# %s methods\n\n" % parent.__name__
|
||||
for name in sorted(methods):
|
||||
func = methods[name]
|
||||
ret += "def %s(self, *args, **kwargs):\n" % name
|
||||
ret += " pass\n"
|
||||
|
||||
if ret:
|
||||
ret += "\n\n"
|
||||
if classes:
|
||||
ret += "# %s classes\n\n" % parent.__name__
|
||||
for name in sorted(classes):
|
||||
ret += "class %s(object):\n" % name
|
||||
|
||||
classret = _gi_build_stub(classes[name])
|
||||
if not classret:
|
||||
classret = "pass\n"
|
||||
|
||||
for line in classret.splitlines():
|
||||
ret += " " + line + "\n"
|
||||
ret += "\n"
|
||||
|
||||
return ret
|
||||
|
||||
def _import_gi_module(modname):
|
||||
# we only consider gi.repository submodules
|
||||
if not modname.startswith('gi.repository.'):
|
||||
raise AstroidBuildingException()
|
||||
# build astroid representation unless we already tried so
|
||||
if modname not in _inspected_modules:
|
||||
modnames = [modname]
|
||||
optional_modnames = []
|
||||
|
||||
# GLib and GObject may have some special case handling
|
||||
# in pygobject that we need to cope with. However at
|
||||
# least as of pygobject3-3.13.91 the _glib module doesn't
|
||||
# exist anymore, so if treat these modules as optional.
|
||||
if modname == 'gi.repository.GLib':
|
||||
optional_modnames.append('gi._glib')
|
||||
elif modname == 'gi.repository.GObject':
|
||||
optional_modnames.append('gi._gobject')
|
||||
|
||||
try:
|
||||
modcode = ''
|
||||
for m in itertools.chain(modnames, optional_modnames):
|
||||
try:
|
||||
__import__(m)
|
||||
modcode += _gi_build_stub(sys.modules[m])
|
||||
except ImportError:
|
||||
if m not in optional_modnames:
|
||||
raise
|
||||
except ImportError:
|
||||
astng = _inspected_modules[modname] = None
|
||||
else:
|
||||
astng = AstroidBuilder(MANAGER).string_build(modcode, modname)
|
||||
_inspected_modules[modname] = astng
|
||||
else:
|
||||
astng = _inspected_modules[modname]
|
||||
if astng is None:
|
||||
raise AstroidBuildingException('Failed to import module %r' % modname)
|
||||
return astng
|
||||
|
||||
|
||||
MANAGER.register_failed_import_hook(_import_gi_module)
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from astroid import MANAGER, register_module_extender
|
||||
from astroid.builder import AstroidBuilder
|
||||
|
||||
def mechanize_transform():
|
||||
return AstroidBuilder(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
|
||||
|
||||
''')
|
||||
|
||||
|
||||
register_module_extender(MANAGER, 'mechanize', mechanize_transform)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
"""Astroid hooks for pytest."""
|
||||
|
||||
from astroid import MANAGER, register_module_extender
|
||||
from astroid.builder import AstroidBuilder
|
||||
|
||||
|
||||
def pytest_transform():
|
||||
return AstroidBuilder(MANAGER).string_build('''
|
||||
|
||||
try:
|
||||
import _pytest.mark
|
||||
import _pytest.recwarn
|
||||
import _pytest.runner
|
||||
import _pytest.python
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
deprecated_call = _pytest.recwarn.deprecated_call
|
||||
exit = _pytest.runner.exit
|
||||
fail = _pytest.runner.fail
|
||||
fixture = _pytest.python.fixture
|
||||
importorskip = _pytest.runner.importorskip
|
||||
mark = _pytest.mark.MarkGenerator()
|
||||
raises = _pytest.python.raises
|
||||
skip = _pytest.runner.skip
|
||||
yield_fixture = _pytest.python.yield_fixture
|
||||
|
||||
''')
|
||||
|
||||
register_module_extender(MANAGER, 'pytest', pytest_transform)
|
||||
register_module_extender(MANAGER, 'py.test', pytest_transform)
|
||||
22
vim-plugins/python-mode/pymode/libs/astroid/brain/py2qt4.py
Normal file
22
vim-plugins/python-mode/pymode/libs/astroid/brain/py2qt4.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
"""Astroid hooks for the Python 2 qt4 module.
|
||||
|
||||
Currently help understanding of :
|
||||
|
||||
* PyQT4.QtCore
|
||||
"""
|
||||
|
||||
from astroid import MANAGER, register_module_extender
|
||||
from astroid.builder import AstroidBuilder
|
||||
|
||||
|
||||
def pyqt4_qtcore_transform():
|
||||
return AstroidBuilder(MANAGER).string_build('''
|
||||
|
||||
def SIGNAL(signal_name): pass
|
||||
|
||||
class QObject(object):
|
||||
def emit(self, signal): pass
|
||||
''')
|
||||
|
||||
|
||||
register_module_extender(MANAGER, 'PyQt4.QtCore', pyqt4_qtcore_transform)
|
||||
334
vim-plugins/python-mode/pymode/libs/astroid/brain/py2stdlib.py
Normal file
334
vim-plugins/python-mode/pymode/libs/astroid/brain/py2stdlib.py
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
|
||||
"""Astroid hooks for the Python 2 standard library.
|
||||
|
||||
Currently help understanding of :
|
||||
|
||||
* hashlib.md5 and hashlib.sha1
|
||||
"""
|
||||
|
||||
import sys
|
||||
from functools import partial
|
||||
from textwrap import dedent
|
||||
|
||||
from astroid import (
|
||||
MANAGER, AsStringRegexpPredicate,
|
||||
UseInferenceDefault, inference_tip,
|
||||
YES, InferenceError, register_module_extender)
|
||||
from astroid import exceptions
|
||||
from astroid import nodes
|
||||
from astroid.builder import AstroidBuilder
|
||||
|
||||
PY3K = sys.version_info > (3, 0)
|
||||
PY33 = sys.version_info >= (3, 3)
|
||||
|
||||
# general function
|
||||
|
||||
def infer_func_form(node, base_type, context=None, enum=False):
|
||||
"""Specific inference function for namedtuple or Python 3 enum. """
|
||||
def infer_first(node):
|
||||
try:
|
||||
value = next(node.infer(context=context))
|
||||
if value is YES:
|
||||
raise UseInferenceDefault()
|
||||
else:
|
||||
return value
|
||||
except StopIteration:
|
||||
raise InferenceError()
|
||||
|
||||
# node is a CallFunc node, class name as first argument and generated class
|
||||
# attributes as second argument
|
||||
if len(node.args) != 2:
|
||||
# something weird here, go back to class implementation
|
||||
raise UseInferenceDefault()
|
||||
# namedtuple or enums list of attributes can be a list of strings or a
|
||||
# whitespace-separate string
|
||||
try:
|
||||
name = infer_first(node.args[0]).value
|
||||
names = infer_first(node.args[1])
|
||||
try:
|
||||
attributes = names.value.replace(',', ' ').split()
|
||||
except AttributeError:
|
||||
if not enum:
|
||||
attributes = [infer_first(const).value for const in names.elts]
|
||||
else:
|
||||
# Enums supports either iterator of (name, value) pairs
|
||||
# or mappings.
|
||||
# TODO: support only list, tuples and mappings.
|
||||
if hasattr(names, 'items') and isinstance(names.items, list):
|
||||
attributes = [infer_first(const[0]).value
|
||||
for const in names.items
|
||||
if isinstance(const[0], nodes.Const)]
|
||||
elif hasattr(names, 'elts'):
|
||||
# Enums can support either ["a", "b", "c"]
|
||||
# or [("a", 1), ("b", 2), ...], but they can't
|
||||
# be mixed.
|
||||
if all(isinstance(const, nodes.Tuple)
|
||||
for const in names.elts):
|
||||
attributes = [infer_first(const.elts[0]).value
|
||||
for const in names.elts
|
||||
if isinstance(const, nodes.Tuple)]
|
||||
else:
|
||||
attributes = [infer_first(const).value
|
||||
for const in names.elts]
|
||||
else:
|
||||
raise AttributeError
|
||||
if not attributes:
|
||||
raise AttributeError
|
||||
except (AttributeError, exceptions.InferenceError) as exc:
|
||||
raise UseInferenceDefault()
|
||||
# we want to return a Class node instance with proper attributes set
|
||||
class_node = nodes.Class(name, 'docstring')
|
||||
class_node.parent = node.parent
|
||||
# set base class=tuple
|
||||
class_node.bases.append(base_type)
|
||||
# XXX add __init__(*attributes) method
|
||||
for attr in attributes:
|
||||
fake_node = nodes.EmptyNode()
|
||||
fake_node.parent = class_node
|
||||
class_node.instance_attrs[attr] = [fake_node]
|
||||
return class_node, name, attributes
|
||||
|
||||
|
||||
# module specific transformation functions #####################################
|
||||
|
||||
def hashlib_transform():
|
||||
template = '''
|
||||
|
||||
class %(name)s(object):
|
||||
def __init__(self, value=''): pass
|
||||
def digest(self):
|
||||
return %(digest)s
|
||||
def copy(self):
|
||||
return self
|
||||
def update(self, value): pass
|
||||
def hexdigest(self):
|
||||
return ''
|
||||
@property
|
||||
def name(self):
|
||||
return %(name)r
|
||||
@property
|
||||
def block_size(self):
|
||||
return 1
|
||||
@property
|
||||
def digest_size(self):
|
||||
return 1
|
||||
'''
|
||||
algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
|
||||
classes = "".join(
|
||||
template % {'name': hashfunc, 'digest': 'b""' if PY3K else '""'}
|
||||
for hashfunc in algorithms)
|
||||
return AstroidBuilder(MANAGER).string_build(classes)
|
||||
|
||||
|
||||
def collections_transform():
|
||||
return AstroidBuilder(MANAGER).string_build('''
|
||||
|
||||
class defaultdict(dict):
|
||||
default_factory = None
|
||||
def __missing__(self, key): pass
|
||||
|
||||
class deque(object):
|
||||
maxlen = 0
|
||||
def __init__(self, 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
|
||||
def __iter__(self): return self
|
||||
|
||||
''')
|
||||
|
||||
|
||||
def pkg_resources_transform():
|
||||
return AstroidBuilder(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
|
||||
|
||||
''')
|
||||
|
||||
|
||||
def subprocess_transform():
|
||||
if PY3K:
|
||||
communicate = (bytes('string', 'ascii'), bytes('string', 'ascii'))
|
||||
init = """
|
||||
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, restore_signals=True,
|
||||
start_new_session=False, pass_fds=()):
|
||||
pass
|
||||
"""
|
||||
else:
|
||||
communicate = ('string', 'string')
|
||||
init = """
|
||||
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
|
||||
"""
|
||||
if PY33:
|
||||
wait_signature = 'def wait(self, timeout=None)'
|
||||
else:
|
||||
wait_signature = 'def wait(self)'
|
||||
return AstroidBuilder(MANAGER).string_build('''
|
||||
|
||||
class Popen(object):
|
||||
returncode = pid = 0
|
||||
stdin = stdout = stderr = file()
|
||||
|
||||
%(init)s
|
||||
|
||||
def communicate(self, input=None):
|
||||
return %(communicate)r
|
||||
%(wait_signature)s:
|
||||
return self.returncode
|
||||
def poll(self):
|
||||
return self.returncode
|
||||
def send_signal(self, signal):
|
||||
pass
|
||||
def terminate(self):
|
||||
pass
|
||||
def kill(self):
|
||||
pass
|
||||
''' % {'init': init,
|
||||
'communicate': communicate,
|
||||
'wait_signature': wait_signature})
|
||||
|
||||
|
||||
# namedtuple support ###########################################################
|
||||
|
||||
def looks_like_namedtuple(node):
|
||||
func = node.func
|
||||
if type(func) is nodes.Getattr:
|
||||
return func.attrname == 'namedtuple'
|
||||
if type(func) is nodes.Name:
|
||||
return func.name == 'namedtuple'
|
||||
return False
|
||||
|
||||
def infer_named_tuple(node, context=None):
|
||||
"""Specific inference function for namedtuple CallFunc node"""
|
||||
class_node, name, attributes = infer_func_form(node, nodes.Tuple._proxied,
|
||||
context=context)
|
||||
fake = AstroidBuilder(MANAGER).string_build('''
|
||||
class %(name)s(tuple):
|
||||
_fields = %(fields)r
|
||||
def _asdict(self):
|
||||
return self.__dict__
|
||||
@classmethod
|
||||
def _make(cls, iterable, new=tuple.__new__, len=len):
|
||||
return new(cls, iterable)
|
||||
def _replace(_self, **kwds):
|
||||
result = _self._make(map(kwds.pop, %(fields)r, _self))
|
||||
if kwds:
|
||||
raise ValueError('Got unexpected field names: %%r' %% list(kwds))
|
||||
return result
|
||||
''' % {'name': name, 'fields': attributes})
|
||||
class_node.locals['_asdict'] = fake.body[0].locals['_asdict']
|
||||
class_node.locals['_make'] = fake.body[0].locals['_make']
|
||||
class_node.locals['_replace'] = fake.body[0].locals['_replace']
|
||||
class_node.locals['_fields'] = fake.body[0].locals['_fields']
|
||||
# we use UseInferenceDefault, we can't be a generator so return an iterator
|
||||
return iter([class_node])
|
||||
|
||||
def infer_enum(node, context=None):
|
||||
""" Specific inference function for enum CallFunc node. """
|
||||
enum_meta = nodes.Class("EnumMeta", 'docstring')
|
||||
class_node = infer_func_form(node, enum_meta,
|
||||
context=context, enum=True)[0]
|
||||
return iter([class_node.instanciate_class()])
|
||||
|
||||
def infer_enum_class(node):
|
||||
""" Specific inference for enums. """
|
||||
names = set(('Enum', 'IntEnum', 'enum.Enum', 'enum.IntEnum'))
|
||||
for basename in node.basenames:
|
||||
# TODO: doesn't handle subclasses yet. This implementation
|
||||
# is a hack to support enums.
|
||||
if basename not in names:
|
||||
continue
|
||||
if node.root().name == 'enum':
|
||||
# Skip if the class is directly from enum module.
|
||||
break
|
||||
for local, values in node.locals.items():
|
||||
if any(not isinstance(value, nodes.AssName)
|
||||
for value in values):
|
||||
continue
|
||||
|
||||
stmt = values[0].statement()
|
||||
if isinstance(stmt.targets[0], nodes.Tuple):
|
||||
targets = stmt.targets[0].itered()
|
||||
else:
|
||||
targets = stmt.targets
|
||||
|
||||
new_targets = []
|
||||
for target in targets:
|
||||
# Replace all the assignments with our mocked class.
|
||||
classdef = dedent('''
|
||||
class %(name)s(object):
|
||||
@property
|
||||
def value(self):
|
||||
# Not the best return.
|
||||
return None
|
||||
@property
|
||||
def name(self):
|
||||
return %(name)r
|
||||
''' % {'name': target.name})
|
||||
fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name]
|
||||
fake.parent = target.parent
|
||||
for method in node.mymethods():
|
||||
fake.locals[method.name] = [method]
|
||||
new_targets.append(fake.instanciate_class())
|
||||
node.locals[local] = new_targets
|
||||
break
|
||||
return node
|
||||
|
||||
|
||||
MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_named_tuple),
|
||||
looks_like_namedtuple)
|
||||
MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_enum),
|
||||
AsStringRegexpPredicate('Enum', 'func'))
|
||||
MANAGER.register_transform(nodes.Class, infer_enum_class)
|
||||
register_module_extender(MANAGER, 'hashlib', hashlib_transform)
|
||||
register_module_extender(MANAGER, 'collections', collections_transform)
|
||||
register_module_extender(MANAGER, 'pkg_resources', pkg_resources_transform)
|
||||
register_module_extender(MANAGER, 'subprocess', subprocess_transform)
|
||||
79
vim-plugins/python-mode/pymode/libs/astroid/brain/pynose.py
Normal file
79
vim-plugins/python-mode/pymode/libs/astroid/brain/pynose.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
||||
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
||||
#
|
||||
# This file is part of astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Hooks for nose library."""
|
||||
|
||||
import re
|
||||
import textwrap
|
||||
|
||||
import astroid
|
||||
import astroid.builder
|
||||
|
||||
_BUILDER = astroid.builder.AstroidBuilder(astroid.MANAGER)
|
||||
|
||||
|
||||
def _pep8(name, caps=re.compile('([A-Z])')):
|
||||
return caps.sub(lambda m: '_' + m.groups()[0].lower(), name)
|
||||
|
||||
|
||||
def _nose_tools_functions():
|
||||
"""Get an iterator of names and bound methods."""
|
||||
module = _BUILDER.string_build(textwrap.dedent('''
|
||||
import unittest
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
pass
|
||||
a = Test()
|
||||
'''))
|
||||
try:
|
||||
case = next(module['a'].infer())
|
||||
except astroid.InferenceError:
|
||||
return
|
||||
for method in case.methods():
|
||||
if method.name.startswith('assert') and '_' not in method.name:
|
||||
pep8_name = _pep8(method.name)
|
||||
yield pep8_name, astroid.BoundMethod(method, case)
|
||||
|
||||
|
||||
def _nose_tools_transform(node):
|
||||
for method_name, method in _nose_tools_functions():
|
||||
node.locals[method_name] = [method]
|
||||
|
||||
|
||||
def _nose_tools_trivial_transform():
|
||||
"""Custom transform for the nose.tools module."""
|
||||
stub = _BUILDER.string_build('''__all__ = []''')
|
||||
all_entries = ['ok_', 'eq_']
|
||||
|
||||
for pep8_name, method in _nose_tools_functions():
|
||||
all_entries.append(pep8_name)
|
||||
stub[pep8_name] = method
|
||||
|
||||
# Update the __all__ variable, since nose.tools
|
||||
# does this manually with .append.
|
||||
all_assign = stub['__all__'].parent
|
||||
all_object = astroid.List(all_entries)
|
||||
all_object.parent = all_assign
|
||||
all_assign.value = all_object
|
||||
return stub
|
||||
|
||||
|
||||
astroid.register_module_extender(astroid.MANAGER, 'nose.tools.trivial',
|
||||
_nose_tools_trivial_transform)
|
||||
astroid.MANAGER.register_transform(astroid.Module, _nose_tools_transform,
|
||||
lambda n: n.name == 'nose.tools')
|
||||
261
vim-plugins/python-mode/pymode/libs/astroid/brain/pysix_moves.py
Normal file
261
vim-plugins/python-mode/pymode/libs/astroid/brain/pysix_moves.py
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
||||
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
||||
#
|
||||
# This file is part of astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Astroid hooks for six.moves."""
|
||||
|
||||
import sys
|
||||
from textwrap import dedent
|
||||
|
||||
from astroid import MANAGER, register_module_extender
|
||||
from astroid.builder import AstroidBuilder
|
||||
from astroid.exceptions import AstroidBuildingException
|
||||
|
||||
def _indent(text, prefix, predicate=None):
|
||||
"""Adds 'prefix' to the beginning of selected lines in 'text'.
|
||||
|
||||
If 'predicate' is provided, 'prefix' will only be added to the lines
|
||||
where 'predicate(line)' is True. If 'predicate' is not provided,
|
||||
it will default to adding 'prefix' to all non-empty lines that do not
|
||||
consist solely of whitespace characters.
|
||||
"""
|
||||
if predicate is None:
|
||||
predicate = lambda line: line.strip()
|
||||
|
||||
def prefixed_lines():
|
||||
for line in text.splitlines(True):
|
||||
yield prefix + line if predicate(line) else line
|
||||
return ''.join(prefixed_lines())
|
||||
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
_IMPORTS_2 = """
|
||||
import BaseHTTPServer
|
||||
import CGIHTTPServer
|
||||
import SimpleHTTPServer
|
||||
|
||||
from StringIO import StringIO
|
||||
from cStringIO import StringIO as cStringIO
|
||||
from UserDict import UserDict
|
||||
from UserList import UserList
|
||||
from UserString import UserString
|
||||
|
||||
import __builtin__ as builtins
|
||||
import thread as _thread
|
||||
import dummy_thread as _dummy_thread
|
||||
import ConfigParser as configparser
|
||||
import copy_reg as copyreg
|
||||
from itertools import (imap as map,
|
||||
ifilter as filter,
|
||||
ifilterfalse as filterfalse,
|
||||
izip_longest as zip_longest,
|
||||
izip as zip)
|
||||
import htmlentitydefs as html_entities
|
||||
import HTMLParser as html_parser
|
||||
import httplib as http_client
|
||||
import cookielib as http_cookiejar
|
||||
import Cookie as http_cookies
|
||||
import Queue as queue
|
||||
import repr as reprlib
|
||||
from pipes import quote as shlex_quote
|
||||
import SocketServer as socketserver
|
||||
import SimpleXMLRPCServer as xmlrpc_server
|
||||
import xmlrpclib as xmlrpc_client
|
||||
import _winreg as winreg
|
||||
import robotparser as urllib_robotparser
|
||||
import Tkinter as tkinter
|
||||
import tkFileDialog as tkinter_tkfiledialog
|
||||
|
||||
input = raw_input
|
||||
intern = intern
|
||||
range = xrange
|
||||
xrange = xrange
|
||||
reduce = reduce
|
||||
reload_module = reload
|
||||
|
||||
class UrllibParse(object):
|
||||
import urlparse as _urlparse
|
||||
import urllib as _urllib
|
||||
ParseResult = _urlparse.ParseResult
|
||||
SplitResult = _urlparse.SplitResult
|
||||
parse_qs = _urlparse.parse_qs
|
||||
parse_qsl = _urlparse.parse_qsl
|
||||
urldefrag = _urlparse.urldefrag
|
||||
urljoin = _urlparse.urljoin
|
||||
urlparse = _urlparse.urlparse
|
||||
urlsplit = _urlparse.urlsplit
|
||||
urlunparse = _urlparse.urlunparse
|
||||
urlunsplit = _urlparse.urlunsplit
|
||||
quote = _urllib.quote
|
||||
quote_plus = _urllib.quote_plus
|
||||
unquote = _urllib.unquote
|
||||
unquote_plus = _urllib.unquote_plus
|
||||
urlencode = _urllib.urlencode
|
||||
splitquery = _urllib.splitquery
|
||||
splittag = _urllib.splittag
|
||||
splituser = _urllib.splituser
|
||||
uses_fragment = _urlparse.uses_fragment
|
||||
uses_netloc = _urlparse.uses_netloc
|
||||
uses_params = _urlparse.uses_params
|
||||
uses_query = _urlparse.uses_query
|
||||
uses_relative = _urlparse.uses_relative
|
||||
|
||||
class UrllibError(object):
|
||||
import urllib2 as _urllib2
|
||||
import urllib as _urllib
|
||||
URLError = _urllib2.URLError
|
||||
HTTPError = _urllib2.HTTPError
|
||||
ContentTooShortError = _urllib.ContentTooShortError
|
||||
|
||||
class DummyModule(object):
|
||||
pass
|
||||
|
||||
class UrllibRequest(object):
|
||||
import urlparse as _urlparse
|
||||
import urllib2 as _urllib2
|
||||
import urllib as _urllib
|
||||
urlopen = _urllib2.urlopen
|
||||
install_opener = _urllib2.install_opener
|
||||
build_opener = _urllib2.build_opener
|
||||
pathname2url = _urllib.pathname2url
|
||||
url2pathname = _urllib.url2pathname
|
||||
getproxies = _urllib.getproxies
|
||||
Request = _urllib2.Request
|
||||
OpenerDirector = _urllib2.OpenerDirector
|
||||
HTTPDefaultErrorHandler = _urllib2.HTTPDefaultErrorHandler
|
||||
HTTPRedirectHandler = _urllib2.HTTPRedirectHandler
|
||||
HTTPCookieProcessor = _urllib2.HTTPCookieProcessor
|
||||
ProxyHandler = _urllib2.ProxyHandler
|
||||
BaseHandler = _urllib2.BaseHandler
|
||||
HTTPPasswordMgr = _urllib2.HTTPPasswordMgr
|
||||
HTTPPasswordMgrWithDefaultRealm = _urllib2.HTTPPasswordMgrWithDefaultRealm
|
||||
AbstractBasicAuthHandler = _urllib2.AbstractBasicAuthHandler
|
||||
HTTPBasicAuthHandler = _urllib2.HTTPBasicAuthHandler
|
||||
ProxyBasicAuthHandler = _urllib2.ProxyBasicAuthHandler
|
||||
AbstractDigestAuthHandler = _urllib2.AbstractDigestAuthHandler
|
||||
HTTPDigestAuthHandler = _urllib2.HTTPDigestAuthHandler
|
||||
ProxyDigestAuthHandler = _urllib2.ProxyDigestAuthHandler
|
||||
HTTPHandler = _urllib2.HTTPHandler
|
||||
HTTPSHandler = _urllib2.HTTPSHandler
|
||||
FileHandler = _urllib2.FileHandler
|
||||
FTPHandler = _urllib2.FTPHandler
|
||||
CacheFTPHandler = _urllib2.CacheFTPHandler
|
||||
UnknownHandler = _urllib2.UnknownHandler
|
||||
HTTPErrorProcessor = _urllib2.HTTPErrorProcessor
|
||||
urlretrieve = _urllib.urlretrieve
|
||||
urlcleanup = _urllib.urlcleanup
|
||||
proxy_bypass = _urllib.proxy_bypass
|
||||
|
||||
urllib_parse = UrllibParse()
|
||||
urllib_error = UrllibError()
|
||||
urllib = DummyModule()
|
||||
urllib.request = UrllibRequest()
|
||||
urllib.parse = UrllibParse()
|
||||
urllib.error = UrllibError()
|
||||
"""
|
||||
else:
|
||||
_IMPORTS_3 = """
|
||||
import _io
|
||||
cStringIO = _io.StringIO
|
||||
filter = filter
|
||||
from itertools import filterfalse
|
||||
input = input
|
||||
from sys import intern
|
||||
map = map
|
||||
range = range
|
||||
from imp import reload as reload_module
|
||||
from functools import reduce
|
||||
from shlex import quote as shlex_quote
|
||||
from io import StringIO
|
||||
from collections import UserDict, UserList, UserString
|
||||
xrange = range
|
||||
zip = zip
|
||||
from itertools import zip_longest
|
||||
import builtins
|
||||
import configparser
|
||||
import copyreg
|
||||
import _dummy_thread
|
||||
import http.cookiejar as http_cookiejar
|
||||
import http.cookies as http_cookies
|
||||
import html.entities as html_entities
|
||||
import html.parser as html_parser
|
||||
import http.client as http_client
|
||||
import http.server
|
||||
BaseHTTPServer = CGIHTTPServer = SimpleHTTPServer = http.server
|
||||
import pickle as cPickle
|
||||
import queue
|
||||
import reprlib
|
||||
import socketserver
|
||||
import _thread
|
||||
import winreg
|
||||
import xmlrpc.server as xmlrpc_server
|
||||
import xmlrpc.client as xmlrpc_client
|
||||
import urllib.robotparser as urllib_robotparser
|
||||
import email.mime.multipart as email_mime_multipart
|
||||
import email.mime.nonmultipart as email_mime_nonmultipart
|
||||
import email.mime.text as email_mime_text
|
||||
import email.mime.base as email_mime_base
|
||||
import urllib.parse as urllib_parse
|
||||
import urllib.error as urllib_error
|
||||
import tkinter
|
||||
import tkinter.dialog as tkinter_dialog
|
||||
import tkinter.filedialog as tkinter_filedialog
|
||||
import tkinter.scrolledtext as tkinter_scrolledtext
|
||||
import tkinter.simpledialog as tkinder_simpledialog
|
||||
import tkinter.tix as tkinter_tix
|
||||
import tkinter.ttk as tkinter_ttk
|
||||
import tkinter.constants as tkinter_constants
|
||||
import tkinter.dnd as tkinter_dnd
|
||||
import tkinter.colorchooser as tkinter_colorchooser
|
||||
import tkinter.commondialog as tkinter_commondialog
|
||||
import tkinter.filedialog as tkinter_tkfiledialog
|
||||
import tkinter.font as tkinter_font
|
||||
import tkinter.messagebox as tkinter_messagebox
|
||||
import urllib.request
|
||||
import urllib.robotparser as urllib_robotparser
|
||||
import urllib.parse as urllib_parse
|
||||
import urllib.error as urllib_error
|
||||
"""
|
||||
if sys.version_info[0] == 2:
|
||||
_IMPORTS = dedent(_IMPORTS_2)
|
||||
else:
|
||||
_IMPORTS = dedent(_IMPORTS_3)
|
||||
|
||||
|
||||
def six_moves_transform():
|
||||
code = dedent('''
|
||||
class Moves(object):
|
||||
{}
|
||||
moves = Moves()
|
||||
''').format(_indent(_IMPORTS, " "))
|
||||
module = AstroidBuilder(MANAGER).string_build(code)
|
||||
module.name = 'six.moves'
|
||||
return module
|
||||
|
||||
|
||||
def _six_fail_hook(modname):
|
||||
if modname != 'six.moves':
|
||||
raise AstroidBuildingException
|
||||
module = AstroidBuilder(MANAGER).string_build(_IMPORTS)
|
||||
module.name = 'six.moves'
|
||||
return module
|
||||
|
||||
|
||||
register_module_extender(MANAGER, 'six', six_moves_transform)
|
||||
register_module_extender(MANAGER, 'requests.packages.urllib3.packages.six',
|
||||
six_moves_transform)
|
||||
MANAGER.register_failed_import_hook(_six_fail_hook)
|
||||
240
vim-plugins/python-mode/pymode/libs/astroid/builder.py
Normal file
240
vim-plugins/python-mode/pymode/libs/astroid/builder.py
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
||||
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
||||
#
|
||||
# This file is part of astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""The AstroidBuilder makes astroid 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.
|
||||
"""
|
||||
from __future__ import with_statement
|
||||
|
||||
__docformat__ = "restructuredtext en"
|
||||
|
||||
import sys
|
||||
from os.path import splitext, basename, exists, abspath
|
||||
|
||||
from astroid.exceptions import AstroidBuildingException, InferenceError
|
||||
from astroid.raw_building import InspectBuilder
|
||||
from astroid.rebuilder import TreeRebuilder
|
||||
from astroid.manager import AstroidManager
|
||||
from astroid.bases import YES, Instance
|
||||
from astroid.modutils import modpath_from_file
|
||||
|
||||
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):
|
||||
with open(filename, 'rb') as byte_stream:
|
||||
encoding = detect_encoding(byte_stream.readline)[0]
|
||||
stream = open(filename, 'r', newline=None, encoding=encoding)
|
||||
try:
|
||||
data = stream.read()
|
||||
except UnicodeError: # wrong encodingg
|
||||
# detect_encoding returns utf-8 if no encoding specified
|
||||
msg = 'Wrong (%s) or no encoding specified' % encoding
|
||||
raise AstroidBuildingException(msg)
|
||||
return stream, encoding, data
|
||||
|
||||
else:
|
||||
import re
|
||||
|
||||
_ENCODING_RGX = re.compile(r"\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 = AstroidManager()
|
||||
|
||||
class AstroidBuilder(InspectBuilder):
|
||||
"""provide astroid building methods"""
|
||||
|
||||
def __init__(self, manager=None):
|
||||
InspectBuilder.__init__(self)
|
||||
self._manager = manager or MANAGER
|
||||
|
||||
def module_build(self, module, modname=None):
|
||||
"""build an astroid 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)
|
||||
# we have to handle transformation by ourselves since the rebuilder
|
||||
# isn't called for builtin nodes
|
||||
#
|
||||
# XXX it's then only called for Module nodes, not for underlying
|
||||
# nodes
|
||||
node = self._manager.transform(node)
|
||||
return node
|
||||
|
||||
def file_build(self, path, modname=None):
|
||||
"""build astroid 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 as exc:
|
||||
msg = 'Unable to load file %r (%s)' % (path, exc)
|
||||
raise AstroidBuildingException(msg)
|
||||
except SyntaxError as exc: # py3k encoding specification error
|
||||
raise AstroidBuildingException(exc)
|
||||
except LookupError as exc: # unknown encoding
|
||||
raise AstroidBuildingException(exc)
|
||||
with stream:
|
||||
# get module name if necessary
|
||||
if modname is None:
|
||||
try:
|
||||
modname = '.'.join(modpath_from_file(path))
|
||||
except ImportError:
|
||||
modname = splitext(basename(path))[0]
|
||||
# build astroid representation
|
||||
module = self._data_build(data, modname, path)
|
||||
return self._post_build(module, encoding)
|
||||
|
||||
def string_build(self, data, modname='', path=None):
|
||||
"""build astroid from source code string and return rebuilded astroid"""
|
||||
module = self._data_build(data, modname, path)
|
||||
module.file_bytes = data.encode('utf-8')
|
||||
return self._post_build(module, 'utf-8')
|
||||
|
||||
def _post_build(self, module, encoding):
|
||||
"""handles encoding and delayed nodes
|
||||
after a module has been built
|
||||
"""
|
||||
module.file_encoding = encoding
|
||||
self._manager.cache_module(module)
|
||||
# post tree building steps after we stored the module in the cache:
|
||||
for from_node in module._from_nodes:
|
||||
if from_node.modname == '__future__':
|
||||
for symbol, _ in from_node.names:
|
||||
module.future_imports.add(symbol)
|
||||
self.add_from_names_to_locals(from_node)
|
||||
# handle delayed assattr nodes
|
||||
for delayed in module._delayed_assattr:
|
||||
self.delayed_assattr(delayed)
|
||||
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
|
||||
try:
|
||||
node = parse(data + '\n')
|
||||
except TypeError as exc:
|
||||
raise AstroidBuildingException(exc)
|
||||
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
|
||||
rebuilder = TreeRebuilder(self._manager)
|
||||
module = rebuilder.visit_module(node, modname, node_file, package)
|
||||
module._from_nodes = rebuilder._from_nodes
|
||||
module._delayed_assattr = 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.do_import_module()
|
||||
except InferenceError:
|
||||
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
|
||||
|
||||
51
vim-plugins/python-mode/pymode/libs/astroid/exceptions.py
Normal file
51
vim-plugins/python-mode/pymode/libs/astroid/exceptions.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""this module contains exceptions used in the astroid library
|
||||
|
||||
"""
|
||||
|
||||
__doctype__ = "restructuredtext en"
|
||||
|
||||
class AstroidError(Exception):
|
||||
"""base exception class for all astroid related exceptions"""
|
||||
|
||||
class AstroidBuildingException(AstroidError):
|
||||
"""exception class when we are unable to build an astroid representation"""
|
||||
|
||||
class ResolveError(AstroidError):
|
||||
"""base class of astroid 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 UseInferenceDefault(Exception):
|
||||
"""exception to be raised in custom inference function to indicate that it
|
||||
should go back to the default behaviour
|
||||
"""
|
||||
|
||||
class UnresolvableName(InferenceError):
|
||||
"""raised when we are unable to resolve a name"""
|
||||
|
||||
class NoDefault(AstroidError):
|
||||
"""raised by function's `default_value` method when an argument has
|
||||
no default value
|
||||
"""
|
||||
|
||||
405
vim-plugins/python-mode/pymode/libs/astroid/inference.py
Normal file
405
vim-plugins/python-mode/pymode/libs/astroid/inference.py
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""this module contains a set of functions to handle inference on astroid trees
|
||||
"""
|
||||
|
||||
__doctype__ = "restructuredtext en"
|
||||
|
||||
from itertools import chain
|
||||
|
||||
from astroid import nodes
|
||||
|
||||
from astroid.manager import AstroidManager
|
||||
from astroid.exceptions import (AstroidError, InferenceError, NoDefault,
|
||||
NotFoundError, UnresolvableName)
|
||||
from astroid.bases import (YES, Instance, InferenceContext,
|
||||
_infer_stmts, copy_context, path_wrapper,
|
||||
raise_if_nothing_infered)
|
||||
from astroid.protocols import (
|
||||
_arguments_infer_argname,
|
||||
BIN_OP_METHOD, UNARY_OP_METHOD)
|
||||
|
||||
MANAGER = AstroidManager()
|
||||
|
||||
|
||||
class CallContext(object):
|
||||
"""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 astroid (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,))
|
||||
# if we have a method, extract one position
|
||||
# from the index, so we'll take in account
|
||||
# the extra parameter represented by `self` or `cls`
|
||||
if funcnode.type in ('method', 'classmethod'):
|
||||
argindex -= 1
|
||||
# 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
|
||||
nodes.Set._infer = infer_end
|
||||
|
||||
def _higher_function_scope(node):
|
||||
""" Search for the first function which encloses the given
|
||||
scope. This can be used for looking up in that function's
|
||||
scope, in case looking up in a lower scope for a particular
|
||||
name fails.
|
||||
|
||||
:param node: A scope node.
|
||||
:returns:
|
||||
``None``, if no parent function scope was found,
|
||||
otherwise an instance of :class:`astroid.scoped_nodes.Function`,
|
||||
which encloses the given node.
|
||||
"""
|
||||
current = node
|
||||
while current.parent and not isinstance(current.parent, nodes.Function):
|
||||
current = current.parent
|
||||
if current and current.parent:
|
||||
return current.parent
|
||||
|
||||
def infer_name(self, context=None):
|
||||
"""infer a Name: use name lookup rules"""
|
||||
frame, stmts = self.lookup(self.name)
|
||||
if not stmts:
|
||||
# Try to see if the name is enclosed in a nested function
|
||||
# and use the higher (first function) scope for searching.
|
||||
# TODO: should this be promoted to other nodes as well?
|
||||
parent_function = _higher_function_scope(self.scope())
|
||||
if parent_function:
|
||||
_, stmts = parent_function.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()
|
||||
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"""
|
||||
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]"""
|
||||
value = next(self.value.infer(context))
|
||||
if value is YES:
|
||||
yield YES
|
||||
return
|
||||
|
||||
index = next(self.slice.infer(context))
|
||||
if index is YES:
|
||||
yield YES
|
||||
return
|
||||
|
||||
if isinstance(index, nodes.Const):
|
||||
try:
|
||||
assigned = value.getitem(index.value, context)
|
||||
except AttributeError:
|
||||
raise InferenceError()
|
||||
except (IndexError, TypeError):
|
||||
yield YES
|
||||
return
|
||||
|
||||
# Prevent inferring if the infered subscript
|
||||
# is the same as the original subscripted object.
|
||||
if self is assigned:
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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_ast_from_something(self.object,
|
||||
context=context):
|
||||
yield infered
|
||||
except AstroidError:
|
||||
yield YES
|
||||
nodes.EmptyNode._infer = path_wrapper(infer_empty_node)
|
||||
|
||||
|
||||
def infer_index(self, context=None):
|
||||
return self.value.infer(context)
|
||||
nodes.Index._infer = infer_index
|
||||
273
vim-plugins/python-mode/pymode/libs/astroid/inspector.py
Normal file
273
vim-plugins/python-mode/pymode/libs/astroid/inspector.py
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""visitor doing some postprocessing on the astroid tree.
|
||||
Try to resolve definitions (namespace) dictionary, relationship...
|
||||
|
||||
This module has been imported from pyreverse
|
||||
"""
|
||||
|
||||
__docformat__ = "restructuredtext en"
|
||||
|
||||
from os.path import dirname
|
||||
|
||||
import astroid
|
||||
from astroid.exceptions import InferenceError
|
||||
from astroid.utils import LocalsVisitor
|
||||
from astroid.modutils import get_module_part, is_relative, is_standard_module
|
||||
|
||||
class IdGeneratorMixIn(object):
|
||||
"""
|
||||
Mixin adding the ability to generate integer uid
|
||||
"""
|
||||
def __init__(self, start_value=0):
|
||||
self.id_count = start_value
|
||||
|
||||
def init_counter(self, start_value=0):
|
||||
"""init the id counter
|
||||
"""
|
||||
self.id_count = start_value
|
||||
|
||||
def generate_id(self):
|
||||
"""generate a new identifier
|
||||
"""
|
||||
self.id_count += 1
|
||||
return self.id_count
|
||||
|
||||
|
||||
class Linker(IdGeneratorMixIn, LocalsVisitor):
|
||||
"""
|
||||
walk on the project tree and resolve relationships.
|
||||
|
||||
According to options the following attributes may be added to visited nodes:
|
||||
|
||||
* uid,
|
||||
a unique identifier for the node (on astroid.Project, astroid.Module,
|
||||
astroid.Class and astroid.locals_type). Only if the linker has been instantiated
|
||||
with tag=True parameter (False by default).
|
||||
|
||||
* Function
|
||||
a mapping from locals names to their bounded value, which may be a
|
||||
constant like a string or an integer, or an astroid node (on astroid.Module,
|
||||
astroid.Class and astroid.Function).
|
||||
|
||||
* instance_attrs_type
|
||||
as locals_type but for klass member attributes (only on astroid.Class)
|
||||
|
||||
* implements,
|
||||
list of implemented interface _objects_ (only on astroid.Class nodes)
|
||||
"""
|
||||
|
||||
def __init__(self, project, inherited_interfaces=0, tag=False):
|
||||
IdGeneratorMixIn.__init__(self)
|
||||
LocalsVisitor.__init__(self)
|
||||
# take inherited interface in consideration or not
|
||||
self.inherited_interfaces = inherited_interfaces
|
||||
# tag nodes or not
|
||||
self.tag = tag
|
||||
# visited project
|
||||
self.project = project
|
||||
|
||||
|
||||
def visit_project(self, node):
|
||||
"""visit an astroid.Project node
|
||||
|
||||
* optionally tag the node with a unique id
|
||||
"""
|
||||
if self.tag:
|
||||
node.uid = self.generate_id()
|
||||
for module in node.modules:
|
||||
self.visit(module)
|
||||
|
||||
def visit_package(self, node):
|
||||
"""visit an astroid.Package node
|
||||
|
||||
* optionally tag the node with a unique id
|
||||
"""
|
||||
if self.tag:
|
||||
node.uid = self.generate_id()
|
||||
for subelmt in node.values():
|
||||
self.visit(subelmt)
|
||||
|
||||
def visit_module(self, node):
|
||||
"""visit an astroid.Module node
|
||||
|
||||
* set the locals_type mapping
|
||||
* set the depends mapping
|
||||
* optionally tag the node with a unique id
|
||||
"""
|
||||
if hasattr(node, 'locals_type'):
|
||||
return
|
||||
node.locals_type = {}
|
||||
node.depends = []
|
||||
if self.tag:
|
||||
node.uid = self.generate_id()
|
||||
|
||||
def visit_class(self, node):
|
||||
"""visit an astroid.Class node
|
||||
|
||||
* set the locals_type and instance_attrs_type mappings
|
||||
* set the implements list and build it
|
||||
* optionally tag the node with a unique id
|
||||
"""
|
||||
if hasattr(node, 'locals_type'):
|
||||
return
|
||||
node.locals_type = {}
|
||||
if self.tag:
|
||||
node.uid = self.generate_id()
|
||||
# resolve ancestors
|
||||
for baseobj in node.ancestors(recurs=False):
|
||||
specializations = getattr(baseobj, 'specializations', [])
|
||||
specializations.append(node)
|
||||
baseobj.specializations = specializations
|
||||
# resolve instance attributes
|
||||
node.instance_attrs_type = {}
|
||||
for assattrs in node.instance_attrs.values():
|
||||
for assattr in assattrs:
|
||||
self.handle_assattr_type(assattr, node)
|
||||
# resolve implemented interface
|
||||
try:
|
||||
node.implements = list(node.interfaces(self.inherited_interfaces))
|
||||
except InferenceError:
|
||||
node.implements = ()
|
||||
|
||||
def visit_function(self, node):
|
||||
"""visit an astroid.Function node
|
||||
|
||||
* set the locals_type mapping
|
||||
* optionally tag the node with a unique id
|
||||
"""
|
||||
if hasattr(node, 'locals_type'):
|
||||
return
|
||||
node.locals_type = {}
|
||||
if self.tag:
|
||||
node.uid = self.generate_id()
|
||||
|
||||
link_project = visit_project
|
||||
link_module = visit_module
|
||||
link_class = visit_class
|
||||
link_function = visit_function
|
||||
|
||||
def visit_assname(self, node):
|
||||
"""visit an astroid.AssName node
|
||||
|
||||
handle locals_type
|
||||
"""
|
||||
# avoid double parsing done by different Linkers.visit
|
||||
# running over the same project:
|
||||
if hasattr(node, '_handled'):
|
||||
return
|
||||
node._handled = True
|
||||
if node.name in node.frame():
|
||||
frame = node.frame()
|
||||
else:
|
||||
# the name has been defined as 'global' in the frame and belongs
|
||||
# there. Btw the frame is not yet visited as the name is in the
|
||||
# root locals; the frame hence has no locals_type attribute
|
||||
frame = node.root()
|
||||
try:
|
||||
values = node.infered()
|
||||
try:
|
||||
already_infered = frame.locals_type[node.name]
|
||||
for valnode in values:
|
||||
if not valnode in already_infered:
|
||||
already_infered.append(valnode)
|
||||
except KeyError:
|
||||
frame.locals_type[node.name] = values
|
||||
except astroid.InferenceError:
|
||||
pass
|
||||
|
||||
def handle_assattr_type(self, node, parent):
|
||||
"""handle an astroid.AssAttr node
|
||||
|
||||
handle instance_attrs_type
|
||||
"""
|
||||
try:
|
||||
values = list(node.infer())
|
||||
try:
|
||||
already_infered = parent.instance_attrs_type[node.attrname]
|
||||
for valnode in values:
|
||||
if not valnode in already_infered:
|
||||
already_infered.append(valnode)
|
||||
except KeyError:
|
||||
parent.instance_attrs_type[node.attrname] = values
|
||||
except astroid.InferenceError:
|
||||
pass
|
||||
|
||||
def visit_import(self, node):
|
||||
"""visit an astroid.Import node
|
||||
|
||||
resolve module dependencies
|
||||
"""
|
||||
context_file = node.root().file
|
||||
for name in node.names:
|
||||
relative = is_relative(name[0], context_file)
|
||||
self._imported_module(node, name[0], relative)
|
||||
|
||||
|
||||
def visit_from(self, node):
|
||||
"""visit an astroid.From node
|
||||
|
||||
resolve module dependencies
|
||||
"""
|
||||
basename = node.modname
|
||||
context_file = node.root().file
|
||||
if context_file is not None:
|
||||
relative = is_relative(basename, context_file)
|
||||
else:
|
||||
relative = False
|
||||
for name in node.names:
|
||||
if name[0] == '*':
|
||||
continue
|
||||
# analyze dependencies
|
||||
fullname = '%s.%s' % (basename, name[0])
|
||||
if fullname.find('.') > -1:
|
||||
try:
|
||||
# XXX: don't use get_module_part, missing package precedence
|
||||
fullname = get_module_part(fullname, context_file)
|
||||
except ImportError:
|
||||
continue
|
||||
if fullname != basename:
|
||||
self._imported_module(node, fullname, relative)
|
||||
|
||||
|
||||
def compute_module(self, context_name, mod_path):
|
||||
"""return true if the module should be added to dependencies"""
|
||||
package_dir = dirname(self.project.path)
|
||||
if context_name == mod_path:
|
||||
return 0
|
||||
elif is_standard_module(mod_path, (package_dir,)):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# protected methods ########################################################
|
||||
|
||||
def _imported_module(self, node, mod_path, relative):
|
||||
"""notify an imported module, used to analyze dependencies
|
||||
"""
|
||||
module = node.root()
|
||||
context_name = module.name
|
||||
if relative:
|
||||
mod_path = '%s.%s' % ('.'.join(context_name.split('.')[:-1]),
|
||||
mod_path)
|
||||
if self.compute_module(context_name, mod_path):
|
||||
# handle dependencies
|
||||
if not hasattr(module, 'depends'):
|
||||
module.depends = []
|
||||
mod_paths = module.depends
|
||||
if not mod_path in mod_paths:
|
||||
mod_paths.append(mod_path)
|
||||
391
vim-plugins/python-mode/pymode/libs/astroid/manager.py
Normal file
391
vim-plugins/python-mode/pymode/libs/astroid/manager.py
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""astroid manager: avoid multiple astroid build of a same module when
|
||||
possible by providing a class responsible to get astroid representation
|
||||
from various source and using a cache of built modules)
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
__docformat__ = "restructuredtext en"
|
||||
|
||||
import collections
|
||||
import imp
|
||||
import os
|
||||
from os.path import dirname, join, isdir, exists
|
||||
from warnings import warn
|
||||
import zipimport
|
||||
|
||||
from logilab.common.configuration import OptionsProviderMixIn
|
||||
|
||||
from astroid.exceptions import AstroidBuildingException
|
||||
from astroid import modutils
|
||||
|
||||
|
||||
def astroid_wrapper(func, modname):
|
||||
"""wrapper to give to AstroidManager.project_from_files"""
|
||||
print('parsing %s...' % modname)
|
||||
try:
|
||||
return func(modname)
|
||||
except AstroidBuildingException as exc:
|
||||
print(exc)
|
||||
except Exception as 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 AstroidManager(OptionsProviderMixIn):
|
||||
"""the astroid manager, responsible to build astroid from files
|
||||
or modules.
|
||||
|
||||
Use the Borg pattern.
|
||||
"""
|
||||
|
||||
name = 'astroid 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__ = AstroidManager.brain
|
||||
if not self.__dict__:
|
||||
OptionsProviderMixIn.__init__(self)
|
||||
self.load_defaults()
|
||||
# NOTE: cache entries are added by the [re]builder
|
||||
self.astroid_cache = {}
|
||||
self._mod_file_cache = {}
|
||||
self.transforms = collections.defaultdict(list)
|
||||
self._failed_import_hooks = []
|
||||
self.always_load_extensions = False
|
||||
self.optimize_ast = False
|
||||
self.extension_package_whitelist = set()
|
||||
|
||||
def ast_from_file(self, filepath, modname=None, fallback=True, source=False):
|
||||
"""given a module name, return the astroid object"""
|
||||
try:
|
||||
filepath = modutils.get_source_file(filepath, include_no_ext=True)
|
||||
source = True
|
||||
except modutils.NoSourceFile:
|
||||
pass
|
||||
if modname is None:
|
||||
try:
|
||||
modname = '.'.join(modutils.modpath_from_file(filepath))
|
||||
except ImportError:
|
||||
modname = filepath
|
||||
if modname in self.astroid_cache and self.astroid_cache[modname].file == filepath:
|
||||
return self.astroid_cache[modname]
|
||||
if source:
|
||||
from astroid.builder import AstroidBuilder
|
||||
return AstroidBuilder(self).file_build(filepath, modname)
|
||||
elif fallback and modname:
|
||||
return self.ast_from_module_name(modname)
|
||||
raise AstroidBuildingException('unable to get astroid for file %s' %
|
||||
filepath)
|
||||
|
||||
def _build_stub_module(self, modname):
|
||||
from astroid.builder import AstroidBuilder
|
||||
return AstroidBuilder(self).string_build('', modname)
|
||||
|
||||
def _can_load_extension(self, modname):
|
||||
if self.always_load_extensions:
|
||||
return True
|
||||
if modutils.is_standard_module(modname):
|
||||
return True
|
||||
parts = modname.split('.')
|
||||
return any(
|
||||
'.'.join(parts[:x]) in self.extension_package_whitelist
|
||||
for x in range(1, len(parts) + 1))
|
||||
|
||||
def ast_from_module_name(self, modname, context_file=None):
|
||||
"""given a module name, return the astroid object"""
|
||||
if modname in self.astroid_cache:
|
||||
return self.astroid_cache[modname]
|
||||
if modname == '__main__':
|
||||
return self._build_stub_module(modname)
|
||||
old_cwd = os.getcwd()
|
||||
if context_file:
|
||||
os.chdir(dirname(context_file))
|
||||
try:
|
||||
filepath, mp_type = self.file_from_module_name(modname, context_file)
|
||||
if mp_type == modutils.PY_ZIPMODULE:
|
||||
module = self.zip_import_data(filepath)
|
||||
if module is not None:
|
||||
return module
|
||||
elif mp_type in (imp.C_BUILTIN, imp.C_EXTENSION):
|
||||
if mp_type == imp.C_EXTENSION and not self._can_load_extension(modname):
|
||||
return self._build_stub_module(modname)
|
||||
try:
|
||||
module = modutils.load_module_from_name(modname)
|
||||
except Exception as ex:
|
||||
msg = 'Unable to load module %s (%s)' % (modname, ex)
|
||||
raise AstroidBuildingException(msg)
|
||||
return self.ast_from_module(module, modname)
|
||||
elif mp_type == imp.PY_COMPILED:
|
||||
raise AstroidBuildingException("Unable to load compiled module %s" % (modname,))
|
||||
if filepath is None:
|
||||
raise AstroidBuildingException("Unable to load module %s" % (modname,))
|
||||
return self.ast_from_file(filepath, modname, fallback=False)
|
||||
except AstroidBuildingException as e:
|
||||
for hook in self._failed_import_hooks:
|
||||
try:
|
||||
return hook(modname)
|
||||
except AstroidBuildingException:
|
||||
pass
|
||||
raise e
|
||||
finally:
|
||||
os.chdir(old_cwd)
|
||||
|
||||
def zip_import_data(self, filepath):
|
||||
if zipimport is None:
|
||||
return None
|
||||
from astroid.builder import AstroidBuilder
|
||||
builder = AstroidBuilder(self)
|
||||
for ext in ('.zip', '.egg'):
|
||||
try:
|
||||
eggpath, resource = filepath.rsplit(ext + os.path.sep, 1)
|
||||
except ValueError:
|
||||
continue
|
||||
try:
|
||||
importer = zipimport.zipimporter(eggpath + ext)
|
||||
zmodname = resource.replace(os.path.sep, '.')
|
||||
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 = modutils.file_info_from_modpath(
|
||||
modname.split('.'), context_file=contextfile)
|
||||
except ImportError as ex:
|
||||
msg = 'Unable to load module %s (%s)' % (modname, ex)
|
||||
value = AstroidBuildingException(msg)
|
||||
self._mod_file_cache[(modname, contextfile)] = value
|
||||
if isinstance(value, AstroidBuildingException):
|
||||
raise value
|
||||
return value
|
||||
|
||||
def ast_from_module(self, module, modname=None):
|
||||
"""given an imported module, return the astroid object"""
|
||||
modname = modname or module.__name__
|
||||
if modname in self.astroid_cache:
|
||||
return self.astroid_cache[modname]
|
||||
try:
|
||||
# some builtin modules don't have __file__ attribute
|
||||
filepath = module.__file__
|
||||
if modutils.is_python_source(filepath):
|
||||
return self.ast_from_file(filepath, modname)
|
||||
except AttributeError:
|
||||
pass
|
||||
from astroid.builder import AstroidBuilder
|
||||
return AstroidBuilder(self).module_build(module, modname)
|
||||
|
||||
def ast_from_class(self, klass, modname=None):
|
||||
"""get astroid for the given class"""
|
||||
if modname is None:
|
||||
try:
|
||||
modname = klass.__module__
|
||||
except AttributeError:
|
||||
raise AstroidBuildingException(
|
||||
'Unable to get module for class %s' % safe_repr(klass))
|
||||
modastroid = self.ast_from_module_name(modname)
|
||||
return modastroid.getattr(klass.__name__)[0] # XXX
|
||||
|
||||
|
||||
def infer_ast_from_something(self, obj, context=None):
|
||||
"""infer astroid 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 AstroidBuildingException(
|
||||
'Unable to get module for %s' % safe_repr(klass))
|
||||
except Exception as ex:
|
||||
raise AstroidBuildingException(
|
||||
'Unexpected error while retrieving module for %s: %s'
|
||||
% (safe_repr(klass), ex))
|
||||
try:
|
||||
name = klass.__name__
|
||||
except AttributeError:
|
||||
raise AstroidBuildingException(
|
||||
'Unable to get name for %s' % safe_repr(klass))
|
||||
except Exception as ex:
|
||||
raise AstroidBuildingException(
|
||||
'Unexpected error while retrieving name for %s: %s'
|
||||
% (safe_repr(klass), ex))
|
||||
# take care, on living object __module__ is regularly wrong :(
|
||||
modastroid = self.ast_from_module_name(modname)
|
||||
if klass is obj:
|
||||
for infered in modastroid.igetattr(name, context):
|
||||
yield infered
|
||||
else:
|
||||
for infered in modastroid.igetattr(name, context):
|
||||
yield infered.instanciate_class()
|
||||
|
||||
def project_from_files(self, files, func_wrapper=astroid_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 = modutils.file_from_modpath(something.split('.'))
|
||||
elif isdir(something):
|
||||
fpath = join(something, '__init__.py')
|
||||
else:
|
||||
fpath = something
|
||||
astroid = func_wrapper(self.ast_from_file, fpath)
|
||||
if astroid is None:
|
||||
continue
|
||||
# XXX why is first file defining the project.path ?
|
||||
project.path = project.path or astroid.file
|
||||
project.add_module(astroid)
|
||||
base_name = astroid.name
|
||||
# recurse in package except if __init__ was explicitly given
|
||||
if astroid.package and something.find('__init__') == -1:
|
||||
# recurse on others packages / modules if this is a package
|
||||
for fpath in modutils.get_module_files(dirname(astroid.file),
|
||||
black_list):
|
||||
astroid = func_wrapper(self.ast_from_file, fpath)
|
||||
if astroid is None or astroid.name == base_name:
|
||||
continue
|
||||
project.add_module(astroid)
|
||||
return project
|
||||
|
||||
def register_transform(self, node_class, transform, predicate=None):
|
||||
"""Register `transform(node)` function to be applied on the given
|
||||
Astroid's `node_class` if `predicate` is None or returns true
|
||||
when called with the node as argument.
|
||||
|
||||
The transform function may return a value which is then used to
|
||||
substitute the original node in the tree.
|
||||
"""
|
||||
self.transforms[node_class].append((transform, predicate))
|
||||
|
||||
def unregister_transform(self, node_class, transform, predicate=None):
|
||||
"""Unregister the given transform."""
|
||||
self.transforms[node_class].remove((transform, predicate))
|
||||
|
||||
def register_failed_import_hook(self, hook):
|
||||
"""Registers a hook to resolve imports that cannot be found otherwise.
|
||||
|
||||
`hook` must be a function that accepts a single argument `modname` which
|
||||
contains the name of the module or package that could not be imported.
|
||||
If `hook` can resolve the import, must return a node of type `astroid.Module`,
|
||||
otherwise, it must raise `AstroidBuildingException`.
|
||||
"""
|
||||
self._failed_import_hooks.append(hook)
|
||||
|
||||
def transform(self, node):
|
||||
"""Call matching transforms for the given node if any and return the
|
||||
transformed node.
|
||||
"""
|
||||
cls = node.__class__
|
||||
if cls not in self.transforms:
|
||||
# no transform registered for this class of node
|
||||
return node
|
||||
|
||||
transforms = self.transforms[cls]
|
||||
orig_node = node # copy the reference
|
||||
for transform_func, predicate in transforms:
|
||||
if predicate is None or predicate(node):
|
||||
ret = transform_func(node)
|
||||
# if the transformation function returns something, it's
|
||||
# expected to be a replacement for the node
|
||||
if ret is not None:
|
||||
if node is not orig_node:
|
||||
# node has already be modified by some previous
|
||||
# transformation, warn about it
|
||||
warn('node %s substituted multiple times' % node)
|
||||
node = ret
|
||||
return node
|
||||
|
||||
def cache_module(self, module):
|
||||
"""Cache a module if no module with the same name is known yet."""
|
||||
self.astroid_cache.setdefault(module.name, module)
|
||||
|
||||
def clear_cache(self, astroid_builtin=None):
|
||||
# XXX clear transforms
|
||||
self.astroid_cache.clear()
|
||||
# force bootstrap again, else we may ends up with cache inconsistency
|
||||
# between the manager and CONST_PROXY, making
|
||||
# unittest_lookup.LookupTC.test_builtin_lookup fail depending on the
|
||||
# test order
|
||||
import astroid.raw_building
|
||||
astroid.raw_building._astroid_bootstrapping(
|
||||
astroid_builtin=astroid_builtin)
|
||||
|
||||
|
||||
class Project(object):
|
||||
"""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))
|
||||
|
||||
|
||||
124
vim-plugins/python-mode/pymode/libs/astroid/mixins.py
Normal file
124
vim-plugins/python-mode/pymode/libs/astroid/mixins.py
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# 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 astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""This module contains some mixins for the different nodes.
|
||||
"""
|
||||
|
||||
from logilab.common.decorators import cachedproperty
|
||||
|
||||
from astroid.exceptions import (AstroidBuildingException, InferenceError,
|
||||
NotFoundError)
|
||||
|
||||
|
||||
class BlockRangeMixIn(object):
|
||||
"""override block range """
|
||||
|
||||
@cachedproperty
|
||||
def blockstart_tolineno(self):
|
||||
return self.lineno
|
||||
|
||||
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=None):
|
||||
"""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
|
||||
if modname is None:
|
||||
modname = self.modname
|
||||
# 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 AstroidBuildingException:
|
||||
raise InferenceError(modname)
|
||||
except SyntaxError as 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)
|
||||
|
||||
670
vim-plugins/python-mode/pymode/libs/astroid/modutils.py
Normal file
670
vim-plugins/python-mode/pymode/libs/astroid/modutils.py
Normal file
|
|
@ -0,0 +1,670 @@
|
|||
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
||||
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
||||
#
|
||||
# This file is part of astroid.
|
||||
#
|
||||
# astroid 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.
|
||||
#
|
||||
# astroid 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 astroid. 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_DIRS: set of str
|
||||
:var STD_LIB_DIRS: directories where standard modules are located
|
||||
|
||||
:type BUILTIN_MODULES: dict
|
||||
:var BUILTIN_MODULES: dictionary with builtin module names has key
|
||||
"""
|
||||
from __future__ import with_statement
|
||||
|
||||
__docformat__ = "restructuredtext en"
|
||||
|
||||
import imp
|
||||
import os
|
||||
import sys
|
||||
from distutils.sysconfig import get_python_lib
|
||||
from distutils.errors import DistutilsPlatformError
|
||||
import zipimport
|
||||
|
||||
try:
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
pkg_resources = None
|
||||
|
||||
from logilab.common import _handle_blacklist
|
||||
|
||||
PY_ZIPMODULE = object()
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
PY_SOURCE_EXTS = ('py', 'pyw')
|
||||
PY_COMPILED_EXTS = ('dll', 'pyd')
|
||||
else:
|
||||
PY_SOURCE_EXTS = ('py',)
|
||||
PY_COMPILED_EXTS = ('so',)
|
||||
|
||||
# Notes about STD_LIB_DIRS
|
||||
# Consider arch-specific installation for STD_LIB_DIRS 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>`_
|
||||
try:
|
||||
# The explicit sys.prefix is to work around a patch in virtualenv that
|
||||
# replaces the 'real' sys.prefix (i.e. the location of the binary)
|
||||
# with the prefix from which the virtualenv was created. This throws
|
||||
# off the detection logic for standard library modules, thus the
|
||||
# workaround.
|
||||
STD_LIB_DIRS = set([
|
||||
get_python_lib(standard_lib=True, prefix=sys.prefix),
|
||||
# Take care of installations where exec_prefix != prefix.
|
||||
get_python_lib(standard_lib=True, prefix=sys.exec_prefix),
|
||||
get_python_lib(standard_lib=True)])
|
||||
if os.name == 'nt':
|
||||
STD_LIB_DIRS.add(os.path.join(sys.prefix, 'dlls'))
|
||||
try:
|
||||
# real_prefix is defined when running inside virtualenv.
|
||||
STD_LIB_DIRS.add(os.path.join(sys.real_prefix, 'dlls'))
|
||||
except AttributeError:
|
||||
pass
|
||||
# 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_DIRS = set()
|
||||
|
||||
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
|
||||
"""
|
||||
|
||||
def _normalize_path(path):
|
||||
return os.path.normcase(os.path.abspath(path))
|
||||
|
||||
|
||||
_NORM_PATH_CACHE = {}
|
||||
|
||||
def _cache_normalize_path(path):
|
||||
"""abspath with caching"""
|
||||
# _module_file calls abspath on every path in sys.path every time it's
|
||||
# called; on a larger codebase this easily adds up to half a second just
|
||||
# assembling path components. This cache alleviates that.
|
||||
try:
|
||||
return _NORM_PATH_CACHE[path]
|
||||
except KeyError:
|
||||
if not path: # don't cache result for ''
|
||||
return _normalize_path(path)
|
||||
result = _NORM_PATH_CACHE[path] = _normalize_path(path)
|
||||
return result
|
||||
|
||||
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 = imp.find_module(part, path)
|
||||
module = imp.load_module(curname, mp_file, mp_filename, mp_desc)
|
||||
# mp_file still needs to be closed.
|
||||
if mp_file:
|
||||
mp_file.close()
|
||||
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 = [os.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 = os.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 = os.path.splitext(os.path.abspath(filename))[0]
|
||||
if extrapath is not None:
|
||||
for path_ in extrapath:
|
||||
path = os.path.abspath(path_)
|
||||
if path and os.path.normcase(base[:len(path)]) == os.path.normcase(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 = _cache_normalize_path(path)
|
||||
if path and os.path.normcase(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):
|
||||
return file_info_from_modpath(modpath, path, context_file)[0]
|
||||
|
||||
def file_info_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, import type)
|
||||
: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 = os.path.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__, imp.PY_SOURCE
|
||||
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 = os.path.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_module_files(src_directory, 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 = os.path.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 = os.path.splitext(os.path.abspath(filename))
|
||||
for ext in PY_SOURCE_EXTS:
|
||||
source_path = '%s.%s' % (base, ext)
|
||||
if os.path.exists(source_path):
|
||||
return source_path
|
||||
if include_no_ext and not orig_ext and os.path.exists(base):
|
||||
return base
|
||||
raise NoSourceFile(filename)
|
||||
|
||||
|
||||
def is_python_source(filename):
|
||||
"""
|
||||
rtype: bool
|
||||
return: True if the filename is a python source file
|
||||
"""
|
||||
return os.path.splitext(filename)[1][1:] in PY_SOURCE_EXTS
|
||||
|
||||
|
||||
def is_standard_module(modname, std_path=None):
|
||||
"""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:
|
||||
# import failed, i'm probably not so wrong by supposing it's
|
||||
# not standard...
|
||||
return False
|
||||
# modules which are not living in a file are considered standard
|
||||
# (sys and __builtin__ for instance)
|
||||
if filename is None:
|
||||
return True
|
||||
filename = _normalize_path(filename)
|
||||
if filename.startswith(_cache_normalize_path(EXT_LIB_DIR)):
|
||||
return False
|
||||
if std_path is None:
|
||||
std_path = STD_LIB_DIRS
|
||||
for path in std_path:
|
||||
if filename.startswith(_cache_normalize_path(path)):
|
||||
return True
|
||||
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 os.path.isdir(from_file):
|
||||
from_file = os.path.dirname(from_file)
|
||||
if from_file in sys.path:
|
||||
return False
|
||||
try:
|
||||
stream, _, _ = imp.find_module(modname.split('.')[0], [from_file])
|
||||
|
||||
# Close the stream to avoid ResourceWarnings.
|
||||
if stream:
|
||||
stream.close()
|
||||
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 == imp.PY_COMPILED:
|
||||
try:
|
||||
return get_source_file(mp_filename), imp.PY_SOURCE
|
||||
except NoSourceFile:
|
||||
return mp_filename, imp.PY_COMPILED
|
||||
elif mtype == imp.C_BUILTIN:
|
||||
# integrated builtin module
|
||||
return None, imp.C_BUILTIN
|
||||
elif mtype == imp.PKG_DIRECTORY:
|
||||
mp_filename = _has_init(mp_filename)
|
||||
mtype = imp.PY_SOURCE
|
||||
return mp_filename, mtype
|
||||
|
||||
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(os.path.sep.join(modpath)):
|
||||
raise ImportError('No module named %s in %s/%s' % (
|
||||
'.'.join(modpath[1:]), filepath, modpath))
|
||||
return PY_ZIPMODULE, os.path.abspath(filepath) + os.path.sep + os.path.sep.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
|
||||
# pkg_resources support (aka setuptools namespace packages)
|
||||
if (pkg_resources is not None
|
||||
and modpath[0] in pkg_resources._namespace_packages
|
||||
and modpath[0] in sys.modules
|
||||
and len(modpath) > 1):
|
||||
# setuptools has added into sys.modules a module object with proper
|
||||
# __path__, get back information from there
|
||||
module = sys.modules[modpath.pop(0)]
|
||||
path = module.__path__
|
||||
imported = []
|
||||
while modpath:
|
||||
modname = modpath[0]
|
||||
# take care to changes in find_module implementation wrt builtin modules
|
||||
#
|
||||
# Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23)
|
||||
# >>> imp.find_module('posix')
|
||||
# (None, 'posix', ('', '', 6))
|
||||
#
|
||||
# Python 3.3.1 (default, Apr 26 2013, 12:08:46)
|
||||
# >>> imp.find_module('posix')
|
||||
# (None, None, ('', '', 6))
|
||||
try:
|
||||
stream, mp_filename, mp_desc = imp.find_module(modname, path)
|
||||
except ImportError:
|
||||
if checkeggs:
|
||||
return _search_zip(modpath, pic)[:2]
|
||||
raise
|
||||
else:
|
||||
# Don't forget to close the stream to avoid
|
||||
# spurious ResourceWarnings.
|
||||
if stream:
|
||||
stream.close()
|
||||
|
||||
if checkeggs and mp_filename:
|
||||
fullabspath = [_cache_normalize_path(x) for x in _path]
|
||||
try:
|
||||
pathindex = fullabspath.index(os.path.dirname(_normalize_path(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 != imp.PKG_DIRECTORY:
|
||||
raise ImportError('No module %s in %s' % ('.'.join(modpath),
|
||||
'.'.join(imported)))
|
||||
# XXX guess if package is using pkgutil.extend_path by looking for
|
||||
# those keywords in the first four Kbytes
|
||||
try:
|
||||
with open(os.path.join(mp_filename, '__init__.py'), 'rb') as stream:
|
||||
data = stream.read(4096)
|
||||
except IOError:
|
||||
path = [mp_filename]
|
||||
else:
|
||||
if b'pkgutil' in data and b'extend_path' in data:
|
||||
# extend_path is called, search sys.path for module/packages
|
||||
# of this name see pkgutil.extend_path documentation
|
||||
path = [os.path.join(p, *imported) for p in sys.path
|
||||
if os.path.isdir(os.path.join(p, *imported))]
|
||||
else:
|
||||
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 = os.path.join(directory, '__init__')
|
||||
for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'):
|
||||
if os.path.exists(mod_or_pack + '.' + ext):
|
||||
return mod_or_pack + '.' + ext
|
||||
return None
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue