diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 3b087e6f..613addba 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,6 +1,6 @@ [bumpversion] commit = True -current_version = 0.9.2 +current_version = 0.13.0 files = plugin/pymode.vim tag = True tag_name = {new_version} @@ -8,4 +8,3 @@ tag_name = {new_version} [bumpversion:file:doc/pymode.txt] search = Version: {current_version} replace = Version: {new_version} - diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..8847bdf2 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +liberapay: diraol diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000..be619481 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 150 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 21 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: inactive +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: > + Closed due to inactivity. diff --git a/.github/workflows/test_pymode.yml b/.github/workflows/test_pymode.yml new file mode 100644 index 00000000..332dcdad --- /dev/null +++ b/.github/workflows/test_pymode.yml @@ -0,0 +1,71 @@ +name: Testing python-mode + +on: [push] + +jobs: + test-python-3_8: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install dependencies + run: | + sudo apt update + export PYTHON_CONFIGURE_OPTS="--enable-shared" + sudo apt install -yqq libncurses5-dev libgtk2.0-dev libatk1.0-dev libcairo2-dev libx11-dev libxpm-dev libxt-dev python3-dev lua5.2 liblua5.2-dev libperl-dev git + sudo apt remove --purge -yqq vim vim-runtime gvim + - name: build and install vim from source + working-directory: /tmp + run: | + export PYTHON_CONFIGURE_OPTS="--enable-shared" + git clone https://github.com/vim/vim.git + cd vim + ./configure --with-features=huge --enable-multibyte --enable-python3interp=yes --with-python3-config-dir=/usr/lib/python3.8/config-3.8m-x86_64-linux-gnu --enable-perlinterp=yes --enable-luainterp=yes --enable-cscope --prefix=/usr/local + sudo make && sudo make install + - name: Install python-mode + run: | + export PYMODE_DIR="${HOME}/work/python-mode/python-mode" + mkdir -p ${HOME}/.vim/pack/foo/start/ + ln -s ${PYMODE_DIR} ${HOME}/.vim/pack/foo/start/python-mode + cp ${PYMODE_DIR}/tests/utils/pymoderc ${HOME}/.pymoderc + cp ${PYMODE_DIR}/tests/utils/vimrc ${HOME}/.vimrc + touch ${HOME}/.vimrc.before ${HOME}/.vimrc.after + - name: Run python-mode test script + run: | + alias python=python3 + cd ${HOME}/work/python-mode/python-mode + git submodule update --init --recursive + git submodule sync + bash tests/test.sh + test-python-3_9: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install dependencies + run: | + sudo apt update + export PYTHON_CONFIGURE_OPTS="--enable-shared" + sudo apt install -yqq libncurses5-dev libgtk2.0-dev libatk1.0-dev libcairo2-dev libx11-dev libxpm-dev libxt-dev python3-dev lua5.2 liblua5.2-dev libperl-dev git + sudo apt remove --purge -yqq vim vim-runtime gvim + - name: build and install vim from source + working-directory: /tmp + run: | + export PYTHON_CONFIGURE_OPTS="--enable-shared" + git clone https://github.com/vim/vim.git + cd vim + ./configure --with-features=huge --enable-multibyte --enable-python3interp=yes --with-python3-config-dir=/usr/lib/python3.9/config-3.9m-x86_64-linux-gnu --enable-perlinterp=yes --enable-luainterp=yes --enable-cscope --prefix=/usr/local + sudo make && sudo make install + - name: Install python-mode + run: | + export PYMODE_DIR="${HOME}/work/python-mode/python-mode" + mkdir -p ${HOME}/.vim/pack/foo/start/ + ln -s ${PYMODE_DIR} ${HOME}/.vim/pack/foo/start/python-mode + cp ${PYMODE_DIR}/tests/utils/pymoderc ${HOME}/.pymoderc + cp ${PYMODE_DIR}/tests/utils/vimrc ${HOME}/.vimrc + touch ${HOME}/.vimrc.before ${HOME}/.vimrc.after + - name: Run python-mode test script + run: | + alias python=python3 + cd ${HOME}/work/python-mode/python-mode + git submodule update --init --recursive + git submodule sync + bash tests/test.sh diff --git a/.gitignore b/.gitignore index f5674a78..40ca63ba 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ test.py todo.txt vendor vim.py +vim_session_*.vim +__*/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..4874edc5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,50 @@ +[submodule "submodules/autopep8"] + path = submodules/autopep8 + url = https://github.com/hhatto/autopep8 + ignore = dirty + shallow = true +[submodule "submodules/pycodestyle"] + path = submodules/pycodestyle + url = https://github.com/PyCQA/pycodestyle + ignore = dirty + shallow = true +[submodule "submodules/pydocstyle"] + path = submodules/pydocstyle + url = https://github.com/PyCQA/pydocstyle + ignore = dirty + shallow = true +[submodule "submodules/mccabe"] + path = submodules/mccabe + url = https://github.com/PyCQA/mccabe + ignore = dirty + shallow = true +[submodule "submodules/pyflakes"] + path = submodules/pyflakes + url = https://github.com/PyCQA/pyflakes + ignore = dirty + shallow = true +[submodule "submodules/snowball_py"] + path = submodules/snowball_py + url = https://github.com/diraol/snowball_py + ignore = dirty + branch = develop + shallow = true +[submodule "submodules/pylint"] + path = submodules/pylint + url = https://github.com/PyCQA/pylint + shallow = true +[submodule "submodules/rope"] + path = submodules/rope + url = https://github.com/python-rope/rope + shallow = true +[submodule "submodules/astroid"] + path = submodules/astroid + url = https://github.com/PyCQA/astroid + shallow = true +[submodule "submodules/pylama"] + path = submodules/pylama + url = https://github.com/klen/pylama + shallow = true +[submodule "submodules/toml"] + path = submodules/toml + url = https://github.com/uiri/toml.git diff --git a/.ruby-gemset b/.ruby-gemset deleted file mode 100644 index 5ded393e..00000000 --- a/.ruby-gemset +++ /dev/null @@ -1 +0,0 @@ -vim-flavor diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index 67b8bc0d..00000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -ruby-1.9.3 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e10ed9f1..00000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: ruby -python: "2.7" -rvm: - - 1.9.3 -script: - - make travis diff --git a/AUTHORS b/AUTHORS index cc3de277..6c2c6b95 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,35 +1,48 @@ -Maintainers: +Author: * Kirill Klenov -* Bryce Guinta (https://github.com/brycepg) +Maintainers: + +* Diego Rabatone Oliveira (https://github.com/diraol); Contributors: * Alvin Francis (http://github.com/alvinfrancis); -* Andriy Kohut (https://github.com/andriykohut) +* Amir Eldor (https://github.com/amireldor); +* Andriy Kohut (https://github.com/andriykohut); * Anler Hp (http://github.com/ikame); * Anton Parkhomenko (http://github.com/chuwy); * Ashley Hewson (http://github.com/ashleyh); +* Ben Davis (https://github.com/bendavis78); * Benjamin Ruston (http://github.com/bruston); +* Boatx (https://github.com/boatx); * Boris Filippov (http://github.com/frenzykryger); -* Brad Mease (http://github.com/bmease) -* Brendan Maguire (https://github.com/brendanmaguire) -* Daniel Hahler (http://github.com/blueyed) +* Brad Belyeu (https://github.com/bbelyeu); +* Brad Mease (http://github.com/bmease); +* Brendan Maguire (https://github.com/brendanmaguire); +* Bryce Guinta (https://github.com/brycepg); +* 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); +* Felipe M. Vieira (https://github.com/fmv1992) +* Filip Poboril (https://github.com/fpob); * Florent Xicluna (http://github.com/florentx); * Fredrik Henrysson (http://github.com/fhenrysson); +* fwuzju (https://github.com/fwuzju); +* Grzegorz Janik (http://github.com/glujan); * Igor Guerrero (http://github.com/igorgue); -* Jacob Niehus (https://github.com/wilywampa) -* Jason Harvey (http://github.com/alienth) -* Jay Rainey (https://github.com/jawrainey) +* 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); +* lee (https://github.com/loyalpartner); +* Lie Ryan (https://github.com/lieryan/); * Lowe Thiderman (http://github.com/thiderman); * Martin Brochhaus (http://github.com/mbrochh); * Matt Dodge (https://github.com/mattdodge); @@ -39,26 +52,26 @@ Contributors: * Mohammed (http://github.com/mbadran); * Naoya Inada (http://github.com/naoina); * Nate Zhang (https://github.com/natezhang93); +* nixon (https://github.com/nixon); * Paweł Korzeniewski (https://github.com/korzeniewskipl); * Pedro Algarvio (http://github.com/s0undt3ch); * Phillip Cloud (http://github.com/cpcloud); -* Piet Delport (http://github.com/pjdelport); +* Pi 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); +* sphaugh (https://github.com/sphaugh); * Steve Losh (http://github.com/sjl); * Tommy Allen (https://github.com/tweekmonster); * Tony Narlock (https://github.com/tony); +* tramchamploo (https://github.com/tramchamploo); * 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); +* Yury A. Kartynnik (https://github.com/kartynnik); +* Xiangyu Xu (https://github.com/bkbncn); +* Zach Himsel (https://github.com/zhimsel); diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..001a9194 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,411 @@ +# Changelog + +## TODO + +- Move changelog rst syntax to markdown +- `pymode_rope`: check disables +- Remove supoort for python 2. From 0.11.0 on we will focus on supporting + python 3+ (probably 3.5+). +- Inspect why files starting with the following code do not get loaded: + + ```python + def main(): + pass + + if __name__ == '__main__': + main() + ``` + +## 2019-05-11 0.10.0 + +After many changes, including moving most of our dependencies from copied +source code to submodules, and lot's of problems maintaining Python 2 and +Python 3 support, this (0.10.x) is the last version of python-mode that will +support Python 2. Some patches may be done in order to fix issues related to +Python 2 or some backward compatible changes that can be applied. + +## 2017-07-xxx 0.9.5 + +- pylama: migrated to submodule + +## 2017-07-11 0.9.4 + +- pylama: fixed erratic behavior of skip option causing unintended + skipping of lint checkers + +- PEP257 requires `snowbalstemmer`: added as submodule + +- Fixed handling of `g:pymode_lint_ignore` and `g:pymode_lint_select`: from + strings to list + +- Migrated modules from pymode/libs to + [submodules/](https://github.com/fmv1992/python-mode/tree/develop/submodules) + + - Rationale: no need to single handedly update each module; + removes burden from developers + +- Improved folding accuracy + + - Improved nested definitions folding + - Improved block delimiting + +## (changelog poorly maintained) 0.8.2 + +- 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 `` 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_` -> `pymode_rope_`) +- 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 +- `r a` for RopeAutoImport + +## 2011-10-12 0.1.4 + +- Add default pylint configuration + +## 2011-10-12 0.1.3 + +- Fix pylint and update docs + +## 2011-10-11 0.1.2 + +- First public release diff --git a/Changelog.rst b/Changelog.rst deleted file mode 100644 index e396eb69..00000000 --- a/Changelog.rst +++ /dev/null @@ -1,356 +0,0 @@ -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 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_ -> pymode_rope_) -* 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 -* "r a" for RopeAutoImport - -## 2011-10-12 0.1.4 -------------------- -* Add default pylint configuration - -## 2011-10-12 0.1.3 -------------------- -* Fix pylint and update docs - -## 2011-10-11 0.1.2 -------------------- -* First public release diff --git a/Gemfile b/Gemfile deleted file mode 100644 index a87f4e1a..00000000 --- a/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'https://rubygems.org' - -gem 'vim-flavor', '~> 1.1' diff --git a/Makefile b/Makefile deleted file mode 100644 index dac3a287..00000000 --- a/Makefile +++ /dev/null @@ -1,95 +0,0 @@ -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 - @pip install --upgrade --force-reinstall --target=$(LIBS) pydocstyle - @pip install --upgrade --force-reinstall --target=$(LIBS) pycodestyle - @pip install --upgrade --force-reinstall --target=$(LIBS) pyflakes - @pip install --upgrade --force-reinstall --target=$(LIBS) mccabe - @find $(LIBS)/*.dist-info | xargs rm -rf - -.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 " -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 diff --git a/README.rst b/README.rst deleted file mode 100644 index 0706f0c6..00000000 --- a/README.rst +++ /dev/null @@ -1,367 +0,0 @@ -|logo| Python-mode, Python in VIM -################################# - -.. image:: https://travis-ci.org/python-mode/python-mode.png?branch=develop - :target: https://travis-ci.org/python-mode/python-mode - ------ - -*The project needs contributors* - -** Python-mode Slack Channel is here: https://python-mode.herokuapp.com/ ** - ------ - -| -| Src: https://github.com/python-mode/python-mode -| Homepage: https://klen.github.io/python-mode/ -| Docs: https://github.com/python-mode/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 (``r``) -- Add/remove breakpoints (``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_) -- Strong code completion (rope_) -- Go to definition (``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/python-mode/python-mode.git - -- Enable `pathogen `_ - in your ``~/.vimrc``: :: - - " Pathogen load - filetype off - - call pathogen#infect() - call pathogen#helptags() - - filetype plugin indent on - syntax on - - -Manually --------- -:: - - % git clone https://github.com/python-mode/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 /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 `_ -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 = "" - - " Override run current python file key shortcut to Ctrl-Shift-e - let g:pymode_run_bind = "" - - " Override view python doc key shortcut to Ctrl-Shift-d - let g:pymode_doc_bind = "" - - -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/python-mode/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/python-mode/python-mode - -Please make a pull request to `development` branch and add yourself to -`AUTHORS`. - -Source Links -=================== -- `doc/pymode.txt - `__ - -- ``:help pymode`` -- `plugin/pymode.vim - `__ - -- python-mode VIM plugin -- `syntax/python.vim - `__ - -- python-mode ``python.vim`` VIM syntax -- `syntax/pyrex.vim - `__ - -- ``pyrex.vim`` VIM syntax (pyrex, Cython) -- `t/ - `__ - -- ``*.vim`` more python-mode VIM configuration -- `pymode/ - `__ - -- ``*.py`` -- python-mode Python module -- `pymode/libs/ - `__ - -- ``*.py`` -- `Python Libraries <#python-libraries>`__ - - -Python Libraries ------------------- -Vendored Python modules are located -mostly in -`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/python-mode/python-mode/develop/logo.png diff --git a/Rakefile b/Rakefile deleted file mode 100644 index 63a3a361..00000000 --- a/Rakefile +++ /dev/null @@ -1,11 +0,0 @@ -#!/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 diff --git a/after/ftplugin/python.vim b/after/ftplugin/python.vim index 0dec7542..0fdd01a3 100644 --- a/after/ftplugin/python.vim +++ b/after/ftplugin/python.vim @@ -11,36 +11,36 @@ if g:pymode_motion finish endif - nnoremap ]] :call pymode#motion#move('v^(classdef)s', '') - nnoremap [[ :call pymode#motion#move('v^(classdef)s', 'b') - nnoremap ]C :call pymode#motion#move('v^(classdef)s', '') - nnoremap [C :call pymode#motion#move('v^(classdef)s', 'b') - nnoremap ]M :call pymode#motion#move('^s*defs', '') - nnoremap [M :call pymode#motion#move('^s*defs', 'b') - - onoremap ]] :call pymode#motion#move('v^(classdef)s', '') - onoremap [[ :call pymode#motion#move('v^(classdef)s', 'b') - onoremap ]C :call pymode#motion#move('v^(classdef)s', '') - onoremap [C :call pymode#motion#move('v^(classdef)s', 'b') - onoremap ]M :call pymode#motion#move('^s*defs', '') - onoremap [M :call pymode#motion#move('^s*defs', 'b') - - vnoremap ]] :call pymode#motion#vmove('v^(classdef)s', '') - vnoremap [[ :call pymode#motion#vmove('v^(classdef)s', 'b') - vnoremap ]M :call pymode#motion#vmove('^s*defs', '') - vnoremap [M :call pymode#motion#vmove('^s*defs', 'b') - - onoremap C :call pymode#motion#select('^s*classs', 0) - onoremap aC :call pymode#motion#select('^s*classs', 0) - onoremap iC :call pymode#motion#select('^s*classs', 1) - vnoremap aC :call pymode#motion#select('^s*classs', 0) - vnoremap iC :call pymode#motion#select('^s*classs', 1) - - onoremap M :call pymode#motion#select('^s*defs', 0) - onoremap aM :call pymode#motion#select('^s*defs', 0) - onoremap iM :call pymode#motion#select('^s*defs', 1) - vnoremap aM :call pymode#motion#select('^s*defs', 0) - vnoremap iM :call pymode#motion#select('^s*defs', 1) + nnoremap ]] :call pymode#motion#move('^(class%(asyncs+)=def)s', '') + nnoremap [[ :call pymode#motion#move('^(class%(asyncs+)=def)s', 'b') + nnoremap ]C :call pymode#motion#move('^(class%(asyncs+)=def)s', '') + nnoremap [C :call pymode#motion#move('^(class%(asyncs+)=def)s', 'b') + nnoremap ]M :call pymode#motion#move('^s*(asyncs+)=defs', '') + nnoremap [M :call pymode#motion#move('^s*(asyncs+)=defs', 'b') + + onoremap ]] :call pymode#motion#move('^(class%(asyncs+)=def)s', '') + onoremap [[ :call pymode#motion#move('^(class%(asyncs+)=def)s', 'b') + onoremap ]C :call pymode#motion#move('^(class%(asyncs+)=def)s', '') + onoremap [C :call pymode#motion#move('^(class%(asyncs+)=def)s', 'b') + onoremap ]M :call pymode#motion#move('^s*(asyncs+)=defs', '') + onoremap [M :call pymode#motion#move('^s*(asyncs+)=defs', 'b') + + vnoremap ]] :call pymode#motion#vmove('^(class%(asyncs+)=def)s', '') + vnoremap [[ :call pymode#motion#vmove('^(class%(asyncs+)=def)s', 'b') + vnoremap ]M :call pymode#motion#vmove('^s*(asyncs+)=defs', '') + vnoremap [M :call pymode#motion#vmove('^s*(asyncs+)=defs', 'b') + + onoremap C :call pymode#motion#select_c('^s*classs', 0) + onoremap aC :call pymode#motion#select_c('^s*classs', 0) + onoremap iC :call pymode#motion#select_c('^s*classs', 1) + vnoremap aC :call pymode#motion#select_c('^s*classs', 0) + vnoremap iC :call pymode#motion#select_c('^s*classs', 1) + + onoremap M :call pymode#motion#select('^s*(asyncs+)=@', '^s*(asyncs+)=defs', 0) + onoremap aM :call pymode#motion#select('^s*(asyncs+)=@', '^s*(asyncs+)=defs', 0) + onoremap iM :call pymode#motion#select('^s*(asyncs+)=@', '^s*(asyncs+)=defs', 1) + vnoremap aM :call pymode#motion#select('^s*(asyncs+)=@', '^s*(asyncs+)=defs', 0) + vnoremap iM :call pymode#motion#select('^s*(asyncs+)=@', '^s*(asyncs+)=defs', 1) endif @@ -53,6 +53,6 @@ if g:pymode_rope && g:pymode_rope_completion if tolower(g:pymode_rope_completion_bind) == '' exe "inoremap =pymode#rope#complete(0)" endif - end + endif -end +endif diff --git a/autoload/pymode.vim b/autoload/pymode.vim index 723af9b5..b637289a 100644 --- a/autoload/pymode.vim +++ b/autoload/pymode.vim @@ -62,7 +62,7 @@ endfunction "}}} " DESC: Open temp buffer. fun! pymode#tempbuffer_open(name) "{{{ pclose - exe "botright 8new " . a:name + exe g:pymode_preview_position . " " . g:pymode_preview_height . "new " . a:name setlocal buftype=nofile bufhidden=delete noswapfile nowrap previewwindow redraw endfunction "}}} @@ -71,12 +71,11 @@ endfunction "}}} fun! pymode#trim_whitespaces() "{{{ if g:pymode_trim_whitespaces let cursor_pos = getpos('.') - silent! %s/\s\+$// + silent! %s/\s\+$//e call setpos('.', cursor_pos) endif endfunction "}}} - fun! pymode#save() "{{{ if &modifiable && &modified try @@ -120,9 +119,25 @@ fun! pymode#buffer_post_write() "{{{ endfunction "}}} fun! pymode#debug(msg) "{{{ + " Pymode's debug function. + " Should be called by other pymode's functions to report outputs. See + " the function PymodeDebugFolding for example. + " TODO: why echom here creates a problem? + " echom '' . a:msg + '|||||||||||' + + let l:info_separator = repeat('-', 79) + if g:pymode_debug - let g:pymode_debug += 1 - echom string(g:pymode_debug) . ': ' . string(a:msg) + if ! exists('g:pymode_debug_counter') + let g:pymode_debug_counter = 0 + endif + let g:pymode_debug_counter += 1 + " NOTE: Print a separator for every message except folding ones (since + " they could be many). + if a:msg !~ 'has folding:' + echom l:info_separator + endif + echom '' . 'pymode debug msg ' . g:pymode_debug_counter . ': ' . a:msg endif endfunction "}}} diff --git a/autoload/pymode/breakpoint.vim b/autoload/pymode/breakpoint.vim index c3189aad..98639b57 100644 --- a/autoload/pymode/breakpoint.vim +++ b/autoload/pymode/breakpoint.vim @@ -1,35 +1,34 @@ fun! pymode#breakpoint#init() "{{{ - if !g:pymode_breakpoint + " If breakpoints are either disabled or already defined do nothing. + if ! g:pymode_breakpoint || g:pymode_breakpoint_cmd != '' 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 + " Else go for a 'smart scan' of the defaults. + else PymodePython << EOF -from imp import find_module +from importlib.util import find_spec -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 +if sys.version_info >= (3, 7): + vim.command('let g:pymode_breakpoint_cmd = "breakpoint()"') +else: + for module in ('wdb', 'pudb', 'ipdb', 'pdb'): + if find_spec(module): + vim.command('let g:pymode_breakpoint_cmd = "import %s; %s.set_trace() # XXX BREAKPOINT"' % (module, module)) + break EOF + endif endfunction "}}} fun! pymode#breakpoint#operate(lnum) "{{{ + if g:pymode_breakpoint_cmd == '' + echoerr("g:pymode_breakpoint_cmd is empty") + return -1 + endif let line = getline(a:lnum) if strridx(line, g:pymode_breakpoint_cmd) != -1 normal dd diff --git a/autoload/pymode/debug.vim b/autoload/pymode/debug.vim new file mode 100644 index 00000000..2be5149c --- /dev/null +++ b/autoload/pymode/debug.vim @@ -0,0 +1,67 @@ +" Set debugging functions. + +" DESC: Get debug information about pymode problem. +fun! pymode#debug#sysinfo() "{{{ + " OS info. {{{ + let l:os_name = "Unknown" + if has('win16') || has('win32') || has('win64') + let l:os_name = "Windows" + else + let l:os_name = substitute(system('uname'), "\n", "", "") + endif + call pymode#debug("Operating system: " . l:os_name) + " }}} + " Loaded scripts info. {{{ + call pymode#debug("Scriptnames:") + let l:scriptnames_var = execute('scriptnames') + " }}} + " Variables info. {{{ + " Drop verbose file temporarily to prevent the 'let' from showing up. + let l:tmp = &verbosefile + set verbosefile= + let l:all_variables = filter( + \ split(execute('let', 'silent!'), '\n'), + \ 'v:val =~ "^pymode"') + let &verbosefile = l:tmp + " NOTE: echom does not display multiline messages. Thus a for loop is + " needed. + call pymode#debug("Pymode variables:") + for pymodevar in sort(l:all_variables) + echom pymodevar + endfor + " }}} + " Git commit info. {{{ + " Find in the scriptnames the first occurence of 'python-mode'. Then parse + " the result outputting its path. This is in turn fed into the git command. + call pymode#debug("Git commit: ") + let l:pymode_folder = substitute( + \ filter( + \ split(l:scriptnames_var, '\n'), + \ 'v:val =~ "/python-mode/"')[0], + \ '\(^\s\+[0-9]\+:\s\+\)\([/~].*python-mode\/\)\(.*\)', + \ '\2', + \ '') + let l:git_head_sha1 = system('git -C ' . expand(l:pymode_folder). ' rev-parse HEAD ' ) + echom join(filter(split(l:git_head_sha1, '\zs'), 'v:val =~? "[0-9A-Fa-f]"'), '') + " }}} + " Git submodules status. {{{ + call pymode#debug("Git submodule status:") + let l:git_submodule_status = system('git -C ' . expand(l:pymode_folder). ' submodule status') + for submodule in split(l:git_submodule_status, '\n') + echom submodule + endfor + " }}} + call pymode#debug("End of pymode#debug#sysinfo") +endfunction "}}} + +" DESC: Define debug folding function. +function! pymode#debug#foldingexpr(lnum) "{{{ + let l:get_folding_result = pymode#folding#foldcase(a:lnum) + " NOTE: the 'has folding:' expression is special in the pymode#debug. + call pymode#debug( + \ 'line ' . a:lnum + \ . ' has folding: ' . l:get_folding_result['foldlevel'] + \ . ' with foldcase ' . l:get_folding_result['foldcase']) + return l:get_folding_result['foldlevel'] +endfunction +" }}} diff --git a/autoload/pymode/doc.vim b/autoload/pymode/doc.vim index b89eb0e7..a7a753c5 100644 --- a/autoload/pymode/doc.vim +++ b/autoload/pymode/doc.vim @@ -32,6 +32,9 @@ fun! pymode#doc#show(word) "{{{ if g:pymode_doc_vertical wincmd L endif + + normal gg + wincmd p endfunction "}}} diff --git a/autoload/pymode/folding.vim b/autoload/pymode/folding.vim index 3b29aebb..9cbb64d3 100644 --- a/autoload/pymode/folding.vim +++ b/autoload/pymode/folding.vim @@ -1,5 +1,3 @@ -" 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. @@ -8,26 +6,25 @@ 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*[uUrR]\=\%("""\|''''''\)' -let s:doc_end_regex = '\%("""\|''''''\)\s*$' +let s:decorator_regex = '^\s*@\(author:\)\@!' +let s:docstring_line_regex = '^\s*[uUrR]\=\("""\|''''''\).\+\1\s*$' +let s:docstring_begin_regex = '^\s*[uUrR]\=\%("""\|''''''\).*\S' +let s:docstring_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*[uUrR]\=\("""\|''''''\).\+\1\s*$' +let s:docstring_general_regex = '\%("""\|''''''\)' 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 + while getline(fs) !~ s:def_regex && getline(fs) !~ s:docstring_begin_regex let fs = nextnonblank(fs + 1) endwhile - if getline(fs) =~ s:doc_end_regex && getline(fs) =~ s:doc_begin_regex + if getline(fs) =~ s:docstring_end_regex && getline(fs) =~ s:docstring_begin_regex let fs = nextnonblank(fs + 1) endif let line = getline(fs) @@ -49,6 +46,19 @@ endfunction "}}} fun! pymode#folding#expr(lnum) "{{{ + let l:return_value = pymode#folding#foldcase(a:lnum)['foldlevel'] + + return l:return_value + +endfunction "}}} + +fun! pymode#folding#foldcase(lnum) "{{{ + " Return a dictionary with a brief description of the foldcase and the + " evaluated foldlevel: {'foldcase': 'case description', 'foldlevel': 1}. + + let l:foldcase = 'general' + let l:foldlevel = 0 + let line = getline(a:lnum) let indent = indent(a:lnum) let prev_line = getline(a:lnum - 1) @@ -56,18 +66,26 @@ fun! pymode#folding#expr(lnum) "{{{ " Decorators {{{ if line =~ s:decorator_regex - return ">".(indent / &shiftwidth + 1) + let l:foldcase = 'decorator declaration' + let l:foldlevel = '>'.(indent / &shiftwidth + 1) + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} endif "}}} " Definition {{{ if line =~ s:def_regex + + " TODO: obscure case. " 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 + " xxx " if indent(a:lnum) >= indent(a:lnum+1) + " xxx " \ && getline(prevnonblank(a:lnum)) !~ ':\s*$' + " xxx " let l:foldcase = 'definition' + " xxx " let l:foldlevel = '=' + " xxx " return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} + " xxx " endif + " Check if last decorator is before the last def let decorated = 0 let lnum = a:lnum - 1 @@ -81,10 +99,13 @@ fun! pymode#folding#expr(lnum) "{{{ let lnum -= 1 endwhile if decorated - return '=' + let l:foldcase = 'decorated function declaration' + let l:foldlevel = '=' else - return ">".(indent / &shiftwidth + 1) + let l:foldcase = 'function declaration' + let l:foldlevel = '>'.(indent / &shiftwidth + 1) endif + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} endif "}}} " Docstrings {{{ @@ -95,102 +116,126 @@ fun! pymode#folding#expr(lnum) "{{{ " Notice that an effect of this is that other docstring matches will not " be one liners. - if line =~ s:doc_line_regex - return "=" + if line =~ s:docstring_line_regex + let l:foldcase = 'one-liner docstring' + let l:foldlevel = '=' + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} endif - - if line =~ s:doc_begin_regex - " echom 'just entering' + if line =~ s:docstring_begin_regex if s:Is_opening_folding(a:lnum) - " echom 'entering at line ' . a:lnum - return ">".(indent / &shiftwidth + 1) + let l:foldcase = 'open multiline docstring' + let l:foldlevel = 'a1' endif + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} endif - if line =~ s:doc_end_regex + if line =~ s:docstring_end_regex if !s:Is_opening_folding(a:lnum) - " echom 'leaving at line ' . a:lnum - return "<".(indent / &shiftwidth + 1) + let l:foldcase = 'close multiline docstring' + let l:foldlevel = 's1' endif + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} 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 + " Blocks. {{{ + let s:save_cursor = getcurpos() + let line_block_start = s:BlockStart(a:lnum) + let line_block_end = s:BlockEnd(a:lnum) + let prev_line_block_start = s:BlockStart(a:lnum - 1) + if line !~ s:blank_regex + if line_block_start == prev_line_block_start + \ || a:lnum - line_block_start == 1 + let l:foldcase = 'non blank line; first line of block or part of it' + let l:foldlevel = '=' + elseif indent < indent(prevnonblank(a:lnum - 1)) + if indent == 0 + let l:foldcase = 'non blank line; zero indent' + let l:foldlevel = 0 + else + let l:foldcase = 'non blank line; non zero indent' + let l:foldlevel = indent(line_block_start) / &shiftwidth + 1 endif - finally - call setpos('.', curpos) - endtry - endif " }}} + endif + call setpos('.', s:save_cursor) + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} + else + call setpos('.', s:save_cursor) + endif + " endif " }}} " Blank Line {{{ + " Comments: cases of blank lines: + " 1. After non blank line: gets folded with previous line. + " 1. Just after a block; in this case it gets folded with the block. + " 1. Between docstrings and imports. + " 1. Inside docstrings. + " 2. Inside functions/methods. + " 3. Between functions/methods. 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 '=' + if prev_line !~ s:blank_regex + let l:foldcase = 'blank line after non blank line' + let l:foldlevel = '=' + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} + elseif a:lnum > line_block_start && a:lnum < line_block_end + let l:foldcase = 'blank line inside block' + let l:foldlevel = '=' + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} endif + " if prev_line =~ s:blank_regex + " if indent(a:lnum + 1) == 0 && next_line !~ s:blank_regex && next_line !~ s:docstring_general_regex + " if s:Is_opening_folding(a:lnum) + " let l:foldcase = 'case 1' + " let l:foldlevel = '=' + " return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} + " else + " let l:foldcase = 'case 2' + " let l:foldlevel = 0 + " return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} + " endif + " endif + " let l:foldcase = 'case 3' + " let l:foldlevel = -1 + " return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} + " else + " let l:foldcase = 'case 4' + " let l:foldlevel = '=' + " return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} + " endif endif " }}} - return '=' + return {'foldcase': l:foldcase, 'foldlevel': l:foldlevel} endfunction "}}} fun! s:BlockStart(lnum) "{{{ + " Returns the definition statement line which encloses the current line. + + let line = getline(a:lnum) + if line !~ s:blank_regex + let l:inferred_indent = indent(a:lnum) + else + let l:inferred_indent = prevnonblank(a:lnum) + endif + " 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] + " Flags from searchpos() (same as search()): + " b: search Backward instead of forward + " n: do Not move the cursor + " W: don't Wrap around the end of the file + let previous_definition = searchpos(s:def_regex, 'bnW') + + while previous_definition[0] != 1 && previous_definition != [0, 0] + \ && indent(previous_definition[0]) >= l:inferred_indent + let previous_definition = searchpos(s:def_regex, 'bnW') + call cursor(previous_definition[0] - 1, 0) + endwhile + let last_def = previous_definition[0] if last_def + call cursor(last_def, 0) 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] @@ -200,75 +245,84 @@ fun! s:BlockStart(lnum) "{{{ " 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 + 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] + + let result = searchpos('\v^\s{,'.max_indent.'}(def |class )\w', 'bcnW')[0] + + return result + endfunction "}}} +function! Blockstart(x) + let save_cursor = getcurpos() + return s:BlockStart(a:x) + call setpos('.', save_cursor) +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! Blockend(lnum) + let save_cursor = getcurpos() + return s:BlockEnd(a:lnum) + call setpos('.', save_cursor) +endfunction function! s:Is_opening_folding(lnum) "{{{ - " Helper function to see if docstring is opening or closing + " Helper function to see if multi line docstring is opening or closing. - " Cache the result so the loop runs only once per change + " 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 + return b:fold_cache[a:lnum - 1] "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 + " To be analized if odd/even to inform if it is opening or closing. + let fold_odd_even = 0 + " To inform is already has an open docstring. + let has_open_docstring = 0 + " To help skipping ''' and """ which are not docstrings. + let extra_docstrings = 0 " 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 + if i_line =~ s:docstring_begin_regex && ! has_open_docstring " 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 + let fold_odd_even = fold_odd_even + 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 + elseif i_line =~ s:docstring_end_regex && has_open_docstring let has_open_docstring = 0 - let number_of_folding = number_of_folding + 1 + let fold_odd_even = fold_odd_even + 1 - elseif i_line =~ s:doc_general_regex - " echom "extra docstrings on line " . i + elseif i_line =~ s:docstring_general_regex let extra_docstrings = extra_docstrings + 1 - endif - endfor + endif + + call add(b:fold_cache, fold_odd_even % 2) - call add(b:fold_cache, number_of_folding % 2) + endfor return b:fold_cache[a:lnum] + endfunction "}}} " vim: fdm=marker:fdl=0 diff --git a/autoload/pymode/indent.vim b/autoload/pymode/indent.vim index efd41f29..e964f378 100644 --- a/autoload/pymode/indent.vim +++ b/autoload/pymode/indent.vim @@ -24,7 +24,9 @@ function! pymode#indent#get_indent(lnum) if closing_paren return indent(parlnum) else - return indent(parlnum) + &shiftwidth + let l:indent_width = (g:pymode_indent_hanging_width > 0 ? + \ g:pymode_indent_hanging_width : &shiftwidth) + return indent(parlnum) + l:indent_width endif else return parcol diff --git a/autoload/pymode/lint.vim b/autoload/pymode/lint.vim index e7dba8b5..29dd6168 100644 --- a/autoload/pymode/lint.vim +++ b/autoload/pymode/lint.vim @@ -5,7 +5,7 @@ call pymode#tools#loclist#init() fun! pymode#lint#auto() "{{{ - if !pymode#save() + if ! pymode#save() return 0 endif PymodePython from pymode import auto @@ -42,7 +42,7 @@ fun! pymode#lint#toggle() "{{{ call pymode#wide_message("Code checking is enabled.") else call pymode#wide_message("Code checking is disabled.") - end + endif endfunction "}}} @@ -61,6 +61,9 @@ fun! pymode#lint#check() "{{{ if loclist.is_empty() call pymode#wide_message('Code checking is completed. No errors found.') + call g:PymodeSigns.refresh(loclist) + call loclist.show() + return endif call g:PymodeSigns.refresh(loclist) @@ -68,7 +71,7 @@ fun! pymode#lint#check() "{{{ call loclist.show() call pymode#lint#show_errormessage() - call pymode#wide_message('Found errors and warnings: ' . len(loclist._loclist)) + call pymode#wide_message('Found ' . loclist.num_errors() . ' error(s) and ' . loclist.num_warnings() . ' warning(s)') endfunction " }}} diff --git a/autoload/pymode/motion.vim b/autoload/pymode/motion.vim index 67e99e6b..c88fb913 100644 --- a/autoload/pymode/motion.vim +++ b/autoload/pymode/motion.vim @@ -21,64 +21,72 @@ fun! pymode#motion#vmove(pattern, flags) range "{{{ call cursor(a:firstline, 0) normal! v call cursor(end) -endfunction "}}} +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) "{{{ +fun! pymode#motion#select(first_pattern, second_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 + let posns = s:BlockStart(orig[0], a:first_pattern, a:second_pattern) + if getline(posns[0]) !~ a:first_pattern && getline(posns[0]) !~ a:second_pattern return 0 endif - let enum = s:BlockEnd(snum, indent(snum)) + let snum = posns[0] + let enum = s:BlockEnd(posns[1], indent(posns[1])) while cnt - let lnum = search(a:pattern, 'nW') + let lnum = search(a:second_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 pymode#motion#pos_le([snum, 0], orig) && pymode#motion#pos_le(orig, [enum+1, 0]) if a:inner - let snum = snum + 1 - let enum = prevnonblank(enum) + let snum = posns[1] + 1 endif call cursor(snum, 1) - normal! v + normal! V call cursor(enum, len(getline(enum))) endif endfunction "}}} +fun! pymode#motion#select_c(pattern, inner) "{{{ + call pymode#motion#select(a:pattern, a:pattern, a:inner) +endfunction "}}} -fun! s:BlockStart(lnum, ...) "{{{ - let pattern = a:0 ? a:1 : '^\s*\(@\|class\s.*:\|def\s\)' +fun! s:BlockStart(lnum, first_pattern, second_pattern) "{{{ 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 + " Skip comments, deeper or equal lines + if line =~ '^\s*#' || test >= indent 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) + + " Indent is strictly less at this point: check for def/class/@ + if line =~ a:first_pattern || line =~ a:second_pattern + while getline(lnum-1) =~ a:first_pattern + let lnum = lnum - 1 + endwhile + let first_pos = lnum + while getline(lnum) !~ a:second_pattern + let lnum = lnum + 1 + endwhile + let second_pos = lnum + return [first_pos, second_pos] + endif endwhile - return 0 + return [0, 0] endfunction "}}} @@ -89,7 +97,7 @@ fun! s:BlockEnd(lnum, ...) "{{{ let lnum = nextnonblank(lnum + 1) if getline(lnum) =~ '^\s*#' | continue elseif lnum && indent(lnum) <= indent - return lnum - 1 + return prevnonblank(lnum - 1) endif endwhile return line('$') diff --git a/autoload/pymode/rope.vim b/autoload/pymode/rope.vim index a82a46d9..c1a2de0c 100644 --- a/autoload/pymode/rope.vim +++ b/autoload/pymode/rope.vim @@ -1,5 +1,9 @@ " Python-mode Rope support -" + +if ! g:pymode_rope + finish +endif + PymodePython from pymode import rope call pymode#tools#loclist#init() @@ -11,24 +15,28 @@ endfunction fun! pymode#rope#complete(dot) if pumvisible() - return "\" - end + if stridx('noselect', &completeopt) != -1 + return "\" + else + return "" + endif + endif if a:dot PymodePython rope.complete(True) else PymodePython rope.complete() - end - return pumvisible() ? "\\" : "" + endif + return pumvisible() && stridx('noselect', &completeopt) != -1 ? "\\" : "" endfunction fun! pymode#rope#complete_on_dot() "{{{ if !exists("*synstack") return "" - end + endif for group in map(synstack(line('.'), col('.') - 1), 'synIDattr(v:val, "name")') for name in ['pythonString', 'pythonComment', 'pythonNumber', 'pythonDocstring'] if group == name - return "" + return "" endif endfor endfor @@ -72,8 +80,11 @@ fun! pymode#rope#show_doc() setlocal nomodifiable setlocal nomodified setlocal filetype=rst + + normal gg + wincmd p - end + endif endfunction diff --git a/autoload/pymode/run.vim b/autoload/pymode/run.vim index 24c8729c..356409b6 100644 --- a/autoload/pymode/run.vim +++ b/autoload/pymode/run.vim @@ -74,8 +74,8 @@ fun! pymode#run#code_run(line1, line2) "{{{ 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 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 diff --git a/autoload/pymode/tools/loclist.vim b/autoload/pymode/tools/loclist.vim index 18b6d294..b9121bdf 100644 --- a/autoload/pymode/tools/loclist.vim +++ b/autoload/pymode/tools/loclist.vim @@ -24,19 +24,37 @@ endfunction "}}} fun! g:PymodeLocList.is_empty() "{{{ - return empty(self._loclist) + return empty(self._errlist) && empty(self._warnlist) +endfunction "}}} + +fun! g:PymodeLocList.loclist() "{{{ + let loclist = copy(self._errlist) + call extend(loclist, self._warnlist) + return loclist +endfunction "}}} + +fun! g:PymodeLocList.num_errors() "{{{ + return len(self._errlist) +endfunction "}}} + +fun! g:PymodeLocList.num_warnings() "{{{ + return len(self._warnlist) endfunction "}}} fun! g:PymodeLocList.clear() "{{{ - let self._loclist = [] + let self._errlist = [] + let self._warnlist = [] let self._messages = {} let self._name = expand('%:t') endfunction "}}} fun! g:PymodeLocList.extend(raw_list) "{{{ - call extend(self._loclist, a:raw_list) + let err_list = filter(copy(a:raw_list), 'v:val["type"] == "E"') + let warn_list = filter(copy(a:raw_list), 'v:val["type"] != "E"') + call extend(self._errlist, err_list) + call extend(self._warnlist, warn_list) for issue in a:raw_list let self._messages[issue.lnum] = issue.text endfor @@ -46,7 +64,7 @@ endfunction "}}} fun! g:PymodeLocList.filter(filters) "{{{ let loclist = [] - for error in self._loclist + for error in self.loclist() let passes_filters = 1 for key in keys(a:filters) if get(error, key, '') !=? a:filters[key] @@ -65,7 +83,7 @@ endfunction "}}} fun! g:PymodeLocList.show() "{{{ - call setloclist(0, self._loclist) + call setloclist(0, self.loclist()) if self.is_empty() lclose elseif g:pymode_lint_cwindow diff --git a/autoload/pymode/tools/signs.vim b/autoload/pymode/tools/signs.vim index 3487cf85..579573ed 100644 --- a/autoload/pymode/tools/signs.vim +++ b/autoload/pymode/tools/signs.vim @@ -46,7 +46,7 @@ endfunction "}}} fun! g:PymodeSigns.place(loclist) "{{{ let seen = {} - for issue in a:loclist._loclist + 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) diff --git a/autoload/pymode/troubleshooting.vim b/autoload/pymode/troubleshooting.vim deleted file mode 100644 index 915a5c5e..00000000 --- a/autoload/pymode/troubleshooting.vim +++ /dev/null @@ -1,89 +0,0 @@ -" DESC: Get debug information about pymode problem -fun! pymode#troubleshooting#test() "{{{ - new - setlocal buftype=nofile bufhidden=delete noswapfile nowrap - - let os = "Unknown" - if has('win16') || has('win32') || has('win64') - let os = "Windows" - else - let os = substitute(system('uname'), "\n", "", "") - endif - - if !pymode#default('g:pymode_init', 1) - call pymode#init(expand(':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 "}}} diff --git a/debug.vim b/debug.vim deleted file mode 100644 index c7d32661..00000000 --- a/debug.vim +++ /dev/null @@ -1,13 +0,0 @@ -" 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(':p:h')) -set rtp -=$HOME/.vim -set rtp -=$HOME/.vim/after -set nocp -syntax enable diff --git a/debugvimrc.vim b/debugvimrc.vim new file mode 100644 index 00000000..a8b3f188 --- /dev/null +++ b/debugvimrc.vim @@ -0,0 +1,32 @@ +" Use this settings for testing the plugin. +" +" Run vim with command: +" +" $ vim -u ./debug.vim /my/py/file.py +" +" Only python-mode will be loaded. + +" Disable all persistence between sessions. +let skip_defaults_vim=1 +" TODO XXX: this nevertheless keeps viminfo enabled. As a workaround the flag +" '-i NONE' should be added to vim's loading. +set viminfo= +set nobackup +set noswapfile + +" Modify vimrc configuration. +execute('set rtp+='. expand(':p:h')) +set rtp -=$HOME/.vim +set rtp -=$HOME/.vim/after +set nocompatible + +" Activate debugging. +let g:pymode_debug = 1 + +" Define a common shell for non Windows systems. +if ! (has('win16') || has('win32') || has('win64')) + set shell=/bin/bash +endif + +" IMPORTANT: Do note that the history of this session is saved on the log file. +" See the augroup in ./ftplugin/python/pymode.vim file. diff --git a/doc/pymode.txt b/doc/pymode.txt index 1551f119..6d047698 100644 --- a/doc/pymode.txt +++ b/doc/pymode.txt @@ -1,4 +1,4 @@ -*pymode.txt* *python-mode.txt* *pymode* *python-mode* +*pymode.txt* For Vim Version 8.0 Last change: 2019 March 08 ____ _ _ ____ _ _ _____ _ _ __ __ _____ ____ ____ ~ ( _ \( \/ )(_ _)( )_( )( _ )( \( )___( \/ )( _ )( _ \( ___) ~ @@ -6,36 +6,42 @@ (__) (__) (__) (_) (_)(_____)(_)\_) (_/\/\_)(_____)(____/(____) ~ - Version: 0.9.2 - -============================================================================== -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| - -============================================================================== + Version: 0.13.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. Development...............................................|pymode-development| +8. Credits.......................................................|pymode-credits| +9. License.......................................................|pymode-license| + +=============================================================================== 1. Intro ~ - *pymode-intro* + *pymode-intro* + +XXX IMPORTANT: As of 2017-11-18 python-mode is going through a major redesign. +Thus some of its functionality may not work as expected. Please be patient and +do report bugs or inconsistencies in its documentation. But remember to look +for already openned bug reports for the same issue before creating a new one. 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, @@ -46,7 +52,7 @@ 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* +Features: *pymode-features* - Support Python version 2.6+ and 3.2+ - Syntax highlighting @@ -67,34 +73,34 @@ Features: *pymode-features* - And more, more ... -============================================================================== +=============================================================================== 2. Common functionality ~ - *pymode-common* + *pymode-common* This script provides the following options that can customizes the behavior of -PythonMode. These options should be set in your |vimrc|. +python-mode. These options should be set in your |vimrc|. - Below shows the default values. +Find below the default values: -Turn on the whole plugin *'g:pymode'* +Turn on the whole plugin. *'g:pymode'* > let g:pymode = 1 -Turn off plugin's warnings *'g:pymode_warnings'* +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. +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'* +Trim unused white spaces on save. *'g:pymode_trim_whitespaces'* > let g:pymode_trim_whitespaces = 1 -Setup default python options *'g:pymode_options'* +Setup default python options. *'g:pymode_options'* > let g:pymode_options = 1 @@ -111,105 +117,129 @@ python buffers: > setlocal commentstring=#%s setlocal define=^\s*\\(def\\\\|class\\) -Setup max line length *'g:pymode_options_max_line_length'* +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'* +Enable colorcolumn display at max_line_length. *'g:pymode_options_colorcolumn'* > let g:pymode_options_colorcolumn = 1 -Setup pymode |quickfix| window +Setup pymode |quickfix| window. - *'g:pymode_quickfix_maxheight'* *'g:pymode_quickfix_minheight'* + *'g:pymode_quickfix_maxheight'* *'g:pymode_quickfix_minheight'* > let g:pymode_quickfix_minheight = 3 let g:pymode_quickfix_maxheight = 6 ------------------------------------------------------------------------------- +Set pymode |preview| window height. *'g:pymode_preview_height'* +Preview window is used to show documentation and ouput from |pymode-run|. +> + let g:pymode_preview_height = &previewheight + +Set where pymode |preview| window will appear. *'g:pymode_preview_position'* +> + let g:pymode_preview_position = 'botright' + +Value is command which can influcece where new window created by `:new` command +will appear, eg. `:botright`. + +------------------------------------------------------------------------------- 2.1. Python version ~ - *pymode-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. +By default pymode will attempt to use Python 3, if available. However, you can +also disable all Python features of pymode. - *'g:pymode_python'* + *'g:pymode_python'* > - let g:pymode_python = 'python' + let g:pymode_python = 'python3' -Values are `python`, `python3`, `disable`. If value set to `disable` most +Values are `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-indent* Pymode supports PEP8-compatible python indent. -Enable pymode indentation *'g:pymode_indent'* +Enable pymode indentation *'g:pymode_indent'* > let g:pymode_indent = 1 ------------------------------------------------------------------------------- + +Customization: + +Hanging indent size after an open parenthesis or bracket (but nothing after the +parenthesis), when vertical alignment is not used. Defaults to `&shiftwidth`. + *'g:pymode_indent_hanging_width'* +> + let g:pymode_indent_hanging_width = &shiftwidth + let g:pymode_indent_hanging_width = 4 + +------------------------------------------------------------------------------- 2.3 Python folding ~ - *pymode-folding* + *pymode-folding* -Fast and usual python folding in Vim. -Enable pymode folding *'g:pymode_folding'* +Enable pymode folding *'g:pymode_folding'* > - let g:pymode_folding = 1 + let g:pymode_folding = 0 + +Currently folding is considered experimental. There are several issues with +its implementation. ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.4 Vim motion ~ - *pymode-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'* + *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-documentation* Pymode could show documentation for current word by `pydoc`. Commands: -*:PymodeDoc* — show documentation +*:PymodeDoc* — show documentation -Turns on the documentation script *'g:pymode_doc'* +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'* + *'g:pymode_doc_bind'* > let g:pymode_doc_bind = 'K' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.6 Support virtualenv ~ - *pymode-virtualenv* + *pymode-virtualenv* Commands: *:PymodeVirtualenv* -- Activate virtualenv (path can be absolute or @@ -219,33 +249,33 @@ Enable automatic virtualenv detection *'g:pymode_virtualenv' > let g:pymode_virtualenv = 1 -Set path to virtualenv manually *'g:pymode_virtualenv_path'* +Set path to virtualenv manually *'g:pymode_virtualenv_path'* > let g:pymode_virtualenv_path = $VIRTUAL_ENV ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.7 Run code ~ - *pymode-run* + *pymode-run* Commands: *:PymodeRun* -- Run current buffer or selection -Turn on the run code script *'g:pymode_run'* +Turn on the run code script *'g:pymode_run'* > let g:pymode_run = 1 -Binds keys to run python code *'g:pymode_run_bind'* +Binds keys to run python code *'g:pymode_run_bind'* > let g:pymode_run_bind = 'r' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.8 Breakpoints ~ - *pymode-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'* +Enable functionality *'g:pymode_breakpoint'* > let g:pymode_breakpoint = 1 @@ -258,9 +288,9 @@ Manually set breakpoint command (leave empty for automatic detection) let g:pymode_breakpoint_cmd = '' -============================================================================== +=============================================================================== 3. Code checking ~ - *pymode-lint* + *pymode-lint* Pymode supports `pylint`, `pep257`, `pep8`, `pyflakes`, `mccabe` code checkers. You could run several similar checkers. @@ -277,44 +307,44 @@ Commands: *:PymodeLintToggle* -- Toggle code checking *:PymodeLintAuto* -- Fix PEP8 errors in current buffer automatically -Turn on code checking *'g:pymode_lint'* +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'* +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'* +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'* +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'* +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'* +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 +Skip errors and warnings *'g:pymode_lint_ignore'* +E.g. ["W", "E2"] (Skip all Warnings and the Errors starting with E2) etc. > - let g:pymode_lint_ignore = "E501,W" + let g:pymode_lint_ignore = ["E501", "W",] -Select some error or warnings. *'g:pymode_lint_select'* +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" + let g:pymode_lint_select = ["E501", "W0011", "W430"] -Sort errors by relevance *'g:pymode_lint_sort'* +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 ... @@ -322,11 +352,11 @@ after them 'C' and ... let g:pymode_lint_sort = [] Auto open cwindow (quickfix) if any errors have been found - *'g:pymode_lint_cwindow'* + *'g:pymode_lint_cwindow'* > let g:pymode_lint_cwindow = 1 -Place error |signs| *'g:pymode_signs'* +Place error |signs| *'g:pymode_signs'* > let g:pymode_lint_signs = 1 @@ -339,44 +369,43 @@ Definitions for |signs| let g:pymode_lint_info_symbol = 'II' let g:pymode_lint_pyflakes_symbol = 'FF' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 3.1 Set code checkers options ~ - *pymode-lint-options* + *pymode-lint-options* Pymode has the ability to set code checkers options from pymode variables: -Set PEP8 options *'g:pymode_lint_options_pep8'* +Set PEP8 options *'g:pymode_lint_options_pep8'* > let g:pymode_lint_options_pep8 = - \ {'max_line_length': g:pymode_options_max_line_length}) + \ {'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'* +Set Pyflakes options *'g:pymode_lint_options_pyflakes'* > let g:pymode_lint_options_pyflakes = { 'builtins': '_' } -Set mccabe options *'g:pymode_lint_options_mccabe'* +Set mccabe options *'g:pymode_lint_options_mccabe'* > let g:pymode_lint_options_mccabe = { 'complexity': 12 } -Set pep257 options *'g:pymode_lint_options_pep257'* +Set pep257 options *'g:pymode_lint_options_pep257'* > let g:pymode_lint_options_pep257 = {} -Set pylint options *'g:pymode_lint_options_pylint'* +Set pylint options *'g:pymode_lint_options_pylint'* > let g:pymode_lint_options_pylint = - \ {'max-line-length': g:pymode_options_max_line_length}) + \ {'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* +=============================================================================== +4. Rope support ~ + *pymode-rope* Pymode supports Rope refactoring operations, code completion and code assists. @@ -390,12 +419,12 @@ Commands: |:PymodeRopeUndo| -- Undo changes from last refactoring -Turn on the rope script *'g:pymode_rope'* +Turn on the rope script *'g:pymode_rope'* > let g:pymode_rope = 1 .ropeproject Folder ~ - *.ropeproject* + *.ropeproject* *:PymodeRopeNewProject* [] -- Open new Rope project in the given path *:PymodeRopeRegenerate* -- Regenerate the project cache @@ -422,13 +451,13 @@ 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'* + *'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'* + *'g:pymode_rope_project_root'* > let g:pymode_rope_project_root = "" @@ -438,15 +467,14 @@ 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'* + *'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'* +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 = 'd' @@ -455,9 +483,9 @@ Regenerate project cache on every save (if file has been modified) > let g:pymode_rope_regenerate_on_write = 1 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 4.1 Completion ~ - *pymode-completion* + *pymode-completion* By default you can use for autocompletion. The first entry will be automatically selected and you can press to insert the entry in @@ -465,26 +493,32 @@ your code. and / works too. Autocompletion is also called by typing a period in |Insert| mode by default. +If there's only one complete item, vim may be inserting it automatically +instead of using a popup menu. If the complete item which inserted is not +your wanted, you can roll it back use '' in |Insert| mode or setup +'completeopt' with `menuone` and `noinsert` in your vimrc. .e.g. +> + set completeopt=menuone,noinsert -Turn on code completion support in the plugin *'g:pymode_rope_completion'* +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'* + *'g:pymode_rope_complete_on_dot'* > let g:pymode_rope_complete_on_dot = 1 -Keymap for autocomplete *'g:pymode_rope_completion_bind'* +Keymap for autocomplete *'g:pymode_rope_completion_bind'* > let g:pymode_rope_completion_bind = '' Extended autocompletion (rope could complete objects which have not been -imported) from project *'g:pymode_rope_autoimport'* +imported) from project *'g:pymode_rope_autoimport'* > let g:pymode_rope_autoimport = 0 -Load modules to autoimport by default *'g:pymode_rope_autoimport_modules'* +Load modules to autoimport by default *'g:pymode_rope_autoimport_modules'* > let g:pymode_rope_autoimport_modules = ['os', 'shutil', 'datetime'] @@ -493,24 +527,24 @@ Offer to unresolved import object after completion. let g:pymode_rope_autoimport_import_after_complete = 0 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 4.2 Find definition ~ - *pymode-rope-findit* + *pymode-rope-findit* By default when you press *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'* +to definition. +Leave empty for disable key binding. *'g:pymode_rope_goto_definition_bind'* > let g:pymode_rope_goto_definition_bind = 'g' Command for open window when definition has been found -Values are (`e`, `new`, `vnew`) *'g:pymode_rope_goto_definition_cmd'* +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* + *pymode-rope-refactoring* Rename method/function/class/variable in the project ~ @@ -518,7 +552,7 @@ 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'* + *'g:pymode_rope_rename_bind'* > let g:pymode_rope_rename_bind = 'rr' @@ -527,7 +561,7 @@ Rename a current module/package ~ *:PymodeRopeRenameModule* -- Rename current module -Keymap for rename current module *'g:pymode_rope_rename_module_bind'* +Keymap for rename current module *'g:pymode_rope_rename_module_bind'* > let g:pymode_rope_rename_module_bind = 'r1r' @@ -538,18 +572,18 @@ Imports ~ Organize imports sorts imports, too. It does that according to PEP8. Unused imports will be dropped. -Keymap *'g:pymode_rope_organize_imports_bind'* +Keymap *'g:pymode_rope_organize_imports_bind'* > let g:pymode_rope_organize_imports_bind = 'ro' -Insert import for current word under cursor *'g:pymode_rope_autoimport_bind'* +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 = 'ra' Convert module to package ~ - *'g:pymode_rope_module_to_package_bind'* + *'g:pymode_rope_module_to_package_bind'* *:PymodeRopeModuleToPackage* -- convert current module to package @@ -559,19 +593,19 @@ Keybinding: Extract method/variable ~ - *pymode-rope-extract* + *pymode-rope-extract* Extract method/variable from selected lines. - *'g:pymode_rope_extract_method_bind'* - *'g:pymode_rope_extract_variable_bind'* + *'g:pymode_rope_extract_method_bind'* + *'g:pymode_rope_extract_variable_bind'* > let g:pymode_rope_extract_method_bind = 'rm' let g:pymode_rope_extract_variable_bind = 'rl' Use function ~ - *pymode-rope-use* + *pymode-rope-use* It tries to find the places in which a function can be used and changes the code to call it instead. @@ -580,7 +614,7 @@ code to call it instead. Move method/fields ~ - *pymode-rope-move* + *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 @@ -595,10 +629,10 @@ Change function signature ~ let g:pymode_rope_change_signature_bind = 'rs' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 4.4 Undo/Redo changes ~ - *pymode-rope-undo* - *pymode-rope-redo* + *pymode-rope-undo* + *pymode-rope-redo* Commands: @@ -606,94 +640,114 @@ Commands: *:PymodeRopeRedo* -- Redo last changes in the project -============================================================================== +=============================================================================== 5. Syntax ~ - *pymode-syntax* + *pymode-syntax* -Turn on pymode syntax *'g: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'* + *'g:pymode_syntax_slow_sync'* > let g:pymode_syntax_slow_sync = 1 -Enable all python highlights *'g:pymode_syntax_all'* +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'* +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'* +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'* +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'* +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'* +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'* +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'* +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'* + *'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'* +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'* +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'* +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'* + *'g:pymode_syntax_docstrings'* > let g:pymode_syntax_docstrings = g:pymode_syntax_all -============================================================================== +=============================================================================== 6. FAQ ~ - *pymode-faq* + *pymode-faq* -Python-mode doesn't work ------------------------- +1. Python-mode doesn't work +--------------------------- -Open any python file and run ":call pymode#troubleshooting#test()", -fix the warning or send me the output. +First remember to get the latest and updated version of the project source +code and also update the project submodules. +Clear all python cache/compiled files (`*.pyc` files and `__pycache__` +directory and everything under it). In Linux/Unix/MacOS you can run: -Rope completion is very slow *pymode-rope-slow* ----------------------------- +`find . -type f -name '*.pyc' -delete && find . -type d -name '__pycache__' -delete` + +Then start python mode with: +`vim -i NONE -u /debugvimrc.vim` + +Reproduce the error and submit your python mode debug file. You can check its +location with `:messages` for something like: + +`pymode debug msg 1: Starting debug on: 2017-11-18 16:44:13 with file /tmp/pymode_debug_file.txt` + +Please submit the entire content of the file along with a reasoning of why the +plugin seems broken. + + *Underlined do check for sensitive information in the file before + *Underlined submitting! + + + +2. Rope completion is very slow *pymode-rope-slow* +------------------------------- Rope creates a project-level service directory in |.ropeproject| @@ -715,9 +769,8 @@ You may also set |'g:pymode_rope_project_root'| to manually specify the project root path. - -Pylint check is very slow -------------------------- +3. 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 @@ -726,9 +779,8 @@ modules if possible. Try using another code checker: see You may set |exrc| and |secure| in your |vimrc| to auto-set custom settings from `.vimrc` from your projects directories. - -OSX cannot import urandom -------------------------- +4. OSX cannot import urandom +---------------------------- See: https://groups.google.com/forum/?fromgroups=#!topic/vim_dev/2NXKF6kDONo @@ -740,11 +792,53 @@ The sequence of commands that fixed this: brew install -v --force macvim brew link macvim brew link python -< -============================================================================== -7. Credits ~ - *pymode-credits* +5. Folding is slow +------------------ + +Python mode adds folding for definitions and multi line docstrings. These may +be costly to compute on large files. To disable them one simple has to to add: + + let g:pymode_folding = 1 + +to their vimrc file. + +Beware that when editing python files in multiple windows vim computes the +folding for every typed character. Thus it may be useful to define: + + augroup unset_folding_in_insert_mode + autocmd! + autocmd InsertEnter *.py setlocal foldmethod=marker + autocmd InsertLeave *.py setlocal foldmethod=expr + augroup END + +=============================================================================== +7. Development~ + *pymode-development* + +This section briefly defines development guidelines for python-mode. + +1. This help file uses vim's conventions defined at |help-writing|. +2. The name of the plugin shall be referred to as 'python-mode' throughout +documentation (except as a first word in a sentence in which case is +'Python-mode'). +3. All defined functions should use vim's conventions and start with 'Pymode'. +4. Special marks for project development are `XXX` and `TODO`. They provide a +easy way for developers to check pending issues. +5. If submitting a pull request then a test should be added which smartly +covers the found bug/new feature. Check out the `tests/test.sh` (1) file and +other executed files. +A suggested structure is the following: add your test to +`tests/test_bash` (2) and a vim script to be sourced at +`tests/test_procedures_vimscript` (3). Try to make use of the already existing +files at `tests/test_python_sample_code` (4). File (1) should be trigger the +newly added file (2). This latter file should invoke vim which in turn sources +file (3). File (3) may then read (4) as a first part of its assertion +structure and then execute the remaning of the instructions/assertions. + +=============================================================================== +8. Credits ~ + *pymode-credits* Kirill Klenov http://klen.github.com/ http://github.com/klen/ @@ -758,8 +852,9 @@ The sequence of commands that fixed this: http://www.logilab.fr/ Pyflakes: - Copyright (c) 2005 Divmod, Inc. - http://www.divmod.com/ + Copyright (c) 2005-2011 Divmod, Inc. + Copyright (c) 2013-2014 Florent Xicluna + https://github.com/PyCQA/pyflakes PEP8: Copyright (c) 2006 Johann C. Rocholl @@ -778,19 +873,20 @@ The sequence of commands that fixed this: http://github.com/hynek/vim-python-pep8-indent -============================================================================== -8. License ~ - *pymode-license* +=============================================================================== +9. 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 :) +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! +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: + vim:tw=79:ts=8:ft=help:norl: diff --git a/ftplugin/python/pymode.vim b/ftplugin/python/pymode.vim index 97daecca..a1370669 100644 --- a/ftplugin/python/pymode.vim +++ b/ftplugin/python/pymode.vim @@ -5,7 +5,7 @@ endif if g:pymode_python == 'disable' if g:pymode_warning - call pymode#error("Pymode requires vim compiled with +python. Most of features will be disabled.") + call pymode#error("Pymode requires vim compiled with +python3 (exclusively). Most of features will be disabled.") endif finish @@ -110,7 +110,7 @@ if g:pymode_lint " let &l:updatetime = g:pymode_lint_async_updatetime " au! BufEnter call pymode#lint#start() " au! BufLeave call pymode#lint#stop() - end + endif endif @@ -124,7 +124,7 @@ if g:pymode_doc exe "nnoremap " g:pymode_doc_bind ":call pymode#doc#find()" exe "vnoremap " g:pymode_doc_bind ":call pymode#doc#show(@*)" -end +endif " Rope support if g:pymode_rope @@ -134,69 +134,69 @@ if g:pymode_rope endif if g:pymode_rope_show_doc_bind != "" exe "noremap " . g:pymode_rope_show_doc_bind . " :call pymode#rope#show_doc()" - end + endif if g:pymode_rope_find_it_bind != "" exe "noremap " . g:pymode_rope_find_it_bind . " :call pymode#rope#find_it()" - end + endif if g:pymode_rope_organize_imports_bind != "" exe "noremap " . g:pymode_rope_organize_imports_bind . " :call pymode#rope#organize_imports()" - end + endif if g:pymode_rope_rename_bind != "" exe "noremap " . g:pymode_rope_rename_bind . " :call pymode#rope#rename()" - end + endif if g:pymode_rope_rename_module_bind != "" exe "noremap " . g:pymode_rope_rename_module_bind . " :call pymode#rope#rename_module()" - end + endif if g:pymode_rope_extract_method_bind != "" exe "vnoremap " . g:pymode_rope_extract_method_bind . " :call pymode#rope#extract_method()" - end + endif if g:pymode_rope_extract_variable_bind != "" exe "vnoremap " . g:pymode_rope_extract_variable_bind . " :call pymode#rope#extract_variable()" - end + endif if g:pymode_rope_inline_bind != "" exe "noremap " . g:pymode_rope_inline_bind . " :call pymode#rope#inline()" - end + endif if g:pymode_rope_move_bind != "" exe "noremap " . g:pymode_rope_move_bind . " :call pymode#rope#move()" - end + endif if g:pymode_rope_change_signature_bind != "" exe "noremap " . g:pymode_rope_change_signature_bind . " :call pymode#rope#signature()" - end + endif if g:pymode_rope_use_function_bind != "" exe "noremap " . g:pymode_rope_use_function_bind . " :call pymode#rope#use_function()" - end + endif if g:pymode_rope_generate_function_bind != "" exe "noremap " . g:pymode_rope_generate_function_bind . " :call pymode#rope#generate_function()" - end + endif if g:pymode_rope_generate_package_bind != "" exe "noremap " . g:pymode_rope_generate_package_bind . " :call pymode#rope#generate_package()" - end + endif if g:pymode_rope_generate_class_bind != "" exe "noremap " . g:pymode_rope_generate_class_bind . " :call pymode#rope#generate_class()" - end + endif if g:pymode_rope_module_to_package_bind != "" exe "noremap " . g:pymode_rope_module_to_package_bind . " :call pymode#rope#module_to_package()" - end + endif if g:pymode_rope_autoimport_bind != "" exe "noremap " . g:pymode_rope_autoimport_bind . " :PymodeRopeAutoImport" - end + endif if g:pymode_rope_completion && g:pymode_rope_complete_on_dot inoremap . .=pymode#rope#complete_on_dot() - end + endif command! -buffer -nargs=? PymodeRopeNewProject call pymode#rope#new() command! -buffer PymodeRopeUndo call pymode#rope#undo() @@ -207,6 +207,52 @@ if g:pymode_rope if g:pymode_rope_autoimport command! -buffer PymodeRopeAutoImport call pymode#rope#autoimport(expand('')) - end + endif -end +endif + + +if g:pymode_debug + " Redefine functions to be debugged here functions here. + + " NOTE: The redraw seems to be necessary to force messages to get echoed to + " the screen. See: + " https://groups.google.com/forum/#!topic/vim_use/EfcXOjq_rKE + " for details. + " silent! redraw! + " TODO: when loading with 'vim -u ./debug.vim' the messages shown in vim + " are unduly cleared. Need a fix. + + " Start debbuging environment. {{{ + if ! &verbosefile + " Get a system independent temporary filename. The 'marker' variable is + " used to get rid of a null character getting inserted at position. + " substitute() was not able to remove it. + " TODO: see https://superuser.com/questions/935574/get-rid-of-null-character-in-vim-variable + let g:pymode_debug_tempfile=matchstr( + \ execute( + \ g:pymode_python + \ . " import os;import tempfile; marker='|';" + \ . " print(marker, tempfile.gettempdir(), os.sep, " + \ . "'pymode_debug_file.txt', marker, sep='', end='')"), + \ '|\zs.*\ze|') + execute "set verbosefile=" . g:pymode_debug_tempfile + endif + call pymode#debug('Starting debug on: ' + \ . strftime("\%Y-\%m-\%d \%H:\%M:\%S") + \ . ' with file ' . &verbosefile) + " }}} + " Redefine folding expression. {{{ + if g:pymode_folding + setlocal foldexpr=pymode#debug#foldingexpr(v:lnum) + endif + call pymode#debug#sysinfo() + " }}} + " Define auto commands for vim. {{{ + augroup augroup_save_issue_commands + autocmd! + autocmd VimLeave *.py | call pymode#debug('Session history:') | silent! history + augroup END + " }}} + + endif diff --git a/plugin/pymode.vim b/plugin/pymode.vim index 3833cef3..9c01a9d5 100644 --- a/plugin/pymode.vim +++ b/plugin/pymode.vim @@ -1,15 +1,15 @@ " vi: fdl=1 -let g:pymode_version = "0.9.2" - -com! PymodeVersion echomsg "Current python-mode version: " . g:pymode_version -com! PymodeTroubleshooting call pymode#troubleshooting#test() +let g:pymode_version = "0.13.0" " 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 +if !g:pymode || &cp || &diff + " Update pymode status to prevent loading in other files and adding this + " condition to all of them. + let g:pymode = 0 finish endif @@ -19,7 +19,11 @@ filetype plugin on " OPTIONS: {{{ " Vim Python interpreter. Set to 'disable' for remove python features. -call pymode#default('g:pymode_python', '') +if has("python3") && executable('python3') + call pymode#default('g:pymode_python', 'python3') +else + call pymode#default('g:pymode_python', 'disable') +endif " Disable pymode warnings call pymode#default('g:pymode_warning', 1) @@ -34,12 +38,18 @@ call pymode#default('g:pymode_doc_bind', 'K') " Enable/Disable pymode PEP8 indentation call pymode#default("g:pymode_indent", 1) +" Customize hanging indent size different than &shiftwidth +call pymode#default("g:pymode_indent_hanging_width", -1) + +" TODO: currently folding suffers from a bad performance and incorrect +" implementation. This feature should be considered experimental. " Enable/disable pymode folding for pyfiles. -call pymode#default("g:pymode_folding", 1) +call pymode#default("g:pymode_folding", 0) " 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\)\@!') +" call pymode#default("g:pymode_folding_regex", '^\s*\%(class\|def\|async\s\+def\)') " Enable/disable python motion operators call pymode#default("g:pymode_motion", 1) @@ -49,7 +59,7 @@ 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_max_line_length", 79) call pymode#default("g:pymode_options_colorcolumn", 1) " Enable/disable vertical display of python documentation @@ -61,6 +71,12 @@ call pymode#default('g:pymode_quickfix_maxheight', 6) " Maximal height of pymode quickfix window call pymode#default('g:pymode_quickfix_minheight', 3) +" Height of preview window +call pymode#default('g:pymode_preview_height', &previewheight) + +" Position of preview window +call pymode#default('g:pymode_preview_position', 'botright') + " LOAD VIRTUALENV {{{ " " Enable virtualenv support @@ -105,14 +121,14 @@ 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 +" Choices are: pylint, pyflakes, pep8, mccabe and pep257 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", "") +call pymode#default("g:pymode_lint_ignore", []) " Select errors and warnings (e.g. E4,W) -call pymode#default("g:pymode_lint_select", "") +call pymode#default("g:pymode_lint_select", []) " Auto open cwindow if any errors has been finded call pymode#default("g:pymode_lint_cwindow", 1) @@ -135,6 +151,7 @@ call pymode#default("g:pymode_lint_info_symbol", "II") call pymode#default("g:pymode_lint_pyflakes_symbol", "FF") " Code checkers options +" TODO: check if most adequate name name is pep8 or pycodestyle. call pymode#default("g:pymode_lint_options_pep8", \ {'max_line_length': g:pymode_options_max_line_length}) @@ -167,96 +184,98 @@ call pymode#default('g:pymode_breakpoint_cmd', '') " ROPE (refactoring, codeassist) {{{ " " Rope support -call pymode#default('g:pymode_rope', 1) +call pymode#default('g:pymode_rope', 0) " System plugin variable -call pymode#default('g:pymode_rope_current', '') +if g:pymode_rope + call pymode#default('g:pymode_rope_current', '') -" Configurable rope project root -call pymode#default('g:pymode_rope_project_root', '') + " 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') + " 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) + " 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) + " 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) + " 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) + " 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']) + " 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', 'ra') + " Bind keys to autoimport module for object under cursor + call pymode#default('g:pymode_rope_autoimport_bind', 'ra') -" Automatic completion on dot -call pymode#default('g:pymode_rope_complete_on_dot', 1) + " 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', '') + " Bind keys for autocomplete (leave empty for disable) + call pymode#default('g:pymode_rope_completion_bind', '') -" Bind keys for goto definition (leave empty for disable) -call pymode#default('g:pymode_rope_goto_definition_bind', 'g') + " Bind keys for goto definition (leave empty for disable) + call pymode#default('g:pymode_rope_goto_definition_bind', 'g') -" set command for open definition (e, new, vnew) -call pymode#default('g:pymode_rope_goto_definition_cmd', 'new') + " set command for open definition (e, new, vnew) + call pymode#default('g:pymode_rope_goto_definition_cmd', 'new') -" Bind keys for show documentation (leave empty for disable) -call pymode#default('g:pymode_rope_show_doc_bind', 'd') + " Bind keys for show documentation (leave empty for disable) + call pymode#default('g:pymode_rope_show_doc_bind', 'd') -" Bind keys for find occurencies (leave empty for disable) -call pymode#default('g:pymode_rope_find_it_bind', 'f') + " Bind keys for find occurencies (leave empty for disable) + call pymode#default('g:pymode_rope_find_it_bind', 'f') -" Bind keys for organize imports (leave empty for disable) -call pymode#default('g:pymode_rope_organize_imports_bind', 'ro') + " Bind keys for organize imports (leave empty for disable) + call pymode#default('g:pymode_rope_organize_imports_bind', 'ro') -" Bind keys for rename variable/method/class in the project (leave empty for disable) -call pymode#default('g:pymode_rope_rename_bind', 'rr') + " Bind keys for rename variable/method/class in the project (leave empty for disable) + call pymode#default('g:pymode_rope_rename_bind', 'rr') -" Bind keys for rename module -call pymode#default('g:pymode_rope_rename_module_bind', 'r1r') + " Bind keys for rename module + call pymode#default('g:pymode_rope_rename_module_bind', 'r1r') -" Bind keys for convert module to package -call pymode#default('g:pymode_rope_module_to_package_bind', 'r1p') + " Bind keys for convert module to package + call pymode#default('g:pymode_rope_module_to_package_bind', 'r1p') -" Creates a new function or method (depending on the context) from the selected lines -call pymode#default('g:pymode_rope_extract_method_bind', 'rm') + " Creates a new function or method (depending on the context) from the selected lines + call pymode#default('g:pymode_rope_extract_method_bind', 'rm') -" Creates a variable from the selected lines -call pymode#default('g:pymode_rope_extract_variable_bind', 'rl') + " Creates a variable from the selected lines + call pymode#default('g:pymode_rope_extract_variable_bind', 'rl') -" Inline refactoring -call pymode#default('g:pymode_rope_inline_bind', 'ri') + " Inline refactoring + call pymode#default('g:pymode_rope_inline_bind', 'ri') -" Move refactoring -call pymode#default('g:pymode_rope_move_bind', 'rv') + " Move refactoring + call pymode#default('g:pymode_rope_move_bind', 'rv') -" Generate function -call pymode#default('g:pymode_rope_generate_function_bind', 'rnf') + " Generate function + call pymode#default('g:pymode_rope_generate_function_bind', 'rnf') -" Generate class -call pymode#default('g:pymode_rope_generate_class_bind', 'rnc') + " Generate class + call pymode#default('g:pymode_rope_generate_class_bind', 'rnc') -" Generate package -call pymode#default('g:pymode_rope_generate_package_bind', 'rnp') + " Generate package + call pymode#default('g:pymode_rope_generate_package_bind', 'rnp') -" Change signature -call pymode#default('g:pymode_rope_change_signature_bind', 'rs') + " Change signature + call pymode#default('g:pymode_rope_change_signature_bind', 'rs') -" Tries to find the places in which a function can be used and changes the -" code to call it instead -call pymode#default('g:pymode_rope_use_function_bind', 'ru') + " Tries to find the places in which a function can be used and changes the + " code to call it instead + call pymode#default('g:pymode_rope_use_function_bind', 'ru') -" Regenerate project cache on every save -call pymode#default('g:pymode_rope_regenerate_on_write', 1) + " Regenerate project cache on every save + call pymode#default('g:pymode_rope_regenerate_on_write', 1) +endif " }}} @@ -268,31 +287,16 @@ if &compatible 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") + if (exists('g:_uspy') && g:_uspy == ':py3') || 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 - let g:UltiSnipsUsePythonVersion = 2 - -elseif g:pymode_python == 'python3' +if g:pymode_python == 'python3' command! -nargs=1 PymodePython python3 let g:UltiSnipsUsePythonVersion = 3 @@ -310,7 +314,6 @@ else endif - command! PymodeVersion echomsg "Pymode version: " . g:pymode_version . " interpreter: " . g:pymode_python . " lint: " . g:pymode_lint . " rope: " . g:pymode_rope augroup pymode diff --git a/pymode/__init__.py b/pymode/__init__.py index d5e63ba3..aba22870 100644 --- a/pymode/__init__.py +++ b/pymode/__init__.py @@ -1,23 +1,31 @@ -""" Pymode support functions. """ - -from __future__ import absolute_import +"""Pymode support functions.""" import sys +from importlib.machinery import PathFinder as _PathFinder + import vim # noqa +if not hasattr(vim, 'find_module'): + vim.find_module = _PathFinder.find_module + def auto(): - """ Fix PEP8 erorrs in current buffer. """ + """Fix PEP8 erorrs in current buffer. + + pymode: uses it in command PymodeLintAuto with pymode#lint#auto() + + """ from .autopep8 import fix_file class Options(object): - aggressive = 2 + aggressive = 1 diff = False experimental = True ignore = vim.eval('g:pymode_lint_ignore') in_place = True indent_size = int(vim.eval('&tabstop')) line_range = None + hang_closing = False max_line_length = int(vim.eval('g:pymode_options_max_line_length')) pep8_passes = 100 recursive = False @@ -28,8 +36,8 @@ class Options(object): def get_documentation(): - """ Search documentation and append to current buffer. """ - from ._compat import StringIO + """Search documentation and append to current buffer.""" + from io import StringIO sys.stdout, _ = StringIO(), sys.stdout help(vim.eval('a:word')) diff --git a/pymode/_compat.py b/pymode/_compat.py deleted file mode 100644 index d859f152..00000000 --- a/pymode/_compat.py +++ /dev/null @@ -1,98 +0,0 @@ -""" 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 diff --git a/pymode/async.py b/pymode/async.py index dd314d76..d211ac4a 100644 --- a/pymode/async.py +++ b/pymode/async.py @@ -1,6 +1,6 @@ """ Python-mode async support. """ -from ._compat import Queue +from queue import Queue # noqa RESULTS = Queue() diff --git a/pymode/autopep8.py b/pymode/autopep8.py deleted file mode 100644 index 62e5832f..00000000 --- a/pymode/autopep8.py +++ /dev/null @@ -1,3885 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2010-2011 Hideo Hattori -# Copyright (C) 2011-2013 Hideo Hattori, Steven Myint -# Copyright (C) 2013-2016 Hideo Hattori, Steven Myint, Bill Wendling -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -"""Automatically formats Python code to conform to the PEP 8 style guide. - -Fixes that only need be done once can be added by adding a function of the form -"fix_(source)" to this module. They should return the fixed source code. -These fixes are picked up by apply_global_fixes(). - -Fixes that depend on pycodestyle should be added as methods to FixPEP8. See the -class documentation for more information. - -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -import codecs -import collections -import copy -import difflib -import fnmatch -import inspect -import io -import keyword -import locale -import os -import re -import signal -import sys -import textwrap -import token -import tokenize - -import pycodestyle - - -try: - unicode -except NameError: - unicode = str - - -__version__ = '1.3.2' - - -CR = '\r' -LF = '\n' -CRLF = '\r\n' - - -PYTHON_SHEBANG_REGEX = re.compile(r'^#!.*\bpython[23]?\b\s*$') -LAMBDA_REGEX = re.compile(r'([\w.]+)\s=\slambda\s*([\(\)\w,\s.]*):') -COMPARE_NEGATIVE_REGEX = re.compile(r'\b(not)\s+([^][)(}{]+)\s+(in|is)\s') -BARE_EXCEPT_REGEX = re.compile(r'except\s*:') -STARTSWITH_DEF_REGEX = re.compile(r'^(async\s+def|def)\s.*\):') - - -# For generating line shortening candidates. -SHORTEN_OPERATOR_GROUPS = frozenset([ - frozenset([',']), - frozenset(['%']), - frozenset([',', '(', '[', '{']), - frozenset(['%', '(', '[', '{']), - frozenset([',', '(', '[', '{', '%', '+', '-', '*', '/', '//']), - frozenset(['%', '+', '-', '*', '/', '//']), -]) - - -DEFAULT_IGNORE = 'E24,W503' -DEFAULT_INDENT_SIZE = 4 - - -# W602 is handled separately due to the need to avoid "with_traceback". -CODE_TO_2TO3 = { - 'E231': ['ws_comma'], - 'E721': ['idioms'], - 'W601': ['has_key'], - 'W603': ['ne'], - 'W604': ['repr'], - 'W690': ['apply', - 'except', - 'exitfunc', - 'numliterals', - 'operator', - 'paren', - 'reduce', - 'renames', - 'standarderror', - 'sys_exc', - 'throw', - 'tuple_params', - 'xreadlines']} - - -if sys.platform == 'win32': # pragma: no cover - DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8') -else: - DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or - os.path.expanduser('~/.config'), 'pep8') -PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8') - - -MAX_PYTHON_FILE_DETECTION_BYTES = 1024 - - -def open_with_encoding(filename, - encoding=None, mode='r', limit_byte_check=-1): - """Return opened file with a specific encoding.""" - if not encoding: - encoding = detect_encoding(filename, limit_byte_check=limit_byte_check) - - return io.open(filename, mode=mode, encoding=encoding, - newline='') # Preserve line endings - - -def detect_encoding(filename, limit_byte_check=-1): - """Return file encoding.""" - try: - with open(filename, 'rb') as input_file: - from lib2to3.pgen2 import tokenize as lib2to3_tokenize - encoding = lib2to3_tokenize.detect_encoding(input_file.readline)[0] - - with open_with_encoding(filename, encoding) as test_file: - test_file.read(limit_byte_check) - - return encoding - except (LookupError, SyntaxError, UnicodeDecodeError): - return 'latin-1' - - -def readlines_from_file(filename): - """Return contents of file.""" - with open_with_encoding(filename) as input_file: - return input_file.readlines() - - -def extended_blank_lines(logical_line, - blank_lines, - blank_before, - indent_level, - previous_logical): - """Check for missing blank lines after class declaration.""" - if previous_logical.startswith('def '): - if blank_lines and pycodestyle.DOCSTRING_REGEX.match(logical_line): - yield (0, 'E303 too many blank lines ({0})'.format(blank_lines)) - elif pycodestyle.DOCSTRING_REGEX.match(previous_logical): - # Missing blank line between class docstring and method declaration. - if ( - indent_level and - not blank_lines and - not blank_before and - logical_line.startswith(('def ')) and - '(self' in logical_line - ): - yield (0, 'E301 expected 1 blank line, found 0') - - -pycodestyle.register_check(extended_blank_lines) - - -def continued_indentation(logical_line, tokens, indent_level, indent_char, - noqa): - """Override pycodestyle's function to provide indentation information.""" - first_row = tokens[0][2][0] - nrows = 1 + tokens[-1][2][0] - first_row - if noqa or nrows == 1: - return - - # indent_next tells us whether the next block is indented. Assuming - # that it is indented by 4 spaces, then we should not allow 4-space - # indents on the final continuation line. In turn, some other - # indents are allowed to have an extra 4 spaces. - indent_next = logical_line.endswith(':') - - row = depth = 0 - valid_hangs = ( - (DEFAULT_INDENT_SIZE,) - if indent_char != '\t' else (DEFAULT_INDENT_SIZE, - 2 * DEFAULT_INDENT_SIZE) - ) - - # Remember how many brackets were opened on each line. - parens = [0] * nrows - - # Relative indents of physical lines. - rel_indent = [0] * nrows - - # For each depth, collect a list of opening rows. - open_rows = [[0]] - # For each depth, memorize the hanging indentation. - hangs = [None] - - # Visual indents. - indent_chances = {} - last_indent = tokens[0][2] - indent = [last_indent[1]] - - last_token_multiline = None - line = None - last_line = '' - last_line_begins_with_multiline = False - for token_type, text, start, end, line in tokens: - - newline = row < start[0] - first_row - if newline: - row = start[0] - first_row - newline = (not last_token_multiline and - token_type not in (tokenize.NL, tokenize.NEWLINE)) - last_line_begins_with_multiline = last_token_multiline - - if newline: - # This is the beginning of a continuation line. - last_indent = start - - # Record the initial indent. - rel_indent[row] = pycodestyle.expand_indent(line) - indent_level - - # Identify closing bracket. - close_bracket = (token_type == tokenize.OP and text in ']})') - - # Is the indent relative to an opening bracket line? - for open_row in reversed(open_rows[depth]): - hang = rel_indent[row] - rel_indent[open_row] - hanging_indent = hang in valid_hangs - if hanging_indent: - break - if hangs[depth]: - hanging_indent = (hang == hangs[depth]) - - visual_indent = (not close_bracket and hang > 0 and - indent_chances.get(start[1])) - - if close_bracket and indent[depth]: - # Closing bracket for visual indent. - if start[1] != indent[depth]: - yield (start, 'E124 {0}'.format(indent[depth])) - elif close_bracket and not hang: - pass - elif indent[depth] and start[1] < indent[depth]: - # Visual indent is broken. - yield (start, 'E128 {0}'.format(indent[depth])) - elif (hanging_indent or - (indent_next and - rel_indent[row] == 2 * DEFAULT_INDENT_SIZE)): - # Hanging indent is verified. - if close_bracket: - yield (start, 'E123 {0}'.format(indent_level + - rel_indent[open_row])) - hangs[depth] = hang - elif visual_indent is True: - # Visual indent is verified. - indent[depth] = start[1] - elif visual_indent in (text, unicode): - # Ignore token lined up with matching one from a previous line. - pass - else: - one_indented = (indent_level + rel_indent[open_row] + - DEFAULT_INDENT_SIZE) - # Indent is broken. - if hang <= 0: - error = ('E122', one_indented) - elif indent[depth]: - error = ('E127', indent[depth]) - elif not close_bracket and hangs[depth]: - error = ('E131', one_indented) - elif hang > DEFAULT_INDENT_SIZE: - error = ('E126', one_indented) - else: - hangs[depth] = hang - error = ('E121', one_indented) - - yield (start, '{0} {1}'.format(*error)) - - # Look for visual indenting. - if ( - parens[row] and - token_type not in (tokenize.NL, tokenize.COMMENT) and - not indent[depth] - ): - indent[depth] = start[1] - indent_chances[start[1]] = True - # Deal with implicit string concatenation. - elif (token_type in (tokenize.STRING, tokenize.COMMENT) or - text in ('u', 'ur', 'b', 'br')): - indent_chances[start[1]] = unicode - # Special case for the "if" statement because len("if (") is equal to - # 4. - elif not indent_chances and not row and not depth and text == 'if': - indent_chances[end[1] + 1] = True - elif text == ':' and line[end[1]:].isspace(): - open_rows[depth].append(row) - - # Keep track of bracket depth. - if token_type == tokenize.OP: - if text in '([{': - depth += 1 - indent.append(0) - hangs.append(None) - if len(open_rows) == depth: - open_rows.append([]) - open_rows[depth].append(row) - parens[row] += 1 - elif text in ')]}' and depth > 0: - # Parent indents should not be more than this one. - prev_indent = indent.pop() or last_indent[1] - hangs.pop() - for d in range(depth): - if indent[d] > prev_indent: - indent[d] = 0 - for ind in list(indent_chances): - if ind >= prev_indent: - del indent_chances[ind] - del open_rows[depth + 1:] - depth -= 1 - if depth: - indent_chances[indent[depth]] = True - for idx in range(row, -1, -1): - if parens[idx]: - parens[idx] -= 1 - break - assert len(indent) == depth + 1 - if ( - start[1] not in indent_chances and - # This is for purposes of speeding up E121 (GitHub #90). - not last_line.rstrip().endswith(',') - ): - # Allow to line up tokens. - indent_chances[start[1]] = text - - last_token_multiline = (start[0] != end[0]) - if last_token_multiline: - rel_indent[end[0] - first_row] = rel_indent[row] - - last_line = line - - if ( - indent_next and - not last_line_begins_with_multiline and - pycodestyle.expand_indent(line) == indent_level + DEFAULT_INDENT_SIZE - ): - pos = (start[0], indent[0] + 4) - desired_indent = indent_level + 2 * DEFAULT_INDENT_SIZE - if visual_indent: - yield (pos, 'E129 {0}'.format(desired_indent)) - else: - yield (pos, 'E125 {0}'.format(desired_indent)) - - -del pycodestyle._checks['logical_line'][pycodestyle.continued_indentation] -pycodestyle.register_check(continued_indentation) - - -class FixPEP8(object): - - """Fix invalid code. - - Fixer methods are prefixed "fix_". The _fix_source() method looks for these - automatically. - - The fixer method can take either one or two arguments (in addition to - self). The first argument is "result", which is the error information from - pycodestyle. The second argument, "logical", is required only for - logical-line fixes. - - The fixer method can return the list of modified lines or None. An empty - list would mean that no changes were made. None would mean that only the - line reported in the pycodestyle error was modified. Note that the modified - line numbers that are returned are indexed at 1. This typically would - correspond with the line number reported in the pycodestyle error - information. - - [fixed method list] - - e111,e114,e115,e116 - - e121,e122,e123,e124,e125,e126,e127,e128,e129 - - e201,e202,e203 - - e211 - - e221,e222,e223,e224,e225 - - e231 - - e251 - - e261,e262 - - e271,e272,e273,e274 - - e301,e302,e303,e304,e306 - - e401 - - e502 - - e701,e702,e703,e704 - - e711,e712,e713,e714 - - e722 - - e731 - - w291 - - w503 - - """ - - def __init__(self, filename, - options, - contents=None, - long_line_ignore_cache=None): - self.filename = filename - if contents is None: - self.source = readlines_from_file(filename) - else: - sio = io.StringIO(contents) - self.source = sio.readlines() - self.options = options - self.indent_word = _get_indentword(''.join(self.source)) - - self.long_line_ignore_cache = ( - set() if long_line_ignore_cache is None - else long_line_ignore_cache) - - # Many fixers are the same even though pycodestyle categorizes them - # differently. - self.fix_e115 = self.fix_e112 - self.fix_e116 = self.fix_e113 - self.fix_e121 = self._fix_reindent - self.fix_e122 = self._fix_reindent - self.fix_e123 = self._fix_reindent - self.fix_e124 = self._fix_reindent - self.fix_e126 = self._fix_reindent - self.fix_e127 = self._fix_reindent - self.fix_e128 = self._fix_reindent - self.fix_e129 = self._fix_reindent - self.fix_e202 = self.fix_e201 - self.fix_e203 = self.fix_e201 - self.fix_e211 = self.fix_e201 - self.fix_e221 = self.fix_e271 - self.fix_e222 = self.fix_e271 - self.fix_e223 = self.fix_e271 - self.fix_e226 = self.fix_e225 - self.fix_e227 = self.fix_e225 - self.fix_e228 = self.fix_e225 - self.fix_e241 = self.fix_e271 - self.fix_e242 = self.fix_e224 - self.fix_e261 = self.fix_e262 - self.fix_e272 = self.fix_e271 - self.fix_e273 = self.fix_e271 - self.fix_e274 = self.fix_e271 - self.fix_e306 = self.fix_e301 - self.fix_e501 = ( - self.fix_long_line_logically if - options and (options.aggressive >= 2 or options.experimental) else - self.fix_long_line_physically) - self.fix_e703 = self.fix_e702 - self.fix_w293 = self.fix_w291 - - def _fix_source(self, results): - try: - (logical_start, logical_end) = _find_logical(self.source) - logical_support = True - except (SyntaxError, tokenize.TokenError): # pragma: no cover - logical_support = False - - completed_lines = set() - for result in sorted(results, key=_priority_key): - if result['line'] in completed_lines: - continue - - fixed_methodname = 'fix_' + result['id'].lower() - if hasattr(self, fixed_methodname): - fix = getattr(self, fixed_methodname) - - line_index = result['line'] - 1 - original_line = self.source[line_index] - - is_logical_fix = len(_get_parameters(fix)) > 2 - if is_logical_fix: - logical = None - if logical_support: - logical = _get_logical(self.source, - result, - logical_start, - logical_end) - if logical and set(range( - logical[0][0] + 1, - logical[1][0] + 1)).intersection( - completed_lines): - continue - - modified_lines = fix(result, logical) - else: - modified_lines = fix(result) - - if modified_lines is None: - # Force logical fixes to report what they modified. - assert not is_logical_fix - - if self.source[line_index] == original_line: - modified_lines = [] - - if modified_lines: - completed_lines.update(modified_lines) - elif modified_lines == []: # Empty list means no fix - if self.options.verbose >= 2: - print( - '---> Not fixing {error} on line {line}'.format( - error=result['id'], line=result['line']), - file=sys.stderr) - else: # We assume one-line fix when None. - completed_lines.add(result['line']) - else: - if self.options.verbose >= 3: - print( - "---> '{0}' is not defined.".format(fixed_methodname), - file=sys.stderr) - - info = result['info'].strip() - print('---> {0}:{1}:{2}:{3}'.format(self.filename, - result['line'], - result['column'], - info), - file=sys.stderr) - - def fix(self): - """Return a version of the source code with PEP 8 violations fixed.""" - pep8_options = { - 'ignore': self.options.ignore, - 'select': self.options.select, - 'max_line_length': self.options.max_line_length, - } - results = _execute_pep8(pep8_options, self.source) - - if self.options.verbose: - progress = {} - for r in results: - if r['id'] not in progress: - progress[r['id']] = set() - progress[r['id']].add(r['line']) - print('---> {n} issue(s) to fix {progress}'.format( - n=len(results), progress=progress), file=sys.stderr) - - if self.options.line_range: - start, end = self.options.line_range - results = [r for r in results - if start <= r['line'] <= end] - - self._fix_source(filter_results(source=''.join(self.source), - results=results, - aggressive=self.options.aggressive)) - - if self.options.line_range: - # If number of lines has changed then change line_range. - count = sum(sline.count('\n') - for sline in self.source[start - 1:end]) - self.options.line_range[1] = start + count - 1 - - return ''.join(self.source) - - def _fix_reindent(self, result): - """Fix a badly indented line. - - This is done by adding or removing from its initial indent only. - - """ - num_indent_spaces = int(result['info'].split()[1]) - line_index = result['line'] - 1 - target = self.source[line_index] - - self.source[line_index] = ' ' * num_indent_spaces + target.lstrip() - - def fix_e112(self, result): - """Fix under-indented comments.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - if not target.lstrip().startswith('#'): - # Don't screw with invalid syntax. - return [] - - self.source[line_index] = self.indent_word + target - - def fix_e113(self, result): - """Fix over-indented comments.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - indent = _get_indentation(target) - stripped = target.lstrip() - - if not stripped.startswith('#'): - # Don't screw with invalid syntax. - return [] - - self.source[line_index] = indent[1:] + stripped - - def fix_e125(self, result): - """Fix indentation undistinguish from the next logical line.""" - num_indent_spaces = int(result['info'].split()[1]) - line_index = result['line'] - 1 - target = self.source[line_index] - - spaces_to_add = num_indent_spaces - len(_get_indentation(target)) - indent = len(_get_indentation(target)) - modified_lines = [] - - while len(_get_indentation(self.source[line_index])) >= indent: - self.source[line_index] = (' ' * spaces_to_add + - self.source[line_index]) - modified_lines.append(1 + line_index) # Line indexed at 1. - line_index -= 1 - - return modified_lines - - def fix_e131(self, result): - """Fix indentation undistinguish from the next logical line.""" - num_indent_spaces = int(result['info'].split()[1]) - line_index = result['line'] - 1 - target = self.source[line_index] - - spaces_to_add = num_indent_spaces - len(_get_indentation(target)) - - if spaces_to_add >= 0: - self.source[line_index] = (' ' * spaces_to_add + - self.source[line_index]) - else: - offset = abs(spaces_to_add) - self.source[line_index] = self.source[line_index][offset:] - - def fix_e201(self, result): - """Remove extraneous whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - fixed = fix_whitespace(target, - offset=offset, - replacement='') - - self.source[line_index] = fixed - - def fix_e224(self, result): - """Remove extraneous whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + target[offset:].replace('\t', ' ') - self.source[result['line'] - 1] = fixed - - def fix_e225(self, result): - """Fix missing whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + ' ' + target[offset:] - - # Only proceed if non-whitespace characters match. - # And make sure we don't break the indentation. - if ( - fixed.replace(' ', '') == target.replace(' ', '') and - _get_indentation(fixed) == _get_indentation(target) - ): - self.source[result['line'] - 1] = fixed - error_code = result.get('id', 0) - try: - ts = generate_tokens(fixed) - except tokenize.TokenError: - return - if not check_syntax(fixed.lstrip()): - return - errors = list( - pycodestyle.missing_whitespace_around_operator(fixed, ts)) - for e in reversed(errors): - if error_code != e[1].split()[0]: - continue - offset = e[0][1] - fixed = fixed[:offset] + ' ' + fixed[offset:] - self.source[result['line'] - 1] = fixed - else: - return [] - - def fix_e231(self, result): - """Add missing whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - fixed = target[:offset].rstrip() + ' ' + target[offset:].lstrip() - self.source[line_index] = fixed - - def fix_e251(self, result): - """Remove whitespace around parameter '=' sign.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - # This is necessary since pycodestyle sometimes reports columns that - # goes past the end of the physical line. This happens in cases like, - # foo(bar\n=None) - c = min(result['column'] - 1, - len(target) - 1) - - if target[c].strip(): - fixed = target - else: - fixed = target[:c].rstrip() + target[c:].lstrip() - - # There could be an escaped newline - # - # def foo(a=\ - # 1) - if fixed.endswith(('=\\\n', '=\\\r\n', '=\\\r')): - self.source[line_index] = fixed.rstrip('\n\r \t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] # Line indexed at 1 - - self.source[result['line'] - 1] = fixed - - def fix_e262(self, result): - """Fix spacing after comment hash.""" - target = self.source[result['line'] - 1] - offset = result['column'] - - code = target[:offset].rstrip(' \t#') - comment = target[offset:].lstrip(' \t#') - - fixed = code + (' # ' + comment if comment.strip() else '\n') - - self.source[result['line'] - 1] = fixed - - def fix_e271(self, result): - """Fix extraneous whitespace around keywords.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - fixed = fix_whitespace(target, - offset=offset, - replacement=' ') - - if fixed == target: - return [] - else: - self.source[line_index] = fixed - - def fix_e301(self, result): - """Add missing blank line.""" - cr = '\n' - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e302(self, result): - """Add missing 2 blank lines.""" - add_linenum = 2 - int(result['info'].split()[-1]) - cr = '\n' * add_linenum - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e303(self, result): - """Remove extra blank lines.""" - delete_linenum = int(result['info'].split('(')[1].split(')')[0]) - 2 - delete_linenum = max(1, delete_linenum) - - # We need to count because pycodestyle reports an offset line number if - # there are comments. - cnt = 0 - line = result['line'] - 2 - modified_lines = [] - while cnt < delete_linenum and line >= 0: - if not self.source[line].strip(): - self.source[line] = '' - modified_lines.append(1 + line) # Line indexed at 1 - cnt += 1 - line -= 1 - - return modified_lines - - def fix_e304(self, result): - """Remove blank line following function decorator.""" - line = result['line'] - 2 - if not self.source[line].strip(): - self.source[line] = '' - - def fix_e305(self, result): - """Add missing 2 blank lines after end of function or class.""" - cr = '\n' - # check comment line - offset = result['line'] - 2 - while True: - if offset < 0: - break - line = self.source[offset].lstrip() - if not line: - break - if line[0] != '#': - break - offset -= 1 - offset += 1 - self.source[offset] = cr + self.source[offset] - - def fix_e401(self, result): - """Put imports on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - if not target.lstrip().startswith('import'): - return [] - - indentation = re.split(pattern=r'\bimport\b', - string=target, maxsplit=1)[0] - fixed = (target[:offset].rstrip('\t ,') + '\n' + - indentation + 'import ' + target[offset:].lstrip('\t ,')) - self.source[line_index] = fixed - - def fix_long_line_logically(self, result, logical): - """Try to make lines fit within --max-line-length characters.""" - if ( - not logical or - len(logical[2]) == 1 or - self.source[result['line'] - 1].lstrip().startswith('#') - ): - return self.fix_long_line_physically(result) - - start_line_index = logical[0][0] - end_line_index = logical[1][0] - logical_lines = logical[2] - - previous_line = get_item(self.source, start_line_index - 1, default='') - next_line = get_item(self.source, end_line_index + 1, default='') - - single_line = join_logical_line(''.join(logical_lines)) - - try: - fixed = self.fix_long_line( - target=single_line, - previous_line=previous_line, - next_line=next_line, - original=''.join(logical_lines)) - except (SyntaxError, tokenize.TokenError): - return self.fix_long_line_physically(result) - - if fixed: - for line_index in range(start_line_index, end_line_index + 1): - self.source[line_index] = '' - self.source[start_line_index] = fixed - return range(start_line_index + 1, end_line_index + 1) - - return [] - - def fix_long_line_physically(self, result): - """Try to make lines fit within --max-line-length characters.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - previous_line = get_item(self.source, line_index - 1, default='') - next_line = get_item(self.source, line_index + 1, default='') - - try: - fixed = self.fix_long_line( - target=target, - previous_line=previous_line, - next_line=next_line, - original=target) - except (SyntaxError, tokenize.TokenError): - return [] - - if fixed: - self.source[line_index] = fixed - return [line_index + 1] - - return [] - - def fix_long_line(self, target, previous_line, - next_line, original): - cache_entry = (target, previous_line, next_line) - if cache_entry in self.long_line_ignore_cache: - return [] - - if target.lstrip().startswith('#'): - if self.options.aggressive: - # Wrap commented lines. - return shorten_comment( - line=target, - max_line_length=self.options.max_line_length, - last_comment=not next_line.lstrip().startswith('#')) - else: - return [] - - fixed = get_fixed_long_line( - target=target, - previous_line=previous_line, - original=original, - indent_word=self.indent_word, - max_line_length=self.options.max_line_length, - aggressive=self.options.aggressive, - experimental=self.options.experimental, - verbose=self.options.verbose) - - if fixed and not code_almost_equal(original, fixed): - return fixed - - self.long_line_ignore_cache.add(cache_entry) - return None - - def fix_e502(self, result): - """Remove extraneous escape of newline.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - self.source[line_index] = target.rstrip('\n\r \t\\') + '\n' - - def fix_e701(self, result): - """Put colon-separated compound statement on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - c = result['column'] - - fixed_source = (target[:c] + '\n' + - _get_indentation(target) + self.indent_word + - target[c:].lstrip('\n\r \t\\')) - self.source[result['line'] - 1] = fixed_source - return [result['line'], result['line'] + 1] - - def fix_e702(self, result, logical): - """Put semicolon-separated compound statement on separate lines.""" - if not logical: - return [] # pragma: no cover - logical_lines = logical[2] - - # Avoid applying this when indented. - # https://docs.python.org/reference/compound_stmts.html - for line in logical_lines: - if ':' in line: - return [] - - line_index = result['line'] - 1 - target = self.source[line_index] - - if target.rstrip().endswith('\\'): - # Normalize '1; \\\n2' into '1; 2'. - self.source[line_index] = target.rstrip('\n \r\t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] - - if target.rstrip().endswith(';'): - self.source[line_index] = target.rstrip('\n \r\t;') + '\n' - return [line_index + 1] - - offset = result['column'] - 1 - first = target[:offset].rstrip(';').rstrip() - second = (_get_indentation(logical_lines[0]) + - target[offset:].lstrip(';').lstrip()) - - # Find inline comment. - inline_comment = None - if target[offset:].lstrip(';').lstrip()[:2] == '# ': - inline_comment = target[offset:].lstrip(';') - - if inline_comment: - self.source[line_index] = first + inline_comment - else: - self.source[line_index] = first + '\n' + second - return [line_index + 1] - - def fix_e704(self, result): - """Fix multiple statements on one line def""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - match = STARTSWITH_DEF_REGEX.match(target) - if match: - self.source[line_index] = '{0}\n{1}{2}'.format( - match.group(0), - _get_indentation(target) + self.indent_word, - target[match.end(0):].lstrip()) - - def fix_e711(self, result): - """Fix comparison with None.""" - (line_index, offset, target) = get_index_offset_contents(result, - self.source) - - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - if not right.startswith('None'): - return [] - - if center.strip() == '==': - new_center = 'is' - elif center.strip() == '!=': - new_center = 'is not' - else: - return [] - - self.source[line_index] = ' '.join([left, new_center, right]) - - def fix_e712(self, result): - """Fix (trivial case of) comparison with boolean.""" - (line_index, offset, target) = get_index_offset_contents(result, - self.source) - - # Handle very easy "not" special cases. - if re.match(r'^\s*if [\w.]+ == False:$', target): - self.source[line_index] = re.sub(r'if ([\w.]+) == False:', - r'if not \1:', target, count=1) - elif re.match(r'^\s*if [\w.]+ != True:$', target): - self.source[line_index] = re.sub(r'if ([\w.]+) != True:', - r'if not \1:', target, count=1) - else: - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - # Handle simple cases only. - new_right = None - if center.strip() == '==': - if re.match(r'\bTrue\b', right): - new_right = re.sub(r'\bTrue\b *', '', right, count=1) - elif center.strip() == '!=': - if re.match(r'\bFalse\b', right): - new_right = re.sub(r'\bFalse\b *', '', right, count=1) - - if new_right is None: - return [] - - if new_right[0].isalnum(): - new_right = ' ' + new_right - - self.source[line_index] = left + new_right - - def fix_e713(self, result): - """Fix (trivial case of) non-membership check.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - - match = COMPARE_NEGATIVE_REGEX.search(target) - if match: - if match.group(3) == 'in': - pos_start = match.start(1) - self.source[line_index] = '{0}{1} {2} {3} {4}'.format( - target[:pos_start], match.group(2), match.group(1), - match.group(3), target[match.end():]) - - def fix_e714(self, result): - """Fix object identity should be 'is not' case.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - - match = COMPARE_NEGATIVE_REGEX.search(target) - if match: - if match.group(3) == 'is': - pos_start = match.start(1) - self.source[line_index] = '{0}{1} {2} {3} {4}'.format( - target[:pos_start], match.group(2), match.group(3), - match.group(1), target[match.end():]) - - def fix_e722(self, result): - """fix bare except""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - match = BARE_EXCEPT_REGEX.search(target) - if match: - self.source[line_index] = '{0}{1}{2}'.format( - target[:result['column'] - 1], "except BaseException:", - target[match.end():]) - - def fix_e731(self, result): - """Fix do not assign a lambda expression check.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - match = LAMBDA_REGEX.search(target) - if match: - end = match.end() - self.source[line_index] = '{0}def {1}({2}): return {3}'.format( - target[:match.start(0)], match.group(1), match.group(2), - target[end:].lstrip()) - - def fix_w291(self, result): - """Remove trailing whitespace.""" - fixed_line = self.source[result['line'] - 1].rstrip() - self.source[result['line'] - 1] = fixed_line + '\n' - - def fix_w391(self, _): - """Remove trailing blank lines.""" - blank_count = 0 - for line in reversed(self.source): - line = line.rstrip() - if line: - break - else: - blank_count += 1 - - original_length = len(self.source) - self.source = self.source[:original_length - blank_count] - return range(1, 1 + original_length) - - def fix_w503(self, result): - (line_index, _, target) = get_index_offset_contents(result, - self.source) - one_string_token = target.split()[0] - try: - ts = generate_tokens(one_string_token) - except tokenize.TokenError: - return - if not _is_binary_operator(ts[0][0], one_string_token): - return - # find comment - comment_index = None - for i in range(5): - # NOTE: try to parse code in 5 times - if (line_index - i) < 0: - break - from_index = line_index - i - 1 - to_index = line_index + 1 - try: - ts = generate_tokens("".join(self.source[from_index:to_index])) - except Exception: - continue - newline_count = 0 - newline_index = [] - for i, t in enumerate(ts): - if t[0] in (tokenize.NEWLINE, tokenize.NL): - newline_index.append(i) - newline_count += 1 - if newline_count > 2: - tts = ts[newline_index[-3]:] - else: - tts = ts - old = None - for t in tts: - if tokenize.COMMENT == t[0]: - if old is None: - comment_index = 0 - else: - comment_index = old[3][1] - break - old = t - break - i = target.index(one_string_token) - self.source[line_index] = '{0}{1}'.format( - target[:i], target[i + len(one_string_token):]) - nl = find_newline(self.source[line_index - 1:line_index]) - before_line = self.source[line_index - 1] - bl = before_line.index(nl) - if comment_index: - self.source[line_index - 1] = '{0} {1} {2}'.format( - before_line[:comment_index], one_string_token, - before_line[comment_index + 1:]) - else: - self.source[line_index - 1] = '{0} {1}{2}'.format( - before_line[:bl], one_string_token, before_line[bl:]) - - -def get_index_offset_contents(result, source): - """Return (line_index, column_offset, line_contents).""" - line_index = result['line'] - 1 - return (line_index, - result['column'] - 1, - source[line_index]) - - -def get_fixed_long_line(target, previous_line, original, - indent_word=' ', max_line_length=79, - aggressive=False, experimental=False, verbose=False): - """Break up long line and return result. - - Do this by generating multiple reformatted candidates and then - ranking the candidates to heuristically select the best option. - - """ - indent = _get_indentation(target) - source = target[len(indent):] - assert source.lstrip() == source - assert not target.lstrip().startswith('#') - - # Check for partial multiline. - tokens = list(generate_tokens(source)) - - candidates = shorten_line( - tokens, source, indent, - indent_word, - max_line_length, - aggressive=aggressive, - experimental=experimental, - previous_line=previous_line) - - # Also sort alphabetically as a tie breaker (for determinism). - candidates = sorted( - sorted(set(candidates).union([target, original])), - key=lambda x: line_shortening_rank( - x, - indent_word, - max_line_length, - experimental=experimental)) - - if verbose >= 4: - print(('-' * 79 + '\n').join([''] + candidates + ['']), - file=wrap_output(sys.stderr, 'utf-8')) - - if candidates: - best_candidate = candidates[0] - - # Don't allow things to get longer. - if longest_line_length(best_candidate) > longest_line_length(original): - return None - - return best_candidate - - -def longest_line_length(code): - """Return length of longest line.""" - return max(len(line) for line in code.splitlines()) - - -def join_logical_line(logical_line): - """Return single line based on logical line input.""" - indentation = _get_indentation(logical_line) - - return indentation + untokenize_without_newlines( - generate_tokens(logical_line.lstrip())) + '\n' - - -def untokenize_without_newlines(tokens): - """Return source code based on tokens.""" - text = '' - last_row = 0 - last_column = -1 - - for t in tokens: - token_string = t[1] - (start_row, start_column) = t[2] - (end_row, end_column) = t[3] - - if start_row > last_row: - last_column = 0 - if ( - (start_column > last_column or token_string == '\n') and - not text.endswith(' ') - ): - text += ' ' - - if token_string != '\n': - text += token_string - - last_row = end_row - last_column = end_column - - return text.rstrip() - - -def _find_logical(source_lines): - # Make a variable which is the index of all the starts of lines. - logical_start = [] - logical_end = [] - last_newline = True - parens = 0 - for t in generate_tokens(''.join(source_lines)): - if t[0] in [tokenize.COMMENT, tokenize.DEDENT, - tokenize.INDENT, tokenize.NL, - tokenize.ENDMARKER]: - continue - if not parens and t[0] in [tokenize.NEWLINE, tokenize.SEMI]: - last_newline = True - logical_end.append((t[3][0] - 1, t[2][1])) - continue - if last_newline and not parens: - logical_start.append((t[2][0] - 1, t[2][1])) - last_newline = False - if t[0] == tokenize.OP: - if t[1] in '([{': - parens += 1 - elif t[1] in '}])': - parens -= 1 - return (logical_start, logical_end) - - -def _get_logical(source_lines, result, logical_start, logical_end): - """Return the logical line corresponding to the result. - - Assumes input is already E702-clean. - - """ - row = result['line'] - 1 - col = result['column'] - 1 - ls = None - le = None - for i in range(0, len(logical_start), 1): - assert logical_end - x = logical_end[i] - if x[0] > row or (x[0] == row and x[1] > col): - le = x - ls = logical_start[i] - break - if ls is None: - return None - original = source_lines[ls[0]:le[0] + 1] - return ls, le, original - - -def get_item(items, index, default=None): - if 0 <= index < len(items): - return items[index] - - return default - - -def reindent(source, indent_size): - """Reindent all lines.""" - reindenter = Reindenter(source) - return reindenter.run(indent_size) - - -def code_almost_equal(a, b): - """Return True if code is similar. - - Ignore whitespace when comparing specific line. - - """ - split_a = split_and_strip_non_empty_lines(a) - split_b = split_and_strip_non_empty_lines(b) - - if len(split_a) != len(split_b): - return False - - for (index, _) in enumerate(split_a): - if ''.join(split_a[index].split()) != ''.join(split_b[index].split()): - return False - - return True - - -def split_and_strip_non_empty_lines(text): - """Return lines split by newline. - - Ignore empty lines. - - """ - return [line.strip() for line in text.splitlines() if line.strip()] - - -def fix_e265(source, aggressive=False): # pylint: disable=unused-argument - """Format block comments.""" - if '#' not in source: - # Optimization. - return source - - ignored_line_numbers = multiline_string_lines( - source, - include_docstrings=True) | set(commented_out_code_lines(source)) - - fixed_lines = [] - sio = io.StringIO(source) - for (line_number, line) in enumerate(sio.readlines(), start=1): - if ( - line.lstrip().startswith('#') and - line_number not in ignored_line_numbers and - not pycodestyle.noqa(line) - ): - indentation = _get_indentation(line) - line = line.lstrip() - - # Normalize beginning if not a shebang. - if len(line) > 1: - pos = next((index for index, c in enumerate(line) - if c != '#')) - if ( - # Leave multiple spaces like '# ' alone. - (line[:pos].count('#') > 1 or line[1].isalnum()) and - # Leave stylistic outlined blocks alone. - not line.rstrip().endswith('#') - ): - line = '# ' + line.lstrip('# \t') - - fixed_lines.append(indentation + line) - else: - fixed_lines.append(line) - - return ''.join(fixed_lines) - - -def refactor(source, fixer_names, ignore=None, filename=''): - """Return refactored code using lib2to3. - - Skip if ignore string is produced in the refactored code. - - """ - from lib2to3 import pgen2 - try: - new_text = refactor_with_2to3(source, - fixer_names=fixer_names, - filename=filename) - except (pgen2.parse.ParseError, - SyntaxError, - UnicodeDecodeError, - UnicodeEncodeError): - return source - - if ignore: - if ignore in new_text and ignore not in source: - return source - - return new_text - - -def code_to_2to3(select, ignore): - fixes = set() - for code, fix in CODE_TO_2TO3.items(): - if code_match(code, select=select, ignore=ignore): - fixes |= set(fix) - return fixes - - -def fix_2to3(source, - aggressive=True, select=None, ignore=None, filename=''): - """Fix various deprecated code (via lib2to3).""" - if not aggressive: - return source - - select = select or [] - ignore = ignore or [] - - return refactor(source, - code_to_2to3(select=select, - ignore=ignore), - filename=filename) - - -def fix_w602(source, aggressive=True): - """Fix deprecated form of raising exception.""" - if not aggressive: - return source - - return refactor(source, ['raise'], - ignore='with_traceback') - - -def find_newline(source): - """Return type of newline used in source. - - Input is a list of lines. - - """ - assert not isinstance(source, unicode) - - counter = collections.defaultdict(int) - for line in source: - if line.endswith(CRLF): - counter[CRLF] += 1 - elif line.endswith(CR): - counter[CR] += 1 - elif line.endswith(LF): - counter[LF] += 1 - - return (sorted(counter, key=counter.get, reverse=True) or [LF])[0] - - -def _get_indentword(source): - """Return indentation type.""" - indent_word = ' ' # Default in case source has no indentation - try: - for t in generate_tokens(source): - if t[0] == token.INDENT: - indent_word = t[1] - break - except (SyntaxError, tokenize.TokenError): - pass - return indent_word - - -def _get_indentation(line): - """Return leading whitespace.""" - if line.strip(): - non_whitespace_index = len(line) - len(line.lstrip()) - return line[:non_whitespace_index] - - return '' - - -def get_diff_text(old, new, filename): - """Return text of unified diff between old and new.""" - newline = '\n' - diff = difflib.unified_diff( - old, new, - 'original/' + filename, - 'fixed/' + filename, - lineterm=newline) - - text = '' - for line in diff: - text += line - - # Work around missing newline (http://bugs.python.org/issue2142). - if text and not line.endswith(newline): - text += newline + r'\ No newline at end of file' + newline - - return text - - -def _priority_key(pep8_result): - """Key for sorting PEP8 results. - - Global fixes should be done first. This is important for things like - indentation. - - """ - priority = [ - # Fix multiline colon-based before semicolon based. - 'e701', - # Break multiline statements early. - 'e702', - # Things that make lines longer. - 'e225', 'e231', - # Remove extraneous whitespace before breaking lines. - 'e201', - # Shorten whitespace in comment before resorting to wrapping. - 'e262' - ] - middle_index = 10000 - lowest_priority = [ - # We need to shorten lines last since the logical fixer can get in a - # loop, which causes us to exit early. - 'e501', - 'w503' - ] - key = pep8_result['id'].lower() - try: - return priority.index(key) - except ValueError: - try: - return middle_index + lowest_priority.index(key) + 1 - except ValueError: - return middle_index - - -def shorten_line(tokens, source, indentation, indent_word, max_line_length, - aggressive=False, experimental=False, previous_line=''): - """Separate line at OPERATOR. - - Multiple candidates will be yielded. - - """ - for candidate in _shorten_line(tokens=tokens, - source=source, - indentation=indentation, - indent_word=indent_word, - aggressive=aggressive, - previous_line=previous_line): - yield candidate - - if aggressive: - for key_token_strings in SHORTEN_OPERATOR_GROUPS: - shortened = _shorten_line_at_tokens( - tokens=tokens, - source=source, - indentation=indentation, - indent_word=indent_word, - key_token_strings=key_token_strings, - aggressive=aggressive) - - if shortened is not None and shortened != source: - yield shortened - - if experimental: - for shortened in _shorten_line_at_tokens_new( - tokens=tokens, - source=source, - indentation=indentation, - max_line_length=max_line_length): - - yield shortened - - -def _shorten_line(tokens, source, indentation, indent_word, - aggressive=False, previous_line=''): - """Separate line at OPERATOR. - - The input is expected to be free of newlines except for inside multiline - strings and at the end. - - Multiple candidates will be yielded. - - """ - for (token_type, - token_string, - start_offset, - end_offset) in token_offsets(tokens): - - if ( - token_type == tokenize.COMMENT and - not is_probably_part_of_multiline(previous_line) and - not is_probably_part_of_multiline(source) and - not source[start_offset + 1:].strip().lower().startswith( - ('noqa', 'pragma:', 'pylint:')) - ): - # Move inline comments to previous line. - first = source[:start_offset] - second = source[start_offset:] - yield (indentation + second.strip() + '\n' + - indentation + first.strip() + '\n') - elif token_type == token.OP and token_string != '=': - # Don't break on '=' after keyword as this violates PEP 8. - - assert token_type != token.INDENT - - first = source[:end_offset] - - second_indent = indentation - if first.rstrip().endswith('('): - second_indent += indent_word - elif '(' in first: - second_indent += ' ' * (1 + first.find('(')) - else: - second_indent += indent_word - - second = (second_indent + source[end_offset:].lstrip()) - if ( - not second.strip() or - second.lstrip().startswith('#') - ): - continue - - # Do not begin a line with a comma - if second.lstrip().startswith(','): - continue - # Do end a line with a dot - if first.rstrip().endswith('.'): - continue - if token_string in '+-*/': - fixed = first + ' \\' + '\n' + second - else: - fixed = first + '\n' + second - - # Only fix if syntax is okay. - if check_syntax(normalize_multiline(fixed) - if aggressive else fixed): - yield indentation + fixed - - -def _is_binary_operator(token_type, text): - return ((token_type == tokenize.OP or text in ['and', 'or']) and - text not in '()[]{},:.;@=%~') - - -# A convenient way to handle tokens. -Token = collections.namedtuple('Token', ['token_type', 'token_string', - 'spos', 'epos', 'line']) - - -class ReformattedLines(object): - - """The reflowed lines of atoms. - - Each part of the line is represented as an "atom." They can be moved - around when need be to get the optimal formatting. - - """ - - ########################################################################### - # Private Classes - - class _Indent(object): - - """Represent an indentation in the atom stream.""" - - def __init__(self, indent_amt): - self._indent_amt = indent_amt - - def emit(self): - return ' ' * self._indent_amt - - @property - def size(self): - return self._indent_amt - - class _Space(object): - - """Represent a space in the atom stream.""" - - def emit(self): - return ' ' - - @property - def size(self): - return 1 - - class _LineBreak(object): - - """Represent a line break in the atom stream.""" - - def emit(self): - return '\n' - - @property - def size(self): - return 0 - - def __init__(self, max_line_length): - self._max_line_length = max_line_length - self._lines = [] - self._bracket_depth = 0 - self._prev_item = None - self._prev_prev_item = None - - def __repr__(self): - return self.emit() - - ########################################################################### - # Public Methods - - def add(self, obj, indent_amt, break_after_open_bracket): - if isinstance(obj, Atom): - self._add_item(obj, indent_amt) - return - - self._add_container(obj, indent_amt, break_after_open_bracket) - - def add_comment(self, item): - num_spaces = 2 - if len(self._lines) > 1: - if isinstance(self._lines[-1], self._Space): - num_spaces -= 1 - if len(self._lines) > 2: - if isinstance(self._lines[-2], self._Space): - num_spaces -= 1 - - while num_spaces > 0: - self._lines.append(self._Space()) - num_spaces -= 1 - self._lines.append(item) - - def add_indent(self, indent_amt): - self._lines.append(self._Indent(indent_amt)) - - def add_line_break(self, indent): - self._lines.append(self._LineBreak()) - self.add_indent(len(indent)) - - def add_line_break_at(self, index, indent_amt): - self._lines.insert(index, self._LineBreak()) - self._lines.insert(index + 1, self._Indent(indent_amt)) - - def add_space_if_needed(self, curr_text, equal=False): - if ( - not self._lines or isinstance( - self._lines[-1], (self._LineBreak, self._Indent, self._Space)) - ): - return - - prev_text = unicode(self._prev_item) - prev_prev_text = ( - unicode(self._prev_prev_item) if self._prev_prev_item else '') - - if ( - # The previous item was a keyword or identifier and the current - # item isn't an operator that doesn't require a space. - ((self._prev_item.is_keyword or self._prev_item.is_string or - self._prev_item.is_name or self._prev_item.is_number) and - (curr_text[0] not in '([{.,:}])' or - (curr_text[0] == '=' and equal))) or - - # Don't place spaces around a '.', unless it's in an 'import' - # statement. - ((prev_prev_text != 'from' and prev_text[-1] != '.' and - curr_text != 'import') and - - # Don't place a space before a colon. - curr_text[0] != ':' and - - # Don't split up ending brackets by spaces. - ((prev_text[-1] in '}])' and curr_text[0] not in '.,}])') or - - # Put a space after a colon or comma. - prev_text[-1] in ':,' or - - # Put space around '=' if asked to. - (equal and prev_text == '=') or - - # Put spaces around non-unary arithmetic operators. - ((self._prev_prev_item and - (prev_text not in '+-' and - (self._prev_prev_item.is_name or - self._prev_prev_item.is_number or - self._prev_prev_item.is_string)) and - prev_text in ('+', '-', '%', '*', '/', '//', '**', 'in'))))) - ): - self._lines.append(self._Space()) - - def previous_item(self): - """Return the previous non-whitespace item.""" - return self._prev_item - - def fits_on_current_line(self, item_extent): - return self.current_size() + item_extent <= self._max_line_length - - def current_size(self): - """The size of the current line minus the indentation.""" - size = 0 - for item in reversed(self._lines): - size += item.size - if isinstance(item, self._LineBreak): - break - - return size - - def line_empty(self): - return (self._lines and - isinstance(self._lines[-1], - (self._LineBreak, self._Indent))) - - def emit(self): - string = '' - for item in self._lines: - if isinstance(item, self._LineBreak): - string = string.rstrip() - string += item.emit() - - return string.rstrip() + '\n' - - ########################################################################### - # Private Methods - - def _add_item(self, item, indent_amt): - """Add an item to the line. - - Reflow the line to get the best formatting after the item is - inserted. The bracket depth indicates if the item is being - inserted inside of a container or not. - - """ - if self._prev_item and self._prev_item.is_string and item.is_string: - # Place consecutive string literals on separate lines. - self._lines.append(self._LineBreak()) - self._lines.append(self._Indent(indent_amt)) - - item_text = unicode(item) - if self._lines and self._bracket_depth: - # Adding the item into a container. - self._prevent_default_initializer_splitting(item, indent_amt) - - if item_text in '.,)]}': - self._split_after_delimiter(item, indent_amt) - - elif self._lines and not self.line_empty(): - # Adding the item outside of a container. - if self.fits_on_current_line(len(item_text)): - self._enforce_space(item) - - else: - # Line break for the new item. - self._lines.append(self._LineBreak()) - self._lines.append(self._Indent(indent_amt)) - - self._lines.append(item) - self._prev_item, self._prev_prev_item = item, self._prev_item - - if item_text in '([{': - self._bracket_depth += 1 - - elif item_text in '}])': - self._bracket_depth -= 1 - assert self._bracket_depth >= 0 - - def _add_container(self, container, indent_amt, break_after_open_bracket): - actual_indent = indent_amt + 1 - - if ( - unicode(self._prev_item) != '=' and - not self.line_empty() and - not self.fits_on_current_line( - container.size + self._bracket_depth + 2) - ): - - if unicode(container)[0] == '(' and self._prev_item.is_name: - # Don't split before the opening bracket of a call. - break_after_open_bracket = True - actual_indent = indent_amt + 4 - elif ( - break_after_open_bracket or - unicode(self._prev_item) not in '([{' - ): - # If the container doesn't fit on the current line and the - # current line isn't empty, place the container on the next - # line. - self._lines.append(self._LineBreak()) - self._lines.append(self._Indent(indent_amt)) - break_after_open_bracket = False - else: - actual_indent = self.current_size() + 1 - break_after_open_bracket = False - - if isinstance(container, (ListComprehension, IfExpression)): - actual_indent = indent_amt - - # Increase the continued indentation only if recursing on a - # container. - container.reflow(self, ' ' * actual_indent, - break_after_open_bracket=break_after_open_bracket) - - def _prevent_default_initializer_splitting(self, item, indent_amt): - """Prevent splitting between a default initializer. - - When there is a default initializer, it's best to keep it all on - the same line. It's nicer and more readable, even if it goes - over the maximum allowable line length. This goes back along the - current line to determine if we have a default initializer, and, - if so, to remove extraneous whitespaces and add a line - break/indent before it if needed. - - """ - if unicode(item) == '=': - # This is the assignment in the initializer. Just remove spaces for - # now. - self._delete_whitespace() - return - - if (not self._prev_item or not self._prev_prev_item or - unicode(self._prev_item) != '='): - return - - self._delete_whitespace() - prev_prev_index = self._lines.index(self._prev_prev_item) - - if ( - isinstance(self._lines[prev_prev_index - 1], self._Indent) or - self.fits_on_current_line(item.size + 1) - ): - # The default initializer is already the only item on this line. - # Don't insert a newline here. - return - - # Replace the space with a newline/indent combo. - if isinstance(self._lines[prev_prev_index - 1], self._Space): - del self._lines[prev_prev_index - 1] - - self.add_line_break_at(self._lines.index(self._prev_prev_item), - indent_amt) - - def _split_after_delimiter(self, item, indent_amt): - """Split the line only after a delimiter.""" - self._delete_whitespace() - - if self.fits_on_current_line(item.size): - return - - last_space = None - for current_item in reversed(self._lines): - if ( - last_space and - (not isinstance(current_item, Atom) or - not current_item.is_colon) - ): - break - else: - last_space = None - if isinstance(current_item, self._Space): - last_space = current_item - if isinstance(current_item, (self._LineBreak, self._Indent)): - return - - if not last_space: - return - - self.add_line_break_at(self._lines.index(last_space), indent_amt) - - def _enforce_space(self, item): - """Enforce a space in certain situations. - - There are cases where we will want a space where normally we - wouldn't put one. This just enforces the addition of a space. - - """ - if isinstance(self._lines[-1], - (self._Space, self._LineBreak, self._Indent)): - return - - if not self._prev_item: - return - - item_text = unicode(item) - prev_text = unicode(self._prev_item) - - # Prefer a space around a '.' in an import statement, and between the - # 'import' and '('. - if ( - (item_text == '.' and prev_text == 'from') or - (item_text == 'import' and prev_text == '.') or - (item_text == '(' and prev_text == 'import') - ): - self._lines.append(self._Space()) - - def _delete_whitespace(self): - """Delete all whitespace from the end of the line.""" - while isinstance(self._lines[-1], (self._Space, self._LineBreak, - self._Indent)): - del self._lines[-1] - - -class Atom(object): - - """The smallest unbreakable unit that can be reflowed.""" - - def __init__(self, atom): - self._atom = atom - - def __repr__(self): - return self._atom.token_string - - def __len__(self): - return self.size - - def reflow( - self, reflowed_lines, continued_indent, extent, - break_after_open_bracket=False, - is_list_comp_or_if_expr=False, - next_is_dot=False - ): - if self._atom.token_type == tokenize.COMMENT: - reflowed_lines.add_comment(self) - return - - total_size = extent if extent else self.size - - if self._atom.token_string not in ',:([{}])': - # Some atoms will need an extra 1-sized space token after them. - total_size += 1 - - prev_item = reflowed_lines.previous_item() - if ( - not is_list_comp_or_if_expr and - not reflowed_lines.fits_on_current_line(total_size) and - not (next_is_dot and - reflowed_lines.fits_on_current_line(self.size + 1)) and - not reflowed_lines.line_empty() and - not self.is_colon and - not (prev_item and prev_item.is_name and - unicode(self) == '(') - ): - # Start a new line if there is already something on the line and - # adding this atom would make it go over the max line length. - reflowed_lines.add_line_break(continued_indent) - else: - reflowed_lines.add_space_if_needed(unicode(self)) - - reflowed_lines.add(self, len(continued_indent), - break_after_open_bracket) - - def emit(self): - return self.__repr__() - - @property - def is_keyword(self): - return keyword.iskeyword(self._atom.token_string) - - @property - def is_string(self): - return self._atom.token_type == tokenize.STRING - - @property - def is_name(self): - return self._atom.token_type == tokenize.NAME - - @property - def is_number(self): - return self._atom.token_type == tokenize.NUMBER - - @property - def is_comma(self): - return self._atom.token_string == ',' - - @property - def is_colon(self): - return self._atom.token_string == ':' - - @property - def size(self): - return len(self._atom.token_string) - - -class Container(object): - - """Base class for all container types.""" - - def __init__(self, items): - self._items = items - - def __repr__(self): - string = '' - last_was_keyword = False - - for item in self._items: - if item.is_comma: - string += ', ' - elif item.is_colon: - string += ': ' - else: - item_string = unicode(item) - if ( - string and - (last_was_keyword or - (not string.endswith(tuple('([{,.:}]) ')) and - not item_string.startswith(tuple('([{,.:}])')))) - ): - string += ' ' - string += item_string - - last_was_keyword = item.is_keyword - return string - - def __iter__(self): - for element in self._items: - yield element - - def __getitem__(self, idx): - return self._items[idx] - - def reflow(self, reflowed_lines, continued_indent, - break_after_open_bracket=False): - last_was_container = False - for (index, item) in enumerate(self._items): - next_item = get_item(self._items, index + 1) - - if isinstance(item, Atom): - is_list_comp_or_if_expr = ( - isinstance(self, (ListComprehension, IfExpression))) - item.reflow(reflowed_lines, continued_indent, - self._get_extent(index), - is_list_comp_or_if_expr=is_list_comp_or_if_expr, - next_is_dot=(next_item and - unicode(next_item) == '.')) - if last_was_container and item.is_comma: - reflowed_lines.add_line_break(continued_indent) - last_was_container = False - else: # isinstance(item, Container) - reflowed_lines.add(item, len(continued_indent), - break_after_open_bracket) - last_was_container = not isinstance(item, (ListComprehension, - IfExpression)) - - if ( - break_after_open_bracket and index == 0 and - # Prefer to keep empty containers together instead of - # separating them. - unicode(item) == self.open_bracket and - (not next_item or unicode(next_item) != self.close_bracket) and - (len(self._items) != 3 or not isinstance(next_item, Atom)) - ): - reflowed_lines.add_line_break(continued_indent) - break_after_open_bracket = False - else: - next_next_item = get_item(self._items, index + 2) - if ( - unicode(item) not in ['.', '%', 'in'] and - next_item and not isinstance(next_item, Container) and - unicode(next_item) != ':' and - next_next_item and (not isinstance(next_next_item, Atom) or - unicode(next_item) == 'not') and - not reflowed_lines.line_empty() and - not reflowed_lines.fits_on_current_line( - self._get_extent(index + 1) + 2) - ): - reflowed_lines.add_line_break(continued_indent) - - def _get_extent(self, index): - """The extent of the full element. - - E.g., the length of a function call or keyword. - - """ - extent = 0 - prev_item = get_item(self._items, index - 1) - seen_dot = prev_item and unicode(prev_item) == '.' - while index < len(self._items): - item = get_item(self._items, index) - index += 1 - - if isinstance(item, (ListComprehension, IfExpression)): - break - - if isinstance(item, Container): - if prev_item and prev_item.is_name: - if seen_dot: - extent += 1 - else: - extent += item.size - - prev_item = item - continue - elif (unicode(item) not in ['.', '=', ':', 'not'] and - not item.is_name and not item.is_string): - break - - if unicode(item) == '.': - seen_dot = True - - extent += item.size - prev_item = item - - return extent - - @property - def is_string(self): - return False - - @property - def size(self): - return len(self.__repr__()) - - @property - def is_keyword(self): - return False - - @property - def is_name(self): - return False - - @property - def is_comma(self): - return False - - @property - def is_colon(self): - return False - - @property - def open_bracket(self): - return None - - @property - def close_bracket(self): - return None - - -class Tuple(Container): - - """A high-level representation of a tuple.""" - - @property - def open_bracket(self): - return '(' - - @property - def close_bracket(self): - return ')' - - -class List(Container): - - """A high-level representation of a list.""" - - @property - def open_bracket(self): - return '[' - - @property - def close_bracket(self): - return ']' - - -class DictOrSet(Container): - - """A high-level representation of a dictionary or set.""" - - @property - def open_bracket(self): - return '{' - - @property - def close_bracket(self): - return '}' - - -class ListComprehension(Container): - - """A high-level representation of a list comprehension.""" - - @property - def size(self): - length = 0 - for item in self._items: - if isinstance(item, IfExpression): - break - length += item.size - return length - - -class IfExpression(Container): - - """A high-level representation of an if-expression.""" - - -def _parse_container(tokens, index, for_or_if=None): - """Parse a high-level container, such as a list, tuple, etc.""" - - # Store the opening bracket. - items = [Atom(Token(*tokens[index]))] - index += 1 - - num_tokens = len(tokens) - while index < num_tokens: - tok = Token(*tokens[index]) - - if tok.token_string in ',)]}': - # First check if we're at the end of a list comprehension or - # if-expression. Don't add the ending token as part of the list - # comprehension or if-expression, because they aren't part of those - # constructs. - if for_or_if == 'for': - return (ListComprehension(items), index - 1) - - elif for_or_if == 'if': - return (IfExpression(items), index - 1) - - # We've reached the end of a container. - items.append(Atom(tok)) - - # If not, then we are at the end of a container. - if tok.token_string == ')': - # The end of a tuple. - return (Tuple(items), index) - - elif tok.token_string == ']': - # The end of a list. - return (List(items), index) - - elif tok.token_string == '}': - # The end of a dictionary or set. - return (DictOrSet(items), index) - - elif tok.token_string in '([{': - # A sub-container is being defined. - (container, index) = _parse_container(tokens, index) - items.append(container) - - elif tok.token_string == 'for': - (container, index) = _parse_container(tokens, index, 'for') - items.append(container) - - elif tok.token_string == 'if': - (container, index) = _parse_container(tokens, index, 'if') - items.append(container) - - else: - items.append(Atom(tok)) - - index += 1 - - return (None, None) - - -def _parse_tokens(tokens): - """Parse the tokens. - - This converts the tokens into a form where we can manipulate them - more easily. - - """ - - index = 0 - parsed_tokens = [] - - num_tokens = len(tokens) - while index < num_tokens: - tok = Token(*tokens[index]) - - assert tok.token_type != token.INDENT - if tok.token_type == tokenize.NEWLINE: - # There's only one newline and it's at the end. - break - - if tok.token_string in '([{': - (container, index) = _parse_container(tokens, index) - if not container: - return None - parsed_tokens.append(container) - else: - parsed_tokens.append(Atom(tok)) - - index += 1 - - return parsed_tokens - - -def _reflow_lines(parsed_tokens, indentation, max_line_length, - start_on_prefix_line): - """Reflow the lines so that it looks nice.""" - - if unicode(parsed_tokens[0]) == 'def': - # A function definition gets indented a bit more. - continued_indent = indentation + ' ' * 2 * DEFAULT_INDENT_SIZE - else: - continued_indent = indentation + ' ' * DEFAULT_INDENT_SIZE - - break_after_open_bracket = not start_on_prefix_line - - lines = ReformattedLines(max_line_length) - lines.add_indent(len(indentation.lstrip('\r\n'))) - - if not start_on_prefix_line: - # If splitting after the opening bracket will cause the first element - # to be aligned weirdly, don't try it. - first_token = get_item(parsed_tokens, 0) - second_token = get_item(parsed_tokens, 1) - - if ( - first_token and second_token and - unicode(second_token)[0] == '(' and - len(indentation) + len(first_token) + 1 == len(continued_indent) - ): - return None - - for item in parsed_tokens: - lines.add_space_if_needed(unicode(item), equal=True) - - save_continued_indent = continued_indent - if start_on_prefix_line and isinstance(item, Container): - start_on_prefix_line = False - continued_indent = ' ' * (lines.current_size() + 1) - - item.reflow(lines, continued_indent, break_after_open_bracket) - continued_indent = save_continued_indent - - return lines.emit() - - -def _shorten_line_at_tokens_new(tokens, source, indentation, - max_line_length): - """Shorten the line taking its length into account. - - The input is expected to be free of newlines except for inside - multiline strings and at the end. - - """ - # Yield the original source so to see if it's a better choice than the - # shortened candidate lines we generate here. - yield indentation + source - - parsed_tokens = _parse_tokens(tokens) - - if parsed_tokens: - # Perform two reflows. The first one starts on the same line as the - # prefix. The second starts on the line after the prefix. - fixed = _reflow_lines(parsed_tokens, indentation, max_line_length, - start_on_prefix_line=True) - if fixed and check_syntax(normalize_multiline(fixed.lstrip())): - yield fixed - - fixed = _reflow_lines(parsed_tokens, indentation, max_line_length, - start_on_prefix_line=False) - if fixed and check_syntax(normalize_multiline(fixed.lstrip())): - yield fixed - - -def _shorten_line_at_tokens(tokens, source, indentation, indent_word, - key_token_strings, aggressive): - """Separate line by breaking at tokens in key_token_strings. - - The input is expected to be free of newlines except for inside - multiline strings and at the end. - - """ - offsets = [] - for (index, _t) in enumerate(token_offsets(tokens)): - (token_type, - token_string, - start_offset, - end_offset) = _t - - assert token_type != token.INDENT - - if token_string in key_token_strings: - # Do not break in containers with zero or one items. - unwanted_next_token = { - '(': ')', - '[': ']', - '{': '}'}.get(token_string) - if unwanted_next_token: - if ( - get_item(tokens, - index + 1, - default=[None, None])[1] == unwanted_next_token or - get_item(tokens, - index + 2, - default=[None, None])[1] == unwanted_next_token - ): - continue - - if ( - index > 2 and token_string == '(' and - tokens[index - 1][1] in ',(%[' - ): - # Don't split after a tuple start, or before a tuple start if - # the tuple is in a list. - continue - - if end_offset < len(source) - 1: - # Don't split right before newline. - offsets.append(end_offset) - else: - # Break at adjacent strings. These were probably meant to be on - # separate lines in the first place. - previous_token = get_item(tokens, index - 1) - if ( - token_type == tokenize.STRING and - previous_token and previous_token[0] == tokenize.STRING - ): - offsets.append(start_offset) - - current_indent = None - fixed = None - for line in split_at_offsets(source, offsets): - if fixed: - fixed += '\n' + current_indent + line - - for symbol in '([{': - if line.endswith(symbol): - current_indent += indent_word - else: - # First line. - fixed = line - assert not current_indent - current_indent = indent_word - - assert fixed is not None - - if check_syntax(normalize_multiline(fixed) - if aggressive > 1 else fixed): - return indentation + fixed - - return None - - -def token_offsets(tokens): - """Yield tokens and offsets.""" - end_offset = 0 - previous_end_row = 0 - previous_end_column = 0 - for t in tokens: - token_type = t[0] - token_string = t[1] - (start_row, start_column) = t[2] - (end_row, end_column) = t[3] - - # Account for the whitespace between tokens. - end_offset += start_column - if previous_end_row == start_row: - end_offset -= previous_end_column - - # Record the start offset of the token. - start_offset = end_offset - - # Account for the length of the token itself. - end_offset += len(token_string) - - yield (token_type, - token_string, - start_offset, - end_offset) - - previous_end_row = end_row - previous_end_column = end_column - - -def normalize_multiline(line): - """Normalize multiline-related code that will cause syntax error. - - This is for purposes of checking syntax. - - """ - if line.startswith('def ') and line.rstrip().endswith(':'): - return line + ' pass' - elif line.startswith('return '): - return 'def _(): ' + line - elif line.startswith('@'): - return line + 'def _(): pass' - elif line.startswith('class '): - return line + ' pass' - elif line.startswith(('if ', 'elif ', 'for ', 'while ')): - return line + ' pass' - - return line - - -def fix_whitespace(line, offset, replacement): - """Replace whitespace at offset and return fixed line.""" - # Replace escaped newlines too - left = line[:offset].rstrip('\n\r \t\\') - right = line[offset:].lstrip('\n\r \t\\') - if right.startswith('#'): - return line - - return left + replacement + right - - -def _execute_pep8(pep8_options, source): - """Execute pycodestyle via python method calls.""" - class QuietReport(pycodestyle.BaseReport): - - """Version of checker that does not print.""" - - def __init__(self, options): - super(QuietReport, self).__init__(options) - self.__full_error_results = [] - - def error(self, line_number, offset, text, check): - """Collect errors.""" - code = super(QuietReport, self).error(line_number, - offset, - text, - check) - if code: - self.__full_error_results.append( - {'id': code, - 'line': line_number, - 'column': offset + 1, - 'info': text}) - - def full_error_results(self): - """Return error results in detail. - - Results are in the form of a list of dictionaries. Each - dictionary contains 'id', 'line', 'column', and 'info'. - - """ - return self.__full_error_results - - checker = pycodestyle.Checker('', lines=source, reporter=QuietReport, - **pep8_options) - checker.check_all() - return checker.report.full_error_results() - - -def _remove_leading_and_normalize(line): - return line.lstrip().rstrip(CR + LF) + '\n' - - -class Reindenter(object): - - """Reindents badly-indented code to uniformly use four-space indentation. - - Released to the public domain, by Tim Peters, 03 October 2000. - - """ - - def __init__(self, input_text): - sio = io.StringIO(input_text) - source_lines = sio.readlines() - - self.string_content_line_numbers = multiline_string_lines(input_text) - - # File lines, rstripped & tab-expanded. Dummy at start is so - # that we can use tokenize's 1-based line numbering easily. - # Note that a line is all-blank iff it is a newline. - self.lines = [] - for line_number, line in enumerate(source_lines, start=1): - # Do not modify if inside a multiline string. - if line_number in self.string_content_line_numbers: - self.lines.append(line) - else: - # Only expand leading tabs. - self.lines.append(_get_indentation(line).expandtabs() + - _remove_leading_and_normalize(line)) - - self.lines.insert(0, None) - self.index = 1 # index into self.lines of next line - self.input_text = input_text - - def run(self, indent_size=DEFAULT_INDENT_SIZE): - """Fix indentation and return modified line numbers. - - Line numbers are indexed at 1. - - """ - if indent_size < 1: - return self.input_text - - try: - stats = _reindent_stats(tokenize.generate_tokens(self.getline)) - except (SyntaxError, tokenize.TokenError): - return self.input_text - # Remove trailing empty lines. - lines = self.lines - # Sentinel. - stats.append((len(lines), 0)) - # Map count of leading spaces to # we want. - have2want = {} - # Program after transformation. - after = [] - # Copy over initial empty lines -- there's nothing to do until - # we see a line with *something* on it. - i = stats[0][0] - after.extend(lines[1:i]) - for i in range(len(stats) - 1): - thisstmt, thislevel = stats[i] - nextstmt = stats[i + 1][0] - have = _leading_space_count(lines[thisstmt]) - want = thislevel * indent_size - if want < 0: - # A comment line. - if have: - # An indented comment line. If we saw the same - # indentation before, reuse what it most recently - # mapped to. - want = have2want.get(have, -1) - if want < 0: - # Then it probably belongs to the next real stmt. - for j in range(i + 1, len(stats) - 1): - jline, jlevel = stats[j] - if jlevel >= 0: - if have == _leading_space_count(lines[jline]): - want = jlevel * indent_size - break - if want < 0: # Maybe it's a hanging - # comment like this one, - # in which case we should shift it like its base - # line got shifted. - for j in range(i - 1, -1, -1): - jline, jlevel = stats[j] - if jlevel >= 0: - want = (have + _leading_space_count( - after[jline - 1]) - - _leading_space_count(lines[jline])) - break - if want < 0: - # Still no luck -- leave it alone. - want = have - else: - want = 0 - assert want >= 0 - have2want[have] = want - diff = want - have - if diff == 0 or have == 0: - after.extend(lines[thisstmt:nextstmt]) - else: - for line_number, line in enumerate(lines[thisstmt:nextstmt], - start=thisstmt): - if line_number in self.string_content_line_numbers: - after.append(line) - elif diff > 0: - if line == '\n': - after.append(line) - else: - after.append(' ' * diff + line) - else: - remove = min(_leading_space_count(line), -diff) - after.append(line[remove:]) - - return ''.join(after) - - def getline(self): - """Line-getter for tokenize.""" - if self.index >= len(self.lines): - line = '' - else: - line = self.lines[self.index] - self.index += 1 - return line - - -def _reindent_stats(tokens): - """Return list of (lineno, indentlevel) pairs. - - One for each stmt and comment line. indentlevel is -1 for comment - lines, as a signal that tokenize doesn't know what to do about them; - indeed, they're our headache! - - """ - find_stmt = 1 # Next token begins a fresh stmt? - level = 0 # Current indent level. - stats = [] - - for t in tokens: - token_type = t[0] - sline = t[2][0] - line = t[4] - - if token_type == tokenize.NEWLINE: - # A program statement, or ENDMARKER, will eventually follow, - # after some (possibly empty) run of tokens of the form - # (NL | COMMENT)* (INDENT | DEDENT+)? - find_stmt = 1 - - elif token_type == tokenize.INDENT: - find_stmt = 1 - level += 1 - - elif token_type == tokenize.DEDENT: - find_stmt = 1 - level -= 1 - - elif token_type == tokenize.COMMENT: - if find_stmt: - stats.append((sline, -1)) - # But we're still looking for a new stmt, so leave - # find_stmt alone. - - elif token_type == tokenize.NL: - pass - - elif find_stmt: - # This is the first "real token" following a NEWLINE, so it - # must be the first token of the next program statement, or an - # ENDMARKER. - find_stmt = 0 - if line: # Not endmarker. - stats.append((sline, level)) - - return stats - - -def _leading_space_count(line): - """Return number of leading spaces in line.""" - i = 0 - while i < len(line) and line[i] == ' ': - i += 1 - return i - - -def refactor_with_2to3(source_text, fixer_names, filename=''): - """Use lib2to3 to refactor the source. - - Return the refactored source code. - - """ - from lib2to3.refactor import RefactoringTool - fixers = ['lib2to3.fixes.fix_' + name for name in fixer_names] - tool = RefactoringTool(fixer_names=fixers, explicit=fixers) - - from lib2to3.pgen2 import tokenize as lib2to3_tokenize - try: - # The name parameter is necessary particularly for the "import" fixer. - return unicode(tool.refactor_string(source_text, name=filename)) - except lib2to3_tokenize.TokenError: - return source_text - - -def check_syntax(code): - """Return True if syntax is okay.""" - try: - return compile(code, '', 'exec') - except (SyntaxError, TypeError, UnicodeDecodeError): - return False - - -def filter_results(source, results, aggressive): - """Filter out spurious reports from pycodestyle. - - If aggressive is True, we allow possibly unsafe fixes (E711, E712). - - """ - non_docstring_string_line_numbers = multiline_string_lines( - source, include_docstrings=False) - all_string_line_numbers = multiline_string_lines( - source, include_docstrings=True) - - commented_out_code_line_numbers = commented_out_code_lines(source) - - has_e901 = any(result['id'].lower() == 'e901' for result in results) - - for r in results: - issue_id = r['id'].lower() - - if r['line'] in non_docstring_string_line_numbers: - if issue_id.startswith(('e1', 'e501', 'w191')): - continue - - if r['line'] in all_string_line_numbers: - if issue_id in ['e501']: - continue - - # We must offset by 1 for lines that contain the trailing contents of - # multiline strings. - if not aggressive and (r['line'] + 1) in all_string_line_numbers: - # Do not modify multiline strings in non-aggressive mode. Remove - # trailing whitespace could break doctests. - if issue_id.startswith(('w29', 'w39')): - continue - - if aggressive <= 0: - if issue_id.startswith(('e711', 'e72', 'w6')): - continue - - if aggressive <= 1: - if issue_id.startswith(('e712', 'e713', 'e714', 'w5')): - continue - - if aggressive <= 2: - if issue_id.startswith(('e704', 'w5')): - continue - - if r['line'] in commented_out_code_line_numbers: - if issue_id.startswith(('e26', 'e501')): - continue - - # Do not touch indentation if there is a token error caused by - # incomplete multi-line statement. Otherwise, we risk screwing up the - # indentation. - if has_e901: - if issue_id.startswith(('e1', 'e7')): - continue - - yield r - - -def multiline_string_lines(source, include_docstrings=False): - """Return line numbers that are within multiline strings. - - The line numbers are indexed at 1. - - Docstrings are ignored. - - """ - line_numbers = set() - previous_token_type = '' - try: - for t in generate_tokens(source): - token_type = t[0] - start_row = t[2][0] - end_row = t[3][0] - - if token_type == tokenize.STRING and start_row != end_row: - if ( - include_docstrings or - previous_token_type != tokenize.INDENT - ): - # We increment by one since we want the contents of the - # string. - line_numbers |= set(range(1 + start_row, 1 + end_row)) - - previous_token_type = token_type - except (SyntaxError, tokenize.TokenError): - pass - - return line_numbers - - -def commented_out_code_lines(source): - """Return line numbers of comments that are likely code. - - Commented-out code is bad practice, but modifying it just adds even - more clutter. - - """ - line_numbers = [] - try: - for t in generate_tokens(source): - token_type = t[0] - token_string = t[1] - start_row = t[2][0] - line = t[4] - - # Ignore inline comments. - if not line.lstrip().startswith('#'): - continue - - if token_type == tokenize.COMMENT: - stripped_line = token_string.lstrip('#').strip() - if ( - ' ' in stripped_line and - '#' not in stripped_line and - check_syntax(stripped_line) - ): - line_numbers.append(start_row) - except (SyntaxError, tokenize.TokenError): - pass - - return line_numbers - - -def shorten_comment(line, max_line_length, last_comment=False): - """Return trimmed or split long comment line. - - If there are no comments immediately following it, do a text wrap. - Doing this wrapping on all comments in general would lead to jagged - comment text. - - """ - assert len(line) > max_line_length - line = line.rstrip() - - # PEP 8 recommends 72 characters for comment text. - indentation = _get_indentation(line) + '# ' - max_line_length = min(max_line_length, - len(indentation) + 72) - - MIN_CHARACTER_REPEAT = 5 - if ( - len(line) - len(line.rstrip(line[-1])) >= MIN_CHARACTER_REPEAT and - not line[-1].isalnum() - ): - # Trim comments that end with things like --------- - return line[:max_line_length] + '\n' - elif last_comment and re.match(r'\s*#+\s*\w+', line): - split_lines = textwrap.wrap(line.lstrip(' \t#'), - initial_indent=indentation, - subsequent_indent=indentation, - width=max_line_length, - break_long_words=False, - break_on_hyphens=False) - return '\n'.join(split_lines) + '\n' - - return line + '\n' - - -def normalize_line_endings(lines, newline): - """Return fixed line endings. - - All lines will be modified to use the most common line ending. - - """ - return [line.rstrip('\n\r') + newline for line in lines] - - -def mutual_startswith(a, b): - return b.startswith(a) or a.startswith(b) - - -def code_match(code, select, ignore): - if ignore: - assert not isinstance(ignore, unicode) - for ignored_code in [c.strip() for c in ignore]: - if mutual_startswith(code.lower(), ignored_code.lower()): - return False - - if select: - assert not isinstance(select, unicode) - for selected_code in [c.strip() for c in select]: - if mutual_startswith(code.lower(), selected_code.lower()): - return True - return False - - return True - - -def fix_code(source, options=None, encoding=None, apply_config=False): - """Return fixed source code. - - "encoding" will be used to decode "source" if it is a byte string. - - """ - options = _get_options(options, apply_config) - - if not isinstance(source, unicode): - source = source.decode(encoding or get_encoding()) - - sio = io.StringIO(source) - return fix_lines(sio.readlines(), options=options) - - -def _get_options(raw_options, apply_config): - """Return parsed options.""" - if not raw_options: - return parse_args([''], apply_config=apply_config) - - if isinstance(raw_options, dict): - options = parse_args([''], apply_config=apply_config) - for name, value in raw_options.items(): - if not hasattr(options, name): - raise ValueError("No such option '{}'".format(name)) - - # Check for very basic type errors. - expected_type = type(getattr(options, name)) - if not isinstance(expected_type, (str, unicode)): - if isinstance(value, (str, unicode)): - raise ValueError( - "Option '{}' should not be a string".format(name)) - setattr(options, name, value) - else: - options = raw_options - - return options - - -def fix_lines(source_lines, options, filename=''): - """Return fixed source code.""" - # Transform everything to line feed. Then change them back to original - # before returning fixed source code. - original_newline = find_newline(source_lines) - tmp_source = ''.join(normalize_line_endings(source_lines, '\n')) - - # Keep a history to break out of cycles. - previous_hashes = set() - - if options.line_range: - # Disable "apply_local_fixes()" for now due to issue #175. - fixed_source = tmp_source - else: - # Apply global fixes only once (for efficiency). - fixed_source = apply_global_fixes(tmp_source, - options, - filename=filename) - - passes = 0 - long_line_ignore_cache = set() - while hash(fixed_source) not in previous_hashes: - if options.pep8_passes >= 0 and passes > options.pep8_passes: - break - passes += 1 - - previous_hashes.add(hash(fixed_source)) - - tmp_source = copy.copy(fixed_source) - - fix = FixPEP8( - filename, - options, - contents=tmp_source, - long_line_ignore_cache=long_line_ignore_cache) - - fixed_source = fix.fix() - - sio = io.StringIO(fixed_source) - return ''.join(normalize_line_endings(sio.readlines(), original_newline)) - - -def fix_file(filename, options=None, output=None, apply_config=False): - if not options: - options = parse_args([filename], apply_config=apply_config) - - original_source = readlines_from_file(filename) - - fixed_source = original_source - - if options.in_place or output: - encoding = detect_encoding(filename) - - if output: - output = LineEndingWrapper(wrap_output(output, encoding=encoding)) - - fixed_source = fix_lines(fixed_source, options, filename=filename) - - if options.diff: - new = io.StringIO(fixed_source) - new = new.readlines() - diff = get_diff_text(original_source, new, filename) - if output: - output.write(diff) - output.flush() - else: - return diff - elif options.in_place: - fp = open_with_encoding(filename, encoding=encoding, mode='w') - fp.write(fixed_source) - fp.close() - else: - if output: - output.write(fixed_source) - output.flush() - else: - return fixed_source - - -def global_fixes(): - """Yield multiple (code, function) tuples.""" - for function in list(globals().values()): - if inspect.isfunction(function): - arguments = _get_parameters(function) - if arguments[:1] != ['source']: - continue - - code = extract_code_from_function(function) - if code: - yield (code, function) - - -def _get_parameters(function): - # pylint: disable=deprecated-method - if sys.version_info >= (3, 3): - # We need to match "getargspec()", which includes "self" as the first - # value for methods. - # https://bugs.python.org/issue17481#msg209469 - if inspect.ismethod(function): - function = function.__func__ - - return list(inspect.signature(function).parameters) - else: - return inspect.getargspec(function)[0] - - -def apply_global_fixes(source, options, where='global', filename=''): - """Run global fixes on source code. - - These are fixes that only need be done once (unlike those in - FixPEP8, which are dependent on pycodestyle). - - """ - if any(code_match(code, select=options.select, ignore=options.ignore) - for code in ['E101', 'E111']): - source = reindent(source, - indent_size=options.indent_size) - - for (code, function) in global_fixes(): - if code_match(code, select=options.select, ignore=options.ignore): - if options.verbose: - print('---> Applying {0} fix for {1}'.format(where, - code.upper()), - file=sys.stderr) - source = function(source, - aggressive=options.aggressive) - - source = fix_2to3(source, - aggressive=options.aggressive, - select=options.select, - ignore=options.ignore, - filename=filename) - - return source - - -def extract_code_from_function(function): - """Return code handled by function.""" - if not function.__name__.startswith('fix_'): - return None - - code = re.sub('^fix_', '', function.__name__) - if not code: - return None - - try: - int(code[1:]) - except ValueError: - return None - - return code - - -def _get_package_version(): - packages = ["pycodestyle: {0}".format(pycodestyle.__version__)] - return ", ".join(packages) - - -def create_parser(): - """Return command-line parser.""" - # Do import locally to be friendly to those who use autopep8 as a library - # and are supporting Python 2.6. - import argparse - - parser = argparse.ArgumentParser(description=docstring_summary(__doc__), - prog='autopep8') - parser.add_argument('--version', action='version', - version='%(prog)s {0} ({1})'.format( - __version__, _get_package_version())) - parser.add_argument('-v', '--verbose', action='count', - default=0, - help='print verbose messages; ' - 'multiple -v result in more verbose messages') - parser.add_argument('-d', '--diff', action='store_true', - help='print the diff for the fixed source') - parser.add_argument('-i', '--in-place', action='store_true', - help='make changes to files in place') - parser.add_argument('--global-config', metavar='filename', - default=DEFAULT_CONFIG, - help='path to a global pep8 config file; if this file ' - 'does not exist then this is ignored ' - '(default: {0})'.format(DEFAULT_CONFIG)) - parser.add_argument('--ignore-local-config', action='store_true', - help="don't look for and apply local config files; " - 'if not passed, defaults are updated with any ' - "config files in the project's root directory") - parser.add_argument('-r', '--recursive', action='store_true', - help='run recursively over directories; ' - 'must be used with --in-place or --diff') - parser.add_argument('-j', '--jobs', type=int, metavar='n', default=1, - help='number of parallel jobs; ' - 'match CPU count if value is less than 1') - parser.add_argument('-p', '--pep8-passes', metavar='n', - default=-1, type=int, - help='maximum number of additional pep8 passes ' - '(default: infinite)') - parser.add_argument('-a', '--aggressive', action='count', default=0, - help='enable non-whitespace changes; ' - 'multiple -a result in more aggressive changes') - parser.add_argument('--experimental', action='store_true', - help='enable experimental fixes') - parser.add_argument('--exclude', metavar='globs', - help='exclude file/directory names that match these ' - 'comma-separated globs') - parser.add_argument('--list-fixes', action='store_true', - help='list codes for fixes; ' - 'used by --ignore and --select') - parser.add_argument('--ignore', metavar='errors', default='', - help='do not fix these errors/warnings ' - '(default: {0})'.format(DEFAULT_IGNORE)) - parser.add_argument('--select', metavar='errors', default='', - help='fix only these errors/warnings (e.g. E4,W)') - parser.add_argument('--max-line-length', metavar='n', default=79, type=int, - help='set maximum allowed line length ' - '(default: %(default)s)') - parser.add_argument('--line-range', '--range', metavar='line', - default=None, type=int, nargs=2, - help='only fix errors found within this inclusive ' - 'range of line numbers (e.g. 1 99); ' - 'line numbers are indexed at 1') - parser.add_argument('--indent-size', default=DEFAULT_INDENT_SIZE, - type=int, help=argparse.SUPPRESS) - parser.add_argument('files', nargs='*', - help="files to format or '-' for standard in") - - return parser - - -def parse_args(arguments, apply_config=False): - """Parse command-line options.""" - parser = create_parser() - args = parser.parse_args(arguments) - - if not args.files and not args.list_fixes: - parser.error('incorrect number of arguments') - - args.files = [decode_filename(name) for name in args.files] - - if apply_config: - parser = read_config(args, parser) - args = parser.parse_args(arguments) - args.files = [decode_filename(name) for name in args.files] - - if '-' in args.files: - if len(args.files) > 1: - parser.error('cannot mix stdin and regular files') - - if args.diff: - parser.error('--diff cannot be used with standard input') - - if args.in_place: - parser.error('--in-place cannot be used with standard input') - - if args.recursive: - parser.error('--recursive cannot be used with standard input') - - if len(args.files) > 1 and not (args.in_place or args.diff): - parser.error('autopep8 only takes one filename as argument ' - 'unless the "--in-place" or "--diff" args are ' - 'used') - - if args.recursive and not (args.in_place or args.diff): - parser.error('--recursive must be used with --in-place or --diff') - - if args.in_place and args.diff: - parser.error('--in-place and --diff are mutually exclusive') - - if args.max_line_length <= 0: - parser.error('--max-line-length must be greater than 0') - - if args.select: - args.select = _split_comma_separated(args.select) - - if args.ignore: - args.ignore = _split_comma_separated(args.ignore) - elif not args.select: - if args.aggressive: - # Enable everything by default if aggressive. - args.select = set(['E', 'W']) - else: - args.ignore = _split_comma_separated(DEFAULT_IGNORE) - - if args.exclude: - args.exclude = _split_comma_separated(args.exclude) - else: - args.exclude = set([]) - - if args.jobs < 1: - # Do not import multiprocessing globally in case it is not supported - # on the platform. - import multiprocessing - args.jobs = multiprocessing.cpu_count() - - if args.jobs > 1 and not args.in_place: - parser.error('parallel jobs requires --in-place') - - if args.line_range: - if args.line_range[0] <= 0: - parser.error('--range must be positive numbers') - if args.line_range[0] > args.line_range[1]: - parser.error('First value of --range should be less than or equal ' - 'to the second') - - return args - - -def read_config(args, parser): - """Read both user configuration and local configuration.""" - try: - from configparser import ConfigParser as SafeConfigParser - from configparser import Error - except ImportError: - from ConfigParser import SafeConfigParser - from ConfigParser import Error - - config = SafeConfigParser() - - try: - config.read(args.global_config) - - if not args.ignore_local_config: - parent = tail = args.files and os.path.abspath( - os.path.commonprefix(args.files)) - while tail: - if config.read([os.path.join(parent, fn) - for fn in PROJECT_CONFIG]): - break - (parent, tail) = os.path.split(parent) - - defaults = dict() - option_list = dict([(o.dest, o.type or type(o.default)) - for o in parser._actions]) - - for section in ['pep8', 'pycodestyle']: - if not config.has_section(section): - continue - for (k, _) in config.items(section): - norm_opt = k.lstrip('-').replace('-', '_') - opt_type = option_list[norm_opt] - if opt_type is int: - value = config.getint(section, k) - elif opt_type is bool: - value = config.getboolean(section, k) - else: - value = config.get(section, k) - defaults[norm_opt] = value - - parser.set_defaults(**defaults) - except Error: - # Ignore for now. - pass - - return parser - - -def _split_comma_separated(string): - """Return a set of strings.""" - return set(text.strip() for text in string.split(',') if text.strip()) - - -def decode_filename(filename): - """Return Unicode filename.""" - if isinstance(filename, unicode): - return filename - - return filename.decode(sys.getfilesystemencoding()) - - -def supported_fixes(): - """Yield pep8 error codes that autopep8 fixes. - - Each item we yield is a tuple of the code followed by its - description. - - """ - yield ('E101', docstring_summary(reindent.__doc__)) - - instance = FixPEP8(filename=None, options=None, contents='') - for attribute in dir(instance): - code = re.match('fix_([ew][0-9][0-9][0-9])', attribute) - if code: - yield ( - code.group(1).upper(), - re.sub(r'\s+', ' ', - docstring_summary(getattr(instance, attribute).__doc__)) - ) - - for (code, function) in sorted(global_fixes()): - yield (code.upper() + (4 - len(code)) * ' ', - re.sub(r'\s+', ' ', docstring_summary(function.__doc__))) - - for code in sorted(CODE_TO_2TO3): - yield (code.upper() + (4 - len(code)) * ' ', - re.sub(r'\s+', ' ', docstring_summary(fix_2to3.__doc__))) - - -def docstring_summary(docstring): - """Return summary of docstring.""" - return docstring.split('\n')[0] if docstring else '' - - -def line_shortening_rank(candidate, indent_word, max_line_length, - experimental=False): - """Return rank of candidate. - - This is for sorting candidates. - - """ - if not candidate.strip(): - return 0 - - rank = 0 - lines = candidate.rstrip().split('\n') - - offset = 0 - if ( - not lines[0].lstrip().startswith('#') and - lines[0].rstrip()[-1] not in '([{' - ): - for (opening, closing) in ('()', '[]', '{}'): - # Don't penalize empty containers that aren't split up. Things like - # this "foo(\n )" aren't particularly good. - opening_loc = lines[0].find(opening) - closing_loc = lines[0].find(closing) - if opening_loc >= 0: - if closing_loc < 0 or closing_loc != opening_loc + 1: - offset = max(offset, 1 + opening_loc) - - current_longest = max(offset + len(x.strip()) for x in lines) - - rank += 4 * max(0, current_longest - max_line_length) - - rank += len(lines) - - # Too much variation in line length is ugly. - rank += 2 * standard_deviation(len(line) for line in lines) - - bad_staring_symbol = { - '(': ')', - '[': ']', - '{': '}'}.get(lines[0][-1]) - - if len(lines) > 1: - if ( - bad_staring_symbol and - lines[1].lstrip().startswith(bad_staring_symbol) - ): - rank += 20 - - for lineno, current_line in enumerate(lines): - current_line = current_line.strip() - - if current_line.startswith('#'): - continue - - for bad_start in ['.', '%', '+', '-', '/']: - if current_line.startswith(bad_start): - rank += 100 - - # Do not tolerate operators on their own line. - if current_line == bad_start: - rank += 1000 - - if ( - current_line.endswith(('.', '%', '+', '-', '/')) and - "': " in current_line - ): - rank += 1000 - - if current_line.endswith(('(', '[', '{', '.')): - # Avoid lonely opening. They result in longer lines. - if len(current_line) <= len(indent_word): - rank += 100 - - # Avoid the ugliness of ", (\n". - if ( - current_line.endswith('(') and - current_line[:-1].rstrip().endswith(',') - ): - rank += 100 - - # Avoid the ugliness of "something[\n" and something[index][\n. - if ( - current_line.endswith('[') and - len(current_line) > 1 and - (current_line[-2].isalnum() or current_line[-2] in ']') - ): - rank += 300 - - # Also avoid the ugliness of "foo.\nbar" - if current_line.endswith('.'): - rank += 100 - - if has_arithmetic_operator(current_line): - rank += 100 - - # Avoid breaking at unary operators. - if re.match(r'.*[(\[{]\s*[\-\+~]$', current_line.rstrip('\\ ')): - rank += 1000 - - if re.match(r'.*lambda\s*\*$', current_line.rstrip('\\ ')): - rank += 1000 - - if current_line.endswith(('%', '(', '[', '{')): - rank -= 20 - - # Try to break list comprehensions at the "for". - if current_line.startswith('for '): - rank -= 50 - - if current_line.endswith('\\'): - # If a line ends in \-newline, it may be part of a - # multiline string. In that case, we would like to know - # how long that line is without the \-newline. If it's - # longer than the maximum, or has comments, then we assume - # that the \-newline is an okay candidate and only - # penalize it a bit. - total_len = len(current_line) - lineno += 1 - while lineno < len(lines): - total_len += len(lines[lineno]) - - if lines[lineno].lstrip().startswith('#'): - total_len = max_line_length - break - - if not lines[lineno].endswith('\\'): - break - - lineno += 1 - - if total_len < max_line_length: - rank += 10 - else: - rank += 100 if experimental else 1 - - # Prefer breaking at commas rather than colon. - if ',' in current_line and current_line.endswith(':'): - rank += 10 - - # Avoid splitting dictionaries between key and value. - if current_line.endswith(':'): - rank += 100 - - rank += 10 * count_unbalanced_brackets(current_line) - - return max(0, rank) - - -def standard_deviation(numbers): - """Return standard devation.""" - numbers = list(numbers) - if not numbers: - return 0 - mean = sum(numbers) / len(numbers) - return (sum((n - mean) ** 2 for n in numbers) / - len(numbers)) ** .5 - - -def has_arithmetic_operator(line): - """Return True if line contains any arithmetic operators.""" - for operator in pycodestyle.ARITHMETIC_OP: - if operator in line: - return True - - return False - - -def count_unbalanced_brackets(line): - """Return number of unmatched open/close brackets.""" - count = 0 - for opening, closing in ['()', '[]', '{}']: - count += abs(line.count(opening) - line.count(closing)) - - return count - - -def split_at_offsets(line, offsets): - """Split line at offsets. - - Return list of strings. - - """ - result = [] - - previous_offset = 0 - current_offset = 0 - for current_offset in sorted(offsets): - if current_offset < len(line) and previous_offset != current_offset: - result.append(line[previous_offset:current_offset].strip()) - previous_offset = current_offset - - result.append(line[current_offset:]) - - return result - - -class LineEndingWrapper(object): - - r"""Replace line endings to work with sys.stdout. - - It seems that sys.stdout expects only '\n' as the line ending, no matter - the platform. Otherwise, we get repeated line endings. - - """ - - def __init__(self, output): - self.__output = output - - def write(self, s): - self.__output.write(s.replace('\r\n', '\n').replace('\r', '\n')) - - def flush(self): - self.__output.flush() - - -def match_file(filename, exclude): - """Return True if file is okay for modifying/recursing.""" - base_name = os.path.basename(filename) - - if base_name.startswith('.'): - return False - - for pattern in exclude: - if fnmatch.fnmatch(base_name, pattern): - return False - if fnmatch.fnmatch(filename, pattern): - return False - - if not os.path.isdir(filename) and not is_python_file(filename): - return False - - return True - - -def find_files(filenames, recursive, exclude): - """Yield filenames.""" - while filenames: - name = filenames.pop(0) - if recursive and os.path.isdir(name): - for root, directories, children in os.walk(name): - filenames += [os.path.join(root, f) for f in children - if match_file(os.path.join(root, f), - exclude)] - directories[:] = [d for d in directories - if match_file(os.path.join(root, d), - exclude)] - else: - yield name - - -def _fix_file(parameters): - """Helper function for optionally running fix_file() in parallel.""" - if parameters[1].verbose: - print('[file:{0}]'.format(parameters[0]), file=sys.stderr) - try: - fix_file(*parameters) - except IOError as error: - print(unicode(error), file=sys.stderr) - - -def fix_multiple_files(filenames, options, output=None): - """Fix list of files. - - Optionally fix files recursively. - - """ - filenames = find_files(filenames, options.recursive, options.exclude) - if options.jobs > 1: - import multiprocessing - pool = multiprocessing.Pool(options.jobs) - pool.map(_fix_file, - [(name, options) for name in filenames]) - else: - for name in filenames: - _fix_file((name, options, output)) - - -def is_python_file(filename): - """Return True if filename is Python file.""" - if filename.endswith('.py'): - return True - - try: - with open_with_encoding( - filename, - limit_byte_check=MAX_PYTHON_FILE_DETECTION_BYTES) as f: - text = f.read(MAX_PYTHON_FILE_DETECTION_BYTES) - if not text: - return False - first_line = text.splitlines()[0] - except (IOError, IndexError): - return False - - if not PYTHON_SHEBANG_REGEX.match(first_line): - return False - - return True - - -def is_probably_part_of_multiline(line): - """Return True if line is likely part of a multiline string. - - When multiline strings are involved, pep8 reports the error as being - at the start of the multiline string, which doesn't work for us. - - """ - return ( - '"""' in line or - "'''" in line or - line.rstrip().endswith('\\') - ) - - -def wrap_output(output, encoding): - """Return output with specified encoding.""" - return codecs.getwriter(encoding)(output.buffer - if hasattr(output, 'buffer') - else output) - - -def get_encoding(): - """Return preferred encoding.""" - return locale.getpreferredencoding() or sys.getdefaultencoding() - - -def main(argv=None, apply_config=True): - """Command-line entry.""" - if argv is None: - argv = sys.argv - - try: - # Exit on broken pipe. - signal.signal(signal.SIGPIPE, signal.SIG_DFL) - except AttributeError: # pragma: no cover - # SIGPIPE is not available on Windows. - pass - - try: - args = parse_args(argv[1:], apply_config=apply_config) - - if args.list_fixes: - for code, description in sorted(supported_fixes()): - print('{code} - {description}'.format( - code=code, description=description)) - return 0 - - if args.files == ['-']: - assert not args.in_place - - encoding = sys.stdin.encoding or get_encoding() - - # LineEndingWrapper is unnecessary here due to the symmetry between - # standard in and standard out. - wrap_output(sys.stdout, encoding=encoding).write( - fix_code(sys.stdin.read(), args, encoding=encoding)) - else: - if args.in_place or args.diff: - args.files = list(set(args.files)) - else: - assert len(args.files) == 1 - assert not args.recursive - - fix_multiple_files(args.files, args, sys.stdout) - except KeyboardInterrupt: - return 1 # pragma: no cover - - -class CachedTokenizer(object): - - """A one-element cache around tokenize.generate_tokens(). - - Original code written by Ned Batchelder, in coverage.py. - - """ - - def __init__(self): - self.last_text = None - self.last_tokens = None - - def generate_tokens(self, text): - """A stand-in for tokenize.generate_tokens().""" - if text != self.last_text: - string_io = io.StringIO(text) - self.last_tokens = list( - tokenize.generate_tokens(string_io.readline) - ) - self.last_text = text - return self.last_tokens - - -_cached_tokenizer = CachedTokenizer() -generate_tokens = _cached_tokenizer.generate_tokens - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/pymode/autopep8.py b/pymode/autopep8.py new file mode 120000 index 00000000..0a26e017 --- /dev/null +++ b/pymode/autopep8.py @@ -0,0 +1 @@ +../submodules/autopep8/autopep8.py \ No newline at end of file diff --git a/pymode/environment.py b/pymode/environment.py index c146ea6e..30ae0e50 100644 --- a/pymode/environment.py +++ b/pymode/environment.py @@ -1,14 +1,10 @@ """Define interfaces.""" -from __future__ import print_function - import json import os.path import time import vim # noqa -from ._compat import PY2 - class VimPymodeEnviroment(object): @@ -53,13 +49,10 @@ def lines(self): :return list: """ - if not PY2: - return self.curbuf - - return [l.decode(self.options.get('encoding')) for l in self.curbuf] + return self.curbuf @staticmethod - def var(name, to_bool=False, silence=False): + def var(name, to_bool=False, silence=False, default=None): """Get vim variable. :return vimobj: @@ -69,7 +62,7 @@ def var(name, to_bool=False, silence=False): value = vim.eval(name) except vim.error: if silence: - return None + return default raise if to_bool: @@ -91,24 +84,31 @@ def message(msg, history=False): return vim.command('call pymode#wide_message("%s")' % str(msg)) - def user_input(self, msg, default=''): + def user_input(self, msg='', default=''): """Return user input or default. :return str: """ - msg = '%s %s ' % (self.prefix, msg) + prompt = [] + prompt.append(str(self.prefix.strip())) + prompt.append(str(msg).strip()) if default != '': - msg += '[%s] ' % default + prompt.append('[%s]' % default) + + prompt.append('> ') + prompt = ' '.join([s for s in prompt if s]) + + vim.command('echohl Debug') try: - vim.command('echohl Debug') - input_str = vim.eval('input("%s> ")' % msg) - vim.command('echohl none') + input_str = vim.eval('input(%r)' % (prompt,)) except KeyboardInterrupt: input_str = '' + vim.command('echohl none') + return input_str or default def user_confirm(self, msg, yes=False): @@ -201,9 +201,6 @@ def prepare_value(self, value, dumps=True): 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=""): diff --git a/pymode/libs/astroid/tests/__init__.py b/pymode/libs/__init__.py similarity index 100% rename from pymode/libs/astroid/tests/__init__.py rename to pymode/libs/__init__.py diff --git a/pymode/libs/astroid b/pymode/libs/astroid new file mode 120000 index 00000000..492d8fbc --- /dev/null +++ b/pymode/libs/astroid @@ -0,0 +1 @@ +../../submodules/astroid/astroid \ No newline at end of file diff --git a/pymode/libs/astroid/__init__.py b/pymode/libs/astroid/__init__.py deleted file mode 100644 index 175dcb5e..00000000 --- a/pymode/libs/astroid/__init__.py +++ /dev/null @@ -1,136 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""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 Instance, BoundMethod, UnboundMethod -from astroid.node_classes import are_exclusive, unpack_infer -from astroid.scoped_nodes import builtin_lookup -from astroid.builder import parse -from astroid.util import YES - -# make a manager instance (borg) as well as Project and Package classes -# accessible from astroid package -from astroid.manager import AstroidManager -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(Call, 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, objs in extension_module._locals.items(): - node._locals[name] = objs - for obj in objs: - if obj.parent is extension_module: - obj.parent = node - - 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]) diff --git a/pymode/libs/astroid/__pkginfo__.py b/pymode/libs/astroid/__pkginfo__.py deleted file mode 100644 index 7a5acfa5..00000000 --- a/pymode/libs/astroid/__pkginfo__.py +++ /dev/null @@ -1,42 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""astroid packaging information""" -distname = 'astroid' - -modname = 'astroid' - -numversion = (1, 4, 9) -version = '.'.join([str(num) for num in numversion]) - -install_requires = ['six', 'lazy_object_proxy', 'wrapt'] - -license = 'LGPL' - -author = 'Python Code Quality Authority' -author_email = 'code-quality@python.org' -mailinglist = "mailto://%s" % author_email -web = 'https://github.com/PyCQA/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", - ] diff --git a/pymode/libs/astroid/arguments.py b/pymode/libs/astroid/arguments.py deleted file mode 100644 index f05d48a3..00000000 --- a/pymode/libs/astroid/arguments.py +++ /dev/null @@ -1,233 +0,0 @@ -# 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 . - -from astroid import bases -from astroid import context as contextmod -from astroid import exceptions -from astroid import nodes -from astroid import util - -import six - - -class CallSite(object): - """Class for understanding arguments passed into a call site - - It needs a call context, which contains the arguments and the - keyword arguments that were passed into a given call site. - In order to infer what an argument represents, call - :meth:`infer_argument` with the corresponding function node - and the argument name. - """ - - def __init__(self, callcontext): - args = callcontext.args - keywords = callcontext.keywords - self.duplicated_keywords = set() - self._unpacked_args = self._unpack_args(args) - self._unpacked_kwargs = self._unpack_keywords(keywords) - - self.positional_arguments = [ - arg for arg in self._unpacked_args - if arg is not util.YES - ] - self.keyword_arguments = { - key: value for key, value in self._unpacked_kwargs.items() - if value is not util.YES - } - - @classmethod - def from_call(cls, call_node): - """Get a CallSite object from the given Call node.""" - callcontext = contextmod.CallContext(call_node.args, - call_node.keywords) - return cls(callcontext) - - def has_invalid_arguments(self): - """Check if in the current CallSite were passed *invalid* arguments - - This can mean multiple things. For instance, if an unpacking - of an invalid object was passed, then this method will return True. - Other cases can be when the arguments can't be inferred by astroid, - for example, by passing objects which aren't known statically. - """ - return len(self.positional_arguments) != len(self._unpacked_args) - - def has_invalid_keywords(self): - """Check if in the current CallSite were passed *invalid* keyword arguments - - For instance, unpacking a dictionary with integer keys is invalid - (**{1:2}), because the keys must be strings, which will make this - method to return True. Other cases where this might return True if - objects which can't be inferred were passed. - """ - return len(self.keyword_arguments) != len(self._unpacked_kwargs) - - def _unpack_keywords(self, keywords): - values = {} - context = contextmod.InferenceContext() - for name, value in keywords: - if name is None: - # Then it's an unpacking operation (**) - try: - inferred = next(value.infer(context=context)) - except exceptions.InferenceError: - values[name] = util.YES - continue - - if not isinstance(inferred, nodes.Dict): - # Not something we can work with. - values[name] = util.YES - continue - - for dict_key, dict_value in inferred.items: - try: - dict_key = next(dict_key.infer(context=context)) - except exceptions.InferenceError: - values[name] = util.YES - continue - if not isinstance(dict_key, nodes.Const): - values[name] = util.YES - continue - if not isinstance(dict_key.value, six.string_types): - values[name] = util.YES - continue - if dict_key.value in values: - # The name is already in the dictionary - values[dict_key.value] = util.YES - self.duplicated_keywords.add(dict_key.value) - continue - values[dict_key.value] = dict_value - else: - values[name] = value - return values - - @staticmethod - def _unpack_args(args): - values = [] - context = contextmod.InferenceContext() - for arg in args: - if isinstance(arg, nodes.Starred): - try: - inferred = next(arg.value.infer(context=context)) - except exceptions.InferenceError: - values.append(util.YES) - continue - - if inferred is util.YES: - values.append(util.YES) - continue - if not hasattr(inferred, 'elts'): - values.append(util.YES) - continue - values.extend(inferred.elts) - else: - values.append(arg) - return values - - def infer_argument(self, funcnode, name, context): - """infer a function argument value according to the call context""" - if name in self.duplicated_keywords: - raise exceptions.InferenceError(name) - - # Look into the keywords first, maybe it's already there. - try: - return self.keyword_arguments[name].infer(context) - except KeyError: - pass - - # Too many arguments given and no variable arguments. - if len(self.positional_arguments) > len(funcnode.args.args): - if not funcnode.args.vararg: - raise exceptions.InferenceError(name) - - positional = self.positional_arguments[:len(funcnode.args.args)] - vararg = self.positional_arguments[len(funcnode.args.args):] - argindex = funcnode.args.find_argname(name)[0] - kwonlyargs = set(arg.name for arg in funcnode.args.kwonlyargs) - kwargs = { - key: value for key, value in self.keyword_arguments.items() - if key not in kwonlyargs - } - # If there are too few positionals compared to - # what the function expects to receive, check to see - # if the missing positional arguments were passed - # as keyword arguments and if so, place them into the - # positional args list. - if len(positional) < len(funcnode.args.args): - for func_arg in funcnode.args.args: - if func_arg.name in kwargs: - arg = kwargs.pop(func_arg.name) - positional.append(arg) - - 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, bases.Instance): - boundnode = bases.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.positional_arguments[argindex].infer(context) - except IndexError: - pass - - if funcnode.args.kwarg == name: - # It wants all the keywords that were passed into - # the call site. - if self.has_invalid_keywords(): - raise exceptions.InferenceError - kwarg = nodes.Dict() - kwarg.lineno = funcnode.args.lineno - kwarg.col_offset = funcnode.args.col_offset - kwarg.parent = funcnode.args - items = [(nodes.const_factory(key), value) - for key, value in kwargs.items()] - kwarg.items = items - return iter((kwarg, )) - elif funcnode.args.vararg == name: - # It wants all the args that were passed into - # the call site. - if self.has_invalid_arguments(): - raise exceptions.InferenceError - args = nodes.Tuple() - args.lineno = funcnode.args.lineno - args.col_offset = funcnode.args.col_offset - args.parent = funcnode.args - args.elts = vararg - return iter((args, )) - - # Check if it's a default parameter. - try: - return funcnode.args.default_value(name).infer(context) - except exceptions.NoDefault: - pass - raise exceptions.InferenceError(name) diff --git a/pymode/libs/astroid/as_string.py b/pymode/libs/astroid/as_string.py deleted file mode 100644 index 2b07200c..00000000 --- a/pymode/libs/astroid/as_string.py +++ /dev/null @@ -1,548 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""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 - -import six - -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_ methods ########################################### - - def visit_arguments(self, node): - """return an astroid.Function node as string""" - return node.format_args() - - def visit_assignattr(self, node): - """return an astroid.AssAttr node as string""" - return self.visit_attribute(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_assignname(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_repr(self, node): - """return an astroid.Repr 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_call(self, node): - """return an astroid.Call node as string""" - expr_str = node.func.accept(self) - args = [arg.accept(self) for arg in node.args] - if node.keywords: - keywords = [kwarg.accept(self) for kwarg in node.keywords] - else: - keywords = [] - - args.extend(keywords) - return '%s(%s)' % (expr_str, ', '.join(args)) - - def visit_classdef(self, node): - """return an astroid.ClassDef 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_attribute(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(self._visit_dict(node)) - - def _visit_dict(self, node): - for key, value in node.items: - key = key.accept(self) - value = value.accept(self) - if key == '**': - # It can only be a DictUnpack node. - yield key + value - else: - yield '%s: %s' % (key, value) - - def visit_dictunpack(self, node): - return '**' - - 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_expr(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_importfrom(self, node): - """return an astroid.ImportFrom node as string""" - return 'from %s import %s' % ('.' * (node.level or 0) + node.modname, - _import_string(node.names)) - - def visit_functiondef(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_annotation = '' - if six.PY3 and node.returns: - return_annotation = '->' + node.returns.as_string() - trailer = return_annotation + ":" - else: - trailer = ":" - def_format = "\n%sdef %s(%s)%s%s\n%s" - return def_format % (decorate, node.name, - node.args.accept(self), - trailer, docs, - self._stmt_list(node.body)) - - def visit_generatorexp(self, node): - """return an astroid.GeneratorExp node as string""" - return '(%s %s)' % (node.elt.accept(self), - ' '.join([n.accept(self) for n in node.generators])) - - def visit_attribute(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""" - if node.arg is None: - return '**%s' % node.value.accept(self) - 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,) - - def visit_starred(self, node): - """return Starred node as string""" - return "*" + node.value.accept(self) - - - # These aren't for real AST nodes, but for inference objects. - - def visit_frozenset(self, node): - return node.parent.accept(self) - - def visit_super(self, node): - return node.parent.accept(self) - - def visit_yes(self, node): - return "Uninferable" - - -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_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 visit_asyncfunctiondef(self, node): - function = super(AsStringVisitor3k, self).visit_functiondef(node) - return 'async ' + function.strip() - - def visit_await(self, node): - return 'await %s' % node.value.accept(self) - - def visit_asyncwith(self, node): - return 'async %s' % self.visit_with(node) - - def visit_asyncfor(self, node): - return 'async %s' % self.visit_for(node) - - -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() diff --git a/pymode/libs/astroid/astpeephole.py b/pymode/libs/astroid/astpeephole.py deleted file mode 100644 index af03462a..00000000 --- a/pymode/libs/astroid/astpeephole.py +++ /dev/null @@ -1,86 +0,0 @@ -# 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 . -"""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 diff --git a/pymode/libs/astroid/bases.py b/pymode/libs/astroid/bases.py deleted file mode 100644 index 8dfa8126..00000000 --- a/pymode/libs/astroid/bases.py +++ /dev/null @@ -1,636 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""This module contains base classes and functions for the nodes and some -inference utils. -""" -import functools -import sys -import warnings - -import wrapt - -from astroid import context as contextmod -from astroid import decorators as decoratorsmod -from astroid import exceptions -from astroid import util - - -if sys.version_info >= (3, 0): - BUILTINS = 'builtins' -else: - BUILTINS = '__builtin__' -PROPERTIES = {BUILTINS + '.property', 'abc.abstractproperty'} -# List of possible property names. We use this list in order -# to see if a method is a property or not. This should be -# pretty reliable and fast, the alternative being to check each -# decorator to see if its a real property-like descriptor, which -# can be too complicated. -# Also, these aren't qualified, because each project can -# define them, we shouldn't expect to know every possible -# property-like decorator! -# TODO(cpopa): just implement descriptors already. -POSSIBLE_PROPERTIES = {"cached_property", "cachedproperty", - "lazyproperty", "lazy_property", "reify", - "lazyattribute", "lazy_attribute", - "LazyProperty", "lazy"} - - -def _is_property(meth): - if PROPERTIES.intersection(meth.decoratornames()): - return True - stripped = {name.split(".")[-1] for name in meth.decoratornames() - if name is not util.YES} - return any(name in stripped for name in POSSIBLE_PROPERTIES) - - -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 - - -def _infer_stmts(stmts, context, frame=None): - """Return an iterator on statements inferred by each statement in *stmts*.""" - stmt = None - inferred = False - if context is not None: - name = context.lookupname - context = context.clone() - else: - name = None - context = contextmod.InferenceContext() - - for stmt in stmts: - if stmt is util.YES: - yield stmt - inferred = True - continue - context.lookupname = stmt._infer_name(frame, name) - try: - for inferred in stmt.infer(context=context): - yield inferred - inferred = True - except exceptions.UnresolvableName: - continue - except exceptions.InferenceError: - yield util.YES - inferred = True - if not inferred: - raise exceptions.InferenceError(str(stmt)) - - -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 exceptions.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 exceptions.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 exceptions.NotFoundError: - pass - return values - - def igetattr(self, name, context=None): - """inferred getattr""" - if not context: - context = contextmod.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 exceptions.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 exceptions.NotFoundError: - raise exceptions.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 _is_property(attr): - for inferred in attr.infer_call_result(self, context): - yield inferred - else: - yield BoundMethod(attr, self) - elif hasattr(attr, 'name') and attr.name == '': - # This is a lambda function defined at class level, - # since its scope is the underlying _proxied class. - # Unfortunately, we can't do an isinstance check here, - # because of the circular dependency between astroid.bases - # and astroid.scoped_nodes. - if attr.statement().scope() == self._proxied: - if attr.args.args and attr.args.args[0].name == 'self': - yield BoundMethod(attr, self) - continue - yield attr - else: - yield attr - - def infer_call_result(self, caller, context=None): - """infer what a class instance is returning when called""" - inferred = False - for node in self._proxied.igetattr('__call__', context): - if node is util.YES or not node.callable(): - continue - for res in node.infer_call_result(caller, context): - inferred = True - yield res - if not inferred: - raise exceptions.InferenceError() - - def __repr__(self): - return '' % (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 exceptions.NotFoundError: - return False - - def pytype(self): - return self._proxied.qname() - - def display_type(self): - return 'Instance of' - - - # TODO(cpopa): this is set in inference.py - # The circular dependency hell goes deeper and deeper. - # pylint: disable=unused-argument - def getitem(self, index, context=None): - pass - -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 self._proxied.getattr(name, context) - - def igetattr(self, name, context=None): - if name == 'im_func': - return iter((self._proxied,)) - return self._proxied.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 util.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=None): - - if context is None: - context = contextmod.InferenceContext() - context = context.clone() - context.boundnode = self.bound - return super(BoundMethod, self).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 '' % (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""" - @functools.wraps(func) - def wrapped(node, context=None, _func=func, **kwargs): - """wrapper function handling context""" - if context is None: - context = contextmod.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 ares not in yielded: - yield res - yielded.add(ares) - return wrapped - -@wrapt.decorator -def yes_if_nothing_inferred(func, instance, args, kwargs): - inferred = False - for node in func(*args, **kwargs): - inferred = True - yield node - if not inferred: - yield util.YES - -@wrapt.decorator -def raise_if_nothing_inferred(func, instance, args, kwargs): - inferred = False - for node in func(*args, **kwargs): - inferred = True - yield node - if not inferred: - raise exceptions.InferenceError() - - -# 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 FunctionDef 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 exceptions.UseInferenceDefault: - pass - - if not context: - return self._infer(context, **kwargs) - - key = (self, context.lookupname, - context.callcontext, context.boundnode) - if key in context.inferred: - return iter(context.inferred[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 isinstance(attr, (list, tuple)): - return attr[-1] - else: - return attr - return None - - def parent_of(self, node): - """return true if i'm a parent of the given node""" - parent = node.parent - while parent is not None: - if self is parent: - return True - parent = parent.parent - return False - - def statement(self): - """return the first parent node marked as statement node""" - if self.is_statement: - return self - return self.parent.statement() - - def frame(self): - """return the first parent frame node (i.e. Module, FunctionDef or - ClassDef) - - """ - return self.parent.frame() - - def scope(self): - """return the first node defining a new scope (i.e. Module, - FunctionDef, ClassDef, 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 - - msg = 'Could not find %s in %s\'s children' - raise exceptions.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 exceptions.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 - - @decoratorsmod.cachedproperty - def fromlineno(self): - if self.lineno is None: - return self._fixed_source_line() - else: - return self.lineno - - @decoratorsmod.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 ImportFrom, 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 exceptions.InferenceError(self.__class__.__name__) - - def inferred(self): - '''return list of inferred values for a more simple inference usage''' - return list(self.infer()) - - def infered(self): - warnings.warn('%s.infered() is deprecated and slated for removal ' - 'in astroid 2.0, use %s.inferred() instead.' - % (type(self).__name__, type(self).__name__), - PendingDeprecationWarning, stacklevel=2) - return self.inferred() - - def instanciate_class(self): - """instanciate a node if it is a ClassDef 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] diff --git a/pymode/libs/astroid/brain/brain_builtin_inference.py b/pymode/libs/astroid/brain/brain_builtin_inference.py deleted file mode 100644 index ed78111f..00000000 --- a/pymode/libs/astroid/brain/brain_builtin_inference.py +++ /dev/null @@ -1,336 +0,0 @@ -"""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 arguments -from astroid import nodes -from astroid import objects -from astroid.builder import AstroidBuilder -from astroid import util - -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: - if not result.parent: - # Let the transformation function determine - # the parent for its result. Otherwise, - # we set it to be the node we transformed from. - result.parent = node - - result.lineno = node.lineno - result.col_offset = node.col_offset - return iter([result]) - - MANAGER.register_transform(nodes.Call, - 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: - inferred = next(arg.infer(context=context)) - except (InferenceError, StopIteration): - raise UseInferenceDefault() - if inferred is util.YES: - raise UseInferenceDefault() - transformed = transform(inferred) - if not transformed or transformed is util.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) - -infer_frozenset = partial( - _infer_builtin, - klass=objects.FrozenSet, - iterables=(nodes.List, nodes.Tuple, nodes.Set), - build_elts=frozenset) - - -def _get_elts(arg, context): - is_iterable = lambda n: isinstance(n, - (nodes.List, nodes.Tuple, nodes.Set)) - try: - inferred = next(arg.infer(context)) - except (InferenceError, UnresolvableName): - raise UseInferenceDefault() - if isinstance(inferred, nodes.Dict): - items = inferred.items - elif is_iterable(inferred): - items = [] - for elt in inferred.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 inferred, we'll fallback to default inference. - """ - call = arguments.CallSite.from_call(node) - if call.has_invalid_arguments() or call.has_invalid_keywords(): - raise UseInferenceDefault - - args = call.positional_arguments - kwargs = list(call.keyword_arguments.items()) - - if not args and not kwargs: - # dict() - return nodes.Dict() - elif kwargs and not args: - # dict(a=1, b=2, c=4) - items = [(nodes.Const(key), value) for key, value in kwargs] - elif len(args) == 1 and kwargs: - # dict(some_iterable, b=2, c=4) - elts = _get_elts(args[0], context) - keys = [(nodes.Const(key), value) for key, value in kwargs] - items = elts + keys - elif len(args) == 1: - items = _get_elts(args[0], context) - else: - raise UseInferenceDefault() - - empty = nodes.Dict() - empty.items = items - return empty - - -def _node_class(node): - klass = node.frame() - while klass is not None and not isinstance(klass, nodes.ClassDef): - if klass.parent is None: - klass = None - else: - klass = klass.parent.frame() - return klass - - -def infer_super(node, context=None): - """Understand super calls. - - There are some restrictions for what can be understood: - - * unbounded super (one argument form) is not understood. - - * if the super call is not inside a function (classmethod or method), - then the default inference will be used. - - * if the super arguments can't be infered, the default inference - will be used. - """ - if len(node.args) == 1: - # Ignore unbounded super. - raise UseInferenceDefault - - scope = node.scope() - if not isinstance(scope, nodes.FunctionDef): - # Ignore non-method uses of super. - raise UseInferenceDefault - if scope.type not in ('classmethod', 'method'): - # Not interested in staticmethods. - raise UseInferenceDefault - - cls = _node_class(scope) - if not len(node.args): - mro_pointer = cls - # In we are in a classmethod, the interpreter will fill - # automatically the class as the second argument, not an instance. - if scope.type == 'classmethod': - mro_type = cls - else: - mro_type = cls.instantiate_class() - else: - # TODO(cpopa): support flow control (multiple inference values). - try: - mro_pointer = next(node.args[0].infer(context=context)) - except InferenceError: - raise UseInferenceDefault - try: - mro_type = next(node.args[1].infer(context=context)) - except InferenceError: - raise UseInferenceDefault - - if mro_pointer is YES or mro_type is YES: - # No way we could understand this. - raise UseInferenceDefault - - super_obj = objects.Super(mro_pointer=mro_pointer, - mro_type=mro_type, - self_class=cls, - scope=scope) - super_obj.parent = node - return iter([super_obj]) - - -# Builtins inference -MANAGER.register_transform(nodes.Call, - inference_tip(infer_super), - lambda n: (isinstance(n.func, nodes.Name) and - n.func.name == 'super')) - -register_builtin_transform(infer_tuple, 'tuple') -register_builtin_transform(infer_set, 'set') -register_builtin_transform(infer_list, 'list') -register_builtin_transform(infer_dict, 'dict') -register_builtin_transform(infer_frozenset, 'frozenset') diff --git a/pymode/libs/astroid/brain/brain_dateutil.py b/pymode/libs/astroid/brain/brain_dateutil.py deleted file mode 100644 index d077327b..00000000 --- a/pymode/libs/astroid/brain/brain_dateutil.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Astroid hooks for dateutil""" - -import textwrap - -from astroid import MANAGER, register_module_extender -from astroid.builder import AstroidBuilder - -def dateutil_transform(): - return AstroidBuilder(MANAGER).string_build(textwrap.dedent(''' - import datetime - def parse(timestr, parserinfo=None, **kwargs): - return datetime.datetime() - ''')) - -register_module_extender(MANAGER, 'dateutil.parser', dateutil_transform) diff --git a/pymode/libs/astroid/brain/brain_gi.py b/pymode/libs/astroid/brain/brain_gi.py deleted file mode 100644 index d9fc1b45..00000000 --- a/pymode/libs/astroid/brain/brain_gi.py +++ /dev/null @@ -1,195 +0,0 @@ -"""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 -import warnings - -from astroid import MANAGER, AstroidBuildingException, nodes -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 (str(obj).startswith(", ) - # Only accept function calls with two constant arguments - if len(node.args) != 2: - return False - - if not all(isinstance(arg, nodes.Const) for arg in node.args): - return False - - func = node.func - if isinstance(func, nodes.Attribute): - if func.attrname != 'require_version': - return False - if isinstance(func.expr, nodes.Name) and func.expr.name == 'gi': - return True - - return False - - if isinstance(func, nodes.Name): - return func.name == 'require_version' - - return False - -def _register_require_version(node): - # Load the gi.require_version locally - try: - import gi - gi.require_version(node.args[0].value, node.args[1].value) - except Exception: - pass - - return node - -MANAGER.register_failed_import_hook(_import_gi_module) -MANAGER.register_transform(nodes.Call, _register_require_version, _looks_like_require_version) diff --git a/pymode/libs/astroid/brain/brain_mechanize.py b/pymode/libs/astroid/brain/brain_mechanize.py deleted file mode 100644 index 20a253a4..00000000 --- a/pymode/libs/astroid/brain/brain_mechanize.py +++ /dev/null @@ -1,18 +0,0 @@ -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) diff --git a/pymode/libs/astroid/brain/brain_nose.py b/pymode/libs/astroid/brain/brain_nose.py deleted file mode 100644 index 4b077843..00000000 --- a/pymode/libs/astroid/brain/brain_nose.py +++ /dev/null @@ -1,82 +0,0 @@ -# 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 . - -"""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) - if method.name == 'assertEqual': - # nose also exports assert_equals. - yield 'assert_equals', 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') diff --git a/pymode/libs/astroid/brain/brain_numpy.py b/pymode/libs/astroid/brain/brain_numpy.py deleted file mode 100644 index 75f4f18f..00000000 --- a/pymode/libs/astroid/brain/brain_numpy.py +++ /dev/null @@ -1,62 +0,0 @@ -# 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 . - -"""Astroid hooks for numpy.""" - -import astroid - - -# TODO(cpopa): drop when understanding augmented assignments - -def numpy_core_transform(): - return astroid.parse(''' - from numpy.core import numeric - from numpy.core import fromnumeric - from numpy.core import defchararray - from numpy.core import records - from numpy.core import function_base - from numpy.core import machar - from numpy.core import getlimits - from numpy.core import shape_base - __all__ = (['char', 'rec', 'memmap', 'chararray'] + numeric.__all__ + - fromnumeric.__all__ + - records.__all__ + - function_base.__all__ + - machar.__all__ + - getlimits.__all__ + - shape_base.__all__) - ''') - - -def numpy_transform(): - return astroid.parse(''' - from numpy import core - from numpy import matrixlib as _mat - from numpy import lib - __all__ = ['add_newdocs', - 'ModuleDeprecationWarning', - 'VisibleDeprecationWarning', 'linalg', 'fft', 'random', - 'ctypeslib', 'ma', - '__version__', 'pkgload', 'PackageLoader', - 'show_config'] + core.__all__ + _mat.__all__ + lib.__all__ - - ''') - - -astroid.register_module_extender(astroid.MANAGER, 'numpy.core', numpy_core_transform) -astroid.register_module_extender(astroid.MANAGER, 'numpy', numpy_transform) diff --git a/pymode/libs/astroid/brain/brain_pytest.py b/pymode/libs/astroid/brain/brain_pytest.py deleted file mode 100644 index 1859b985..00000000 --- a/pymode/libs/astroid/brain/brain_pytest.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Astroid hooks for pytest.""" -from __future__ import absolute_import -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 - import _pytest.skipping - import _pytest.assertion -except ImportError: - pass -else: - deprecated_call = _pytest.recwarn.deprecated_call - warns = _pytest.recwarn.warns - - exit = _pytest.runner.exit - fail = _pytest.runner.fail - skip = _pytest.runner.skip - importorskip = _pytest.runner.importorskip - - xfail = _pytest.skipping.xfail - mark = _pytest.mark.MarkGenerator() - raises = _pytest.python.raises - - # New in pytest 3.0 - try: - approx = _pytest.python.approx - register_assert_rewrite = _pytest.assertion.register_assert_rewrite - except AttributeError: - pass - - -# Moved in pytest 3.0 - -try: - import _pytest.freeze_support - freeze_includes = _pytest.freeze_support.freeze_includes -except ImportError: - try: - import _pytest.genscript - freeze_includes = _pytest.genscript.freeze_includes - except ImportError: - pass - -try: - import _pytest.debugging - set_trace = _pytest.debugging.pytestPDB().set_trace -except ImportError: - try: - import _pytest.pdb - set_trace = _pytest.pdb.pytestPDB().set_trace - except ImportError: - pass - -try: - import _pytest.fixtures - fixture = _pytest.fixtures.fixture - yield_fixture = _pytest.fixtures.yield_fixture -except ImportError: - try: - import _pytest.python - fixture = _pytest.python.fixture - yield_fixture = _pytest.python.yield_fixture - except ImportError: - pass -''') - -register_module_extender(MANAGER, 'pytest', pytest_transform) -register_module_extender(MANAGER, 'py.test', pytest_transform) diff --git a/pymode/libs/astroid/brain/brain_qt.py b/pymode/libs/astroid/brain/brain_qt.py deleted file mode 100644 index 1a03b2be..00000000 --- a/pymode/libs/astroid/brain/brain_qt.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Astroid hooks for the PyQT library.""" - -from astroid import MANAGER, register_module_extender -from astroid.builder import AstroidBuilder -from astroid import nodes -from astroid import parse - - -def _looks_like_signal(node, signal_name='pyqtSignal'): - if '__class__' in node._instance_attrs: - cls = node._instance_attrs['__class__'][0] - return cls.name == signal_name - return False - - -def transform_pyqt_signal(node): - module = parse(''' - class pyqtSignal(object): - def connect(self, slot, type=None, no_receiver_check=False): - pass - def disconnect(self, slot): - pass - def emit(self, *args): - pass - ''') - signal_cls = module['pyqtSignal'] - node._instance_attrs['emit'] = signal_cls['emit'] - node._instance_attrs['disconnect'] = signal_cls['disconnect'] - node._instance_attrs['connect'] = signal_cls['connect'] - - -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) -MANAGER.register_transform(nodes.FunctionDef, transform_pyqt_signal, - _looks_like_signal) \ No newline at end of file diff --git a/pymode/libs/astroid/brain/brain_six.py b/pymode/libs/astroid/brain/brain_six.py deleted file mode 100644 index 9596a6c8..00000000 --- a/pymode/libs/astroid/brain/brain_six.py +++ /dev/null @@ -1,288 +0,0 @@ -# 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 . - -"""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, InferenceError -from astroid import nodes - - -SIX_ADD_METACLASS = 'six.add_metaclass' - - -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 - -def transform_six_add_metaclass(node): - """Check if the given class node is decorated with *six.add_metaclass* - - If so, inject its argument as the metaclass of the underlying class. - """ - if not node.decorators: - return - - for decorator in node.decorators.nodes: - if not isinstance(decorator, nodes.Call): - continue - - try: - func = next(decorator.func.infer()) - except InferenceError: - continue - if func.qname() == SIX_ADD_METACLASS and decorator.args: - metaclass = decorator.args[0] - node._metaclass = metaclass - return node - - -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) -MANAGER.register_transform(nodes.ClassDef, transform_six_add_metaclass) diff --git a/pymode/libs/astroid/brain/brain_ssl.py b/pymode/libs/astroid/brain/brain_ssl.py deleted file mode 100644 index 1cf8d1b8..00000000 --- a/pymode/libs/astroid/brain/brain_ssl.py +++ /dev/null @@ -1,65 +0,0 @@ -"""Astroid hooks for the ssl library.""" - -from astroid import MANAGER, register_module_extender -from astroid.builder import AstroidBuilder -from astroid import nodes -from astroid import parse - - -def ssl_transform(): - return parse(''' - from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION - from _ssl import _SSLContext, MemoryBIO - from _ssl import ( - SSLError, SSLZeroReturnError, SSLWantReadError, SSLWantWriteError, - SSLSyscallError, SSLEOFError, - ) - from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED - from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj - from _ssl import RAND_status, RAND_add, RAND_bytes, RAND_pseudo_bytes - try: - from _ssl import RAND_egd - except ImportError: - # LibreSSL does not provide RAND_egd - pass - from _ssl import (OP_ALL, OP_CIPHER_SERVER_PREFERENCE, - OP_NO_COMPRESSION, OP_NO_SSLv2, OP_NO_SSLv3, - OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2, - OP_SINGLE_DH_USE, OP_SINGLE_ECDH_USE) - - from _ssl import (ALERT_DESCRIPTION_ACCESS_DENIED, ALERT_DESCRIPTION_BAD_CERTIFICATE, - ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE, - ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE, - ALERT_DESCRIPTION_BAD_RECORD_MAC, - ALERT_DESCRIPTION_CERTIFICATE_EXPIRED, - ALERT_DESCRIPTION_CERTIFICATE_REVOKED, - ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN, - ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE, - ALERT_DESCRIPTION_CLOSE_NOTIFY, ALERT_DESCRIPTION_DECODE_ERROR, - ALERT_DESCRIPTION_DECOMPRESSION_FAILURE, - ALERT_DESCRIPTION_DECRYPT_ERROR, - ALERT_DESCRIPTION_HANDSHAKE_FAILURE, - ALERT_DESCRIPTION_ILLEGAL_PARAMETER, - ALERT_DESCRIPTION_INSUFFICIENT_SECURITY, - ALERT_DESCRIPTION_INTERNAL_ERROR, - ALERT_DESCRIPTION_NO_RENEGOTIATION, - ALERT_DESCRIPTION_PROTOCOL_VERSION, - ALERT_DESCRIPTION_RECORD_OVERFLOW, - ALERT_DESCRIPTION_UNEXPECTED_MESSAGE, - ALERT_DESCRIPTION_UNKNOWN_CA, - ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY, - ALERT_DESCRIPTION_UNRECOGNIZED_NAME, - ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE, - ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION, - ALERT_DESCRIPTION_USER_CANCELLED) - from _ssl import (SSL_ERROR_EOF, SSL_ERROR_INVALID_ERROR_CODE, SSL_ERROR_SSL, - SSL_ERROR_SYSCALL, SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_READ, - SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_X509_LOOKUP, SSL_ERROR_ZERO_RETURN) - from _ssl import VERIFY_CRL_CHECK_CHAIN, VERIFY_CRL_CHECK_LEAF, VERIFY_DEFAULT, VERIFY_X509_STRICT - from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN - from _ssl import _OPENSSL_API_VERSION - from _ssl import PROTOCOL_SSLv23, PROTOCOL_TLSv1, PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2 - ''') - - -register_module_extender(MANAGER, 'ssl', ssl_transform) diff --git a/pymode/libs/astroid/brain/brain_stdlib.py b/pymode/libs/astroid/brain/brain_stdlib.py deleted file mode 100644 index ad395a27..00000000 --- a/pymode/libs/astroid/brain/brain_stdlib.py +++ /dev/null @@ -1,473 +0,0 @@ - -"""Astroid hooks for the Python 2 standard library. - -Currently help understanding of : - -* hashlib.md5 and hashlib.sha1 -""" - -import functools -import sys -from textwrap import dedent - -from astroid import ( - MANAGER, UseInferenceDefault, inference_tip, BoundMethod, - InferenceError, register_module_extender) -from astroid import exceptions -from astroid import nodes -from astroid.builder import AstroidBuilder -from astroid import util -from astroid import test_utils - -PY3K = sys.version_info > (3, 0) -PY33 = sys.version_info >= (3, 3) -PY34 = sys.version_info >= (3, 4) - -# 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): - if node is util.YES: - raise UseInferenceDefault - try: - value = next(node.infer(context=context)) - if value is util.YES: - raise UseInferenceDefault() - else: - return value - except StopIteration: - raise InferenceError() - - # node is a Call 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): - raise UseInferenceDefault() - - # If we can't iner the name of the class, don't crash, up to this point - # we know it is a namedtuple anyway. - name = name or 'Uninferable' - # we want to return a Class node instance with proper attributes set - class_node = nodes.ClassDef(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 - fake_node.attrname = attr - 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): - self.iterable = iterable - 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 __reversed__(self): return self.iterable[::-1] - def __getitem__(self, index): pass - def __setitem__(self, index, value): pass - def __delitem__(self, index): pass -''') - - -def pkg_resources_transform(): - return AstroidBuilder(MANAGER).string_build(''' -def require(*requirements): - return pkg_resources.working_set.require(*requirements) - -def run_script(requires, script_name): - return pkg_resources.working_set.run_script(requires, script_name) - -def iter_entry_points(group, name=None): - return pkg_resources.working_set.iter_entry_points(group, name) - -def resource_exists(package_or_requirement, resource_name): - return get_provider(package_or_requirement).has_resource(resource_name) - -def resource_isdir(package_or_requirement, resource_name): - return get_provider(package_or_requirement).resource_isdir( - resource_name) - -def resource_filename(package_or_requirement, resource_name): - return get_provider(package_or_requirement).get_resource_filename( - self, resource_name) - -def resource_stream(package_or_requirement, resource_name): - return get_provider(package_or_requirement).get_resource_stream( - self, resource_name) - -def resource_string(package_or_requirement, resource_name): - return get_provider(package_or_requirement).get_resource_string( - self, resource_name) - -def resource_listdir(package_or_requirement, resource_name): - return get_provider(package_or_requirement).resource_listdir( - resource_name) - -def extraction_error(): - pass - -def get_cache_path(archive_name, names=()): - extract_path = self.extraction_path or get_default_cache() - target_path = os.path.join(extract_path, archive_name+'-tmp', *names) - return target_path - -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')) - communicate_signature = 'def communicate(self, input=None, timeout=None)' - 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') - communicate_signature = 'def communicate(self, input=None)' - 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)' - if PY3K: - ctx_manager = ''' - def __enter__(self): return self - def __exit__(self, *args): pass - ''' - else: - ctx_manager = '' - code = dedent(''' - - class Popen(object): - returncode = pid = 0 - stdin = stdout = stderr = file() - - %(init)s - - %(communicate_signature)s: - 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 - %(ctx_manager)s - ''' % {'init': init, - 'communicate': communicate, - 'communicate_signature': communicate_signature, - 'wait_signature': wait_signature, - 'ctx_manager': ctx_manager}) - return AstroidBuilder(MANAGER).string_build(code) - - -# namedtuple support ########################################################### - -def _looks_like(node, name): - func = node.func - if isinstance(func, nodes.Attribute): - return func.attrname == name - if isinstance(func, nodes.Name): - return func.name == name - return False - -_looks_like_namedtuple = functools.partial(_looks_like, name='namedtuple') -_looks_like_enum = functools.partial(_looks_like, name='Enum') - - -def infer_named_tuple(node, context=None): - """Specific inference function for namedtuple Call 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): - return self - ''' % {'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 Call node. """ - enum_meta = test_utils.extract_node(''' - class EnumMeta(object): - 'docstring' - def __call__(self, node): - class EnumAttribute(object): - name = '' - value = 0 - return EnumAttribute() - ''') - class_node = infer_func_form(node, enum_meta, - context=context, enum=True)[0] - return iter([class_node.instantiate_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.AssignName) - 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(%(types)s): - @property - def value(self): - # Not the best return. - return None - @property - def name(self): - return %(name)r - ''' % {'name': target.name, 'types': ', '.join(node.basenames)}) - 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.instantiate_class()) - node._locals[local] = new_targets - break - return node - -def multiprocessing_transform(): - module = AstroidBuilder(MANAGER).string_build(dedent(''' - from multiprocessing.managers import SyncManager - def Manager(): - return SyncManager() - ''')) - if not PY34: - return module - - # On Python 3.4, multiprocessing uses a getattr lookup inside contexts, - # in order to get the attributes they need. Since it's extremely - # dynamic, we use this approach to fake it. - node = AstroidBuilder(MANAGER).string_build(dedent(''' - from multiprocessing.context import DefaultContext, BaseContext - default = DefaultContext() - base = BaseContext() - ''')) - try: - context = next(node['default'].infer()) - base = next(node['base'].infer()) - except InferenceError: - return module - - for node in (context, base): - for key, value in node._locals.items(): - if key.startswith("_"): - continue - - value = value[0] - if isinstance(value, nodes.FunctionDef): - # We need to rebound this, since otherwise - # it will have an extra argument (self). - value = BoundMethod(value, node) - module[key] = value - return module - -def multiprocessing_managers_transform(): - return AstroidBuilder(MANAGER).string_build(dedent(''' - import array - import threading - import multiprocessing.pool as pool - - import six - - class Namespace(object): - pass - - class Value(object): - def __init__(self, typecode, value, lock=True): - self._typecode = typecode - self._value = value - def get(self): - return self._value - def set(self, value): - self._value = value - def __repr__(self): - return '%s(%r, %r)'%(type(self).__name__, self._typecode, self._value) - value = property(get, set) - - def Array(typecode, sequence, lock=True): - return array.array(typecode, sequence) - - class SyncManager(object): - Queue = JoinableQueue = six.moves.queue.Queue - Event = threading.Event - RLock = threading.RLock - BoundedSemaphore = threading.BoundedSemaphore - Condition = threading.Condition - Barrier = threading.Barrier - Pool = pool.Pool - list = list - dict = dict - Value = Value - Array = Array - Namespace = Namespace - __enter__ = lambda self: self - __exit__ = lambda *args: args - - def start(self, initializer=None, initargs=None): - pass - def shutdown(self): - pass - ''')) - - -MANAGER.register_transform(nodes.Call, inference_tip(infer_named_tuple), - _looks_like_namedtuple) -MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), - _looks_like_enum) -MANAGER.register_transform(nodes.ClassDef, 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) -register_module_extender(MANAGER, 'multiprocessing.managers', - multiprocessing_managers_transform) -register_module_extender(MANAGER, 'multiprocessing', multiprocessing_transform) diff --git a/pymode/libs/astroid/builder.py b/pymode/libs/astroid/builder.py deleted file mode 100644 index 63c156a1..00000000 --- a/pymode/libs/astroid/builder.py +++ /dev/null @@ -1,263 +0,0 @@ -# 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 . -"""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 - -import _ast -import os -import sys -import textwrap - -from astroid import bases -from astroid import exceptions -from astroid import manager -from astroid import modutils -from astroid import raw_building -from astroid import rebuilder -from astroid import util - - -def _parse(string): - return compile(string, "", 'exec', _ast.PyCF_ONLY_AST) - - -if sys.version_info >= (3, 0): - # pylint: disable=no-name-in-module; We don't understand flows yet. - 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 encoding - # detect_encoding returns utf-8 if no encoding specified - msg = 'Wrong (%s) or no encoding specified' % encoding - raise exceptions.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 - - -MANAGER = manager.AstroidManager() - - -class AstroidBuilder(raw_building.InspectBuilder): - """Class for building an astroid tree from source code or from a live module. - - The param *manager* specifies the manager class which should be used. - If no manager is given, then the default one will be used. The - param *apply_transforms* determines if the transforms should be - applied after the tree was built from source or from a live object, - by default being True. - """ - - def __init__(self, manager=None, apply_transforms=True): - super(AstroidBuilder, self).__init__() - self._manager = manager or MANAGER - self._apply_transforms = apply_transforms - - 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 = os.path.splitext(modutils._path_from_filename(path)) - if ext in ('.py', '.pyc', '.pyo') and os.path.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) - if self._apply_transforms: - # We have to handle transformation by ourselves since the - # rebuilder isn't called for builtin nodes - node = self._manager.visit_transforms(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 exceptions.AstroidBuildingException(msg) - except SyntaxError as exc: # py3k encoding specification error - raise exceptions.AstroidBuildingException(exc) - except LookupError as exc: # unknown encoding - raise exceptions.AstroidBuildingException(exc) - with stream: - # get module name if necessary - if modname is None: - try: - modname = '.'.join(modutils.modpath_from_file(path)) - except ImportError: - modname = os.path.splitext(os.path.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.""" - module = self._data_build(data, modname, path) - module.source_code = 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._import_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) - - # Visit the transforms - if self._apply_transforms: - module = self._manager.visit_transforms(module) - return module - - def _data_build(self, data, modname, path): - """Build tree node from data and add some informations""" - try: - node = _parse(data + '\n') - except (TypeError, ValueError, SyntaxError) as exc: - raise exceptions.AstroidBuildingException(exc) - if path is not None: - node_file = os.path.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 - builder = rebuilder.TreeRebuilder(self._manager) - module = builder.visit_module(node, modname, node_file, package) - module._import_from_nodes = builder._import_from_nodes - module._delayed_assattr = builder._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 exceptions.InferenceError: - continue - for name in imported._public_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 - - This adds name to locals and handle members definition. - """ - try: - frame = node.frame() - for inferred in node.expr.infer(): - if inferred is util.YES: - continue - try: - if inferred.__class__ is bases.Instance: - inferred = inferred._proxied - iattrs = inferred._instance_attrs - elif isinstance(inferred, bases.Instance): - # Const, Tuple, ... we may be wrong, may be not, but - # anyway we don't want to pollute builtin's namespace - continue - elif inferred.is_function: - iattrs = inferred._instance_attrs - else: - iattrs = inferred._locals - except AttributeError: - # XXX log error - 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 exceptions.InferenceError: - pass - - -def parse(code, module_name='', path=None, apply_transforms=True): - """Parses a source string in order to obtain an astroid AST from it - - :param str code: The code for the module. - :param str module_name: The name for the module, if any - :param str path: The path for the module - :param bool apply_transforms: - Apply the transforms for the give code. Use it if you - don't want the default transforms to be applied. - """ - code = textwrap.dedent(code) - builder = AstroidBuilder(manager=MANAGER, - apply_transforms=apply_transforms) - return builder.string_build(code, modname=module_name, path=path) diff --git a/pymode/libs/astroid/context.py b/pymode/libs/astroid/context.py deleted file mode 100644 index 284dfa18..00000000 --- a/pymode/libs/astroid/context.py +++ /dev/null @@ -1,81 +0,0 @@ -# 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 . - -"""Various context related utilities, including inference and call contexts.""" - -import contextlib - - -class InferenceContext(object): - __slots__ = ('path', 'lookupname', 'callcontext', 'boundnode', 'inferred') - - def __init__(self, path=None, inferred=None): - self.path = path or set() - self.lookupname = None - self.callcontext = None - self.boundnode = None - self.inferred = inferred 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, inferred=self.inferred) - 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.inferred[key] = tuple(results) - return - - @contextlib.contextmanager - def restore_path(self): - path = set(self.path) - yield - self.path = path - - -class CallContext(object): - """Holds information for a call site.""" - - __slots__ = ('args', 'keywords') - - def __init__(self, args, keywords=None): - self.args = args - if keywords: - keywords = [(arg.arg, arg.value) for arg in keywords] - else: - keywords = [] - self.keywords = keywords - - -def copy_context(context): - if context is not None: - return context.clone() - else: - return InferenceContext() diff --git a/pymode/libs/astroid/decorators.py b/pymode/libs/astroid/decorators.py deleted file mode 100644 index a446536c..00000000 --- a/pymode/libs/astroid/decorators.py +++ /dev/null @@ -1,75 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -# -# The code in this file was originally part of logilab-common, licensed under -# the same license. - -""" A few useful function/method decorators.""" - -import wrapt - - -@wrapt.decorator -def cached(func, instance, args, kwargs): - """Simple decorator to cache result of method calls without args.""" - cache = getattr(instance, '__cache', None) - if cache is None: - instance.__cache = cache = {} - try: - return cache[func] - except KeyError: - cache[func] = result = func(*args, **kwargs) - return result - - -class cachedproperty(object): - """ Provides a cached property equivalent to the stacking of - @cached and @property, but more efficient. - - After first usage, the becomes part of the object's - __dict__. Doing: - - del obj. empties the cache. - - Idea taken from the pyramid_ framework and the mercurial_ project. - - .. _pyramid: http://pypi.python.org/pypi/pyramid - .. _mercurial: http://pypi.python.org/pypi/Mercurial - """ - __slots__ = ('wrapped',) - - def __init__(self, wrapped): - try: - wrapped.__name__ - except AttributeError: - raise TypeError('%s must have a __name__ attribute' % - wrapped) - self.wrapped = wrapped - - @property - def __doc__(self): - doc = getattr(self.wrapped, '__doc__', None) - return ('%s' - % ('\n%s' % doc if doc else '')) - - def __get__(self, inst, objtype=None): - if inst is None: - return self - val = self.wrapped(inst) - setattr(inst, self.wrapped.__name__, val) - return val diff --git a/pymode/libs/astroid/exceptions.py b/pymode/libs/astroid/exceptions.py deleted file mode 100644 index 47f2fe50..00000000 --- a/pymode/libs/astroid/exceptions.py +++ /dev/null @@ -1,71 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""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 MroError(ResolveError): - """Error raised when there is a problem with method resolution of a class.""" - - -class DuplicateBasesError(MroError): - """Error raised when there are duplicate bases in the same class bases.""" - - -class InconsistentMroError(MroError): - """Error raised when a class's MRO is inconsistent.""" - - -class SuperError(ResolveError): - """Error raised when there is a problem with a super call.""" - - -class SuperArgumentTypeError(SuperError): - """Error raised when the super arguments are invalid.""" - - -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 - """ - diff --git a/pymode/libs/astroid/inference.py b/pymode/libs/astroid/inference.py deleted file mode 100644 index ddd43561..00000000 --- a/pymode/libs/astroid/inference.py +++ /dev/null @@ -1,359 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""this module contains a set of functions to handle inference on astroid trees -""" - -from __future__ import print_function - -from astroid import bases -from astroid import context as contextmod -from astroid import exceptions -from astroid import manager -from astroid import nodes -from astroid import protocols -from astroid import util - - -MANAGER = manager.AstroidManager() - - -# .infer method ############################################################### - - -def infer_end(self, context=None): - """inference's end for node such as Module, ClassDef, FunctionDef, - Const... - - """ - yield self -nodes.Module._infer = infer_end -nodes.ClassDef._infer = infer_end -nodes.FunctionDef._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.FunctionDef): - 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 exceptions.UnresolvableName(self.name) - context = context.clone() - context.lookupname = self.name - return bases._infer_stmts(stmts, context, frame) -nodes.Name._infer = bases.path_wrapper(infer_name) -nodes.AssignName.infer_lhs = infer_name # won't work with a path wrapper - - -@bases.path_wrapper -@bases.raise_if_nothing_inferred -def infer_call(self, context=None): - """infer a Call node by trying to guess what the function returns""" - callcontext = context.clone() - callcontext.callcontext = contextmod.CallContext(args=self.args, - keywords=self.keywords) - callcontext.boundnode = None - for callee in self.func.infer(context): - if callee is util.YES: - yield callee - continue - try: - if hasattr(callee, 'infer_call_result'): - for inferred in callee.infer_call_result(self, callcontext): - yield inferred - except exceptions.InferenceError: - ## XXX log error ? - continue -nodes.Call._infer = infer_call - - -@bases.path_wrapper -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 exceptions.InferenceError() - if asname: - yield self.do_import_module(self.real_name(name)) - else: - yield self.do_import_module(name) -nodes.Import._infer = infer_import - - -def infer_name_module(self, name): - context = contextmod.InferenceContext() - context.lookupname = name - return self.infer(context, asname=False) -nodes.Import.infer_name_module = infer_name_module - - -@bases.path_wrapper -def infer_import_from(self, context=None, asname=True): - """infer a ImportFrom node: return the imported module/object""" - name = context.lookupname - if name is None: - raise exceptions.InferenceError() - if asname: - name = self.real_name(name) - module = self.do_import_module() - try: - context = contextmod.copy_context(context) - context.lookupname = name - stmts = module.getattr(name, ignore_locals=module is self.root()) - return bases._infer_stmts(stmts, context) - except exceptions.NotFoundError: - raise exceptions.InferenceError(name) -nodes.ImportFrom._infer = infer_import_from - - -@bases.raise_if_nothing_inferred -def infer_attribute(self, context=None): - """infer an Attribute node by using getattr on the associated object""" - for owner in self.expr.infer(context): - if owner is util.YES: - yield owner - continue - try: - context.boundnode = owner - for obj in owner.igetattr(self.attrname, context): - yield obj - context.boundnode = None - except (exceptions.NotFoundError, exceptions.InferenceError): - context.boundnode = None - except AttributeError: - # XXX method / function - context.boundnode = None -nodes.Attribute._infer = bases.path_wrapper(infer_attribute) -nodes.AssignAttr.infer_lhs = infer_attribute # # won't work with a path wrapper - - -@bases.path_wrapper -def infer_global(self, context=None): - if context.lookupname is None: - raise exceptions.InferenceError() - try: - return bases._infer_stmts(self.root().getattr(context.lookupname), - context) - except exceptions.NotFoundError: - raise exceptions.InferenceError() -nodes.Global._infer = infer_global - - -@bases.raise_if_nothing_inferred -def infer_subscript(self, context=None): - """Inference for subscripts - - We're understanding if the index is a Const - or a slice, passing the result of inference - to the value's `getitem` method, which should - handle each supported index type accordingly. - """ - - value = next(self.value.infer(context)) - if value is util.YES: - yield util.YES - return - - index = next(self.slice.infer(context)) - if index is util.YES: - yield util.YES - return - - if isinstance(index, nodes.Const): - try: - assigned = value.getitem(index.value, context) - except AttributeError: - raise exceptions.InferenceError() - except (IndexError, TypeError): - yield util.YES - return - - # Prevent inferring if the infered subscript - # is the same as the original subscripted object. - if self is assigned or assigned is util.YES: - yield util.YES - return - for infered in assigned.infer(context): - yield infered - else: - raise exceptions.InferenceError() -nodes.Subscript._infer = bases.path_wrapper(infer_subscript) -nodes.Subscript.infer_lhs = infer_subscript - -@bases.raise_if_nothing_inferred -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 = protocols.UNARY_OP_METHOD[self.op] - if meth is None: - yield util.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 util.YES -nodes.UnaryOp._infer = bases.path_wrapper(infer_unaryop) - -def _infer_binop(binop, operand1, operand2, context, failures=None): - if operand1 is util.YES: - yield operand1 - return - try: - for valnode in operand1.infer_binary_op(binop, operand2, context): - yield valnode - except AttributeError: - try: - # XXX just suppose if the type implement meth, returned type - # will be the same - operand1.getattr(protocols.BIN_OP_METHOD[operator]) - yield operand1 - except: - if failures is None: - yield util.YES - else: - failures.append(operand1) - -@bases.yes_if_nothing_inferred -def infer_binop(self, context=None): - failures = [] - for lhs in self.left.infer(context): - for val in _infer_binop(self, lhs, self.right, context, failures): - yield val - for lhs in failures: - for rhs in self.right.infer(context): - for val in _infer_binop(self, rhs, lhs, context): - yield val -nodes.BinOp._infer = bases.path_wrapper(infer_binop) - - -def infer_arguments(self, context=None): - name = context.lookupname - if name is None: - raise exceptions.InferenceError() - return protocols._arguments_infer_argname(self, name, context) -nodes.Arguments._infer = infer_arguments - - -@bases.path_wrapper -def infer_assign(self, context=None): - """infer a AssignName/AssignAttr: 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 bases._infer_stmts(stmts, context) -nodes.AssignName._infer = infer_assign -nodes.AssignAttr._infer = infer_assign - -def infer_augassign(self, context=None): - failures = [] - for lhs in self.target.infer_lhs(context): - for val in _infer_binop(self, lhs, self.value, context, failures): - yield val - for lhs in failures: - for rhs in self.value.infer(context): - for val in _infer_binop(self, rhs, lhs, context): - yield val -nodes.AugAssign._infer = bases.path_wrapper(infer_augassign) - - -# no infer method on DelName and DelAttr (expected InferenceError) - -@bases.path_wrapper -def infer_empty_node(self, context=None): - if not self.has_underlying_object(): - yield util.YES - else: - try: - for inferred in MANAGER.infer_ast_from_something(self.object, - context=context): - yield inferred - except exceptions.AstroidError: - yield util.YES -nodes.EmptyNode._infer = infer_empty_node - - -def infer_index(self, context=None): - return self.value.infer(context) -nodes.Index._infer = infer_index - -# TODO: move directly into bases.Instance when the dependency hell -# will be solved. -def instance_getitem(self, index, context=None): - # Rewrap index to Const for this case - index = nodes.Const(index) - if context: - new_context = context.clone() - else: - context = new_context = contextmod.InferenceContext() - - # Create a new callcontext for providing index as an argument. - new_context.callcontext = contextmod.CallContext(args=[index]) - new_context.boundnode = self - - method = next(self.igetattr('__getitem__', context=context)) - if not isinstance(method, bases.BoundMethod): - raise exceptions.InferenceError - - try: - return next(method.infer_call_result(self, new_context)) - except StopIteration: - raise exceptions.InferenceError - -bases.Instance.getitem = instance_getitem diff --git a/pymode/libs/astroid/manager.py b/pymode/libs/astroid/manager.py deleted file mode 100644 index d08adc29..00000000 --- a/pymode/libs/astroid/manager.py +++ /dev/null @@ -1,267 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""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 - -import imp -import os -import zipimport - -from astroid import exceptions -from astroid import modutils -from astroid import transforms - - -def safe_repr(obj): - try: - return repr(obj) - except Exception: # pylint: disable=broad-except - return '???' - - -class AstroidManager(object): - """the astroid manager, responsible to build astroid from files - or modules. - - Use the Borg pattern. - """ - - name = 'astroid loader' - brain = {} - - def __init__(self): - self.__dict__ = AstroidManager.brain - if not self.__dict__: - # NOTE: cache entries are added by the [re]builder - self.astroid_cache = {} - self._mod_file_cache = {} - self._failed_import_hooks = [] - self.always_load_extensions = False - self.optimize_ast = False - self.extension_package_whitelist = set() - self._transform = transforms.TransformVisitor() - - # Export these APIs for convenience - self.register_transform = self._transform.register_transform - self.unregister_transform = self._transform.unregister_transform - - def visit_transforms(self, node): - """Visit the transforms and apply them to the given *node*.""" - return self._transform.visit(node) - - 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].source_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 exceptions.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(os.path.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 exceptions.AstroidBuildingException(msg) - return self.ast_from_module(module, modname) - elif mp_type == imp.PY_COMPILED: - msg = "Unable to load compiled module %s" % (modname,) - raise exceptions.AstroidBuildingException(msg) - if filepath is None: - msg = "Unable to load module %s" % (modname,) - raise exceptions.AstroidBuildingException(msg) - return self.ast_from_file(filepath, modname, fallback=False) - except exceptions.AstroidBuildingException as e: - for hook in self._failed_import_hooks: - try: - return hook(modname) - except exceptions.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 Exception: # pylint: disable=broad-except - continue - return None - - def file_from_module_name(self, modname, contextfile): - # pylint: disable=redefined-variable-type - 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 = exceptions.AstroidBuildingException(msg) - self._mod_file_cache[(modname, contextfile)] = value - if isinstance(value, exceptions.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: - msg = 'Unable to get module for class %s' % safe_repr(klass) - raise exceptions.AstroidBuildingException(msg) - 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: - msg = 'Unable to get module for %s' % safe_repr(klass) - raise exceptions.AstroidBuildingException(msg) - except Exception as ex: - msg = ('Unexpected error while retrieving module for %s: %s' - % (safe_repr(klass), ex)) - raise exceptions.AstroidBuildingException(msg) - try: - name = klass.__name__ - except AttributeError: - msg = 'Unable to get name for %s' % safe_repr(klass) - raise exceptions.AstroidBuildingException(msg) - except Exception as ex: - exc = ('Unexpected error while retrieving name for %s: %s' - % (safe_repr(klass), ex)) - raise exceptions.AstroidBuildingException(exc) - # take care, on living object __module__ is regularly wrong :( - modastroid = self.ast_from_module_name(modname) - if klass is obj: - for inferred in modastroid.igetattr(name, context): - yield inferred - else: - for inferred in modastroid.igetattr(name, context): - yield inferred.instantiate_class() - - 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 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) diff --git a/pymode/libs/astroid/mixins.py b/pymode/libs/astroid/mixins.py deleted file mode 100644 index 57082f0f..00000000 --- a/pymode/libs/astroid/mixins.py +++ /dev/null @@ -1,147 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""This module contains some mixins for the different nodes. -""" - -import warnings - -from astroid import decorators -from astroid import exceptions - - -class BlockRangeMixIn(object): - """override block range """ - - @decorators.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 assign_type(self): - return self - - def ass_type(self): - warnings.warn('%s.ass_type() is deprecated and slated for removal ' - 'in astroid 2.0, use %s.assign_type() instead.' - % (type(self).__name__, type(self).__name__), - PendingDeprecationWarning, stacklevel=2) - return self.assign_type() - - -class AssignTypeMixin(object): - - def assign_type(self): - return self - - def ass_type(self): - warnings.warn('%s.ass_type() is deprecated and slated for removal ' - 'in astroid 2.0, use %s.assign_type() instead.' - % (type(self).__name__, type(self).__name__), - PendingDeprecationWarning, stacklevel=2) - return self.assign_type() - - 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 assign_type(self): - return self.parent.assign_type() - - def ass_type(self): - warnings.warn('%s.ass_type() is deprecated and slated for removal ' - 'in astroid 2.0, use %s.assign_type() instead.' - % (type(self).__name__, type(self).__name__), - PendingDeprecationWarning, stacklevel=2) - return self.assign_type() - - -class ImportFromMixin(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 imported by - """ - # 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, - relative_only=level and level >= 1) - except exceptions.AstroidBuildingException as ex: - if isinstance(ex.args[0], SyntaxError): - raise exceptions.InferenceError(str(ex)) - raise exceptions.InferenceError(modname) - except SyntaxError as ex: - raise exceptions.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 exceptions.NotFoundError(asname) diff --git a/pymode/libs/astroid/modutils.py b/pymode/libs/astroid/modutils.py deleted file mode 100644 index 31104cb5..00000000 --- a/pymode/libs/astroid/modutils.py +++ /dev/null @@ -1,741 +0,0 @@ -# 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 . -"""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 - -import imp -import os -import platform -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 - -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',) - - -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)]) -# 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() - -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 -if platform.python_implementation() == 'PyPy': - _root = os.path.join(sys.prefix, 'lib_pypy') - STD_LIB_DIRS.add(_root) - try: - # real_prefix is defined when running inside virtualenv. - STD_LIB_DIRS.add(os.path.join(sys.real_prefix, 'lib_pypy')) - except AttributeError: - pass - del _root -if os.name == 'posix': - # Need the real prefix is we're under a virtualenv, otherwise - # the usual one will do. - try: - prefix = sys.real_prefix - except AttributeError: - prefix = sys.prefix - - def _posix_path(path): - base_python = 'python%d.%d' % sys.version_info[:2] - return os.path.join(prefix, path, base_python) - - STD_LIB_DIRS.add(_posix_path('lib')) - if sys.maxsize > 2**32: - # This tries to fix a problem with /usr/lib64 builds, - # where systems are running both 32-bit and 64-bit code - # on the same machine, which reflects into the places where - # standard library could be found. More details can be found - # here http://bugs.python.org/issue1294959. - # An easy reproducing case would be - # https://github.com/PyCQA/pylint/issues/712#issuecomment-163178753 - STD_LIB_DIRS.add(_posix_path('lib64')) - -EXT_LIB_DIR = get_python_lib() -IS_JYTHON = platform.python_implementation() == 'Jython' -BUILTIN_MODULES = dict.fromkeys(sys.builtin_module_names, True) - - -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)) - - -def _path_from_filename(filename, is_jython=IS_JYTHON): - if not is_jython: - if sys.version_info > (3, 0): - return filename - else: - if filename.endswith(".pyc"): - return filename[:-1] - return filename - head, has_pyclass, _ = filename.partition("$py.class") - if has_pyclass: - return head + ".py" - return filename - - -def _handle_blacklist(blacklist, dirnames, filenames): - """remove files/directories in the black list - - dirnames/filenames are usually from os.walk - """ - for norecurs in blacklist: - if norecurs in dirnames: - dirnames.remove(norecurs) - elif norecurs in filenames: - filenames.remove(norecurs) - - -_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=True): - """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__', '') - prevmodule = module - if not _file and _is_namespace(curname): - continue - if not _file and len(modpath) != len(parts): - raise ImportError('no module in %s' % '.'.join(parts[len(modpath):])) - path = [os.path.dirname(_file)] - return module - - -def load_module_from_file(filepath, path=None, use_sys=True, 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""" - modpath = [] - for part in mod_path: - modpath.append(part) - path = os.path.join(path, part) - if not _is_namespace('.'.join(modpath)) and 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 - """ - filename = _path_from_filename(filename) - filename = os.path.abspath(filename) - base = os.path.splitext(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('astroid.as_string.dump') - 'astroid.as_string' - - :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: iterable - list of files or directories to ignore. - - :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 - """ - filename = os.path.abspath(_path_from_filename(filename)) - base, orig_ext = os.path.splitext(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: - # we assume there are no namespaces in stdlib - return not _is_namespace(modname) - 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 list(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)) - -try: - import pkg_resources -except ImportError: - pkg_resources = None - - -def _is_namespace(modname): - return (pkg_resources is not None - and modname in pkg_resources._namespace_packages) - - -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 _is_namespace(modpath[0]) and modpath[0] in sys.modules: - # setuptools has added into sys.modules a module object with proper - # __path__, get back information from there - module = sys.modules[modpath.pop(0)] - path = list(module.__path__) - if not modpath: - return imp.C_BUILTIN, None - 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: - extend_path = b'pkgutil' in data and b'extend_path' in data - declare_namespace = ( - b"pkg_resources" in data - and b"declare_namespace(__name__)" in data) - if extend_path or declare_namespace: - # 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 diff --git a/pymode/libs/astroid/node_classes.py b/pymode/libs/astroid/node_classes.py deleted file mode 100644 index ca773c3a..00000000 --- a/pymode/libs/astroid/node_classes.py +++ /dev/null @@ -1,1053 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""Module for some node classes. More nodes in scoped_nodes.py -""" - -import abc -import warnings - -import lazy_object_proxy -import six - -from astroid import bases -from astroid import context as contextmod -from astroid import decorators -from astroid import exceptions -from astroid import mixins -from astroid import util - - -BUILTINS = six.moves.builtins.__name__ - - -@bases.raise_if_nothing_inferred -def unpack_infer(stmt, context=None): - """recursively generate nodes inferred by the given statement. - If the inferred value is a list or a tuple, recurse on the elements - """ - if isinstance(stmt, (List, Tuple)): - for elt in stmt.elts: - if elt is util.YES: - yield elt - continue - for inferred_elt in unpack_infer(elt, context): - yield inferred_elt - return - # if inferred is a final node, return it and stop - inferred = next(stmt.infer(context)) - if inferred is stmt: - yield inferred - return - # else, infer recursivly, except YES object that should be returned as is - for inferred in stmt.infer(context): - if inferred is util.YES: - yield inferred - else: - for inf_inf in unpack_infer(inferred, context): - yield inf_inf - - -def are_exclusive(stmt1, stmt2, exceptions=None): - """return true if the two given statements are mutually exclusive - - `exceptions` may be a list of exception names. If specified, discard If - branches and check one of the statement is in an exception handler catching - one of the given exceptions. - - algorithm : - 1) index stmt1's parents - 2) climb among stmt2's parents until we find a common parent - 3) if the common parent is a If or TryExcept statement, look if nodes are - in exclusive branches - """ - # index stmt1's parents - stmt1_parents = {} - children = {} - node = stmt1.parent - previous = stmt1 - while node: - stmt1_parents[node] = 1 - children[node] = previous - previous = node - node = node.parent - # climb among stmt2's parents until we find a common parent - node = stmt2.parent - previous = stmt2 - while node: - if node in stmt1_parents: - # if the common parent is a If or TryExcept statement, look if - # nodes are in exclusive branches - if isinstance(node, If) and exceptions is None: - if (node.locate_child(previous)[1] - is not node.locate_child(children[node])[1]): - return True - elif isinstance(node, TryExcept): - c2attr, c2node = node.locate_child(previous) - c1attr, c1node = node.locate_child(children[node]) - if c1node is not c2node: - if ((c2attr == 'body' - and c1attr == 'handlers' - and children[node].catch(exceptions)) or - (c2attr == 'handlers' and c1attr == 'body' and previous.catch(exceptions)) or - (c2attr == 'handlers' and c1attr == 'orelse') or - (c2attr == 'orelse' and c1attr == 'handlers')): - return True - elif c2attr == 'handlers' and c1attr == 'handlers': - return previous is not children[node] - return False - previous = node - node = node.parent - return False - - -@six.add_metaclass(abc.ABCMeta) -class _BaseContainer(mixins.ParentAssignTypeMixin, - bases.NodeNG, - bases.Instance): - """Base class for Set, FrozenSet, Tuple and List.""" - - _astroid_fields = ('elts',) - - def __init__(self, elts=None): - if elts is None: - self.elts = [] - else: - self.elts = [const_factory(e) for e in elts] - - def itered(self): - return self.elts - - def bool_value(self): - return bool(self.elts) - - @abc.abstractmethod - def pytype(self): - pass - - -class LookupMixIn(object): - """Mixin looking up a name in the right scope - """ - - def lookup(self, name): - """lookup a variable name - - return the scope node and the list of assignments associated to the - given name according to the scope where it has been found (locals, - globals or builtin) - - The lookup is starting from self's scope. If self is not a frame itself - and the name is found in the inner frame locals, statements will be - filtered to remove ignorable statements according to self's location - """ - return self.scope().scope_lookup(self, name) - - def ilookup(self, name): - """inferred lookup - - return an iterator on inferred values of the statements returned by - the lookup method - """ - frame, stmts = self.lookup(name) - context = contextmod.InferenceContext() - return bases._infer_stmts(stmts, context, frame) - - def _filter_stmts(self, stmts, frame, offset): - """filter statements to remove ignorable statements. - - If self is not a frame itself and the name is found in the inner - frame locals, statements will be filtered to remove ignorable - statements according to self's location - """ - # if offset == -1, my actual frame is not the inner frame but its parent - # - # class A(B): pass - # - # we need this to resolve B correctly - if offset == -1: - myframe = self.frame().parent.frame() - else: - myframe = self.frame() - # If the frame of this node is the same as the statement - # of this node, then the node is part of a class or - # a function definition and the frame of this node should be the - # the upper frame, not the frame of the definition. - # For more information why this is important, - # see Pylint issue #295. - # For example, for 'b', the statement is the same - # as the frame / scope: - # - # def test(b=1): - # ... - - if self.statement() is myframe and myframe.parent: - myframe = myframe.parent.frame() - - mystmt = self.statement() - # line filtering if we are in the same frame - # - # take care node may be missing lineno information (this is the case for - # nodes inserted for living objects) - if myframe is frame and mystmt.fromlineno is not None: - assert mystmt.fromlineno is not None, mystmt - mylineno = mystmt.fromlineno + offset - else: - # disabling lineno filtering - mylineno = 0 - _stmts = [] - _stmt_parents = [] - for node in stmts: - stmt = node.statement() - # line filtering is on and we have reached our location, break - if mylineno > 0 and stmt.fromlineno > mylineno: - break - assert hasattr(node, 'assign_type'), (node, node.scope(), - node.scope().locals) - assign_type = node.assign_type() - if node.has_base(self): - break - - _stmts, done = assign_type._get_filtered_stmts(self, node, _stmts, mystmt) - if done: - break - - optional_assign = assign_type.optional_assign - if optional_assign and assign_type.parent_of(self): - # we are inside a loop, loop var assigment is hidding previous - # assigment - _stmts = [node] - _stmt_parents = [stmt.parent] - continue - - # XXX comment various branches below!!! - try: - pindex = _stmt_parents.index(stmt.parent) - except ValueError: - pass - else: - # we got a parent index, this means the currently visited node - # is at the same block level as a previously visited node - if _stmts[pindex].assign_type().parent_of(assign_type): - # both statements are not at the same block level - continue - # if currently visited node is following previously considered - # assignement and both are not exclusive, we can drop the - # previous one. For instance in the following code :: - # - # if a: - # x = 1 - # else: - # x = 2 - # print x - # - # we can't remove neither x = 1 nor x = 2 when looking for 'x' - # of 'print x'; while in the following :: - # - # x = 1 - # x = 2 - # print x - # - # we can remove x = 1 when we see x = 2 - # - # moreover, on loop assignment types, assignment won't - # necessarily be done if the loop has no iteration, so we don't - # want to clear previous assigments if any (hence the test on - # optional_assign) - if not (optional_assign or are_exclusive(_stmts[pindex], node)): - del _stmt_parents[pindex] - del _stmts[pindex] - if isinstance(node, AssignName): - if not optional_assign and stmt.parent is mystmt.parent: - _stmts = [] - _stmt_parents = [] - elif isinstance(node, DelName): - _stmts = [] - _stmt_parents = [] - continue - if not are_exclusive(self, node): - _stmts.append(node) - _stmt_parents.append(stmt.parent) - return _stmts - - -# Name classes - -class AssignName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG): - """class representing an AssName node""" - - -class DelName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG): - """class representing a DelName node""" - - -class Name(LookupMixIn, bases.NodeNG): - """class representing a Name node""" - - -class Arguments(mixins.AssignTypeMixin, bases.NodeNG): - """class representing an Arguments node""" - if six.PY3: - # Python 3.4+ uses a different approach regarding annotations, - # each argument is a new class, _ast.arg, which exposes an - # 'annotation' attribute. In astroid though, arguments are exposed - # as is in the Arguments node and the only way to expose annotations - # is by using something similar with Python 3.3: - # - we expose 'varargannotation' and 'kwargannotation' of annotations - # of varargs and kwargs. - # - we expose 'annotation', a list with annotations for - # for each normal argument. If an argument doesn't have an - # annotation, its value will be None. - - _astroid_fields = ('args', 'defaults', 'kwonlyargs', - 'kw_defaults', 'annotations', - 'varargannotation', 'kwargannotation') - annotations = None - varargannotation = None - kwargannotation = None - else: - _astroid_fields = ('args', 'defaults', 'kwonlyargs', 'kw_defaults') - args = None - defaults = None - kwonlyargs = None - kw_defaults = None - - def __init__(self, vararg=None, kwarg=None): - self.vararg = vararg - self.kwarg = kwarg - - def _infer_name(self, frame, name): - if self.parent is frame: - return name - return None - - @decorators.cachedproperty - def fromlineno(self): - lineno = super(Arguments, self).fromlineno - return max(lineno, self.parent.fromlineno or 0) - - def format_args(self): - """return arguments formatted as string""" - result = [] - if self.args: - result.append( - _format_args(self.args, self.defaults, - getattr(self, 'annotations', None)) - ) - if self.vararg: - result.append('*%s' % self.vararg) - if self.kwonlyargs: - if not self.vararg: - result.append('*') - result.append(_format_args(self.kwonlyargs, self.kw_defaults)) - if self.kwarg: - result.append('**%s' % self.kwarg) - return ', '.join(result) - - def default_value(self, argname): - """return the default value for an argument - - :raise `NoDefault`: if there is no default value defined - """ - i = _find_arg(argname, self.args)[0] - if i is not None: - idx = i - (len(self.args) - len(self.defaults)) - if idx >= 0: - return self.defaults[idx] - i = _find_arg(argname, self.kwonlyargs)[0] - if i is not None and self.kw_defaults[i] is not None: - return self.kw_defaults[i] - raise exceptions.NoDefault() - - def is_argument(self, name): - """return True if the name is defined in arguments""" - if name == self.vararg: - return True - if name == self.kwarg: - return True - return self.find_argname(name, True)[1] is not None - - def find_argname(self, argname, rec=False): - """return index and Name node with given name""" - if self.args: # self.args may be None in some cases (builtin function) - return _find_arg(argname, self.args, rec) - return None, None - - def get_children(self): - """override get_children to skip over None elements in kw_defaults""" - for child in super(Arguments, self).get_children(): - if child is not None: - yield child - - -def _find_arg(argname, args, rec=False): - for i, arg in enumerate(args): - if isinstance(arg, Tuple): - if rec: - found = _find_arg(argname, arg.elts) - if found[0] is not None: - return found - elif arg.name == argname: - return i, arg - return None, None - - -def _format_args(args, defaults=None, annotations=None): - values = [] - if args is None: - return '' - if annotations is None: - annotations = [] - if defaults is not None: - default_offset = len(args) - len(defaults) - packed = six.moves.zip_longest(args, annotations) - for i, (arg, annotation) in enumerate(packed): - if isinstance(arg, Tuple): - values.append('(%s)' % _format_args(arg.elts)) - else: - argname = arg.name - if annotation is not None: - argname += ':' + annotation.as_string() - values.append(argname) - - if defaults is not None and i >= default_offset: - if defaults[i-default_offset] is not None: - values[-1] += '=' + defaults[i-default_offset].as_string() - return ', '.join(values) - - -class AssignAttr(mixins.ParentAssignTypeMixin, bases.NodeNG): - """class representing an AssignAttr node""" - _astroid_fields = ('expr',) - expr = None - -class Assert(bases.Statement): - """class representing an Assert node""" - _astroid_fields = ('test', 'fail',) - test = None - fail = None - -class Assign(bases.Statement, mixins.AssignTypeMixin): - """class representing an Assign node""" - _astroid_fields = ('targets', 'value',) - targets = None - value = None - -class AugAssign(bases.Statement, mixins.AssignTypeMixin): - """class representing an AugAssign node""" - _astroid_fields = ('target', 'value',) - target = None - value = None - -class Repr(bases.NodeNG): - """class representing a Backquote node""" - _astroid_fields = ('value',) - value = None - -class BinOp(bases.NodeNG): - """class representing a BinOp node""" - _astroid_fields = ('left', 'right',) - left = None - right = None - -class BoolOp(bases.NodeNG): - """class representing a BoolOp node""" - _astroid_fields = ('values',) - values = None - -class Break(bases.Statement): - """class representing a Break node""" - - -class Call(bases.NodeNG): - """class representing a Call node""" - _astroid_fields = ('func', 'args', 'keywords') - func = None - args = None - keywords = None - - @property - def starargs(self): - args = self.args or [] - return [arg for arg in args if isinstance(arg, Starred)] - - @property - def kwargs(self): - keywords = self.keywords or [] - return [keyword for keyword in keywords if keyword.arg is None] - -class Compare(bases.NodeNG): - """class representing a Compare node""" - _astroid_fields = ('left', 'ops',) - left = None - ops = None - - def get_children(self): - """override get_children for tuple fields""" - yield self.left - for _, comparator in self.ops: - yield comparator # we don't want the 'op' - - def last_child(self): - """override last_child""" - # XXX maybe if self.ops: - return self.ops[-1][1] - #return self.left - - -class Comprehension(bases.NodeNG): - """class representing a Comprehension node""" - _astroid_fields = ('target', 'iter', 'ifs') - target = None - iter = None - ifs = None - - optional_assign = True - def assign_type(self): - return self - - def ass_type(self): - warnings.warn('%s.ass_type() is deprecated and slated for removal' - 'in astroid 2.0, use %s.assign_type() instead.' - % (type(self).__name__, type(self).__name__), - PendingDeprecationWarning, stacklevel=2) - return self.assign_type() - - def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt): - """method used in filter_stmts""" - if self is mystmt: - if isinstance(lookup_node, (Const, Name)): - return [lookup_node], True - - elif self.statement() is mystmt: - # original node's statement is the assignment, only keeps - # current node (gen exp, list comp) - - return [node], True - - return stmts, False - - -class Const(bases.NodeNG, bases.Instance): - """represent a constant node like num, str, bool, None, bytes""" - - def __init__(self, value=None): - self.value = value - - def getitem(self, index, context=None): - if isinstance(self.value, six.string_types): - return Const(self.value[index]) - if isinstance(self.value, bytes) and six.PY3: - # Bytes aren't instances of six.string_types - # on Python 3. Also, indexing them should return - # integers. - return Const(self.value[index]) - raise TypeError('%r (value=%s)' % (self, self.value)) - - def has_dynamic_getattr(self): - return False - - def itered(self): - if isinstance(self.value, six.string_types): - return self.value - raise TypeError() - - def pytype(self): - return self._proxied.qname() - - -class Continue(bases.Statement): - """class representing a Continue node""" - - -class Decorators(bases.NodeNG): - """class representing a Decorators node""" - _astroid_fields = ('nodes',) - nodes = None - - def __init__(self, nodes=None): - self.nodes = nodes - - def scope(self): - # skip the function node to go directly to the upper level scope - return self.parent.parent.scope() - - -class DelAttr(mixins.ParentAssignTypeMixin, bases.NodeNG): - """class representing a DelAttr node""" - _astroid_fields = ('expr',) - expr = None - - - -class Delete(mixins.AssignTypeMixin, bases.Statement): - """class representing a Delete node""" - _astroid_fields = ('targets',) - targets = None - - -class Dict(bases.NodeNG, bases.Instance): - """class representing a Dict node""" - _astroid_fields = ('items',) - - def __init__(self, items=None): - if items is None: - self.items = [] - else: - self.items = [(const_factory(k), const_factory(v)) - for k, v in list(items.items())] - - def pytype(self): - return '%s.dict' % BUILTINS - - def get_children(self): - """get children of a Dict node""" - # overrides get_children - for key, value in self.items: - yield key - yield value - - def last_child(self): - """override last_child""" - if self.items: - return self.items[-1][1] - return None - - def itered(self): - return self.items[::2] - - def getitem(self, lookup_key, context=None): - for key, value in self.items: - # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}. - if isinstance(key, DictUnpack): - try: - return value.getitem(lookup_key, context) - except IndexError: - continue - for inferredkey in key.infer(context): - if inferredkey is util.YES: - continue - if isinstance(inferredkey, Const) \ - and inferredkey.value == lookup_key: - return value - # This should raise KeyError, but all call sites only catch - # IndexError. Let's leave it like that for now. - raise IndexError(lookup_key) - - -class Expr(bases.Statement): - """class representing a Expr node""" - _astroid_fields = ('value',) - value = None - - -class Ellipsis(bases.NodeNG): # pylint: disable=redefined-builtin - """class representing an Ellipsis node""" - - -class EmptyNode(bases.NodeNG): - """class representing an EmptyNode node""" - - -class ExceptHandler(mixins.AssignTypeMixin, bases.Statement): - """class representing an ExceptHandler node""" - _astroid_fields = ('type', 'name', 'body',) - type = None - name = None - body = None - - @decorators.cachedproperty - def blockstart_tolineno(self): - if self.name: - return self.name.tolineno - elif self.type: - return self.type.tolineno - else: - return self.lineno - - def catch(self, exceptions): - if self.type is None or exceptions is None: - return True - for node in self.type.nodes_of_class(Name): - if node.name in exceptions: - return True - - -class Exec(bases.Statement): - """class representing an Exec node""" - _astroid_fields = ('expr', 'globals', 'locals',) - expr = None - globals = None - locals = None - - -class ExtSlice(bases.NodeNG): - """class representing an ExtSlice node""" - _astroid_fields = ('dims',) - dims = None - -class For(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement): - """class representing a For node""" - _astroid_fields = ('target', 'iter', 'body', 'orelse',) - target = None - iter = None - body = None - orelse = None - - optional_assign = True - @decorators.cachedproperty - def blockstart_tolineno(self): - return self.iter.tolineno - - -class AsyncFor(For): - """Asynchronous For built with `async` keyword.""" - - -class Await(bases.NodeNG): - """Await node for the `await` keyword.""" - - _astroid_fields = ('value', ) - value = None - - def postinit(self, value=None): - self.value = value - - -class ImportFrom(mixins.ImportFromMixin, bases.Statement): - """class representing a From node""" - - def __init__(self, fromname, names, level=0): - self.modname = fromname - self.names = names - self.level = level - -class Attribute(bases.NodeNG): - """class representing a Attribute node""" - _astroid_fields = ('expr',) - expr = None - - -class Global(bases.Statement): - """class representing a Global node""" - - def __init__(self, names): - self.names = names - - def _infer_name(self, frame, name): - return name - - -class If(mixins.BlockRangeMixIn, bases.Statement): - """class representing an If node""" - _astroid_fields = ('test', 'body', 'orelse') - test = None - body = None - orelse = None - - @decorators.cachedproperty - def blockstart_tolineno(self): - return self.test.tolineno - - def block_range(self, lineno): - """handle block line numbers range for if statements""" - if lineno == self.body[0].fromlineno: - return lineno, lineno - if lineno <= self.body[-1].tolineno: - return lineno, self.body[-1].tolineno - return self._elsed_block_range(lineno, self.orelse, - self.body[0].fromlineno - 1) - - -class IfExp(bases.NodeNG): - """class representing an IfExp node""" - _astroid_fields = ('test', 'body', 'orelse') - test = None - body = None - orelse = None - - -class Import(mixins.ImportFromMixin, bases.Statement): - """class representing an Import node""" - - -class Index(bases.NodeNG): - """class representing an Index node""" - _astroid_fields = ('value',) - value = None - - -class Keyword(bases.NodeNG): - """class representing a Keyword node""" - _astroid_fields = ('value',) - value = None - - -class List(_BaseContainer): - """class representing a List node""" - - def pytype(self): - return '%s.list' % BUILTINS - - def getitem(self, index, context=None): - return self.elts[index] - - -class Nonlocal(bases.Statement): - """class representing a Nonlocal node""" - - def __init__(self, names): - self.names = names - - def _infer_name(self, frame, name): - return name - - -class Pass(bases.Statement): - """class representing a Pass node""" - - -class Print(bases.Statement): - """class representing a Print node""" - _astroid_fields = ('dest', 'values',) - dest = None - values = None - - -class Raise(bases.Statement): - """class representing a Raise node""" - exc = None - if six.PY2: - _astroid_fields = ('exc', 'inst', 'tback') - inst = None - tback = None - else: - _astroid_fields = ('exc', 'cause') - exc = None - cause = None - - def raises_not_implemented(self): - if not self.exc: - return - for name in self.exc.nodes_of_class(Name): - if name.name == 'NotImplementedError': - return True - - -class Return(bases.Statement): - """class representing a Return node""" - _astroid_fields = ('value',) - value = None - - -class Set(_BaseContainer): - """class representing a Set node""" - - def pytype(self): - return '%s.set' % BUILTINS - - -class Slice(bases.NodeNG): - """class representing a Slice node""" - _astroid_fields = ('lower', 'upper', 'step') - lower = None - upper = None - step = None - -class Starred(mixins.ParentAssignTypeMixin, bases.NodeNG): - """class representing a Starred node""" - _astroid_fields = ('value',) - value = None - - -class Subscript(bases.NodeNG): - """class representing a Subscript node""" - _astroid_fields = ('value', 'slice') - value = None - slice = None - - -class TryExcept(mixins.BlockRangeMixIn, bases.Statement): - """class representing a TryExcept node""" - _astroid_fields = ('body', 'handlers', 'orelse',) - body = None - handlers = None - orelse = None - - def _infer_name(self, frame, name): - return name - - def block_range(self, lineno): - """handle block line numbers range for try/except statements""" - last = None - for exhandler in self.handlers: - if exhandler.type and lineno == exhandler.type.fromlineno: - return lineno, lineno - if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno: - return lineno, exhandler.body[-1].tolineno - if last is None: - last = exhandler.body[0].fromlineno - 1 - return self._elsed_block_range(lineno, self.orelse, last) - - -class TryFinally(mixins.BlockRangeMixIn, bases.Statement): - """class representing a TryFinally node""" - _astroid_fields = ('body', 'finalbody',) - body = None - finalbody = None - - def block_range(self, lineno): - """handle block line numbers range for try/finally statements""" - child = self.body[0] - # py2.5 try: except: finally: - if (isinstance(child, TryExcept) and child.fromlineno == self.fromlineno - and lineno > self.fromlineno and lineno <= child.tolineno): - return child.block_range(lineno) - return self._elsed_block_range(lineno, self.finalbody) - - -class Tuple(_BaseContainer): - """class representing a Tuple node""" - - def pytype(self): - return '%s.tuple' % BUILTINS - - def getitem(self, index, context=None): - return self.elts[index] - - -class UnaryOp(bases.NodeNG): - """class representing an UnaryOp node""" - _astroid_fields = ('operand',) - operand = None - - -class While(mixins.BlockRangeMixIn, bases.Statement): - """class representing a While node""" - _astroid_fields = ('test', 'body', 'orelse',) - test = None - body = None - orelse = None - - @decorators.cachedproperty - def blockstart_tolineno(self): - return self.test.tolineno - - def block_range(self, lineno): - """handle block line numbers range for for and while statements""" - return self. _elsed_block_range(lineno, self.orelse) - - -class With(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement): - """class representing a With node""" - _astroid_fields = ('items', 'body') - items = None - body = None - - @decorators.cachedproperty - def blockstart_tolineno(self): - return self.items[-1][0].tolineno - - def get_children(self): - for expr, var in self.items: - yield expr - if var: - yield var - for elt in self.body: - yield elt - - -class AsyncWith(With): - """Asynchronous `with` built with the `async` keyword.""" - - -class Yield(bases.NodeNG): - """class representing a Yield node""" - _astroid_fields = ('value',) - value = None - -class YieldFrom(Yield): - """ Class representing a YieldFrom node. """ - - -class DictUnpack(bases.NodeNG): - """Represents the unpacking of dicts into dicts using PEP 448.""" - - -# constants ############################################################## - -CONST_CLS = { - list: List, - tuple: Tuple, - dict: Dict, - set: Set, - type(None): Const, - type(NotImplemented): Const, - } - -def _update_const_classes(): - """update constant classes, so the keys of CONST_CLS can be reused""" - klasses = (bool, int, float, complex, str) - if six.PY2: - klasses += (unicode, long) - klasses += (bytes,) - for kls in klasses: - CONST_CLS[kls] = Const -_update_const_classes() - - -def const_factory(value): - """return an astroid node for a python value""" - # XXX we should probably be stricter here and only consider stuff in - # CONST_CLS or do better treatment: in case where value is not in CONST_CLS, - # we should rather recall the builder on this value than returning an empty - # node (another option being that const_factory shouldn't be called with something - # not in CONST_CLS) - assert not isinstance(value, bases.NodeNG) - try: - return CONST_CLS[value.__class__](value) - except (KeyError, AttributeError): - node = EmptyNode() - node.object = value - return node - - -# Backward-compatibility aliases -def instancecheck(cls, other): - wrapped = cls.__wrapped__ - other_cls = other.__class__ - is_instance_of = wrapped is other_cls or issubclass(other_cls, wrapped) - warnings.warn("%r is deprecated and slated for removal in astroid " - "2.0, use %r instead" % (cls.__class__.__name__, - wrapped.__name__), - PendingDeprecationWarning, stacklevel=2) - return is_instance_of - - -def proxy_alias(alias_name, node_type): - proxy = type(alias_name, (lazy_object_proxy.Proxy,), - {'__class__': object.__dict__['__class__'], - '__instancecheck__': instancecheck}) - return proxy(lambda: node_type) - -Backquote = proxy_alias('Backquote', Repr) -Discard = proxy_alias('Discard', Expr) -AssName = proxy_alias('AssName', AssignName) -AssAttr = proxy_alias('AssAttr', AssignAttr) -Getattr = proxy_alias('Getattr', Attribute) -CallFunc = proxy_alias('CallFunc', Call) -From = proxy_alias('From', ImportFrom) diff --git a/pymode/libs/astroid/nodes.py b/pymode/libs/astroid/nodes.py deleted file mode 100644 index 2fd6cb65..00000000 --- a/pymode/libs/astroid/nodes.py +++ /dev/null @@ -1,87 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -""" -on all nodes : - .is_statement, returning true if the node should be considered as a - statement node - .root(), returning the root node of the tree (i.e. a Module) - .previous_sibling(), returning previous sibling statement node - .next_sibling(), returning next sibling statement node - .statement(), returning the first parent node marked as statement node - .frame(), returning the first node defining a new local scope (i.e. - Module, FunctionDef or ClassDef) - .set_local(name, node), define an identifier on the first parent frame, - with the node defining it. This is used by the astroid builder and should not - be used from out there. - -on ImportFrom and Import : - .real_name(name), - - -""" -# pylint: disable=unused-import,redefined-builtin - -from astroid.node_classes import ( - Arguments, AssignAttr, Assert, Assign, - AssignName, AugAssign, Repr, BinOp, BoolOp, Break, Call, Compare, - Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, - Dict, Expr, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, - ImportFrom, Attribute, Global, If, IfExp, Import, Index, Keyword, - List, Name, Nonlocal, Pass, Print, Raise, Return, Set, Slice, Starred, Subscript, - TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, YieldFrom, - const_factory, - AsyncFor, Await, AsyncWith, - # Backwards-compatibility aliases - Backquote, Discard, AssName, AssAttr, Getattr, CallFunc, From, - # Node not present in the builtin ast module. - DictUnpack, -) -from astroid.scoped_nodes import ( - Module, GeneratorExp, Lambda, DictComp, - ListComp, SetComp, FunctionDef, ClassDef, - AsyncFunctionDef, - # Backwards-compatibility aliases - Class, Function, GenExpr, -) - - - -ALL_NODE_CLASSES = ( - AsyncFunctionDef, AsyncFor, AsyncWith, Await, - - Arguments, AssignAttr, Assert, Assign, AssignName, AugAssign, - Repr, BinOp, BoolOp, Break, - Call, ClassDef, Compare, Comprehension, Const, Continue, - Decorators, DelAttr, DelName, Delete, - Dict, DictComp, DictUnpack, Expr, - Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, - For, ImportFrom, FunctionDef, - Attribute, GeneratorExp, Global, - If, IfExp, Import, Index, - Keyword, - Lambda, List, ListComp, - Name, Nonlocal, - Module, - Pass, Print, - Raise, Return, - Set, SetComp, Slice, Starred, Subscript, - TryExcept, TryFinally, Tuple, - UnaryOp, - While, With, - Yield, YieldFrom, - ) diff --git a/pymode/libs/astroid/objects.py b/pymode/libs/astroid/objects.py deleted file mode 100644 index d2f4270b..00000000 --- a/pymode/libs/astroid/objects.py +++ /dev/null @@ -1,186 +0,0 @@ -# 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 . - -""" -Inference objects are a way to represent composite AST nodes, -which are used only as inference results, so they can't be found in the -code tree. For instance, inferring the following frozenset use, leads to an -inferred FrozenSet: - - CallFunc(func=Name('frozenset'), args=Tuple(...)) - -""" - -import six - -from astroid import MANAGER -from astroid.bases import ( - BUILTINS, NodeNG, Instance, _infer_stmts, - BoundMethod, _is_property -) -from astroid.decorators import cachedproperty -from astroid.exceptions import ( - SuperError, SuperArgumentTypeError, - NotFoundError, MroError -) -from astroid.node_classes import const_factory -from astroid.scoped_nodes import ClassDef, FunctionDef -from astroid.mixins import ParentAssignTypeMixin - - -class FrozenSet(NodeNG, Instance, ParentAssignTypeMixin): - """class representing a FrozenSet composite node""" - - def __init__(self, elts=None): - if elts is None: - self.elts = [] - else: - self.elts = [const_factory(e) for e in elts] - - def pytype(self): - return '%s.frozenset' % BUILTINS - - def itered(self): - return self.elts - - def _infer(self, context=None): - yield self - - @cachedproperty - def _proxied(self): - builtins = MANAGER.astroid_cache[BUILTINS] - return builtins.getattr('frozenset')[0] - - -class Super(NodeNG): - """Proxy class over a super call. - - This class offers almost the same behaviour as Python's super, - which is MRO lookups for retrieving attributes from the parents. - - The *mro_pointer* is the place in the MRO from where we should - start looking, not counting it. *mro_type* is the object which - provides the MRO, it can be both a type or an instance. - *self_class* is the class where the super call is, while - *scope* is the function where the super call is. - """ - - def __init__(self, mro_pointer, mro_type, self_class, scope): - self.type = mro_type - self.mro_pointer = mro_pointer - self._class_based = False - self._self_class = self_class - self._scope = scope - self._model = { - '__thisclass__': self.mro_pointer, - '__self_class__': self._self_class, - '__self__': self.type, - '__class__': self._proxied, - } - - def _infer(self, context=None): - yield self - - def super_mro(self): - """Get the MRO which will be used to lookup attributes in this super.""" - if not isinstance(self.mro_pointer, ClassDef): - raise SuperArgumentTypeError("The first super argument must be type.") - - if isinstance(self.type, ClassDef): - # `super(type, type)`, most likely in a class method. - self._class_based = True - mro_type = self.type - else: - mro_type = getattr(self.type, '_proxied', None) - if not isinstance(mro_type, (Instance, ClassDef)): - raise SuperArgumentTypeError("super(type, obj): obj must be an " - "instance or subtype of type") - - if not mro_type.newstyle: - raise SuperError("Unable to call super on old-style classes.") - - mro = mro_type.mro() - if self.mro_pointer not in mro: - raise SuperArgumentTypeError("super(type, obj): obj must be an " - "instance or subtype of type") - - index = mro.index(self.mro_pointer) - return mro[index + 1:] - - @cachedproperty - def _proxied(self): - builtins = MANAGER.astroid_cache[BUILTINS] - return builtins.getattr('super')[0] - - def pytype(self): - return '%s.super' % BUILTINS - - def display_type(self): - return 'Super of' - - @property - def name(self): - """Get the name of the MRO pointer.""" - return self.mro_pointer.name - - def igetattr(self, name, context=None): - """Retrieve the inferred values of the given attribute name.""" - - local_name = self._model.get(name) - if local_name: - yield local_name - return - - try: - mro = self.super_mro() - except (MroError, SuperError) as exc: - # Don't let invalid MROs or invalid super calls - # to leak out as is from this function. - six.raise_from(NotFoundError, exc) - - found = False - for cls in mro: - if name not in cls._locals: - continue - - found = True - for infered in _infer_stmts([cls[name]], context, frame=self): - if not isinstance(infered, FunctionDef): - yield infered - continue - - # We can obtain different descriptors from a super depending - # on what we are accessing and where the super call is. - if infered.type == 'classmethod': - yield BoundMethod(infered, cls) - elif self._scope.type == 'classmethod' and infered.type == 'method': - yield infered - elif self._class_based or infered.type == 'staticmethod': - yield infered - elif _is_property(infered): - # TODO: support other descriptors as well. - for value in infered.infer_call_result(self, context): - yield value - else: - yield BoundMethod(infered, cls) - - if not found: - raise NotFoundError(name) - - def getattr(self, name, context=None): - return list(self.igetattr(name, context=context)) diff --git a/pymode/libs/astroid/protocols.py b/pymode/libs/astroid/protocols.py deleted file mode 100644 index 87a6d4d2..00000000 --- a/pymode/libs/astroid/protocols.py +++ /dev/null @@ -1,470 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""this module contains a set of functions to handle python protocols for nodes -where it makes sense. -""" - -import collections -import operator -import sys - -from astroid import arguments -from astroid import bases -from astroid import context as contextmod -from astroid import exceptions -from astroid import node_classes -from astroid import nodes -from astroid import util - -BIN_OP_METHOD = {'+': '__add__', - '-': '__sub__', - '/': '__div__', - '//': '__floordiv__', - '*': '__mul__', - '**': '__pow__', - '%': '__mod__', - '&': '__and__', - '|': '__or__', - '^': '__xor__', - '<<': '__lshift__', - '>>': '__rshift__', - '@': '__matmul__' - } - -UNARY_OP_METHOD = {'+': '__pos__', - '-': '__neg__', - '~': '__invert__', - 'not': None, # XXX not '__nonzero__' - } - -# unary operations ############################################################ - -def tl_infer_unary_op(self, operator): - if operator == 'not': - return node_classes.const_factory(not bool(self.elts)) - raise TypeError() # XXX log unsupported operation -nodes.Tuple.infer_unary_op = tl_infer_unary_op -nodes.List.infer_unary_op = tl_infer_unary_op - - -def dict_infer_unary_op(self, operator): - if operator == 'not': - return node_classes.const_factory(not bool(self.items)) - raise TypeError() # XXX log unsupported operation -nodes.Dict.infer_unary_op = dict_infer_unary_op - - -def const_infer_unary_op(self, operator): - if operator == 'not': - return node_classes.const_factory(not self.value) - # XXX log potentially raised TypeError - elif operator == '+': - return node_classes.const_factory(+self.value) - else: # operator == '-': - return node_classes.const_factory(-self.value) -nodes.Const.infer_unary_op = const_infer_unary_op - - -# binary operations ########################################################### - -BIN_OP_IMPL = {'+': lambda a, b: a + b, - '-': lambda a, b: a - b, - '/': lambda a, b: a / b, - '//': lambda a, b: a // b, - '*': lambda a, b: a * b, - '**': lambda a, b: a ** b, - '%': lambda a, b: a % b, - '&': lambda a, b: a & b, - '|': lambda a, b: a | b, - '^': lambda a, b: a ^ b, - '<<': lambda a, b: a << b, - '>>': lambda a, b: a >> b, - } - -if sys.version_info >= (3, 5): - # MatMult is available since Python 3.5+. - BIN_OP_IMPL['@'] = operator.matmul - -for key, impl in list(BIN_OP_IMPL.items()): - BIN_OP_IMPL[key+'='] = impl - -def const_infer_binary_op(self, binop, other, context): - operator = binop.op - for other in other.infer(context): - if isinstance(other, nodes.Const): - try: - impl = BIN_OP_IMPL[operator] - - try: - yield node_classes.const_factory(impl(self.value, other.value)) - except Exception: - # ArithmeticError is not enough: float >> float is a TypeError - # TODO : let pylint know about the problem - pass - except TypeError: - # XXX log TypeError - continue - elif other is util.YES: - yield other - else: - try: - for val in other.infer_binary_op(binop, self, context): - yield val - except AttributeError: - yield util.YES -nodes.Const.infer_binary_op = bases.yes_if_nothing_inferred(const_infer_binary_op) - - - -def _multiply_seq_by_int(self, binop, other, context): - node = self.__class__() - node.parent = binop - elts = [] - for elt in self.elts: - infered = util.safe_infer(elt, context) - if infered is None: - infered = util.YES - elts.append(infered) - node.elts = elts * other.value - return node - - -def _filter_uninferable_nodes(elts, context): - for elt in elts: - if elt is util.YES: - yield elt - else: - for inferred in elt.infer(context): - yield inferred - - -def tl_infer_binary_op(self, binop, other, context): - operator = binop.op - for other in other.infer(context): - if isinstance(other, self.__class__) and operator == '+': - node = self.__class__() - node.parent = binop - elts = list(_filter_uninferable_nodes(self.elts, context)) - elts += list(_filter_uninferable_nodes(other.elts, context)) - node.elts = elts - yield node - elif isinstance(other, nodes.Const) and operator == '*': - if not isinstance(other.value, int): - yield util.YES - continue - yield _multiply_seq_by_int(self, binop, other, context) - elif isinstance(other, bases.Instance) and not isinstance(other, nodes.Const): - yield util.YES - # XXX else log TypeError -nodes.Tuple.infer_binary_op = bases.yes_if_nothing_inferred(tl_infer_binary_op) -nodes.List.infer_binary_op = bases.yes_if_nothing_inferred(tl_infer_binary_op) - - -def dict_infer_binary_op(self, binop, other, context): - for other in other.infer(context): - if isinstance(other, bases.Instance) and isinstance(other._proxied, nodes.ClassDef): - yield util.YES - # XXX else log TypeError -nodes.Dict.infer_binary_op = bases.yes_if_nothing_inferred(dict_infer_binary_op) - -def instance_infer_binary_op(self, binop, other, context): - operator = binop.op - try: - methods = self.getattr(BIN_OP_METHOD[operator]) - except (exceptions.NotFoundError, KeyError): - # Unknown operator - yield util.YES - else: - for method in methods: - if not isinstance(method, nodes.FunctionDef): - continue - for result in method.infer_call_result(self, context): - if result is not util.YES: - yield result - # We are interested only in the first infered method, - # don't go looking in the rest of the methods of the ancestors. - break - -bases.Instance.infer_binary_op = bases.yes_if_nothing_inferred(instance_infer_binary_op) - - -# assignment ################################################################## - -"""the assigned_stmts method is responsible to return the assigned statement -(e.g. not inferred) according to the assignment type. - -The `asspath` argument is used to record the lhs path of the original node. -For instance if we want assigned statements for 'c' in 'a, (b,c)', asspath -will be [1, 1] once arrived to the Assign node. - -The `context` argument is the current inference context which should be given -to any intermediary inference necessary. -""" - -def _resolve_looppart(parts, asspath, context): - """recursive function to resolve multiple assignments on loops""" - asspath = asspath[:] - index = asspath.pop(0) - for part in parts: - if part is util.YES: - continue - # XXX handle __iter__ and log potentially detected errors - if not hasattr(part, 'itered'): - continue - try: - itered = part.itered() - except TypeError: - continue # XXX log error - for stmt in itered: - try: - assigned = stmt.getitem(index, context) - except (AttributeError, IndexError): - continue - except TypeError: # stmt is unsubscriptable Const - continue - if not asspath: - # we achieved to resolved the assignment path, - # don't infer the last part - yield assigned - elif assigned is util.YES: - break - else: - # we are not yet on the last part of the path - # search on each possibly inferred value - try: - for inferred in _resolve_looppart(assigned.infer(context), - asspath, context): - yield inferred - except exceptions.InferenceError: - break - - -@bases.raise_if_nothing_inferred -def for_assigned_stmts(self, node=None, context=None, asspath=None): - if asspath is None: - for lst in self.iter.infer(context): - if isinstance(lst, (nodes.Tuple, nodes.List)): - for item in lst.elts: - yield item - else: - for inferred in _resolve_looppart(self.iter.infer(context), - asspath, context): - yield inferred - -nodes.For.assigned_stmts = for_assigned_stmts -nodes.Comprehension.assigned_stmts = for_assigned_stmts - - -def sequence_assigned_stmts(self, node=None, context=None, asspath=None): - if asspath is None: - asspath = [] - try: - index = self.elts.index(node) - except ValueError: - util.reraise(exceptions.InferenceError( - 'Tried to retrieve a node {node!r} which does not exist', - node=self, assign_path=asspath, context=context)) - - asspath.insert(0, index) - return self.parent.assigned_stmts(node=self, context=context, asspath=asspath) - -nodes.Tuple.assigned_stmts = sequence_assigned_stmts -nodes.List.assigned_stmts = sequence_assigned_stmts - - -def assend_assigned_stmts(self, node=None, context=None, asspath=None): - return self.parent.assigned_stmts(node=self, context=context) -nodes.AssignName.assigned_stmts = assend_assigned_stmts -nodes.AssignAttr.assigned_stmts = assend_assigned_stmts - - -def _arguments_infer_argname(self, name, context): - # arguments information may be missing, in which case we can't do anything - # more - if not (self.args or self.vararg or self.kwarg): - yield util.YES - return - # first argument of instance/class method - if self.args and getattr(self.args[0], 'name', None) == name: - functype = self.parent.type - if functype == 'method': - yield bases.Instance(self.parent.parent.frame()) - return - if functype == 'classmethod': - yield self.parent.parent.frame() - return - - if context and context.callcontext: - call_site = arguments.CallSite(context.callcontext) - for value in call_site.infer_argument(self.parent, name, context): - yield value - return - - # TODO: just provide the type here, no need to have an empty Dict. - if name == self.vararg: - vararg = node_classes.const_factory(()) - vararg.parent = self - yield vararg - return - if name == self.kwarg: - kwarg = node_classes.const_factory({}) - kwarg.parent = self - yield kwarg - return - # if there is a default value, yield it. And then yield YES to reflect - # we can't guess given argument value - try: - context = contextmod.copy_context(context) - for inferred in self.default_value(name).infer(context): - yield inferred - yield util.YES - except exceptions.NoDefault: - yield util.YES - - -def arguments_assigned_stmts(self, node=None, context=None, asspath=None): - if context.callcontext: - # reset call context/name - callcontext = context.callcontext - context = contextmod.copy_context(context) - context.callcontext = None - args = arguments.CallSite(callcontext) - return args.infer_argument(self.parent, node.name, context) - return _arguments_infer_argname(self, node.name, context) - -nodes.Arguments.assigned_stmts = arguments_assigned_stmts - - -@bases.raise_if_nothing_inferred -def assign_assigned_stmts(self, node=None, context=None, asspath=None): - if not asspath: - yield self.value - return - for inferred in _resolve_asspart(self.value.infer(context), asspath, context): - yield inferred - -nodes.Assign.assigned_stmts = assign_assigned_stmts -nodes.AugAssign.assigned_stmts = assign_assigned_stmts - - -def _resolve_asspart(parts, asspath, context): - """recursive function to resolve multiple assignments""" - asspath = asspath[:] - index = asspath.pop(0) - for part in parts: - if hasattr(part, 'getitem'): - try: - assigned = part.getitem(index, context) - # XXX raise a specific exception to avoid potential hiding of - # unexpected exception ? - except (TypeError, IndexError): - return - if not asspath: - # we achieved to resolved the assignment path, don't infer the - # last part - yield assigned - elif assigned is util.YES: - return - else: - # we are not yet on the last part of the path search on each - # possibly inferred value - try: - for inferred in _resolve_asspart(assigned.infer(context), - asspath, context): - yield inferred - except exceptions.InferenceError: - return - - -@bases.raise_if_nothing_inferred -def excepthandler_assigned_stmts(self, node=None, context=None, asspath=None): - for assigned in node_classes.unpack_infer(self.type): - if isinstance(assigned, nodes.ClassDef): - assigned = bases.Instance(assigned) - yield assigned -nodes.ExceptHandler.assigned_stmts = bases.raise_if_nothing_inferred(excepthandler_assigned_stmts) - - -@bases.raise_if_nothing_inferred -def with_assigned_stmts(self, node=None, context=None, asspath=None): - if asspath is None: - for _, vars in self.items: - if vars is None: - continue - for lst in vars.infer(context): - if isinstance(lst, (nodes.Tuple, nodes.List)): - for item in lst.nodes: - yield item -nodes.With.assigned_stmts = with_assigned_stmts - - -@bases.yes_if_nothing_inferred -def starred_assigned_stmts(self, node=None, context=None, asspath=None): - stmt = self.statement() - if not isinstance(stmt, (nodes.Assign, nodes.For)): - raise exceptions.InferenceError() - - if isinstance(stmt, nodes.Assign): - value = stmt.value - lhs = stmt.targets[0] - - if sum(1 for node in lhs.nodes_of_class(nodes.Starred)) > 1: - # Too many starred arguments in the expression. - raise exceptions.InferenceError() - - if context is None: - context = contextmod.InferenceContext() - try: - rhs = next(value.infer(context)) - except exceptions.InferenceError: - yield util.YES - return - if rhs is util.YES or not hasattr(rhs, 'elts'): - # Not interested in inferred values without elts. - yield util.YES - return - - elts = collections.deque(rhs.elts[:]) - if len(lhs.elts) > len(rhs.elts): - # a, *b, c = (1, 2) - raise exceptions.InferenceError() - - # Unpack iteratively the values from the rhs of the assignment, - # until the find the starred node. What will remain will - # be the list of values which the Starred node will represent - # This is done in two steps, from left to right to remove - # anything before the starred node and from right to left - # to remvoe anything after the starred node. - - for index, node in enumerate(lhs.elts): - if not isinstance(node, nodes.Starred): - elts.popleft() - continue - lhs_elts = collections.deque(reversed(lhs.elts[index:])) - for node in lhs_elts: - if not isinstance(node, nodes.Starred): - elts.pop() - continue - # We're done - packed = nodes.List() - packed.elts = elts - packed.parent = self - yield packed - break - -nodes.Starred.assigned_stmts = starred_assigned_stmts diff --git a/pymode/libs/astroid/raw_building.py b/pymode/libs/astroid/raw_building.py deleted file mode 100644 index aaaf52f2..00000000 --- a/pymode/libs/astroid/raw_building.py +++ /dev/null @@ -1,390 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""this module contains a set of functions to create astroid trees from scratch -(build_* functions) or from living object (object_build_* functions) -""" - -import sys -import os -from os.path import abspath -from inspect import (getargspec, isdatadescriptor, isfunction, ismethod, - ismethoddescriptor, isclass, isbuiltin, ismodule) -import six - -from astroid.node_classes import CONST_CLS -from astroid.nodes import (Module, Class, Const, const_factory, From, - Function, EmptyNode, Name, Arguments) -from astroid.bases import BUILTINS, Generator -from astroid.manager import AstroidManager -MANAGER = AstroidManager() - -_CONSTANTS = tuple(CONST_CLS) # the keys of CONST_CLS eg python builtin types -_JYTHON = os.name == 'java' -_BUILTINS = vars(six.moves.builtins) - -def _io_discrepancy(member): - # _io module names itself `io`: http://bugs.python.org/issue18602 - member_self = getattr(member, '__self__', None) - return (member_self and - ismodule(member_self) and - member_self.__name__ == '_io' and - member.__module__ == 'io') - -def _attach_local_node(parent, node, name): - node.name = name # needed by add_local_node - parent.add_local_node(node) - - -def _add_dunder_class(func, member): - """Add a __class__ member to the given func node, if we can determine it.""" - python_cls = member.__class__ - cls_name = getattr(python_cls, '__name__', None) - if not cls_name: - return - bases = [ancestor.__name__ for ancestor in python_cls.__bases__] - ast_klass = build_class(cls_name, bases, python_cls.__doc__) - func._instance_attrs['__class__'] = [ast_klass] - - -_marker = object() - -def attach_dummy_node(node, name, object=_marker): - """create a dummy node and register it in the locals of the given - node with the specified name - """ - enode = EmptyNode() - enode.object = object - _attach_local_node(node, enode, name) - -def _has_underlying_object(self): - return hasattr(self, 'object') and self.object is not _marker - -EmptyNode.has_underlying_object = _has_underlying_object - -def attach_const_node(node, name, value): - """create a Const node and register it in the locals of the given - node with the specified name - """ - if not name in node.special_attributes: - _attach_local_node(node, const_factory(value), name) - -def attach_import_node(node, modname, membername): - """create a From node and register it in the locals of the given - node with the specified name - """ - from_node = From(modname, [(membername, None)]) - _attach_local_node(node, from_node, membername) - - -def build_module(name, doc=None): - """create and initialize a astroid Module node""" - node = Module(name, doc, pure_python=False) - node.package = False - node.parent = None - return node - -def build_class(name, basenames=(), doc=None): - """create and initialize a astroid Class node""" - node = Class(name, doc) - for base in basenames: - basenode = Name() - basenode.name = base - node.bases.append(basenode) - basenode.parent = node - return node - -def build_function(name, args=None, defaults=None, flag=0, doc=None): - """create and initialize a astroid Function node""" - args, defaults = args or [], defaults or [] - # first argument is now a list of decorators - func = Function(name, doc) - func.args = argsnode = Arguments() - argsnode.args = [] - for arg in args: - argsnode.args.append(Name()) - argsnode.args[-1].name = arg - argsnode.args[-1].parent = argsnode - argsnode.defaults = [] - for default in defaults: - argsnode.defaults.append(const_factory(default)) - argsnode.defaults[-1].parent = argsnode - argsnode.kwarg = None - argsnode.vararg = None - argsnode.parent = func - if args: - register_arguments(func) - return func - - -def build_from_import(fromname, names): - """create and initialize an astroid From import statement""" - return From(fromname, [(name, None) for name in names]) - -def register_arguments(func, args=None): - """add given arguments to local - - args is a list that may contains nested lists - (i.e. def func(a, (b, c, d)): ...) - """ - if args is None: - args = func.args.args - if func.args.vararg: - func.set_local(func.args.vararg, func.args) - if func.args.kwarg: - func.set_local(func.args.kwarg, func.args) - for arg in args: - if isinstance(arg, Name): - func.set_local(arg.name, arg) - else: - register_arguments(func, arg.elts) - -def object_build_class(node, member, localname): - """create astroid for a living class object""" - basenames = [base.__name__ for base in member.__bases__] - return _base_class_object_build(node, member, basenames, - localname=localname) - -def object_build_function(node, member, localname): - """create astroid for a living function object""" - args, varargs, varkw, defaults = getargspec(member) - if varargs is not None: - args.append(varargs) - if varkw is not None: - args.append(varkw) - func = build_function(getattr(member, '__name__', None) or localname, args, - defaults, six.get_function_code(member).co_flags, member.__doc__) - node.add_local_node(func, localname) - -def object_build_datadescriptor(node, member, name): - """create astroid for a living data descriptor object""" - return _base_class_object_build(node, member, [], name) - -def object_build_methoddescriptor(node, member, localname): - """create astroid for a living method descriptor object""" - # FIXME get arguments ? - func = build_function(getattr(member, '__name__', None) or localname, - doc=member.__doc__) - # set node's arguments to None to notice that we have no information, not - # and empty argument list - func.args.args = None - node.add_local_node(func, localname) - _add_dunder_class(func, member) - -def _base_class_object_build(node, member, basenames, name=None, localname=None): - """create astroid for a living class object, with a given set of base names - (e.g. ancestors) - """ - klass = build_class(name or getattr(member, '__name__', None) or localname, - basenames, member.__doc__) - klass._newstyle = isinstance(member, type) - node.add_local_node(klass, localname) - try: - # limit the instantiation trick since it's too dangerous - # (such as infinite test execution...) - # this at least resolves common case such as Exception.args, - # OSError.errno - if issubclass(member, Exception): - instdict = member().__dict__ - else: - raise TypeError - except: - pass - else: - for name, obj in instdict.items(): - valnode = EmptyNode() - valnode.object = obj - valnode.parent = klass - valnode.lineno = 1 - klass._instance_attrs[name] = [valnode] - return klass - - - - -class InspectBuilder(object): - """class for building nodes from living object - - this is actually a really minimal representation, including only Module, - Function and Class nodes and some others as guessed. - """ - - # astroid from living objects ############################################### - - def __init__(self): - self._done = {} - self._module = None - - def inspect_build(self, module, modname=None, path=None): - """build astroid from a living module (i.e. using inspect) - this is used when there is no python source code available (either - because it's a built-in module or because the .py is not available) - """ - self._module = module - if modname is None: - modname = module.__name__ - try: - node = build_module(modname, module.__doc__) - except AttributeError: - # in jython, java modules have no __doc__ (see #109562) - node = build_module(modname) - node.source_file = path and abspath(path) or path - node.name = modname - MANAGER.cache_module(node) - node.package = hasattr(module, '__path__') - self._done = {} - self.object_build(node, module) - return node - - def object_build(self, node, obj): - """recursive method which create a partial ast from real objects - (only function, class, and method are handled) - """ - if obj in self._done: - return self._done[obj] - self._done[obj] = node - for name in dir(obj): - try: - member = getattr(obj, name) - except AttributeError: - # damned ExtensionClass.Base, I know you're there ! - attach_dummy_node(node, name) - continue - if ismethod(member): - member = six.get_method_function(member) - if isfunction(member): - # verify this is not an imported function - filename = getattr(six.get_function_code(member), - 'co_filename', None) - if filename is None: - assert isinstance(member, object) - object_build_methoddescriptor(node, member, name) - elif filename != getattr(self._module, '__file__', None): - attach_dummy_node(node, name, member) - else: - object_build_function(node, member, name) - elif isbuiltin(member): - if (not _io_discrepancy(member) and - self.imported_member(node, member, name)): - continue - object_build_methoddescriptor(node, member, name) - elif isclass(member): - if self.imported_member(node, member, name): - continue - if member in self._done: - class_node = self._done[member] - if not class_node in node._locals.get(name, ()): - node.add_local_node(class_node, name) - else: - class_node = object_build_class(node, member, name) - # recursion - self.object_build(class_node, member) - if name == '__class__' and class_node.parent is None: - class_node.parent = self._done[self._module] - elif ismethoddescriptor(member): - assert isinstance(member, object) - object_build_methoddescriptor(node, member, name) - elif isdatadescriptor(member): - assert isinstance(member, object) - object_build_datadescriptor(node, member, name) - elif type(member) in _CONSTANTS: - attach_const_node(node, name, member) - else: - # create an empty node so that the name is actually defined - attach_dummy_node(node, name, member) - - def imported_member(self, node, member, name): - """verify this is not an imported class or handle it""" - # /!\ some classes like ExtensionClass doesn't have a __module__ - # attribute ! Also, this may trigger an exception on badly built module - # (see http://www.logilab.org/ticket/57299 for instance) - try: - modname = getattr(member, '__module__', None) - except: - # XXX use logging - print('unexpected error while building astroid from living object') - import traceback - traceback.print_exc() - modname = None - if modname is None: - if (name in ('__new__', '__subclasshook__') - or (name in _BUILTINS and _JYTHON)): - # Python 2.5.1 (r251:54863, Sep 1 2010, 22:03:14) - # >>> print object.__new__.__module__ - # None - modname = BUILTINS - else: - attach_dummy_node(node, name, member) - return True - - real_name = { - 'gtk': 'gtk_gtk', - '_io': 'io', - }.get(modname, modname) - - if real_name != self._module.__name__: - # check if it sounds valid and then add an import node, else use a - # dummy node - try: - getattr(sys.modules[modname], name) - except (KeyError, AttributeError): - attach_dummy_node(node, name, member) - else: - attach_import_node(node, modname, name) - return True - return False - - -### astroid bootstrapping ###################################################### -Astroid_BUILDER = InspectBuilder() - -_CONST_PROXY = {} -def _astroid_bootstrapping(astroid_builtin=None): - """astroid boot strapping the builtins module""" - # this boot strapping is necessary since we need the Const nodes to - # inspect_build builtins, and then we can proxy Const - if astroid_builtin is None: - from six.moves import builtins - astroid_builtin = Astroid_BUILDER.inspect_build(builtins) - - for cls, node_cls in CONST_CLS.items(): - if cls is type(None): - proxy = build_class('NoneType') - proxy.parent = astroid_builtin - elif cls is type(NotImplemented): - proxy = build_class('NotImplementedType') - proxy.parent = astroid_builtin - else: - proxy = astroid_builtin.getattr(cls.__name__)[0] - if cls in (dict, list, set, tuple): - node_cls._proxied = proxy - else: - _CONST_PROXY[cls] = proxy - -_astroid_bootstrapping() - -# TODO : find a nicer way to handle this situation; -# However __proxied introduced an -# infinite recursion (see https://bugs.launchpad.net/pylint/+bug/456870) -def _set_proxied(const): - return _CONST_PROXY[const.value.__class__] -Const._proxied = property(_set_proxied) - -from types import GeneratorType -Generator._proxied = Class(GeneratorType.__name__, GeneratorType.__doc__) -Astroid_BUILDER.object_build(Generator._proxied, GeneratorType) - diff --git a/pymode/libs/astroid/rebuilder.py b/pymode/libs/astroid/rebuilder.py deleted file mode 100644 index 859b8280..00000000 --- a/pymode/libs/astroid/rebuilder.py +++ /dev/null @@ -1,989 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""this module contains utilities for rebuilding a _ast tree in -order to get a single Astroid representation -""" - -import sys -import _ast -from _ast import ( - # binary operators - Add, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor, - LShift, RShift, - # logical operators - And, Or, - # unary operators - UAdd, USub, Not, Invert, - # comparison operators - Eq, Gt, GtE, In, Is, IsNot, Lt, LtE, NotEq, NotIn, - ) - -from astroid import nodes as new -from astroid import astpeephole - - -_BIN_OP_CLASSES = {Add: '+', - BitAnd: '&', - BitOr: '|', - BitXor: '^', - Div: '/', - FloorDiv: '//', - Mod: '%', - Mult: '*', - Pow: '**', - Sub: '-', - LShift: '<<', - RShift: '>>', - } -if sys.version_info >= (3, 5): - from _ast import MatMult - _BIN_OP_CLASSES[MatMult] = '@' - -_BOOL_OP_CLASSES = {And: 'and', - Or: 'or', - } - -_UNARY_OP_CLASSES = {UAdd: '+', - USub: '-', - Not: 'not', - Invert: '~', - } - -_CMP_OP_CLASSES = {Eq: '==', - Gt: '>', - GtE: '>=', - In: 'in', - Is: 'is', - IsNot: 'is not', - Lt: '<', - LtE: '<=', - NotEq: '!=', - NotIn: 'not in', - } - -CONST_NAME_TRANSFORMS = {'None': None, - 'True': True, - 'False': False, - } - -REDIRECT = {'arguments': 'Arguments', - 'comprehension': 'Comprehension', - "ListCompFor": 'Comprehension', - "GenExprFor": 'Comprehension', - 'excepthandler': 'ExceptHandler', - 'keyword': 'Keyword', - } -PY3K = sys.version_info >= (3, 0) -PY34 = sys.version_info >= (3, 4) - -def _init_set_doc(node, newnode): - newnode.doc = None - try: - if isinstance(node.body[0], _ast.Expr) and isinstance(node.body[0].value, _ast.Str): - newnode.doc = node.body[0].value.s - node.body = node.body[1:] - - except IndexError: - pass # ast built from scratch - -def _lineno_parent(oldnode, newnode, parent): - newnode.parent = parent - newnode.lineno = oldnode.lineno - newnode.col_offset = oldnode.col_offset - -def _set_infos(oldnode, newnode, parent): - newnode.parent = parent - if hasattr(oldnode, 'lineno'): - newnode.lineno = oldnode.lineno - if hasattr(oldnode, 'col_offset'): - newnode.col_offset = oldnode.col_offset - -def _create_yield_node(node, parent, rebuilder, factory): - newnode = factory() - _lineno_parent(node, newnode, parent) - if node.value is not None: - newnode.value = rebuilder.visit(node.value, newnode, None) - return newnode - -def _visit_or_none(node, attr, visitor, parent, assign_ctx, visit='visit', - **kws): - """If the given node has an attribute, visits the attribute, and - otherwise returns None. - - """ - value = getattr(node, attr, None) - if value: - return getattr(visitor, visit)(value, parent, assign_ctx, **kws) - else: - return None - - -class TreeRebuilder(object): - """Rebuilds the _ast tree to become an Astroid tree""" - - def __init__(self, manager): - self._manager = manager - self.asscontext = None - self._global_names = [] - self._import_from_nodes = [] - self._delayed_assattr = [] - self._visit_meths = {} - self._peepholer = astpeephole.ASTPeepholeOptimizer() - - def visit_module(self, node, modname, modpath, package): - """visit a Module node by returning a fresh instance of it""" - newnode = new.Module(modname, None) - newnode.package = package - newnode.parent = None - _init_set_doc(node, newnode) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.source_file = modpath - return newnode - - def visit(self, node, parent, assign_ctx=None): - cls = node.__class__ - if cls in self._visit_meths: - visit_method = self._visit_meths[cls] - else: - cls_name = cls.__name__ - visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower() - visit_method = getattr(self, visit_name) - self._visit_meths[cls] = visit_method - return visit_method(node, parent, assign_ctx) - - def _save_assignment(self, node, name=None): - """save assignement situation since node.parent is not available yet""" - if self._global_names and node.name in self._global_names[-1]: - node.root().set_local(node.name, node) - else: - node.parent.set_local(node.name, node) - - def visit_arguments(self, node, parent, assign_ctx=None): - """visit a Arguments node by returning a fresh instance of it""" - newnode = new.Arguments() - newnode.parent = parent - newnode.args = [self.visit(child, newnode, "Assign") - for child in node.args] - newnode.defaults = [self.visit(child, newnode, assign_ctx) - for child in node.defaults] - newnode.kwonlyargs = [] - newnode.kw_defaults = [] - vararg, kwarg = node.vararg, node.kwarg - # change added in 82732 (7c5c678e4164), vararg and kwarg - # are instances of `_ast.arg`, not strings - if vararg: - if PY34: - if vararg.annotation: - newnode.varargannotation = self.visit(vararg.annotation, - newnode, assign_ctx) - vararg = vararg.arg - elif PY3K and node.varargannotation: - newnode.varargannotation = self.visit(node.varargannotation, - newnode, assign_ctx) - if kwarg: - if PY34: - if kwarg.annotation: - newnode.kwargannotation = self.visit(kwarg.annotation, - newnode, assign_ctx) - kwarg = kwarg.arg - elif PY3K: - if node.kwargannotation: - newnode.kwargannotation = self.visit(node.kwargannotation, - newnode, assign_ctx) - newnode.vararg = vararg - newnode.kwarg = kwarg - # save argument names in locals: - if vararg: - newnode.parent.set_local(vararg, newnode) - if kwarg: - newnode.parent.set_local(kwarg, newnode) - return newnode - - def visit_assignattr(self, node, parent, assign_ctx=None): - """visit a AssAttr node by returning a fresh instance of it""" - newnode = new.AssignAttr() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.expr, newnode, assign_ctx) - self._delayed_assattr.append(newnode) - return newnode - - def visit_assert(self, node, parent, assign_ctx=None): - """visit a Assert node by returning a fresh instance of it""" - newnode = new.Assert() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - if node.msg is not None: - newnode.fail = self.visit(node.msg, newnode, assign_ctx) - return newnode - - def visit_assign(self, node, parent, assign_ctx=None): - """visit a Assign node by returning a fresh instance of it""" - newnode = new.Assign() - _lineno_parent(node, newnode, parent) - newnode.targets = [self.visit(child, newnode, "Assign") - for child in node.targets] - newnode.value = self.visit(node.value, newnode, None) - return newnode - - def visit_assignname(self, node, parent, assign_ctx=None, node_name=None): - '''visit a node and return a AssName node''' - newnode = new.AssignName() - _set_infos(node, newnode, parent) - newnode.name = node_name - self._save_assignment(newnode) - return newnode - - def visit_augassign(self, node, parent, assign_ctx=None): - """visit a AugAssign node by returning a fresh instance of it""" - newnode = new.AugAssign() - _lineno_parent(node, newnode, parent) - newnode.op = _BIN_OP_CLASSES[node.op.__class__] + "=" - newnode.target = self.visit(node.target, newnode, "Assign") - newnode.value = self.visit(node.value, newnode, None) - return newnode - - def visit_repr(self, node, parent, assign_ctx=None): - """visit a Backquote node by returning a fresh instance of it""" - newnode = new.Repr() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, assign_ctx) - return newnode - - def visit_binop(self, node, parent, assign_ctx=None): - """visit a BinOp node by returning a fresh instance of it""" - if isinstance(node.left, _ast.BinOp) and self._manager.optimize_ast: - # Optimize BinOp operations in order to remove - # redundant recursion. For instance, if the - # following code is parsed in order to obtain - # its ast, then the rebuilder will fail with an - # infinite recursion, the same will happen with the - # inference engine as well. There's no need to hold - # so many objects for the BinOp if they can be reduced - # to something else (also, the optimization - # might handle only Const binops, which isn't a big - # problem for the correctness of the program). - # - # ("a" + "b" + # one thousand more + "c") - optimized = self._peepholer.optimize_binop(node) - if optimized: - _lineno_parent(node, optimized, parent) - return optimized - - newnode = new.BinOp() - _lineno_parent(node, newnode, parent) - newnode.left = self.visit(node.left, newnode, assign_ctx) - newnode.right = self.visit(node.right, newnode, assign_ctx) - newnode.op = _BIN_OP_CLASSES[node.op.__class__] - return newnode - - def visit_boolop(self, node, parent, assign_ctx=None): - """visit a BoolOp node by returning a fresh instance of it""" - newnode = new.BoolOp() - _lineno_parent(node, newnode, parent) - newnode.values = [self.visit(child, newnode, assign_ctx) - for child in node.values] - newnode.op = _BOOL_OP_CLASSES[node.op.__class__] - return newnode - - def visit_break(self, node, parent, assign_ctx=None): - """visit a Break node by returning a fresh instance of it""" - newnode = new.Break() - _set_infos(node, newnode, parent) - return newnode - - def visit_call(self, node, parent, assign_ctx=None): - """visit a CallFunc node by returning a fresh instance of it""" - newnode = new.Call() - _lineno_parent(node, newnode, parent) - newnode.func = self.visit(node.func, newnode, assign_ctx) - args = [self.visit(child, newnode, assign_ctx) - for child in node.args] - - starargs = _visit_or_none(node, 'starargs', self, newnode, - assign_ctx) - kwargs = _visit_or_none(node, 'kwargs', self, newnode, - assign_ctx) - keywords = None - if node.keywords: - keywords = [self.visit(child, newnode, assign_ctx) - for child in node.keywords] - - if starargs: - new_starargs = new.Starred() - new_starargs.col_offset = starargs.col_offset - new_starargs.lineno = starargs.lineno - new_starargs.parent = starargs.parent - new_starargs.value = starargs - args.append(new_starargs) - if kwargs: - new_kwargs = new.Keyword() - new_kwargs.arg = None - new_kwargs.col_offset = kwargs.col_offset - new_kwargs.lineno = kwargs.lineno - new_kwargs.parent = kwargs.parent - new_kwargs.value = kwargs - if keywords: - keywords.append(new_kwargs) - else: - keywords = [new_kwargs] - - newnode.args = args - newnode.keywords = keywords - return newnode - - def visit_classdef(self, node, parent, assign_ctx=None): - """visit a Class node to become astroid""" - newnode = new.ClassDef(node.name, None) - _lineno_parent(node, newnode, parent) - _init_set_doc(node, newnode) - newnode.bases = [self.visit(child, newnode, assign_ctx) - for child in node.bases] - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - if node.decorator_list: - newnode.decorators = self.visit_decorators(node, newnode, assign_ctx) - newnode.parent.frame().set_local(newnode.name, newnode) - return newnode - - def visit_const(self, node, parent, assign_ctx=None): - """visit a Const node by returning a fresh instance of it""" - newnode = new.Const(node.value) - _set_infos(node, newnode, parent) - return newnode - - def visit_continue(self, node, parent, assign_ctx=None): - """visit a Continue node by returning a fresh instance of it""" - newnode = new.Continue() - _set_infos(node, newnode, parent) - return newnode - - def visit_compare(self, node, parent, assign_ctx=None): - """visit a Compare node by returning a fresh instance of it""" - newnode = new.Compare() - _lineno_parent(node, newnode, parent) - newnode.left = self.visit(node.left, newnode, assign_ctx) - newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode, assign_ctx)) - for (op, expr) in zip(node.ops, node.comparators)] - return newnode - - def visit_comprehension(self, node, parent, assign_ctx=None): - """visit a Comprehension node by returning a fresh instance of it""" - newnode = new.Comprehension() - newnode.parent = parent - newnode.target = self.visit(node.target, newnode, 'Assign') - newnode.iter = self.visit(node.iter, newnode, None) - newnode.ifs = [self.visit(child, newnode, None) - for child in node.ifs] - return newnode - - def visit_decorators(self, node, parent, assign_ctx=None): - """visit a Decorators node by returning a fresh instance of it""" - # /!\ node is actually a _ast.Function node while - # parent is a astroid.nodes.Function node - newnode = new.Decorators() - _lineno_parent(node, newnode, parent) - decorators = node.decorator_list - newnode.nodes = [self.visit(child, newnode, assign_ctx) - for child in decorators] - return newnode - - def visit_delete(self, node, parent, assign_ctx=None): - """visit a Delete node by returning a fresh instance of it""" - newnode = new.Delete() - _lineno_parent(node, newnode, parent) - newnode.targets = [self.visit(child, newnode, 'Del') - for child in node.targets] - return newnode - - def _visit_dict_items(self, node, parent, newnode, assign_ctx): - for key, value in zip(node.keys, node.values): - rebuilt_value = self.visit(value, newnode, assign_ctx) - if not key: - # Python 3.5 and extended unpacking - rebuilt_key = new.DictUnpack() - rebuilt_key.lineno = rebuilt_value.lineno - rebuilt_key.col_offset = rebuilt_value.col_offset - rebuilt_key.parent = rebuilt_value.parent - else: - rebuilt_key = self.visit(key, newnode, assign_ctx) - yield rebuilt_key, rebuilt_value - - def visit_dict(self, node, parent, assign_ctx=None): - """visit a Dict node by returning a fresh instance of it""" - newnode = new.Dict() - _lineno_parent(node, newnode, parent) - newnode.items = list(self._visit_dict_items(node, parent, newnode, assign_ctx)) - return newnode - - def visit_dictcomp(self, node, parent, assign_ctx=None): - """visit a DictComp node by returning a fresh instance of it""" - newnode = new.DictComp() - _lineno_parent(node, newnode, parent) - newnode.key = self.visit(node.key, newnode, assign_ctx) - newnode.value = self.visit(node.value, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] - return newnode - - def visit_expr(self, node, parent, assign_ctx=None): - """visit a Discard node by returning a fresh instance of it""" - newnode = new.Expr() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, assign_ctx) - return newnode - - def visit_ellipsis(self, node, parent, assign_ctx=None): - """visit an Ellipsis node by returning a fresh instance of it""" - newnode = new.Ellipsis() - _set_infos(node, newnode, parent) - return newnode - - def visit_emptynode(self, node, parent, assign_ctx=None): - """visit an EmptyNode node by returning a fresh instance of it""" - newnode = new.EmptyNode() - _set_infos(node, newnode, parent) - return newnode - - def visit_excepthandler(self, node, parent, assign_ctx=None): - """visit an ExceptHandler node by returning a fresh instance of it""" - newnode = new.ExceptHandler() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.type = self.visit(node.type, newnode, assign_ctx) - if node.name is not None: - # /!\ node.name can be a tuple - newnode.name = self.visit(node.name, newnode, 'Assign') - newnode.body = [self.visit(child, newnode, None) - for child in node.body] - return newnode - - def visit_exec(self, node, parent, assign_ctx=None): - """visit an Exec node by returning a fresh instance of it""" - newnode = new.Exec() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.body, newnode) - if node.globals is not None: - newnode.globals = self.visit(node.globals, newnode, - assign_ctx) - if node.locals is not None: - newnode.locals = self.visit(node.locals, newnode, - assign_ctx) - return newnode - - def visit_extslice(self, node, parent, assign_ctx=None): - """visit an ExtSlice node by returning a fresh instance of it""" - newnode = new.ExtSlice() - newnode.parent = parent - newnode.dims = [self.visit(dim, newnode, assign_ctx) - for dim in node.dims] - return newnode - - def _visit_for(self, cls, node, parent, assign_ctx=None): - """visit a For node by returning a fresh instance of it""" - newnode = cls() - _lineno_parent(node, newnode, parent) - newnode.target = self.visit(node.target, newnode, "Assign") - newnode.iter = self.visit(node.iter, newnode, None) - newnode.body = [self.visit(child, newnode, None) - for child in node.body] - newnode.orelse = [self.visit(child, newnode, None) - for child in node.orelse] - return newnode - - def visit_for(self, node, parent, assign_ctx=None): - return self._visit_for(new.For, node, parent, - assign_ctx=assign_ctx) - def visit_importfrom(self, node, parent, assign_ctx=None): - """visit a From node by returning a fresh instance of it""" - names = [(alias.name, alias.asname) for alias in node.names] - newnode = new.ImportFrom(node.module or '', names, node.level or None) - _set_infos(node, newnode, parent) - # store From names to add them to locals after building - self._import_from_nodes.append(newnode) - return newnode - - def _visit_functiondef(self, cls, node, parent, assign_ctx=None): - """visit an FunctionDef node to become astroid""" - self._global_names.append({}) - newnode = cls(node.name, None) - _lineno_parent(node, newnode, parent) - _init_set_doc(node, newnode) - newnode.args = self.visit(node.args, newnode, assign_ctx) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - decorators = node.decorator_list - if decorators: - newnode.decorators = self.visit_decorators( - node, newnode, assign_ctx) - if PY3K and node.returns: - newnode.returns = self.visit(node.returns, newnode, - assign_ctx) - self._global_names.pop() - frame = newnode.parent.frame() - frame.set_local(newnode.name, newnode) - return newnode - - def visit_functiondef(self, node, parent, assign_ctx=None): - return self._visit_functiondef(new.FunctionDef, node, parent, - assign_ctx=assign_ctx) - - def visit_generatorexp(self, node, parent, assign_ctx=None): - """visit a GenExpr node by returning a fresh instance of it""" - newnode = new.GeneratorExp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] - return newnode - - def visit_attribute(self, node, parent, assign_ctx=None): - """visit a Getattr node by returning a fresh instance of it""" - # pylint: disable=redefined-variable-type - if assign_ctx == "Del": - # FIXME : maybe we should reintroduce and visit_delattr ? - # for instance, deactivating asscontext - newnode = new.DelAttr() - elif assign_ctx == "Assign": - # FIXME : maybe we should call visit_assattr ? - # Prohibit a local save if we are in an ExceptHandler. - newnode = new.AssignAttr() - if not isinstance(parent, new.ExceptHandler): - self._delayed_assattr.append(newnode) - else: - newnode = new.Attribute() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.value, newnode, None) - newnode.attrname = node.attr - return newnode - - def visit_global(self, node, parent, assign_ctx=None): - """visit an Global node to become astroid""" - newnode = new.Global(node.names) - _set_infos(node, newnode, parent) - if self._global_names: # global at the module level, no effect - for name in node.names: - self._global_names[-1].setdefault(name, []).append(newnode) - return newnode - - def visit_if(self, node, parent, assign_ctx=None): - """visit a If node by returning a fresh instance of it""" - newnode = new.If() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] - return newnode - - def visit_ifexp(self, node, parent, assign_ctx=None): - """visit a IfExp node by returning a fresh instance of it""" - newnode = new.IfExp() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - newnode.body = self.visit(node.body, newnode, assign_ctx) - newnode.orelse = self.visit(node.orelse, newnode, assign_ctx) - return newnode - - def visit_import(self, node, parent, assign_ctx=None): - """visit a Import node by returning a fresh instance of it""" - newnode = new.Import() - _set_infos(node, newnode, parent) - newnode.names = [(alias.name, alias.asname) for alias in node.names] - # save import names in parent's locals: - for (name, asname) in newnode.names: - name = asname or name - newnode.parent.set_local(name.split('.')[0], newnode) - return newnode - - def visit_index(self, node, parent, assign_ctx=None): - """visit a Index node by returning a fresh instance of it""" - newnode = new.Index() - newnode.parent = parent - newnode.value = self.visit(node.value, newnode, assign_ctx) - return newnode - - def visit_keyword(self, node, parent, assign_ctx=None): - """visit a Keyword node by returning a fresh instance of it""" - newnode = new.Keyword() - newnode.parent = parent - newnode.arg = node.arg - newnode.value = self.visit(node.value, newnode, assign_ctx) - return newnode - - def visit_lambda(self, node, parent, assign_ctx=None): - """visit a Lambda node by returning a fresh instance of it""" - newnode = new.Lambda() - _lineno_parent(node, newnode, parent) - newnode.args = self.visit(node.args, newnode, assign_ctx) - newnode.body = self.visit(node.body, newnode, assign_ctx) - return newnode - - def visit_list(self, node, parent, assign_ctx=None): - """visit a List node by returning a fresh instance of it""" - newnode = new.List() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode, assign_ctx) - for child in node.elts] - return newnode - - def visit_listcomp(self, node, parent, assign_ctx=None): - """visit a ListComp node by returning a fresh instance of it""" - newnode = new.ListComp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] - return newnode - - def visit_name(self, node, parent, assign_ctx=None): - """visit a Name node by returning a fresh instance of it""" - # True and False can be assigned to something in py2x, so we have to - # check first the asscontext - # pylint: disable=redefined-variable-type - if assign_ctx == "Del": - newnode = new.DelName() - elif assign_ctx is not None: # Ass - newnode = new.AssName() - elif node.id in CONST_NAME_TRANSFORMS: - newnode = new.Const(CONST_NAME_TRANSFORMS[node.id]) - _set_infos(node, newnode, parent) - return newnode - else: - newnode = new.Name() - _lineno_parent(node, newnode, parent) - newnode.name = node.id - # XXX REMOVE me : - if assign_ctx in ('Del', 'Assign'): # 'Aug' ?? - self._save_assignment(newnode) - return newnode - - def visit_bytes(self, node, parent, assign_ctx=None): - """visit a Bytes node by returning a fresh instance of Const""" - newnode = new.Const(node.s) - _set_infos(node, newnode, parent) - return newnode - - def visit_num(self, node, parent, assign_ctx=None): - """visit a Num node by returning a fresh instance of Const""" - newnode = new.Const(node.n) - _set_infos(node, newnode, parent) - return newnode - - def visit_pass(self, node, parent, assign_ctx=None): - """visit a Pass node by returning a fresh instance of it""" - newnode = new.Pass() - _set_infos(node, newnode, parent) - return newnode - - def visit_str(self, node, parent, assign_ctx=None): - """visit a Str node by returning a fresh instance of Const""" - newnode = new.Const(node.s) - _set_infos(node, newnode, parent) - return newnode - - def visit_print(self, node, parent, assign_ctx=None): - """visit a Print node by returning a fresh instance of it""" - newnode = new.Print() - _lineno_parent(node, newnode, parent) - newnode.nl = node.nl - if node.dest is not None: - newnode.dest = self.visit(node.dest, newnode, assign_ctx) - newnode.values = [self.visit(child, newnode, assign_ctx) - for child in node.values] - return newnode - - def visit_raise(self, node, parent, assign_ctx=None): - """visit a Raise node by returning a fresh instance of it""" - newnode = new.Raise() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.exc = self.visit(node.type, newnode, assign_ctx) - if node.inst is not None: - newnode.inst = self.visit(node.inst, newnode, assign_ctx) - if node.tback is not None: - newnode.tback = self.visit(node.tback, newnode, assign_ctx) - return newnode - - def visit_return(self, node, parent, assign_ctx=None): - """visit a Return node by returning a fresh instance of it""" - newnode = new.Return() - _lineno_parent(node, newnode, parent) - if node.value is not None: - newnode.value = self.visit(node.value, newnode, assign_ctx) - return newnode - - def visit_set(self, node, parent, assign_ctx=None): - """visit a Set node by returning a fresh instance of it""" - newnode = new.Set() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode, assign_ctx) - for child in node.elts] - return newnode - - def visit_setcomp(self, node, parent, assign_ctx=None): - """visit a SetComp node by returning a fresh instance of it""" - newnode = new.SetComp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] - return newnode - - def visit_slice(self, node, parent, assign_ctx=None): - """visit a Slice node by returning a fresh instance of it""" - newnode = new.Slice() - newnode.parent = parent - if node.lower is not None: - newnode.lower = self.visit(node.lower, newnode, assign_ctx) - if node.upper is not None: - newnode.upper = self.visit(node.upper, newnode, assign_ctx) - if node.step is not None: - newnode.step = self.visit(node.step, newnode, assign_ctx) - return newnode - - def visit_subscript(self, node, parent, assign_ctx=None): - """visit a Subscript node by returning a fresh instance of it""" - newnode = new.Subscript() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, None) - newnode.slice = self.visit(node.slice, newnode, None) - return newnode - - def visit_tryexcept(self, node, parent, assign_ctx=None): - """visit a TryExcept node by returning a fresh instance of it""" - newnode = new.TryExcept() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.handlers = [self.visit(child, newnode, assign_ctx) - for child in node.handlers] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] - return newnode - - def visit_tryfinally(self, node, parent, assign_ctx=None): - """visit a TryFinally node by returning a fresh instance of it""" - newnode = new.TryFinally() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.finalbody = [self.visit(n, newnode, assign_ctx) - for n in node.finalbody] - return newnode - - def visit_tuple(self, node, parent, assign_ctx=None): - """visit a Tuple node by returning a fresh instance of it""" - newnode = new.Tuple() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode, assign_ctx) - for child in node.elts] - return newnode - - def visit_unaryop(self, node, parent, assign_ctx=None): - """visit a UnaryOp node by returning a fresh instance of it""" - newnode = new.UnaryOp() - _lineno_parent(node, newnode, parent) - newnode.operand = self.visit(node.operand, newnode, assign_ctx) - newnode.op = _UNARY_OP_CLASSES[node.op.__class__] - return newnode - - def visit_while(self, node, parent, assign_ctx=None): - """visit a While node by returning a fresh instance of it""" - newnode = new.While() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] - return newnode - - def visit_with(self, node, parent, assign_ctx=None): - newnode = new.With() - _lineno_parent(node, newnode, parent) - expr = self.visit(node.context_expr, newnode, assign_ctx) - if node.optional_vars is not None: - vars = self.visit(node.optional_vars, newnode, 'Assign') - else: - vars = None - self.asscontext = None - newnode.items = [(expr, vars)] - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - return newnode - - def visit_yield(self, node, parent, assign_ctx=None): - """visit a Yield node by returning a fresh instance of it""" - return _create_yield_node(node, parent, self, new.Yield) - -class TreeRebuilder3k(TreeRebuilder): - """extend and overwrite TreeRebuilder for python3k""" - - def visit_arg(self, node, parent, assign_ctx=None): - """visit a arg node by returning a fresh AssName instance""" - # TODO(cpopa): introduce an Arg node instead of using AssignName. - return self.visit_assignname(node, parent, assign_ctx, node.arg) - - def visit_nameconstant(self, node, parent, assign_ctx=None): - # in Python 3.4 we have NameConstant for True / False / None - newnode = new.Const(node.value) - _set_infos(node, newnode, parent) - return newnode - - def visit_arguments(self, node, parent, assign_ctx=None): - newnode = super(TreeRebuilder3k, self).visit_arguments(node, parent, assign_ctx) - newnode.kwonlyargs = [self.visit(child, newnode, 'Assign') - for child in node.kwonlyargs] - newnode.kw_defaults = [self.visit(child, newnode, None) - if child else None for child in node.kw_defaults] - newnode.annotations = [ - self.visit(arg.annotation, newnode, None) if arg.annotation else None - for arg in node.args] - return newnode - - def visit_excepthandler(self, node, parent, assign_ctx=None): - """visit an ExceptHandler node by returning a fresh instance of it""" - newnode = new.ExceptHandler() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.type = self.visit(node.type, newnode, assign_ctx) - if node.name is not None: - newnode.name = self.visit_assignname(node, newnode, 'Assign', node.name) - newnode.body = [self.visit(child, newnode, None) - for child in node.body] - return newnode - - def visit_nonlocal(self, node, parent, assign_ctx=None): - """visit a Nonlocal node and return a new instance of it""" - newnode = new.Nonlocal(node.names) - _set_infos(node, newnode, parent) - return newnode - - def visit_raise(self, node, parent, assign_ctx=None): - """visit a Raise node by returning a fresh instance of it""" - newnode = new.Raise() - _lineno_parent(node, newnode, parent) - # no traceback; anyway it is not used in Pylint - if node.exc is not None: - newnode.exc = self.visit(node.exc, newnode, assign_ctx) - if node.cause is not None: - newnode.cause = self.visit(node.cause, newnode, assign_ctx) - return newnode - - def visit_starred(self, node, parent, assign_ctx=None): - """visit a Starred node and return a new instance of it""" - newnode = new.Starred() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, assign_ctx) - return newnode - - def visit_try(self, node, parent, assign_ctx=None): - # python 3.3 introduce a new Try node replacing TryFinally/TryExcept nodes - # pylint: disable=redefined-variable-type - if node.finalbody: - newnode = new.TryFinally() - _lineno_parent(node, newnode, parent) - newnode.finalbody = [self.visit(n, newnode, assign_ctx) - for n in node.finalbody] - if node.handlers: - excnode = new.TryExcept() - _lineno_parent(node, excnode, newnode) - excnode.body = [self.visit(child, excnode, assign_ctx) - for child in node.body] - excnode.handlers = [self.visit(child, excnode, assign_ctx) - for child in node.handlers] - excnode.orelse = [self.visit(child, excnode, assign_ctx) - for child in node.orelse] - newnode.body = [excnode] - else: - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - elif node.handlers: - newnode = new.TryExcept() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.handlers = [self.visit(child, newnode, assign_ctx) - for child in node.handlers] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] - return newnode - - def _visit_with(self, cls, node, parent, assign_ctx=None): - if 'items' not in node._fields: - # python < 3.3 - return super(TreeRebuilder3k, self).visit_with(node, parent, - assign_ctx) - - newnode = cls() - _lineno_parent(node, newnode, parent) - def visit_child(child): - expr = self.visit(child.context_expr, newnode) - if child.optional_vars: - var = self.visit(child.optional_vars, newnode, - 'Assign') - else: - var = None - return expr, var - newnode.items = [visit_child(child) - for child in node.items] - newnode.body = [self.visit(child, newnode, None) - for child in node.body] - return newnode - - def visit_with(self, node, parent, assign_ctx=None): - return self._visit_with(new.With, node, parent, assign_ctx=assign_ctx) - - def visit_yieldfrom(self, node, parent, assign_ctx=None): - return _create_yield_node(node, parent, self, new.YieldFrom) - - def visit_classdef(self, node, parent, assign_ctx=None): - newnode = super(TreeRebuilder3k, self).visit_classdef(node, parent, assign_ctx) - newnode._newstyle = True - for keyword in node.keywords: - if keyword.arg == 'metaclass': - newnode._metaclass = self.visit(keyword, newnode, assign_ctx).value - break - return newnode - - # Async structs added in Python 3.5 - def visit_asyncfunctiondef(self, node, parent, assign_ctx=None): - return self._visit_functiondef(new.AsyncFunctionDef, node, parent, - assign_ctx=assign_ctx) - - - def visit_asyncfor(self, node, parent, assign_ctx=None): - return self._visit_for(new.AsyncFor, node, parent, - assign_ctx=assign_ctx) - - def visit_await(self, node, parent, assign_ctx=None): - newnode = new.Await() - newnode.lineno = node.lineno - newnode.col_offset = node.col_offset - newnode.parent = parent - newnode.value = self.visit(node.value, newnode, None) - return newnode - - def visit_asyncwith(self, node, parent, assign_ctx=None): - return self._visit_with(new.AsyncWith, node, parent, - assign_ctx=assign_ctx) - - -if sys.version_info >= (3, 0): - TreeRebuilder = TreeRebuilder3k diff --git a/pymode/libs/astroid/scoped_nodes.py b/pymode/libs/astroid/scoped_nodes.py deleted file mode 100644 index d78d1510..00000000 --- a/pymode/libs/astroid/scoped_nodes.py +++ /dev/null @@ -1,1716 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . - -""" -This module contains the classes for "scoped" node, i.e. which are opening a -new local scope in the language definition : Module, ClassDef, FunctionDef (and -Lambda, GeneratorExp, DictComp and SetComp to some extent). -""" - -import io -import itertools -import warnings - -import six -import wrapt - -from astroid import bases -from astroid import context as contextmod -from astroid import exceptions -from astroid import manager -from astroid import mixins -from astroid import node_classes -from astroid import decorators as decorators_mod -from astroid import util - - -BUILTINS = six.moves.builtins.__name__ -ITER_METHODS = ('__iter__', '__getitem__') - - -def _c3_merge(sequences): - """Merges MROs in *sequences* to a single MRO using the C3 algorithm. - - Adapted from http://www.python.org/download/releases/2.3/mro/. - - """ - result = [] - while True: - sequences = [s for s in sequences if s] # purge empty sequences - if not sequences: - return result - for s1 in sequences: # find merge candidates among seq heads - candidate = s1[0] - for s2 in sequences: - if candidate in s2[1:]: - candidate = None - break # reject the current head, it appears later - else: - break - if not candidate: - # Show all the remaining bases, which were considered as - # candidates for the next mro sequence. - bases = ["({})".format(", ".join(base.name - for base in subsequence)) - for subsequence in sequences] - raise exceptions.InconsistentMroError( - "Cannot create a consistent method resolution " - "order for bases %s" % ", ".join(bases)) - - result.append(candidate) - # remove the chosen candidate - for seq in sequences: - if seq[0] == candidate: - del seq[0] - - -def _verify_duplicates_mro(sequences): - for sequence in sequences: - names = [node.qname() for node in sequence] - if len(names) != len(set(names)): - raise exceptions.DuplicateBasesError('Duplicates found in the mro.') - - -def remove_nodes(cls): - @wrapt.decorator - def decorator(func, instance, args, kwargs): - nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)] - if not nodes: - raise exceptions.NotFoundError() - return nodes - return decorator - - -def function_to_method(n, klass): - if isinstance(n, FunctionDef): - if n.type == 'classmethod': - return bases.BoundMethod(n, klass) - if n.type != 'staticmethod': - return bases.UnboundMethod(n) - return n - - -def std_special_attributes(self, name, add_locals=True): - if add_locals: - locals = self._locals - else: - locals = {} - if name == '__name__': - return [node_classes.const_factory(self.name)] + locals.get(name, []) - if name == '__doc__': - return [node_classes.const_factory(self.doc)] + locals.get(name, []) - if name == '__dict__': - return [node_classes.Dict()] + locals.get(name, []) - raise exceptions.NotFoundError(name) - - -MANAGER = manager.AstroidManager() -def builtin_lookup(name): - """lookup a name into the builtin module - return the list of matching statements and the astroid for the builtin - module - """ - builtin_astroid = MANAGER.ast_from_module(six.moves.builtins) - if name == '__dict__': - return builtin_astroid, () - try: - stmts = builtin_astroid._locals[name] - except KeyError: - stmts = () - return builtin_astroid, stmts - - -# TODO move this Mixin to mixins.py; problem: 'FunctionDef' in _scope_lookup -class LocalsDictNodeNG(node_classes.LookupMixIn, bases.NodeNG): - """ this class provides locals handling common to Module, FunctionDef - and ClassDef nodes, including a dict like interface for direct access - to locals information - """ - - # attributes below are set by the builder module or by raw factories - - # dictionary of locals with name as key and node defining the local as - # value - @property - def locals(self): - util.attribute_to_function_warning('locals', 2.0, 'get_locals') - return self._locals - @locals.setter - def locals(self, _locals): - util.attribute_to_function_warning('locals', 2.0, 'get_locals') - self._locals = _locals - @locals.deleter - def locals(self): - util.attribute_to_function_warning('locals', 2.0, 'get_locals') - del self._locals - - def qname(self): - """return the 'qualified' name of the node, eg module.name, - module.class.name ... - """ - if self.parent is None: - return self.name - return '%s.%s' % (self.parent.frame().qname(), self.name) - - def frame(self): - """return the first parent frame node (i.e. Module, FunctionDef or ClassDef) - """ - return self - - def scope(self): - """return the first node defining a new scope (i.e. Module, - FunctionDef, ClassDef, Lambda but also GeneratorExp, DictComp and SetComp) - """ - return self - - def _scope_lookup(self, node, name, offset=0): - """XXX method for interfacing the scope lookup""" - try: - stmts = node._filter_stmts(self._locals[name], self, offset) - except KeyError: - stmts = () - if stmts: - return self, stmts - if self.parent: # i.e. not Module - # nested scope: if parent scope is a function, that's fine - # else jump to the module - pscope = self.parent.scope() - if not pscope.is_function: - pscope = pscope.root() - return pscope.scope_lookup(node, name) - return builtin_lookup(name) # Module - - def set_local(self, name, stmt): - """define in locals ( is the node defining the name) - if the node is a Module node (i.e. has globals), add the name to - globals - - if the name is already defined, ignore it - """ - #assert not stmt in self._locals.get(name, ()), (self, stmt) - self._locals.setdefault(name, []).append(stmt) - - __setitem__ = set_local - - def _append_node(self, child): - """append a child, linking it in the tree""" - self.body.append(child) - child.parent = self - - def add_local_node(self, child_node, name=None): - """append a child which should alter locals to the given node""" - if name != '__class__': - # add __class__ node as a child will cause infinite recursion later! - self._append_node(child_node) - self.set_local(name or child_node.name, child_node) - - def __getitem__(self, item): - """method from the `dict` interface returning the first node - associated with the given name in the locals dictionary - - :type item: str - :param item: the name of the locally defined object - :raises KeyError: if the name is not defined - """ - return self._locals[item][0] - - def __iter__(self): - """method from the `dict` interface returning an iterator on - `self.keys()` - """ - return iter(self.keys()) - - def keys(self): - """method from the `dict` interface returning a tuple containing - locally defined names - """ - return list(self._locals.keys()) - - def values(self): - """method from the `dict` interface returning a tuple containing - locally defined nodes which are instance of `FunctionDef` or `ClassDef` - """ - return [self[key] for key in self.keys()] - - def items(self): - """method from the `dict` interface returning a list of tuple - containing each locally defined name with its associated node, - which is an instance of `FunctionDef` or `ClassDef` - """ - return list(zip(self.keys(), self.values())) - - def __contains__(self, name): - return name in self._locals - - -class Module(LocalsDictNodeNG): - _astroid_fields = ('body',) - - fromlineno = 0 - lineno = 0 - - # attributes below are set by the builder module or by raw factories - - # the file from which as been extracted the astroid representation. It may - # be None if the representation has been built from a built-in module - source_file = None - # Alternatively, if built from a string/bytes, this can be set - source_code = None - # encoding of python source file, so we can get unicode out of it (python2 - # only) - file_encoding = None - # the module name - name = None - # boolean for astroid built from source (i.e. ast) - pure_python = None - # boolean for package module - package = None - # dictionary of globals with name as key and node defining the global - # as value - _globals = None - - # Future imports - _future_imports = None - - # names of python special attributes (handled by getattr impl.) - special_attributes = set(('__name__', '__doc__', '__file__', '__path__', - '__dict__')) - # names of module attributes available through the global scope - scope_attrs = set(('__name__', '__doc__', '__file__', '__path__')) - - def __init__(self, name, doc, pure_python=True): - self.name = name - self.doc = doc - self.pure_python = pure_python - self._locals = self._globals = {} - self.body = [] - self._future_imports = set() - - # Future deprecation warnings - @property - def file(self): - util.rename_warning('file', 2.0, 'source_file') - return self.source_file - @file.setter - def file(self, source_file): - util.rename_warning('file', 2.0, 'source_file') - self.source_file = source_file - @file.deleter - def file(self): - util.rename_warning('file', 2.0, 'source_file') - del self.source_file - - @property - def path(self): - util.rename_warning('path', 2.0, 'source_file') - return self.source_file - @path.setter - def path(self, source_file): - util.rename_warning('path', 2.0, 'source_file') - self.source_file = source_file - @path.deleter - def path(self): - util.rename_warning('path', 2.0, 'source_file') - del self.source_file - - @property - def file_bytes(self): - util.rename_warning('file_bytes', 2.0, 'source_code') - return self.source_code - @file_bytes.setter - def file_bytes(self, source_code): - util.rename_warning('file_bytes', 2.0, 'source_code') - self.source_code = source_code - @file_bytes.deleter - def file_bytes(self): - util.rename_warning('file_bytes', 2.0, 'source_code') - del self.source_code - - @property - def globals(self): - util.attribute_to_function_warning('globals', 2.0, 'get_locals') - return self._locals - @globals.setter - def globals(self, _globals): - util.attribute_to_function_warning('globals', 2.0, 'get_locals') - self._locals = _globals - @globals.deleter - def globals(self): - util.attribute_to_function_warning('globals', 2.0, 'get_locals') - del self._locals - - @property - def future_imports(self): - util.attribute_to_function_warning('future_imports', 2.0, 'future_imports') - return self._future_imports - @future_imports.setter - def future_imports(self, _future_imports): - util.attribute_to_function_warning('future_imports', 2.0, 'future_imports') - self._future_imports = _future_imports - @future_imports.deleter - def future_imports(self): - util.attribute_to_function_warning('future_imports', 2.0, 'future_imports') - del self._future_imports - - def _get_stream(self): - if self.source_code is not None: - return io.BytesIO(self.source_code) - if self.source_file is not None: - stream = open(self.source_file, 'rb') - return stream - return None - - @property - def file_stream(self): - warnings.warn("file_stream property is deprecated and " - "it is slated for removal in astroid 1.6." - "Use the new method 'stream' instead.", - PendingDeprecationWarning, - stacklevel=2) - return self._get_stream() - - def stream(self): - """Get a stream to the underlying file or bytes.""" - return self._get_stream() - - def close(self): - """Close the underlying file streams.""" - warnings.warn("close method is deprecated and it is " - "slated for removal in astroid 1.6, along " - "with 'file_stream' property. " - "Its behaviour is replaced by managing each " - "file stream returned by the 'stream' method.", - PendingDeprecationWarning, - stacklevel=2) - - def block_range(self, lineno): - """return block line numbers. - - start from the beginning whatever the given lineno - """ - return self.fromlineno, self.tolineno - - def scope_lookup(self, node, name, offset=0): - if name in self.scope_attrs and name not in self._locals: - try: - return self, self.getattr(name) - except exceptions.NotFoundError: - return self, () - return self._scope_lookup(node, name, offset) - - def pytype(self): - return '%s.module' % BUILTINS - - def display_type(self): - return 'Module' - - @remove_nodes(node_classes.DelName) - def getattr(self, name, context=None, ignore_locals=False): - if name in self.special_attributes: - if name == '__file__': - return [node_classes.const_factory(self.source_file)] + self._locals.get(name, []) - if name == '__path__' and self.package: - return [node_classes.List()] + self._locals.get(name, []) - return std_special_attributes(self, name) - if not ignore_locals and name in self._locals: - return self._locals[name] - if self.package: - try: - return [self.import_module(name, relative_only=True)] - except exceptions.AstroidBuildingException: - raise exceptions.NotFoundError(name) - except SyntaxError: - raise exceptions.NotFoundError(name) - raise exceptions.NotFoundError(name) - - def igetattr(self, name, context=None): - """inferred getattr""" - # set lookup name since this is necessary to infer on import nodes for - # instance - context = contextmod.copy_context(context) - context.lookupname = name - try: - return bases._infer_stmts(self.getattr(name, context), - context, frame=self) - except exceptions.NotFoundError: - raise exceptions.InferenceError(name) - - def fully_defined(self): - """return True if this module has been built from a .py file - and so contains a complete representation including the code - """ - return self.source_file is not None and self.source_file.endswith('.py') - - def statement(self): - """return the first parent node marked as statement node - consider a module as a statement... - """ - return self - - def previous_sibling(self): - """module has no sibling""" - return - - def next_sibling(self): - """module has no sibling""" - return - - if six.PY2: - @decorators_mod.cachedproperty - def _absolute_import_activated(self): - for stmt in self._locals.get('absolute_import', ()): - if isinstance(stmt, node_classes.ImportFrom) and stmt.modname == '__future__': - return True - return False - else: - _absolute_import_activated = True - - def absolute_import_activated(self): - return self._absolute_import_activated - - def import_module(self, modname, relative_only=False, level=None): - """import the given module considering self as context""" - if relative_only and level is None: - level = 0 - absmodname = self.relative_to_absolute_name(modname, level) - try: - return MANAGER.ast_from_module_name(absmodname) - except exceptions.AstroidBuildingException: - # we only want to import a sub module or package of this module, - # skip here - if relative_only: - raise - return MANAGER.ast_from_module_name(modname) - - def relative_to_absolute_name(self, modname, level): - """return the absolute module name for a relative import. - - The relative import can be implicit or explicit. - """ - # XXX this returns non sens when called on an absolute import - # like 'pylint.checkers.astroid.utils' - # XXX doesn't return absolute name if self.name isn't absolute name - if self.absolute_import_activated() and level is None: - return modname - if level: - if self.package: - level = level - 1 - package_name = self.name.rsplit('.', level)[0] - elif self.package: - package_name = self.name - else: - package_name = self.name.rsplit('.', 1)[0] - if package_name: - if not modname: - return package_name - return '%s.%s' % (package_name, modname) - return modname - - def wildcard_import_names(self): - """return the list of imported names when this module is 'wildcard - imported' - - It doesn't include the '__builtins__' name which is added by the - current CPython implementation of wildcard imports. - """ - # We separate the different steps of lookup in try/excepts - # to avoid catching too many Exceptions - default = [name for name in self.keys() if not name.startswith('_')] - try: - all = self['__all__'] - except KeyError: - return default - - try: - explicit = next(all.assigned_stmts()) - except exceptions.InferenceError: - return default - except AttributeError: - # not an assignment node - # XXX infer? - return default - - # Try our best to detect the exported name. - inferred = [] - try: - explicit = next(explicit.infer()) - except exceptions.InferenceError: - return default - if not isinstance(explicit, (node_classes.Tuple, node_classes.List)): - return default - - str_const = lambda node: (isinstance(node, node_classes.Const) and - isinstance(node.value, six.string_types)) - for node in explicit.elts: - if str_const(node): - inferred.append(node.value) - else: - try: - inferred_node = next(node.infer()) - except exceptions.InferenceError: - continue - if str_const(inferred_node): - inferred.append(inferred_node.value) - return inferred - - def _public_names(self): - """Get the list of the names which are publicly available in this module.""" - return [name for name in self.keys() if not name.startswith('_')] - - def bool_value(self): - return True - - -class ComprehensionScope(LocalsDictNodeNG): - def frame(self): - return self.parent.frame() - - scope_lookup = LocalsDictNodeNG._scope_lookup - - -class GeneratorExp(ComprehensionScope): - _astroid_fields = ('elt', 'generators') - - def __init__(self): - self._locals = {} - self.elt = None - self.generators = [] - - -class DictComp(ComprehensionScope): - _astroid_fields = ('key', 'value', 'generators') - - def __init__(self): - self._locals = {} - self.key = None - self.value = None - self.generators = [] - - -class SetComp(ComprehensionScope): - _astroid_fields = ('elt', 'generators') - - def __init__(self): - self._locals = {} - self.elt = None - self.generators = [] - - -class _ListComp(bases.NodeNG): - """class representing a ListComp node""" - _astroid_fields = ('elt', 'generators') - elt = None - generators = None - - -if six.PY3: - class ListComp(_ListComp, ComprehensionScope): - """class representing a ListComp node""" - def __init__(self): - self._locals = {} -else: - class ListComp(_ListComp): - """class representing a ListComp node""" - - -def _infer_decorator_callchain(node): - """Detect decorator call chaining and see if the end result is a - static or a classmethod. - """ - if not isinstance(node, FunctionDef): - return - if not node.parent: - return - try: - # TODO: We don't handle multiple inference results right now, - # because there's no flow to reason when the return - # is what we are looking for, a static or a class method. - result = next(node.infer_call_result(node.parent)) - except (StopIteration, exceptions.InferenceError): - return - if isinstance(result, bases.Instance): - result = result._proxied - if isinstance(result, ClassDef): - if result.is_subtype_of('%s.classmethod' % BUILTINS): - return 'classmethod' - if result.is_subtype_of('%s.staticmethod' % BUILTINS): - return 'staticmethod' - - -class Lambda(mixins.FilterStmtsMixin, LocalsDictNodeNG): - _astroid_fields = ('args', 'body',) - name = '' - - # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod' - type = 'function' - - def __init__(self): - self._locals = {} - self.args = [] - self.body = [] - - def pytype(self): - if 'method' in self.type: - return '%s.instancemethod' % BUILTINS - return '%s.function' % BUILTINS - - def display_type(self): - if 'method' in self.type: - return 'Method' - return 'Function' - - def callable(self): - return True - - def argnames(self): - """return a list of argument names""" - if self.args.args: # maybe None with builtin functions - names = _rec_get_names(self.args.args) - else: - names = [] - if self.args.vararg: - names.append(self.args.vararg) - if self.args.kwarg: - names.append(self.args.kwarg) - return names - - def infer_call_result(self, caller, context=None): - """infer what a function is returning when called""" - return self.body.infer(context) - - def scope_lookup(self, node, name, offset=0): - if node in self.args.defaults or node in self.args.kw_defaults: - frame = self.parent.frame() - # line offset to avoid that def func(f=func) resolve the default - # value to the defined function - offset = -1 - else: - # check this is not used in function decorators - frame = self - return frame._scope_lookup(node, name, offset) - - - -class FunctionDef(bases.Statement, Lambda): - if six.PY3: - _astroid_fields = ('decorators', 'args', 'returns', 'body') - returns = None - else: - _astroid_fields = ('decorators', 'args', 'body') - - special_attributes = set(('__name__', '__doc__', '__dict__')) - is_function = True - # attributes below are set by the builder module or by raw factories - decorators = None - - def __init__(self, name, doc): - self._locals = {} - self.args = [] - self.body = [] - self.name = name - self.doc = doc - self._instance_attrs = {} - - @property - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - return self._instance_attrs - @instance_attrs.setter - def instance_attrs(self, _instance_attrs): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - self._instance_attrs = _instance_attrs - @instance_attrs.deleter - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - del self._instance_attrs - - @decorators_mod.cachedproperty - def extra_decorators(self): - """Get the extra decorators that this function can haves - Additional decorators are considered when they are used as - assignments, as in `method = staticmethod(method)`. - The property will return all the callables that are used for - decoration. - """ - frame = self.parent.frame() - if not isinstance(frame, ClassDef): - return [] - - decorators = [] - for assign in frame.nodes_of_class(node_classes.Assign): - if (isinstance(assign.value, node_classes.Call) - and isinstance(assign.value.func, node_classes.Name)): - for assign_node in assign.targets: - if not isinstance(assign_node, node_classes.AssignName): - # Support only `name = callable(name)` - continue - - if assign_node.name != self.name: - # Interested only in the assignment nodes that - # decorates the current method. - continue - try: - meth = frame[self.name] - except KeyError: - continue - else: - # Must be a function and in the same frame as the - # original method. - if (isinstance(meth, FunctionDef) - and assign_node.frame() == frame): - decorators.append(assign.value) - return decorators - - @decorators_mod.cachedproperty - def type(self): - """Get the function type for this node. - - Possible values are: method, function, staticmethod, classmethod. - """ - builtin_descriptors = {'classmethod', 'staticmethod'} - - for decorator in self.extra_decorators: - if decorator.func.name in builtin_descriptors: - return decorator.func.name - - frame = self.parent.frame() - type_name = 'function' - if isinstance(frame, ClassDef): - if self.name == '__new__': - return 'classmethod' - else: - type_name = 'method' - - if self.decorators: - for node in self.decorators.nodes: - if isinstance(node, node_classes.Name): - if node.name in builtin_descriptors: - return node.name - - if isinstance(node, node_classes.Call): - # Handle the following case: - # @some_decorator(arg1, arg2) - # def func(...) - # - try: - current = next(node.func.infer()) - except exceptions.InferenceError: - continue - _type = _infer_decorator_callchain(current) - if _type is not None: - return _type - - try: - for inferred in node.infer(): - # Check to see if this returns a static or a class method. - _type = _infer_decorator_callchain(inferred) - if _type is not None: - return _type - - if not isinstance(inferred, ClassDef): - continue - for ancestor in inferred.ancestors(): - if not isinstance(ancestor, ClassDef): - continue - if ancestor.is_subtype_of('%s.classmethod' % BUILTINS): - return 'classmethod' - elif ancestor.is_subtype_of('%s.staticmethod' % BUILTINS): - return 'staticmethod' - except exceptions.InferenceError: - pass - return type_name - - @decorators_mod.cachedproperty - def fromlineno(self): - # lineno is the line number of the first decorator, we want the def - # statement lineno - lineno = self.lineno - if self.decorators is not None: - lineno += sum(node.tolineno - node.lineno + 1 - for node in self.decorators.nodes) - - return lineno - - @decorators_mod.cachedproperty - def blockstart_tolineno(self): - return self.args.tolineno - - def block_range(self, lineno): - """return block line numbers. - - start from the "def" position whatever the given lineno - """ - return self.fromlineno, self.tolineno - - def getattr(self, name, context=None): - """this method doesn't look in the instance_attrs dictionary since it's - done by an Instance proxy at inference time. - """ - if name == '__module__': - return [node_classes.const_factory(self.root().qname())] - if name in self._instance_attrs: - return self._instance_attrs[name] - return std_special_attributes(self, name, False) - - def igetattr(self, name, context=None): - """Inferred getattr, which returns an iterator of inferred statements.""" - try: - return bases._infer_stmts(self.getattr(name, context), - context, frame=self) - except exceptions.NotFoundError: - raise exceptions.InferenceError(name) - - def is_method(self): - """return true if the function node should be considered as a method""" - # check we are defined in a ClassDef, because this is usually expected - # (e.g. pylint...) when is_method() return True - return self.type != 'function' and isinstance(self.parent.frame(), ClassDef) - - @decorators_mod.cached - def decoratornames(self): - """return a list of decorator qualified names""" - result = set() - decoratornodes = [] - if self.decorators is not None: - # pylint: disable=unsupported-binary-operation; damn flow control. - decoratornodes += self.decorators.nodes - decoratornodes += self.extra_decorators - for decnode in decoratornodes: - try: - for infnode in decnode.infer(): - result.add(infnode.qname()) - except exceptions.InferenceError: - continue - return result - - def is_bound(self): - """return true if the function is bound to an Instance or a class""" - return self.type == 'classmethod' - - def is_abstract(self, pass_is_abstract=True): - """Returns True if the method is abstract. - - A method is considered abstract if - - the only statement is 'raise NotImplementedError', or - - the only statement is 'pass' and pass_is_abstract is True, or - - the method is annotated with abc.astractproperty/abc.abstractmethod - """ - if self.decorators: - for node in self.decorators.nodes: - try: - inferred = next(node.infer()) - except exceptions.InferenceError: - continue - if inferred and inferred.qname() in ('abc.abstractproperty', - 'abc.abstractmethod'): - return True - - for child_node in self.body: - if isinstance(child_node, node_classes.Raise): - if child_node.raises_not_implemented(): - return True - return pass_is_abstract and isinstance(child_node, node_classes.Pass) - # empty function is the same as function with a single "pass" statement - if pass_is_abstract: - return True - - def is_generator(self): - """return true if this is a generator function""" - yield_nodes = (node_classes.Yield, node_classes.YieldFrom) - return next(self.nodes_of_class(yield_nodes, - skip_klass=(FunctionDef, Lambda)), False) - - def infer_call_result(self, caller, context=None): - """infer what a function is returning when called""" - if self.is_generator(): - result = bases.Generator() - result.parent = self - yield result - return - # This is really a gigantic hack to work around metaclass generators - # that return transient class-generating functions. Pylint's AST structure - # cannot handle a base class object that is only used for calling __new__, - # but does not contribute to the inheritance structure itself. We inject - # a fake class into the hierarchy here for several well-known metaclass - # generators, and filter it out later. - if (self.name == 'with_metaclass' and - len(self.args.args) == 1 and - self.args.vararg is not None): - metaclass = next(caller.args[0].infer(context)) - if isinstance(metaclass, ClassDef): - c = ClassDef('temporary_class', None) - c.hide = True - c.parent = self - class_bases = [next(b.infer(context)) for b in caller.args[1:]] - c.bases = [base for base in class_bases if base != util.YES] - c._metaclass = metaclass - yield c - return - returns = self.nodes_of_class(node_classes.Return, skip_klass=FunctionDef) - for returnnode in returns: - if returnnode.value is None: - yield node_classes.Const(None) - else: - try: - for inferred in returnnode.value.infer(context): - yield inferred - except exceptions.InferenceError: - yield util.YES - - -class AsyncFunctionDef(FunctionDef): - """Asynchronous function created with the `async` keyword.""" - - -def _rec_get_names(args, names=None): - """return a list of all argument names""" - if names is None: - names = [] - for arg in args: - if isinstance(arg, node_classes.Tuple): - _rec_get_names(arg.elts, names) - else: - names.append(arg.name) - return names - - -def _is_metaclass(klass, seen=None): - """ Return if the given class can be - used as a metaclass. - """ - if klass.name == 'type': - return True - if seen is None: - seen = set() - for base in klass.bases: - try: - for baseobj in base.infer(): - baseobj_name = baseobj.qname() - if baseobj_name in seen: - continue - else: - seen.add(baseobj_name) - if isinstance(baseobj, bases.Instance): - # not abstract - return False - if baseobj is util.YES: - continue - if baseobj is klass: - continue - if not isinstance(baseobj, ClassDef): - continue - if baseobj._type == 'metaclass': - return True - if _is_metaclass(baseobj, seen): - return True - except exceptions.InferenceError: - continue - return False - - -def _class_type(klass, ancestors=None): - """return a ClassDef node type to differ metaclass and exception - from 'regular' classes - """ - # XXX we have to store ancestors in case we have a ancestor loop - if klass._type is not None: - return klass._type - if _is_metaclass(klass): - klass._type = 'metaclass' - elif klass.name.endswith('Exception'): - klass._type = 'exception' - else: - if ancestors is None: - ancestors = set() - klass_name = klass.qname() - if klass_name in ancestors: - # XXX we are in loop ancestors, and have found no type - klass._type = 'class' - return 'class' - ancestors.add(klass_name) - for base in klass.ancestors(recurs=False): - name = _class_type(base, ancestors) - if name != 'class': - if name == 'metaclass' and not _is_metaclass(klass): - # don't propagate it if the current class - # can't be a metaclass - continue - klass._type = base.type - break - if klass._type is None: - klass._type = 'class' - return klass._type - - -class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, bases.Statement): - - # some of the attributes below are set by the builder module or - # by a raw factories - - # a dictionary of class instances attributes - _astroid_fields = ('decorators', 'bases', 'body') # name - - decorators = None - special_attributes = set(('__name__', '__doc__', '__dict__', '__module__', - '__bases__', '__mro__', '__subclasses__')) - - _type = None - _metaclass_hack = False - hide = False - type = property(_class_type, - doc="class'type, possible values are 'class' | " - "'metaclass' | 'exception'") - - def __init__(self, name, doc): - self._instance_attrs = {} - self._locals = {} - self.bases = [] - self.body = [] - self.name = name - self.doc = doc - - @property - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - return self._instance_attrs - @instance_attrs.setter - def instance_attrs(self, _instance_attrs): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - self._instance_attrs = _instance_attrs - @instance_attrs.deleter - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - del self._instance_attrs - - def _newstyle_impl(self, context=None): - if context is None: - context = contextmod.InferenceContext() - if self._newstyle is not None: - return self._newstyle - for base in self.ancestors(recurs=False, context=context): - if base._newstyle_impl(context): - self._newstyle = True - break - klass = self._explicit_metaclass() - # could be any callable, we'd need to infer the result of klass(name, - # bases, dict). punt if it's not a class node. - if klass is not None and isinstance(klass, ClassDef): - self._newstyle = klass._newstyle_impl(context) - if self._newstyle is None: - self._newstyle = False - return self._newstyle - - _newstyle = None - newstyle = property(_newstyle_impl, - doc="boolean indicating if it's a new style class" - "or not") - - @decorators_mod.cachedproperty - def blockstart_tolineno(self): - if self.bases: - return self.bases[-1].tolineno - else: - return self.fromlineno - - def block_range(self, lineno): - """return block line numbers. - - start from the "class" position whatever the given lineno - """ - return self.fromlineno, self.tolineno - - def pytype(self): - if self.newstyle: - return '%s.type' % BUILTINS - return '%s.classobj' % BUILTINS - - def display_type(self): - return 'Class' - - def callable(self): - return True - - def is_subtype_of(self, type_name, context=None): - if self.qname() == type_name: - return True - for anc in self.ancestors(context=context): - if anc.qname() == type_name: - return True - - def _infer_type_call(self, caller, context): - name_node = next(caller.args[0].infer(context)) - if (isinstance(name_node, node_classes.Const) and - isinstance(name_node.value, six.string_types)): - name = name_node.value - else: - return util.YES - - result = ClassDef(name, None) - - # Get the bases of the class. - class_bases = next(caller.args[1].infer(context)) - if isinstance(class_bases, (node_classes.Tuple, node_classes.List)): - result.bases = class_bases.itered() - else: - # There is currently no AST node that can represent an 'unknown' - # node (YES is not an AST node), therefore we simply return YES here - # although we know at least the name of the class. - return util.YES - - # Get the members of the class - try: - members = next(caller.args[2].infer(context)) - except exceptions.InferenceError: - members = None - - if members and isinstance(members, node_classes.Dict): - for attr, value in members.items: - if (isinstance(attr, node_classes.Const) and - isinstance(attr.value, six.string_types)): - result._locals[attr.value] = [value] - - result.parent = caller.parent - return result - - def infer_call_result(self, caller, context=None): - """infer what a class is returning when called""" - if (self.is_subtype_of('%s.type' % (BUILTINS,), context) - and len(caller.args) == 3): - result = self._infer_type_call(caller, context) - yield result - else: - yield bases.Instance(self) - - def scope_lookup(self, node, name, offset=0): - # pylint: disable=redefined-variable-type - if any(node == base or base.parent_of(node) - for base in self.bases): - # Handle the case where we have either a name - # in the bases of a class, which exists before - # the actual definition or the case where we have - # a Getattr node, with that name. - # - # name = ... - # class A(name): - # def name(self): ... - # - # import name - # class A(name.Name): - # def name(self): ... - - frame = self.parent.frame() - # line offset to avoid that class A(A) resolve the ancestor to - # the defined class - offset = -1 - else: - frame = self - return frame._scope_lookup(node, name, offset) - - @property - def basenames(self): - """Get the list of parent class names, as they appear in the class definition.""" - return [bnode.as_string() for bnode in self.bases] - - def ancestors(self, recurs=True, context=None): - """return an iterator on the node base classes in a prefixed - depth first order - - :param recurs: - boolean indicating if it should recurse or return direct - ancestors only - """ - # FIXME: should be possible to choose the resolution order - # FIXME: inference make infinite loops possible here - yielded = set([self]) - if context is None: - context = contextmod.InferenceContext() - if six.PY3: - if not self.bases and self.qname() != 'builtins.object': - yield builtin_lookup("object")[1][0] - return - - for stmt in self.bases: - with context.restore_path(): - try: - for baseobj in stmt.infer(context): - if not isinstance(baseobj, ClassDef): - if isinstance(baseobj, bases.Instance): - baseobj = baseobj._proxied - else: - continue - if not baseobj.hide: - if baseobj in yielded: - continue - yielded.add(baseobj) - yield baseobj - if recurs: - for grandpa in baseobj.ancestors(recurs=True, - context=context): - if grandpa is self: - # This class is the ancestor of itself. - break - if grandpa in yielded: - continue - yielded.add(grandpa) - yield grandpa - except exceptions.InferenceError: - continue - - def local_attr_ancestors(self, name, context=None): - """return an iterator on astroid representation of parent classes - which have defined in their locals - """ - if self.newstyle and all(n.newstyle for n in self.ancestors(context)): - # Look up in the mro if we can. This will result in the - # attribute being looked up just as Python does it. - try: - ancestors = self.mro(context)[1:] - except exceptions.MroError: - # Fallback to use ancestors, we can't determine - # a sane MRO. - ancestors = self.ancestors(context=context) - else: - ancestors = self.ancestors(context=context) - for astroid in ancestors: - if name in astroid: - yield astroid - - def instance_attr_ancestors(self, name, context=None): - """return an iterator on astroid representation of parent classes - which have defined in their instance attribute dictionary - """ - for astroid in self.ancestors(context=context): - if name in astroid._instance_attrs: - yield astroid - - def has_base(self, node): - return node in self.bases - - @remove_nodes(node_classes.DelAttr) - def local_attr(self, name, context=None): - """return the list of assign node associated to name in this class - locals or in its parents - - :raises `NotFoundError`: - if no attribute with this name has been find in this class or - its parent classes - """ - try: - return self._locals[name] - except KeyError: - for class_node in self.local_attr_ancestors(name, context): - return class_node._locals[name] - raise exceptions.NotFoundError(name) - - @remove_nodes(node_classes.DelAttr) - def instance_attr(self, name, context=None): - """return the astroid nodes associated to name in this class instance - attributes dictionary and in its parents - - :raises `NotFoundError`: - if no attribute with this name has been find in this class or - its parent classes - """ - # Return a copy, so we don't modify self._instance_attrs, - # which could lead to infinite loop. - values = list(self._instance_attrs.get(name, [])) - # get all values from parents - for class_node in self.instance_attr_ancestors(name, context): - values += class_node._instance_attrs[name] - if not values: - raise exceptions.NotFoundError(name) - return values - - def instantiate_class(self): - """return Instance of ClassDef node, else return self""" - return bases.Instance(self) - - def instanciate_class(self): - """return Instance of ClassDef node, else return self""" - util.rename_warning('instanciate_class()', 2.0, 'instantiate_class()') - return self.instantiate_class() - - def getattr(self, name, context=None): - """this method doesn't look in the instance_attrs dictionary since it's - done by an Instance proxy at inference time. - - It may return a YES object if the attribute has not been actually - found but a __getattr__ or __getattribute__ method is defined - """ - values = self._locals.get(name, []) - if name in self.special_attributes: - if name == '__module__': - return [node_classes.const_factory(self.root().qname())] + values - if name == '__bases__': - node = node_classes.Tuple() - elts = list(self._inferred_bases(context)) - node.elts = elts - return [node] + values - if name == '__mro__' and self.newstyle: - mro = self.mro() - node = node_classes.Tuple() - node.elts = mro - return [node] - return std_special_attributes(self, name) - # don't modify the list in self._locals! - values = list(values) - for classnode in self.ancestors(recurs=True, context=context): - values += classnode._locals.get(name, []) - if not values: - raise exceptions.NotFoundError(name) - return values - - def igetattr(self, name, context=None): - """inferred getattr, need special treatment in class to handle - descriptors - """ - # set lookup name since this is necessary to infer on import nodes for - # instance - context = contextmod.copy_context(context) - context.lookupname = name - try: - for inferred in bases._infer_stmts(self.getattr(name, context), - context, frame=self): - # yield YES object instead of descriptors when necessary - if (not isinstance(inferred, node_classes.Const) - and isinstance(inferred, bases.Instance)): - try: - inferred._proxied.getattr('__get__', context) - except exceptions.NotFoundError: - yield inferred - else: - yield util.YES - else: - yield function_to_method(inferred, self) - except exceptions.NotFoundError: - if not name.startswith('__') and self.has_dynamic_getattr(context): - # class handle some dynamic attributes, return a YES object - yield util.YES - else: - raise exceptions.InferenceError(name) - - def has_dynamic_getattr(self, context=None): - """ - Check if the current instance has a custom __getattr__ - or a custom __getattribute__. - - If any such method is found and it is not from - builtins, nor from an extension module, then the function - will return True. - """ - def _valid_getattr(node): - root = node.root() - return root.name != BUILTINS and getattr(root, 'pure_python', None) - - try: - return _valid_getattr(self.getattr('__getattr__', context)[0]) - except exceptions.NotFoundError: - #if self.newstyle: XXX cause an infinite recursion error - try: - getattribute = self.getattr('__getattribute__', context)[0] - return _valid_getattr(getattribute) - except exceptions.NotFoundError: - pass - return False - - def methods(self): - """return an iterator on all methods defined in the class and - its ancestors - """ - done = {} - for astroid in itertools.chain(iter((self,)), self.ancestors()): - for meth in astroid.mymethods(): - if meth.name in done: - continue - done[meth.name] = None - yield meth - - def mymethods(self): - """return an iterator on all methods defined in the class""" - for member in self.values(): - if isinstance(member, FunctionDef): - yield member - - def implicit_metaclass(self): - """Get the implicit metaclass of the current class - - For newstyle classes, this will return an instance of builtins.type. - For oldstyle classes, it will simply return None, since there's - no implicit metaclass there. - """ - - if self.newstyle: - return builtin_lookup('type')[1][0] - - _metaclass = None - def _explicit_metaclass(self): - """ Return the explicit defined metaclass - for the current class. - - An explicit defined metaclass is defined - either by passing the ``metaclass`` keyword argument - in the class definition line (Python 3) or (Python 2) by - having a ``__metaclass__`` class attribute, or if there are - no explicit bases but there is a global ``__metaclass__`` variable. - """ - for base in self.bases: - try: - for baseobj in base.infer(): - if isinstance(baseobj, ClassDef) and baseobj.hide: - self._metaclass = baseobj._metaclass - self._metaclass_hack = True - break - except exceptions.InferenceError: - pass - - if self._metaclass: - # Expects this from Py3k TreeRebuilder - try: - return next(node for node in self._metaclass.infer() - if node is not util.YES) - except (exceptions.InferenceError, StopIteration): - return None - if six.PY3: - return None - - if '__metaclass__' in self._locals: - assignment = self._locals['__metaclass__'][-1] - elif self.bases: - return None - elif '__metaclass__' in self.root()._locals: - assignments = [ass for ass in self.root()._locals['__metaclass__'] - if ass.lineno < self.lineno] - if not assignments: - return None - assignment = assignments[-1] - else: - return None - - try: - inferred = next(assignment.infer()) - except exceptions.InferenceError: - return - if inferred is util.YES: # don't expose this - return None - return inferred - - def _find_metaclass(self, seen=None): - if seen is None: - seen = set() - seen.add(self) - - klass = self._explicit_metaclass() - if klass is None: - for parent in self.ancestors(): - if parent not in seen: - klass = parent._find_metaclass(seen) - if klass is not None: - break - return klass - - def metaclass(self): - """Return the metaclass of this class. - - If this class does not define explicitly a metaclass, - then the first defined metaclass in ancestors will be used - instead. - """ - return self._find_metaclass() - - def has_metaclass_hack(self): - return self._metaclass_hack - - def _islots(self): - """ Return an iterator with the inferred slots. """ - if '__slots__' not in self._locals: - return - for slots in self.igetattr('__slots__'): - # check if __slots__ is a valid type - for meth in ITER_METHODS: - try: - slots.getattr(meth) - break - except exceptions.NotFoundError: - continue - else: - continue - - if isinstance(slots, node_classes.Const): - # a string. Ignore the following checks, - # but yield the node, only if it has a value - if slots.value: - yield slots - continue - if not hasattr(slots, 'itered'): - # we can't obtain the values, maybe a .deque? - continue - - if isinstance(slots, node_classes.Dict): - values = [item[0] for item in slots.items] - else: - values = slots.itered() - if values is util.YES: - continue - if not values: - # Stop the iteration, because the class - # has an empty list of slots. - raise StopIteration(values) - - for elt in values: - try: - for inferred in elt.infer(): - if inferred is util.YES: - continue - if (not isinstance(inferred, node_classes.Const) or - not isinstance(inferred.value, - six.string_types)): - continue - if not inferred.value: - continue - yield inferred - except exceptions.InferenceError: - continue - - def _slots(self): - if not self.newstyle: - raise NotImplementedError( - "The concept of slots is undefined for old-style classes.") - - slots = self._islots() - try: - first = next(slots) - except StopIteration as exc: - # The class doesn't have a __slots__ definition or empty slots. - if exc.args and exc.args[0] not in ('', None): - return exc.args[0] - return None - # pylint: disable=unsupported-binary-operation; false positive - return [first] + list(slots) - - # Cached, because inferring them all the time is expensive - @decorators_mod.cached - def slots(self): - """Get all the slots for this node. - - If the class doesn't define any slot, through `__slots__` - variable, then this function will return a None. - Also, it will return None in the case the slots weren't inferred. - Otherwise, it will return a list of slot names. - """ - def grouped_slots(): - # Not interested in object, since it can't have slots. - for cls in self.mro()[:-1]: - try: - cls_slots = cls._slots() - except NotImplementedError: - continue - if cls_slots is not None: - for slot in cls_slots: - yield slot - else: - yield None - - if not self.newstyle: - raise NotImplementedError( - "The concept of slots is undefined for old-style classes.") - - slots = list(grouped_slots()) - if not all(slot is not None for slot in slots): - return None - - return sorted(slots, key=lambda item: item.value) - - def _inferred_bases(self, context=None): - # TODO(cpopa): really similar with .ancestors, - # but the difference is when one base is inferred, - # only the first object is wanted. That's because - # we aren't interested in superclasses, as in the following - # example: - # - # class SomeSuperClass(object): pass - # class SomeClass(SomeSuperClass): pass - # class Test(SomeClass): pass - # - # Inferring SomeClass from the Test's bases will give - # us both SomeClass and SomeSuperClass, but we are interested - # only in SomeClass. - - if context is None: - context = contextmod.InferenceContext() - if six.PY3: - if not self.bases and self.qname() != 'builtins.object': - yield builtin_lookup("object")[1][0] - return - - for stmt in self.bases: - try: - baseobj = next(stmt.infer(context=context)) - except exceptions.InferenceError: - continue - if isinstance(baseobj, bases.Instance): - baseobj = baseobj._proxied - if not isinstance(baseobj, ClassDef): - continue - if not baseobj.hide: - yield baseobj - else: - for base in baseobj.bases: - yield base - - def mro(self, context=None): - """Get the method resolution order, using C3 linearization. - - It returns the list of ancestors sorted by the mro. - This will raise `NotImplementedError` for old-style classes, since - they don't have the concept of MRO. - """ - if not self.newstyle: - raise NotImplementedError( - "Could not obtain mro for old-style classes.") - - bases = list(self._inferred_bases(context=context)) - bases_mro = [] - for base in bases: - try: - mro = base.mro(context=context) - bases_mro.append(mro) - except NotImplementedError: - # Some classes have in their ancestors both newstyle and - # old style classes. For these we can't retrieve the .mro, - # although in Python it's possible, since the class we are - # currently working is in fact new style. - # So, we fallback to ancestors here. - ancestors = list(base.ancestors(context=context)) - bases_mro.append(ancestors) - - unmerged_mro = ([[self]] + bases_mro + [bases]) - _verify_duplicates_mro(unmerged_mro) - return _c3_merge(unmerged_mro) - -def get_locals(node): - '''Stub function for forwards compatibility.''' - return node._locals - -def get_attributes(node): - '''Stub function for forwards compatibility.''' - return node._instance_attrs - -# Backwards-compatibility aliases -Class = node_classes.proxy_alias('Class', ClassDef) -Function = node_classes.proxy_alias('Function', FunctionDef) -GenExpr = node_classes.proxy_alias('GenExpr', GeneratorExp) diff --git a/pymode/libs/astroid/test_utils.py b/pymode/libs/astroid/test_utils.py deleted file mode 100644 index 9e45abcf..00000000 --- a/pymode/libs/astroid/test_utils.py +++ /dev/null @@ -1,201 +0,0 @@ -"""Utility functions for test code that uses astroid ASTs as input.""" -import functools -import sys - -from astroid import nodes -from astroid import builder -# The name of the transient function that is used to -# wrap expressions to be extracted when calling -# extract_node. -_TRANSIENT_FUNCTION = '__' - -# The comment used to select a statement to be extracted -# when calling extract_node. -_STATEMENT_SELECTOR = '#@' - -def _extract_expressions(node): - """Find expressions in a call to _TRANSIENT_FUNCTION and extract them. - - The function walks the AST recursively to search for expressions that - are wrapped into a call to _TRANSIENT_FUNCTION. If it finds such an - expression, it completely removes the function call node from the tree, - replacing it by the wrapped expression inside the parent. - - :param node: An astroid node. - :type node: astroid.bases.NodeNG - :yields: The sequence of wrapped expressions on the modified tree - expression can be found. - """ - if (isinstance(node, nodes.Call) - and isinstance(node.func, nodes.Name) - and node.func.name == _TRANSIENT_FUNCTION): - real_expr = node.args[0] - real_expr.parent = node.parent - # Search for node in all _astng_fields (the fields checked when - # get_children is called) of its parent. Some of those fields may - # be lists or tuples, in which case the elements need to be checked. - # When we find it, replace it by real_expr, so that the AST looks - # like no call to _TRANSIENT_FUNCTION ever took place. - for name in node.parent._astroid_fields: - child = getattr(node.parent, name) - if isinstance(child, (list, tuple)): - for idx, compound_child in enumerate(child): - if compound_child is node: - child[idx] = real_expr - elif child is node: - setattr(node.parent, name, real_expr) - yield real_expr - else: - for child in node.get_children(): - for result in _extract_expressions(child): - yield result - - -def _find_statement_by_line(node, line): - """Extracts the statement on a specific line from an AST. - - If the line number of node matches line, it will be returned; - otherwise its children are iterated and the function is called - recursively. - - :param node: An astroid node. - :type node: astroid.bases.NodeNG - :param line: The line number of the statement to extract. - :type line: int - :returns: The statement on the line, or None if no statement for the line - can be found. - :rtype: astroid.bases.NodeNG or None - """ - if isinstance(node, (nodes.ClassDef, nodes.FunctionDef)): - # This is an inaccuracy in the AST: the nodes that can be - # decorated do not carry explicit information on which line - # the actual definition (class/def), but .fromline seems to - # be close enough. - node_line = node.fromlineno - else: - node_line = node.lineno - - if node_line == line: - return node - - for child in node.get_children(): - result = _find_statement_by_line(child, line) - if result: - return result - - return None - -def extract_node(code, module_name=''): - """Parses some Python code as a module and extracts a designated AST node. - - Statements: - To extract one or more statement nodes, append #@ to the end of the line - - Examples: - >>> def x(): - >>> def y(): - >>> return 1 #@ - - The return statement will be extracted. - - >>> class X(object): - >>> def meth(self): #@ - >>> pass - - The funcion object 'meth' will be extracted. - - Expressions: - To extract arbitrary expressions, surround them with the fake - function call __(...). After parsing, the surrounded expression - will be returned and the whole AST (accessible via the returned - node's parent attribute) will look like the function call was - never there in the first place. - - Examples: - >>> a = __(1) - - The const node will be extracted. - - >>> def x(d=__(foo.bar)): pass - - The node containing the default argument will be extracted. - - >>> def foo(a, b): - >>> return 0 < __(len(a)) < b - - The node containing the function call 'len' will be extracted. - - If no statements or expressions are selected, the last toplevel - statement will be returned. - - If the selected statement is a discard statement, (i.e. an expression - turned into a statement), the wrapped expression is returned instead. - - For convenience, singleton lists are unpacked. - - :param str code: A piece of Python code that is parsed as - a module. Will be passed through textwrap.dedent first. - :param str module_name: The name of the module. - :returns: The designated node from the parse tree, or a list of nodes. - :rtype: astroid.bases.NodeNG, or a list of nodes. - """ - def _extract(node): - if isinstance(node, nodes.Expr): - return node.value - else: - return node - - requested_lines = [] - for idx, line in enumerate(code.splitlines()): - if line.strip().endswith(_STATEMENT_SELECTOR): - requested_lines.append(idx + 1) - - tree = builder.parse(code, module_name=module_name) - extracted = [] - if requested_lines: - for line in requested_lines: - extracted.append(_find_statement_by_line(tree, line)) - - # Modifies the tree. - extracted.extend(_extract_expressions(tree)) - - if not extracted: - extracted.append(tree.body[-1]) - - extracted = [_extract(node) for node in extracted] - if len(extracted) == 1: - return extracted[0] - else: - return extracted - - -def require_version(minver=None, maxver=None): - """ Compare version of python interpreter to the given one. Skip the test - if older. - """ - def parse(string, default=None): - string = string or default - try: - return tuple(int(v) for v in string.split('.')) - except ValueError: - raise ValueError('%s is not a correct version : should be X.Y[.Z].' % version) - - def check_require_version(f): - current = sys.version_info[:3] - if parse(minver, "0") < current <= parse(maxver, "4"): - return f - else: - str_version = '.'.join(str(v) for v in sys.version_info) - @functools.wraps(f) - def new_f(self, *args, **kwargs): - if minver is not None: - self.skipTest('Needs Python > %s. Current version is %s.' % (minver, str_version)) - elif maxver is not None: - self.skipTest('Needs Python <= %s. Current version is %s.' % (maxver, str_version)) - return new_f - - - return check_require_version - -def get_name_node(start_from, name, index=0): - return [n for n in start_from.nodes_of_class(nodes.Name) if n.name == name][index] diff --git a/pymode/libs/astroid/tests/resources.py b/pymode/libs/astroid/tests/resources.py deleted file mode 100644 index 7988d053..00000000 --- a/pymode/libs/astroid/tests/resources.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2014 Google, Inc. 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 . -import os -import sys - -import pkg_resources - -from astroid import builder -from astroid import MANAGER -from astroid.bases import BUILTINS - - -DATA_DIR = 'testdata/python{}/'.format(sys.version_info[0]) - -def find(name): - return pkg_resources.resource_filename( - 'astroid.tests', os.path.normpath(os.path.join(DATA_DIR, name))) - - -def build_file(path, modname=None): - return builder.AstroidBuilder().file_build(find(path), modname) - - -class SysPathSetup(object): - def setUp(self): - sys.path.insert(0, find('')) - - def tearDown(self): - del sys.path[0] - datadir = find('') - for key in list(sys.path_importer_cache): - if key.startswith(datadir): - del sys.path_importer_cache[key] - - -class AstroidCacheSetupMixin(object): - """Mixin for handling the astroid cache problems. - - When clearing the astroid cache, some tests fails due to - cache inconsistencies, where some objects had a different - builtins object referenced. - This saves the builtins module and makes sure to add it - back to the astroid_cache after the tests finishes. - The builtins module is special, since some of the - transforms for a couple of its objects (str, bytes etc) - are executed only once, so astroid_bootstrapping will be - useless for retrieving the original builtins module. - """ - - @classmethod - def setUpClass(cls): - cls._builtins = MANAGER.astroid_cache.get(BUILTINS) - - @classmethod - def tearDownClass(cls): - if cls._builtins: - MANAGER.astroid_cache[BUILTINS] = cls._builtins diff --git a/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg b/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg deleted file mode 100644 index f62599c7..00000000 Binary files a/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg and /dev/null differ diff --git a/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip b/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip deleted file mode 100644 index f62599c7..00000000 Binary files a/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip and /dev/null differ diff --git a/pymode/libs/astroid/tests/testdata/python2/data/SSL1/Connection1.py b/pymode/libs/astroid/tests/testdata/python2/data/SSL1/Connection1.py deleted file mode 100644 index 6bbb1302..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/SSL1/Connection1.py +++ /dev/null @@ -1,14 +0,0 @@ -"""M2Crypto.SSL.Connection - -Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" -from __future__ import print_function -RCS_id='$Id: Connection1.py,v 1.1 2005-06-13 20:55:22 syt Exp $' - -#Some code deleted here - -class Connection: - - """An SSL connection.""" - - def __init__(self, ctx, sock=None): - print('init Connection') diff --git a/pymode/libs/astroid/tests/testdata/python2/data/SSL1/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/SSL1/__init__.py deleted file mode 100644 index a007b049..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/SSL1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from Connection1 import Connection diff --git a/pymode/libs/astroid/tests/testdata/python2/data/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/__init__.py deleted file mode 100644 index 332e2e72..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $" diff --git a/pymode/libs/astroid/tests/testdata/python2/data/absimp/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/absimp/__init__.py deleted file mode 100644 index b98444df..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/absimp/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""a package with absolute import activated -""" - -from __future__ import absolute_import - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py deleted file mode 100644 index 239499a6..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""a side package with nothing in it -""" - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/absimp/string.py b/pymode/libs/astroid/tests/testdata/python2/data/absimp/string.py deleted file mode 100644 index e68e7496..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/absimp/string.py +++ /dev/null @@ -1,3 +0,0 @@ -from __future__ import absolute_import, print_function -import string -print(string) diff --git a/pymode/libs/astroid/tests/testdata/python2/data/absimport.py b/pymode/libs/astroid/tests/testdata/python2/data/absimport.py deleted file mode 100644 index f98effa6..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/absimport.py +++ /dev/null @@ -1,3 +0,0 @@ -from __future__ import absolute_import -import email -from email import message diff --git a/pymode/libs/astroid/tests/testdata/python2/data/all.py b/pymode/libs/astroid/tests/testdata/python2/data/all.py deleted file mode 100644 index 23f7d2b6..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/all.py +++ /dev/null @@ -1,9 +0,0 @@ - -name = 'a' -_bla = 2 -other = 'o' -class Aaa: pass - -def func(): print 'yo' - -__all__ = 'Aaa', '_bla', 'name' diff --git a/pymode/libs/astroid/tests/testdata/python2/data/appl/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/appl/__init__.py deleted file mode 100644 index d652ffd9..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/appl/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Init -""" diff --git a/pymode/libs/astroid/tests/testdata/python2/data/appl/myConnection.py b/pymode/libs/astroid/tests/testdata/python2/data/appl/myConnection.py deleted file mode 100644 index 5b24b259..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/appl/myConnection.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import print_function -from data import SSL1 -class MyConnection(SSL1.Connection): - - """An SSL connection.""" - - def __init__(self, dummy): - print('MyConnection init') - -if __name__ == '__main__': - myConnection = MyConnection(' ') - raw_input('Press Enter to continue...') diff --git a/pymode/libs/astroid/tests/testdata/python2/data/clientmodule_test.py b/pymode/libs/astroid/tests/testdata/python2/data/clientmodule_test.py deleted file mode 100644 index a178ca6d..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/clientmodule_test.py +++ /dev/null @@ -1,32 +0,0 @@ -""" docstring for file clientmodule.py """ -from data.suppliermodule_test import Interface as IFace, DoNothing - -class Toto: pass - -class Ancestor: - """ Ancestor method """ - __implements__ = (IFace,) - - def __init__(self, value): - local_variable = 0 - self.attr = 'this method shouldn\'t have a docstring' - self.__value = value - - def get_value(self): - """ nice docstring ;-) """ - return self.__value - - def set_value(self, value): - self.__value = value - return 'this method shouldn\'t have a docstring' - -class Specialization(Ancestor): - TYPE = 'final class' - top = 'class' - - def __init__(self, value, _id): - Ancestor.__init__(self, value) - self._id = _id - self.relation = DoNothing() - self.toto = Toto() - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/descriptor_crash.py b/pymode/libs/astroid/tests/testdata/python2/data/descriptor_crash.py deleted file mode 100644 index 11fbb4a2..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/descriptor_crash.py +++ /dev/null @@ -1,11 +0,0 @@ - -import urllib - -class Page(object): - _urlOpen = staticmethod(urllib.urlopen) - - def getPage(self, url): - handle = self._urlOpen(url) - data = handle.read() - handle.close() - return data diff --git a/pymode/libs/astroid/tests/testdata/python2/data/email.py b/pymode/libs/astroid/tests/testdata/python2/data/email.py deleted file mode 100644 index dc593564..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/email.py +++ /dev/null @@ -1 +0,0 @@ -"""fake email module to test absolute import doesn't grab this one""" diff --git a/pymode/libs/astroid/tests/testdata/python2/data/find_test/module.py b/pymode/libs/astroid/tests/testdata/python2/data/find_test/module.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python2/data/find_test/module2.py b/pymode/libs/astroid/tests/testdata/python2/data/find_test/module2.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python2/data/find_test/noendingnewline.py b/pymode/libs/astroid/tests/testdata/python2/data/find_test/noendingnewline.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python2/data/find_test/nonregr.py b/pymode/libs/astroid/tests/testdata/python2/data/find_test/nonregr.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python2/data/format.py b/pymode/libs/astroid/tests/testdata/python2/data/format.py deleted file mode 100644 index 73797061..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/format.py +++ /dev/null @@ -1,34 +0,0 @@ -"""A multiline string -""" - -function('aeozrijz\ -earzer', hop) -# XXX write test -x = [i for i in range(5) - if i % 4] - -fonction(1, - 2, - 3, - 4) - -def definition(a, - b, - c): - return a + b + c - -class debile(dict, - object): - pass - -if aaaa: pass -else: - aaaa,bbbb = 1,2 - aaaa,bbbb = bbbb,aaaa -# XXX write test -hop = \ - aaaa - - -__revision__.lower(); - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/joined_strings.py b/pymode/libs/astroid/tests/testdata/python2/data/joined_strings.py deleted file mode 100644 index 302e7cd7..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/joined_strings.py +++ /dev/null @@ -1,1051 +0,0 @@ -x = ('R0lGODlhigJnAef/AAABAAEEAAkCAAMGAg0GBAYJBQoMCBMODQ4QDRITEBkS' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7') \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python2/data/lmfp/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/lmfp/__init__.py deleted file mode 100644 index 74b26b82..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/lmfp/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# force a "direct" python import -from . import foo diff --git a/pymode/libs/astroid/tests/testdata/python2/data/lmfp/foo.py b/pymode/libs/astroid/tests/testdata/python2/data/lmfp/foo.py deleted file mode 100644 index 8f7de1e8..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/lmfp/foo.py +++ /dev/null @@ -1,6 +0,0 @@ -import sys -if not getattr(sys, 'bar', None): - sys.just_once = [] -# there used to be two numbers here because -# of a load_module_from_path bug -sys.just_once.append(42) diff --git a/pymode/libs/astroid/tests/testdata/python2/data/module.py b/pymode/libs/astroid/tests/testdata/python2/data/module.py deleted file mode 100644 index 6a67b9b6..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/module.py +++ /dev/null @@ -1,89 +0,0 @@ -"""test module for astroid -""" - -__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $' -from astroid.node_classes import Name as NameNode -from astroid import modutils -from astroid.utils import * -import os.path -MY_DICT = {} - -def global_access(key, val): - """function test""" - local = 1 - MY_DICT[key] = val - for i in val: - if i: - del MY_DICT[i] - continue - else: - break - else: - return local - - -class YO: - """hehe""" - a = 1 - - def __init__(self): - try: - self.yo = 1 - except ValueError, ex: - pass - except (NameError, TypeError): - raise XXXError() - except: - raise - - - -class YOUPI(YO): - class_attr = None - - def __init__(self): - self.member = None - - def method(self): - """method test""" - global MY_DICT - try: - MY_DICT = {} - local = None - autre = [a for (a, b) in MY_DICT if b] - if b in autre: - return b - else: - if a in autre: - return a - global_access(local, val=autre) - finally: - return local - - def static_method(): - """static method test""" - assert MY_DICT, '???' - static_method = staticmethod(static_method) - - def class_method(cls): - """class method test""" - exec a in b - class_method = classmethod(class_method) - - -def four_args(a, b, c, d): - """four arguments (was nested_args)""" - pass - while 1: - if a: - break - a += +1 - else: - b += -2 - if c: - d = ((a) and (b)) or (c) - else: - c = ((a) and (b)) or (d) - map(lambda x, y: (y, x), a) -redirect = four_args - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/module1abs/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/module1abs/__init__.py deleted file mode 100644 index 42949a44..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/module1abs/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from __future__ import absolute_import, print_function -from . import core -from .core import * -print(sys.version) diff --git a/pymode/libs/astroid/tests/testdata/python2/data/module1abs/core.py b/pymode/libs/astroid/tests/testdata/python2/data/module1abs/core.py deleted file mode 100644 index de101117..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/module1abs/core.py +++ /dev/null @@ -1 +0,0 @@ -import sys diff --git a/pymode/libs/astroid/tests/testdata/python2/data/module2.py b/pymode/libs/astroid/tests/testdata/python2/data/module2.py deleted file mode 100644 index 0a1bd1ad..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/module2.py +++ /dev/null @@ -1,143 +0,0 @@ -from data.module import YO, YOUPI -import data - - -class Specialization(YOUPI, YO): - pass - - - -class Metaclass(type): - pass - - - -class Interface: - pass - - - -class MyIFace(Interface): - pass - - - -class AnotherIFace(Interface): - pass - - - -class MyException(Exception): - pass - - - -class MyError(MyException): - pass - - - -class AbstractClass(object): - - def to_override(self, whatever): - raise NotImplementedError() - - def return_something(self, param): - if param: - return 'toto' - return - - - -class Concrete0: - __implements__ = MyIFace - - - -class Concrete1: - __implements__ = (MyIFace, AnotherIFace) - - - -class Concrete2: - __implements__ = (MyIFace, AnotherIFace) - - - -class Concrete23(Concrete1): - pass - -del YO.member -del YO -[SYN1, SYN2] = (Concrete0, Concrete1) -assert '1' -b = (1) | (((2) & (3)) ^ (8)) -bb = ((1) | (two)) | (6) -ccc = ((one) & (two)) & (three) -dddd = ((x) ^ (o)) ^ (r) -exec 'c = 3' -exec 'c = 3' in {}, {} - -def raise_string(a=2, *args, **kwargs): - raise Exception, 'yo' - yield 'coucou' - yield -a = (b) + (2) -c = (b) * (2) -c = (b) / (2) -c = (b) // (2) -c = (b) - (2) -c = (b) % (2) -c = (b) ** (2) -c = (b) << (2) -c = (b) >> (2) -c = ~b -c = not b -d = [c] -e = d[:] -e = d[a:b:c] -raise_string(*args, **kwargs) -print >> stream, 'bonjour' -print >> stream, 'salut', - -def make_class(any, base=data.module.YO, *args, **kwargs): - """check base is correctly resolved to Concrete0""" - - - class Aaaa(base): - """dynamic class""" - - - return Aaaa -from os.path import abspath -import os as myos - - -class A: - pass - - - -class A(A): - pass - - -def generator(): - """A generator.""" - yield - -def not_a_generator(): - """A function that contains generator, but is not one.""" - - def generator(): - yield - genl = lambda : (yield) - -def with_metaclass(meta, *bases): - return meta('NewBase', bases, {}) - - -class NotMetaclass(with_metaclass(Metaclass)): - pass - - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/noendingnewline.py b/pymode/libs/astroid/tests/testdata/python2/data/noendingnewline.py deleted file mode 100644 index e1d6e4a1..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/noendingnewline.py +++ /dev/null @@ -1,36 +0,0 @@ -import unittest - - -class TestCase(unittest.TestCase): - - def setUp(self): - unittest.TestCase.setUp(self) - - - def tearDown(self): - unittest.TestCase.tearDown(self) - - def testIt(self): - self.a = 10 - self.xxx() - - - def xxx(self): - if False: - pass - print 'a' - - if False: - pass - pass - - if False: - pass - print 'rara' - - -if __name__ == '__main__': - print 'test2' - unittest.main() - - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/nonregr.py b/pymode/libs/astroid/tests/testdata/python2/data/nonregr.py deleted file mode 100644 index 813469fe..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/nonregr.py +++ /dev/null @@ -1,57 +0,0 @@ -from __future__ import generators, print_function - -try: - enumerate = enumerate -except NameError: - - def enumerate(iterable): - """emulates the python2.3 enumerate() function""" - i = 0 - for val in iterable: - yield i, val - i += 1 - -def toto(value): - for k, v in value: - print(v.get('yo')) - - -import imp -fp, mpath, desc = imp.find_module('optparse',a) -s_opt = imp.load_module('std_optparse', fp, mpath, desc) - -class OptionParser(s_opt.OptionParser): - - def parse_args(self, args=None, values=None, real_optparse=False): - if real_optparse: - pass -## return super(OptionParser, self).parse_args() - else: - import optcomp - optcomp.completion(self) - - -class Aaa(object): - """docstring""" - def __init__(self): - self.__setattr__('a','b') - pass - - def one_public(self): - """docstring""" - pass - - def another_public(self): - """docstring""" - pass - -class Ccc(Aaa): - """docstring""" - - class Ddd(Aaa): - """docstring""" - pass - - class Eee(Ddd): - """docstring""" - pass diff --git a/pymode/libs/astroid/tests/testdata/python2/data/notall.py b/pymode/libs/astroid/tests/testdata/python2/data/notall.py deleted file mode 100644 index 7be27b18..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/notall.py +++ /dev/null @@ -1,7 +0,0 @@ -name = 'a' -_bla = 2 -other = 'o' -class Aaa: pass - -def func(): print('yo') - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/package/__init__.py deleted file mode 100644 index 575d18b1..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""package's __init__ file""" - - -from . import subpackage diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/absimport.py b/pymode/libs/astroid/tests/testdata/python2/data/package/absimport.py deleted file mode 100644 index 33ed117c..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/absimport.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import absolute_import, print_function -import import_package_subpackage_module # fail -print(import_package_subpackage_module) - -from . import hello as hola - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/hello.py b/pymode/libs/astroid/tests/testdata/python2/data/package/hello.py deleted file mode 100644 index b154c844..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/hello.py +++ /dev/null @@ -1,2 +0,0 @@ -"""hello module""" - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py b/pymode/libs/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py deleted file mode 100644 index ad442c16..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py +++ /dev/null @@ -1,49 +0,0 @@ -# pylint: disable-msg=I0011,C0301,W0611 -"""I found some of my scripts trigger off an AttributeError in pylint -0.8.1 (with common 0.12.0 and astroid 0.13.1). - -Traceback (most recent call last): - File "/usr/bin/pylint", line 4, in ? - lint.Run(sys.argv[1:]) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__ - linter.check(args) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check - self.check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file - astroid = self._check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file - self.check_astroid_module(astroid, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module - self.astroid_events(astroid, [checker for checker in checkers - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events - checker.visit(astroid) - File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit - method(node) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import - self._check_module_attrs(node, module, name_parts[1:]) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs - self.add_message('E0611', args=(name, module.name), -AttributeError: Import instance has no attribute 'name' - - -You can reproduce it by: -(1) create package structure like the following: - -package/ - __init__.py - subpackage/ - __init__.py - module.py - -(2) in package/__init__.py write: - -import subpackage - -(3) run pylint with a script importing package.subpackage.module. -""" -__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $' -import package.subpackage.module diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/__init__.py deleted file mode 100644 index dc4782e6..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage""" diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/module.py b/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/module.py deleted file mode 100644 index 4b7244ba..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/module.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage.module""" diff --git a/pymode/libs/astroid/tests/testdata/python2/data/recursion.py b/pymode/libs/astroid/tests/testdata/python2/data/recursion.py deleted file mode 100644 index 85f65134..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/recursion.py +++ /dev/null @@ -1,3 +0,0 @@ -""" For issue #25 """ -class Base(object): - pass \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python2/data/suppliermodule_test.py b/pymode/libs/astroid/tests/testdata/python2/data/suppliermodule_test.py deleted file mode 100644 index ddacb477..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/suppliermodule_test.py +++ /dev/null @@ -1,13 +0,0 @@ -""" file suppliermodule.py """ - -class NotImplemented(Exception): - pass - -class Interface: - def get_value(self): - raise NotImplemented() - - def set_value(self, value): - raise NotImplemented() - -class DoNothing : pass diff --git a/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/__init__.py deleted file mode 100644 index 713e5591..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/__init__.py +++ /dev/null @@ -1 +0,0 @@ -x = "șțîâ" \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg b/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg deleted file mode 100644 index f62599c7..00000000 Binary files a/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg and /dev/null differ diff --git a/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip b/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip deleted file mode 100644 index f62599c7..00000000 Binary files a/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip and /dev/null differ diff --git a/pymode/libs/astroid/tests/testdata/python3/data/SSL1/Connection1.py b/pymode/libs/astroid/tests/testdata/python3/data/SSL1/Connection1.py deleted file mode 100644 index 7373271d..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/SSL1/Connection1.py +++ /dev/null @@ -1,14 +0,0 @@ -"""M2Crypto.SSL.Connection - -Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" - -RCS_id='$Id: Connection1.py,v 1.1 2005-06-13 20:55:22 syt Exp $' - -#Some code deleted here - -class Connection: - - """An SSL connection.""" - - def __init__(self, ctx, sock=None): - print('init Connection') diff --git a/pymode/libs/astroid/tests/testdata/python3/data/SSL1/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/SSL1/__init__.py deleted file mode 100644 index c83ededc..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/SSL1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .Connection1 import Connection diff --git a/pymode/libs/astroid/tests/testdata/python3/data/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/__init__.py deleted file mode 100644 index 332e2e72..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $" diff --git a/pymode/libs/astroid/tests/testdata/python3/data/absimp/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/absimp/__init__.py deleted file mode 100644 index b98444df..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/absimp/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""a package with absolute import activated -""" - -from __future__ import absolute_import - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py deleted file mode 100644 index 239499a6..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""a side package with nothing in it -""" - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/absimp/string.py b/pymode/libs/astroid/tests/testdata/python3/data/absimp/string.py deleted file mode 100644 index e68e7496..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/absimp/string.py +++ /dev/null @@ -1,3 +0,0 @@ -from __future__ import absolute_import, print_function -import string -print(string) diff --git a/pymode/libs/astroid/tests/testdata/python3/data/absimport.py b/pymode/libs/astroid/tests/testdata/python3/data/absimport.py deleted file mode 100644 index 88f9d955..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/absimport.py +++ /dev/null @@ -1,3 +0,0 @@ - -import email -from email import message diff --git a/pymode/libs/astroid/tests/testdata/python3/data/all.py b/pymode/libs/astroid/tests/testdata/python3/data/all.py deleted file mode 100644 index 587765b5..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/all.py +++ /dev/null @@ -1,9 +0,0 @@ - -name = 'a' -_bla = 2 -other = 'o' -class Aaa: pass - -def func(): print('yo') - -__all__ = 'Aaa', '_bla', 'name' diff --git a/pymode/libs/astroid/tests/testdata/python3/data/appl/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/appl/__init__.py deleted file mode 100644 index d652ffd9..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/appl/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Init -""" diff --git a/pymode/libs/astroid/tests/testdata/python3/data/appl/myConnection.py b/pymode/libs/astroid/tests/testdata/python3/data/appl/myConnection.py deleted file mode 100644 index 49269534..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/appl/myConnection.py +++ /dev/null @@ -1,11 +0,0 @@ -from data import SSL1 -class MyConnection(SSL1.Connection): - - """An SSL connection.""" - - def __init__(self, dummy): - print('MyConnection init') - -if __name__ == '__main__': - myConnection = MyConnection(' ') - input('Press Enter to continue...') diff --git a/pymode/libs/astroid/tests/testdata/python3/data/clientmodule_test.py b/pymode/libs/astroid/tests/testdata/python3/data/clientmodule_test.py deleted file mode 100644 index a178ca6d..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/clientmodule_test.py +++ /dev/null @@ -1,32 +0,0 @@ -""" docstring for file clientmodule.py """ -from data.suppliermodule_test import Interface as IFace, DoNothing - -class Toto: pass - -class Ancestor: - """ Ancestor method """ - __implements__ = (IFace,) - - def __init__(self, value): - local_variable = 0 - self.attr = 'this method shouldn\'t have a docstring' - self.__value = value - - def get_value(self): - """ nice docstring ;-) """ - return self.__value - - def set_value(self, value): - self.__value = value - return 'this method shouldn\'t have a docstring' - -class Specialization(Ancestor): - TYPE = 'final class' - top = 'class' - - def __init__(self, value, _id): - Ancestor.__init__(self, value) - self._id = _id - self.relation = DoNothing() - self.toto = Toto() - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/descriptor_crash.py b/pymode/libs/astroid/tests/testdata/python3/data/descriptor_crash.py deleted file mode 100644 index 11fbb4a2..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/descriptor_crash.py +++ /dev/null @@ -1,11 +0,0 @@ - -import urllib - -class Page(object): - _urlOpen = staticmethod(urllib.urlopen) - - def getPage(self, url): - handle = self._urlOpen(url) - data = handle.read() - handle.close() - return data diff --git a/pymode/libs/astroid/tests/testdata/python3/data/email.py b/pymode/libs/astroid/tests/testdata/python3/data/email.py deleted file mode 100644 index dc593564..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/email.py +++ /dev/null @@ -1 +0,0 @@ -"""fake email module to test absolute import doesn't grab this one""" diff --git a/pymode/libs/astroid/tests/testdata/python3/data/find_test/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/find_test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python3/data/find_test/module.py b/pymode/libs/astroid/tests/testdata/python3/data/find_test/module.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python3/data/find_test/module2.py b/pymode/libs/astroid/tests/testdata/python3/data/find_test/module2.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python3/data/find_test/noendingnewline.py b/pymode/libs/astroid/tests/testdata/python3/data/find_test/noendingnewline.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python3/data/find_test/nonregr.py b/pymode/libs/astroid/tests/testdata/python3/data/find_test/nonregr.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python3/data/format.py b/pymode/libs/astroid/tests/testdata/python3/data/format.py deleted file mode 100644 index 73797061..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/format.py +++ /dev/null @@ -1,34 +0,0 @@ -"""A multiline string -""" - -function('aeozrijz\ -earzer', hop) -# XXX write test -x = [i for i in range(5) - if i % 4] - -fonction(1, - 2, - 3, - 4) - -def definition(a, - b, - c): - return a + b + c - -class debile(dict, - object): - pass - -if aaaa: pass -else: - aaaa,bbbb = 1,2 - aaaa,bbbb = bbbb,aaaa -# XXX write test -hop = \ - aaaa - - -__revision__.lower(); - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/joined_strings.py b/pymode/libs/astroid/tests/testdata/python3/data/joined_strings.py deleted file mode 100644 index 302e7cd7..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/joined_strings.py +++ /dev/null @@ -1,1051 +0,0 @@ -x = ('R0lGODlhigJnAef/AAABAAEEAAkCAAMGAg0GBAYJBQoMCBMODQ4QDRITEBkS' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7' - +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp' - +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA' - +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7') \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python3/data/lmfp/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/lmfp/__init__.py deleted file mode 100644 index 74b26b82..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/lmfp/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# force a "direct" python import -from . import foo diff --git a/pymode/libs/astroid/tests/testdata/python3/data/lmfp/foo.py b/pymode/libs/astroid/tests/testdata/python3/data/lmfp/foo.py deleted file mode 100644 index 8f7de1e8..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/lmfp/foo.py +++ /dev/null @@ -1,6 +0,0 @@ -import sys -if not getattr(sys, 'bar', None): - sys.just_once = [] -# there used to be two numbers here because -# of a load_module_from_path bug -sys.just_once.append(42) diff --git a/pymode/libs/astroid/tests/testdata/python3/data/module.py b/pymode/libs/astroid/tests/testdata/python3/data/module.py deleted file mode 100644 index 2a5fb58c..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/module.py +++ /dev/null @@ -1,88 +0,0 @@ -"""test module for astroid -""" - -__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $' -from astroid.node_classes import Name as NameNode -from astroid import modutils -from astroid.utils import * -import os.path -MY_DICT = {} - -def global_access(key, val): - """function test""" - local = 1 - MY_DICT[key] = val - for i in val: - if i: - del MY_DICT[i] - continue - else: - break - else: - return - - -class YO: - """hehe""" - a = 1 - - def __init__(self): - try: - self.yo = 1 - except ValueError as ex: - pass - except (NameError, TypeError): - raise XXXError() - except: - raise - - - -class YOUPI(YO): - class_attr = None - - def __init__(self): - self.member = None - - def method(self): - """method test""" - global MY_DICT - try: - MY_DICT = {} - local = None - autre = [a for (a, b) in MY_DICT if b] - if b in autre: - return - else: - if a in autre: - return 'hehe' - global_access(local, val=autre) - finally: - return local - - def static_method(): - """static method test""" - assert MY_DICT, '???' - static_method = staticmethod(static_method) - - def class_method(cls): - """class method test""" - exec(a, b) - class_method = classmethod(class_method) - - -def four_args(a, b, c, d): - """four arguments (was nested_args)""" - while 1: - if a: - break - a += +1 - else: - b += -2 - if c: - d = ((a) and (b)) or (c) - else: - c = ((a) and (b)) or (d) - list(map(lambda x, y: (y, x), a)) -redirect = four_args - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/module1abs/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/module1abs/__init__.py deleted file mode 100644 index f9d5b686..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/module1abs/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ - -from . import core -from .core import * -print(sys.version) diff --git a/pymode/libs/astroid/tests/testdata/python3/data/module1abs/core.py b/pymode/libs/astroid/tests/testdata/python3/data/module1abs/core.py deleted file mode 100644 index de101117..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/module1abs/core.py +++ /dev/null @@ -1 +0,0 @@ -import sys diff --git a/pymode/libs/astroid/tests/testdata/python3/data/module2.py b/pymode/libs/astroid/tests/testdata/python3/data/module2.py deleted file mode 100644 index 1171bdfe..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/module2.py +++ /dev/null @@ -1,143 +0,0 @@ -from data.module import YO, YOUPI -import data - - -class Specialization(YOUPI, YO): - pass - - - -class Metaclass(type): - pass - - - -class Interface: - pass - - - -class MyIFace(Interface): - pass - - - -class AnotherIFace(Interface): - pass - - - -class MyException(Exception): - pass - - - -class MyError(MyException): - pass - - - -class AbstractClass(object): - - def to_override(self, whatever): - raise NotImplementedError() - - def return_something(self, param): - if param: - return 'toto' - return - - - -class Concrete0: - __implements__ = MyIFace - - - -class Concrete1: - __implements__ = (MyIFace, AnotherIFace) - - - -class Concrete2: - __implements__ = (MyIFace, AnotherIFace) - - - -class Concrete23(Concrete1): - pass - -del YO.member -del YO -[SYN1, SYN2] = (Concrete0, Concrete1) -assert repr(1) -b = (1) | (((2) & (3)) ^ (8)) -bb = ((1) | (two)) | (6) -ccc = ((one) & (two)) & (three) -dddd = ((x) ^ (o)) ^ (r) -exec('c = 3') -exec('c = 3', {}, {}) - -def raise_string(a=2, *args, **kwargs): - raise Exception('yo') - yield 'coucou' - yield -a = (b) + (2) -c = (b) * (2) -c = (b) / (2) -c = (b) // (2) -c = (b) - (2) -c = (b) % (2) -c = (b) ** (2) -c = (b) << (2) -c = (b) >> (2) -c = ~b -c = not b -d = [c] -e = d[:] -e = d[a:b:c] -raise_string(*args, **kwargs) -print('bonjour', file=stream) -print('salut', end=' ', file=stream) - -def make_class(any, base=data.module.YO, *args, **kwargs): - """check base is correctly resolved to Concrete0""" - - - class Aaaa(base): - """dynamic class""" - - - return Aaaa -from os.path import abspath -import os as myos - - -class A: - pass - - - -class A(A): - pass - - -def generator(): - """A generator.""" - yield - -def not_a_generator(): - """A function that contains generator, but is not one.""" - - def generator(): - yield - genl = lambda : (yield) - -def with_metaclass(meta, *bases): - return meta('NewBase', bases, {}) - - -class NotMetaclass(with_metaclass(Metaclass)): - pass - - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/noendingnewline.py b/pymode/libs/astroid/tests/testdata/python3/data/noendingnewline.py deleted file mode 100644 index e17b92cc..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/noendingnewline.py +++ /dev/null @@ -1,36 +0,0 @@ -import unittest - - -class TestCase(unittest.TestCase): - - def setUp(self): - unittest.TestCase.setUp(self) - - - def tearDown(self): - unittest.TestCase.tearDown(self) - - def testIt(self): - self.a = 10 - self.xxx() - - - def xxx(self): - if False: - pass - print('a') - - if False: - pass - pass - - if False: - pass - print('rara') - - -if __name__ == '__main__': - print('test2') - unittest.main() - - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/nonregr.py b/pymode/libs/astroid/tests/testdata/python3/data/nonregr.py deleted file mode 100644 index 78765c85..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/nonregr.py +++ /dev/null @@ -1,57 +0,0 @@ - - -try: - enumerate = enumerate -except NameError: - - def enumerate(iterable): - """emulates the python2.3 enumerate() function""" - i = 0 - for val in iterable: - yield i, val - i += 1 - -def toto(value): - for k, v in value: - print(v.get('yo')) - - -import imp -fp, mpath, desc = imp.find_module('optparse',a) -s_opt = imp.load_module('std_optparse', fp, mpath, desc) - -class OptionParser(s_opt.OptionParser): - - def parse_args(self, args=None, values=None, real_optparse=False): - if real_optparse: - pass -## return super(OptionParser, self).parse_args() - else: - import optcomp - optcomp.completion(self) - - -class Aaa(object): - """docstring""" - def __init__(self): - self.__setattr__('a','b') - pass - - def one_public(self): - """docstring""" - pass - - def another_public(self): - """docstring""" - pass - -class Ccc(Aaa): - """docstring""" - - class Ddd(Aaa): - """docstring""" - pass - - class Eee(Ddd): - """docstring""" - pass diff --git a/pymode/libs/astroid/tests/testdata/python3/data/notall.py b/pymode/libs/astroid/tests/testdata/python3/data/notall.py deleted file mode 100644 index 9d35aa3a..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/notall.py +++ /dev/null @@ -1,8 +0,0 @@ - -name = 'a' -_bla = 2 -other = 'o' -class Aaa: pass - -def func(): print('yo') - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/package/__init__.py deleted file mode 100644 index 575d18b1..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""package's __init__ file""" - - -from . import subpackage diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/absimport.py b/pymode/libs/astroid/tests/testdata/python3/data/package/absimport.py deleted file mode 100644 index 33ed117c..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/absimport.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import absolute_import, print_function -import import_package_subpackage_module # fail -print(import_package_subpackage_module) - -from . import hello as hola - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/hello.py b/pymode/libs/astroid/tests/testdata/python3/data/package/hello.py deleted file mode 100644 index b154c844..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/hello.py +++ /dev/null @@ -1,2 +0,0 @@ -"""hello module""" - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py b/pymode/libs/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py deleted file mode 100644 index ad442c16..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py +++ /dev/null @@ -1,49 +0,0 @@ -# pylint: disable-msg=I0011,C0301,W0611 -"""I found some of my scripts trigger off an AttributeError in pylint -0.8.1 (with common 0.12.0 and astroid 0.13.1). - -Traceback (most recent call last): - File "/usr/bin/pylint", line 4, in ? - lint.Run(sys.argv[1:]) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__ - linter.check(args) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check - self.check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file - astroid = self._check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file - self.check_astroid_module(astroid, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module - self.astroid_events(astroid, [checker for checker in checkers - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events - checker.visit(astroid) - File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit - method(node) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import - self._check_module_attrs(node, module, name_parts[1:]) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs - self.add_message('E0611', args=(name, module.name), -AttributeError: Import instance has no attribute 'name' - - -You can reproduce it by: -(1) create package structure like the following: - -package/ - __init__.py - subpackage/ - __init__.py - module.py - -(2) in package/__init__.py write: - -import subpackage - -(3) run pylint with a script importing package.subpackage.module. -""" -__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $' -import package.subpackage.module diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/__init__.py deleted file mode 100644 index dc4782e6..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage""" diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/module.py b/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/module.py deleted file mode 100644 index 4b7244ba..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/module.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage.module""" diff --git a/pymode/libs/astroid/tests/testdata/python3/data/recursion.py b/pymode/libs/astroid/tests/testdata/python3/data/recursion.py deleted file mode 100644 index 85f65134..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/recursion.py +++ /dev/null @@ -1,3 +0,0 @@ -""" For issue #25 """ -class Base(object): - pass \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python3/data/suppliermodule_test.py b/pymode/libs/astroid/tests/testdata/python3/data/suppliermodule_test.py deleted file mode 100644 index ddacb477..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/suppliermodule_test.py +++ /dev/null @@ -1,13 +0,0 @@ -""" file suppliermodule.py """ - -class NotImplemented(Exception): - pass - -class Interface: - def get_value(self): - raise NotImplemented() - - def set_value(self, value): - raise NotImplemented() - -class DoNothing : pass diff --git a/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/__init__.py deleted file mode 100644 index 713e5591..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/__init__.py +++ /dev/null @@ -1 +0,0 @@ -x = "șțîâ" \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/unittest_brain.py b/pymode/libs/astroid/tests/unittest_brain.py deleted file mode 100644 index 9dbbe1d0..00000000 --- a/pymode/libs/astroid/tests/unittest_brain.py +++ /dev/null @@ -1,506 +0,0 @@ -# Copyright 2013 Google Inc. All Rights Reserved. -# -# This file is part of astroid. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see . -"""Tests for basic functionality in astroid.brain.""" -import sys -import unittest - -import six - -from astroid import MANAGER -from astroid import bases -from astroid import builder -from astroid import nodes -from astroid import test_utils -from astroid import util -import astroid - - -try: - import nose # pylint: disable=unused-import - HAS_NOSE = True -except ImportError: - HAS_NOSE = False - -try: - import multiprocessing # pylint: disable=unused-import - HAS_MULTIPROCESSING = True -except ImportError: - HAS_MULTIPROCESSING = False - -try: - import enum # pylint: disable=unused-import - HAS_ENUM = True -except ImportError: - HAS_ENUM = False - -try: - import dateutil # pylint: disable=unused-import - HAS_DATEUTIL = True -except ImportError: - HAS_DATEUTIL = False - -try: - import numpy # pylint: disable=unused-import - HAS_NUMPY = True -except ImportError: - HAS_NUMPY = False - -try: - import pytest # pylint: disable=unused-import - HAS_PYTEST = True -except ImportError: - HAS_PYTEST = False - - -class HashlibTest(unittest.TestCase): - def test_hashlib(self): - """Tests that brain extensions for hashlib work.""" - hashlib_module = MANAGER.ast_from_module_name('hashlib') - for class_name in ['md5', 'sha1']: - class_obj = hashlib_module[class_name] - self.assertIn('update', class_obj) - self.assertIn('digest', class_obj) - self.assertIn('hexdigest', class_obj) - self.assertIn('block_size', class_obj) - self.assertIn('digest_size', class_obj) - self.assertEqual(len(class_obj['__init__'].args.args), 2) - self.assertEqual(len(class_obj['__init__'].args.defaults), 1) - self.assertEqual(len(class_obj['update'].args.args), 2) - self.assertEqual(len(class_obj['digest'].args.args), 1) - self.assertEqual(len(class_obj['hexdigest'].args.args), 1) - - -class NamedTupleTest(unittest.TestCase): - - def test_namedtuple_base(self): - klass = test_utils.extract_node(""" - from collections import namedtuple - - class X(namedtuple("X", ["a", "b", "c"])): - pass - """) - self.assertEqual( - [anc.name for anc in klass.ancestors()], - ['X', 'tuple', 'object']) - for anc in klass.ancestors(): - self.assertFalse(anc.parent is None) - - def test_namedtuple_inference(self): - klass = test_utils.extract_node(""" - from collections import namedtuple - - name = "X" - fields = ["a", "b", "c"] - class X(namedtuple(name, fields)): - pass - """) - for base in klass.ancestors(): - if base.name == 'X': - break - self.assertSetEqual({"a", "b", "c"}, set(base._instance_attrs)) - - def test_namedtuple_inference_failure(self): - klass = test_utils.extract_node(""" - from collections import namedtuple - - def foo(fields): - return __(namedtuple("foo", fields)) - """) - self.assertIs(util.YES, next(klass.infer())) - - @unittest.skipIf(sys.version_info[0] > 2, - 'namedtuple inference is broken on Python 3') - def test_namedtuple_advanced_inference(self): - # urlparse return an object of class ParseResult, which has a - # namedtuple call and a mixin as base classes - result = test_utils.extract_node(""" - import urlparse - - result = __(urlparse.urlparse('gopher://')) - """) - instance = next(result.infer()) - self.assertEqual(len(instance.getattr('scheme')), 1) - self.assertEqual(len(instance.getattr('port')), 1) - with self.assertRaises(astroid.NotFoundError): - instance.getattr('foo') - self.assertEqual(len(instance.getattr('geturl')), 1) - self.assertEqual(instance.name, 'ParseResult') - - def test_namedtuple_instance_attrs(self): - result = test_utils.extract_node(''' - from collections import namedtuple - namedtuple('a', 'a b c')(1, 2, 3) #@ - ''') - inferred = next(result.infer()) - for name, attr in inferred._instance_attrs.items(): - self.assertEqual(attr[0].attrname, name) - - def test_namedtuple_uninferable_fields(self): - node = test_utils.extract_node(''' - x = [A] * 2 - from collections import namedtuple - l = namedtuple('a', x) - l(1) - ''') - inferred = next(node.infer()) - self.assertIs(util.YES, inferred) - - -class ModuleExtenderTest(unittest.TestCase): - def testExtensionModules(self): - transformer = MANAGER._transform - for extender, _ in transformer.transforms[nodes.Module]: - n = nodes.Module('__main__', None) - extender(n) - - -@unittest.skipUnless(HAS_NOSE, "This test requires nose library.") -class NoseBrainTest(unittest.TestCase): - - def test_nose_tools(self): - methods = test_utils.extract_node(""" - from nose.tools import assert_equal - from nose.tools import assert_equals - from nose.tools import assert_true - assert_equal = assert_equal #@ - assert_true = assert_true #@ - assert_equals = assert_equals #@ - """) - assert_equal = next(methods[0].value.infer()) - assert_true = next(methods[1].value.infer()) - assert_equals = next(methods[2].value.infer()) - - self.assertIsInstance(assert_equal, astroid.BoundMethod) - self.assertIsInstance(assert_true, astroid.BoundMethod) - self.assertIsInstance(assert_equals, astroid.BoundMethod) - self.assertEqual(assert_equal.qname(), - 'unittest.case.TestCase.assertEqual') - self.assertEqual(assert_true.qname(), - 'unittest.case.TestCase.assertTrue') - self.assertEqual(assert_equals.qname(), - 'unittest.case.TestCase.assertEqual') - - -class SixBrainTest(unittest.TestCase): - - def test_attribute_access(self): - ast_nodes = test_utils.extract_node(''' - import six - six.moves.http_client #@ - six.moves.urllib_parse #@ - six.moves.urllib_error #@ - six.moves.urllib.request #@ - ''') - http_client = next(ast_nodes[0].infer()) - self.assertIsInstance(http_client, nodes.Module) - self.assertEqual(http_client.name, - 'http.client' if six.PY3 else 'httplib') - - urllib_parse = next(ast_nodes[1].infer()) - if six.PY3: - self.assertIsInstance(urllib_parse, nodes.Module) - self.assertEqual(urllib_parse.name, 'urllib.parse') - else: - # On Python 2, this is a fake module, the same behaviour - # being mimicked in brain's tip for six.moves. - self.assertIsInstance(urllib_parse, astroid.Instance) - urljoin = next(urllib_parse.igetattr('urljoin')) - urlencode = next(urllib_parse.igetattr('urlencode')) - if six.PY2: - # In reality it's a function, but our implementations - # transforms it into a method. - self.assertIsInstance(urljoin, astroid.BoundMethod) - self.assertEqual(urljoin.qname(), 'urlparse.urljoin') - self.assertIsInstance(urlencode, astroid.BoundMethod) - self.assertEqual(urlencode.qname(), 'urllib.urlencode') - else: - self.assertIsInstance(urljoin, nodes.FunctionDef) - self.assertEqual(urljoin.qname(), 'urllib.parse.urljoin') - self.assertIsInstance(urlencode, nodes.FunctionDef) - self.assertEqual(urlencode.qname(), 'urllib.parse.urlencode') - - urllib_error = next(ast_nodes[2].infer()) - if six.PY3: - self.assertIsInstance(urllib_error, nodes.Module) - self.assertEqual(urllib_error.name, 'urllib.error') - else: - # On Python 2, this is a fake module, the same behaviour - # being mimicked in brain's tip for six.moves. - self.assertIsInstance(urllib_error, astroid.Instance) - urlerror = next(urllib_error.igetattr('URLError')) - self.assertIsInstance(urlerror, nodes.ClassDef) - content_too_short = next(urllib_error.igetattr('ContentTooShortError')) - self.assertIsInstance(content_too_short, nodes.ClassDef) - - urllib_request = next(ast_nodes[3].infer()) - if six.PY3: - self.assertIsInstance(urllib_request, nodes.Module) - self.assertEqual(urllib_request.name, 'urllib.request') - else: - self.assertIsInstance(urllib_request, astroid.Instance) - urlopen = next(urllib_request.igetattr('urlopen')) - urlretrieve = next(urllib_request.igetattr('urlretrieve')) - if six.PY2: - # In reality it's a function, but our implementations - # transforms it into a method. - self.assertIsInstance(urlopen, astroid.BoundMethod) - self.assertEqual(urlopen.qname(), 'urllib2.urlopen') - self.assertIsInstance(urlretrieve, astroid.BoundMethod) - self.assertEqual(urlretrieve.qname(), 'urllib.urlretrieve') - else: - self.assertIsInstance(urlopen, nodes.FunctionDef) - self.assertEqual(urlopen.qname(), 'urllib.request.urlopen') - self.assertIsInstance(urlretrieve, nodes.FunctionDef) - self.assertEqual(urlretrieve.qname(), 'urllib.request.urlretrieve') - - def test_from_imports(self): - ast_node = test_utils.extract_node(''' - from six.moves import http_client - http_client.HTTPSConnection #@ - ''') - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, nodes.ClassDef) - if six.PY3: - qname = 'http.client.HTTPSConnection' - else: - qname = 'httplib.HTTPSConnection' - self.assertEqual(inferred.qname(), qname) - - -@unittest.skipUnless(HAS_MULTIPROCESSING, - 'multiprocesing is required for this test, but ' - 'on some platforms it is missing ' - '(Jython for instance)') -class MultiprocessingBrainTest(unittest.TestCase): - - def test_multiprocessing_module_attributes(self): - # Test that module attributes are working, - # especially on Python 3.4+, where they are obtained - # from a context. - module = test_utils.extract_node(""" - import multiprocessing - """) - module = module.do_import_module('multiprocessing') - cpu_count = next(module.igetattr('cpu_count')) - if sys.version_info < (3, 4): - self.assertIsInstance(cpu_count, nodes.FunctionDef) - else: - self.assertIsInstance(cpu_count, astroid.BoundMethod) - - def test_module_name(self): - module = test_utils.extract_node(""" - import multiprocessing - multiprocessing.SyncManager() - """) - inferred_sync_mgr = next(module.infer()) - module = inferred_sync_mgr.root() - self.assertEqual(module.name, 'multiprocessing.managers') - - def test_multiprocessing_manager(self): - # Test that we have the proper attributes - # for a multiprocessing.managers.SyncManager - module = builder.parse(""" - import multiprocessing - manager = multiprocessing.Manager() - queue = manager.Queue() - joinable_queue = manager.JoinableQueue() - event = manager.Event() - rlock = manager.RLock() - bounded_semaphore = manager.BoundedSemaphore() - condition = manager.Condition() - barrier = manager.Barrier() - pool = manager.Pool() - list = manager.list() - dict = manager.dict() - value = manager.Value() - array = manager.Array() - namespace = manager.Namespace() - """) - queue = next(module['queue'].infer()) - self.assertEqual(queue.qname(), - "{}.Queue".format(six.moves.queue.__name__)) - - joinable_queue = next(module['joinable_queue'].infer()) - self.assertEqual(joinable_queue.qname(), - "{}.Queue".format(six.moves.queue.__name__)) - - event = next(module['event'].infer()) - event_name = "threading.{}".format("Event" if six.PY3 else "_Event") - self.assertEqual(event.qname(), event_name) - - rlock = next(module['rlock'].infer()) - rlock_name = "threading._RLock" - self.assertEqual(rlock.qname(), rlock_name) - - bounded_semaphore = next(module['bounded_semaphore'].infer()) - semaphore_name = "threading.{}".format( - "BoundedSemaphore" if six.PY3 else "_BoundedSemaphore") - self.assertEqual(bounded_semaphore.qname(), semaphore_name) - - pool = next(module['pool'].infer()) - pool_name = "multiprocessing.pool.Pool" - self.assertEqual(pool.qname(), pool_name) - - for attr in ('list', 'dict'): - obj = next(module[attr].infer()) - self.assertEqual(obj.qname(), - "{}.{}".format(bases.BUILTINS, attr)) - - array = next(module['array'].infer()) - self.assertEqual(array.qname(), "array.array") - - manager = next(module['manager'].infer()) - # Verify that we have these attributes - self.assertTrue(manager.getattr('start')) - self.assertTrue(manager.getattr('shutdown')) - - -@unittest.skipUnless(HAS_ENUM, - 'The enum module was only added in Python 3.4. Support for ' - 'older Python versions may be available through the enum34 ' - 'compatibility module.') -class EnumBrainTest(unittest.TestCase): - - def test_simple_enum(self): - module = builder.parse(""" - import enum - - class MyEnum(enum.Enum): - one = "one" - two = "two" - - def mymethod(self, x): - return 5 - - """) - - enum = next(module['MyEnum'].infer()) - one = enum['one'] - self.assertEqual(one.pytype(), '.MyEnum.one') - - property_type = '{}.property'.format(bases.BUILTINS) - for propname in ('name', 'value'): - prop = next(iter(one.getattr(propname))) - self.assertIn(property_type, prop.decoratornames()) - - meth = one.getattr('mymethod')[0] - self.assertIsInstance(meth, astroid.FunctionDef) - - def test_looks_like_enum_false_positive(self): - # Test that a class named Enumeration is not considered a builtin enum. - module = builder.parse(''' - class Enumeration(object): - def __init__(self, name, enum_list): - pass - test = 42 - ''') - enum = module['Enumeration'] - test = next(enum.igetattr('test')) - self.assertEqual(test.value, 42) - - def test_enum_multiple_base_classes(self): - module = builder.parse(""" - import enum - - class Mixin: - pass - - class MyEnum(Mixin, enum.Enum): - one = 1 - """) - enum = next(module['MyEnum'].infer()) - one = enum['one'] - - clazz = one.getattr('__class__')[0] - self.assertTrue(clazz.is_subtype_of('.Mixin'), - 'Enum instance should share base classes with generating class') - - def test_int_enum(self): - module = builder.parse(""" - import enum - - class MyEnum(enum.IntEnum): - one = 1 - """) - - enum = next(module['MyEnum'].infer()) - one = enum['one'] - - clazz = one.getattr('__class__')[0] - int_type = '{}.{}'.format(bases.BUILTINS, 'int') - self.assertTrue(clazz.is_subtype_of(int_type), - 'IntEnum based enums should be a subtype of int') - - def test_enum_func_form_is_class_not_instance(self): - cls, instance = test_utils.extract_node(''' - from enum import Enum - f = Enum('Audience', ['a', 'b', 'c']) - f #@ - f(1) #@ - ''') - inferred_cls = next(cls.infer()) - self.assertIsInstance(inferred_cls, bases.Instance) - inferred_instance = next(instance.infer()) - self.assertIsInstance(inferred_instance, bases.Instance) - self.assertIsInstance(next(inferred_instance.igetattr('name')), nodes.Const) - self.assertIsInstance(next(inferred_instance.igetattr('value')), nodes.Const) - - -@unittest.skipUnless(HAS_DATEUTIL, "This test requires the dateutil library.") -class DateutilBrainTest(unittest.TestCase): - def test_parser(self): - module = builder.parse(""" - from dateutil.parser import parse - d = parse('2000-01-01') - """) - d_type = next(module['d'].infer()) - self.assertEqual(d_type.qname(), "datetime.datetime") - - -@unittest.skipUnless(HAS_NUMPY, "This test requires the numpy library.") -class NumpyBrainTest(unittest.TestCase): - - def test_numpy(self): - node = test_utils.extract_node(''' - import numpy - numpy.ones #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.FunctionDef) - - -@unittest.skipUnless(HAS_PYTEST, "This test requires the pytest library.") -class PytestBrainTest(unittest.TestCase): - - def test_pytest(self): - ast_node = test_utils.extract_node(''' - import pytest - pytest #@ - ''') - module = next(ast_node.infer()) - attrs = ['deprecated_call', 'warns', 'exit', 'fail', 'skip', - 'importorskip', 'xfail', 'mark', 'raises', 'freeze_includes', - 'set_trace', 'fixture', 'yield_fixture'] - if pytest.__version__.split('.')[0] == '3': - attrs += ['approx', 'register_assert_rewrite'] - - for attr in attrs: - self.assertIn(attr, module) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_builder.py b/pymode/libs/astroid/tests/unittest_builder.py deleted file mode 100644 index 920f36e8..00000000 --- a/pymode/libs/astroid/tests/unittest_builder.py +++ /dev/null @@ -1,774 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""tests for the astroid builder and rebuilder module""" - -import os -import sys -import unittest - -import six - -from astroid import builder -from astroid import exceptions -from astroid import manager -from astroid import nodes -from astroid import test_utils -from astroid import util -from astroid.tests import resources - -MANAGER = manager.AstroidManager() -BUILTINS = six.moves.builtins.__name__ - - -class FromToLineNoTest(unittest.TestCase): - - def setUp(self): - self.astroid = resources.build_file('data/format.py') - - def test_callfunc_lineno(self): - stmts = self.astroid.body - # on line 4: - # function('aeozrijz\ - # earzer', hop) - discard = stmts[0] - self.assertIsInstance(discard, nodes.Expr) - self.assertEqual(discard.fromlineno, 4) - self.assertEqual(discard.tolineno, 5) - callfunc = discard.value - self.assertIsInstance(callfunc, nodes.Call) - self.assertEqual(callfunc.fromlineno, 4) - self.assertEqual(callfunc.tolineno, 5) - name = callfunc.func - self.assertIsInstance(name, nodes.Name) - self.assertEqual(name.fromlineno, 4) - self.assertEqual(name.tolineno, 4) - strarg = callfunc.args[0] - self.assertIsInstance(strarg, nodes.Const) - if hasattr(sys, 'pypy_version_info'): - lineno = 4 - else: - lineno = 5 # no way for this one in CPython (is 4 actually) - self.assertEqual(strarg.fromlineno, lineno) - self.assertEqual(strarg.tolineno, lineno) - namearg = callfunc.args[1] - self.assertIsInstance(namearg, nodes.Name) - self.assertEqual(namearg.fromlineno, 5) - self.assertEqual(namearg.tolineno, 5) - # on line 10: - # fonction(1, - # 2, - # 3, - # 4) - discard = stmts[2] - self.assertIsInstance(discard, nodes.Expr) - self.assertEqual(discard.fromlineno, 10) - self.assertEqual(discard.tolineno, 13) - callfunc = discard.value - self.assertIsInstance(callfunc, nodes.Call) - self.assertEqual(callfunc.fromlineno, 10) - self.assertEqual(callfunc.tolineno, 13) - name = callfunc.func - self.assertIsInstance(name, nodes.Name) - self.assertEqual(name.fromlineno, 10) - self.assertEqual(name.tolineno, 10) - for i, arg in enumerate(callfunc.args): - self.assertIsInstance(arg, nodes.Const) - self.assertEqual(arg.fromlineno, 10+i) - self.assertEqual(arg.tolineno, 10+i) - - def test_function_lineno(self): - stmts = self.astroid.body - # on line 15: - # def definition(a, - # b, - # c): - # return a + b + c - function = stmts[3] - self.assertIsInstance(function, nodes.FunctionDef) - self.assertEqual(function.fromlineno, 15) - self.assertEqual(function.tolineno, 18) - return_ = function.body[0] - self.assertIsInstance(return_, nodes.Return) - self.assertEqual(return_.fromlineno, 18) - self.assertEqual(return_.tolineno, 18) - if sys.version_info < (3, 0): - self.assertEqual(function.blockstart_tolineno, 17) - else: - self.skipTest('FIXME http://bugs.python.org/issue10445 ' - '(no line number on function args)') - - def test_decorated_function_lineno(self): - astroid = builder.parse(''' - @decorator - def function( - arg): - print (arg) - ''', __name__) - function = astroid['function'] - self.assertEqual(function.fromlineno, 3) # XXX discussable, but that's what is expected by pylint right now - self.assertEqual(function.tolineno, 5) - self.assertEqual(function.decorators.fromlineno, 2) - self.assertEqual(function.decorators.tolineno, 2) - if sys.version_info < (3, 0): - self.assertEqual(function.blockstart_tolineno, 4) - else: - self.skipTest('FIXME http://bugs.python.org/issue10445 ' - '(no line number on function args)') - - - def test_class_lineno(self): - stmts = self.astroid.body - # on line 20: - # class debile(dict, - # object): - # pass - class_ = stmts[4] - self.assertIsInstance(class_, nodes.ClassDef) - self.assertEqual(class_.fromlineno, 20) - self.assertEqual(class_.tolineno, 22) - self.assertEqual(class_.blockstart_tolineno, 21) - pass_ = class_.body[0] - self.assertIsInstance(pass_, nodes.Pass) - self.assertEqual(pass_.fromlineno, 22) - self.assertEqual(pass_.tolineno, 22) - - def test_if_lineno(self): - stmts = self.astroid.body - # on line 20: - # if aaaa: pass - # else: - # aaaa,bbbb = 1,2 - # aaaa,bbbb = bbbb,aaaa - if_ = stmts[5] - self.assertIsInstance(if_, nodes.If) - self.assertEqual(if_.fromlineno, 24) - self.assertEqual(if_.tolineno, 27) - self.assertEqual(if_.blockstart_tolineno, 24) - self.assertEqual(if_.orelse[0].fromlineno, 26) - self.assertEqual(if_.orelse[1].tolineno, 27) - - def test_for_while_lineno(self): - for code in (''' - for a in range(4): - print (a) - break - else: - print ("bouh") - ''', ''' - while a: - print (a) - break - else: - print ("bouh") - '''): - astroid = builder.parse(code, __name__) - stmt = astroid.body[0] - self.assertEqual(stmt.fromlineno, 2) - self.assertEqual(stmt.tolineno, 6) - self.assertEqual(stmt.blockstart_tolineno, 2) - self.assertEqual(stmt.orelse[0].fromlineno, 6) # XXX - self.assertEqual(stmt.orelse[0].tolineno, 6) - - def test_try_except_lineno(self): - astroid = builder.parse(''' - try: - print (a) - except: - pass - else: - print ("bouh") - ''', __name__) - try_ = astroid.body[0] - self.assertEqual(try_.fromlineno, 2) - self.assertEqual(try_.tolineno, 7) - self.assertEqual(try_.blockstart_tolineno, 2) - self.assertEqual(try_.orelse[0].fromlineno, 7) # XXX - self.assertEqual(try_.orelse[0].tolineno, 7) - hdlr = try_.handlers[0] - self.assertEqual(hdlr.fromlineno, 4) - self.assertEqual(hdlr.tolineno, 5) - self.assertEqual(hdlr.blockstart_tolineno, 4) - - - def test_try_finally_lineno(self): - astroid = builder.parse(''' - try: - print (a) - finally: - print ("bouh") - ''', __name__) - try_ = astroid.body[0] - self.assertEqual(try_.fromlineno, 2) - self.assertEqual(try_.tolineno, 5) - self.assertEqual(try_.blockstart_tolineno, 2) - self.assertEqual(try_.finalbody[0].fromlineno, 5) # XXX - self.assertEqual(try_.finalbody[0].tolineno, 5) - - - def test_try_finally_25_lineno(self): - astroid = builder.parse(''' - try: - print (a) - except: - pass - finally: - print ("bouh") - ''', __name__) - try_ = astroid.body[0] - self.assertEqual(try_.fromlineno, 2) - self.assertEqual(try_.tolineno, 7) - self.assertEqual(try_.blockstart_tolineno, 2) - self.assertEqual(try_.finalbody[0].fromlineno, 7) # XXX - self.assertEqual(try_.finalbody[0].tolineno, 7) - - - def test_with_lineno(self): - astroid = builder.parse(''' - from __future__ import with_statement - with file("/tmp/pouet") as f: - print (f) - ''', __name__) - with_ = astroid.body[1] - self.assertEqual(with_.fromlineno, 3) - self.assertEqual(with_.tolineno, 4) - self.assertEqual(with_.blockstart_tolineno, 3) - - -class BuilderTest(unittest.TestCase): - - def setUp(self): - self.builder = builder.AstroidBuilder() - - def test_data_build_null_bytes(self): - with self.assertRaises(exceptions.AstroidBuildingException): - self.builder.string_build('\x00') - - def test_data_build_invalid_x_escape(self): - with self.assertRaises(exceptions.AstroidBuildingException): - self.builder.string_build('"\\x1"') - - def test_missing_newline(self): - """check that a file with no trailing new line is parseable""" - resources.build_file('data/noendingnewline.py') - - def test_missing_file(self): - with self.assertRaises(exceptions.AstroidBuildingException): - resources.build_file('data/inexistant.py') - - def test_inspect_build0(self): - """test astroid tree build from a living object""" - builtin_ast = MANAGER.ast_from_module_name(BUILTINS) - if six.PY2: - fclass = builtin_ast['file'] - self.assertIn('name', fclass) - self.assertIn('mode', fclass) - self.assertIn('read', fclass) - self.assertTrue(fclass.newstyle) - self.assertTrue(fclass.pytype(), '%s.type' % BUILTINS) - self.assertIsInstance(fclass['read'], nodes.FunctionDef) - # check builtin function has args.args == None - dclass = builtin_ast['dict'] - self.assertIsNone(dclass['has_key'].args.args) - # just check type and object are there - builtin_ast.getattr('type') - objectastroid = builtin_ast.getattr('object')[0] - self.assertIsInstance(objectastroid.getattr('__new__')[0], nodes.FunctionDef) - # check open file alias - builtin_ast.getattr('open') - # check 'help' is there (defined dynamically by site.py) - builtin_ast.getattr('help') - # check property has __init__ - pclass = builtin_ast['property'] - self.assertIn('__init__', pclass) - self.assertIsInstance(builtin_ast['None'], nodes.Const) - self.assertIsInstance(builtin_ast['True'], nodes.Const) - self.assertIsInstance(builtin_ast['False'], nodes.Const) - if six.PY3: - self.assertIsInstance(builtin_ast['Exception'], nodes.ClassDef) - self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ClassDef) - else: - self.assertIsInstance(builtin_ast['Exception'], nodes.ImportFrom) - self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ImportFrom) - - def test_inspect_build1(self): - time_ast = MANAGER.ast_from_module_name('time') - self.assertTrue(time_ast) - self.assertEqual(time_ast['time'].args.defaults, []) - - if os.name == 'java': - test_inspect_build1 = unittest.expectedFailure(test_inspect_build1) - - def test_inspect_build2(self): - """test astroid tree build from a living object""" - try: - from mx import DateTime - except ImportError: - self.skipTest('test skipped: mxDateTime is not available') - else: - dt_ast = self.builder.inspect_build(DateTime) - dt_ast.getattr('DateTime') - # this one is failing since DateTimeType.__module__ = 'builtins' ! - #dt_ast.getattr('DateTimeType') - - def test_inspect_build3(self): - self.builder.inspect_build(unittest) - - @test_utils.require_version(maxver='3.0') - def test_inspect_build_instance(self): - """test astroid tree build from a living object""" - import exceptions - builtin_ast = self.builder.inspect_build(exceptions) - fclass = builtin_ast['OSError'] - # things like OSError.strerror are now (2.5) data descriptors on the - # class instead of entries in the __dict__ of an instance - container = fclass - self.assertIn('errno', container) - self.assertIn('strerror', container) - self.assertIn('filename', container) - - def test_inspect_build_type_object(self): - builtin_ast = MANAGER.ast_from_module_name(BUILTINS) - - inferred = list(builtin_ast.igetattr('object')) - self.assertEqual(len(inferred), 1) - inferred = inferred[0] - self.assertEqual(inferred.name, 'object') - inferred.as_string() # no crash test - - inferred = list(builtin_ast.igetattr('type')) - self.assertEqual(len(inferred), 1) - inferred = inferred[0] - self.assertEqual(inferred.name, 'type') - inferred.as_string() # no crash test - - def test_inspect_transform_module(self): - # ensure no cached version of the time module - MANAGER._mod_file_cache.pop(('time', None), None) - MANAGER.astroid_cache.pop('time', None) - def transform_time(node): - if node.name == 'time': - node.transformed = True - MANAGER.register_transform(nodes.Module, transform_time) - try: - time_ast = MANAGER.ast_from_module_name('time') - self.assertTrue(getattr(time_ast, 'transformed', False)) - finally: - MANAGER.unregister_transform(nodes.Module, transform_time) - - def test_package_name(self): - """test base properties and method of a astroid module""" - datap = resources.build_file('data/__init__.py', 'data') - self.assertEqual(datap.name, 'data') - self.assertEqual(datap.package, 1) - datap = resources.build_file('data/__init__.py', 'data.__init__') - self.assertEqual(datap.name, 'data') - self.assertEqual(datap.package, 1) - - def test_yield_parent(self): - """check if we added discard nodes as yield parent (w/ compiler)""" - code = """ - def yiell(): #@ - yield 0 - if noe: - yield more - """ - func = test_utils.extract_node(code) - self.assertIsInstance(func, nodes.FunctionDef) - stmt = func.body[0] - self.assertIsInstance(stmt, nodes.Expr) - self.assertIsInstance(stmt.value, nodes.Yield) - self.assertIsInstance(func.body[1].body[0], nodes.Expr) - self.assertIsInstance(func.body[1].body[0].value, nodes.Yield) - - def test_object(self): - obj_ast = self.builder.inspect_build(object) - self.assertIn('__setattr__', obj_ast) - - def test_newstyle_detection(self): - data = ''' - class A: - "old style" - - class B(A): - "old style" - - class C(object): - "new style" - - class D(C): - "new style" - - __metaclass__ = type - - class E(A): - "old style" - - class F: - "new style" - ''' - mod_ast = builder.parse(data, __name__) - if six.PY3: - self.assertTrue(mod_ast['A'].newstyle) - self.assertTrue(mod_ast['B'].newstyle) - self.assertTrue(mod_ast['E'].newstyle) - else: - self.assertFalse(mod_ast['A'].newstyle) - self.assertFalse(mod_ast['B'].newstyle) - self.assertFalse(mod_ast['E'].newstyle) - self.assertTrue(mod_ast['C'].newstyle) - self.assertTrue(mod_ast['D'].newstyle) - self.assertTrue(mod_ast['F'].newstyle) - - def test_globals(self): - data = ''' - CSTE = 1 - - def update_global(): - global CSTE - CSTE += 1 - - def global_no_effect(): - global CSTE2 - print (CSTE) - ''' - astroid = builder.parse(data, __name__) - self.assertEqual(len(astroid.getattr('CSTE')), 2) - self.assertIsInstance(astroid.getattr('CSTE')[0], nodes.AssignName) - self.assertEqual(astroid.getattr('CSTE')[0].fromlineno, 2) - self.assertEqual(astroid.getattr('CSTE')[1].fromlineno, 6) - with self.assertRaises(exceptions.NotFoundError): - astroid.getattr('CSTE2') - with self.assertRaises(exceptions.InferenceError): - next(astroid['global_no_effect'].ilookup('CSTE2')) - - @unittest.skipIf(os.name == 'java', - 'This test is skipped on Jython, because the ' - 'socket object is patched later on with the ' - 'methods we are looking for. Since we do not ' - 'understand setattr in for loops yet, we skip this') - def test_socket_build(self): - import socket - astroid = self.builder.module_build(socket) - # XXX just check the first one. Actually 3 objects are inferred (look at - # the socket module) but the last one as those attributes dynamically - # set and astroid is missing this. - for fclass in astroid.igetattr('socket'): - self.assertIn('connect', fclass) - self.assertIn('send', fclass) - self.assertIn('close', fclass) - break - - def test_gen_expr_var_scope(self): - data = 'l = list(n for n in range(10))\n' - astroid = builder.parse(data, __name__) - # n unavailable outside gen expr scope - self.assertNotIn('n', astroid) - # test n is inferable anyway - n = test_utils.get_name_node(astroid, 'n') - self.assertIsNot(n.scope(), astroid) - self.assertEqual([i.__class__ for i in n.infer()], - [util.YES.__class__]) - - def test_no_future_imports(self): - mod = builder.parse("import sys") - self.assertEqual(set(), mod._future_imports) - - def test_future_imports(self): - mod = builder.parse("from __future__ import print_function") - self.assertEqual(set(['print_function']), mod._future_imports) - - def test_two_future_imports(self): - mod = builder.parse(""" - from __future__ import print_function - from __future__ import absolute_import - """) - self.assertEqual(set(['print_function', 'absolute_import']), mod._future_imports) - - def test_inferred_build(self): - code = ''' - class A: pass - A.type = "class" - - def A_assign_type(self): - print (self) - A.assign_type = A_assign_type - ''' - astroid = builder.parse(code) - lclass = list(astroid.igetattr('A')) - self.assertEqual(len(lclass), 1) - lclass = lclass[0] - self.assertIn('assign_type', lclass._locals) - self.assertIn('type', lclass._locals) - - def test_augassign_attr(self): - builder.parse(""" - class Counter: - v = 0 - def inc(self): - self.v += 1 - """, __name__) - # TODO: Check self.v += 1 generate AugAssign(AssAttr(...)), - # not AugAssign(GetAttr(AssName...)) - - def test_inferred_dont_pollute(self): - code = ''' - def func(a=None): - a.custom_attr = 0 - def func2(a={}): - a.custom_attr = 0 - ''' - builder.parse(code) - nonetype = nodes.const_factory(None) - self.assertNotIn('custom_attr', nonetype._locals) - self.assertNotIn('custom_attr', nonetype._instance_attrs) - nonetype = nodes.const_factory({}) - self.assertNotIn('custom_attr', nonetype._locals) - self.assertNotIn('custom_attr', nonetype._instance_attrs) - - def test_asstuple(self): - code = 'a, b = range(2)' - astroid = builder.parse(code) - self.assertIn('b', astroid._locals) - code = ''' - def visit_if(self, node): - node.test, body = node.tests[0] - ''' - astroid = builder.parse(code) - self.assertIn('body', astroid['visit_if']._locals) - - def test_build_constants(self): - '''test expected values of constants after rebuilding''' - code = ''' - def func(): - return None - return - return 'None' - ''' - astroid = builder.parse(code) - none, nothing, chain = [ret.value for ret in astroid.body[0].body] - self.assertIsInstance(none, nodes.Const) - self.assertIsNone(none.value) - self.assertIsNone(nothing) - self.assertIsInstance(chain, nodes.Const) - self.assertEqual(chain.value, 'None') - - def test_not_implemented(self): - node = test_utils.extract_node(''' - NotImplemented #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, NotImplemented) - - -class FileBuildTest(unittest.TestCase): - def setUp(self): - self.module = resources.build_file('data/module.py', 'data.module') - - def test_module_base_props(self): - """test base properties and method of a astroid module""" - module = self.module - self.assertEqual(module.name, 'data.module') - self.assertEqual(module.doc, "test module for astroid\n") - self.assertEqual(module.fromlineno, 0) - self.assertIsNone(module.parent) - self.assertEqual(module.frame(), module) - self.assertEqual(module.root(), module) - self.assertEqual(module.source_file, os.path.abspath(resources.find('data/module.py'))) - self.assertEqual(module.pure_python, 1) - self.assertEqual(module.package, 0) - self.assertFalse(module.is_statement) - self.assertEqual(module.statement(), module) - self.assertEqual(module.statement(), module) - - def test_module_locals(self): - """test the 'locals' dictionary of a astroid module""" - module = self.module - _locals = module._locals - self.assertIs(_locals, module._globals) - keys = sorted(_locals.keys()) - should = ['MY_DICT', 'NameNode', 'YO', 'YOUPI', - '__revision__', 'global_access', 'modutils', 'four_args', - 'os', 'redirect'] - should.sort() - self.assertEqual(keys, sorted(should)) - - def test_function_base_props(self): - """test base properties and method of a astroid function""" - module = self.module - function = module['global_access'] - self.assertEqual(function.name, 'global_access') - self.assertEqual(function.doc, 'function test') - self.assertEqual(function.fromlineno, 11) - self.assertTrue(function.parent) - self.assertEqual(function.frame(), function) - self.assertEqual(function.parent.frame(), module) - self.assertEqual(function.root(), module) - self.assertEqual([n.name for n in function.args.args], ['key', 'val']) - self.assertEqual(function.type, 'function') - - def test_function_locals(self): - """test the 'locals' dictionary of a astroid function""" - _locals = self.module['global_access']._locals - self.assertEqual(len(_locals), 4) - keys = sorted(_locals.keys()) - self.assertEqual(keys, ['i', 'key', 'local', 'val']) - - def test_class_base_props(self): - """test base properties and method of a astroid class""" - module = self.module - klass = module['YO'] - self.assertEqual(klass.name, 'YO') - self.assertEqual(klass.doc, 'hehe') - self.assertEqual(klass.fromlineno, 25) - self.assertTrue(klass.parent) - self.assertEqual(klass.frame(), klass) - self.assertEqual(klass.parent.frame(), module) - self.assertEqual(klass.root(), module) - self.assertEqual(klass.basenames, []) - if six.PY3: - self.assertTrue(klass.newstyle) - else: - self.assertFalse(klass.newstyle) - - def test_class_locals(self): - """test the 'locals' dictionary of a astroid class""" - module = self.module - klass1 = module['YO'] - locals1 = klass1._locals - keys = sorted(locals1.keys()) - self.assertEqual(keys, ['__init__', 'a']) - klass2 = module['YOUPI'] - locals2 = klass2._locals - keys = locals2.keys() - self.assertEqual(sorted(keys), - ['__init__', 'class_attr', 'class_method', - 'method', 'static_method']) - - def test_class_instance_attrs(self): - module = self.module - klass1 = module['YO'] - klass2 = module['YOUPI'] - self.assertEqual(list(klass1._instance_attrs.keys()), ['yo']) - self.assertEqual(list(klass2._instance_attrs.keys()), ['member']) - - def test_class_basenames(self): - module = self.module - klass1 = module['YO'] - klass2 = module['YOUPI'] - self.assertEqual(klass1.basenames, []) - self.assertEqual(klass2.basenames, ['YO']) - - def test_method_base_props(self): - """test base properties and method of a astroid method""" - klass2 = self.module['YOUPI'] - # "normal" method - method = klass2['method'] - self.assertEqual(method.name, 'method') - self.assertEqual([n.name for n in method.args.args], ['self']) - self.assertEqual(method.doc, 'method test') - self.assertEqual(method.fromlineno, 47) - self.assertEqual(method.type, 'method') - # class method - method = klass2['class_method'] - self.assertEqual([n.name for n in method.args.args], ['cls']) - self.assertEqual(method.type, 'classmethod') - # static method - method = klass2['static_method'] - self.assertEqual(method.args.args, []) - self.assertEqual(method.type, 'staticmethod') - - def test_method_locals(self): - """test the 'locals' dictionary of a astroid method""" - method = self.module['YOUPI']['method'] - _locals = method._locals - keys = sorted(_locals) - if sys.version_info < (3, 0): - self.assertEqual(len(_locals), 5) - self.assertEqual(keys, ['a', 'autre', 'b', 'local', 'self']) - else:# ListComp variables are no more accessible outside - self.assertEqual(len(_locals), 3) - self.assertEqual(keys, ['autre', 'local', 'self']) - - -class ModuleBuildTest(resources.SysPathSetup, FileBuildTest): - - def setUp(self): - super(ModuleBuildTest, self).setUp() - abuilder = builder.AstroidBuilder() - try: - import data.module - except ImportError: - # Make pylint happy. - self.skipTest('Unable to load data.module') - else: - self.module = abuilder.module_build(data.module, 'data.module') - -@unittest.skipIf(six.PY3, "guess_encoding not used on Python 3") -class TestGuessEncoding(unittest.TestCase): - def setUp(self): - self.guess_encoding = builder._guess_encoding - - def testEmacs(self): - e = self.guess_encoding('# -*- coding: UTF-8 -*-') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding('# -*- coding:UTF-8 -*-') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding(''' - ### -*- coding: ISO-8859-1 -*- - ''') - self.assertEqual(e, 'ISO-8859-1') - e = self.guess_encoding(''' - - ### -*- coding: ISO-8859-1 -*- - ''') - self.assertIsNone(e) - - def testVim(self): - e = self.guess_encoding('# vim:fileencoding=UTF-8') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding(''' - ### vim:fileencoding=ISO-8859-1 - ''') - self.assertEqual(e, 'ISO-8859-1') - e = self.guess_encoding(''' - - ### vim:fileencoding= ISO-8859-1 - ''') - self.assertIsNone(e) - - def test_wrong_coding(self): - # setting "coding" varaible - e = self.guess_encoding("coding = UTF-8") - self.assertIsNone(e) - # setting a dictionnary entry - e = self.guess_encoding("coding:UTF-8") - self.assertIsNone(e) - # setting an arguement - e = self.guess_encoding("def do_something(a_word_with_coding=None):") - self.assertIsNone(e) - - def testUTF8(self): - e = self.guess_encoding('\xef\xbb\xbf any UTF-8 data') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding(' any UTF-8 data \xef\xbb\xbf') - self.assertIsNone(e) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_inference.py b/pymode/libs/astroid/tests/unittest_inference.py deleted file mode 100644 index 86497727..00000000 --- a/pymode/libs/astroid/tests/unittest_inference.py +++ /dev/null @@ -1,2130 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""tests for the astroid inference capabilities -""" -import sys -from functools import partial -import unittest -import warnings - -import six - -from astroid import InferenceError, builder, nodes -from astroid.builder import parse -from astroid.inference import infer_end as inference_infer_end -from astroid.bases import Instance, BoundMethod, UnboundMethod,\ - path_wrapper, BUILTINS -from astroid import arguments -from astroid import objects -from astroid import test_utils -from astroid import util -from astroid.tests import resources - - -def get_node_of_class(start_from, klass): - return next(start_from.nodes_of_class(klass)) - -builder = builder.AstroidBuilder() - -if sys.version_info < (3, 0): - EXC_MODULE = 'exceptions' -else: - EXC_MODULE = BUILTINS - - -class InferenceUtilsTest(unittest.TestCase): - - def test_path_wrapper(self): - def infer_default(self, *args): - raise InferenceError - infer_default = path_wrapper(infer_default) - infer_end = path_wrapper(inference_infer_end) - with self.assertRaises(InferenceError): - next(infer_default(1)) - self.assertEqual(next(infer_end(1)), 1) - - -def _assertInferElts(node_type, self, node, elts): - inferred = next(node.infer()) - self.assertIsInstance(inferred, node_type) - self.assertEqual(sorted(elt.value for elt in inferred.elts), - elts) - -def partialmethod(func, arg): - """similar to functools.partial but return a lambda instead of a class so returned value may be - turned into a method. - """ - return lambda *args, **kwargs: func(arg, *args, **kwargs) - -class InferenceTest(resources.SysPathSetup, unittest.TestCase): - - # additional assertInfer* method for builtin types - - def assertInferConst(self, node, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected) - - def assertInferDict(self, node, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - - elts = set([(key.value, value.value) - for (key, value) in inferred.items]) - self.assertEqual(sorted(elts), sorted(expected.items())) - - assertInferTuple = partialmethod(_assertInferElts, nodes.Tuple) - assertInferList = partialmethod(_assertInferElts, nodes.List) - assertInferSet = partialmethod(_assertInferElts, nodes.Set) - assertInferFrozenSet = partialmethod(_assertInferElts, objects.FrozenSet) - - CODE = ''' - class C(object): - "new style" - attr = 4 - - def meth1(self, arg1, optarg=0): - var = object() - print ("yo", arg1, optarg) - self.iattr = "hop" - return var - - def meth2(self): - self.meth1(*self.meth3) - - def meth3(self, d=attr): - b = self.attr - c = self.iattr - return b, c - - ex = Exception("msg") - v = C().meth1(1) - m_unbound = C.meth1 - m_bound = C().meth1 - a, b, c = ex, 1, "bonjour" - [d, e, f] = [ex, 1.0, ("bonjour", v)] - g, h = f - i, (j, k) = "glup", f - - a, b= b, a # Gasp ! - ''' - - ast = parse(CODE, __name__) - - def test_infer_abstract_property_return_values(self): - module = parse(''' - import abc - - class A(object): - @abc.abstractproperty - def test(self): - return 42 - - a = A() - x = a.test - ''') - inferred = next(module['x'].infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - def test_module_inference(self): - inferred = self.ast.infer() - obj = next(inferred) - self.assertEqual(obj.name, __name__) - self.assertEqual(obj.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_class_inference(self): - inferred = self.ast['C'].infer() - obj = next(inferred) - self.assertEqual(obj.name, 'C') - self.assertEqual(obj.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_function_inference(self): - inferred = self.ast['C']['meth1'].infer() - obj = next(inferred) - self.assertEqual(obj.name, 'meth1') - self.assertEqual(obj.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_builtin_name_inference(self): - inferred = self.ast['C']['meth1']['var'].infer() - var = next(inferred) - self.assertEqual(var.name, 'object') - self.assertEqual(var.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_tupleassign_name_inference(self): - inferred = self.ast['a'].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['b'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 1) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['c'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "bonjour") - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_listassign_name_inference(self): - inferred = self.ast['d'].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['e'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 1.0) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['f'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Tuple) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_advanced_tupleassign_name_inference1(self): - inferred = self.ast['g'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "bonjour") - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['h'].infer() - var = next(inferred) - self.assertEqual(var.name, 'object') - self.assertEqual(var.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_advanced_tupleassign_name_inference2(self): - inferred = self.ast['i'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, u"glup") - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['j'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "bonjour") - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['k'].infer() - var = next(inferred) - self.assertEqual(var.name, 'object') - self.assertEqual(var.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_swap_assign_inference(self): - inferred = self.ast._locals['a'][1].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 1) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast._locals['b'][1].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference1(self): - inferred = self.ast['ex'].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference2(self): - inferred = get_node_of_class(self.ast['C']['meth2'], nodes.Attribute).infer() - meth1 = next(inferred) - self.assertEqual(meth1.name, 'meth1') - self.assertEqual(meth1.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference3(self): - inferred = self.ast['C']['meth3']['b'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 4) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference4(self): - inferred = self.ast['C']['meth3']['c'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "hop") - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_callfunc_inference(self): - inferred = self.ast['v'].infer() - meth1 = next(inferred) - self.assertIsInstance(meth1, Instance) - self.assertEqual(meth1.name, 'object') - self.assertEqual(meth1.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_unbound_method_inference(self): - inferred = self.ast['m_unbound'].infer() - meth1 = next(inferred) - self.assertIsInstance(meth1, UnboundMethod) - self.assertEqual(meth1.name, 'meth1') - self.assertEqual(meth1.parent.frame().name, 'C') - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_bound_method_inference(self): - inferred = self.ast['m_bound'].infer() - meth1 = next(inferred) - self.assertIsInstance(meth1, BoundMethod) - self.assertEqual(meth1.name, 'meth1') - self.assertEqual(meth1.parent.frame().name, 'C') - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_args_default_inference1(self): - optarg = test_utils.get_name_node(self.ast['C']['meth1'], 'optarg') - inferred = optarg.infer() - obj1 = next(inferred) - self.assertIsInstance(obj1, nodes.Const) - self.assertEqual(obj1.value, 0) - obj1 = next(inferred) - self.assertIs(obj1, util.YES, obj1) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_args_default_inference2(self): - inferred = self.ast['C']['meth3'].ilookup('d') - obj1 = next(inferred) - self.assertIsInstance(obj1, nodes.Const) - self.assertEqual(obj1.value, 4) - obj1 = next(inferred) - self.assertIs(obj1, util.YES, obj1) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_inference_restrictions(self): - inferred = test_utils.get_name_node(self.ast['C']['meth1'], 'arg1').infer() - obj1 = next(inferred) - self.assertIs(obj1, util.YES, obj1) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_ancestors_inference(self): - code = ''' - class A(object): #@ - pass - - class A(A): #@ - pass - ''' - a1, a2 = test_utils.extract_node(code, __name__) - a2_ancestors = list(a2.ancestors()) - self.assertEqual(len(a2_ancestors), 2) - self.assertIs(a2_ancestors[0], a1) - - def test_ancestors_inference2(self): - code = ''' - class A(object): #@ - pass - - class B(A): #@ - pass - - class A(B): #@ - pass - ''' - a1, b, a2 = test_utils.extract_node(code, __name__) - a2_ancestors = list(a2.ancestors()) - self.assertEqual(len(a2_ancestors), 3) - self.assertIs(a2_ancestors[0], b) - self.assertIs(a2_ancestors[1], a1) - - def test_f_arg_f(self): - code = ''' - def f(f=1): - return f - - a = f() - ''' - ast = parse(code, __name__) - a = ast['a'] - a_inferred = a.inferred() - self.assertEqual(a_inferred[0].value, 1) - self.assertEqual(len(a_inferred), 1) - - def test_infered_warning(self): - code = ''' - def f(f=1): - return f - - a = f() - ''' - ast = parse(code, __name__) - a = ast['a'] - - warnings.simplefilter('always') - with warnings.catch_warnings(record=True) as w: - a.infered() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - - def test_exc_ancestors(self): - code = ''' - def f(): - raise __(NotImplementedError) - ''' - error = test_utils.extract_node(code, __name__) - nie = error.inferred()[0] - self.assertIsInstance(nie, nodes.ClassDef) - nie_ancestors = [c.name for c in nie.ancestors()] - if sys.version_info < (3, 0): - self.assertEqual(nie_ancestors, ['RuntimeError', 'StandardError', 'Exception', 'BaseException', 'object']) - else: - self.assertEqual(nie_ancestors, ['RuntimeError', 'Exception', 'BaseException', 'object']) - - def test_except_inference(self): - code = ''' - try: - print (hop) - except NameError as ex: - ex1 = ex - except Exception as ex: - ex2 = ex - raise - ''' - ast = parse(code, __name__) - ex1 = ast['ex1'] - ex1_infer = ex1.infer() - ex1 = next(ex1_infer) - self.assertIsInstance(ex1, Instance) - self.assertEqual(ex1.name, 'NameError') - self.assertRaises(StopIteration, partial(next, ex1_infer)) - ex2 = ast['ex2'] - ex2_infer = ex2.infer() - ex2 = next(ex2_infer) - self.assertIsInstance(ex2, Instance) - self.assertEqual(ex2.name, 'Exception') - self.assertRaises(StopIteration, partial(next, ex2_infer)) - - def test_del1(self): - code = ''' - del undefined_attr - ''' - delete = test_utils.extract_node(code, __name__) - self.assertRaises(InferenceError, delete.infer) - - def test_del2(self): - code = ''' - a = 1 - b = a - del a - c = a - a = 2 - d = a - ''' - ast = parse(code, __name__) - n = ast['b'] - n_infer = n.infer() - inferred = next(n_infer) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 1) - self.assertRaises(StopIteration, partial(next, n_infer)) - n = ast['c'] - n_infer = n.infer() - self.assertRaises(InferenceError, partial(next, n_infer)) - n = ast['d'] - n_infer = n.infer() - inferred = next(n_infer) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 2) - self.assertRaises(StopIteration, partial(next, n_infer)) - - def test_builtin_types(self): - code = ''' - l = [1] - t = (2,) - d = {} - s = '' - s2 = '_' - ''' - ast = parse(code, __name__) - n = ast['l'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.List) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.getitem(0).value, 1) - self.assertIsInstance(inferred._proxied, nodes.ClassDef) - self.assertEqual(inferred._proxied.name, 'list') - self.assertIn('append', inferred._proxied._locals) - n = ast['t'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.getitem(0).value, 2) - self.assertIsInstance(inferred._proxied, nodes.ClassDef) - self.assertEqual(inferred._proxied.name, 'tuple') - n = ast['d'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Dict) - self.assertIsInstance(inferred, Instance) - self.assertIsInstance(inferred._proxied, nodes.ClassDef) - self.assertEqual(inferred._proxied.name, 'dict') - self.assertIn('get', inferred._proxied._locals) - n = ast['s'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'str') - self.assertIn('lower', inferred._proxied._locals) - n = ast['s2'] - inferred = next(n.infer()) - self.assertEqual(inferred.getitem(0).value, '_') - - code = 's = {1}' - ast = parse(code, __name__) - n = ast['s'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Set) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'set') - self.assertIn('remove', inferred._proxied._locals) - - @test_utils.require_version(maxver='3.0') - def test_unicode_type(self): - code = '''u = u""''' - ast = parse(code, __name__) - n = ast['u'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'unicode') - self.assertIn('lower', inferred._proxied._locals) - - @unittest.expectedFailure - def test_descriptor_are_callable(self): - code = ''' - class A: - statm = staticmethod(open) - clsm = classmethod('whatever') - ''' - ast = parse(code, __name__) - statm = next(ast['A'].igetattr('statm')) - self.assertTrue(statm.callable()) - clsm = next(ast['A'].igetattr('clsm')) - self.assertFalse(clsm.callable()) - - def test_bt_ancestor_crash(self): - code = ''' - class Warning(Warning): - pass - ''' - ast = parse(code, __name__) - w = ast['Warning'] - ancestors = w.ancestors() - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'Warning') - self.assertEqual(ancestor.root().name, EXC_MODULE) - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'Exception') - self.assertEqual(ancestor.root().name, EXC_MODULE) - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'BaseException') - self.assertEqual(ancestor.root().name, EXC_MODULE) - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'object') - self.assertEqual(ancestor.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, ancestors)) - - def test_qqch(self): - code = ''' - from astroid.modutils import load_module_from_name - xxx = load_module_from_name('__pkginfo__') - ''' - ast = parse(code, __name__) - xxx = ast['xxx'] - self.assertSetEqual({n.__class__ for n in xxx.inferred()}, - {nodes.Const, util.YES.__class__}) - - def test_method_argument(self): - code = ''' - class ErudiEntitySchema: - """a entity has a type, a set of subject and or object relations""" - def __init__(self, e_type, **kwargs): - kwargs['e_type'] = e_type.capitalize().encode() - - def meth(self, e_type, *args, **kwargs): - kwargs['e_type'] = e_type.capitalize().encode() - print(args) - ''' - ast = parse(code, __name__) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'e_type') - self.assertEqual([n.__class__ for n in arg.infer()], - [util.YES.__class__]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'kwargs') - self.assertEqual([n.__class__ for n in arg.infer()], - [nodes.Dict]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'e_type') - self.assertEqual([n.__class__ for n in arg.infer()], - [util.YES.__class__]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'args') - self.assertEqual([n.__class__ for n in arg.infer()], - [nodes.Tuple]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'kwargs') - self.assertEqual([n.__class__ for n in arg.infer()], - [nodes.Dict]) - - def test_tuple_then_list(self): - code = ''' - def test_view(rql, vid, tags=()): - tags = list(tags) - __(tags).append(vid) - ''' - name = test_utils.extract_node(code, __name__) - it = name.infer() - tags = next(it) - self.assertIsInstance(tags, nodes.List) - self.assertEqual(tags.elts, []) - with self.assertRaises(StopIteration): - next(it) - - def test_mulassign_inference(self): - code = ''' - def first_word(line): - """Return the first word of a line""" - - return line.split()[0] - - def last_word(line): - """Return last word of a line""" - - return line.split()[-1] - - def process_line(word_pos): - """Silly function: returns (ok, callable) based on argument. - - For test purpose only. - """ - - if word_pos > 0: - return (True, first_word) - elif word_pos < 0: - return (True, last_word) - else: - return (False, None) - - if __name__ == '__main__': - - line_number = 0 - for a_line in file('test_callable.py'): - tupletest = process_line(line_number) - (ok, fct) = process_line(line_number) - if ok: - fct(a_line) - ''' - ast = parse(code, __name__) - self.assertEqual(len(list(ast['process_line'].infer_call_result(None))), 3) - self.assertEqual(len(list(ast['tupletest'].infer())), 3) - values = ['FunctionDef(first_word)', 'FunctionDef(last_word)', 'Const(NoneType)'] - self.assertEqual([str(inferred) - for inferred in ast['fct'].infer()], values) - - def test_float_complex_ambiguity(self): - code = ''' - def no_conjugate_member(magic_flag): #@ - """should not raise E1101 on something.conjugate""" - if magic_flag: - something = 1.0 - else: - something = 1.0j - if isinstance(something, float): - return something - return __(something).conjugate() - ''' - func, retval = test_utils.extract_node(code, __name__) - self.assertEqual( - [i.value for i in func.ilookup('something')], - [1.0, 1.0j]) - self.assertEqual( - [i.value for i in retval.infer()], - [1.0, 1.0j]) - - def test_lookup_cond_branches(self): - code = ''' - def no_conjugate_member(magic_flag): - """should not raise E1101 on something.conjugate""" - something = 1.0 - if magic_flag: - something = 1.0j - return something.conjugate() - ''' - ast = parse(code, __name__) - values = [i.value for i in test_utils.get_name_node(ast, 'something', -1).infer()] - self.assertEqual(values, [1.0, 1.0j]) - - - def test_simple_subscript(self): - code = ''' - class A(object): - def __getitem__(self, index): - return index + 42 - [1, 2, 3][0] #@ - (1, 2, 3)[1] #@ - (1, 2, 3)[-1] #@ - [1, 2, 3][0] + (2, )[0] + (3, )[-1] #@ - e = {'key': 'value'} - e['key'] #@ - "first"[0] #@ - list([1, 2, 3])[-1] #@ - tuple((4, 5, 6))[2] #@ - A()[0] #@ - A()[-1] #@ - ''' - ast_nodes = test_utils.extract_node(code, __name__) - expected = [1, 2, 3, 6, 'value', 'f', 3, 6, 42, 41] - for node, expected_value in zip(ast_nodes, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected_value) - - def test_invalid_subscripts(self): - ast_nodes = test_utils.extract_node(''' - class NoGetitem(object): - pass - class InvalidGetitem(object): - def __getitem__(self): pass - class InvalidGetitem2(object): - __getitem__ = 42 - NoGetitem()[4] #@ - InvalidGetitem()[5] #@ - InvalidGetitem2()[10] #@ - [1, 2, 3][None] #@ - 'lala'['bala'] #@ - ''') - for node in ast_nodes[:3]: - self.assertRaises(InferenceError, next, node.infer()) - for node in ast_nodes[3:]: - self.assertEqual(next(node.infer()), util.YES) - - def test_bytes_subscript(self): - node = test_utils.extract_node('''b'a'[0]''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - if six.PY2: - self.assertEqual(inferred.value, 'a') - else: - self.assertEqual(inferred.value, 97) - - #def test_simple_tuple(self): - #"""test case for a simple tuple value""" - ## XXX tuple inference is not implemented ... - #code = """ -#a = (1,) -#b = (22,) -#some = a + b -#""" - #ast = builder.string_build(code, __name__, __file__) - #self.assertEqual(ast['some'].infer.next().as_string(), "(1, 22)") - - def test_simple_for(self): - code = ''' - for a in [1, 2, 3]: - print (a) - for b,c in [(1,2), (3,4)]: - print (b) - print (c) - - print ([(d,e) for e,d in ([1,2], [3,4])]) - ''' - ast = parse(code, __name__) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'a', -1).infer()], [1, 2, 3]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'b', -1).infer()], [1, 3]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'c', -1).infer()], [2, 4]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3]) - - def test_simple_for_genexpr(self): - code = ''' - print ((d,e) for e,d in ([1,2], [3,4])) - ''' - ast = parse(code, __name__) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3]) - - - def test_builtin_help(self): - code = ''' - help() - ''' - # XXX failing since __builtin__.help assignment has - # been moved into a function... - node = test_utils.extract_node(code, __name__) - inferred = list(node.func.infer()) - self.assertEqual(len(inferred), 1, inferred) - self.assertIsInstance(inferred[0], Instance) - self.assertEqual(inferred[0].name, "_Helper") - - def test_builtin_open(self): - code = ''' - open("toto.txt") - ''' - node = test_utils.extract_node(code, __name__).func - inferred = list(node.infer()) - self.assertEqual(len(inferred), 1) - if hasattr(sys, 'pypy_version_info'): - self.assertIsInstance(inferred[0], nodes.ClassDef) - self.assertEqual(inferred[0].name, 'file') - else: - self.assertIsInstance(inferred[0], nodes.FunctionDef) - self.assertEqual(inferred[0].name, 'open') - - def test_callfunc_context_func(self): - code = ''' - def mirror(arg=None): - return arg - - un = mirror(1) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('un')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, 1) - - def test_callfunc_context_lambda(self): - code = ''' - mirror = lambda x=None: x - - un = mirror(1) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('mirror')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Lambda) - inferred = list(ast.igetattr('un')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, 1) - - def test_factory_method(self): - code = ''' - class Super(object): - @classmethod - def instance(cls): - return cls() - - class Sub(Super): - def method(self): - print ('method called') - - sub = Sub.instance() - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('sub')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], Instance) - self.assertEqual(inferred[0]._proxied.name, 'Sub') - - - def test_import_as(self): - code = ''' - import os.path as osp - print (osp.dirname(__file__)) - - from os.path import exists as e - assert e(__file__) - - from new import code as make_code - print (make_code) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('osp')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Module) - self.assertEqual(inferred[0].name, 'os.path') - inferred = list(ast.igetattr('e')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - self.assertEqual(inferred[0].name, 'exists') - if sys.version_info >= (3, 0): - self.skipTest(' module has been removed') - inferred = list(ast.igetattr('make_code')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], Instance) - self.assertEqual(str(inferred[0]), - 'Instance of %s.type' % BUILTINS) - - def _test_const_inferred(self, node, value): - inferred = list(node.infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, value) - - def test_unary_not(self): - for code in ('a = not (1,); b = not ()', - 'a = not {1:2}; b = not {}'): - ast = builder.string_build(code, __name__, __file__) - self._test_const_inferred(ast['a'], False) - self._test_const_inferred(ast['b'], True) - - @test_utils.require_version(minver='3.5') - def test_matmul(self): - node = test_utils.extract_node(''' - class Array: - def __matmul__(self, other): - return 42 - Array() @ Array() #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - def test_binary_op_int_add(self): - ast = builder.string_build('a = 1 + 2', __name__, __file__) - self._test_const_inferred(ast['a'], 3) - - def test_binary_op_int_sub(self): - ast = builder.string_build('a = 1 - 2', __name__, __file__) - self._test_const_inferred(ast['a'], -1) - - def test_binary_op_float_div(self): - ast = builder.string_build('a = 1 / 2.', __name__, __file__) - self._test_const_inferred(ast['a'], 1 / 2.) - - def test_binary_op_str_mul(self): - ast = builder.string_build('a = "*" * 40', __name__, __file__) - self._test_const_inferred(ast['a'], "*" * 40) - - def test_binary_op_bitand(self): - ast = builder.string_build('a = 23&20', __name__, __file__) - self._test_const_inferred(ast['a'], 23&20) - - def test_binary_op_bitor(self): - ast = builder.string_build('a = 23|8', __name__, __file__) - self._test_const_inferred(ast['a'], 23|8) - - def test_binary_op_bitxor(self): - ast = builder.string_build('a = 23^9', __name__, __file__) - self._test_const_inferred(ast['a'], 23^9) - - def test_binary_op_shiftright(self): - ast = builder.string_build('a = 23 >>1', __name__, __file__) - self._test_const_inferred(ast['a'], 23>>1) - - def test_binary_op_shiftleft(self): - ast = builder.string_build('a = 23 <<1', __name__, __file__) - self._test_const_inferred(ast['a'], 23<<1) - - - def test_binary_op_list_mul(self): - for code in ('a = [[]] * 2', 'a = 2 * [[]]'): - ast = builder.string_build(code, __name__, __file__) - inferred = list(ast['a'].infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.List) - self.assertEqual(len(inferred[0].elts), 2) - self.assertIsInstance(inferred[0].elts[0], nodes.List) - self.assertIsInstance(inferred[0].elts[1], nodes.List) - - def test_binary_op_list_mul_none(self): - 'test correct handling on list multiplied by None' - ast = builder.string_build('a = [1] * None\nb = [1] * "r"') - inferred = ast['a'].inferred() - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0], util.YES) - inferred = ast['b'].inferred() - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0], util.YES) - - def test_binary_op_list_mul_int(self): - 'test correct handling on list multiplied by int when there are more than one' - code = ''' - from ctypes import c_int - seq = [c_int()] * 4 - ''' - ast = parse(code, __name__) - inferred = ast['seq'].inferred() - self.assertEqual(len(inferred), 1) - listval = inferred[0] - self.assertIsInstance(listval, nodes.List) - self.assertEqual(len(listval.itered()), 4) - - def test_binary_op_tuple_add(self): - ast = builder.string_build('a = (1,) + (2,)', __name__, __file__) - inferred = list(ast['a'].infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Tuple) - self.assertEqual(len(inferred[0].elts), 2) - self.assertEqual(inferred[0].elts[0].value, 1) - self.assertEqual(inferred[0].elts[1].value, 2) - - def test_binary_op_custom_class(self): - code = ''' - class myarray: - def __init__(self, array): - self.array = array - def __mul__(self, x): - return myarray([2,4,6]) - def astype(self): - return "ASTYPE" - - def randint(maximum): - if maximum is not None: - return myarray([1,2,3]) * 2 - else: - return int(5) - - x = randint(1) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('x')) - self.assertEqual(len(inferred), 2) - value = [str(v) for v in inferred] - # The __name__ trick here makes it work when invoked directly - # (__name__ == '__main__') and through pytest (__name__ == - # 'unittest_inference') - self.assertEqual(value, ['Instance of %s.myarray' % __name__, - 'Instance of %s.int' % BUILTINS]) - - def test_nonregr_lambda_arg(self): - code = ''' - def f(g = lambda: None): - __(g()).x -''' - callfuncnode = test_utils.extract_node(code) - inferred = list(callfuncnode.infer()) - self.assertEqual(len(inferred), 2, inferred) - inferred.remove(util.YES) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertIsNone(inferred[0].value) - - def test_nonregr_getitem_empty_tuple(self): - code = ''' - def f(x): - a = ()[x] - ''' - ast = parse(code, __name__) - inferred = list(ast['f'].ilookup('a')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0], util.YES) - - def test_nonregr_instance_attrs(self): - """non regression for instance_attrs infinite loop : pylint / #4""" - - code = """ - class Foo(object): - - def set_42(self): - self.attr = 42 - - class Bar(Foo): - - def __init__(self): - self.attr = 41 - """ - ast = parse(code, __name__) - foo_class = ast['Foo'] - bar_class = ast['Bar'] - bar_self = ast['Bar']['__init__']['self'] - assattr = bar_class._instance_attrs['attr'][0] - self.assertEqual(len(foo_class._instance_attrs['attr']), 1) - self.assertEqual(len(bar_class._instance_attrs['attr']), 1) - self.assertEqual(bar_class._instance_attrs, {'attr': [assattr]}) - # call 'instance_attr' via 'Instance.getattr' to trigger the bug: - instance = bar_self.inferred()[0] - instance.getattr('attr') - self.assertEqual(len(bar_class._instance_attrs['attr']), 1) - self.assertEqual(len(foo_class._instance_attrs['attr']), 1) - self.assertEqual(bar_class._instance_attrs, {'attr': [assattr]}) - - def test_python25_generator_exit(self): - # pylint: disable=redefined-variable-type - buffer = six.StringIO() - sys.stderr = buffer - try: - data = "b = {}[str(0)+''].a" - ast = builder.string_build(data, __name__, __file__) - list(ast['b'].infer()) - output = buffer.getvalue() - finally: - sys.stderr = sys.__stderr__ - # I have no idea how to test for this in another way... - msg = ("Exception exceptions.RuntimeError: " - "'generator ignored GeneratorExit' in " - "ignored") - self.assertNotIn("RuntimeError", output, msg) - - def test_python25_no_relative_import(self): - ast = resources.build_file('data/package/absimport.py') - self.assertTrue(ast.absolute_import_activated(), True) - inferred = next(test_utils.get_name_node(ast, 'import_package_subpackage_module').infer()) - # failed to import since absolute_import is activated - self.assertIs(inferred, util.YES) - - def test_nonregr_absolute_import(self): - ast = resources.build_file('data/absimp/string.py', 'data.absimp.string') - self.assertTrue(ast.absolute_import_activated(), True) - inferred = next(test_utils.get_name_node(ast, 'string').infer()) - self.assertIsInstance(inferred, nodes.Module) - self.assertEqual(inferred.name, 'string') - self.assertIn('ascii_letters', inferred._locals) - - def test_mechanize_open(self): - try: - import mechanize # pylint: disable=unused-variable - except ImportError: - self.skipTest('require mechanize installed') - data = ''' - from mechanize import Browser - print(Browser) - b = Browser() - ''' - ast = parse(data, __name__) - browser = next(test_utils.get_name_node(ast, 'Browser').infer()) - self.assertIsInstance(browser, nodes.ClassDef) - bopen = list(browser.igetattr('open')) - self.skipTest('the commit said: "huum, see that later"') - self.assertEqual(len(bopen), 1) - self.assertIsInstance(bopen[0], nodes.FunctionDef) - self.assertTrue(bopen[0].callable()) - b = next(test_utils.get_name_node(ast, 'b').infer()) - self.assertIsInstance(b, Instance) - bopen = list(b.igetattr('open')) - self.assertEqual(len(bopen), 1) - self.assertIsInstance(bopen[0], BoundMethod) - self.assertTrue(bopen[0].callable()) - - def test_property(self): - code = ''' - from smtplib import SMTP - class SendMailController(object): - - @property - def smtp(self): - return SMTP(mailhost, port) - - @property - def me(self): - return self - - my_smtp = SendMailController().smtp - my_me = SendMailController().me - ''' - decorators = set(['%s.property' % BUILTINS]) - ast = parse(code, __name__) - self.assertEqual(ast['SendMailController']['smtp'].decoratornames(), - decorators) - propinferred = list(ast.body[2].value.infer()) - self.assertEqual(len(propinferred), 1) - propinferred = propinferred[0] - self.assertIsInstance(propinferred, Instance) - self.assertEqual(propinferred.name, 'SMTP') - self.assertEqual(propinferred.root().name, 'smtplib') - self.assertEqual(ast['SendMailController']['me'].decoratornames(), - decorators) - propinferred = list(ast.body[3].value.infer()) - self.assertEqual(len(propinferred), 1) - propinferred = propinferred[0] - self.assertIsInstance(propinferred, Instance) - self.assertEqual(propinferred.name, 'SendMailController') - self.assertEqual(propinferred.root().name, __name__) - - def test_im_func_unwrap(self): - code = ''' - class EnvBasedTC: - def pactions(self): - pass - pactions = EnvBasedTC.pactions.im_func - print (pactions) - - class EnvBasedTC2: - pactions = EnvBasedTC.pactions.im_func - print (pactions) - ''' - ast = parse(code, __name__) - pactions = test_utils.get_name_node(ast, 'pactions') - inferred = list(pactions.infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - pactions = test_utils.get_name_node(ast['EnvBasedTC2'], 'pactions') - inferred = list(pactions.infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - - def test_augassign(self): - code = ''' - a = 1 - a += 2 - print (a) - ''' - ast = parse(code, __name__) - inferred = list(test_utils.get_name_node(ast, 'a').infer()) - - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, 3) - - def test_nonregr_func_arg(self): - code = ''' - def foo(self, bar): - def baz(): - pass - def qux(): - return baz - spam = bar(None, qux) - print (spam) - ''' - ast = parse(code, __name__) - inferred = list(test_utils.get_name_node(ast['foo'], 'spam').infer()) - self.assertEqual(len(inferred), 1) - self.assertIs(inferred[0], util.YES) - - def test_nonregr_func_global(self): - code = ''' - active_application = None - - def get_active_application(): - global active_application - return active_application - - class Application(object): - def __init__(self): - global active_application - active_application = self - - class DataManager(object): - def __init__(self, app=None): - self.app = get_active_application() - def test(self): - p = self.app - print (p) - ''' - ast = parse(code, __name__) - inferred = list(Instance(ast['DataManager']).igetattr('app')) - self.assertEqual(len(inferred), 2, inferred) # None / Instance(Application) - inferred = list(test_utils.get_name_node(ast['DataManager']['test'], 'p').infer()) - self.assertEqual(len(inferred), 2, inferred) - for node in inferred: - if isinstance(node, Instance) and node.name == 'Application': - break - else: - self.fail('expected to find an instance of Application in %s' % inferred) - - def test_list_inference(self): - """#20464""" - code = ''' - from unknown import Unknown - A = [] - B = [] - - def test(): - xyz = [ - Unknown - ] + A + B - return xyz - - Z = test() - ''' - ast = parse(code, __name__) - inferred = next(ast['Z'].infer()) - self.assertIsInstance(inferred, nodes.List) - self.assertEqual(len(inferred.elts), 1) - self.assertIs(inferred.elts[0], util.YES) - - def test__new__(self): - code = ''' - class NewTest(object): - "doc" - def __new__(cls, arg): - self = object.__new__(cls) - self.arg = arg - return self - - n = NewTest() - ''' - ast = parse(code, __name__) - self.assertRaises(InferenceError, list, ast['NewTest'].igetattr('arg')) - n = next(ast['n'].infer()) - inferred = list(n.igetattr('arg')) - self.assertEqual(len(inferred), 1, inferred) - - def test__new__bound_methods(self): - node = test_utils.extract_node(''' - class cls(object): pass - cls().__new__(cls) #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred._proxied, node.root()['cls']) - - def test_two_parents_from_same_module(self): - code = ''' - from data import nonregr - class Xxx(nonregr.Aaa, nonregr.Ccc): - "doc" - ''' - ast = parse(code, __name__) - parents = list(ast['Xxx'].ancestors()) - self.assertEqual(len(parents), 3, parents) # Aaa, Ccc, object - - def test_pluggable_inference(self): - code = ''' - from collections import namedtuple - A = namedtuple('A', ['a', 'b']) - B = namedtuple('B', 'a b') - ''' - ast = parse(code, __name__) - aclass = ast['A'].inferred()[0] - self.assertIsInstance(aclass, nodes.ClassDef) - self.assertIn('a', aclass._instance_attrs) - self.assertIn('b', aclass._instance_attrs) - bclass = ast['B'].inferred()[0] - self.assertIsInstance(bclass, nodes.ClassDef) - self.assertIn('a', bclass._instance_attrs) - self.assertIn('b', bclass._instance_attrs) - - def test_infer_arguments(self): - code = ''' - class A(object): - def first(self, arg1, arg2): - return arg1 - @classmethod - def method(cls, arg1, arg2): - return arg2 - @classmethod - def empty(cls): - return 2 - @staticmethod - def static(arg1, arg2): - return arg1 - def empty_method(self): - return [] - x = A().first(1, []) - y = A.method(1, []) - z = A.static(1, []) - empty = A.empty() - empty_list = A().empty_method() - ''' - ast = parse(code, __name__) - int_node = ast['x'].inferred()[0] - self.assertIsInstance(int_node, nodes.Const) - self.assertEqual(int_node.value, 1) - list_node = ast['y'].inferred()[0] - self.assertIsInstance(list_node, nodes.List) - int_node = ast['z'].inferred()[0] - self.assertIsInstance(int_node, nodes.Const) - self.assertEqual(int_node.value, 1) - empty = ast['empty'].inferred()[0] - self.assertIsInstance(empty, nodes.Const) - self.assertEqual(empty.value, 2) - empty_list = ast['empty_list'].inferred()[0] - self.assertIsInstance(empty_list, nodes.List) - - def test_infer_variable_arguments(self): - code = ''' - def test(*args, **kwargs): - vararg = args - kwarg = kwargs - ''' - ast = parse(code, __name__) - func = ast['test'] - vararg = func.body[0].value - kwarg = func.body[1].value - - kwarg_inferred = kwarg.inferred()[0] - self.assertIsInstance(kwarg_inferred, nodes.Dict) - self.assertIs(kwarg_inferred.parent, func.args) - - vararg_inferred = vararg.inferred()[0] - self.assertIsInstance(vararg_inferred, nodes.Tuple) - self.assertIs(vararg_inferred.parent, func.args) - - def test_infer_nested(self): - code = """ - def nested(): - from threading import Thread - - class NestedThread(Thread): - def __init__(self): - Thread.__init__(self) - """ - # Test that inferring Thread.__init__ looks up in - # the nested scope. - ast = parse(code, __name__) - callfunc = next(ast.nodes_of_class(nodes.Call)) - func = callfunc.func - inferred = func.inferred()[0] - self.assertIsInstance(inferred, UnboundMethod) - - def test_instance_binary_operations(self): - code = """ - class A(object): - def __mul__(self, other): - return 42 - a = A() - b = A() - sub = a - b - mul = a * b - """ - ast = parse(code, __name__) - sub = ast['sub'].inferred()[0] - mul = ast['mul'].inferred()[0] - self.assertIs(sub, util.YES) - self.assertIsInstance(mul, nodes.Const) - self.assertEqual(mul.value, 42) - - def test_instance_binary_operations_parent(self): - code = """ - class A(object): - def __mul__(self, other): - return 42 - class B(A): - pass - a = B() - b = B() - sub = a - b - mul = a * b - """ - ast = parse(code, __name__) - sub = ast['sub'].inferred()[0] - mul = ast['mul'].inferred()[0] - self.assertIs(sub, util. YES) - self.assertIsInstance(mul, nodes.Const) - self.assertEqual(mul.value, 42) - - def test_instance_binary_operations_multiple_methods(self): - code = """ - class A(object): - def __mul__(self, other): - return 42 - class B(A): - def __mul__(self, other): - return [42] - a = B() - b = B() - sub = a - b - mul = a * b - """ - ast = parse(code, __name__) - sub = ast['sub'].inferred()[0] - mul = ast['mul'].inferred()[0] - self.assertIs(sub, util.YES) - self.assertIsInstance(mul, nodes.List) - self.assertIsInstance(mul.elts[0], nodes.Const) - self.assertEqual(mul.elts[0].value, 42) - - def test_infer_call_result_crash(self): - code = """ - class A(object): - def __mul__(self, other): - return type.__new__() - - a = A() - b = A() - c = a * b - """ - ast = parse(code, __name__) - node = ast['c'] - self.assertEqual(node.inferred(), [util.YES]) - - def test_infer_empty_nodes(self): - # Should not crash when trying to infer EmptyNodes. - node = nodes.EmptyNode() - self.assertEqual(node.inferred(), [util.YES]) - - def test_infinite_loop_for_decorators(self): - # Issue https://bitbucket.org/logilab/astroid/issue/50 - # A decorator that returns itself leads to an infinite loop. - code = """ - def decorator(): - def wrapper(): - return decorator() - return wrapper - - @decorator() - def do_a_thing(): - pass - """ - ast = parse(code, __name__) - node = ast['do_a_thing'] - self.assertEqual(node.type, 'function') - - def test_no_infinite_ancestor_loop(self): - klass = test_utils.extract_node(""" - import datetime - - def method(self): - datetime.datetime = something() - - class something(datetime.datetime): #@ - pass - """) - self.assertIn( - 'object', - [base.name for base in klass.ancestors()]) - - def test_stop_iteration_leak(self): - code = """ - class Test: - def __init__(self): - self.config = {0: self.config[0]} - self.config[0].test() #@ - """ - ast = test_utils.extract_node(code, __name__) - expr = ast.func.expr - self.assertRaises(InferenceError, next, expr.infer()) - - def test_tuple_builtin_inference(self): - code = """ - var = (1, 2) - tuple() #@ - tuple([1]) #@ - tuple({2}) #@ - tuple("abc") #@ - tuple({1: 2}) #@ - tuple(var) #@ - tuple(tuple([1])) #@ - - tuple(None) #@ - tuple(1) #@ - tuple(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - - self.assertInferTuple(ast[0], []) - self.assertInferTuple(ast[1], [1]) - self.assertInferTuple(ast[2], [2]) - self.assertInferTuple(ast[3], ["a", "b", "c"]) - self.assertInferTuple(ast[4], [1]) - self.assertInferTuple(ast[5], [1, 2]) - self.assertInferTuple(ast[6], [1]) - - for node in ast[7:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.tuple".format(BUILTINS)) - - def test_frozenset_builtin_inference(self): - code = """ - var = (1, 2) - frozenset() #@ - frozenset([1, 2, 1]) #@ - frozenset({2, 3, 1}) #@ - frozenset("abcab") #@ - frozenset({1: 2}) #@ - frozenset(var) #@ - frozenset(tuple([1])) #@ - - frozenset(set(tuple([4, 5, set([2])]))) #@ - frozenset(None) #@ - frozenset(1) #@ - frozenset(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - - self.assertInferFrozenSet(ast[0], []) - self.assertInferFrozenSet(ast[1], [1, 2]) - self.assertInferFrozenSet(ast[2], [1, 2, 3]) - self.assertInferFrozenSet(ast[3], ["a", "b", "c"]) - self.assertInferFrozenSet(ast[4], [1]) - self.assertInferFrozenSet(ast[5], [1, 2]) - self.assertInferFrozenSet(ast[6], [1]) - - for node in ast[7:]: - infered = next(node.infer()) - self.assertIsInstance(infered, Instance) - self.assertEqual(infered.qname(), "{}.frozenset".format(BUILTINS)) - - def test_set_builtin_inference(self): - code = """ - var = (1, 2) - set() #@ - set([1, 2, 1]) #@ - set({2, 3, 1}) #@ - set("abcab") #@ - set({1: 2}) #@ - set(var) #@ - set(tuple([1])) #@ - - set(set(tuple([4, 5, set([2])]))) #@ - set(None) #@ - set(1) #@ - set(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - - self.assertInferSet(ast[0], []) - self.assertInferSet(ast[1], [1, 2]) - self.assertInferSet(ast[2], [1, 2, 3]) - self.assertInferSet(ast[3], ["a", "b", "c"]) - self.assertInferSet(ast[4], [1]) - self.assertInferSet(ast[5], [1, 2]) - self.assertInferSet(ast[6], [1]) - - for node in ast[7:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.set".format(BUILTINS)) - - def test_list_builtin_inference(self): - code = """ - var = (1, 2) - list() #@ - list([1, 2, 1]) #@ - list({2, 3, 1}) #@ - list("abcab") #@ - list({1: 2}) #@ - list(var) #@ - list(tuple([1])) #@ - - list(list(tuple([4, 5, list([2])]))) #@ - list(None) #@ - list(1) #@ - list(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferList(ast[0], []) - self.assertInferList(ast[1], [1, 1, 2]) - self.assertInferList(ast[2], [1, 2, 3]) - self.assertInferList(ast[3], ["a", "a", "b", "b", "c"]) - self.assertInferList(ast[4], [1]) - self.assertInferList(ast[5], [1, 2]) - self.assertInferList(ast[6], [1]) - - for node in ast[7:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.list".format(BUILTINS)) - - @test_utils.require_version('3.0') - def test_builtin_inference_py3k(self): - code = """ - list(b"abc") #@ - tuple(b"abc") #@ - set(b"abc") #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferList(ast[0], [97, 98, 99]) - self.assertInferTuple(ast[1], [97, 98, 99]) - self.assertInferSet(ast[2], [97, 98, 99]) - - def test_dict_inference(self): - code = """ - dict() #@ - dict(a=1, b=2, c=3) #@ - dict([(1, 2), (2, 3)]) #@ - dict([[1, 2], [2, 3]]) #@ - dict([(1, 2), [2, 3]]) #@ - dict([('a', 2)], b=2, c=3) #@ - dict({1: 2}) #@ - dict({'c': 2}, a=4, b=5) #@ - def func(): - return dict(a=1, b=2) - func() #@ - var = {'x': 2, 'y': 3} - dict(var, a=1, b=2) #@ - - dict([1, 2, 3]) #@ - dict([(1, 2), (1, 2, 3)]) #@ - dict({1: 2}, {1: 2}) #@ - dict({1: 2}, (1, 2)) #@ - dict({1: 2}, (1, 2), a=4) #@ - dict([(1, 2), ([4, 5], 2)]) #@ - dict([None, None]) #@ - - def using_unknown_kwargs(**kwargs): - return dict(**kwargs) - using_unknown_kwargs(a=1, b=2) #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferDict(ast[0], {}) - self.assertInferDict(ast[1], {'a': 1, 'b': 2, 'c': 3}) - for i in range(2, 5): - self.assertInferDict(ast[i], {1: 2, 2: 3}) - self.assertInferDict(ast[5], {'a': 2, 'b': 2, 'c': 3}) - self.assertInferDict(ast[6], {1: 2}) - self.assertInferDict(ast[7], {'c': 2, 'a': 4, 'b': 5}) - self.assertInferDict(ast[8], {'a': 1, 'b': 2}) - self.assertInferDict(ast[9], {'x': 2, 'y': 3, 'a': 1, 'b': 2}) - - for node in ast[10:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.dict".format(BUILTINS)) - - def test_dict_inference_kwargs(self): - ast_node = test_utils.extract_node('''dict(a=1, b=2, **{'c': 3})''') - self.assertInferDict(ast_node, {'a': 1, 'b': 2, 'c': 3}) - - @test_utils.require_version('3.5') - def test_dict_inference_for_multiple_starred(self): - pairs = [ - ('dict(a=1, **{"b": 2}, **{"c":3})', {'a':1, 'b':2, 'c':3}), - ('dict(a=1, **{"b": 2}, d=4, **{"c":3})', {'a':1, 'b':2, 'c':3, 'd':4}), - ('dict({"a":1}, b=2, **{"c":3})', {'a':1, 'b':2, 'c':3}), - ] - for code, expected_value in pairs: - node = test_utils.extract_node(code) - self.assertInferDict(node, expected_value) - - def test_dict_invalid_args(self): - invalid_values = [ - 'dict(*1)', - 'dict(**lala)', - 'dict(**[])', - ] - for invalid in invalid_values: - ast_node = test_utils.extract_node(invalid) - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.dict".format(BUILTINS)) - - def test_str_methods(self): - code = """ - ' '.decode() #@ - - ' '.encode() #@ - ' '.join('abcd') #@ - ' '.replace('a', 'b') #@ - ' '.format('a') #@ - ' '.capitalize() #@ - ' '.title() #@ - ' '.lower() #@ - ' '.upper() #@ - ' '.swapcase() #@ - ' '.strip() #@ - ' '.rstrip() #@ - ' '.lstrip() #@ - ' '.rjust() #@ - ' '.ljust() #@ - ' '.center() #@ - - ' '.index() #@ - ' '.find() #@ - ' '.count() #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferConst(ast[0], u'') - for i in range(1, 16): - self.assertInferConst(ast[i], '') - for i in range(16, 19): - self.assertInferConst(ast[i], 0) - - def test_unicode_methods(self): - code = """ - u' '.encode() #@ - - u' '.decode() #@ - u' '.join('abcd') #@ - u' '.replace('a', 'b') #@ - u' '.format('a') #@ - u' '.capitalize() #@ - u' '.title() #@ - u' '.lower() #@ - u' '.upper() #@ - u' '.swapcase() #@ - u' '.strip() #@ - u' '.rstrip() #@ - u' '.lstrip() #@ - u' '.rjust() #@ - u' '.ljust() #@ - u' '.center() #@ - - u' '.index() #@ - u' '.find() #@ - u' '.count() #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferConst(ast[0], '') - for i in range(1, 16): - self.assertInferConst(ast[i], u'') - for i in range(16, 19): - self.assertInferConst(ast[i], 0) - - def test_scope_lookup_same_attributes(self): - code = ''' - import collections - class Second(collections.Counter): - def collections(self): - return "second" - - ''' - ast = parse(code, __name__) - bases = ast['Second'].bases[0] - inferred = next(bases.infer()) - self.assertTrue(inferred) - self.assertIsInstance(inferred, nodes.ClassDef) - self.assertEqual(inferred.qname(), 'collections.Counter') - - -class ArgumentsTest(unittest.TestCase): - - @staticmethod - def _get_dict_value(inferred): - items = inferred.items - return sorted((key.value, value.value) for key, value in items) - - @staticmethod - def _get_tuple_value(inferred): - elts = inferred.elts - return tuple(elt.value for elt in elts) - - def test_args(self): - expected_values = [(), (1, ), (2, 3), (4, 5), - (3, ), (), (3, 4, 5), - (), (), (4, ), (4, 5), - (), (3, ), (), (), (3, ), (42, )] - ast_nodes = test_utils.extract_node(''' - def func(*args): - return args - func() #@ - func(1) #@ - func(2, 3) #@ - func(*(4, 5)) #@ - def func(a, b, *args): - return args - func(1, 2, 3) #@ - func(1, 2) #@ - func(1, 2, 3, 4, 5) #@ - def func(a, b, c=42, *args): - return args - func(1, 2) #@ - func(1, 2, 3) #@ - func(1, 2, 3, 4) #@ - func(1, 2, 3, 4, 5) #@ - func = lambda a, b, *args: args - func(1, 2) #@ - func(1, 2, 3) #@ - func = lambda a, b=42, *args: args - func(1) #@ - func(1, 2) #@ - func(1, 2, 3) #@ - func(1, 2, *(42, )) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertEqual(self._get_tuple_value(inferred), expected_value) - - @test_utils.require_version('3.5') - def test_multiple_starred_args(self): - expected_values = [ - (1, 2, 3), - (1, 4, 2, 3, 5, 6, 7), - ] - ast_nodes = test_utils.extract_node(''' - def func(a, b, *args): - return args - func(1, 2, *(1, ), *(2, 3)) #@ - func(1, 2, *(1, ), 4, *(2, 3), 5, *(6, 7)) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertEqual(self._get_tuple_value(inferred), expected_value) - - def test_defaults(self): - expected_values = [42, 3, 41, 42] - ast_nodes = test_utils.extract_node(''' - def func(a, b, c=42, *args): - return c - func(1, 2) #@ - func(1, 2, 3) #@ - func(1, 2, c=41) #@ - func(1, 2, 42, 41) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected_value) - - @test_utils.require_version('3.0') - def test_kwonly_args(self): - expected_values = [24, 24, 42, 23, 24, 24, 54] - ast_nodes = test_utils.extract_node(''' - def test(*, f, b): return f - test(f=24, b=33) #@ - def test(a, *, f): return f - test(1, f=24) #@ - def test(a, *, f=42): return f - test(1) #@ - test(1, f=23) #@ - def test(a, b, c=42, *args, f=24): - return f - test(1, 2, 3) #@ - test(1, 2, 3, 4) #@ - test(1, 2, 3, 4, 5, f=54) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected_value) - - def test_kwargs(self): - expected = [ - [('a', 1), ('b', 2), ('c', 3)], - [('a', 1)], - [('a', 'b')], - ] - ast_nodes = test_utils.extract_node(''' - def test(**kwargs): - return kwargs - test(a=1, b=2, c=3) #@ - test(a=1) #@ - test(**{'a': 'b'}) #@ - ''') - for node, expected_value in zip(ast_nodes, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - value = self._get_dict_value(inferred) - self.assertEqual(value, expected_value) - - def test_kwargs_and_other_named_parameters(self): - ast_nodes = test_utils.extract_node(''' - def test(a=42, b=24, **kwargs): - return kwargs - test(42, 24, c=3, d=4) #@ - test(49, b=24, d=4) #@ - test(a=42, b=33, c=3, d=42) #@ - test(a=42, **{'c':42}) #@ - ''') - expected_values = [ - [('c', 3), ('d', 4)], - [('d', 4)], - [('c', 3), ('d', 42)], - [('c', 42)], - ] - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - value = self._get_dict_value(inferred) - self.assertEqual(value, expected_value) - - def test_kwargs_access_by_name(self): - expected_values = [42, 42, 42, 24] - ast_nodes = test_utils.extract_node(''' - def test(**kwargs): - return kwargs['f'] - test(f=42) #@ - test(**{'f': 42}) #@ - test(**dict(f=42)) #@ - def test(f=42, **kwargs): - return kwargs['l'] - test(l=24) #@ - ''') - for ast_node, value in zip(ast_nodes, expected_values): - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, value) - - def test_infer_call_result_invalid_dunder_call_on_instance(self): - ast_nodes = test_utils.extract_node(''' - class A: - __call__ = 42 - class B: - __call__ = A() - class C: - __call = None - A() #@ - B() #@ - C() #@ - ''') - for node in ast_nodes: - inferred = next(node.infer()) - self.assertRaises(InferenceError, next, inferred.infer_call_result(node)) - - - def test_subscript_inference_error(self): - # Used to raise StopIteration - ast_node = test_utils.extract_node(''' - class AttributeDict(dict): - def __getitem__(self, name): - return self - flow = AttributeDict() - flow['app'] = AttributeDict() - flow['app']['config'] = AttributeDict() - flow['app']['config']['doffing'] = AttributeDict() #@ - ''') - self.assertIsNone(util.safe_infer(ast_node.targets[0])) - - def test_classmethod_inferred_by_context(self): - ast_node = test_utils.extract_node(''' - class Super(object): - def instance(cls): - return cls() - instance = classmethod(instance) - - class Sub(Super): - def method(self): - return self - - # should see the Sub.instance() is returning a Sub - # instance, not a Super instance - Sub.instance().method() #@ - ''') - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'Sub') - - @test_utils.require_version('3.5') - def test_multiple_kwargs(self): - expected_value = [ - ('a', 1), - ('b', 2), - ('c', 3), - ('d', 4), - ('f', 42), - ] - ast_node = test_utils.extract_node(''' - def test(**kwargs): - return kwargs - test(a=1, b=2, **{'c': 3}, **{'d': 4}, f=42) #@ - ''') - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - value = self._get_dict_value(inferred) - self.assertEqual(value, expected_value) - - def test_kwargs_are_overriden(self): - ast_nodes = test_utils.extract_node(''' - def test(f): - return f - test(f=23, **{'f': 34}) #@ - def test(f=None): - return f - test(f=23, **{'f':23}) #@ - ''') - for ast_node in ast_nodes: - inferred = next(ast_node.infer()) - self.assertEqual(inferred, util.YES) - - def test_fail_to_infer_args(self): - ast_nodes = test_utils.extract_node(''' - def test(a, **kwargs): return a - test(*missing) #@ - test(*object) #@ - test(*1) #@ - - - def test(**kwargs): return kwargs - test(**miss) #@ - test(**(1, 2)) #@ - test(**1) #@ - test(**{misss:1}) #@ - test(**{object:1}) #@ - test(**{1:1}) #@ - test(**{'a':1, 'a':1}) #@ - - def test(a): return a - test() #@ - test(1, 2, 3) #@ - - from unknown import unknown - test(*unknown) #@ - def test(*args): return args - test(*unknown) #@ - ''') - for node in ast_nodes: - inferred = next(node.infer()) - self.assertEqual(inferred, util.YES) - -class CallSiteTest(unittest.TestCase): - - @staticmethod - def _call_site_from_call(call): - return arguments.CallSite.from_call(call) - - def _test_call_site_pair(self, code, expected_args, expected_keywords): - ast_node = test_utils.extract_node(code) - call_site = self._call_site_from_call(ast_node) - self.assertEqual(len(call_site.positional_arguments), len(expected_args)) - self.assertEqual([arg.value for arg in call_site.positional_arguments], - expected_args) - self.assertEqual(len(call_site.keyword_arguments), len(expected_keywords)) - for keyword, value in expected_keywords.items(): - self.assertIn(keyword, call_site.keyword_arguments) - self.assertEqual(call_site.keyword_arguments[keyword].value, value) - - def _test_call_site(self, pairs): - for pair in pairs: - self._test_call_site_pair(*pair) - - @test_utils.require_version('3.5') - def test_call_site_starred_args(self): - pairs = [ - ( - "f(*(1, 2), *(2, 3), *(3, 4), **{'a':1}, **{'b': 2})", - [1, 2, 2, 3, 3, 4], - {'a': 1, 'b': 2} - ), - ( - "f(1, 2, *(3, 4), 5, *(6, 7), f=24, **{'c':3})", - [1, 2, 3, 4, 5, 6, 7], - {'f':24, 'c': 3}, - ), - # Too many fs passed into. - ( - "f(f=24, **{'f':24})", [], {}, - ), - ] - self._test_call_site(pairs) - - def test_call_site(self): - pairs = [ - ( - "f(1, 2)", [1, 2], {} - ), - ( - "f(1, 2, *(1, 2))", [1, 2, 1, 2], {} - ), - ( - "f(a=1, b=2, c=3)", [], {'a':1, 'b':2, 'c':3} - ) - ] - self._test_call_site(pairs) - - def _test_call_site_valid_arguments(self, values, invalid): - for value in values: - ast_node = test_utils.extract_node(value) - call_site = self._call_site_from_call(ast_node) - self.assertEqual(call_site.has_invalid_arguments(), invalid) - - def test_call_site_valid_arguments(self): - values = [ - "f(*lala)", "f(*1)", "f(*object)", - ] - self._test_call_site_valid_arguments(values, invalid=True) - values = [ - "f()", "f(*(1, ))", "f(1, 2, *(2, 3))", - ] - self._test_call_site_valid_arguments(values, invalid=False) - - def test_duplicated_keyword_arguments(self): - ast_node = test_utils.extract_node('f(f=24, **{"f": 25})') - site = self._call_site_from_call(ast_node) - self.assertIn('f', site.duplicated_keywords) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_lookup.py b/pymode/libs/astroid/tests/unittest_lookup.py deleted file mode 100644 index bd1786d5..00000000 --- a/pymode/libs/astroid/tests/unittest_lookup.py +++ /dev/null @@ -1,352 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""tests for the astroid variable lookup capabilities -""" -import functools -import sys -import unittest - -from astroid import builder -from astroid import exceptions -from astroid import nodes -from astroid import scoped_nodes -from astroid import test_utils -from astroid import util -from astroid.tests import resources - - -class LookupTest(resources.SysPathSetup, unittest.TestCase): - - def setUp(self): - super(LookupTest, self).setUp() - self.module = resources.build_file('data/module.py', 'data.module') - self.module2 = resources.build_file('data/module2.py', 'data.module2') - self.nonregr = resources.build_file('data/nonregr.py', 'data.nonregr') - - def test_limit(self): - code = ''' - l = [a - for a,b in list] - - a = 1 - b = a - a = None - - def func(): - c = 1 - ''' - astroid = builder.parse(code, __name__) - # a & b - a = next(astroid.nodes_of_class(nodes.Name)) - self.assertEqual(a.lineno, 2) - if sys.version_info < (3, 0): - self.assertEqual(len(astroid.lookup('b')[1]), 1) - self.assertEqual(len(astroid.lookup('a')[1]), 1) - b = astroid._locals['b'][1] - else: - self.assertEqual(len(astroid.lookup('b')[1]), 1) - self.assertEqual(len(astroid.lookup('a')[1]), 1) - b = astroid._locals['b'][0] - - stmts = a.lookup('a')[1] - self.assertEqual(len(stmts), 1) - self.assertEqual(b.lineno, 6) - b_infer = b.infer() - b_value = next(b_infer) - self.assertEqual(b_value.value, 1) - # c - self.assertRaises(StopIteration, functools.partial(next, b_infer)) - func = astroid._locals['func'][0] - self.assertEqual(len(func.lookup('c')[1]), 1) - - def test_module(self): - astroid = builder.parse('pass', __name__) - # built-in objects - none = next(astroid.ilookup('None')) - self.assertIsNone(none.value) - obj = next(astroid.ilookup('object')) - self.assertIsInstance(obj, nodes.ClassDef) - self.assertEqual(obj.name, 'object') - self.assertRaises(exceptions.InferenceError, - functools.partial(next, astroid.ilookup('YOAA'))) - - # XXX - self.assertEqual(len(list(self.nonregr.ilookup('enumerate'))), 2) - - def test_class_ancestor_name(self): - code = ''' - class A: - pass - - class A(A): - pass - ''' - astroid = builder.parse(code, __name__) - cls1 = astroid._locals['A'][0] - cls2 = astroid._locals['A'][1] - name = next(cls2.nodes_of_class(nodes.Name)) - self.assertEqual(next(name.infer()), cls1) - - ### backport those test to inline code - def test_method(self): - method = self.module['YOUPI']['method'] - my_dict = next(method.ilookup('MY_DICT')) - self.assertTrue(isinstance(my_dict, nodes.Dict), my_dict) - none = next(method.ilookup('None')) - self.assertIsNone(none.value) - self.assertRaises(exceptions.InferenceError, - functools.partial(next, method.ilookup('YOAA'))) - - def test_function_argument_with_default(self): - make_class = self.module2['make_class'] - base = next(make_class.ilookup('base')) - self.assertTrue(isinstance(base, nodes.ClassDef), base.__class__) - self.assertEqual(base.name, 'YO') - self.assertEqual(base.root().name, 'data.module') - - def test_class(self): - klass = self.module['YOUPI'] - my_dict = next(klass.ilookup('MY_DICT')) - self.assertIsInstance(my_dict, nodes.Dict) - none = next(klass.ilookup('None')) - self.assertIsNone(none.value) - obj = next(klass.ilookup('object')) - self.assertIsInstance(obj, nodes.ClassDef) - self.assertEqual(obj.name, 'object') - self.assertRaises(exceptions.InferenceError, - functools.partial(next, klass.ilookup('YOAA'))) - - def test_inner_classes(self): - ddd = list(self.nonregr['Ccc'].ilookup('Ddd')) - self.assertEqual(ddd[0].name, 'Ddd') - - def test_loopvar_hiding(self): - astroid = builder.parse(""" - x = 10 - for x in range(5): - print (x) - - if x > 0: - print ('#' * x) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x'] - # inside the loop, only one possible assignment - self.assertEqual(len(xnames[0].lookup('x')[1]), 1) - # outside the loop, two possible assignments - self.assertEqual(len(xnames[1].lookup('x')[1]), 2) - self.assertEqual(len(xnames[2].lookup('x')[1]), 2) - - def test_list_comps(self): - astroid = builder.parse(""" - print ([ i for i in range(10) ]) - print ([ i for i in range(10) ]) - print ( list( i for i in range(10) ) ) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - self.assertEqual(len(xnames[2].lookup('i')[1]), 1) - self.assertEqual(xnames[2].lookup('i')[1][0].lineno, 4) - - def test_list_comp_target(self): - """test the list comprehension target""" - astroid = builder.parse(""" - ten = [ var for var in range(10) ] - var - """) - var = astroid.body[1].value - if sys.version_info < (3, 0): - self.assertEqual(var.inferred(), [util.YES]) - else: - self.assertRaises(exceptions.UnresolvableName, var.inferred) - - def test_dict_comps(self): - astroid = builder.parse(""" - print ({ i: j for i in range(10) for j in range(10) }) - print ({ i: j for i in range(10) for j in range(10) }) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'j'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - - def test_set_comps(self): - astroid = builder.parse(""" - print ({ i for i in range(10) }) - print ({ i for i in range(10) }) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - - def test_set_comp_closure(self): - astroid = builder.parse(""" - ten = { var for var in range(10) } - var - """) - var = astroid.body[1].value - self.assertRaises(exceptions.UnresolvableName, var.inferred) - - def test_generator_attributes(self): - tree = builder.parse(""" - def count(): - "test" - yield 0 - - iterer = count() - num = iterer.next() - """) - next_node = tree.body[2].value.func - gener = next_node.expr.inferred()[0] - if sys.version_info < (3, 0): - self.assertIsInstance(gener.getattr('next')[0], nodes.FunctionDef) - else: - self.assertIsInstance(gener.getattr('__next__')[0], nodes.FunctionDef) - self.assertIsInstance(gener.getattr('send')[0], nodes.FunctionDef) - self.assertIsInstance(gener.getattr('throw')[0], nodes.FunctionDef) - self.assertIsInstance(gener.getattr('close')[0], nodes.FunctionDef) - - def test_explicit___name__(self): - code = ''' - class Pouet: - __name__ = "pouet" - p1 = Pouet() - - class PouetPouet(Pouet): pass - p2 = Pouet() - - class NoName: pass - p3 = NoName() - ''' - astroid = builder.parse(code, __name__) - p1 = next(astroid['p1'].infer()) - self.assertTrue(p1.getattr('__name__')) - p2 = next(astroid['p2'].infer()) - self.assertTrue(p2.getattr('__name__')) - self.assertTrue(astroid['NoName'].getattr('__name__')) - p3 = next(astroid['p3'].infer()) - self.assertRaises(exceptions.NotFoundError, p3.getattr, '__name__') - - def test_function_module_special(self): - astroid = builder.parse(''' - def initialize(linter): - """initialize linter with checkers in this package """ - package_load(linter, __path__[0]) - ''', 'data.__init__') - path = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == '__path__'][0] - self.assertEqual(len(path.lookup('__path__')[1]), 1) - - def test_builtin_lookup(self): - self.assertEqual(scoped_nodes.builtin_lookup('__dict__')[1], ()) - intstmts = scoped_nodes.builtin_lookup('int')[1] - self.assertEqual(len(intstmts), 1) - self.assertIsInstance(intstmts[0], nodes.ClassDef) - self.assertEqual(intstmts[0].name, 'int') - self.assertIs(intstmts[0], nodes.const_factory(1)._proxied) - - def test_decorator_arguments_lookup(self): - code = ''' - def decorator(value): - def wrapper(function): - return function - return wrapper - - class foo: - member = 10 #@ - - @decorator(member) #This will cause pylint to complain - def test(self): - pass - ''' - member = test_utils.extract_node(code, __name__).targets[0] - it = member.infer() - obj = next(it) - self.assertIsInstance(obj, nodes.Const) - self.assertEqual(obj.value, 10) - self.assertRaises(StopIteration, functools.partial(next, it)) - - def test_inner_decorator_member_lookup(self): - code = ''' - class FileA: - def decorator(bla): - return bla - - @__(decorator) - def funcA(): - return 4 - ''' - decname = test_utils.extract_node(code, __name__) - it = decname.infer() - obj = next(it) - self.assertIsInstance(obj, nodes.FunctionDef) - self.assertRaises(StopIteration, functools.partial(next, it)) - - def test_static_method_lookup(self): - code = ''' - class FileA: - @staticmethod - def funcA(): - return 4 - - - class Test: - FileA = [1,2,3] - - def __init__(self): - print (FileA.funcA()) - ''' - astroid = builder.parse(code, __name__) - it = astroid['Test']['__init__'].ilookup('FileA') - obj = next(it) - self.assertIsInstance(obj, nodes.ClassDef) - self.assertRaises(StopIteration, functools.partial(next, it)) - - def test_global_delete(self): - code = ''' - def run2(): - f = Frobble() - - class Frobble: - pass - Frobble.mumble = True - - del Frobble - - def run1(): - f = Frobble() - ''' - astroid = builder.parse(code, __name__) - stmts = astroid['run2'].lookup('Frobbel')[1] - self.assertEqual(len(stmts), 0) - stmts = astroid['run1'].lookup('Frobbel')[1] - self.assertEqual(len(stmts), 0) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_manager.py b/pymode/libs/astroid/tests/unittest_manager.py deleted file mode 100644 index 452b759e..00000000 --- a/pymode/libs/astroid/tests/unittest_manager.py +++ /dev/null @@ -1,216 +0,0 @@ -# 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 . -import os -import platform -import sys -import unittest - -import six - -from astroid import exceptions -from astroid import manager -from astroid.tests import resources - - -BUILTINS = six.moves.builtins.__name__ - - -def _get_file_from_object(obj): - if platform.python_implementation() == 'Jython': - return obj.__file__.split("$py.class")[0] + ".py" - if sys.version_info > (3, 0): - return obj.__file__ - if not obj.__file__.endswith(".py"): - return obj.__file__[:-1] - return obj.__file__ - - -class AstroidManagerTest(resources.SysPathSetup, - resources.AstroidCacheSetupMixin, - unittest.TestCase): - - def setUp(self): - super(AstroidManagerTest, self).setUp() - self.manager = manager.AstroidManager() - self.manager.clear_cache(self._builtins) # take care of borg - - def test_ast_from_file(self): - filepath = unittest.__file__ - astroid = self.manager.ast_from_file(filepath) - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_file_cache(self): - filepath = unittest.__file__ - self.manager.ast_from_file(filepath) - astroid = self.manager.ast_from_file('unhandledName', 'unittest') - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_file_astro_builder(self): - filepath = unittest.__file__ - astroid = self.manager.ast_from_file(filepath, None, True, True) - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_file_name_astro_builder_exception(self): - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.ast_from_file, 'unhandledName') - - def test_do_not_expose_main(self): - obj = self.manager.ast_from_module_name('__main__') - self.assertEqual(obj.name, '__main__') - self.assertEqual(obj.items(), []) - - def test_ast_from_module_name(self): - astroid = self.manager.ast_from_module_name('unittest') - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_module_name_not_python_source(self): - astroid = self.manager.ast_from_module_name('time') - self.assertEqual(astroid.name, 'time') - self.assertIn('time', self.manager.astroid_cache) - self.assertEqual(astroid.pure_python, False) - - def test_ast_from_module_name_astro_builder_exception(self): - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.ast_from_module_name, - 'unhandledModule') - - def _test_ast_from_zip(self, archive): - origpath = sys.path[:] - sys.modules.pop('mypypa', None) - archive_path = resources.find(archive) - sys.path.insert(0, archive_path) - try: - module = self.manager.ast_from_module_name('mypypa') - self.assertEqual(module.name, 'mypypa') - end = os.path.join(archive, 'mypypa') - self.assertTrue(module.source_file.endswith(end), - "%s doesn't endswith %s" % (module.source_file, end)) - finally: - # remove the module, else after importing egg, we don't get the zip - if 'mypypa' in self.manager.astroid_cache: - del self.manager.astroid_cache['mypypa'] - del self.manager._mod_file_cache[('mypypa', None)] - if archive_path in sys.path_importer_cache: - del sys.path_importer_cache[archive_path] - sys.path = origpath - - def test_ast_from_module_name_egg(self): - self._test_ast_from_zip( - os.path.sep.join(['data', os.path.normcase('MyPyPa-0.1.0-py2.5.egg')]) - ) - - def test_ast_from_module_name_zip(self): - self._test_ast_from_zip( - os.path.sep.join(['data', os.path.normcase('MyPyPa-0.1.0-py2.5.zip')]) - ) - - def test_zip_import_data(self): - """check if zip_import_data works""" - filepath = resources.find('data/MyPyPa-0.1.0-py2.5.zip/mypypa') - astroid = self.manager.zip_import_data(filepath) - self.assertEqual(astroid.name, 'mypypa') - - def test_zip_import_data_without_zipimport(self): - """check if zip_import_data return None without zipimport""" - self.assertEqual(self.manager.zip_import_data('path'), None) - - def test_file_from_module(self): - """check if the unittest filepath is equals to the result of the method""" - self.assertEqual( - _get_file_from_object(unittest), - self.manager.file_from_module_name('unittest', None)[0]) - - def test_file_from_module_name_astro_building_exception(self): - """check if the method launch a exception with a wrong module name""" - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.file_from_module_name, 'unhandledModule', None) - - def test_ast_from_module(self): - astroid = self.manager.ast_from_module(unittest) - self.assertEqual(astroid.pure_python, True) - import time - astroid = self.manager.ast_from_module(time) - self.assertEqual(astroid.pure_python, False) - - def test_ast_from_module_cache(self): - """check if the module is in the cache manager""" - astroid = self.manager.ast_from_module(unittest) - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_class(self): - astroid = self.manager.ast_from_class(int) - self.assertEqual(astroid.name, 'int') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - - astroid = self.manager.ast_from_class(object) - self.assertEqual(astroid.name, 'object') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - self.assertIn('__setattr__', astroid) - - def test_ast_from_class_with_module(self): - """check if the method works with the module name""" - astroid = self.manager.ast_from_class(int, int.__module__) - self.assertEqual(astroid.name, 'int') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - - astroid = self.manager.ast_from_class(object, object.__module__) - self.assertEqual(astroid.name, 'object') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - self.assertIn('__setattr__', astroid) - - def test_ast_from_class_attr_error(self): - """give a wrong class at the ast_from_class method""" - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.ast_from_class, None) - - def testFailedImportHooks(self): - def hook(modname): - if modname == 'foo.bar': - return unittest - else: - raise exceptions.AstroidBuildingException() - - with self.assertRaises(exceptions.AstroidBuildingException): - self.manager.ast_from_module_name('foo.bar') - self.manager.register_failed_import_hook(hook) - self.assertEqual(unittest, self.manager.ast_from_module_name('foo.bar')) - with self.assertRaises(exceptions.AstroidBuildingException): - self.manager.ast_from_module_name('foo.bar.baz') - del self.manager._failed_import_hooks[0] - - -class BorgAstroidManagerTC(unittest.TestCase): - - def test_borg(self): - """test that the AstroidManager is really a borg, i.e. that two different - instances has same cache""" - first_manager = manager.AstroidManager() - built = first_manager.ast_from_module_name(BUILTINS) - - second_manager = manager.AstroidManager() - second_built = second_manager.ast_from_module_name(BUILTINS) - self.assertIs(built, second_built) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_modutils.py b/pymode/libs/astroid/tests/unittest_modutils.py deleted file mode 100644 index dffc3b8d..00000000 --- a/pymode/libs/astroid/tests/unittest_modutils.py +++ /dev/null @@ -1,269 +0,0 @@ -# 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 . -""" -unit tests for module modutils (module manipulation utilities) -""" -import os -import sys -import unittest - -from astroid import modutils -from astroid.tests import resources - - -def _get_file_from_object(obj): - return modutils._path_from_filename(obj.__file__) - - -class ModuleFileTest(unittest.TestCase): - package = "mypypa" - - def tearDown(self): - for k in list(sys.path_importer_cache.keys()): - if 'MyPyPa' in k: - del sys.path_importer_cache[k] - - def test_find_zipped_module(self): - mtype, mfile = modutils._module_file( - [self.package], [resources.find('data/MyPyPa-0.1.0-py2.5.zip')]) - self.assertEqual(mtype, modutils.PY_ZIPMODULE) - self.assertEqual(mfile.split(os.sep)[-3:], ["data", "MyPyPa-0.1.0-py2.5.zip", self.package]) - - def test_find_egg_module(self): - mtype, mfile = modutils._module_file( - [self.package], [resources.find('data/MyPyPa-0.1.0-py2.5.egg')]) - self.assertEqual(mtype, modutils.PY_ZIPMODULE) - self.assertEqual(mfile.split(os.sep)[-3:], ["data", "MyPyPa-0.1.0-py2.5.egg", self.package]) - - -class LoadModuleFromNameTest(unittest.TestCase): - """ load a python module from it's name """ - - def test_knownValues_load_module_from_name_1(self): - self.assertEqual(modutils.load_module_from_name('sys'), sys) - - def test_knownValues_load_module_from_name_2(self): - self.assertEqual(modutils.load_module_from_name('os.path'), os.path) - - def test_raise_load_module_from_name_1(self): - self.assertRaises(ImportError, - modutils.load_module_from_name, 'os.path', use_sys=0) - - -class GetModulePartTest(unittest.TestCase): - """given a dotted name return the module part of the name""" - - def test_knownValues_get_module_part_1(self): - self.assertEqual(modutils.get_module_part('astroid.modutils'), - 'astroid.modutils') - - def test_knownValues_get_module_part_2(self): - self.assertEqual(modutils.get_module_part('astroid.modutils.get_module_part'), - 'astroid.modutils') - - def test_knownValues_get_module_part_3(self): - """relative import from given file""" - self.assertEqual(modutils.get_module_part('node_classes.AssName', - modutils.__file__), 'node_classes') - - def test_knownValues_get_compiled_module_part(self): - self.assertEqual(modutils.get_module_part('math.log10'), 'math') - self.assertEqual(modutils.get_module_part('math.log10', __file__), 'math') - - def test_knownValues_get_builtin_module_part(self): - self.assertEqual(modutils.get_module_part('sys.path'), 'sys') - self.assertEqual(modutils.get_module_part('sys.path', '__file__'), 'sys') - - def test_get_module_part_exception(self): - self.assertRaises(ImportError, modutils.get_module_part, 'unknown.module', - modutils.__file__) - - -class ModPathFromFileTest(unittest.TestCase): - """ given an absolute file path return the python module's path as a list """ - - def test_knownValues_modpath_from_file_1(self): - from xml.etree import ElementTree - self.assertEqual(modutils.modpath_from_file(ElementTree.__file__), - ['xml', 'etree', 'ElementTree']) - - def test_knownValues_modpath_from_file_2(self): - self.assertEqual(modutils.modpath_from_file('unittest_modutils.py', - {os.getcwd(): 'arbitrary.pkg'}), - ['arbitrary', 'pkg', 'unittest_modutils']) - - def test_raise_modpath_from_file_Exception(self): - self.assertRaises(Exception, modutils.modpath_from_file, '/turlututu') - - -class LoadModuleFromPathTest(resources.SysPathSetup, unittest.TestCase): - - def test_do_not_load_twice(self): - modutils.load_module_from_modpath(['data', 'lmfp', 'foo']) - modutils.load_module_from_modpath(['data', 'lmfp']) - self.assertEqual(len(sys.just_once), 1) - del sys.just_once - - -class FileFromModPathTest(resources.SysPathSetup, unittest.TestCase): - """given a mod path (i.e. splited module / package name), return the - corresponding file, giving priority to source file over precompiled file - if it exists""" - - def test_site_packages(self): - filename = _get_file_from_object(modutils) - result = modutils.file_from_modpath(['astroid', 'modutils']) - self.assertEqual(os.path.realpath(result), os.path.realpath(filename)) - - def test_std_lib(self): - from os import path - self.assertEqual(os.path.realpath(modutils.file_from_modpath(['os', 'path']).replace('.pyc', '.py')), - os.path.realpath(path.__file__.replace('.pyc', '.py'))) - - def test_xmlplus(self): - try: - # don't fail if pyxml isn't installed - from xml.dom import ext - except ImportError: - pass - else: - self.assertEqual(os.path.realpath(modutils.file_from_modpath(['xml', 'dom', 'ext']).replace('.pyc', '.py')), - os.path.realpath(ext.__file__.replace('.pyc', '.py'))) - - def test_builtin(self): - self.assertEqual(modutils.file_from_modpath(['sys']), - None) - - - def test_unexisting(self): - self.assertRaises(ImportError, modutils.file_from_modpath, ['turlututu']) - - def test_unicode_in_package_init(self): - # file_from_modpath should not crash when reading an __init__ - # file with unicode characters. - modutils.file_from_modpath(["data", "unicode_package", "core"]) - - -class GetSourceFileTest(unittest.TestCase): - - def test(self): - filename = _get_file_from_object(os.path) - self.assertEqual(modutils.get_source_file(os.path.__file__), - os.path.normpath(filename)) - - def test_raise(self): - self.assertRaises(modutils.NoSourceFile, modutils.get_source_file, 'whatever') - - -class StandardLibModuleTest(resources.SysPathSetup, unittest.TestCase): - """ - return true if the module may be considered as a module from the standard - library - """ - - def test_datetime(self): - # This is an interesting example, since datetime, on pypy, - # is under lib_pypy, rather than the usual Lib directory. - self.assertTrue(modutils.is_standard_module('datetime')) - - def test_builtins(self): - if sys.version_info < (3, 0): - self.assertEqual(modutils.is_standard_module('__builtin__'), True) - self.assertEqual(modutils.is_standard_module('builtins'), False) - else: - self.assertEqual(modutils.is_standard_module('__builtin__'), False) - self.assertEqual(modutils.is_standard_module('builtins'), True) - - def test_builtin(self): - self.assertEqual(modutils.is_standard_module('sys'), True) - self.assertEqual(modutils.is_standard_module('marshal'), True) - - def test_nonstandard(self): - self.assertEqual(modutils.is_standard_module('astroid'), False) - - def test_unknown(self): - self.assertEqual(modutils.is_standard_module('unknown'), False) - - def test_4(self): - self.assertEqual(modutils.is_standard_module('hashlib'), True) - self.assertEqual(modutils.is_standard_module('pickle'), True) - self.assertEqual(modutils.is_standard_module('email'), True) - self.assertEqual(modutils.is_standard_module('io'), sys.version_info >= (2, 6)) - self.assertEqual(modutils.is_standard_module('StringIO'), sys.version_info < (3, 0)) - self.assertEqual(modutils.is_standard_module('unicodedata'), True) - - def test_custom_path(self): - datadir = resources.find('') - if datadir.startswith(modutils.EXT_LIB_DIR): - self.skipTest('known breakage of is_standard_module on installed package') - self.assertEqual(modutils.is_standard_module('data.module', (datadir,)), True) - self.assertEqual(modutils.is_standard_module('data.module', (os.path.abspath(datadir),)), True) - - def test_failing_edge_cases(self): - from xml import etree - # using a subpackage/submodule path as std_path argument - self.assertEqual(modutils.is_standard_module('xml.etree', etree.__path__), False) - # using a module + object name as modname argument - self.assertEqual(modutils.is_standard_module('sys.path'), True) - # this is because only the first package/module is considered - self.assertEqual(modutils.is_standard_module('sys.whatever'), True) - self.assertEqual(modutils.is_standard_module('xml.whatever', etree.__path__), False) - - -class IsRelativeTest(unittest.TestCase): - - - def test_knownValues_is_relative_1(self): - import email - self.assertEqual(modutils.is_relative('utils', email.__path__[0]), - True) - - def test_knownValues_is_relative_2(self): - from xml.etree import ElementTree - self.assertEqual(modutils.is_relative('ElementPath', ElementTree.__file__), - True) - - def test_knownValues_is_relative_3(self): - import astroid - self.assertEqual(modutils.is_relative('astroid', astroid.__path__[0]), - False) - - -class GetModuleFilesTest(unittest.TestCase): - - def test_get_module_files_1(self): - package = resources.find('data/find_test') - modules = set(modutils.get_module_files(package, [])) - expected = ['__init__.py', 'module.py', 'module2.py', - 'noendingnewline.py', 'nonregr.py'] - self.assertEqual(modules, - {os.path.join(package, x) for x in expected}) - - def test_load_module_set_attribute(self): - import xml.etree.ElementTree - import xml - del xml.etree.ElementTree - del sys.modules['xml.etree.ElementTree'] - m = modutils.load_module_from_modpath(['xml', 'etree', 'ElementTree']) - self.assertTrue(hasattr(xml, 'etree')) - self.assertTrue(hasattr(xml.etree, 'ElementTree')) - self.assertTrue(m is xml.etree.ElementTree) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_nodes.py b/pymode/libs/astroid/tests/unittest_nodes.py deleted file mode 100644 index 6fa4b6f3..00000000 --- a/pymode/libs/astroid/tests/unittest_nodes.py +++ /dev/null @@ -1,764 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of 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 . -"""tests for specific behaviour of astroid nodes -""" -import os -import sys -import textwrap -import unittest -import warnings - -import six - -from astroid import bases -from astroid import builder -from astroid import context as contextmod -from astroid import exceptions -from astroid import node_classes -from astroid import nodes -from astroid import parse -from astroid import util -from astroid import test_utils -from astroid import transforms -from astroid.tests import resources - - -abuilder = builder.AstroidBuilder() -BUILTINS = six.moves.builtins.__name__ - - -class AsStringTest(resources.SysPathSetup, unittest.TestCase): - - def test_tuple_as_string(self): - def build(string): - return abuilder.string_build(string).body[0].value - - self.assertEqual(build('1,').as_string(), '(1, )') - self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)') - self.assertEqual(build('(1, )').as_string(), '(1, )') - self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)') - - def test_as_string_for_list_containing_uninferable(self): - node = test_utils.extract_node(''' - def foo(arg): - bar = [arg] * 1 - ''') - binop = node.body[0].value - inferred = next(binop.infer()) - self.assertEqual(inferred.as_string(), '[Uninferable]') - self.assertEqual(binop.as_string(), '([arg]) * (1)') - - def test_frozenset_as_string(self): - nodes = test_utils.extract_node(''' - frozenset((1, 2, 3)) #@ - frozenset({1, 2, 3}) #@ - frozenset([1, 2, 3,]) #@ - - frozenset(None) #@ - frozenset(1) #@ - ''') - nodes = [next(node.infer()) for node in nodes] - - self.assertEqual(nodes[0].as_string(), 'frozenset((1, 2, 3))') - self.assertEqual(nodes[1].as_string(), 'frozenset({1, 2, 3})') - self.assertEqual(nodes[2].as_string(), 'frozenset([1, 2, 3])') - - self.assertNotEqual(nodes[3].as_string(), 'frozenset(None)') - self.assertNotEqual(nodes[4].as_string(), 'frozenset(1)') - - @test_utils.require_version(minver='3.0') - def test_func_signature_issue_185(self): - code = textwrap.dedent(''' - def test(a, b, c=42, *, x=42, **kwargs): - print(a, b, c, args) - ''') - node = parse(code) - self.assertEqual(node.as_string().strip(), code.strip()) - def test_varargs_kwargs_as_string(self): - ast = abuilder.string_build('raise_string(*args, **kwargs)').body[0] - self.assertEqual(ast.as_string(), 'raise_string(*args, **kwargs)') - - def test_module_as_string(self): - """check as_string on a whole module prepared to be returned identically - """ - module = resources.build_file('data/module.py', 'data.module') - with open(resources.find('data/module.py'), 'r') as fobj: - self.assertMultiLineEqual(module.as_string(), fobj.read()) - - def test_module2_as_string(self): - """check as_string on a whole module prepared to be returned identically - """ - module2 = resources.build_file('data/module2.py', 'data.module2') - with open(resources.find('data/module2.py'), 'r') as fobj: - self.assertMultiLineEqual(module2.as_string(), fobj.read()) - - def test_as_string(self): - """check as_string for python syntax >= 2.7""" - code = '''one_two = {1, 2} -b = {v: k for (k, v) in enumerate('string')} -cdd = {k for k in b}\n\n''' - ast = abuilder.string_build(code) - self.assertMultiLineEqual(ast.as_string(), code) - - @test_utils.require_version('3.0') - def test_3k_as_string(self): - """check as_string for python 3k syntax""" - code = '''print() - -def function(var): - nonlocal counter - try: - hello - except NameError as nexc: - (*hell, o) = b'hello' - raise AttributeError from nexc -\n''' - ast = abuilder.string_build(code) - self.assertEqual(ast.as_string(), code) - - @test_utils.require_version('3.0') - @unittest.expectedFailure - def test_3k_annotations_and_metaclass(self): - code_annotations = textwrap.dedent(''' - def function(var:int): - nonlocal counter - - class Language(metaclass=Natural): - """natural language""" - ''') - - ast = abuilder.string_build(code_annotations) - self.assertEqual(ast.as_string(), code_annotations) - - def test_ellipsis(self): - ast = abuilder.string_build('a[...]').body[0] - self.assertEqual(ast.as_string(), 'a[...]') - - def test_slices(self): - for code in ('a[0]', 'a[1:3]', 'a[:-1:step]', 'a[:,newaxis]', - 'a[newaxis,:]', 'del L[::2]', 'del A[1]', 'del Br[:]'): - ast = abuilder.string_build(code).body[0] - self.assertEqual(ast.as_string(), code) - - def test_slice_and_subscripts(self): - code = """a[:1] = bord[2:] -a[:1] = bord[2:] -del bree[3:d] -bord[2:] -del av[d::f], a[df:] -a[:1] = bord[2:] -del SRC[::1,newaxis,1:] -tous[vals] = 1010 -del thousand[key] -del a[::2], a[:-1:step] -del Fee.form[left:] -aout.vals = miles.of_stuff -del (ccok, (name.thing, foo.attrib.value)), Fee.form[left:] -if all[1] == bord[0:]: - pass\n\n""" - ast = abuilder.string_build(code) - self.assertEqual(ast.as_string(), code) - - -class _NodeTest(unittest.TestCase): - """test transformation of If Node""" - CODE = None - - @property - def astroid(self): - try: - return self.__class__.__dict__['CODE_Astroid'] - except KeyError: - astroid = builder.parse(self.CODE) - self.__class__.CODE_Astroid = astroid - return astroid - - -class IfNodeTest(_NodeTest): - """test transformation of If Node""" - CODE = """ - if 0: - print() - - if True: - print() - else: - pass - - if "": - print() - elif []: - raise - - if 1: - print() - elif True: - print() - elif func(): - pass - else: - raise - """ - - def test_if_elif_else_node(self): - """test transformation for If node""" - self.assertEqual(len(self.astroid.body), 4) - for stmt in self.astroid.body: - self.assertIsInstance(stmt, nodes.If) - self.assertFalse(self.astroid.body[0].orelse) # simple If - self.assertIsInstance(self.astroid.body[1].orelse[0], nodes.Pass) # If / else - self.assertIsInstance(self.astroid.body[2].orelse[0], nodes.If) # If / elif - self.assertIsInstance(self.astroid.body[3].orelse[0].orelse[0], nodes.If) - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.block_range(1), (0, 22)) - self.assertEqual(self.astroid.block_range(10), (0, 22)) # XXX (10, 22) ? - self.assertEqual(self.astroid.body[1].block_range(5), (5, 6)) - self.assertEqual(self.astroid.body[1].block_range(6), (6, 6)) - self.assertEqual(self.astroid.body[1].orelse[0].block_range(7), (7, 8)) - self.assertEqual(self.astroid.body[1].orelse[0].block_range(8), (8, 8)) - - -class TryExceptNodeTest(_NodeTest): - CODE = """ - try: - print ('pouet') - except IOError: - pass - except UnicodeError: - print() - else: - print() - """ - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.body[0].block_range(1), (1, 8)) - self.assertEqual(self.astroid.body[0].block_range(2), (2, 2)) - self.assertEqual(self.astroid.body[0].block_range(3), (3, 8)) - self.assertEqual(self.astroid.body[0].block_range(4), (4, 4)) - self.assertEqual(self.astroid.body[0].block_range(5), (5, 5)) - self.assertEqual(self.astroid.body[0].block_range(6), (6, 6)) - self.assertEqual(self.astroid.body[0].block_range(7), (7, 7)) - self.assertEqual(self.astroid.body[0].block_range(8), (8, 8)) - - -class TryFinallyNodeTest(_NodeTest): - CODE = """ - try: - print ('pouet') - finally: - print ('pouet') - """ - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.body[0].block_range(1), (1, 4)) - self.assertEqual(self.astroid.body[0].block_range(2), (2, 2)) - self.assertEqual(self.astroid.body[0].block_range(3), (3, 4)) - self.assertEqual(self.astroid.body[0].block_range(4), (4, 4)) - - -class TryExceptFinallyNodeTest(_NodeTest): - CODE = """ - try: - print('pouet') - except Exception: - print ('oops') - finally: - print ('pouet') - """ - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.body[0].block_range(1), (1, 6)) - self.assertEqual(self.astroid.body[0].block_range(2), (2, 2)) - self.assertEqual(self.astroid.body[0].block_range(3), (3, 4)) - self.assertEqual(self.astroid.body[0].block_range(4), (4, 4)) - self.assertEqual(self.astroid.body[0].block_range(5), (5, 5)) - self.assertEqual(self.astroid.body[0].block_range(6), (6, 6)) - - -@unittest.skipIf(six.PY3, "Python 2 specific test.") -class TryExcept2xNodeTest(_NodeTest): - CODE = """ - try: - hello - except AttributeError, (retval, desc): - pass - """ - - - def test_tuple_attribute(self): - handler = self.astroid.body[0].handlers[0] - self.assertIsInstance(handler.name, nodes.Tuple) - - -class ImportNodeTest(resources.SysPathSetup, unittest.TestCase): - def setUp(self): - super(ImportNodeTest, self).setUp() - self.module = resources.build_file('data/module.py', 'data.module') - self.module2 = resources.build_file('data/module2.py', 'data.module2') - - def test_import_self_resolve(self): - myos = next(self.module2.igetattr('myos')) - self.assertTrue(isinstance(myos, nodes.Module), myos) - self.assertEqual(myos.name, 'os') - self.assertEqual(myos.qname(), 'os') - self.assertEqual(myos.pytype(), '%s.module' % BUILTINS) - - def test_from_self_resolve(self): - namenode = next(self.module.igetattr('NameNode')) - self.assertTrue(isinstance(namenode, nodes.ClassDef), namenode) - self.assertEqual(namenode.root().name, 'astroid.node_classes') - self.assertEqual(namenode.qname(), 'astroid.node_classes.Name') - self.assertEqual(namenode.pytype(), '%s.type' % BUILTINS) - abspath = next(self.module2.igetattr('abspath')) - self.assertTrue(isinstance(abspath, nodes.FunctionDef), abspath) - self.assertEqual(abspath.root().name, 'os.path') - self.assertEqual(abspath.qname(), 'os.path.abspath') - self.assertEqual(abspath.pytype(), '%s.function' % BUILTINS) - - def test_real_name(self): - from_ = self.module['NameNode'] - self.assertEqual(from_.real_name('NameNode'), 'Name') - imp_ = self.module['os'] - self.assertEqual(imp_.real_name('os'), 'os') - self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'os.path') - imp_ = self.module['NameNode'] - self.assertEqual(imp_.real_name('NameNode'), 'Name') - self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'Name') - imp_ = self.module2['YO'] - self.assertEqual(imp_.real_name('YO'), 'YO') - self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'data') - - def test_as_string(self): - ast = self.module['modutils'] - self.assertEqual(ast.as_string(), "from astroid import modutils") - ast = self.module['NameNode'] - self.assertEqual(ast.as_string(), "from astroid.node_classes import Name as NameNode") - ast = self.module['os'] - self.assertEqual(ast.as_string(), "import os.path") - code = """from . import here -from .. import door -from .store import bread -from ..cave import wine\n\n""" - ast = abuilder.string_build(code) - self.assertMultiLineEqual(ast.as_string(), code) - - def test_bad_import_inference(self): - # Explication of bug - '''When we import PickleError from nonexistent, a call to the infer - method of this From node will be made by unpack_infer. - inference.infer_from will try to import this module, which will fail and - raise a InferenceException (by mixins.do_import_module). The infer_name - will catch this exception and yield and YES instead. - ''' - - code = ''' - try: - from pickle import PickleError - except ImportError: - from nonexistent import PickleError - - try: - pass - except PickleError: - pass - ''' - astroid = builder.parse(code) - handler_type = astroid.body[1].handlers[0].type - - excs = list(node_classes.unpack_infer(handler_type)) - # The number of returned object can differ on Python 2 - # and Python 3. In one version, an additional item will - # be returned, from the _pickle module, which is not - # present in the other version. - self.assertIsInstance(excs[0], nodes.ClassDef) - self.assertEqual(excs[0].name, 'PickleError') - self.assertIs(excs[-1], util.YES) - - def test_absolute_import(self): - astroid = resources.build_file('data/absimport.py') - ctx = contextmod.InferenceContext() - # will fail if absolute import failed - ctx.lookupname = 'message' - next(astroid['message'].infer(ctx)) - ctx.lookupname = 'email' - m = next(astroid['email'].infer(ctx)) - self.assertFalse(m.source_file.startswith(os.path.join('data', 'email.py'))) - - def test_more_absolute_import(self): - astroid = resources.build_file('data/module1abs/__init__.py', 'data.module1abs') - self.assertIn('sys', astroid._locals) - - -class CmpNodeTest(unittest.TestCase): - def test_as_string(self): - ast = abuilder.string_build("a == 2").body[0] - self.assertEqual(ast.as_string(), "a == 2") - - -class ConstNodeTest(unittest.TestCase): - - def _test(self, value): - node = nodes.const_factory(value) - self.assertIsInstance(node._proxied, nodes.ClassDef) - self.assertEqual(node._proxied.name, value.__class__.__name__) - self.assertIs(node.value, value) - self.assertTrue(node._proxied.parent) - self.assertEqual(node._proxied.root().name, value.__class__.__module__) - - def test_none(self): - self._test(None) - - def test_bool(self): - self._test(True) - - def test_int(self): - self._test(1) - - def test_float(self): - self._test(1.0) - - def test_complex(self): - self._test(1.0j) - - def test_str(self): - self._test('a') - - def test_unicode(self): - self._test(u'a') - - -class NameNodeTest(unittest.TestCase): - def test_assign_to_True(self): - """test that True and False assignements don't crash""" - code = """ - True = False - def hello(False): - pass - del True - """ - if sys.version_info >= (3, 0): - with self.assertRaises(exceptions.AstroidBuildingException): - builder.parse(code) - else: - ast = builder.parse(code) - assign_true = ast['True'] - self.assertIsInstance(assign_true, nodes.AssignName) - self.assertEqual(assign_true.name, "True") - del_true = ast.body[2].targets[0] - self.assertIsInstance(del_true, nodes.DelName) - self.assertEqual(del_true.name, "True") - - -class ArgumentsNodeTC(unittest.TestCase): - def test_linenumbering(self): - ast = builder.parse(''' - def func(a, - b): pass - x = lambda x: None - ''') - self.assertEqual(ast['func'].args.fromlineno, 2) - self.assertFalse(ast['func'].args.is_statement) - xlambda = next(ast['x'].infer()) - self.assertEqual(xlambda.args.fromlineno, 4) - self.assertEqual(xlambda.args.tolineno, 4) - self.assertFalse(xlambda.args.is_statement) - if sys.version_info < (3, 0): - self.assertEqual(ast['func'].args.tolineno, 3) - else: - self.skipTest('FIXME http://bugs.python.org/issue10445 ' - '(no line number on function args)') - - def test_builtin_fromlineno_missing(self): - cls = test_utils.extract_node(''' - class Foo(Exception): #@ - pass - ''') - new = cls.getattr('__new__')[-1] - self.assertEqual(new.args.fromlineno, 0) - - -class UnboundMethodNodeTest(unittest.TestCase): - - def test_no_super_getattr(self): - # This is a test for issue - # https://bitbucket.org/logilab/astroid/issue/91, which tests - # that UnboundMethod doesn't call super when doing .getattr. - - ast = builder.parse(''' - class A(object): - def test(self): - pass - meth = A.test - ''') - node = next(ast['meth'].infer()) - with self.assertRaises(exceptions.NotFoundError): - node.getattr('__missssing__') - name = node.getattr('__name__')[0] - self.assertIsInstance(name, nodes.Const) - self.assertEqual(name.value, 'test') - - -class BoundMethodNodeTest(unittest.TestCase): - - def test_is_property(self): - ast = builder.parse(''' - import abc - - def cached_property(): - # Not a real decorator, but we don't care - pass - def reify(): - # Same as cached_property - pass - def lazy_property(): - pass - def lazyproperty(): - pass - def lazy(): pass - class A(object): - @property - def builtin_property(self): - return 42 - @abc.abstractproperty - def abc_property(self): - return 42 - @cached_property - def cached_property(self): return 42 - @reify - def reified(self): return 42 - @lazy_property - def lazy_prop(self): return 42 - @lazyproperty - def lazyprop(self): return 42 - def not_prop(self): pass - @lazy - def decorated_with_lazy(self): return 42 - - cls = A() - builtin_property = cls.builtin_property - abc_property = cls.abc_property - cached_p = cls.cached_property - reified = cls.reified - not_prop = cls.not_prop - lazy_prop = cls.lazy_prop - lazyprop = cls.lazyprop - decorated_with_lazy = cls.decorated_with_lazy - ''') - for prop in ('builtin_property', 'abc_property', 'cached_p', 'reified', - 'lazy_prop', 'lazyprop', 'decorated_with_lazy'): - inferred = next(ast[prop].infer()) - self.assertIsInstance(inferred, nodes.Const, prop) - self.assertEqual(inferred.value, 42, prop) - - inferred = next(ast['not_prop'].infer()) - self.assertIsInstance(inferred, bases.BoundMethod) - - -class AliasesTest(unittest.TestCase): - - def setUp(self): - self.transformer = transforms.TransformVisitor() - - def parse_transform(self, code): - module = parse(code, apply_transforms=False) - return self.transformer.visit(module) - - def test_aliases(self): - def test_from(node): - node.names = node.names + [('absolute_import', None)] - return node - - def test_class(node): - node.name = 'Bar' - return node - - def test_function(node): - node.name = 'another_test' - return node - - def test_callfunc(node): - if node.func.name == 'Foo': - node.func.name = 'Bar' - return node - - def test_assname(node): - if node.name == 'foo': - n = nodes.AssignName() - n.name = 'bar' - return n - def test_assattr(node): - if node.attrname == 'a': - node.attrname = 'b' - return node - - def test_getattr(node): - if node.attrname == 'a': - node.attrname = 'b' - return node - - def test_genexpr(node): - if node.elt.value == 1: - node.elt = nodes.Const(2) - return node - - self.transformer.register_transform(nodes.From, test_from) - self.transformer.register_transform(nodes.Class, test_class) - self.transformer.register_transform(nodes.Function, test_function) - self.transformer.register_transform(nodes.CallFunc, test_callfunc) - self.transformer.register_transform(nodes.AssName, test_assname) - self.transformer.register_transform(nodes.AssAttr, test_assattr) - self.transformer.register_transform(nodes.Getattr, test_getattr) - self.transformer.register_transform(nodes.GenExpr, test_genexpr) - - string = ''' - from __future__ import print_function - - class Foo: pass - - def test(a): return a - - foo = Foo() - foo.a = test(42) - foo.a - (1 for _ in range(0, 42)) - ''' - - module = self.parse_transform(string) - - self.assertEqual(len(module.body[0].names), 2) - self.assertIsInstance(module.body[0], nodes.ImportFrom) - self.assertEqual(module.body[1].name, 'Bar') - self.assertIsInstance(module.body[1], nodes.ClassDef) - self.assertEqual(module.body[2].name, 'another_test') - self.assertIsInstance(module.body[2], nodes.FunctionDef) - self.assertEqual(module.body[3].targets[0].name, 'bar') - self.assertIsInstance(module.body[3].targets[0], nodes.AssignName) - self.assertEqual(module.body[3].value.func.name, 'Bar') - self.assertIsInstance(module.body[3].value, nodes.Call) - self.assertEqual(module.body[4].targets[0].attrname, 'b') - self.assertIsInstance(module.body[4].targets[0], nodes.AssignAttr) - self.assertIsInstance(module.body[5], nodes.Expr) - self.assertEqual(module.body[5].value.attrname, 'b') - self.assertIsInstance(module.body[5].value, nodes.Attribute) - self.assertEqual(module.body[6].value.elt.value, 2) - self.assertIsInstance(module.body[6].value, nodes.GeneratorExp) - - @unittest.skipIf(six.PY3, "Python 3 doesn't have Repr nodes.") - def test_repr(self): - def test_backquote(node): - node.value.name = 'bar' - return node - - self.transformer.register_transform(nodes.Backquote, test_backquote) - - module = self.parse_transform('`foo`') - - self.assertEqual(module.body[0].value.value.name, 'bar') - self.assertIsInstance(module.body[0].value, nodes.Repr) - - -class DeprecationWarningsTest(unittest.TestCase): - def test_asstype_warnings(self): - string = ''' - class C: pass - c = C() - with warnings.catch_warnings(record=True) as w: - pass - ''' - module = parse(string) - filter_stmts_mixin = module.body[0] - assign_type_mixin = module.body[1].targets[0] - parent_assign_type_mixin = module.body[2] - - warnings.simplefilter('always') - - with warnings.catch_warnings(record=True) as w: - filter_stmts_mixin.ass_type() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - with warnings.catch_warnings(record=True) as w: - assign_type_mixin.ass_type() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - with warnings.catch_warnings(record=True) as w: - parent_assign_type_mixin.ass_type() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - - def test_isinstance_warnings(self): - msg_format = ("%r is deprecated and slated for removal in astroid " - "2.0, use %r instead") - for cls in (nodes.Discard, nodes.Backquote, nodes.AssName, - nodes.AssAttr, nodes.Getattr, nodes.CallFunc, nodes.From): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - isinstance(42, cls) - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - actual_msg = msg_format % (cls.__class__.__name__, cls.__wrapped__.__name__) - self.assertEqual(str(w[0].message), actual_msg) - - -@test_utils.require_version('3.5') -class Python35AsyncTest(unittest.TestCase): - - def test_async_await_keywords(self): - async_def, async_for, async_with, await_node = test_utils.extract_node(''' - async def func(): #@ - async for i in range(10): #@ - f = __(await i) - async with test(): #@ - pass - ''') - self.assertIsInstance(async_def, nodes.AsyncFunctionDef) - self.assertIsInstance(async_for, nodes.AsyncFor) - self.assertIsInstance(async_with, nodes.AsyncWith) - self.assertIsInstance(await_node, nodes.Await) - self.assertIsInstance(await_node.value, nodes.Name) - - def _test_await_async_as_string(self, code): - ast_node = parse(code) - self.assertEqual(ast_node.as_string().strip(), code.strip()) - - def test_await_as_string(self): - code = textwrap.dedent(''' - async def function(): - await 42 - ''') - self._test_await_async_as_string(code) - - def test_asyncwith_as_string(self): - code = textwrap.dedent(''' - async def function(): - async with (42): - pass - ''') - self._test_await_async_as_string(code) - - def test_asyncfor_as_string(self): - code = textwrap.dedent(''' - async def function(): - async for i in range(10): - await 42 - ''') - self._test_await_async_as_string(code) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_objects.py b/pymode/libs/astroid/tests/unittest_objects.py deleted file mode 100644 index 62d3f4ff..00000000 --- a/pymode/libs/astroid/tests/unittest_objects.py +++ /dev/null @@ -1,530 +0,0 @@ -# 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 . - -import unittest - -from astroid import bases -from astroid import exceptions -from astroid import nodes -from astroid import objects -from astroid import test_utils - - -class ObjectsTest(unittest.TestCase): - - def test_frozenset(self): - node = test_utils.extract_node(""" - frozenset({1: 2, 2: 3}) #@ - """) - infered = next(node.infer()) - self.assertIsInstance(infered, objects.FrozenSet) - - self.assertEqual(infered.pytype(), "%s.frozenset" % bases.BUILTINS) - - itered = infered.itered() - self.assertEqual(len(itered), 2) - self.assertIsInstance(itered[0], nodes.Const) - self.assertEqual([const.value for const in itered], [1, 2]) - - proxied = infered._proxied - self.assertEqual(infered.qname(), "%s.frozenset" % bases.BUILTINS) - self.assertIsInstance(proxied, nodes.ClassDef) - - -class SuperTests(unittest.TestCase): - - def test_inferring_super_outside_methods(self): - ast_nodes = test_utils.extract_node(''' - class Module(object): - pass - class StaticMethod(object): - @staticmethod - def static(): - # valid, but we don't bother with it. - return super(StaticMethod, StaticMethod) #@ - # super outside methods aren't inferred - super(Module, Module) #@ - # no argument super is not recognised outside methods as well. - super() #@ - ''') - in_static = next(ast_nodes[0].value.infer()) - self.assertIsInstance(in_static, bases.Instance) - self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS) - - module_level = next(ast_nodes[1].infer()) - self.assertIsInstance(module_level, bases.Instance) - self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS) - - no_arguments = next(ast_nodes[2].infer()) - self.assertIsInstance(no_arguments, bases.Instance) - self.assertEqual(no_arguments.qname(), "%s.super" % bases.BUILTINS) - - def test_inferring_unbound_super_doesnt_work(self): - node = test_utils.extract_node(''' - class Test(object): - def __init__(self): - super(Test) #@ - ''') - unbounded = next(node.infer()) - self.assertIsInstance(unbounded, bases.Instance) - self.assertEqual(unbounded.qname(), "%s.super" % bases.BUILTINS) - - def test_use_default_inference_on_not_inferring_args(self): - ast_nodes = test_utils.extract_node(''' - class Test(object): - def __init__(self): - super(Lala, self) #@ - super(Test, lala) #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.Instance) - self.assertEqual(first.qname(), "%s.super" % bases.BUILTINS) - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.Instance) - self.assertEqual(second.qname(), "%s.super" % bases.BUILTINS) - - @test_utils.require_version(maxver='3.0') - def test_super_on_old_style_class(self): - # super doesn't work on old style class, but leave - # that as an error for pylint. We'll infer Super objects, - # but every call will result in a failure at some point. - node = test_utils.extract_node(''' - class OldStyle: - def __init__(self): - super(OldStyle, self) #@ - ''') - old = next(node.infer()) - self.assertIsInstance(old, objects.Super) - self.assertIsInstance(old.mro_pointer, nodes.ClassDef) - self.assertEqual(old.mro_pointer.name, 'OldStyle') - with self.assertRaises(exceptions.SuperError) as cm: - old.super_mro() - self.assertEqual(str(cm.exception), - "Unable to call super on old-style classes.") - - @test_utils.require_version(minver='3.0') - def test_no_arguments_super(self): - ast_nodes = test_utils.extract_node(''' - class First(object): pass - class Second(First): - def test(self): - super() #@ - @classmethod - def test_classmethod(cls): - super() #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, objects.Super) - self.assertIsInstance(first.type, bases.Instance) - self.assertEqual(first.type.name, 'Second') - self.assertIsInstance(first.mro_pointer, nodes.ClassDef) - self.assertEqual(first.mro_pointer.name, 'Second') - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, objects.Super) - self.assertIsInstance(second.type, nodes.ClassDef) - self.assertEqual(second.type.name, 'Second') - self.assertIsInstance(second.mro_pointer, nodes.ClassDef) - self.assertEqual(second.mro_pointer.name, 'Second') - - def test_super_simple_cases(self): - ast_nodes = test_utils.extract_node(''' - class First(object): pass - class Second(First): pass - class Third(First): - def test(self): - super(Third, self) #@ - super(Second, self) #@ - - # mro position and the type - super(Third, Third) #@ - super(Third, Second) #@ - super(Fourth, Fourth) #@ - - class Fourth(Third): - pass - ''') - - # .type is the object which provides the mro. - # .mro_pointer is the position in the mro from where - # the lookup should be done. - - # super(Third, self) - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, objects.Super) - self.assertIsInstance(first.type, bases.Instance) - self.assertEqual(first.type.name, 'Third') - self.assertIsInstance(first.mro_pointer, nodes.ClassDef) - self.assertEqual(first.mro_pointer.name, 'Third') - - # super(Second, self) - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, objects.Super) - self.assertIsInstance(second.type, bases.Instance) - self.assertEqual(second.type.name, 'Third') - self.assertIsInstance(first.mro_pointer, nodes.ClassDef) - self.assertEqual(second.mro_pointer.name, 'Second') - - # super(Third, Third) - third = next(ast_nodes[2].infer()) - self.assertIsInstance(third, objects.Super) - self.assertIsInstance(third.type, nodes.ClassDef) - self.assertEqual(third.type.name, 'Third') - self.assertIsInstance(third.mro_pointer, nodes.ClassDef) - self.assertEqual(third.mro_pointer.name, 'Third') - - # super(Third, second) - fourth = next(ast_nodes[3].infer()) - self.assertIsInstance(fourth, objects.Super) - self.assertIsInstance(fourth.type, nodes.ClassDef) - self.assertEqual(fourth.type.name, 'Second') - self.assertIsInstance(fourth.mro_pointer, nodes.ClassDef) - self.assertEqual(fourth.mro_pointer.name, 'Third') - - # Super(Fourth, Fourth) - fifth = next(ast_nodes[4].infer()) - self.assertIsInstance(fifth, objects.Super) - self.assertIsInstance(fifth.type, nodes.ClassDef) - self.assertEqual(fifth.type.name, 'Fourth') - self.assertIsInstance(fifth.mro_pointer, nodes.ClassDef) - self.assertEqual(fifth.mro_pointer.name, 'Fourth') - - def test_super_infer(self): - node = test_utils.extract_node(''' - class Super(object): - def __init__(self): - super(Super, self) #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, objects.Super) - reinferred = next(inferred.infer()) - self.assertIsInstance(reinferred, objects.Super) - self.assertIs(inferred, reinferred) - - def test_inferring_invalid_supers(self): - ast_nodes = test_utils.extract_node(''' - class Super(object): - def __init__(self): - # MRO pointer is not a type - super(1, self) #@ - # MRO type is not a subtype - super(Super, 1) #@ - # self is not a subtype of Bupper - super(Bupper, self) #@ - class Bupper(Super): - pass - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, objects.Super) - with self.assertRaises(exceptions.SuperError) as cm: - first.super_mro() - self.assertEqual(str(cm.exception), "The first super argument must be type.") - - for node in ast_nodes[1:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, objects.Super, node) - with self.assertRaises(exceptions.SuperArgumentTypeError) as cm: - inferred.super_mro() - self.assertEqual(str(cm.exception), - "super(type, obj): obj must be an instance " - "or subtype of type", node) - - def test_proxied(self): - node = test_utils.extract_node(''' - class Super(object): - def __init__(self): - super(Super, self) #@ - ''') - infered = next(node.infer()) - proxied = infered._proxied - self.assertEqual(proxied.qname(), "%s.super" % bases.BUILTINS) - self.assertIsInstance(proxied, nodes.ClassDef) - - def test_super_bound_model(self): - ast_nodes = test_utils.extract_node(''' - class First(object): - def method(self): - pass - @classmethod - def class_method(cls): - pass - class Super_Type_Type(First): - def method(self): - super(Super_Type_Type, Super_Type_Type).method #@ - super(Super_Type_Type, Super_Type_Type).class_method #@ - @classmethod - def class_method(cls): - super(Super_Type_Type, Super_Type_Type).method #@ - super(Super_Type_Type, Super_Type_Type).class_method #@ - - class Super_Type_Object(First): - def method(self): - super(Super_Type_Object, self).method #@ - super(Super_Type_Object, self).class_method #@ - ''') - # Super(type, type) is the same for both functions and classmethods. - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, nodes.FunctionDef) - self.assertEqual(first.name, 'method') - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.BoundMethod) - self.assertEqual(second.bound.name, 'First') - self.assertEqual(second.type, 'classmethod') - - third = next(ast_nodes[2].infer()) - self.assertIsInstance(third, nodes.FunctionDef) - self.assertEqual(third.name, 'method') - - fourth = next(ast_nodes[3].infer()) - self.assertIsInstance(fourth, bases.BoundMethod) - self.assertEqual(fourth.bound.name, 'First') - self.assertEqual(fourth.type, 'classmethod') - - # Super(type, obj) can lead to different attribute bindings - # depending on the type of the place where super was called. - fifth = next(ast_nodes[4].infer()) - self.assertIsInstance(fifth, bases.BoundMethod) - self.assertEqual(fifth.bound.name, 'First') - self.assertEqual(fifth.type, 'method') - - sixth = next(ast_nodes[5].infer()) - self.assertIsInstance(sixth, bases.BoundMethod) - self.assertEqual(sixth.bound.name, 'First') - self.assertEqual(sixth.type, 'classmethod') - - def test_super_getattr_single_inheritance(self): - ast_nodes = test_utils.extract_node(''' - class First(object): - def test(self): pass - class Second(First): - def test2(self): pass - class Third(Second): - test3 = 42 - def __init__(self): - super(Third, self).test2 #@ - super(Third, self).test #@ - # test3 is local, no MRO lookup is done. - super(Third, self).test3 #@ - super(Third, self) #@ - - # Unbounds. - super(Third, Third).test2 #@ - super(Third, Third).test #@ - - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.BoundMethod) - self.assertEqual(first.bound.name, 'Second') - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.BoundMethod) - self.assertEqual(second.bound.name, 'First') - - with self.assertRaises(exceptions.InferenceError): - next(ast_nodes[2].infer()) - fourth = next(ast_nodes[3].infer()) - with self.assertRaises(exceptions.NotFoundError): - fourth.getattr('test3') - with self.assertRaises(exceptions.NotFoundError): - next(fourth.igetattr('test3')) - - first_unbound = next(ast_nodes[4].infer()) - self.assertIsInstance(first_unbound, nodes.FunctionDef) - self.assertEqual(first_unbound.name, 'test2') - self.assertEqual(first_unbound.parent.name, 'Second') - - second_unbound = next(ast_nodes[5].infer()) - self.assertIsInstance(second_unbound, nodes.FunctionDef) - self.assertEqual(second_unbound.name, 'test') - self.assertEqual(second_unbound.parent.name, 'First') - - def test_super_invalid_mro(self): - node = test_utils.extract_node(''' - class A(object): - test = 42 - class Super(A, A): - def __init__(self): - super(Super, self) #@ - ''') - inferred = next(node.infer()) - with self.assertRaises(exceptions.NotFoundError): - next(inferred.getattr('test')) - - def test_super_complex_mro(self): - ast_nodes = test_utils.extract_node(''' - class A(object): - def spam(self): return "A" - def foo(self): return "A" - @staticmethod - def static(self): pass - class B(A): - def boo(self): return "B" - def spam(self): return "B" - class C(A): - def boo(self): return "C" - class E(C, B): - def __init__(self): - super(E, self).boo #@ - super(C, self).boo #@ - super(E, self).spam #@ - super(E, self).foo #@ - super(E, self).static #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.BoundMethod) - self.assertEqual(first.bound.name, 'C') - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.BoundMethod) - self.assertEqual(second.bound.name, 'B') - third = next(ast_nodes[2].infer()) - self.assertIsInstance(third, bases.BoundMethod) - self.assertEqual(third.bound.name, 'B') - fourth = next(ast_nodes[3].infer()) - self.assertEqual(fourth.bound.name, 'A') - static = next(ast_nodes[4].infer()) - self.assertIsInstance(static, nodes.FunctionDef) - self.assertEqual(static.parent.scope().name, 'A') - - def test_super_data_model(self): - ast_nodes = test_utils.extract_node(''' - class X(object): pass - class A(X): - def __init__(self): - super(A, self) #@ - super(A, A) #@ - super(X, A) #@ - ''') - first = next(ast_nodes[0].infer()) - thisclass = first.getattr('__thisclass__')[0] - self.assertIsInstance(thisclass, nodes.ClassDef) - self.assertEqual(thisclass.name, 'A') - selfclass = first.getattr('__self_class__')[0] - self.assertIsInstance(selfclass, nodes.ClassDef) - self.assertEqual(selfclass.name, 'A') - self_ = first.getattr('__self__')[0] - self.assertIsInstance(self_, bases.Instance) - self.assertEqual(self_.name, 'A') - cls = first.getattr('__class__')[0] - self.assertEqual(cls, first._proxied) - - second = next(ast_nodes[1].infer()) - thisclass = second.getattr('__thisclass__')[0] - self.assertEqual(thisclass.name, 'A') - self_ = second.getattr('__self__')[0] - self.assertIsInstance(self_, nodes.ClassDef) - self.assertEqual(self_.name, 'A') - - third = next(ast_nodes[2].infer()) - thisclass = third.getattr('__thisclass__')[0] - self.assertEqual(thisclass.name, 'X') - selfclass = third.getattr('__self_class__')[0] - self.assertEqual(selfclass.name, 'A') - - def assertEqualMro(self, klass, expected_mro): - self.assertEqual( - [member.name for member in klass.super_mro()], - expected_mro) - - def test_super_mro(self): - ast_nodes = test_utils.extract_node(''' - class A(object): pass - class B(A): pass - class C(A): pass - class E(C, B): - def __init__(self): - super(E, self) #@ - super(C, self) #@ - super(B, self) #@ - - super(B, 1) #@ - super(1, B) #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertEqualMro(first, ['C', 'B', 'A', 'object']) - second = next(ast_nodes[1].infer()) - self.assertEqualMro(second, ['B', 'A', 'object']) - third = next(ast_nodes[2].infer()) - self.assertEqualMro(third, ['A', 'object']) - - fourth = next(ast_nodes[3].infer()) - with self.assertRaises(exceptions.SuperError): - fourth.super_mro() - fifth = next(ast_nodes[4].infer()) - with self.assertRaises(exceptions.SuperError): - fifth.super_mro() - - def test_super_yes_objects(self): - ast_nodes = test_utils.extract_node(''' - from collections import Missing - class A(object): - def __init__(self): - super(Missing, self) #@ - super(A, Missing) #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.Instance) - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.Instance) - - def test_super_invalid_types(self): - node = test_utils.extract_node(''' - import collections - class A(object): - def __init__(self): - super(A, collections) #@ - ''') - inferred = next(node.infer()) - with self.assertRaises(exceptions.SuperError): - inferred.super_mro() - with self.assertRaises(exceptions.SuperArgumentTypeError): - inferred.super_mro() - - def test_super_pytype_display_type_name(self): - node = test_utils.extract_node(''' - class A(object): - def __init__(self): - super(A, self) #@ - ''') - inferred = next(node.infer()) - self.assertEqual(inferred.pytype(), "%s.super" % bases.BUILTINS) - self.assertEqual(inferred.display_type(), 'Super of') - self.assertEqual(inferred.name, 'A') - - def test_super_properties(self): - node = test_utils.extract_node(''' - class Foo(object): - @property - def dict(self): - return 42 - - class Bar(Foo): - @property - def dict(self): - return super(Bar, self).dict - - Bar().dict - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_peephole.py b/pymode/libs/astroid/tests/unittest_peephole.py deleted file mode 100644 index 78349898..00000000 --- a/pymode/libs/astroid/tests/unittest_peephole.py +++ /dev/null @@ -1,121 +0,0 @@ -# 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 . - -"""Tests for the astroid AST peephole optimizer.""" - -import ast -import textwrap -import unittest - -import astroid -from astroid import astpeephole -from astroid import builder -from astroid import manager -from astroid import test_utils -from astroid.tests import resources - - -MANAGER = manager.AstroidManager() - - -class PeepholeOptimizer(unittest.TestCase): - @classmethod - def setUpClass(cls): - MANAGER.optimize_ast = True - - @classmethod - def tearDownClass(cls): - MANAGER.optimize_ast = False - - def setUp(self): - self._optimizer = astpeephole.ASTPeepholeOptimizer() - - @staticmethod - def _get_binops(code): - module = ast.parse(textwrap.dedent(code)) - return [node.value for node in module.body - if isinstance(node, ast.Expr)] - - @test_utils.require_version(maxver='3.0') - def test_optimize_binop_unicode(self): - nodes = self._get_binops(""" - u"a" + u"b" + u"c" - - u"a" + "c" + "b" - u"a" + b"c" - """) - - result = self._optimizer.optimize_binop(nodes[0]) - self.assertIsInstance(result, astroid.Const) - self.assertEqual(result.value, u"abc") - - self.assertIsNone(self._optimizer.optimize_binop(nodes[1])) - self.assertIsNone(self._optimizer.optimize_binop(nodes[2])) - - def test_optimize_binop(self): - nodes = self._get_binops(""" - "a" + "b" + "c" + "d" - b"a" + b"b" + b"c" + b"d" - "a" + "b" - - "a" + "b" + 1 + object - var = 4 - "a" + "b" + var + "c" - "a" + "b" + "c" - "4" - "a" + "b" + "c" + "d".format() - "a" - "b" - "a" - 1 + 4 + 5 + 6 - """) - - result = self._optimizer.optimize_binop(nodes[0]) - self.assertIsInstance(result, astroid.Const) - self.assertEqual(result.value, "abcd") - - result = self._optimizer.optimize_binop(nodes[1]) - self.assertIsInstance(result, astroid.Const) - self.assertEqual(result.value, b"abcd") - - for node in nodes[2:]: - self.assertIsNone(self._optimizer.optimize_binop(node)) - - def test_big_binop_crash(self): - # Test that we don't fail on a lot of joined strings - # through the addition operator. - module = resources.build_file('data/joined_strings.py') - element = next(module['x'].infer()) - self.assertIsInstance(element, astroid.Const) - self.assertEqual(len(element.value), 61660) - - def test_optimisation_disabled(self): - try: - MANAGER.optimize_ast = False - module = builder.parse(""" - '1' + '2' + '3' - """) - self.assertIsInstance(module.body[0], astroid.Expr) - self.assertIsInstance(module.body[0].value, astroid.BinOp) - self.assertIsInstance(module.body[0].value.left, astroid.BinOp) - self.assertIsInstance(module.body[0].value.left.left, - astroid.Const) - finally: - MANAGER.optimize_ast = True - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_protocols.py b/pymode/libs/astroid/tests/unittest_protocols.py deleted file mode 100644 index 16745129..00000000 --- a/pymode/libs/astroid/tests/unittest_protocols.py +++ /dev/null @@ -1,176 +0,0 @@ -# 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 . - -import contextlib -import unittest - -import astroid -from astroid.test_utils import extract_node, require_version -from astroid import InferenceError -from astroid import nodes -from astroid import util -from astroid.node_classes import AssignName, Const, Name, Starred - - -@contextlib.contextmanager -def _add_transform(manager, node, transform, predicate=None): - manager.register_transform(node, transform, predicate) - try: - yield - finally: - manager.unregister_transform(node, transform, predicate) - - -class ProtocolTests(unittest.TestCase): - - def assertConstNodesEqual(self, nodes_list_expected, nodes_list_got): - self.assertEqual(len(nodes_list_expected), len(nodes_list_got)) - for node in nodes_list_got: - self.assertIsInstance(node, Const) - for node, expected_value in zip(nodes_list_got, nodes_list_expected): - self.assertEqual(expected_value, node.value) - - def assertNameNodesEqual(self, nodes_list_expected, nodes_list_got): - self.assertEqual(len(nodes_list_expected), len(nodes_list_got)) - for node in nodes_list_got: - self.assertIsInstance(node, Name) - for node, expected_name in zip(nodes_list_got, nodes_list_expected): - self.assertEqual(expected_name, node.name) - - def test_assigned_stmts_simple_for(self): - assign_stmts = extract_node(""" - for a in (1, 2, 3): #@ - pass - - for b in range(3): #@ - pass - """) - - for1_assnode = next(assign_stmts[0].nodes_of_class(AssignName)) - assigned = list(for1_assnode.assigned_stmts()) - self.assertConstNodesEqual([1, 2, 3], assigned) - - for2_assnode = next(assign_stmts[1].nodes_of_class(AssignName)) - self.assertRaises(InferenceError, - list, for2_assnode.assigned_stmts()) - - @require_version(minver='3.0') - def test_assigned_stmts_starred_for(self): - assign_stmts = extract_node(""" - for *a, b in ((1, 2, 3), (4, 5, 6, 7)): #@ - pass - """) - - for1_starred = next(assign_stmts.nodes_of_class(Starred)) - assigned = next(for1_starred.assigned_stmts()) - self.assertEqual(assigned, util.YES) - - def _get_starred_stmts(self, code): - assign_stmt = extract_node("{} #@".format(code)) - starred = next(assign_stmt.nodes_of_class(Starred)) - return next(starred.assigned_stmts()) - - def _helper_starred_expected_const(self, code, expected): - stmts = self._get_starred_stmts(code) - self.assertIsInstance(stmts, nodes.List) - stmts = stmts.elts - self.assertConstNodesEqual(expected, stmts) - - def _helper_starred_expected(self, code, expected): - stmts = self._get_starred_stmts(code) - self.assertEqual(expected, stmts) - - def _helper_starred_inference_error(self, code): - assign_stmt = extract_node("{} #@".format(code)) - starred = next(assign_stmt.nodes_of_class(Starred)) - self.assertRaises(InferenceError, list, starred.assigned_stmts()) - - @require_version(minver='3.0') - def test_assigned_stmts_starred_assnames(self): - self._helper_starred_expected_const( - "a, *b = (1, 2, 3, 4) #@", [2, 3, 4]) - self._helper_starred_expected_const( - "*a, b = (1, 2, 3) #@", [1, 2]) - self._helper_starred_expected_const( - "a, *b, c = (1, 2, 3, 4, 5) #@", - [2, 3, 4]) - self._helper_starred_expected_const( - "a, *b = (1, 2) #@", [2]) - self._helper_starred_expected_const( - "*b, a = (1, 2) #@", [1]) - self._helper_starred_expected_const( - "[*b] = (1, 2) #@", [1, 2]) - - @require_version(minver='3.0') - def test_assigned_stmts_starred_yes(self): - # Not something iterable and known - self._helper_starred_expected("a, *b = range(3) #@", util.YES) - # Not something inferrable - self._helper_starred_expected("a, *b = balou() #@", util.YES) - # In function, unknown. - self._helper_starred_expected(""" - def test(arg): - head, *tail = arg #@""", util.YES) - # These cases aren't worth supporting. - self._helper_starred_expected( - "a, (*b, c), d = (1, (2, 3, 4), 5) #@", util.YES) - - @require_version(minver='3.0') - def test_assign_stmts_starred_fails(self): - # Too many starred - self._helper_starred_inference_error("a, *b, *c = (1, 2, 3) #@") - # Too many lhs values - self._helper_starred_inference_error("a, *b, c = (1, 2) #@") - # This could be solved properly, but it complicates needlessly the - # code for assigned_stmts, without oferring real benefit. - self._helper_starred_inference_error( - "(*a, b), (c, *d) = (1, 2, 3), (4, 5, 6) #@") - - def test_assigned_stmts_assignments(self): - assign_stmts = extract_node(""" - c = a #@ - - d, e = b, c #@ - """) - - simple_assnode = next(assign_stmts[0].nodes_of_class(AssignName)) - assigned = list(simple_assnode.assigned_stmts()) - self.assertNameNodesEqual(['a'], assigned) - - assnames = assign_stmts[1].nodes_of_class(AssignName) - simple_mul_assnode_1 = next(assnames) - assigned = list(simple_mul_assnode_1.assigned_stmts()) - self.assertNameNodesEqual(['b'], assigned) - simple_mul_assnode_2 = next(assnames) - assigned = list(simple_mul_assnode_2.assigned_stmts()) - self.assertNameNodesEqual(['c'], assigned) - - def test_sequence_assigned_stmts_not_accepting_empty_node(self): - def transform(node): - node.root().locals['__all__'] = [node.value] - - manager = astroid.MANAGER - with _add_transform(manager, astroid.Assign, transform): - module = astroid.parse(''' - __all__ = ['a'] - ''') - module.wildcard_import_names() - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_python3.py b/pymode/libs/astroid/tests/unittest_python3.py deleted file mode 100644 index 87010571..00000000 --- a/pymode/libs/astroid/tests/unittest_python3.py +++ /dev/null @@ -1,254 +0,0 @@ -# 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 . -from textwrap import dedent -import unittest - -from astroid import nodes -from astroid.node_classes import Assign, Expr, YieldFrom, Name, Const -from astroid.builder import AstroidBuilder -from astroid.scoped_nodes import ClassDef, FunctionDef -from astroid.test_utils import require_version, extract_node - - -class Python3TC(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.builder = AstroidBuilder() - - @require_version('3.0') - def test_starred_notation(self): - astroid = self.builder.string_build("*a, b = [1, 2, 3]", 'test', 'test') - - # Get the star node - node = next(next(next(astroid.get_children()).get_children()).get_children()) - - self.assertTrue(isinstance(node.assign_type(), Assign)) - - @require_version('3.3') - def test_yield_from(self): - body = dedent(""" - def func(): - yield from iter([1, 2]) - """) - astroid = self.builder.string_build(body) - func = astroid.body[0] - self.assertIsInstance(func, FunctionDef) - yieldfrom_stmt = func.body[0] - - self.assertIsInstance(yieldfrom_stmt, Expr) - self.assertIsInstance(yieldfrom_stmt.value, YieldFrom) - self.assertEqual(yieldfrom_stmt.as_string(), - 'yield from iter([1, 2])') - - @require_version('3.3') - def test_yield_from_is_generator(self): - body = dedent(""" - def func(): - yield from iter([1, 2]) - """) - astroid = self.builder.string_build(body) - func = astroid.body[0] - self.assertIsInstance(func, FunctionDef) - self.assertTrue(func.is_generator()) - - @require_version('3.3') - def test_yield_from_as_string(self): - body = dedent(""" - def func(): - yield from iter([1, 2]) - value = yield from other() - """) - astroid = self.builder.string_build(body) - func = astroid.body[0] - self.assertEqual(func.as_string().strip(), body.strip()) - - # metaclass tests - - @require_version('3.0') - def test_simple_metaclass(self): - astroid = self.builder.string_build("class Test(metaclass=type): pass") - klass = astroid.body[0] - - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, ClassDef) - self.assertEqual(metaclass.name, 'type') - - @require_version('3.0') - def test_metaclass_error(self): - astroid = self.builder.string_build("class Test(metaclass=typ): pass") - klass = astroid.body[0] - self.assertFalse(klass.metaclass()) - - @require_version('3.0') - def test_metaclass_imported(self): - astroid = self.builder.string_build(dedent(""" - from abc import ABCMeta - class Test(metaclass=ABCMeta): pass""")) - klass = astroid.body[1] - - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - @require_version('3.0') - def test_as_string(self): - body = dedent(""" - from abc import ABCMeta - class Test(metaclass=ABCMeta): pass""") - astroid = self.builder.string_build(body) - klass = astroid.body[1] - - self.assertEqual(klass.as_string(), - '\n\nclass Test(metaclass=ABCMeta):\n pass\n') - - @require_version('3.0') - def test_old_syntax_works(self): - astroid = self.builder.string_build(dedent(""" - class Test: - __metaclass__ = type - class SubTest(Test): pass - """)) - klass = astroid['SubTest'] - metaclass = klass.metaclass() - self.assertIsNone(metaclass) - - @require_version('3.0') - def test_metaclass_yes_leak(self): - astroid = self.builder.string_build(dedent(""" - # notice `ab` instead of `abc` - from ab import ABCMeta - - class Meta(metaclass=ABCMeta): pass - """)) - klass = astroid['Meta'] - self.assertIsNone(klass.metaclass()) - - @require_version('3.0') - def test_parent_metaclass(self): - astroid = self.builder.string_build(dedent(""" - from abc import ABCMeta - class Test(metaclass=ABCMeta): pass - class SubTest(Test): pass - """)) - klass = astroid['SubTest'] - self.assertTrue(klass.newstyle) - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - @require_version('3.0') - def test_metaclass_ancestors(self): - astroid = self.builder.string_build(dedent(""" - from abc import ABCMeta - - class FirstMeta(metaclass=ABCMeta): pass - class SecondMeta(metaclass=type): - pass - - class Simple: - pass - - class FirstImpl(FirstMeta): pass - class SecondImpl(FirstImpl): pass - class ThirdImpl(Simple, SecondMeta): - pass - """)) - classes = { - 'ABCMeta': ('FirstImpl', 'SecondImpl'), - 'type': ('ThirdImpl', ) - } - for metaclass, names in classes.items(): - for name in names: - impl = astroid[name] - meta = impl.metaclass() - self.assertIsInstance(meta, ClassDef) - self.assertEqual(meta.name, metaclass) - - @require_version('3.0') - def test_annotation_support(self): - astroid = self.builder.string_build(dedent(""" - def test(a: int, b: str, c: None, d, e, - *args: float, **kwargs: int)->int: - pass - """)) - func = astroid['test'] - self.assertIsInstance(func.args.varargannotation, Name) - self.assertEqual(func.args.varargannotation.name, 'float') - self.assertIsInstance(func.args.kwargannotation, Name) - self.assertEqual(func.args.kwargannotation.name, 'int') - self.assertIsInstance(func.returns, Name) - self.assertEqual(func.returns.name, 'int') - arguments = func.args - self.assertIsInstance(arguments.annotations[0], Name) - self.assertEqual(arguments.annotations[0].name, 'int') - self.assertIsInstance(arguments.annotations[1], Name) - self.assertEqual(arguments.annotations[1].name, 'str') - self.assertIsInstance(arguments.annotations[2], Const) - self.assertIsNone(arguments.annotations[2].value) - self.assertIsNone(arguments.annotations[3]) - self.assertIsNone(arguments.annotations[4]) - - astroid = self.builder.string_build(dedent(""" - def test(a: int=1, b: str=2): - pass - """)) - func = astroid['test'] - self.assertIsInstance(func.args.annotations[0], Name) - self.assertEqual(func.args.annotations[0].name, 'int') - self.assertIsInstance(func.args.annotations[1], Name) - self.assertEqual(func.args.annotations[1].name, 'str') - self.assertIsNone(func.returns) - - @require_version('3.0') - def test_annotation_as_string(self): - code1 = dedent(''' - def test(a, b:int=4, c=2, f:'lala'=4)->2: - pass''') - code2 = dedent(''' - def test(a:typing.Generic[T], c:typing.Any=24)->typing.Iterable: - pass''') - for code in (code1, code2): - func = extract_node(code) - self.assertEqual(func.as_string(), code) - - @require_version('3.5') - def test_unpacking_in_dicts(self): - code = "{'x': 1, **{'y': 2}}" - node = extract_node(code) - self.assertEqual(node.as_string(), code) - keys = [key for (key, _) in node.items] - self.assertIsInstance(keys[0], nodes.Const) - self.assertIsInstance(keys[1], nodes.DictUnpack) - - @require_version('3.5') - def test_nested_unpacking_in_dicts(self): - code = "{'x': 1, **{'y': 2, **{'z': 3}}}" - node = extract_node(code) - self.assertEqual(node.as_string(), code) - - @require_version('3.5') - def test_unpacking_in_dict_getitem(self): - node = extract_node('{1:2, **{2:3, 3:4}, **{5: 6}}') - for key, expected in ((1, 2), (2, 3), (3, 4), (5, 6)): - value = node.getitem(key) - self.assertIsInstance(value, nodes.Const) - self.assertEqual(value.value, expected) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_raw_building.py b/pymode/libs/astroid/tests/unittest_raw_building.py deleted file mode 100644 index 2bdaac17..00000000 --- a/pymode/libs/astroid/tests/unittest_raw_building.py +++ /dev/null @@ -1,85 +0,0 @@ -import inspect -import os -import unittest - -from six.moves import builtins # pylint: disable=import-error - -from astroid.builder import AstroidBuilder -from astroid.raw_building import ( - attach_dummy_node, build_module, - build_class, build_function, build_from_import -) -from astroid import test_utils -from astroid import nodes -from astroid.bases import BUILTINS - - -class RawBuildingTC(unittest.TestCase): - - def test_attach_dummy_node(self): - node = build_module('MyModule') - attach_dummy_node(node, 'DummyNode') - self.assertEqual(1, len(list(node.get_children()))) - - def test_build_module(self): - node = build_module('MyModule') - self.assertEqual(node.name, 'MyModule') - self.assertEqual(node.pure_python, False) - self.assertEqual(node.package, False) - self.assertEqual(node.parent, None) - - def test_build_class(self): - node = build_class('MyClass') - self.assertEqual(node.name, 'MyClass') - self.assertEqual(node.doc, None) - - def test_build_function(self): - node = build_function('MyFunction') - self.assertEqual(node.name, 'MyFunction') - self.assertEqual(node.doc, None) - - def test_build_function_args(self): - args = ['myArgs1', 'myArgs2'] - node = build_function('MyFunction', args) - self.assertEqual('myArgs1', node.args.args[0].name) - self.assertEqual('myArgs2', node.args.args[1].name) - self.assertEqual(2, len(node.args.args)) - - def test_build_function_defaults(self): - defaults = ['defaults1', 'defaults2'] - node = build_function('MyFunction', None, defaults) - self.assertEqual(2, len(node.args.defaults)) - - def test_build_from_import(self): - names = ['exceptions, inference, inspector'] - node = build_from_import('astroid', names) - self.assertEqual(len(names), len(node.names)) - - @test_utils.require_version(minver='3.0') - def test_io_is__io(self): - # _io module calls itself io. This leads - # to cyclic dependencies when astroid tries to resolve - # what io.BufferedReader is. The code that handles this - # is in astroid.raw_building.imported_member, which verifies - # the true name of the module. - import _io - - builder = AstroidBuilder() - module = builder.inspect_build(_io) - buffered_reader = module.getattr('BufferedReader')[0] - self.assertEqual(buffered_reader.root().name, 'io') - - @unittest.skipUnless(os.name == 'java', 'Requires Jython') - def test_open_is_inferred_correctly(self): - # Lot of Jython builtins don't have a __module__ attribute. - for name, _ in inspect.getmembers(builtins, predicate=inspect.isbuiltin): - if name == 'print': - continue - node = test_utils.extract_node('{0} #@'.format(name)) - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.FunctionDef, name) - self.assertEqual(inferred.root().name, BUILTINS, name) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_regrtest.py b/pymode/libs/astroid/tests/unittest_regrtest.py deleted file mode 100644 index 158c7119..00000000 --- a/pymode/libs/astroid/tests/unittest_regrtest.py +++ /dev/null @@ -1,364 +0,0 @@ -# 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 . -import sys -import unittest -import textwrap - -import six - -from astroid import MANAGER, Instance, nodes -from astroid.bases import BUILTINS -from astroid.builder import AstroidBuilder -from astroid import exceptions -from astroid.raw_building import build_module -from astroid.manager import AstroidManager -from astroid.test_utils import require_version, extract_node -from astroid.tests import resources -from astroid import transforms - - -class NonRegressionTests(resources.AstroidCacheSetupMixin, - unittest.TestCase): - - def setUp(self): - sys.path.insert(0, resources.find('data')) - MANAGER.always_load_extensions = True - MANAGER.astroid_cache[BUILTINS] = self._builtins - - def tearDown(self): - # Since we may have created a brainless manager, leading - # to a new cache builtin module and proxy classes in the constants, - # clear out the global manager cache. - MANAGER.clear_cache(self._builtins) - MANAGER.always_load_extensions = False - sys.path.pop(0) - sys.path_importer_cache.pop(resources.find('data'), None) - - def brainless_manager(self): - manager = AstroidManager() - # avoid caching into the AstroidManager borg since we get problems - # with other tests : - manager.__dict__ = {} - manager._failed_import_hooks = [] - manager.astroid_cache = {} - manager._mod_file_cache = {} - manager._transform = transforms.TransformVisitor() - manager.clear_cache() # trigger proper bootstraping - return manager - - def test_module_path(self): - man = self.brainless_manager() - mod = man.ast_from_module_name('package.import_package_subpackage_module') - package = next(mod.igetattr('package')) - self.assertEqual(package.name, 'package') - subpackage = next(package.igetattr('subpackage')) - self.assertIsInstance(subpackage, nodes.Module) - self.assertTrue(subpackage.package) - self.assertEqual(subpackage.name, 'package.subpackage') - module = next(subpackage.igetattr('module')) - self.assertEqual(module.name, 'package.subpackage.module') - - - def test_package_sidepackage(self): - manager = self.brainless_manager() - assert 'package.sidepackage' not in MANAGER.astroid_cache - package = manager.ast_from_module_name('absimp') - self.assertIsInstance(package, nodes.Module) - self.assertTrue(package.package) - subpackage = next(package.getattr('sidepackage')[0].infer()) - self.assertIsInstance(subpackage, nodes.Module) - self.assertTrue(subpackage.package) - self.assertEqual(subpackage.name, 'absimp.sidepackage') - - - def test_living_property(self): - builder = AstroidBuilder() - builder._done = {} - builder._module = sys.modules[__name__] - builder.object_build(build_module('module_name', ''), Whatever) - - - def test_new_style_class_detection(self): - try: - import pygtk # pylint: disable=unused-variable - except ImportError: - self.skipTest('test skipped: pygtk is not available') - # XXX may fail on some pygtk version, because objects in - # gobject._gobject have __module__ set to gobject :( - builder = AstroidBuilder() - data = """ -import pygtk -pygtk.require("2.6") -import gobject - -class A(gobject.GObject): - pass -""" - astroid = builder.string_build(data, __name__, __file__) - a = astroid['A'] - self.assertTrue(a.newstyle) - - - def test_pylint_config_attr(self): - try: - from pylint import lint # pylint: disable=unused-variable - except ImportError: - self.skipTest('pylint not available') - mod = MANAGER.ast_from_module_name('pylint.lint') - pylinter = mod['PyLinter'] - expect = ['OptionsManagerMixIn', 'object', 'MessagesHandlerMixIn', - 'ReportsHandlerMixIn', 'BaseTokenChecker', 'BaseChecker', - 'OptionsProviderMixIn'] - self.assertListEqual([c.name for c in pylinter.ancestors()], - expect) - self.assertTrue(list(Instance(pylinter).getattr('config'))) - inferred = list(Instance(pylinter).igetattr('config')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0].root().name, 'optparse') - self.assertEqual(inferred[0].name, 'Values') - - def test_numpy_crash(self): - """test don't crash on numpy""" - #a crash occured somewhere in the past, and an - # InferenceError instead of a crash was better, but now we even infer! - try: - import numpy # pylint: disable=unused-variable - except ImportError: - self.skipTest('test skipped: numpy is not available') - builder = AstroidBuilder() - data = """ -from numpy import multiply - -multiply(1, 2, 3) -""" - astroid = builder.string_build(data, __name__, __file__) - callfunc = astroid.body[1].value.func - inferred = callfunc.inferred() - self.assertEqual(len(inferred), 2) - - @require_version('3.0') - def test_nameconstant(self): - # used to fail for Python 3.4 - builder = AstroidBuilder() - astroid = builder.string_build("def test(x=True): pass") - default = astroid.body[0].args.args[0] - self.assertEqual(default.name, 'x') - self.assertEqual(next(default.infer()).value, True) - - @require_version('2.7') - def test_with_infer_assignnames(self): - builder = AstroidBuilder() - data = """ -with open('a.txt') as stream, open('b.txt'): - stream.read() -""" - astroid = builder.string_build(data, __name__, __file__) - # Used to crash due to the fact that the second - # context manager didn't use an assignment name. - list(astroid.nodes_of_class(nodes.Call))[-1].inferred() - - def test_recursion_regression_issue25(self): - builder = AstroidBuilder() - data = """ -import recursion as base - -_real_Base = base.Base - -class Derived(_real_Base): - pass - -def run(): - base.Base = Derived -""" - astroid = builder.string_build(data, __name__, __file__) - # Used to crash in _is_metaclass, due to wrong - # ancestors chain - classes = astroid.nodes_of_class(nodes.ClassDef) - for klass in classes: - # triggers the _is_metaclass call - klass.type # pylint: disable=pointless-statement - - def test_decorator_callchain_issue42(self): - builder = AstroidBuilder() - data = """ - -def test(): - def factory(func): - def newfunc(): - func() - return newfunc - return factory - -@test() -def crash(): - pass -""" - astroid = builder.string_build(data, __name__, __file__) - self.assertEqual(astroid['crash'].type, 'function') - - def test_filter_stmts_scoping(self): - builder = AstroidBuilder() - data = """ -def test(): - compiler = int() - class B(compiler.__class__): - pass - compiler = B() - return compiler -""" - astroid = builder.string_build(data, __name__, __file__) - test = astroid['test'] - result = next(test.infer_call_result(astroid)) - self.assertIsInstance(result, Instance) - base = next(result._proxied.bases[0].infer()) - self.assertEqual(base.name, 'int') - - def test_ancestors_patching_class_recursion(self): - node = AstroidBuilder().string_build(textwrap.dedent(""" - import string - Template = string.Template - - class A(Template): - pass - - class B(A): - pass - - def test(x=False): - if x: - string.Template = A - else: - string.Template = B - """)) - klass = node['A'] - ancestors = list(klass.ancestors()) - self.assertEqual(ancestors[0].qname(), 'string.Template') - - def test_ancestors_yes_in_bases(self): - # Test for issue https://bitbucket.org/logilab/astroid/issue/84 - # This used to crash astroid with a TypeError, because an YES - # node was present in the bases - node = extract_node(""" - def with_metaclass(meta, *bases): - class metaclass(meta): - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - return type.__new__(metaclass, 'temporary_class', (), {}) - - import lala - - class A(with_metaclass(object, lala.lala)): #@ - pass - """) - ancestors = list(node.ancestors()) - if six.PY3: - self.assertEqual(len(ancestors), 1) - self.assertEqual(ancestors[0].qname(), - "{}.object".format(BUILTINS)) - else: - self.assertEqual(len(ancestors), 0) - - def test_ancestors_missing_from_function(self): - # Test for https://www.logilab.org/ticket/122793 - node = extract_node(''' - def gen(): yield - GEN = gen() - next(GEN) - ''') - self.assertRaises(exceptions.InferenceError, next, node.infer()) - - def test_unicode_in_docstring(self): - # Crashed for astroid==1.4.1 - # Test for https://bitbucket.org/logilab/astroid/issues/273/ - - # In a regular file, "coding: utf-8" would have been used. - node = extract_node(u''' - from __future__ import unicode_literals - - class MyClass(object): - def method(self): - "With unicode : %s " - - instance = MyClass() - ''' % u"\u2019") - - next(node.value.infer()).as_string() - - def test_binop_generates_nodes_with_parents(self): - node = extract_node(''' - def no_op(*args): - pass - def foo(*args): - def inner(*more_args): - args + more_args #@ - return inner - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertIsNotNone(inferred.parent) - self.assertIsInstance(inferred.parent, nodes.BinOp) - - def test_decorator_names_inference_error_leaking(self): - node = extract_node(''' - class Parent(object): - @property - def foo(self): - pass - - class Child(Parent): - @Parent.foo.getter - def foo(self): #@ - return super(Child, self).foo + ['oink'] - ''') - inferred = next(node.infer()) - self.assertEqual(inferred.decoratornames(), set()) - - def test_ssl_protocol(self): - node = extract_node(''' - import ssl - ssl.PROTOCOL_TLSv1 - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - - def test_uninferable_string_argument_of_namedtuple(self): - node = extract_node(''' - import collections - collections.namedtuple('{}'.format("a"), '')() - ''') - next(node.infer()) - - @require_version(maxver='3.0') - def test_reassignment_in_except_handler(self): - node = extract_node(''' - import exceptions - try: - {}["a"] - except KeyError, exceptions.IndexError: - pass - - IndexError #@ - ''') - self.assertEqual(len(node.inferred()), 1) - - -class Whatever(object): - a = property(lambda x: x, lambda x: x) - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_scoped_nodes.py b/pymode/libs/astroid/tests/unittest_scoped_nodes.py deleted file mode 100644 index a15c923a..00000000 --- a/pymode/libs/astroid/tests/unittest_scoped_nodes.py +++ /dev/null @@ -1,1583 +0,0 @@ -# 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 . -"""tests for specific behaviour of astroid scoped nodes (i.e. module, class and -function) -""" -import os -import sys -from functools import partial -import unittest -import warnings - -from astroid import builder -from astroid import nodes -from astroid import scoped_nodes -from astroid import util -from astroid.exceptions import ( - InferenceError, NotFoundError, - NoDefault, ResolveError, MroError, - InconsistentMroError, DuplicateBasesError, -) -from astroid.bases import ( - BUILTINS, Instance, - BoundMethod, UnboundMethod, Generator -) -from astroid import __pkginfo__ -from astroid import test_utils -from astroid.tests import resources - - -def _test_dict_interface(self, node, test_attr): - self.assertIs(node[test_attr], node[test_attr]) - self.assertIn(test_attr, node) - node.keys() - node.values() - node.items() - iter(node) - - -class ModuleLoader(resources.SysPathSetup): - def setUp(self): - super(ModuleLoader, self).setUp() - self.module = resources.build_file('data/module.py', 'data.module') - self.module2 = resources.build_file('data/module2.py', 'data.module2') - self.nonregr = resources.build_file('data/nonregr.py', 'data.nonregr') - self.pack = resources.build_file('data/__init__.py', 'data') - - -class ModuleNodeTest(ModuleLoader, unittest.TestCase): - - def test_special_attributes(self): - self.assertEqual(len(self.module.getattr('__name__')), 1) - self.assertIsInstance(self.module.getattr('__name__')[0], nodes.Const) - self.assertEqual(self.module.getattr('__name__')[0].value, 'data.module') - self.assertEqual(len(self.module.getattr('__doc__')), 1) - self.assertIsInstance(self.module.getattr('__doc__')[0], nodes.Const) - self.assertEqual(self.module.getattr('__doc__')[0].value, 'test module for astroid\n') - self.assertEqual(len(self.module.getattr('__file__')), 1) - self.assertIsInstance(self.module.getattr('__file__')[0], nodes.Const) - self.assertEqual(self.module.getattr('__file__')[0].value, - os.path.abspath(resources.find('data/module.py'))) - self.assertEqual(len(self.module.getattr('__dict__')), 1) - self.assertIsInstance(self.module.getattr('__dict__')[0], nodes.Dict) - self.assertRaises(NotFoundError, self.module.getattr, '__path__') - self.assertEqual(len(self.pack.getattr('__path__')), 1) - self.assertIsInstance(self.pack.getattr('__path__')[0], nodes.List) - - def test_dict_interface(self): - _test_dict_interface(self, self.module, 'YO') - - def test_getattr(self): - yo = self.module.getattr('YO')[0] - self.assertIsInstance(yo, nodes.ClassDef) - self.assertEqual(yo.name, 'YO') - red = next(self.module.igetattr('redirect')) - self.assertIsInstance(red, nodes.FunctionDef) - self.assertEqual(red.name, 'four_args') - namenode = next(self.module.igetattr('NameNode')) - self.assertIsInstance(namenode, nodes.ClassDef) - self.assertEqual(namenode.name, 'Name') - # resolve packageredirection - mod = resources.build_file('data/appl/myConnection.py', - 'data.appl.myConnection') - ssl = next(mod.igetattr('SSL1')) - cnx = next(ssl.igetattr('Connection')) - self.assertEqual(cnx.__class__, nodes.ClassDef) - self.assertEqual(cnx.name, 'Connection') - self.assertEqual(cnx.root().name, 'data.SSL1.Connection1') - self.assertEqual(len(self.nonregr.getattr('enumerate')), 2) - # raise ResolveError - self.assertRaises(InferenceError, self.nonregr.igetattr, 'YOAA') - - def test_wildcard_import_names(self): - m = resources.build_file('data/all.py', 'all') - self.assertEqual(m.wildcard_import_names(), ['Aaa', '_bla', 'name']) - m = resources.build_file('data/notall.py', 'notall') - res = sorted(m.wildcard_import_names()) - self.assertEqual(res, ['Aaa', 'func', 'name', 'other']) - - def test_public_names(self): - m = builder.parse(''' - name = 'a' - _bla = 2 - other = 'o' - class Aaa: pass - def func(): print('yo') - __all__ = 'Aaa', '_bla', 'name' - ''') - values = sorted(['Aaa', 'name', 'other', 'func']) - self.assertEqual(sorted(m._public_names()), values) - m = builder.parse(''' - name = 'a' - _bla = 2 - other = 'o' - class Aaa: pass - - def func(): return 'yo' - ''') - res = sorted(m._public_names()) - self.assertEqual(res, values) - - m = builder.parse(''' - from missing import tzop - trop = "test" - __all__ = (trop, "test1", tzop, 42) - ''') - res = sorted(m._public_names()) - self.assertEqual(res, ["trop", "tzop"]) - - m = builder.parse(''' - test = tzop = 42 - __all__ = ('test', ) + ('tzop', ) - ''') - res = sorted(m._public_names()) - self.assertEqual(res, ['test', 'tzop']) - - def test_module_getattr(self): - data = ''' - appli = application - appli += 2 - del appli - ''' - astroid = builder.parse(data, __name__) - # test del statement not returned by getattr - self.assertEqual(len(astroid.getattr('appli')), 2, - astroid.getattr('appli')) - - def test_relative_to_absolute_name(self): - # package - mod = nodes.Module('very.multi.package', 'doc') - mod.package = True - modname = mod.relative_to_absolute_name('utils', 1) - self.assertEqual(modname, 'very.multi.package.utils') - modname = mod.relative_to_absolute_name('utils', 2) - self.assertEqual(modname, 'very.multi.utils') - modname = mod.relative_to_absolute_name('utils', 0) - self.assertEqual(modname, 'very.multi.package.utils') - modname = mod.relative_to_absolute_name('', 1) - self.assertEqual(modname, 'very.multi.package') - # non package - mod = nodes.Module('very.multi.module', 'doc') - mod.package = False - modname = mod.relative_to_absolute_name('utils', 0) - self.assertEqual(modname, 'very.multi.utils') - modname = mod.relative_to_absolute_name('utils', 1) - self.assertEqual(modname, 'very.multi.utils') - modname = mod.relative_to_absolute_name('utils', 2) - self.assertEqual(modname, 'very.utils') - modname = mod.relative_to_absolute_name('', 1) - self.assertEqual(modname, 'very.multi') - - def test_import_1(self): - data = '''from . import subpackage''' - sys.path.insert(0, resources.find('data')) - astroid = builder.parse(data, 'package', 'data/package/__init__.py') - try: - m = astroid.import_module('', level=1) - self.assertEqual(m.name, 'package') - inferred = list(astroid.igetattr('subpackage')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0].name, 'package.subpackage') - finally: - del sys.path[0] - - - def test_import_2(self): - data = '''from . import subpackage as pouet''' - astroid = builder.parse(data, 'package', 'data/package/__init__.py') - sys.path.insert(0, resources.find('data')) - try: - m = astroid.import_module('', level=1) - self.assertEqual(m.name, 'package') - inferred = list(astroid.igetattr('pouet')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0].name, 'package.subpackage') - finally: - del sys.path[0] - - - def test_file_stream_in_memory(self): - data = '''irrelevant_variable is irrelevant''' - astroid = builder.parse(data, 'in_memory') - with warnings.catch_warnings(record=True): - self.assertEqual(astroid.file_stream.read().decode(), data) - - def test_file_stream_physical(self): - path = resources.find('data/all.py') - astroid = builder.AstroidBuilder().file_build(path, 'all') - with open(path, 'rb') as file_io: - with warnings.catch_warnings(record=True): - self.assertEqual(astroid.file_stream.read(), file_io.read()) - - def test_file_stream_api(self): - path = resources.find('data/all.py') - astroid = builder.AstroidBuilder().file_build(path, 'all') - if __pkginfo__.numversion >= (1, 6): - # file_stream is slated for removal in astroid 1.6. - with self.assertRaises(AttributeError): - # pylint: disable=pointless-statement - astroid.file_stream - else: - # Until astroid 1.6, Module.file_stream will emit - # PendingDeprecationWarning in 1.4, DeprecationWarning - # in 1.5 and finally it will be removed in 1.6, leaving - # only Module.stream as the recommended way to retrieve - # its file stream. - with warnings.catch_warnings(record=True) as cm: - warnings.simplefilter("always") - self.assertIsNot(astroid.file_stream, astroid.file_stream) - self.assertGreater(len(cm), 1) - self.assertEqual(cm[0].category, PendingDeprecationWarning) - - def test_stream_api(self): - path = resources.find('data/all.py') - astroid = builder.AstroidBuilder().file_build(path, 'all') - stream = astroid.stream() - self.assertTrue(hasattr(stream, 'close')) - with stream: - with open(path, 'rb') as file_io: - self.assertEqual(stream.read(), file_io.read()) - - -class FunctionNodeTest(ModuleLoader, unittest.TestCase): - - def test_special_attributes(self): - func = self.module2['make_class'] - self.assertEqual(len(func.getattr('__name__')), 1) - self.assertIsInstance(func.getattr('__name__')[0], nodes.Const) - self.assertEqual(func.getattr('__name__')[0].value, 'make_class') - self.assertEqual(len(func.getattr('__doc__')), 1) - self.assertIsInstance(func.getattr('__doc__')[0], nodes.Const) - self.assertEqual(func.getattr('__doc__')[0].value, 'check base is correctly resolved to Concrete0') - self.assertEqual(len(self.module.getattr('__dict__')), 1) - self.assertIsInstance(self.module.getattr('__dict__')[0], nodes.Dict) - - def test_dict_interface(self): - _test_dict_interface(self, self.module['global_access'], 'local') - - def test_default_value(self): - func = self.module2['make_class'] - self.assertIsInstance(func.args.default_value('base'), nodes.Attribute) - self.assertRaises(NoDefault, func.args.default_value, 'args') - self.assertRaises(NoDefault, func.args.default_value, 'kwargs') - self.assertRaises(NoDefault, func.args.default_value, 'any') - #self.assertIsInstance(func.mularg_class('args'), nodes.Tuple) - #self.assertIsInstance(func.mularg_class('kwargs'), nodes.Dict) - #self.assertIsNone(func.mularg_class('base')) - - def test_navigation(self): - function = self.module['global_access'] - self.assertEqual(function.statement(), function) - l_sibling = function.previous_sibling() - # check taking parent if child is not a stmt - self.assertIsInstance(l_sibling, nodes.Assign) - child = function.args.args[0] - self.assertIs(l_sibling, child.previous_sibling()) - r_sibling = function.next_sibling() - self.assertIsInstance(r_sibling, nodes.ClassDef) - self.assertEqual(r_sibling.name, 'YO') - self.assertIs(r_sibling, child.next_sibling()) - last = r_sibling.next_sibling().next_sibling().next_sibling() - self.assertIsInstance(last, nodes.Assign) - self.assertIsNone(last.next_sibling()) - first = l_sibling.root().body[0] - self.assertIsNone(first.previous_sibling()) - - def test_nested_args(self): - if sys.version_info >= (3, 0): - self.skipTest("nested args has been removed in py3.x") - code = ''' - def nested_args(a, (b, c, d)): - "nested arguments test" - ''' - tree = builder.parse(code) - func = tree['nested_args'] - self.assertEqual(sorted(func._locals), ['a', 'b', 'c', 'd']) - self.assertEqual(func.args.format_args(), 'a, (b, c, d)') - - def test_four_args(self): - func = self.module['four_args'] - #self.assertEqual(func.args.args, ['a', ('b', 'c', 'd')]) - local = sorted(func.keys()) - self.assertEqual(local, ['a', 'b', 'c', 'd']) - self.assertEqual(func.type, 'function') - - def test_format_args(self): - func = self.module2['make_class'] - self.assertEqual(func.args.format_args(), - 'any, base=data.module.YO, *args, **kwargs') - func = self.module['four_args'] - self.assertEqual(func.args.format_args(), 'a, b, c, d') - - def test_is_generator(self): - self.assertTrue(self.module2['generator'].is_generator()) - self.assertFalse(self.module2['not_a_generator'].is_generator()) - self.assertFalse(self.module2['make_class'].is_generator()) - - def test_is_abstract(self): - method = self.module2['AbstractClass']['to_override'] - self.assertTrue(method.is_abstract(pass_is_abstract=False)) - self.assertEqual(method.qname(), 'data.module2.AbstractClass.to_override') - self.assertEqual(method.pytype(), '%s.instancemethod' % BUILTINS) - method = self.module2['AbstractClass']['return_something'] - self.assertFalse(method.is_abstract(pass_is_abstract=False)) - # non regression : test raise "string" doesn't cause an exception in is_abstract - func = self.module2['raise_string'] - self.assertFalse(func.is_abstract(pass_is_abstract=False)) - - def test_is_abstract_decorated(self): - methods = test_utils.extract_node(""" - import abc - - class Klass(object): - @abc.abstractproperty - def prop(self): #@ - pass - - @abc.abstractmethod - def method1(self): #@ - pass - - some_other_decorator = lambda x: x - @some_other_decorator - def method2(self): #@ - pass - """) - self.assertTrue(methods[0].is_abstract(pass_is_abstract=False)) - self.assertTrue(methods[1].is_abstract(pass_is_abstract=False)) - self.assertFalse(methods[2].is_abstract(pass_is_abstract=False)) - -## def test_raises(self): -## method = self.module2['AbstractClass']['to_override'] -## self.assertEqual([str(term) for term in method.raises()], -## ["Call(Name('NotImplementedError'), [], None, None)"] ) - -## def test_returns(self): -## method = self.module2['AbstractClass']['return_something'] -## # use string comp since Node doesn't handle __cmp__ -## self.assertEqual([str(term) for term in method.returns()], -## ["Const('toto')", "Const(None)"]) - - def test_lambda_pytype(self): - data = ''' - def f(): - g = lambda: None - ''' - astroid = builder.parse(data) - g = list(astroid['f'].ilookup('g'))[0] - self.assertEqual(g.pytype(), '%s.function' % BUILTINS) - - def test_lambda_qname(self): - astroid = builder.parse('lmbd = lambda: None', __name__) - self.assertEqual('%s.' % __name__, astroid['lmbd'].parent.value.qname()) - - def test_is_method(self): - data = ''' - class A: - def meth1(self): - return 1 - @classmethod - def meth2(cls): - return 2 - @staticmethod - def meth3(): - return 3 - - def function(): - return 0 - - @staticmethod - def sfunction(): - return -1 - ''' - astroid = builder.parse(data) - self.assertTrue(astroid['A']['meth1'].is_method()) - self.assertTrue(astroid['A']['meth2'].is_method()) - self.assertTrue(astroid['A']['meth3'].is_method()) - self.assertFalse(astroid['function'].is_method()) - self.assertFalse(astroid['sfunction'].is_method()) - - def test_argnames(self): - if sys.version_info < (3, 0): - code = 'def f(a, (b, c), *args, **kwargs): pass' - else: - code = 'def f(a, b, c, *args, **kwargs): pass' - astroid = builder.parse(code, __name__) - self.assertEqual(astroid['f'].argnames(), ['a', 'b', 'c', 'args', 'kwargs']) - - def test_return_nothing(self): - """test inferred value on a function with empty return""" - data = ''' - def func(): - return - - a = func() - ''' - astroid = builder.parse(data) - call = astroid.body[1].value - func_vals = call.inferred() - self.assertEqual(len(func_vals), 1) - self.assertIsInstance(func_vals[0], nodes.Const) - self.assertIsNone(func_vals[0].value) - - def test_func_instance_attr(self): - """test instance attributes for functions""" - data = """ - def test(): - print(test.bar) - - test.bar = 1 - test() - """ - astroid = builder.parse(data, 'mod') - func = astroid.body[2].value.func.inferred()[0] - self.assertIsInstance(func, nodes.FunctionDef) - self.assertEqual(func.name, 'test') - one = func.getattr('bar')[0].inferred()[0] - self.assertIsInstance(one, nodes.Const) - self.assertEqual(one.value, 1) - - def test_type_builtin_descriptor_subclasses(self): - astroid = builder.parse(""" - class classonlymethod(classmethod): - pass - class staticonlymethod(staticmethod): - pass - - class Node: - @classonlymethod - def clsmethod_subclass(cls): - pass - @classmethod - def clsmethod(cls): - pass - @staticonlymethod - def staticmethod_subclass(cls): - pass - @staticmethod - def stcmethod(cls): - pass - """) - node = astroid._locals['Node'][0] - self.assertEqual(node._locals['clsmethod_subclass'][0].type, - 'classmethod') - self.assertEqual(node._locals['clsmethod'][0].type, - 'classmethod') - self.assertEqual(node._locals['staticmethod_subclass'][0].type, - 'staticmethod') - self.assertEqual(node._locals['stcmethod'][0].type, - 'staticmethod') - - def test_decorator_builtin_descriptors(self): - astroid = builder.parse(""" - def static_decorator(platform=None, order=50): - def wrapper(f): - f.cgm_module = True - f.cgm_module_order = order - f.cgm_module_platform = platform - return staticmethod(f) - return wrapper - - def long_classmethod_decorator(platform=None, order=50): - def wrapper(f): - def wrapper2(f): - def wrapper3(f): - f.cgm_module = True - f.cgm_module_order = order - f.cgm_module_platform = platform - return classmethod(f) - return wrapper3(f) - return wrapper2(f) - return wrapper - - def classmethod_decorator(platform=None): - def wrapper(f): - f.platform = platform - return classmethod(f) - return wrapper - - def classmethod_wrapper(fn): - def wrapper(cls, *args, **kwargs): - result = fn(cls, *args, **kwargs) - return result - - return classmethod(wrapper) - - def staticmethod_wrapper(fn): - def wrapper(*args, **kwargs): - return fn(*args, **kwargs) - return staticmethod(wrapper) - - class SomeClass(object): - @static_decorator() - def static(node, cfg): - pass - @classmethod_decorator() - def classmethod(cls): - pass - @static_decorator - def not_so_static(node): - pass - @classmethod_decorator - def not_so_classmethod(node): - pass - @classmethod_wrapper - def classmethod_wrapped(cls): - pass - @staticmethod_wrapper - def staticmethod_wrapped(): - pass - @long_classmethod_decorator() - def long_classmethod(cls): - pass - """) - node = astroid._locals['SomeClass'][0] - self.assertEqual(node._locals['static'][0].type, - 'staticmethod') - self.assertEqual(node._locals['classmethod'][0].type, - 'classmethod') - self.assertEqual(node._locals['not_so_static'][0].type, - 'method') - self.assertEqual(node._locals['not_so_classmethod'][0].type, - 'method') - self.assertEqual(node._locals['classmethod_wrapped'][0].type, - 'classmethod') - self.assertEqual(node._locals['staticmethod_wrapped'][0].type, - 'staticmethod') - self.assertEqual(node._locals['long_classmethod'][0].type, - 'classmethod') - - def test_igetattr(self): - func = test_utils.extract_node(''' - def test(): - pass - ''') - func._instance_attrs['value'] = [nodes.Const(42)] - value = func.getattr('value') - self.assertEqual(len(value), 1) - self.assertIsInstance(value[0], nodes.Const) - self.assertEqual(value[0].value, 42) - inferred = next(func.igetattr('value')) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - @test_utils.require_version(minver='3.0') - def test_return_annotation_is_not_the_last(self): - func = builder.parse(''' - def test() -> bytes: - pass - pass - return - ''').body[0] - last_child = func.last_child() - self.assertIsInstance(last_child, nodes.Return) - self.assertEqual(func.tolineno, 5) - - -class ClassNodeTest(ModuleLoader, unittest.TestCase): - - def test_dict_interface(self): - _test_dict_interface(self, self.module['YOUPI'], 'method') - - def test_cls_special_attributes_1(self): - cls = self.module['YO'] - self.assertEqual(len(cls.getattr('__bases__')), 1) - self.assertEqual(len(cls.getattr('__name__')), 1) - self.assertIsInstance(cls.getattr('__name__')[0], nodes.Const) - self.assertEqual(cls.getattr('__name__')[0].value, 'YO') - self.assertEqual(len(cls.getattr('__doc__')), 1) - self.assertIsInstance(cls.getattr('__doc__')[0], nodes.Const) - self.assertEqual(cls.getattr('__doc__')[0].value, 'hehe') - self.assertEqual(len(cls.getattr('__module__')), 1) - self.assertIsInstance(cls.getattr('__module__')[0], nodes.Const) - self.assertEqual(cls.getattr('__module__')[0].value, 'data.module') - self.assertEqual(len(cls.getattr('__dict__')), 1) - if not cls.newstyle: - self.assertRaises(NotFoundError, cls.getattr, '__mro__') - for cls in (nodes.List._proxied, nodes.Const(1)._proxied): - self.assertEqual(len(cls.getattr('__bases__')), 1) - self.assertEqual(len(cls.getattr('__name__')), 1) - self.assertEqual(len(cls.getattr('__doc__')), 1, (cls, cls.getattr('__doc__'))) - self.assertEqual(cls.getattr('__doc__')[0].value, cls.doc) - self.assertEqual(len(cls.getattr('__module__')), 1) - self.assertEqual(len(cls.getattr('__dict__')), 1) - self.assertEqual(len(cls.getattr('__mro__')), 1) - - def test__mro__attribute(self): - node = test_utils.extract_node(''' - class A(object): pass - class B(object): pass - class C(A, B): pass - ''') - mro = node.getattr('__mro__')[0] - self.assertIsInstance(mro, nodes.Tuple) - self.assertEqual(mro.elts, node.mro()) - - def test__bases__attribute(self): - node = test_utils.extract_node(''' - class A(object): pass - class B(object): pass - class C(A, B): pass - class D(C): pass - ''') - bases = node.getattr('__bases__')[0] - self.assertIsInstance(bases, nodes.Tuple) - self.assertEqual(len(bases.elts), 1) - self.assertIsInstance(bases.elts[0], nodes.ClassDef) - self.assertEqual(bases.elts[0].name, 'C') - - def test_cls_special_attributes_2(self): - astroid = builder.parse(''' - class A: pass - class B: pass - - A.__bases__ += (B,) - ''', __name__) - self.assertEqual(len(astroid['A'].getattr('__bases__')), 2) - self.assertIsInstance(astroid['A'].getattr('__bases__')[0], nodes.Tuple) - self.assertIsInstance(astroid['A'].getattr('__bases__')[1], nodes.AssignAttr) - - def test_instance_special_attributes(self): - for inst in (Instance(self.module['YO']), nodes.List(), nodes.Const(1)): - self.assertRaises(NotFoundError, inst.getattr, '__mro__') - self.assertRaises(NotFoundError, inst.getattr, '__bases__') - self.assertRaises(NotFoundError, inst.getattr, '__name__') - self.assertEqual(len(inst.getattr('__dict__')), 1) - self.assertEqual(len(inst.getattr('__doc__')), 1) - - def test_navigation(self): - klass = self.module['YO'] - self.assertEqual(klass.statement(), klass) - l_sibling = klass.previous_sibling() - self.assertTrue(isinstance(l_sibling, nodes.FunctionDef), l_sibling) - self.assertEqual(l_sibling.name, 'global_access') - r_sibling = klass.next_sibling() - self.assertIsInstance(r_sibling, nodes.ClassDef) - self.assertEqual(r_sibling.name, 'YOUPI') - - def test_local_attr_ancestors(self): - module = builder.parse(''' - class A(): - def __init__(self): pass - class B(A): pass - class C(B): pass - class D(object): pass - class F(): pass - class E(F, D): pass - ''') - # Test old-style (Python 2) / new-style (Python 3+) ancestors lookups - klass2 = module['C'] - it = klass2.local_attr_ancestors('__init__') - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'A') - if sys.version_info[0] == 2: - self.assertRaises(StopIteration, partial(next, it)) - else: - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'object') - self.assertRaises(StopIteration, partial(next, it)) - - it = klass2.local_attr_ancestors('method') - self.assertRaises(StopIteration, partial(next, it)) - - # Test mixed-style ancestor lookups - klass2 = module['E'] - it = klass2.local_attr_ancestors('__init__') - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'object') - self.assertRaises(StopIteration, partial(next, it)) - - def test_local_attr_mro(self): - module = builder.parse(''' - class A(object): - def __init__(self): pass - class B(A): - def __init__(self, arg, arg2): pass - class C(A): pass - class D(C, B): pass - ''') - dclass = module['D'] - init = dclass.local_attr('__init__')[0] - self.assertIsInstance(init, nodes.FunctionDef) - self.assertEqual(init.parent.name, 'B') - - cclass = module['C'] - init = cclass.local_attr('__init__')[0] - self.assertIsInstance(init, nodes.FunctionDef) - self.assertEqual(init.parent.name, 'A') - - ancestors = list(dclass.local_attr_ancestors('__init__')) - self.assertEqual([node.name for node in ancestors], ['B', 'A', 'object']) - - def test_instance_attr_ancestors(self): - klass2 = self.module['YOUPI'] - it = klass2.instance_attr_ancestors('yo') - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'YO') - self.assertRaises(StopIteration, partial(next, it)) - klass2 = self.module['YOUPI'] - it = klass2.instance_attr_ancestors('member') - self.assertRaises(StopIteration, partial(next, it)) - - def test_methods(self): - expected_methods = {'__init__', 'class_method', 'method', 'static_method'} - klass2 = self.module['YOUPI'] - methods = {m.name for m in klass2.methods()} - self.assertTrue( - methods.issuperset(expected_methods)) - methods = {m.name for m in klass2.mymethods()} - self.assertSetEqual(expected_methods, methods) - klass2 = self.module2['Specialization'] - methods = {m.name for m in klass2.mymethods()} - self.assertSetEqual(set([]), methods) - method_locals = klass2.local_attr('method') - self.assertEqual(len(method_locals), 1) - self.assertEqual(method_locals[0].name, 'method') - self.assertRaises(NotFoundError, klass2.local_attr, 'nonexistant') - methods = {m.name for m in klass2.methods()} - self.assertTrue(methods.issuperset(expected_methods)) - - #def test_rhs(self): - # my_dict = self.module['MY_DICT'] - # self.assertIsInstance(my_dict.rhs(), nodes.Dict) - # a = self.module['YO']['a'] - # value = a.rhs() - # self.assertIsInstance(value, nodes.Const) - # self.assertEqual(value.value, 1) - - @unittest.skipIf(sys.version_info[0] >= 3, "Python 2 class semantics required.") - def test_ancestors(self): - klass = self.module['YOUPI'] - self.assertEqual(['YO'], [a.name for a in klass.ancestors()]) - klass = self.module2['Specialization'] - self.assertEqual(['YOUPI', 'YO'], [a.name for a in klass.ancestors()]) - - @unittest.skipIf(sys.version_info[0] < 3, "Python 3 class semantics required.") - def test_ancestors_py3(self): - klass = self.module['YOUPI'] - self.assertEqual(['YO', 'object'], [a.name for a in klass.ancestors()]) - klass = self.module2['Specialization'] - self.assertEqual(['YOUPI', 'YO', 'object'], [a.name for a in klass.ancestors()]) - - def test_type(self): - klass = self.module['YOUPI'] - self.assertEqual(klass.type, 'class') - klass = self.module2['Metaclass'] - self.assertEqual(klass.type, 'metaclass') - klass = self.module2['MyException'] - self.assertEqual(klass.type, 'exception') - klass = self.module2['MyError'] - self.assertEqual(klass.type, 'exception') - # the following class used to be detected as a metaclass - # after the fix which used instance._proxied in .ancestors(), - # when in fact it is a normal class - klass = self.module2['NotMetaclass'] - self.assertEqual(klass.type, 'class') - - def test_inner_classes(self): - eee = self.nonregr['Ccc']['Eee'] - self.assertEqual([n.name for n in eee.ancestors()], ['Ddd', 'Aaa', 'object']) - - - def test_classmethod_attributes(self): - data = ''' - class WebAppObject(object): - def registered(cls, application): - cls.appli = application - cls.schema = application.schema - cls.config = application.config - return cls - registered = classmethod(registered) - ''' - astroid = builder.parse(data, __name__) - cls = astroid['WebAppObject'] - self.assertEqual(sorted(cls._locals.keys()), - ['appli', 'config', 'registered', 'schema']) - - def test_class_getattr(self): - data = ''' - class WebAppObject(object): - appli = application - appli += 2 - del self.appli - ''' - astroid = builder.parse(data, __name__) - cls = astroid['WebAppObject'] - # test del statement not returned by getattr - self.assertEqual(len(cls.getattr('appli')), 2) - - - def test_instance_getattr(self): - data = ''' - class WebAppObject(object): - def __init__(self, application): - self.appli = application - self.appli += 2 - del self.appli - ''' - astroid = builder.parse(data) - inst = Instance(astroid['WebAppObject']) - # test del statement not returned by getattr - self.assertEqual(len(inst.getattr('appli')), 2) - - - def test_instance_getattr_with_class_attr(self): - data = ''' - class Parent: - aa = 1 - cc = 1 - - class Klass(Parent): - aa = 0 - bb = 0 - - def incr(self, val): - self.cc = self.aa - if val > self.aa: - val = self.aa - if val < self.bb: - val = self.bb - self.aa += val - ''' - astroid = builder.parse(data) - inst = Instance(astroid['Klass']) - self.assertEqual(len(inst.getattr('aa')), 3, inst.getattr('aa')) - self.assertEqual(len(inst.getattr('bb')), 1, inst.getattr('bb')) - self.assertEqual(len(inst.getattr('cc')), 2, inst.getattr('cc')) - - - def test_getattr_method_transform(self): - data = ''' - class Clazz(object): - - def m1(self, value): - self.value = value - m2 = m1 - - def func(arg1, arg2): - "function that will be used as a method" - return arg1.value + arg2 - - Clazz.m3 = func - inst = Clazz() - inst.m4 = func - ''' - astroid = builder.parse(data) - cls = astroid['Clazz'] - # test del statement not returned by getattr - for method in ('m1', 'm2', 'm3'): - inferred = list(cls.igetattr(method)) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], UnboundMethod) - inferred = list(Instance(cls).igetattr(method)) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], BoundMethod) - inferred = list(Instance(cls).igetattr('m4')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - - def test_getattr_from_grandpa(self): - data = ''' - class Future: - attr = 1 - - class Present(Future): - pass - - class Past(Present): - pass - ''' - astroid = builder.parse(data) - past = astroid['Past'] - attr = past.getattr('attr') - self.assertEqual(len(attr), 1) - attr1 = attr[0] - self.assertIsInstance(attr1, nodes.AssignName) - self.assertEqual(attr1.name, 'attr') - - def test_function_with_decorator_lineno(self): - data = ''' - @f(a=2, - b=3) - def g1(x): - print(x) - - @f(a=2, - b=3) - def g2(): - pass - ''' - astroid = builder.parse(data) - self.assertEqual(astroid['g1'].fromlineno, 4) - self.assertEqual(astroid['g1'].tolineno, 5) - self.assertEqual(astroid['g2'].fromlineno, 9) - self.assertEqual(astroid['g2'].tolineno, 10) - - @test_utils.require_version(maxver='3.0') - def test_simple_metaclass(self): - astroid = builder.parse(""" - class Test(object): - __metaclass__ = type - """) - klass = astroid['Test'] - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.name, 'type') - - def test_metaclass_error(self): - astroid = builder.parse(""" - class Test(object): - __metaclass__ = typ - """) - klass = astroid['Test'] - self.assertFalse(klass.metaclass()) - - @test_utils.require_version(maxver='3.0') - def test_metaclass_imported(self): - astroid = builder.parse(""" - from abc import ABCMeta - class Test(object): - __metaclass__ = ABCMeta - """) - klass = astroid['Test'] - - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - def test_metaclass_yes_leak(self): - astroid = builder.parse(""" - # notice `ab` instead of `abc` - from ab import ABCMeta - - class Meta(object): - __metaclass__ = ABCMeta - """) - klass = astroid['Meta'] - self.assertIsNone(klass.metaclass()) - - @test_utils.require_version(maxver='3.0') - def test_newstyle_and_metaclass_good(self): - astroid = builder.parse(""" - from abc import ABCMeta - class Test: - __metaclass__ = ABCMeta - """) - klass = astroid['Test'] - self.assertTrue(klass.newstyle) - self.assertEqual(klass.metaclass().name, 'ABCMeta') - astroid = builder.parse(""" - from abc import ABCMeta - __metaclass__ = ABCMeta - class Test: - pass - """) - klass = astroid['Test'] - self.assertTrue(klass.newstyle) - self.assertEqual(klass.metaclass().name, 'ABCMeta') - - @test_utils.require_version(maxver='3.0') - def test_nested_metaclass(self): - astroid = builder.parse(""" - from abc import ABCMeta - class A(object): - __metaclass__ = ABCMeta - class B: pass - - __metaclass__ = ABCMeta - class C: - __metaclass__ = type - class D: pass - """) - a = astroid['A'] - b = a._locals['B'][0] - c = astroid['C'] - d = c._locals['D'][0] - self.assertEqual(a.metaclass().name, 'ABCMeta') - self.assertFalse(b.newstyle) - self.assertIsNone(b.metaclass()) - self.assertEqual(c.metaclass().name, 'type') - self.assertEqual(d.metaclass().name, 'ABCMeta') - - @test_utils.require_version(maxver='3.0') - def test_parent_metaclass(self): - astroid = builder.parse(""" - from abc import ABCMeta - class Test: - __metaclass__ = ABCMeta - class SubTest(Test): pass - """) - klass = astroid['SubTest'] - self.assertTrue(klass.newstyle) - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - @test_utils.require_version(maxver='3.0') - def test_metaclass_ancestors(self): - astroid = builder.parse(""" - from abc import ABCMeta - - class FirstMeta(object): - __metaclass__ = ABCMeta - - class SecondMeta(object): - __metaclass__ = type - - class Simple(object): - pass - - class FirstImpl(FirstMeta): pass - class SecondImpl(FirstImpl): pass - class ThirdImpl(Simple, SecondMeta): - pass - """) - classes = { - 'ABCMeta': ('FirstImpl', 'SecondImpl'), - 'type': ('ThirdImpl', ) - } - for metaclass, names in classes.items(): - for name in names: - impl = astroid[name] - meta = impl.metaclass() - self.assertIsInstance(meta, nodes.ClassDef) - self.assertEqual(meta.name, metaclass) - - def test_metaclass_type(self): - klass = test_utils.extract_node(""" - def with_metaclass(meta, base=object): - return meta("NewBase", (base, ), {}) - - class ClassWithMeta(with_metaclass(type)): #@ - pass - """) - self.assertEqual( - ['NewBase', 'object'], - [base.name for base in klass.ancestors()]) - - def test_no_infinite_metaclass_loop(self): - klass = test_utils.extract_node(""" - class SSS(object): - - class JJJ(object): - pass - - @classmethod - def Init(cls): - cls.JJJ = type('JJJ', (cls.JJJ,), {}) - - class AAA(SSS): - pass - - class BBB(AAA.JJJ): - pass - """) - self.assertFalse(scoped_nodes._is_metaclass(klass)) - ancestors = [base.name for base in klass.ancestors()] - self.assertIn('object', ancestors) - self.assertIn('JJJ', ancestors) - - def test_no_infinite_metaclass_loop_with_redefine(self): - nodes = test_utils.extract_node(""" - import datetime - - class A(datetime.date): #@ - @classmethod - def now(cls): - return cls() - - class B(datetime.date): #@ - pass - - datetime.date = A - datetime.date = B - """) - for klass in nodes: - self.assertEqual(None, klass.metaclass()) - - def test_metaclass_generator_hack(self): - klass = test_utils.extract_node(""" - import six - - class WithMeta(six.with_metaclass(type, object)): #@ - pass - """) - self.assertEqual( - ['object'], - [base.name for base in klass.ancestors()]) - self.assertEqual( - 'type', klass.metaclass().name) - - def test_using_six_add_metaclass(self): - klass = test_utils.extract_node(''' - import six - import abc - - @six.add_metaclass(abc.ABCMeta) - class WithMeta(object): - pass - ''') - inferred = next(klass.infer()) - metaclass = inferred.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.qname(), 'abc.ABCMeta') - - def test_using_invalid_six_add_metaclass_call(self): - klass = test_utils.extract_node(''' - import six - @six.add_metaclass() - class Invalid(object): - pass - ''') - inferred = next(klass.infer()) - self.assertIsNone(inferred.metaclass()) - - def test_nonregr_infer_callresult(self): - astroid = builder.parse(""" - class Delegate(object): - def __get__(self, obj, cls): - return getattr(obj._subject, self.attribute) - - class CompositeBuilder(object): - __call__ = Delegate() - - builder = CompositeBuilder(result, composite) - tgts = builder() - """) - instance = astroid['tgts'] - # used to raise "'_Yes' object is not iterable", see - # https://bitbucket.org/logilab/astroid/issue/17 - self.assertEqual(list(instance.infer()), [util.YES]) - - def test_slots(self): - astroid = builder.parse(""" - from collections import deque - from textwrap import dedent - - class First(object): #@ - __slots__ = ("a", "b", 1) - class Second(object): #@ - __slots__ = "a" - class Third(object): #@ - __slots__ = deque(["a", "b", "c"]) - class Fourth(object): #@ - __slots__ = {"a": "a", "b": "b"} - class Fifth(object): #@ - __slots__ = list - class Sixth(object): #@ - __slots__ = "" - class Seventh(object): #@ - __slots__ = dedent.__name__ - class Eight(object): #@ - __slots__ = ("parens") - class Ninth(object): #@ - pass - class Ten(object): #@ - __slots__ = dict({"a": "b", "c": "d"}) - """) - expected = [ - ('First', ('a', 'b')), - ('Second', ('a', )), - ('Third', None), - ('Fourth', ('a', 'b')), - ('Fifth', None), - ('Sixth', None), - ('Seventh', ('dedent', )), - ('Eight', ('parens', )), - ('Ninth', None), - ('Ten', ('a', 'c')), - ] - for cls, expected_value in expected: - slots = astroid[cls].slots() - if expected_value is None: - self.assertIsNone(slots) - else: - self.assertEqual(list(expected_value), - [node.value for node in slots]) - - @test_utils.require_version(maxver='3.0') - def test_slots_py2(self): - module = builder.parse(""" - class UnicodeSlots(object): - __slots__ = (u"a", u"b", "c") - """) - slots = module['UnicodeSlots'].slots() - self.assertEqual(len(slots), 3) - self.assertEqual(slots[0].value, "a") - self.assertEqual(slots[1].value, "b") - self.assertEqual(slots[2].value, "c") - - @test_utils.require_version(maxver='3.0') - def test_slots_py2_not_implemented(self): - module = builder.parse(""" - class OldStyle: - __slots__ = ("a", "b") - """) - msg = "The concept of slots is undefined for old-style classes." - with self.assertRaises(NotImplementedError) as cm: - module['OldStyle'].slots() - self.assertEqual(str(cm.exception), msg) - - def test_slots_empty_list_of_slots(self): - module = builder.parse(""" - class Klass(object): - __slots__ = () - """) - cls = module['Klass'] - self.assertEqual(cls.slots(), []) - - def test_slots_taken_from_parents(self): - module = builder.parse(''' - class FirstParent(object): - __slots__ = ('a', 'b', 'c') - class SecondParent(FirstParent): - __slots__ = ('d', 'e') - class Third(SecondParent): - __slots__ = ('d', ) - ''') - cls = module['Third'] - slots = cls.slots() - self.assertEqual(sorted(set(slot.value for slot in slots)), - ['a', 'b', 'c', 'd', 'e']) - - def test_all_ancestors_need_slots(self): - module = builder.parse(''' - class A(object): - __slots__ = ('a', ) - class B(A): pass - class C(B): - __slots__ = ('a', ) - ''') - cls = module['C'] - self.assertIsNone(cls.slots()) - cls = module['B'] - self.assertIsNone(cls.slots()) - - def assertEqualMro(self, klass, expected_mro): - self.assertEqual( - [member.name for member in klass.mro()], - expected_mro) - - @test_utils.require_version(maxver='3.0') - def test_no_mro_for_old_style(self): - node = test_utils.extract_node(""" - class Old: pass""") - with self.assertRaises(NotImplementedError) as cm: - node.mro() - self.assertEqual(str(cm.exception), "Could not obtain mro for " - "old-style classes.") - - @test_utils.require_version(maxver='3.0') - def test_combined_newstyle_oldstyle_in_mro(self): - node = test_utils.extract_node(''' - class Old: - pass - class New(object): - pass - class New1(object): - pass - class New2(New, New1): - pass - class NewOld(New2, Old): #@ - pass - ''') - self.assertEqualMro(node, ['NewOld', 'New2', 'New', 'New1', 'object', 'Old']) - self.assertTrue(node.newstyle) - - def test_with_metaclass_mro(self): - astroid = builder.parse(""" - import six - - class C(object): - pass - class B(C): - pass - class A(six.with_metaclass(type, B)): - pass - """) - self.assertEqualMro(astroid['A'], ['A', 'B', 'C', 'object']) - - def test_mro(self): - astroid = builder.parse(""" - class C(object): pass - class D(dict, C): pass - - class A1(object): pass - class B1(A1): pass - class C1(A1): pass - class D1(B1, C1): pass - class E1(C1, B1): pass - class F1(D1, E1): pass - class G1(E1, D1): pass - - class Boat(object): pass - class DayBoat(Boat): pass - class WheelBoat(Boat): pass - class EngineLess(DayBoat): pass - class SmallMultihull(DayBoat): pass - class PedalWheelBoat(EngineLess, WheelBoat): pass - class SmallCatamaran(SmallMultihull): pass - class Pedalo(PedalWheelBoat, SmallCatamaran): pass - - class OuterA(object): - class Inner(object): - pass - class OuterB(OuterA): - class Inner(OuterA.Inner): - pass - class OuterC(OuterA): - class Inner(OuterA.Inner): - pass - class OuterD(OuterC): - class Inner(OuterC.Inner, OuterB.Inner): - pass - class Duplicates(str, str): pass - - """) - self.assertEqualMro(astroid['D'], ['D', 'dict', 'C', 'object']) - self.assertEqualMro(astroid['D1'], ['D1', 'B1', 'C1', 'A1', 'object']) - self.assertEqualMro(astroid['E1'], ['E1', 'C1', 'B1', 'A1', 'object']) - with self.assertRaises(InconsistentMroError) as cm: - astroid['F1'].mro() - self.assertEqual(str(cm.exception), - "Cannot create a consistent method resolution order " - "for bases (B1, C1, A1, object), " - "(C1, B1, A1, object)") - - with self.assertRaises(InconsistentMroError) as cm: - astroid['G1'].mro() - self.assertEqual(str(cm.exception), - "Cannot create a consistent method resolution order " - "for bases (C1, B1, A1, object), " - "(B1, C1, A1, object)") - - self.assertEqualMro( - astroid['PedalWheelBoat'], - ["PedalWheelBoat", "EngineLess", - "DayBoat", "WheelBoat", "Boat", "object"]) - - self.assertEqualMro( - astroid["SmallCatamaran"], - ["SmallCatamaran", "SmallMultihull", "DayBoat", "Boat", "object"]) - - self.assertEqualMro( - astroid["Pedalo"], - ["Pedalo", "PedalWheelBoat", "EngineLess", "SmallCatamaran", - "SmallMultihull", "DayBoat", "WheelBoat", "Boat", "object"]) - - self.assertEqualMro( - astroid['OuterD']['Inner'], - ['Inner', 'Inner', 'Inner', 'Inner', 'object']) - - with self.assertRaises(DuplicateBasesError) as cm: - astroid['Duplicates'].mro() - self.assertEqual(str(cm.exception), "Duplicates found in the mro.") - self.assertTrue(issubclass(cm.exception.__class__, MroError)) - self.assertTrue(issubclass(cm.exception.__class__, ResolveError)) - - def test_generator_from_infer_call_result_parent(self): - func = test_utils.extract_node(""" - import contextlib - - @contextlib.contextmanager - def test(): #@ - yield - """) - result = next(func.infer_call_result(func)) - self.assertIsInstance(result, Generator) - self.assertEqual(result.parent, func) - - def test_type_three_arguments(self): - classes = test_utils.extract_node(""" - type('A', (object, ), {"a": 1, "b": 2, missing: 3}) #@ - """) - first = next(classes.infer()) - self.assertIsInstance(first, nodes.ClassDef) - self.assertEqual(first.name, "A") - self.assertEqual(first.basenames, ["object"]) - self.assertIsInstance(first["a"], nodes.Const) - self.assertEqual(first["a"].value, 1) - self.assertIsInstance(first["b"], nodes.Const) - self.assertEqual(first["b"].value, 2) - with self.assertRaises(NotFoundError): - first.getattr("missing") - - def test_implicit_metaclass(self): - cls = test_utils.extract_node(""" - class A(object): - pass - """) - type_cls = scoped_nodes.builtin_lookup("type")[1][0] - self.assertEqual(cls.implicit_metaclass(), type_cls) - - @test_utils.require_version(maxver='3.0') - def test_implicit_metaclass_is_none(self): - cls = test_utils.extract_node(""" - class A: pass - """) - self.assertIsNone(cls.implicit_metaclass()) - - def test_local_attr_invalid_mro(self): - cls = test_utils.extract_node(""" - # A has an invalid MRO, local_attr should fallback - # to using .ancestors. - class A(object, object): - test = 42 - class B(A): #@ - pass - """) - local = cls.local_attr('test')[0] - inferred = next(local.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - def test_has_dynamic_getattr(self): - module = builder.parse(""" - class Getattr(object): - def __getattr__(self, attrname): - pass - - class Getattribute(object): - def __getattribute__(self, attrname): - pass - - class ParentGetattr(Getattr): - pass - """) - self.assertTrue(module['Getattr'].has_dynamic_getattr()) - self.assertTrue(module['Getattribute'].has_dynamic_getattr()) - self.assertTrue(module['ParentGetattr'].has_dynamic_getattr()) - - # Test that objects analyzed through the live introspection - # aren't considered to have dynamic getattr implemented. - import datetime - astroid_builder = builder.AstroidBuilder() - module = astroid_builder.module_build(datetime) - self.assertFalse(module['timedelta'].has_dynamic_getattr()) - - def test_duplicate_bases_namedtuple(self): - module = builder.parse(""" - import collections - _A = collections.namedtuple('A', 'a') - - class A(_A): pass - - class B(A): pass - """) - self.assertRaises(DuplicateBasesError, module['B'].mro) - - def test_instance_bound_method_lambdas(self): - ast_nodes = test_utils.extract_node(''' - class Test(object): #@ - lam = lambda self: self - not_method = lambda xargs: xargs - Test() #@ - ''') - cls = next(ast_nodes[0].infer()) - self.assertIsInstance(next(cls.igetattr('lam')), scoped_nodes.Lambda) - self.assertIsInstance(next(cls.igetattr('not_method')), scoped_nodes.Lambda) - - instance = next(ast_nodes[1].infer()) - lam = next(instance.igetattr('lam')) - self.assertIsInstance(lam, BoundMethod) - not_method = next(instance.igetattr('not_method')) - self.assertIsInstance(not_method, scoped_nodes.Lambda) - - def test_class_extra_decorators_frame_is_not_class(self): - ast_node = test_utils.extract_node(''' - def ala(): - def bala(): #@ - func = 42 - ''') - self.assertEqual(ast_node.extra_decorators, []) - - def test_class_extra_decorators_only_callfunc_are_considered(self): - ast_node = test_utils.extract_node(''' - class Ala(object): - def func(self): #@ - pass - func = 42 - ''') - self.assertEqual(ast_node.extra_decorators, []) - - def test_class_extra_decorators_only_assignment_names_are_considered(self): - ast_node = test_utils.extract_node(''' - class Ala(object): - def func(self): #@ - pass - def __init__(self): - self.func = staticmethod(func) - - ''') - self.assertEqual(ast_node.extra_decorators, []) - - def test_class_extra_decorators_only_same_name_considered(self): - ast_node = test_utils.extract_node(''' - class Ala(object): - def func(self): #@ - pass - bala = staticmethod(func) - ''') - self.assertEqual(ast_node.extra_decorators, []) - self.assertEqual(ast_node.type, 'method') - - def test_class_extra_decorators(self): - static_method, clsmethod = test_utils.extract_node(''' - class Ala(object): - def static(self): #@ - pass - def class_method(self): #@ - pass - class_method = classmethod(class_method) - static = staticmethod(static) - ''') - self.assertEqual(len(clsmethod.extra_decorators), 1) - self.assertEqual(clsmethod.type, 'classmethod') - self.assertEqual(len(static_method.extra_decorators), 1) - self.assertEqual(static_method.type, 'staticmethod') - - def test_extra_decorators_only_class_level_assignments(self): - node = test_utils.extract_node(''' - def _bind(arg): - return arg.bind - - class A(object): - @property - def bind(self): - return 42 - def irelevant(self): - # This is important, because it used to trigger - # a maximum recursion error. - bind = _bind(self) - return bind - A() #@ - ''') - inferred = next(node.infer()) - bind = next(inferred.igetattr('bind')) - self.assertIsInstance(bind, nodes.Const) - self.assertEqual(bind.value, 42) - parent = bind.scope() - self.assertEqual(len(parent.extra_decorators), 0) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_transforms.py b/pymode/libs/astroid/tests/unittest_transforms.py deleted file mode 100644 index 1553bfc4..00000000 --- a/pymode/libs/astroid/tests/unittest_transforms.py +++ /dev/null @@ -1,245 +0,0 @@ -# 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 . - -from __future__ import print_function - -import contextlib -import time -import unittest - -from astroid import builder -from astroid import nodes -from astroid import parse -from astroid import transforms - - -@contextlib.contextmanager -def add_transform(manager, node, transform, predicate=None): - manager.register_transform(node, transform, predicate) - try: - yield - finally: - manager.unregister_transform(node, transform, predicate) - - -class TestTransforms(unittest.TestCase): - - def setUp(self): - self.transformer = transforms.TransformVisitor() - - def parse_transform(self, code): - module = parse(code, apply_transforms=False) - return self.transformer.visit(module) - - def test_function_inlining_transform(self): - def transform_call(node): - # Let's do some function inlining - inferred = next(node.infer()) - return inferred - - self.transformer.register_transform(nodes.Call, - transform_call) - - module = self.parse_transform(''' - def test(): return 42 - test() #@ - ''') - - self.assertIsInstance(module.body[1], nodes.Expr) - self.assertIsInstance(module.body[1].value, nodes.Const) - self.assertEqual(module.body[1].value.value, 42) - - def test_recursive_transforms_into_astroid_fields(self): - # Test that the transformer walks properly the tree - # by going recursively into the _astroid_fields per each node. - def transform_compare(node): - # Let's check the values of the ops - _, right = node.ops[0] - # Assume they are Consts and they were transformed before - # us. - return nodes.const_factory(node.left.value < right.value) - - def transform_name(node): - # Should be Consts - return next(node.infer()) - - self.transformer.register_transform(nodes.Compare, transform_compare) - self.transformer.register_transform(nodes.Name, transform_name) - - module = self.parse_transform(''' - a = 42 - b = 24 - a < b - ''') - - self.assertIsInstance(module.body[2], nodes.Expr) - self.assertIsInstance(module.body[2].value, nodes.Const) - self.assertFalse(module.body[2].value.value) - - def test_transform_patches_locals(self): - def transform_function(node): - assign = nodes.Assign() - name = nodes.AssignName() - name.name = 'value' - assign.targets = [name] - assign.value = nodes.const_factory(42) - node.body.append(assign) - - self.transformer.register_transform(nodes.FunctionDef, - transform_function) - - module = self.parse_transform(''' - def test(): - pass - ''') - - func = module.body[0] - self.assertEqual(len(func.body), 2) - self.assertIsInstance(func.body[1], nodes.Assign) - self.assertEqual(func.body[1].as_string(), 'value = 42') - - def test_predicates(self): - def transform_call(node): - inferred = next(node.infer()) - return inferred - - def should_inline(node): - return node.func.name.startswith('inlineme') - - self.transformer.register_transform(nodes.Call, - transform_call, - should_inline) - - module = self.parse_transform(''' - def inlineme_1(): - return 24 - def dont_inline_me(): - return 42 - def inlineme_2(): - return 2 - inlineme_1() - dont_inline_me() - inlineme_2() - ''') - values = module.body[-3:] - self.assertIsInstance(values[0], nodes.Expr) - self.assertIsInstance(values[0].value, nodes.Const) - self.assertEqual(values[0].value.value, 24) - self.assertIsInstance(values[1], nodes.Expr) - self.assertIsInstance(values[1].value, nodes.Call) - self.assertIsInstance(values[2], nodes.Expr) - self.assertIsInstance(values[2].value, nodes.Const) - self.assertEqual(values[2].value.value, 2) - - def test_transforms_are_separated(self): - # Test that the transforming is done at a separate - # step, which means that we are not doing inference - # on a partially constructred tree anymore, which was the - # source of crashes in the past when certain inference rules - # were used in a transform. - def transform_function(node): - if node.decorators: - for decorator in node.decorators.nodes: - inferred = next(decorator.infer()) - if inferred.qname() == 'abc.abstractmethod': - return next(node.infer_call_result(node)) - - manager = builder.MANAGER - with add_transform(manager, nodes.FunctionDef, transform_function): - module = builder.parse(''' - import abc - from abc import abstractmethod - - class A(object): - @abc.abstractmethod - def ala(self): - return 24 - - @abstractmethod - def bala(self): - return 42 - ''') - - cls = module['A'] - ala = cls.body[0] - bala = cls.body[1] - self.assertIsInstance(ala, nodes.Const) - self.assertEqual(ala.value, 24) - self.assertIsInstance(bala, nodes.Const) - self.assertEqual(bala.value, 42) - - def test_transforms_are_called_for_builtin_modules(self): - # Test that transforms are called for builtin modules. - def transform_function(node): - name = nodes.AssignName() - name.name = 'value' - node.args.args = [name] - return node - - manager = builder.MANAGER - predicate = lambda node: node.root().name == 'time' - with add_transform(manager, nodes.FunctionDef, - transform_function, predicate): - builder_instance = builder.AstroidBuilder() - module = builder_instance.module_build(time) - - asctime = module['asctime'] - self.assertEqual(len(asctime.args.args), 1) - self.assertIsInstance(asctime.args.args[0], nodes.AssignName) - self.assertEqual(asctime.args.args[0].name, 'value') - - def test_builder_apply_transforms(self): - def transform_function(node): - return nodes.const_factory(42) - - manager = builder.MANAGER - with add_transform(manager, nodes.FunctionDef, transform_function): - astroid_builder = builder.AstroidBuilder(apply_transforms=False) - module = astroid_builder.string_build('''def test(): pass''') - - # The transform wasn't applied. - self.assertIsInstance(module.body[0], nodes.FunctionDef) - - def test_transform_crashes_on_is_subtype_of(self): - # Test that we don't crash when having is_subtype_of - # in a transform, as per issue #188. This happened - # before, when the transforms weren't in their own step. - def transform_class(cls): - if cls.is_subtype_of('django.db.models.base.Model'): - return cls - return cls - - self.transformer.register_transform(nodes.ClassDef, - transform_class) - - self.parse_transform(''' - # Change environ to automatically call putenv() if it exists - import os - putenv = os.putenv - try: - # This will fail if there's no putenv - putenv - except NameError: - pass - else: - import UserDict - ''') - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_utils.py b/pymode/libs/astroid/tests/unittest_utils.py deleted file mode 100644 index ef832252..00000000 --- a/pymode/libs/astroid/tests/unittest_utils.py +++ /dev/null @@ -1,124 +0,0 @@ -# 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 . -import unittest - -from astroid import builder -from astroid import InferenceError -from astroid import nodes -from astroid import node_classes -from astroid import test_utils -from astroid import util as astroid_util - - -class InferenceUtil(unittest.TestCase): - - def test_not_exclusive(self): - module = builder.parse(""" - x = 10 - for x in range(5): - print (x) - - if x > 0: - print ('#' * x) - """, __name__, __file__) - xass1 = module.locals['x'][0] - assert xass1.lineno == 2 - xnames = [n for n in module.nodes_of_class(nodes.Name) if n.name == 'x'] - assert len(xnames) == 3 - assert xnames[1].lineno == 6 - self.assertEqual(node_classes.are_exclusive(xass1, xnames[1]), False) - self.assertEqual(node_classes.are_exclusive(xass1, xnames[2]), False) - - def test_if(self): - module = builder.parse(''' - if 1: - a = 1 - a = 2 - elif 2: - a = 12 - a = 13 - else: - a = 3 - a = 4 - ''') - a1 = module.locals['a'][0] - a2 = module.locals['a'][1] - a3 = module.locals['a'][2] - a4 = module.locals['a'][3] - a5 = module.locals['a'][4] - a6 = module.locals['a'][5] - self.assertEqual(node_classes.are_exclusive(a1, a2), False) - self.assertEqual(node_classes.are_exclusive(a1, a3), True) - self.assertEqual(node_classes.are_exclusive(a1, a5), True) - self.assertEqual(node_classes.are_exclusive(a3, a5), True) - self.assertEqual(node_classes.are_exclusive(a3, a4), False) - self.assertEqual(node_classes.are_exclusive(a5, a6), False) - - def test_try_except(self): - module = builder.parse(''' - try: - def exclusive_func2(): - "docstring" - except TypeError: - def exclusive_func2(): - "docstring" - except: - def exclusive_func2(): - "docstring" - else: - def exclusive_func2(): - "this one redefine the one defined line 42" - ''') - f1 = module.locals['exclusive_func2'][0] - f2 = module.locals['exclusive_func2'][1] - f3 = module.locals['exclusive_func2'][2] - f4 = module.locals['exclusive_func2'][3] - self.assertEqual(node_classes.are_exclusive(f1, f2), True) - self.assertEqual(node_classes.are_exclusive(f1, f3), True) - self.assertEqual(node_classes.are_exclusive(f1, f4), False) - self.assertEqual(node_classes.are_exclusive(f2, f4), True) - self.assertEqual(node_classes.are_exclusive(f3, f4), True) - self.assertEqual(node_classes.are_exclusive(f3, f2), True) - - self.assertEqual(node_classes.are_exclusive(f2, f1), True) - self.assertEqual(node_classes.are_exclusive(f4, f1), False) - self.assertEqual(node_classes.are_exclusive(f4, f2), True) - - def test_unpack_infer_uninferable_nodes(self): - node = test_utils.extract_node(''' - x = [A] * 1 - f = [x, [A] * 2] - f - ''') - inferred = next(node.infer()) - unpacked = list(node_classes.unpack_infer(inferred)) - self.assertEqual(len(unpacked), 3) - self.assertTrue(all(elt is astroid_util.YES - for elt in unpacked)) - - def test_unpack_infer_empty_tuple(self): - node = test_utils.extract_node(''' - () - ''') - inferred = next(node.infer()) - with self.assertRaises(InferenceError): - list(node_classes.unpack_infer(inferred)) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/transforms.py b/pymode/libs/astroid/transforms.py deleted file mode 100644 index 5d8fc91b..00000000 --- a/pymode/libs/astroid/transforms.py +++ /dev/null @@ -1,96 +0,0 @@ -# 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 . - -import collections -import warnings - - -class TransformVisitor(object): - """A visitor for handling transforms. - - The standard approach of using it is to call - :meth:`~visit` with an *astroid* module and the class - will take care of the rest, walking the tree and running the - transforms for each encountered node. - """ - - def __init__(self): - self.transforms = collections.defaultdict(list) - - 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 - warnings.warn('node %s substituted multiple times' % node) - node = ret - return node - - def _visit(self, node): - if hasattr(node, '_astroid_fields'): - for field in node._astroid_fields: - value = getattr(node, field) - visited = self._visit_generic(value) - setattr(node, field, visited) - return self._transform(node) - - def _visit_generic(self, node): - if isinstance(node, list): - return [self._visit_generic(child) for child in node] - elif isinstance(node, tuple): - return tuple(self._visit_generic(child) for child in node) - else: - return self._visit(node) - - 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 visit(self, module): - """Walk the given astroid *tree* and transform each encountered node - - Only the nodes which have transforms registered will actually - be replaced or changed. - """ - module.body = [self._visit(child) for child in module.body] - return self._transform(module) diff --git a/pymode/libs/astroid/util.py b/pymode/libs/astroid/util.py deleted file mode 100644 index 44e2039d..00000000 --- a/pymode/libs/astroid/util.py +++ /dev/null @@ -1,89 +0,0 @@ -# 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 . -# -# The code in this file was originally part of logilab-common, licensed under -# the same license. -import warnings - -from astroid import exceptions - - -def generate_warning(message, warning): - return lambda *args: warnings.warn(message % args, warning, stacklevel=3) - -rename_warning = generate_warning( - "%r is deprecated and will be removed in astroid %.1f, use %r instead", - PendingDeprecationWarning) - -attribute_to_method_warning = generate_warning( - "%s is deprecated and will be removed in astroid %.1f, use the " - "method '%s()' instead.", PendingDeprecationWarning) - -attribute_to_function_warning = generate_warning( - "%s is deprecated and will be removed in astroid %.1f, use the " - "function '%s()' instead.", PendingDeprecationWarning) - -method_to_function_warning = generate_warning( - "%s() is deprecated and will be removed in astroid %.1f, use the " - "function '%s()' instead.", PendingDeprecationWarning) - - -class _Yes(object): - """Special inference object, which is returned when inference fails.""" - def __repr__(self): - return 'YES' - - __str__ = __repr__ - - def __getattribute__(self, name): - if name == 'next': - raise AttributeError('next method should not be called') - if name.startswith('__') and name.endswith('__'): - return super(_Yes, self).__getattribute__(name) - if name == 'accept': - return super(_Yes, self).__getattribute__(name) - return self - - def __call__(self, *args, **kwargs): - return self - - def accept(self, visitor): - func = getattr(visitor, "visit_yes") - return func(self) - - -YES = _Yes() - -def safe_infer(node, context=None): - """Return the inferred value for the given node. - - Return None if inference failed or if there is some ambiguity (more than - one node has been inferred). - """ - try: - inferit = node.infer(context=context) - value = next(inferit) - except exceptions.InferenceError: - return - try: - next(inferit) - return # None if there is ambiguity on the inferred node - except exceptions.InferenceError: - return # there is some kind of ambiguity - except StopIteration: - return value diff --git a/pymode/libs/backports.functools_lru_cache-1.3-py3.5-nspkg.pth b/pymode/libs/backports.functools_lru_cache-1.3-py3.5-nspkg.pth deleted file mode 100644 index 0b1f79dd..00000000 --- a/pymode/libs/backports.functools_lru_cache-1.3-py3.5-nspkg.pth +++ /dev/null @@ -1 +0,0 @@ -import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('backports',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('backports', types.ModuleType('backports'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) diff --git a/pymode/libs/backports/configparser/__init__.py b/pymode/libs/backports/configparser/__init__.py deleted file mode 100644 index 06d7a085..00000000 --- a/pymode/libs/backports/configparser/__init__.py +++ /dev/null @@ -1,1390 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""Configuration file parser. - -A configuration file consists of sections, lead by a "[section]" header, -and followed by "name: value" entries, with continuations and such in -the style of RFC 822. - -Intrinsic defaults can be specified by passing them into the -ConfigParser constructor as a dictionary. - -class: - -ConfigParser -- responsible for parsing a list of - configuration files, and managing the parsed database. - - methods: - - __init__(defaults=None, dict_type=_default_dict, allow_no_value=False, - delimiters=('=', ':'), comment_prefixes=('#', ';'), - inline_comment_prefixes=None, strict=True, - empty_lines_in_values=True, default_section='DEFAULT', - interpolation=, converters=): - Create the parser. When `defaults' is given, it is initialized into the - dictionary or intrinsic defaults. The keys must be strings, the values - must be appropriate for %()s string interpolation. - - When `dict_type' is given, it will be used to create the dictionary - objects for the list of sections, for the options within a section, and - for the default values. - - When `delimiters' is given, it will be used as the set of substrings - that divide keys from values. - - When `comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in empty lines. Comments can be - indented. - - When `inline_comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in non-empty lines. - - When `strict` is True, the parser won't allow for any section or option - duplicates while reading from a single source (file, string or - dictionary). Default is True. - - When `empty_lines_in_values' is False (default: True), each empty line - marks the end of an option. Otherwise, internal empty lines of - a multiline option are kept as part of the value. - - When `allow_no_value' is True (default: False), options without - values are accepted; the value presented for these is None. - - sections() - Return all the configuration section names, sans DEFAULT. - - has_section(section) - Return whether the given section exists. - - has_option(section, option) - Return whether the given option exists in the given section. - - options(section) - Return list of configuration options for the named section. - - read(filenames, encoding=None) - Read and parse the list of named configuration files, given by - name. A single filename is also allowed. Non-existing files - are ignored. Return list of successfully read files. - - read_file(f, filename=None) - Read and parse one configuration file, given as a file object. - The filename defaults to f.name; it is only used in error - messages (if f has no `name' attribute, the string `' is used). - - read_string(string) - Read configuration from a given string. - - read_dict(dictionary) - Read configuration from a dictionary. Keys are section names, - values are dictionaries with keys and values that should be present - in the section. If the used dictionary type preserves order, sections - and their keys will be added in order. Values are automatically - converted to strings. - - get(section, option, raw=False, vars=None, fallback=_UNSET) - Return a string value for the named option. All % interpolations are - expanded in the return values, based on the defaults passed into the - constructor and the DEFAULT section. Additional substitutions may be - provided using the `vars' argument, which must be a dictionary whose - contents override any pre-existing defaults. If `option' is a key in - `vars', the value from `vars' is used. - - getint(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to an integer. - - getfloat(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a float. - - getboolean(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a boolean (currently case - insensitively defined as 0, false, no, off for False, and 1, true, - yes, on for True). Returns False or True. - - items(section=_UNSET, raw=False, vars=None) - If section is given, return a list of tuples with (name, value) for - each option in the section. Otherwise, return a list of tuples with - (section_name, section_proxy) for each section, including DEFAULTSECT. - - remove_section(section) - Remove the given file section and all its options. - - remove_option(section, option) - Remove the given option from the given section. - - set(section, option, value) - Set the given option. - - write(fp, space_around_delimiters=True) - Write the configuration state in .ini format. If - `space_around_delimiters' is True (the default), delimiters - between keys and values are surrounded by spaces. -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -from collections import MutableMapping -import functools -import io -import itertools -import re -import sys -import warnings - -from backports.configparser.helpers import OrderedDict as _default_dict -from backports.configparser.helpers import ChainMap as _ChainMap -from backports.configparser.helpers import from_none, open, str, PY2 - -__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError", - "NoOptionError", "InterpolationError", "InterpolationDepthError", - "InterpolationMissingOptionError", "InterpolationSyntaxError", - "ParsingError", "MissingSectionHeaderError", - "ConfigParser", "SafeConfigParser", "RawConfigParser", - "Interpolation", "BasicInterpolation", "ExtendedInterpolation", - "LegacyInterpolation", "SectionProxy", "ConverterMapping", - "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] - -DEFAULTSECT = "DEFAULT" - -MAX_INTERPOLATION_DEPTH = 10 - - -# exception classes -class Error(Exception): - """Base class for ConfigParser exceptions.""" - - def __init__(self, msg=''): - self.message = msg - Exception.__init__(self, msg) - - def __repr__(self): - return self.message - - __str__ = __repr__ - - -class NoSectionError(Error): - """Raised when no section matches a requested option.""" - - def __init__(self, section): - Error.__init__(self, 'No section: %r' % (section,)) - self.section = section - self.args = (section, ) - - -class DuplicateSectionError(Error): - """Raised when a section is repeated in an input source. - - Possible repetitions that raise this exception are: multiple creation - using the API or in strict parsers when a section is found more than once - in a single input file, string or dictionary. - """ - - def __init__(self, section, source=None, lineno=None): - msg = [repr(section), " already exists"] - if source is not None: - message = ["While reading from ", repr(source)] - if lineno is not None: - message.append(" [line {0:2d}]".format(lineno)) - message.append(": section ") - message.extend(msg) - msg = message - else: - msg.insert(0, "Section ") - Error.__init__(self, "".join(msg)) - self.section = section - self.source = source - self.lineno = lineno - self.args = (section, source, lineno) - - -class DuplicateOptionError(Error): - """Raised by strict parsers when an option is repeated in an input source. - - Current implementation raises this exception only when an option is found - more than once in a single file, string or dictionary. - """ - - def __init__(self, section, option, source=None, lineno=None): - msg = [repr(option), " in section ", repr(section), - " already exists"] - if source is not None: - message = ["While reading from ", repr(source)] - if lineno is not None: - message.append(" [line {0:2d}]".format(lineno)) - message.append(": option ") - message.extend(msg) - msg = message - else: - msg.insert(0, "Option ") - Error.__init__(self, "".join(msg)) - self.section = section - self.option = option - self.source = source - self.lineno = lineno - self.args = (section, option, source, lineno) - - -class NoOptionError(Error): - """A requested option was not found.""" - - def __init__(self, option, section): - Error.__init__(self, "No option %r in section: %r" % - (option, section)) - self.option = option - self.section = section - self.args = (option, section) - - -class InterpolationError(Error): - """Base class for interpolation-related exceptions.""" - - def __init__(self, option, section, msg): - Error.__init__(self, msg) - self.option = option - self.section = section - self.args = (option, section, msg) - - -class InterpolationMissingOptionError(InterpolationError): - """A string substitution required a setting which was not available.""" - - def __init__(self, option, section, rawval, reference): - msg = ("Bad value substitution: option {0!r} in section {1!r} contains " - "an interpolation key {2!r} which is not a valid option name. " - "Raw value: {3!r}".format(option, section, reference, rawval)) - InterpolationError.__init__(self, option, section, msg) - self.reference = reference - self.args = (option, section, rawval, reference) - - -class InterpolationSyntaxError(InterpolationError): - """Raised when the source text contains invalid syntax. - - Current implementation raises this exception when the source text into - which substitutions are made does not conform to the required syntax. - """ - - -class InterpolationDepthError(InterpolationError): - """Raised when substitutions are nested too deeply.""" - - def __init__(self, option, section, rawval): - msg = ("Recursion limit exceeded in value substitution: option {0!r} " - "in section {1!r} contains an interpolation key which " - "cannot be substituted in {2} steps. Raw value: {3!r}" - "".format(option, section, MAX_INTERPOLATION_DEPTH, - rawval)) - InterpolationError.__init__(self, option, section, msg) - self.args = (option, section, rawval) - - -class ParsingError(Error): - """Raised when a configuration file does not follow legal syntax.""" - - def __init__(self, source=None, filename=None): - # Exactly one of `source'/`filename' arguments has to be given. - # `filename' kept for compatibility. - if filename and source: - raise ValueError("Cannot specify both `filename' and `source'. " - "Use `source'.") - elif not filename and not source: - raise ValueError("Required argument `source' not given.") - elif filename: - source = filename - Error.__init__(self, 'Source contains parsing errors: %r' % source) - self.source = source - self.errors = [] - self.args = (source, ) - - @property - def filename(self): - """Deprecated, use `source'.""" - warnings.warn( - "The 'filename' attribute will be removed in future versions. " - "Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - return self.source - - @filename.setter - def filename(self, value): - """Deprecated, user `source'.""" - warnings.warn( - "The 'filename' attribute will be removed in future versions. " - "Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - self.source = value - - def append(self, lineno, line): - self.errors.append((lineno, line)) - self.message += '\n\t[line %2d]: %s' % (lineno, line) - - -class MissingSectionHeaderError(ParsingError): - """Raised when a key-value pair is found before any section header.""" - - def __init__(self, filename, lineno, line): - Error.__init__( - self, - 'File contains no section headers.\nfile: %r, line: %d\n%r' % - (filename, lineno, line)) - self.source = filename - self.lineno = lineno - self.line = line - self.args = (filename, lineno, line) - - -# Used in parser getters to indicate the default behaviour when a specific -# option is not found it to raise an exception. Created to enable `None' as -# a valid fallback value. -_UNSET = object() - - -class Interpolation(object): - """Dummy interpolation that passes the value through with no changes.""" - - def before_get(self, parser, section, option, value, defaults): - return value - - def before_set(self, parser, section, option, value): - return value - - def before_read(self, parser, section, option, value): - return value - - def before_write(self, parser, section, option, value): - return value - - -class BasicInterpolation(Interpolation): - """Interpolation as implemented in the classic ConfigParser. - - The option values can contain format strings which refer to other values in - the same section, or values in the special default section. - - For example: - - something: %(dir)s/whatever - - would resolve the "%(dir)s" to the value of dir. All reference - expansions are done late, on demand. If a user needs to use a bare % in - a configuration file, she can escape it by writing %%. Other % usage - is considered a user error and raises `InterpolationSyntaxError'.""" - - _KEYCRE = re.compile(r"%\(([^)]+)\)s") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return ''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace('%%', '') # escaped percent signs - tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax - if '%' in tmp_value: - raise ValueError("invalid interpolation syntax in %r at " - "position %d" % (value, tmp_value.find('%'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - rawval = parser.get(section, option, raw=True, fallback=rest) - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rawval) - while rest: - p = rest.find("%") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == "%": - accum.append("%") - rest = rest[2:] - elif c == "(": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - "bad interpolation variable reference %r" % rest) - var = parser.optionxform(m.group(1)) - rest = rest[m.end():] - try: - v = map[var] - except KeyError: - raise from_none(InterpolationMissingOptionError( - option, section, rawval, var)) - if "%" in v: - self._interpolate_some(parser, option, accum, v, - section, map, depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - "'%%' must be followed by '%%' or '(', " - "found: %r" % (rest,)) - - -class ExtendedInterpolation(Interpolation): - """Advanced variant of interpolation, supports the syntax used by - `zc.buildout'. Enables interpolation between sections.""" - - _KEYCRE = re.compile(r"\$\{([^}]+)\}") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return ''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace('$$', '') # escaped dollar signs - tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax - if '$' in tmp_value: - raise ValueError("invalid interpolation syntax in %r at " - "position %d" % (value, tmp_value.find('$'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - rawval = parser.get(section, option, raw=True, fallback=rest) - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rawval) - while rest: - p = rest.find("$") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == "$": - accum.append("$") - rest = rest[2:] - elif c == "{": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - "bad interpolation variable reference %r" % rest) - path = m.group(1).split(':') - rest = rest[m.end():] - sect = section - opt = option - try: - if len(path) == 1: - opt = parser.optionxform(path[0]) - v = map[opt] - elif len(path) == 2: - sect = path[0] - opt = parser.optionxform(path[1]) - v = parser.get(sect, opt, raw=True) - else: - raise InterpolationSyntaxError( - option, section, - "More than one ':' found: %r" % (rest,)) - except (KeyError, NoSectionError, NoOptionError): - raise from_none(InterpolationMissingOptionError( - option, section, rawval, ":".join(path))) - if "$" in v: - self._interpolate_some(parser, opt, accum, v, sect, - dict(parser.items(sect, raw=True)), - depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - "'$' must be followed by '$' or '{', " - "found: %r" % (rest,)) - - -class LegacyInterpolation(Interpolation): - """Deprecated interpolation used in old versions of ConfigParser. - Use BasicInterpolation or ExtendedInterpolation instead.""" - - _KEYCRE = re.compile(r"%\(([^)]*)\)s|.") - - def before_get(self, parser, section, option, value, vars): - rawval = value - depth = MAX_INTERPOLATION_DEPTH - while depth: # Loop through this until it's done - depth -= 1 - if value and "%(" in value: - replace = functools.partial(self._interpolation_replace, - parser=parser) - value = self._KEYCRE.sub(replace, value) - try: - value = value % vars - except KeyError as e: - raise from_none(InterpolationMissingOptionError( - option, section, rawval, e.args[0])) - else: - break - if value and "%(" in value: - raise InterpolationDepthError(option, section, rawval) - return value - - def before_set(self, parser, section, option, value): - return value - - @staticmethod - def _interpolation_replace(match, parser): - s = match.group(1) - if s is None: - return match.group() - else: - return "%%(%s)s" % parser.optionxform(s) - - -class RawConfigParser(MutableMapping): - """ConfigParser that does not do interpolation.""" - - # Regular expressions for parsing section headers and options - _SECT_TMPL = r""" - \[ # [ - (?P
[^]]+) # very permissive! - \] # ] - """ - _OPT_TMPL = r""" - (?P