k now... emacs>vim
This commit is contained in:
521
.emacs.d/elpa/elpy-20171206.847/NEWS.rst
Normal file
521
.emacs.d/elpa/elpy-20171206.847/NEWS.rst
Normal file
@@ -0,0 +1,521 @@
|
||||
New in Elpy 1.17.0
|
||||
==================
|
||||
|
||||
- The xref functionality in newer Emacsen is now supported for
|
||||
following symbols at point.
|
||||
- Elpy now supports PEP 397 for Windows executable names.
|
||||
- In addition to pylint, Elpy now also supports epylint correctly.
|
||||
- A number of features for working with interactive Python have been added to
|
||||
Elpy; e.g., commands for sending code fragments to the Python shell and the
|
||||
ability to echo their output in the message area. See the documentation for a
|
||||
full list.
|
||||
- Bunch of little bugfixes.
|
||||
|
||||
|
||||
New in Elpy 1.16.0
|
||||
==================
|
||||
|
||||
- You can now change which function is used to run test commands,
|
||||
instead of the default ``compile``, using
|
||||
``elpy-test-compilation-function``. This allows using ``pdb`` to run
|
||||
tests in a debugger, for example.
|
||||
- Elpy now sets ``IPY_TEST_SIMPLE_PROMPT``, which should prevent a
|
||||
number of problems with IPython 5.
|
||||
- If you like Elpy, you can now sponsor its development using Patreon
|
||||
at https://www.patreon.com/jorgenschaefer
|
||||
|
||||
|
||||
New in Elpy 1.15.0
|
||||
==================
|
||||
|
||||
- Elpy now supports profiling, try ``elpy-profile-buffer-or-region``!
|
||||
- Do not randomly downcase completion candidates anymore.
|
||||
- Work around a bug in Emacs 25.1 and before related to current
|
||||
IPython shells.
|
||||
- And lots of other bugfixes.
|
||||
|
||||
|
||||
New in Elpy 1.14.0
|
||||
==================
|
||||
|
||||
- Basic Django support. Try ``C-c C-x c`` and ``C-c C-x r``! Thanks to
|
||||
Daniel Gopar for this.
|
||||
- You can now use manage.py to run Django tests, instead of always
|
||||
using django-admin.py.
|
||||
- When called with a prefix argument ``elpy-importmagic-add-import``
|
||||
will now ask for an alias name to import as.
|
||||
|
||||
|
||||
New in Elpy 1.13.0
|
||||
==================
|
||||
|
||||
- Fewer surprises with syntax checks, ``C-c C-z``, reformatting
|
||||
- Improved behavior for reformatting.
|
||||
- Improved documentation for IPython. IPython 5 broke a lot of things
|
||||
with Emacs. Use it at your own risk.
|
||||
|
||||
|
||||
New in Elpy 1.12.0
|
||||
==================
|
||||
|
||||
- Some symbols can now be completed with parentheses after them,
|
||||
useful for functions. The heuristic for when to add parentheses and
|
||||
not is not optimal, so this is not enabled by default—customize
|
||||
``elpy-company-post-completion-function`` to enable this feature.
|
||||
- Support dedicated Python shells (one per Python file). You can
|
||||
customized ``elpy-dedicated-shells`` to make this the default.
|
||||
- Elpy now uses ``python -m pip`` instead of pip directly to improve
|
||||
interaction with virtualenvs.
|
||||
- Support for Python 2.6 has been officially dropped.
|
||||
- Display for backend errors has been disabled by default. Jedi has
|
||||
not had a release in a long while, and many bugs have been unfixed.
|
||||
These errors have only caused added workload for Elpy maintainers.
|
||||
The option will be reverted once Jedi has had a new release.
|
||||
|
||||
|
||||
New in Elpy 1.11.0
|
||||
==================
|
||||
|
||||
- Elpy now supports yapf to format your code.
|
||||
- You can now adjust whether Elpy should hide modes from the mode line
|
||||
or not using ``elpy-remove-modeline-lighter``
|
||||
- When the new option ``elpy-disable-backend-error-display`` is set,
|
||||
Elpy will not show its error pop-up anymore. This can be useful if
|
||||
you run into an annoying bug in Jedi, for example.
|
||||
- New command ``elpy-goto-definition-other-window`` on ``C-x 4 M-.``.
|
||||
- Expanding ``super`` now gives the short form supported in Python 3.
|
||||
- All Rope errors are now caught, as the upstream maintainers did not
|
||||
show interest in distinguishing between malformed input and bugs in
|
||||
their library.
|
||||
|
||||
|
||||
New in Elpy 1.10.0
|
||||
==================
|
||||
|
||||
- Marking the current indentation level at the top level will now mark
|
||||
the whole buffer.
|
||||
- The region will be normalized before re-indenting it, making the
|
||||
behavior more predictable for partially marked lines.
|
||||
- Using autopep8 on the whole buffer will now keep point (roughly) at
|
||||
the same location as it was.
|
||||
- The autopep8 code now also uses the same configuration options as
|
||||
the command line tool.
|
||||
- Malformed JSON data from the backend is now handled better.
|
||||
- RPC processes are restarted when the current virtualenv changes.
|
||||
- Python 3.5 is now officially supported.
|
||||
- Flymake will now not be enabled in buffers without file name, where
|
||||
it can't run anyhow, or when the checker program does not exist in
|
||||
the first place.
|
||||
- It is now possible to ask Elpy not to remove the mode line lighter
|
||||
of company mode, which can be useful if you use company in other
|
||||
modes.
|
||||
- Test discovery now also allows file names without "test" in them to
|
||||
be tested. Classes and methods still require the substring, though.
|
||||
- Spurious equals signs at the end of completions from Jedi will now
|
||||
be ignored.
|
||||
- Various other bug fixes.
|
||||
|
||||
|
||||
New in Elpy 1.9.0
|
||||
=================
|
||||
|
||||
- Elpy now supports the ``autopep8`` library for automatically
|
||||
formatting Python code. All refactoring-related code is now grouped
|
||||
under ``C-c C-r``. Use ``C-c C-r i`` to fix up imports using
|
||||
importmagic, ``C-c C-r p`` to fix up Python code with autopep8, and
|
||||
``C-c C-r r`` to bring up the old Rope refactoring menu.
|
||||
- ``C-c C-b`` will now select a region containing surrounding lines of
|
||||
the current indentation or more.
|
||||
- ``C-c C-z`` in a Python shell will now switch back to the last
|
||||
Python buffer, allowing to use the key to cycle back and forth
|
||||
between the Python buffer and shell.
|
||||
- The pattern used for ``C-c C-s`` is now customizeable in
|
||||
``elpy-rgrep-file-pattern``.
|
||||
- ``<C-return>`` now can be used to send the current statement to the
|
||||
Python shell. Be careful, this can break with nested statements.
|
||||
- The Elpy minor mode now also works in modes derived from
|
||||
``python-mode``, not just in the mode itself.
|
||||
|
||||
|
||||
New in Elpy 1.8.1
|
||||
=================
|
||||
|
||||
- Ignore a ``KeyError`` from Jedi 0.9.0 which occurs a lot in normal
|
||||
code.
|
||||
|
||||
|
||||
New in Elpy 1.8.0
|
||||
=================
|
||||
|
||||
- Emacs 24.5 is now officially supported
|
||||
- The new configuration option ``elpy-rpc-ignored-buffer-size`` defines a maximum buffer size to be handle completion in, to avoid laggy interaction in unusually large files
|
||||
- Indentation block movement was replaced with code that just moves the marked block or the current line; this should be a lot less magical and more predictable
|
||||
- Running the test at point now correctly ignores any inner methods
|
||||
- Jedi docstrings now show the full name of the object
|
||||
- The RPC interpreter is now chosen correctly on cygwin
|
||||
- ``elpy-shell-send-region-or-buffer`` now warns of tabs in the data being sent
|
||||
- Elpy now binds stdout and stderr to ``/dev/null`` to avoid being confused by spurious output from other libraries
|
||||
- RPC buffers (and processes) are removed after some time to avoid them piling up endlessly
|
||||
- It is not possibly anymore to use customize alone to use ipython, because of some bad interaction between custom options in Elpy and python.el
|
||||
- And lots of bugfixes (50 issues closed!)
|
||||
|
||||
|
||||
New in Elpy 1.7.1
|
||||
=================
|
||||
|
||||
- Do not fail on errors from importmagic.
|
||||
- Handle new minor mode behavior of new versions of yasnippet.
|
||||
- Do use the argument to ``elpy-use-ipython`` correctly.
|
||||
- Handle unexpected data from the backend more gracefully.
|
||||
|
||||
|
||||
New in Elpy 1.7.0
|
||||
=================
|
||||
|
||||
- Elpy now can add missing import directives automatically, by using
|
||||
Alec Thomas' excellent importmagic_ library. Use ``C-c C-m`` to add
|
||||
a single import statement, or ``C-c C-S-m`` to include all missing
|
||||
import statements. Many thanks to Georg Brandl for doing a lot of
|
||||
work to bring this feature to Elpy!
|
||||
- The Jedi backend now also supports ``C-c C-d`` to display a
|
||||
docstring. Thanks again to Georg Brandl for the patch.
|
||||
- It is now possible to disable the display of the current function in
|
||||
the echo area by setting ``elpy-eldoc-show-current-function`` to
|
||||
``nil``.
|
||||
- idomenu was removed.
|
||||
- Twisted's Trial test runner is now supported. Thanks to Elric Milon
|
||||
for the patch!
|
||||
- All test runners now use a variable to decide which command to run,
|
||||
which for example allows using ``manage.py`` for the Django test
|
||||
runner, or your own test script which sets up the environment
|
||||
correctly.
|
||||
- Emacs 24.4 is now officially supported.
|
||||
- Various bugfixes.
|
||||
|
||||
.. _importmagic: https://github.com/alecthomas/importmagic
|
||||
|
||||
New in Elpy 1.6.0
|
||||
=================
|
||||
|
||||
- When point is on a line with a flymake error, Elpy will now show the
|
||||
error in the echo area.
|
||||
- The movement commands (``C-<cursor>``) have been reworked again.
|
||||
Going left and right will now move by indentation levels left of the
|
||||
current indentation, i.e. jump four spaces, and by words right of
|
||||
the current indentation. Going up and down will go to the previous
|
||||
or next line with the indentation level point is at, not the
|
||||
indentation the line has. Try it, it's more difficult to explain
|
||||
than to use.
|
||||
- Completion results are now sorted more sensibly, with
|
||||
single-underscore symbols at the end, and double-underscore symbols
|
||||
after normal symbols, but before single-underscore ones.
|
||||
- ``M-x elpy-config`` will now point out if there are newer versions
|
||||
available for packages used by Elpy.
|
||||
- ``M-x elpy-config`` will now warn if ``~/.local/bin`` is not in
|
||||
``PATH`` while there is no virtualenv active.
|
||||
- The ``M-x elpy-version`` command is back by popular demand.
|
||||
- RPC buffers used by Elpy are now hidden by default, having a space
|
||||
at the beginning of the name.
|
||||
- When the Rope library throws an error, Elpy will now also attempt to
|
||||
provide reproduction steps. This used to only happen for Jedi.
|
||||
- Various bug fixes.
|
||||
|
||||
|
||||
New in Elpy 1.5.1
|
||||
=================
|
||||
|
||||
- Fix a bug where company-mode might get confused about the current
|
||||
backend, leading to an error about ``Symbol's function definition is
|
||||
void: nil``
|
||||
- Fix Rope so it won’t search the whole project directory. This was an
|
||||
intended feature in v1.5 which did not work originally.
|
||||
- Use ``yas-text`` instead of ``text`` in snippets for compatibility
|
||||
with the unreleased yasnippet from MELPA (thanks to Daniel Wu!)
|
||||
|
||||
New in Elpy 1.5.0
|
||||
=================
|
||||
|
||||
- Elpy now has a `manual`_. Additionally, there's a menu bar now which
|
||||
should make it easier to discover Elpy features.
|
||||
- The Elpy Python package now ships with the Emacs Lisp package,
|
||||
removing the need to install Elpy via pip.
|
||||
- Python 3.4 is now officially supported.
|
||||
- The new command ``elpy-config`` can be used to configure Elpy using
|
||||
Emacs' built-in customize system. Elpy has been changed to make the
|
||||
most of this.
|
||||
- Elpy now uses company-mode instead of auto-complete for on-the-fly
|
||||
auto completion. This changes a few things. There is no automatic
|
||||
documentation popup anymore. Instead, you can type ``C-d`` and get
|
||||
the documentation buffer. In addition, you can type ``C-w`` to see
|
||||
the source of the current candidate in context.
|
||||
- Elpy now uses pyvenv as the virtualenv module, enabling
|
||||
virtualenvwrapper hooks.
|
||||
- We now ship with a large number of YASnippet snippets. Try ``M-x
|
||||
yas-insert-snippet``.
|
||||
- The new unified test running interface on ``C-c C-t`` will try to
|
||||
determine the current test and run it, or, failing that, run all
|
||||
tests. Provide a prefix argument to just run all tests no matter
|
||||
what. You can change the test runner to be used using
|
||||
``elpy-set-test-runner``. Elpy supports the default unittest
|
||||
discover runner, the Django discover runner, nosetests and py.test
|
||||
by default. New test runners can easily be defined.
|
||||
- There's a new multi-edit functionality. ``C-c C-e`` will edit all
|
||||
occurrences of the symbol under point. When using Jedi, this is
|
||||
using semantic information as opposed to just syntactic one. When a
|
||||
region is active, edit all occurrences of the text in region in the
|
||||
current buffer.
|
||||
- When sending Python code to the interactive interpreter using ``C-c
|
||||
C-c``, Elpy will now not automatically pop to the interpreter
|
||||
anymore. Use ``C-c C-z`` to switch to the interpreter.
|
||||
- Elpy will now display the current class and function if there is no
|
||||
call tip to be displayed. Removes the ``C-c C-q`` binding.
|
||||
- If there is a call tip, highlight the current argument (requires Jedi).
|
||||
- The documentation interface using ``C-c C-d`` is much smarter now,
|
||||
falling back to pydoc when necessary and providing sensible
|
||||
completion for that, too. Provide a prefix argument if you want no
|
||||
smarts, just pydoc.
|
||||
- ``<S-return>`` and ``<C-S-return>`` now open a line below or above
|
||||
the current one.
|
||||
- ``<C-cursor>`` will now navigate between Python blocks of the same
|
||||
indentation level. ``<M-cursor>`` will move the current block. Try
|
||||
it, it's easier to understand when you see it than to explain it.
|
||||
- There's a new concept of modules. The variable
|
||||
``elpy-default-minor-modes`` is gone (use ``elpy-mode-hook`` for
|
||||
minor modes). Instead, there's now ``elpy-modules`` which can be
|
||||
used to enable or disable certain features of Elpy.
|
||||
- ``elpy-clean-modeline`` is gone, modules now clean themselves up.
|
||||
- Elpy now distinguishes between the project root, where project files
|
||||
are located, and the library root, which should be part of
|
||||
``sys.path`` to import the module under development.
|
||||
- ``elpy-project-ignored-directories`` replaces the old
|
||||
``elpy-rgrep-ignored-directories`` and is used by more features.
|
||||
- ``elpy-doc-websearch`` has been removed as it was barely useable
|
||||
as is.
|
||||
- Elpy now tries to be more helpful when errors in the backend happen.
|
||||
This removes ``elpy-rpc-traceback``, as that will be displayed by
|
||||
default.
|
||||
- Optimizations were added to handle large files, making general
|
||||
interaction a lot faster.
|
||||
- When Rope is being used, do not search through unusually large
|
||||
directories. This should speed up interaction in those cases,
|
||||
especially when editing a file in the home directory.
|
||||
- And a whole lot of minor bug fixes and little improvements.
|
||||
|
||||
.. _manual: https://elpy.readthedocs.io/
|
||||
|
||||
|
||||
New in Elpy 1.4.2
|
||||
==================
|
||||
|
||||
- Minor bugfix to prevent an error from projectile-project-root to
|
||||
interfere with Elpy’s project finding strategy.
|
||||
|
||||
New in Elpy 1.4.1
|
||||
=================
|
||||
|
||||
- Elpy now sets project-wide preferences for Rope, enabling completion
|
||||
in the sys package, among others.
|
||||
- An error is avoided in the Jedi backend when trying to go to symbols
|
||||
in compiled packages.
|
||||
- A compatibility alias was added for nose.el, which insists on
|
||||
breaking backwards compatibility with Emacs 24.x.
|
||||
|
||||
New in Elpy 1.4.0
|
||||
=================
|
||||
|
||||
- Elpy has moved to its own ELPA. Make sure to update your
|
||||
package-archives (as described above).
|
||||
- For a file in a Projectile-managed project is opened, Elpy will now
|
||||
use Projectile’s project root.
|
||||
- When the user has set a valid python-check-command, elpy will now
|
||||
refrain from overriding it.
|
||||
- On Windows, elpy is now using the pythonw.exe interpreter for the
|
||||
RPC process, as that seems to be causing fewer issues.
|
||||
- And various smaller bugfixes.
|
||||
|
||||
New in Elpy 1.3.0
|
||||
=================
|
||||
|
||||
- virtualenv.el has been replaced by pyvenv.el, as that library offers
|
||||
more features.
|
||||
- elpy-rpc-restart now works globally, not just in Elpy buffers.
|
||||
- Elpy does not try to complete in comments anymore.
|
||||
- The new command elpy-rpc-traceback gives access to the last stack
|
||||
trace in the Elpy backend, helping with debugging problems.
|
||||
- The flymake check function is now run with the current directory as
|
||||
/ to avoid accidental imports.
|
||||
- Ensure correct handling of yas-snippet-dirs by Elpy. This variable
|
||||
can be a string, so ensure it’s a list before adding to it.
|
||||
- The new variable elpy-show-installation-instructions can be used to
|
||||
disable the installation screen.
|
||||
- Fix a very nasty bug causing spurious empty lines in a buffer or
|
||||
consume 100% CPU in certain situations when using the Jedi backend.
|
||||
Thanks to Matthias Dahl for finding this bug.
|
||||
- Various other bugfixes.
|
||||
|
||||
New in Elpy 1.2.1
|
||||
=================
|
||||
|
||||
Bugfix release.
|
||||
|
||||
- The refactoring was not ported to the new asynchronous API,
|
||||
resulting in an error when refactoring was attempted.
|
||||
- The project root now always returns a directory. Too many parts of
|
||||
elpy relies on this. If the project root turns out to be your home
|
||||
directory, elpy will warn you about it.
|
||||
- Elpy now works correctly with Emacs 24.2. There were some
|
||||
compatibility functions missing.
|
||||
- Blocking RPC calls now do not block for one second even if there is
|
||||
process output.
|
||||
|
||||
New in Elpy 1.2
|
||||
===============
|
||||
|
||||
- Elpy now uses asynchronous RPC. This means that Emacs should not
|
||||
freeze anymore while eldoc or auto-complete functions run.
|
||||
- ``elpy-shell-send-region-or-buffer`` will now remove common
|
||||
indentation of the region, making it possible to easily send parts
|
||||
of an if statement or function body without manually adjusting the
|
||||
indentation.
|
||||
- The Python package depends on ``flake8``, and will also try to be
|
||||
smarter when detecting ``flake8`` for on-the-fly checking.
|
||||
- ``elpy-check`` can be run with a prefix argument to check the whole
|
||||
project, instead of only the current file.
|
||||
- ``elpy-rgrep-symbol`` now ignores a few common directories
|
||||
(``.tox``, ``build``, ``dist``).
|
||||
- When using the rope backend, Elpy will not create the
|
||||
``.ropeproject`` folders anymore. This should keep projects a lot
|
||||
cleaner.
|
||||
|
||||
New in Elpy 1.1
|
||||
===============
|
||||
|
||||
- Elpy now always uses the root directory of the package as the
|
||||
project root; this should avoid some confusion and improve
|
||||
auto-completion suggestions
|
||||
- ``elpy-shell-send-region-or-buffer`` now accepts a prefix argument
|
||||
to run code wrapped behind ``if __name__ == '__main__'``, which is
|
||||
ignored by default
|
||||
- ``elpy-project-root`` is now a safe local variable and can be set
|
||||
from file variables
|
||||
- Elpy now supports project-specific RPC processes, see
|
||||
``elpy-rpc-project-specific`` for how to use this
|
||||
- ``M-*`` now works to go back where you came from after a ``M-.``
|
||||
- Elpy now ships with a few dedicated snippets for YASnippet
|
||||
- Support and require Jedi 0.6.0
|
||||
|
||||
New in Elpy 1.0
|
||||
===============
|
||||
|
||||
- Version 0.9 was a release candidate, so this release focused on bug
|
||||
fixes instead of new features.
|
||||
- ``elpy-enable`` now takes an optional argument that skips variable
|
||||
initialization for those users who prefer their own defaults for
|
||||
other modes.
|
||||
- ``python-check.sh`` has been removed from Elpy, as the flake8 tool
|
||||
from pypi does everything it does, only better.
|
||||
- Elpy will now start the helper subprocess in the root directory,
|
||||
avoiding accidental Python path clobbering.
|
||||
|
||||
New in Elpy 0.9
|
||||
===============
|
||||
|
||||
- Elpy now officially support Python 2.6, 2.7 and 3.3 on Emacs 24.2
|
||||
and 24.3, with continuous integration tests thanks to
|
||||
`Travis CI`_.
|
||||
- Extended support for Pydoc. ``C-u C-c C-d`` will now prompt for an
|
||||
auto-completed symbol to run Pydoc on. The pydoc output will be
|
||||
formatted and placed in a help buffer for easy review.
|
||||
- Refactoring support is back. ``C-c C-r`` will pop up a refactoring
|
||||
wizard offering various refactoring options. Most of them depend on
|
||||
the presence of Rope, though, even if Jedi is used as a completion
|
||||
backend.
|
||||
- The Rope backend has been extended to provide completions for
|
||||
modules in an import clause.
|
||||
- New refactoring option: Add missing imports. This will search for
|
||||
undefined symbols in the current file and automatically add
|
||||
appropriate imports.
|
||||
- ``C-c C-c (elpy-rgrep-symbol)`` now prompts for a regexp when a prefix
|
||||
argument is given instead of using the symbol at point.
|
||||
|
||||
.. _Travis CI: https://travis-ci.org/
|
||||
|
||||
New in Elpy 0.8
|
||||
===============
|
||||
|
||||
Python Backend Rewrite
|
||||
----------------------
|
||||
|
||||
- Elpy does not use Pymacs, Ropemacs and Ropemode anymore, but instead
|
||||
provides its own Python interface with the elpy package on PyPI.
|
||||
- This not only should improve performance, but also enables using
|
||||
Jedi as an alternative backend for completion. Use ``M-x
|
||||
elpy-set-backend`` to change between rope and jedi. For now, this
|
||||
does disable all refactoring support, though.
|
||||
|
||||
Project Support
|
||||
---------------
|
||||
|
||||
- Elpy now has built-in project support. The interface is rather
|
||||
simple: You can set ``elpy-project-root`` to the correct value in
|
||||
``.dir-locals.el``, or just rely on the automatic detection. If you
|
||||
change your mind, you can always just ``elpy-set-project-root``.
|
||||
- New dependency: Find File in Project (ffip), bound to ``C-c C-f`` by
|
||||
default. This will allow you to find files anywhere in your project
|
||||
using a search-as-you-type interface like ido.
|
||||
- New dependency: nose, bound to ``C-c C-t`` by default. This will run
|
||||
the nosetests binary in the root of your current library directory.
|
||||
You can restrict the tests being run to the current test or the
|
||||
current module by adding prefix arguments.
|
||||
- New function: Recursive grep for symbol, bound to ``C-c C-s`` by
|
||||
default. This will search for the symbol at point in the whole
|
||||
project.
|
||||
|
||||
New dependencies
|
||||
----------------
|
||||
|
||||
- idomenu, bound to ``C-c C-j`` by default. This replaces the standard
|
||||
imenu interface with an ido-based search-as-you-type interface for
|
||||
definitions in the current buffer.
|
||||
- virtualenv.el, replacing pyvirtualenv.el). Use ``M-x
|
||||
virtualenv-workon`` to enable a virtualenv.
|
||||
- iedit.el, bound to ``M-,`` by default. This highlights all occurrences
|
||||
of the symbol at point or the active region in the current buffer or
|
||||
narrowing. When you edit any of them, all others will be edited the
|
||||
same. This allows some basic and very quick refactoring.
|
||||
- New variable ``elpy-default-minor-modes`` which is run by ``elpy-mode``
|
||||
on startup. If you don’t want to use some modes, remove them from
|
||||
here.
|
||||
|
||||
Key Bindings and Functions
|
||||
--------------------------
|
||||
|
||||
- The key bindings have been reworked and cleaned up. Sorry, this
|
||||
might cause confusion.
|
||||
- Yasnippet is now on its own keybinding, ``C-c C-i``, instead of
|
||||
sharing the auto-complete interface. This was done because some
|
||||
snippets conflicted with legitimate, unsnippy completions.
|
||||
- New function: Occur Definitions, bound to ``C-c C-o`` by default. This
|
||||
will run the standard occur command to show definitions (classes and
|
||||
functions) in your current buffer, giving you a very quick outline
|
||||
and the ability to jump to different definitions quickly.
|
||||
- New function: Show Defun, bound to ``C-c C-q`` by default. This will
|
||||
show the current method and possibly class in the mode line, which
|
||||
is helpful in long functions.
|
||||
- New functions: Forward/backward definition, bound to ``M-n`` and ``M-p``
|
||||
as well as ``<M-down>`` and ``<M-up>`` by default. These will jump to
|
||||
the next or previous definition (class or function), helping with
|
||||
quick navigation through a file.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
- The documentation function (``C-c C-d``) now uses pydoc when a prefix
|
||||
arg is given.
|
||||
- The web search function (``C-c C-w``) now searches for the current
|
||||
symbol by default. The tab-completing web documentation interface
|
||||
was removed and is scheduled to be replaced with a new pydoc
|
||||
interface in future versions.
|
||||
- The ``python-check.sh`` is now shipped with elpy. If you load elpy.el
|
||||
before you load python.el, it should be the default
|
||||
``python-check-command``.
|
||||
51
.emacs.d/elpa/elpy-20171206.847/elpy-autoloads.el
Normal file
51
.emacs.d/elpa/elpy-20171206.847/elpy-autoloads.el
Normal file
@@ -0,0 +1,51 @@
|
||||
;;; elpy-autoloads.el --- automatically extracted autoloads
|
||||
;;
|
||||
;;; Code:
|
||||
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
|
||||
|
||||
;;;### (autoloads nil "elpy" "elpy.el" (23080 28380 123219 501000))
|
||||
;;; Generated autoloads from elpy.el
|
||||
|
||||
(autoload 'elpy-enable "elpy" "\
|
||||
Enable Elpy in all future Python buffers.
|
||||
|
||||
\(fn &optional IGNORED)" t nil)
|
||||
|
||||
(autoload 'elpy-mode "elpy" "\
|
||||
Minor mode in Python buffers for the Emacs Lisp Python Environment.
|
||||
|
||||
This mode fully supports virtualenvs. Once you switch a
|
||||
virtualenv using \\[pyvenv-workon], you can use
|
||||
\\[elpy-rpc-restart] to make the elpy Python process use your
|
||||
virtualenv.
|
||||
|
||||
\\{elpy-mode-map}
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(autoload 'elpy-config "elpy" "\
|
||||
Configure Elpy.
|
||||
|
||||
This function will pop up a configuration buffer, which is mostly
|
||||
a customize buffer, but has some more options.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'elpy-version "elpy" "\
|
||||
Display the version of Elpy.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil nil ("elpy-django.el" "elpy-pkg.el" "elpy-profile.el"
|
||||
;;;;;; "elpy-refactor.el" "elpy-shell.el") (23080 28381 456561 159000))
|
||||
|
||||
;;;***
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; End:
|
||||
;;; elpy-autoloads.el ends here
|
||||
170
.emacs.d/elpa/elpy-20171206.847/elpy-django.el
Normal file
170
.emacs.d/elpa/elpy-20171206.847/elpy-django.el
Normal file
@@ -0,0 +1,170 @@
|
||||
;;; elpy-django.el --- Django extension for elpy
|
||||
|
||||
;; Copyright (C) 2013-2016 Jorgen Schaefer
|
||||
|
||||
;; Author: Daniel Gopar <gopardaniel@gmail.com>
|
||||
;; URL: https://github.com/jorgenschaefer/elpy
|
||||
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License
|
||||
;; as published by the Free Software Foundation; either version 3
|
||||
;; of the License, or (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file serves as an extension to elpy by adding django support
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 's)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; User customization
|
||||
|
||||
(defcustom elpy-django-command "django-admin.py"
|
||||
"Command to use when running Django specific commands.
|
||||
Best to set it to full path to 'manage.py' if it's available."
|
||||
:type 'string
|
||||
:safe 'stringp
|
||||
:group 'elpy)
|
||||
(make-variable-buffer-local 'elpy-django-command)
|
||||
|
||||
(defcustom elpy-django-server-ipaddr "127.0.0.1"
|
||||
"What address Django will use when running the dev server."
|
||||
:type 'string
|
||||
:safe 'stringp
|
||||
:group 'elpy)
|
||||
(make-variable-buffer-local 'elpy-django-server-ipaddr)
|
||||
|
||||
(defcustom elpy-django-server-port "8000"
|
||||
"What port Django will use when running the dev server."
|
||||
:type 'string
|
||||
:safe 'stringp
|
||||
:group 'elpy)
|
||||
(make-variable-buffer-local 'elpy-django-server-port)
|
||||
|
||||
(defcustom elpy-django-server-command "runserver"
|
||||
"When executing `elpy-django-runserver' what should be the server
|
||||
command to use."
|
||||
:type 'string
|
||||
:safe 'stringp
|
||||
:group 'elpy)
|
||||
(make-variable-buffer-local 'elpy-django-server-command)
|
||||
|
||||
(defcustom elpy-django-always-prompt nil
|
||||
"When non-nil, it will always prompt for extra arguments
|
||||
to pass with the chosen command."
|
||||
:type 'boolean
|
||||
:safe 'booleanp
|
||||
:group 'elpy)
|
||||
(make-variable-buffer-local 'elpy-django-always-prompt)
|
||||
|
||||
(defcustom elpy-django-commands-with-req-arg '("startapp" "startproject"
|
||||
"loaddata" "sqlmigrate"
|
||||
"sqlsequencereset"
|
||||
"squashmigrations")
|
||||
"Used to determine if we should prompt for arguments. Some commands
|
||||
require arguments in order for it to work."
|
||||
:type 'list
|
||||
:safe 'listp
|
||||
:group 'elpy)
|
||||
(make-variable-buffer-local 'elpy-django-commands-with-req-arg)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Key map
|
||||
|
||||
(defvar elpy-django-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "c") 'elpy-django-command)
|
||||
(define-key map (kbd "r") 'elpy-django-runserver)
|
||||
map)
|
||||
"Key map for django extension")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Helper Functions
|
||||
|
||||
(defun elpy-django-setup ()
|
||||
"Decides whether to start the minor mode or not."
|
||||
;; Make sure we're in an actual file and we can find
|
||||
;; manage.py. Otherwise user will have to manually
|
||||
;; start this mode if they're using 'django-admin.py'
|
||||
(when (locate-dominating-file default-directory "manage.py")
|
||||
;; Let's be nice and point to full path of 'manage.py'
|
||||
;; This only affects the buffer if there's no directory
|
||||
;; variable overwriting it.
|
||||
(setq elpy-django-command
|
||||
(concat (locate-dominating-file default-directory "manage.py") "manage.py"))
|
||||
(elpy-django 1)))
|
||||
|
||||
(defun elpy-django--get-commands ()
|
||||
"Return list of django commands."
|
||||
(let ((dj-commands-str nil)
|
||||
(help-output
|
||||
(shell-command-to-string (concat elpy-django-command " -h"))))
|
||||
(setq dj-commands-str
|
||||
(with-temp-buffer
|
||||
(progn
|
||||
(insert help-output)
|
||||
(goto-char (point-min))
|
||||
(delete-region (point) (search-forward "Available subcommands:" nil nil nil))
|
||||
;; cleanup [auth] and stuff
|
||||
(goto-char (point-min))
|
||||
(save-excursion
|
||||
(replace-regexp "\\[.*\\]" ""))
|
||||
(buffer-string))))
|
||||
;; get a list of commands from the output of manage.py -h
|
||||
;; What would be the pattern to optimize this ?
|
||||
(setq dj-commands-str (split-string dj-commands-str "\n"))
|
||||
(setq dj-commands-str (-remove (lambda (x) (string= x "")) dj-commands-str))
|
||||
(setq dj-commands-str (mapcar (lambda (x) (s-trim x)) dj-commands-str))
|
||||
(sort dj-commands-str 'string-lessp)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; User Functions
|
||||
|
||||
(defun elpy-django-command (cmd)
|
||||
"Prompt user for Django command. If called with `C-u',
|
||||
it will prompt for other flags/arguments to run."
|
||||
(interactive (list (completing-read "Command: " (elpy-django--get-commands) nil nil)))
|
||||
;; Called with C-u, variable is set or is a cmd that requires an argument
|
||||
(when (or current-prefix-arg
|
||||
elpy-django-always-prompt
|
||||
(member cmd elpy-django-commands-with-req-arg))
|
||||
(setq cmd (concat cmd " " (read-shell-command (concat cmd ": ") "--noinput"))))
|
||||
(compile (concat elpy-django-command " " cmd)))
|
||||
|
||||
(defun elpy-django-runserver (arg)
|
||||
"Start the server and automatically add the ipaddr and port.
|
||||
Also create it's own special buffer so that we can have multiple
|
||||
servers running per project.
|
||||
|
||||
When called with a prefix (C-u), it will prompt for additional args."
|
||||
(interactive "P")
|
||||
(let* ((cmd (concat elpy-django-command " " elpy-django-server-command))
|
||||
(proj-root (file-name-base (directory-file-name (elpy-project-root))))
|
||||
(buff-name (format "*runserver[%s]*" proj-root)))
|
||||
;; Kill any previous instance of runserver since we might be doing something new
|
||||
(when (get-buffer buff-name)
|
||||
(kill-buffer buff-name))
|
||||
(setq cmd (concat cmd " " elpy-django-server-ipaddr ":" elpy-django-server-port))
|
||||
(when (or arg elpy-django-always-prompt)
|
||||
(setq cmd (concat cmd " "(read-shell-command (concat cmd ": ")))))
|
||||
(compile cmd)
|
||||
(with-current-buffer "*compilation*"
|
||||
(rename-buffer buff-name))))
|
||||
|
||||
(define-minor-mode elpy-django
|
||||
"Minor mode to for Django commands."
|
||||
:group 'elpy)
|
||||
|
||||
(provide 'elpy-django)
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; elpy-django.el ends here
|
||||
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-django.elc
Normal file
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-django.elc
Normal file
Binary file not shown.
11
.emacs.d/elpa/elpy-20171206.847/elpy-pkg.el
Normal file
11
.emacs.d/elpa/elpy-20171206.847/elpy-pkg.el
Normal file
@@ -0,0 +1,11 @@
|
||||
(define-package "elpy" "20171206.847" "Emacs Python Development Environment"
|
||||
'((company "0.9.2")
|
||||
(emacs "24.4")
|
||||
(find-file-in-project "3.3")
|
||||
(highlight-indentation "0.5.0")
|
||||
(pyvenv "1.3")
|
||||
(yasnippet "0.8.0")
|
||||
(s "1.11.0")))
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
111
.emacs.d/elpa/elpy-20171206.847/elpy-profile.el
Normal file
111
.emacs.d/elpa/elpy-20171206.847/elpy-profile.el
Normal file
@@ -0,0 +1,111 @@
|
||||
;;; elpy-profile.el --- Profiling capabilitiss for elpy
|
||||
|
||||
;; Copyright (C) 2013-2016 Jorgen Schaefer
|
||||
|
||||
;; Author: Gaby Launay <gaby.launay@tutanota.com>
|
||||
;; URL: https://github.com/jorgenschaefer/elpy
|
||||
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License
|
||||
;; as published by the Free Software Foundation; either version 3
|
||||
;; of the License, or (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file serves as an extension to elpy by adding profiling capabilities
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; User customization
|
||||
|
||||
(defcustom elpy-profile-visualizer "snakeviz"
|
||||
"Visualizer for elpy profile results."
|
||||
:type 'str
|
||||
:group 'elpy)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Helper Functions
|
||||
|
||||
(defun elpy-profile--display-profiling (file)
|
||||
"Display the profile result FILE using `elpy-profile-visualizer'."
|
||||
(let ((exec (car (split-string elpy-profile-visualizer " " t)))
|
||||
(args (append (cdr (split-string elpy-profile-visualizer " " t)) (list file))))
|
||||
(if (executable-find exec)
|
||||
(apply 'call-process exec nil 0 nil args)
|
||||
(message "Elpy profile visualizer '%s' not found" exec))))
|
||||
|
||||
(defun elpy-profile--sentinel (process string)
|
||||
"Elpy profile sentinel."
|
||||
(let ((filename (file-name-nondirectory (process-get process 'file)))
|
||||
(prof-file (process-get process 'prof-file))
|
||||
(dont-display (process-get process 'dont-display)))
|
||||
(with-current-buffer "*elpy-profile-log*"
|
||||
(view-mode))
|
||||
(if (not (string-equal string "finished\n"))
|
||||
(progn
|
||||
(message "[%s] Profiling failed" filename)
|
||||
(display-buffer "*elpy-profile-log*"))
|
||||
(message "[%s] Profiling succeeded" filename)
|
||||
(when (not dont-display)
|
||||
(elpy-profile--display-profiling prof-file)))))
|
||||
|
||||
(defun elpy-profile--file (file &optional in-dir dont-display)
|
||||
"Profile asynchronously FILE and display the result using
|
||||
`elpy-profile-visualizer'.
|
||||
|
||||
If IN-DIR is non nil, profile result is saved in the same
|
||||
directory as the script.
|
||||
If DONT-DISPLAY is non nil, don't display the profile results."
|
||||
(ignore-errors (kill-buffer "*elpy-profile-log*"))
|
||||
(let* ((prof-file (if in-dir
|
||||
(concat (file-name-sans-extension file) ".profile")
|
||||
(concat (make-temp-file "elpy-profile-" nil ".profile"))))
|
||||
(proc-name (format "elpy-profile-%s" file))
|
||||
(proc-cmd (list python-shell-interpreter "-m" "cProfile" "-o" prof-file file))
|
||||
(proc (make-process :name proc-name
|
||||
:buffer "*elpy-profile-log*"
|
||||
:sentinel 'elpy-profile--sentinel
|
||||
:command proc-cmd)))
|
||||
(message "[%s] Profiling ..." (file-name-nondirectory file))
|
||||
(process-put proc 'prof-file prof-file)
|
||||
(process-put proc 'file file)
|
||||
(process-put proc 'dont-display dont-display)
|
||||
prof-file))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; User Functions
|
||||
|
||||
(defun elpy-profile-buffer-or-region (&optional in-dir dont-display)
|
||||
"Profile asynchronously the active region or the current buffer
|
||||
and display the result using `elpy-profile-visualizer'.
|
||||
|
||||
If IN-DIR is non nil, profile result is saved in the same
|
||||
directory as the script.
|
||||
If DONT-DISPLAY is non nil, don't display the profile results."
|
||||
(interactive "P")
|
||||
(let* ((file-name (buffer-name))
|
||||
(file-dir (file-name-directory (buffer-file-name)))
|
||||
(beg (if (region-active-p) (region-beginning) (point-min)))
|
||||
(end (if (region-active-p) (region-end) (point-max)))
|
||||
(tmp-file-prefix (if (region-active-p) "_region_" ""))
|
||||
(tmp-file (if in-dir
|
||||
(concat file-dir "/" tmp-file-prefix file-name)
|
||||
(concat (make-temp-file "elpy-profile-" t) "/" tmp-file-prefix file-name)))
|
||||
(region (elpy-shell--region-without-indentation beg end)))
|
||||
(with-temp-buffer
|
||||
(insert region)
|
||||
(write-region (point-min) (point-max) tmp-file nil t))
|
||||
(elpy-profile--file tmp-file t dont-display)))
|
||||
|
||||
(provide 'elpy-profile)
|
||||
;;; elpy-profile.el ends here
|
||||
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-profile.elc
Normal file
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-profile.elc
Normal file
Binary file not shown.
297
.emacs.d/elpa/elpy-20171206.847/elpy-refactor.el
Normal file
297
.emacs.d/elpa/elpy-20171206.847/elpy-refactor.el
Normal file
@@ -0,0 +1,297 @@
|
||||
;;; elpy-refactor.el --- Refactoring mode for Elpy
|
||||
|
||||
;; Copyright (C) 2013-2016 Jorgen Schaefer
|
||||
|
||||
;; Author: Jorgen Schaefer <contact@jorgenschaefer.de>
|
||||
;; URL: https://github.com/jorgenschaefer/elpy
|
||||
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License
|
||||
;; as published by the Free Software Foundation; either version 3
|
||||
;; of the License, or (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides an interface, including a major mode, to use
|
||||
;; refactoring options provided by the Rope library.
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; We require elpy, but elpy loads us, so we shouldn't load it back.
|
||||
;; (require 'elpy)
|
||||
|
||||
(defvar elpy-refactor-changes nil
|
||||
"Changes that will be commited on \\[elpy-refactor-commit].")
|
||||
(make-variable-buffer-local 'elpy-refactor-current-changes)
|
||||
|
||||
(defvar elpy-refactor-window-configuration nil
|
||||
"The old window configuration. Will be restored after commit.")
|
||||
(make-variable-buffer-local 'elpy-refactor-window-configuration)
|
||||
|
||||
(make-obsolete
|
||||
'elpy-refactor
|
||||
"Refactoring has been unstable and flakey, support will be dropped in the future."
|
||||
"elpy 1.5.0")
|
||||
(defun elpy-refactor ()
|
||||
"Run the Elpy refactoring interface for Python code."
|
||||
(interactive)
|
||||
(save-some-buffers)
|
||||
(let* ((selection (elpy-refactor-select
|
||||
(elpy-refactor-rpc-get-options)))
|
||||
(method (car selection))
|
||||
(args (cdr selection)))
|
||||
(when method
|
||||
(elpy-refactor-create-change-buffer
|
||||
(elpy-refactor-rpc-get-changes method args)))))
|
||||
|
||||
(defun elpy-refactor-select (options)
|
||||
"Show the user the refactoring options and let her choose one.
|
||||
|
||||
Depending on the chosen option, ask the user for further
|
||||
arguments and build the argument.
|
||||
|
||||
Return a cons cell of the name of the option and the arg list
|
||||
created."
|
||||
(let ((buf (get-buffer-create "*Elpy Refactor*"))
|
||||
(pos (vector (1- (point))
|
||||
(ignore-errors
|
||||
(1- (region-beginning)))
|
||||
(ignore-errors
|
||||
(1- (region-end)))))
|
||||
(inhibit-read-only t)
|
||||
(options (sort options
|
||||
(lambda (a b)
|
||||
(let ((cata (cdr (assq 'category a)))
|
||||
(catb (cdr (assq 'category b))))
|
||||
(if (equal cata catb)
|
||||
(string< (cdr (assq 'description a))
|
||||
(cdr (assq 'description b)))
|
||||
(string< cata catb))))))
|
||||
(key ?a)
|
||||
last-category
|
||||
option-alist)
|
||||
(with-current-buffer buf
|
||||
(erase-buffer)
|
||||
(dolist (option options)
|
||||
(let ((category (cdr (assq 'category option)))
|
||||
(description (cdr (assq 'description option)))
|
||||
(name (cdr (assq 'name option)))
|
||||
(args (cdr (assq 'args option))))
|
||||
(when (not (equal category last-category))
|
||||
(when last-category
|
||||
(insert "\n"))
|
||||
(insert (propertize category 'face 'bold) "\n")
|
||||
(setq last-category category))
|
||||
(insert " (" key ") " description "\n")
|
||||
(setq option-alist (cons (list key name args)
|
||||
option-alist))
|
||||
(setq key (1+ key))))
|
||||
(let ((window-conf (current-window-configuration)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(with-selected-window (display-buffer buf)
|
||||
(goto-char (point-min)))
|
||||
(fit-window-to-buffer (get-buffer-window buf))
|
||||
(let* ((key (read-key "Refactoring action? "))
|
||||
(entry (cdr (assoc key option-alist))))
|
||||
(kill-buffer buf)
|
||||
(cons (car entry) ; name
|
||||
(elpy-refactor-build-arguments (cadr entry)
|
||||
pos))))
|
||||
(set-window-configuration window-conf))))))
|
||||
|
||||
(defun elpy-refactor-build-arguments (args pos)
|
||||
"Translate an argument list specification to an argument list.
|
||||
|
||||
POS is a vector of three elements, the current offset, the offset
|
||||
of the beginning of the region, and the offset of the end of the
|
||||
region.
|
||||
|
||||
ARGS is a list of triples, each triple containing the name of an
|
||||
argument (ignored), the type of the argument, and a possible
|
||||
prompt string.
|
||||
|
||||
Available types:
|
||||
|
||||
offset - The offset in the buffer, (1- (point))
|
||||
start_offset - Offset of the beginning of the region
|
||||
end_offset - Offset of the end of the region
|
||||
string - A free-form string
|
||||
filename - A non-existing file name
|
||||
directory - An existing directory name
|
||||
boolean - A boolean question"
|
||||
(mapcar (lambda (arg)
|
||||
(let ((type (cadr arg))
|
||||
(prompt (caddr arg)))
|
||||
(cond
|
||||
((equal type "offset")
|
||||
(aref pos 0))
|
||||
((equal type "start_offset")
|
||||
(aref pos 1))
|
||||
((equal type "end_offset")
|
||||
(aref pos 2))
|
||||
((equal type "string")
|
||||
(read-from-minibuffer prompt))
|
||||
((equal type "filename")
|
||||
(expand-file-name
|
||||
(read-file-name prompt)))
|
||||
((equal type "directory")
|
||||
(expand-file-name
|
||||
(read-directory-name prompt)))
|
||||
((equal type "boolean")
|
||||
(y-or-n-p prompt)))))
|
||||
args))
|
||||
|
||||
(defun elpy-refactor-create-change-buffer (changes)
|
||||
"Show the user a buffer of changes.
|
||||
|
||||
The user can review the changes and confirm them with
|
||||
\\[elpy-refactor-commit]."
|
||||
(when (not changes)
|
||||
(error "No changes for this refactoring action."))
|
||||
(with-current-buffer (get-buffer-create "*Elpy Refactor*")
|
||||
(elpy-refactor-mode)
|
||||
(setq elpy-refactor-changes changes
|
||||
elpy-refactor-window-configuration (current-window-configuration))
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(elpy-refactor-insert-changes changes))
|
||||
(select-window (display-buffer (current-buffer)))
|
||||
(goto-char (point-min))))
|
||||
|
||||
(defun elpy-refactor-insert-changes (changes)
|
||||
"Format and display the changes described in CHANGES."
|
||||
(insert (propertize "Use C-c C-c to apply the following changes."
|
||||
'face 'bold)
|
||||
"\n\n")
|
||||
(dolist (change changes)
|
||||
(let ((action (cdr (assq 'action change))))
|
||||
(cond
|
||||
((equal action "change")
|
||||
(insert (cdr (assq 'diff change))
|
||||
"\n"))
|
||||
((equal action "create")
|
||||
(let ((type (cdr (assq 'type change))))
|
||||
(if (equal type "file")
|
||||
(insert "+++ " (cdr (assq 'file change)) "\n"
|
||||
"Create file " (cdr (assq 'file change)) "\n"
|
||||
"\n")
|
||||
(insert "+++ " (cdr (assq 'path change)) "\n"
|
||||
"Create directory " (cdr (assq 'path change)) "\n"
|
||||
"\n"))))
|
||||
((equal action "move")
|
||||
(insert "--- " (cdr (assq 'source change)) "\n"
|
||||
"+++ " (cdr (assq 'destination change)) "\n"
|
||||
"Rename " (cdr (assq 'type change)) "\n"
|
||||
"\n"))
|
||||
((equal action "delete")
|
||||
(let ((type (cdr (assq 'type change))))
|
||||
(if (equal type "file")
|
||||
(insert "--- " (cdr (assq 'file change)) "\n"
|
||||
"Delete file " (cdr (assq 'file change)) "\n"
|
||||
"\n")
|
||||
(insert "--- " (cdr (assq 'path change)) "\n"
|
||||
"Delete directory " (cdr (assq 'path change)) "\n"
|
||||
"\n"))))))))
|
||||
|
||||
(defvar elpy-refactor-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-c C-c") 'elpy-refactor-commit)
|
||||
(define-key map (kbd "q") 'bury-buffer)
|
||||
(define-key map (kbd "h") 'describe-mode)
|
||||
(define-key map (kbd "?") 'describe-mode)
|
||||
map)
|
||||
"The key map for `elpy-refactor-mode'.")
|
||||
|
||||
(define-derived-mode elpy-refactor-mode diff-mode "Elpy Refactor"
|
||||
"Mode to display refactoring actions and ask confirmation from the user.
|
||||
|
||||
\\{elpy-refactor-mode-map}"
|
||||
:group 'elpy
|
||||
(view-mode 1))
|
||||
|
||||
(defun elpy-refactor-commit ()
|
||||
"Commit the changes in the current buffer."
|
||||
(interactive)
|
||||
(when (not elpy-refactor-changes)
|
||||
(error "No changes to commit."))
|
||||
;; Restore the window configuration as the first thing so that
|
||||
;; changes below are visible to the user. Especially the point
|
||||
;; change in possible buffer changes.
|
||||
(set-window-configuration elpy-refactor-window-configuration)
|
||||
(dolist (change elpy-refactor-changes)
|
||||
(let ((action (cdr (assq 'action change))))
|
||||
(cond
|
||||
((equal action "change")
|
||||
(with-current-buffer (find-file-noselect (cdr (assq 'file change)))
|
||||
;; This would break for save-excursion as the buffer is
|
||||
;; truncated, so all markets now point to position 1.
|
||||
(let ((old-point (point)))
|
||||
(undo-boundary)
|
||||
(erase-buffer)
|
||||
(insert (cdr (assq 'contents change)))
|
||||
(undo-boundary)
|
||||
(goto-char old-point))))
|
||||
((equal action "create")
|
||||
(if (equal (cdr (assq 'type change))
|
||||
"file")
|
||||
(find-file-noselect (cdr (assq 'file change)))
|
||||
(make-directory (cdr (assq 'path change)))))
|
||||
((equal action "move")
|
||||
(let* ((source (cdr (assq 'source change)))
|
||||
(dest (cdr (assq 'destination change)))
|
||||
(buf (get-file-buffer source)))
|
||||
(when buf
|
||||
(with-current-buffer buf
|
||||
(setq buffer-file-name dest)
|
||||
(rename-buffer (file-name-nondirectory dest) t)))
|
||||
(rename-file source dest)))
|
||||
((equal action "delete")
|
||||
(if (equal (cdr (assq 'type change)) "file")
|
||||
(let ((name (cdr (assq 'file change))))
|
||||
(when (y-or-n-p (format "Really delete %s? " name))
|
||||
(delete-file name t)))
|
||||
(let ((name (cdr (assq 'directory change))))
|
||||
(when (y-or-n-p (format "Really delete %s? " name))
|
||||
(delete-directory name nil t))))))))
|
||||
(kill-buffer (current-buffer)))
|
||||
|
||||
(defun elpy-refactor-rpc-get-options ()
|
||||
"Get a list of refactoring options from the Elpy RPC."
|
||||
(if (use-region-p)
|
||||
(elpy-rpc "get_refactor_options"
|
||||
(list (buffer-file-name)
|
||||
(1- (region-beginning))
|
||||
(1- (region-end))))
|
||||
(elpy-rpc "get_refactor_options"
|
||||
(list (buffer-file-name)
|
||||
(1- (point))))))
|
||||
|
||||
(defun elpy-refactor-rpc-get-changes (method args)
|
||||
"Get a list of changes from the Elpy RPC after applying METHOD with ARGS."
|
||||
(elpy-rpc "refactor"
|
||||
(list (buffer-file-name)
|
||||
method args)))
|
||||
|
||||
(defun elpy-refactor-options (option)
|
||||
"Show available refactor options and let user choose one."
|
||||
(interactive "c[i]: importmagic-fixup [p]: autopep8-fix-code [r]: refactor")
|
||||
(let ((choice (char-to-string option)))
|
||||
(cond
|
||||
((string-equal choice "i")
|
||||
(elpy-importmagic-fixup))
|
||||
((string-equal choice "p")
|
||||
(elpy-autopep8-fix-code))
|
||||
((string-equal choice "r")
|
||||
(elpy-refactor)))))
|
||||
|
||||
(provide 'elpy-refactor)
|
||||
;;; elpy-refactor.el ends here
|
||||
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-refactor.elc
Normal file
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-refactor.elc
Normal file
Binary file not shown.
1083
.emacs.d/elpa/elpy-20171206.847/elpy-shell.el
Normal file
1083
.emacs.d/elpa/elpy-20171206.847/elpy-shell.el
Normal file
File diff suppressed because it is too large
Load Diff
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-shell.elc
Normal file
BIN
.emacs.d/elpa/elpy-20171206.847/elpy-shell.elc
Normal file
Binary file not shown.
4004
.emacs.d/elpa/elpy-20171206.847/elpy.el
Normal file
4004
.emacs.d/elpa/elpy-20171206.847/elpy.el
Normal file
File diff suppressed because it is too large
Load Diff
BIN
.emacs.d/elpa/elpy-20171206.847/elpy.elc
Normal file
BIN
.emacs.d/elpa/elpy-20171206.847/elpy.elc
Normal file
Binary file not shown.
41
.emacs.d/elpa/elpy-20171206.847/elpy/__init__.py
Normal file
41
.emacs.d/elpa/elpy-20171206.847/elpy/__init__.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# Elpy, the Emacs Lisp Python Environment
|
||||
|
||||
# Copyright (C) 2013-2016 Jorgen Schaefer
|
||||
|
||||
# Author: Jorgen Schaefer <contact@jorgenschaefer.de>
|
||||
# URL: http://github.com/jorgenschaefer/elpy
|
||||
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 3
|
||||
# of the License, or (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""The Emacs Lisp Python Environment.
|
||||
|
||||
Elpy is a mode for Emacs to support writing Python code. This package
|
||||
provides the backend within Python to support auto-completion,
|
||||
documentation extraction, and navigation.
|
||||
|
||||
Emacs will start the protocol by running the module itself, like so:
|
||||
|
||||
python -m elpy
|
||||
|
||||
This will emit a greeting string on a single line, and then wait for
|
||||
the protocol to start. Details of the protocol can be found in
|
||||
elpy.rpc.
|
||||
|
||||
This package is unlikely to be useful on its own.
|
||||
|
||||
"""
|
||||
|
||||
__author__ = "Jorgen Schaefer"
|
||||
__version__ = "1.17.0"
|
||||
__license__ = "GPL"
|
||||
25
.emacs.d/elpa/elpy-20171206.847/elpy/__main__.py
Normal file
25
.emacs.d/elpa/elpy-20171206.847/elpy/__main__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""Main interface to the RPC server.
|
||||
|
||||
You should be able to just run the following to use this module:
|
||||
|
||||
python -m elpy
|
||||
|
||||
The first line should be "elpy-rpc ready". If it isn't, something
|
||||
broke.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import elpy
|
||||
from elpy.server import ElpyRPCServer
|
||||
|
||||
if __name__ == '__main__':
|
||||
stdin = sys.stdin
|
||||
stdout = sys.stdout
|
||||
sys.stdout = sys.stderr = open(os.devnull, "w")
|
||||
stdout.write('elpy-rpc ready ({0})\n'
|
||||
.format(elpy.__version__))
|
||||
stdout.flush()
|
||||
ElpyRPCServer(stdin, stdout).serve_forever()
|
||||
Binary file not shown.
21
.emacs.d/elpa/elpy-20171206.847/elpy/auto_pep8.py
Normal file
21
.emacs.d/elpa/elpy-20171206.847/elpy/auto_pep8.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""Glue for the "autopep8" library.
|
||||
|
||||
"""
|
||||
|
||||
from elpy.rpc import Fault
|
||||
|
||||
|
||||
try:
|
||||
import autopep8
|
||||
except ImportError: # pragma: no cover
|
||||
autopep8 = None
|
||||
|
||||
|
||||
def fix_code(code):
|
||||
"""Formats Python code to conform to the PEP 8 style guide.
|
||||
|
||||
"""
|
||||
if not autopep8:
|
||||
raise Fault('autopep8 not installed, cannot fix code.',
|
||||
code=400)
|
||||
return autopep8.fix_code(code, apply_config=True)
|
||||
33
.emacs.d/elpa/elpy-20171206.847/elpy/compat.py
Normal file
33
.emacs.d/elpa/elpy-20171206.847/elpy/compat.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""Python 2/3 compatibility definitions.
|
||||
|
||||
These are used by the rest of Elpy to keep compatibility definitions
|
||||
in one place.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
PYTHON3 = True
|
||||
|
||||
from io import StringIO
|
||||
|
||||
def ensure_not_unicode(obj):
|
||||
return obj
|
||||
else:
|
||||
PYTHON3 = False
|
||||
|
||||
from StringIO import StringIO # noqa
|
||||
|
||||
def ensure_not_unicode(obj):
|
||||
"""Return obj. If it's a unicode string, convert it to str first.
|
||||
|
||||
Pydoc functions simply don't find anything for unicode
|
||||
strings. No idea why.
|
||||
|
||||
"""
|
||||
if isinstance(obj, unicode):
|
||||
return obj.encode("utf-8")
|
||||
else:
|
||||
return obj
|
||||
118
.emacs.d/elpa/elpy-20171206.847/elpy/impmagic.py
Normal file
118
.emacs.d/elpa/elpy-20171206.847/elpy/impmagic.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""Glue for the "importmagic" library.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
|
||||
|
||||
try:
|
||||
import importmagic.index
|
||||
import importmagic.symbols
|
||||
import importmagic.importer
|
||||
except ImportError: # pragma: no cover
|
||||
importmagic = None
|
||||
|
||||
|
||||
class ImportMagicError(Exception):
|
||||
"""Used to pass defined errors from importmagic to the RPC layer."""
|
||||
|
||||
|
||||
class ImportMagic(object):
|
||||
|
||||
def __init__(self):
|
||||
self.is_enabled = bool(importmagic)
|
||||
# fail_message is reported to the user when symbol_index
|
||||
# is (still) None
|
||||
self.fail_message = "symbol index is not yet ready"
|
||||
self.project_root = None
|
||||
self.symbol_index = None
|
||||
self.favorites = set()
|
||||
self._thread = None
|
||||
|
||||
def _build_symbol_index(self, project_root, custom_path, blacklist_re):
|
||||
try:
|
||||
index = importmagic.index.SymbolIndex(blacklist_re=blacklist_re)
|
||||
if os.environ.get('ELPY_TEST'):
|
||||
# test suite support: do not index the whole PYTHONPATH, it
|
||||
# takes much too long
|
||||
index.build_index([])
|
||||
elif custom_path:
|
||||
index.build_index(custom_path)
|
||||
else:
|
||||
index.build_index([project_root] + sys.path)
|
||||
except Exception as e:
|
||||
self.fail_message = "symbol index failed to build: %s" % e
|
||||
else:
|
||||
self.symbol_index = index
|
||||
|
||||
def build_index(self, project_root, custom_path=None, blacklist_re=None):
|
||||
self.project_root = None
|
||||
self._thread = threading.Thread(target=self._build_symbol_index,
|
||||
args=(project_root, custom_path,
|
||||
blacklist_re))
|
||||
self._thread.setDaemon(True)
|
||||
self._thread.start()
|
||||
|
||||
def get_import_symbols(self, symbol):
|
||||
scores = self.symbol_index.symbol_scores(symbol)
|
||||
|
||||
def sort_key(item):
|
||||
score, mod, var = item
|
||||
if mod in self.favorites:
|
||||
return 2 + score, mod, var
|
||||
return score, mod, var
|
||||
|
||||
scores.sort(key=sort_key, reverse=True)
|
||||
return ["from %s import %s" % (mod, var) if var else "import %s" % mod
|
||||
for (_, mod, var) in scores]
|
||||
|
||||
def add_import(self, source, statement):
|
||||
imports = importmagic.importer.Imports(self.symbol_index, source)
|
||||
if statement.startswith('import '):
|
||||
sepalias = None
|
||||
alias = None
|
||||
if ' as ' in statement:
|
||||
sepalias = statement.find(' as ')
|
||||
alias = statement[sepalias+4:]
|
||||
modname = statement[7:sepalias]
|
||||
imports.add_import(modname, alias)
|
||||
self.favorites.add(modname)
|
||||
else:
|
||||
sep = statement.find(' import ')
|
||||
sepalias = None
|
||||
alias = None
|
||||
if ' as ' in statement:
|
||||
sepalias = statement.find(' as ')
|
||||
alias = statement[sepalias+4:]
|
||||
modname = statement[5:sep]
|
||||
name = statement[sep+8:sepalias]
|
||||
if sep > -1:
|
||||
self.favorites.add(modname)
|
||||
imports.add_import_from(modname, name, alias)
|
||||
start_line, end_line, import_block = imports.get_update()
|
||||
return start_line, end_line, import_block
|
||||
|
||||
def get_unresolved_symbols(self, source):
|
||||
try:
|
||||
scope = importmagic.symbols.Scope.from_source(source)
|
||||
except SyntaxError:
|
||||
raise ImportMagicError('cannot find unresolved names in '
|
||||
'incomplete file')
|
||||
unres, unref = scope.find_unresolved_and_unreferenced_symbols()
|
||||
return list(unres)
|
||||
|
||||
def remove_unreferenced_imports(self, source):
|
||||
try:
|
||||
scope = importmagic.symbols.Scope.from_source(source)
|
||||
except SyntaxError:
|
||||
raise ImportMagicError('cannot find unreferenced imports in '
|
||||
'incomplete file')
|
||||
unres, unref = scope.find_unresolved_and_unreferenced_symbols()
|
||||
# Note: we do not supply "unres" to the call below, since we do
|
||||
# not want to add imports without querying the user from which
|
||||
# module symbols should be imported.
|
||||
start_line, end_line, import_block = importmagic.importer.get_update(
|
||||
source, self.symbol_index, set(), unref)
|
||||
return start_line, end_line, import_block
|
||||
397
.emacs.d/elpa/elpy-20171206.847/elpy/jedibackend.py
Normal file
397
.emacs.d/elpa/elpy-20171206.847/elpy/jedibackend.py
Normal file
@@ -0,0 +1,397 @@
|
||||
"""Elpy backend using the Jedi library.
|
||||
|
||||
This backend uses the Jedi library:
|
||||
|
||||
https://github.com/davidhalter/jedi
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import jedi
|
||||
|
||||
from elpy import rpc
|
||||
|
||||
|
||||
class JediBackend(object):
|
||||
"""The Jedi backend class.
|
||||
|
||||
Implements the RPC calls we can pass on to Jedi.
|
||||
|
||||
Documentation: http://jedi.jedidjah.ch/en/latest/docs/plugin-api.html
|
||||
|
||||
"""
|
||||
name = "jedi"
|
||||
|
||||
def __init__(self, project_root):
|
||||
self.project_root = project_root
|
||||
self.completions = {}
|
||||
sys.path.append(project_root)
|
||||
|
||||
def rpc_get_completions(self, filename, source, offset):
|
||||
line, column = pos_to_linecol(source, offset)
|
||||
proposals = run_with_debug(jedi, 'completions',
|
||||
source=source, line=line, column=column,
|
||||
path=filename, encoding='utf-8')
|
||||
if proposals is None:
|
||||
return []
|
||||
self.completions = dict((proposal.name, proposal)
|
||||
for proposal in proposals)
|
||||
return [{'name': proposal.name.rstrip("="),
|
||||
'suffix': proposal.complete.rstrip("="),
|
||||
'annotation': proposal.type,
|
||||
'meta': proposal.description}
|
||||
for proposal in proposals]
|
||||
|
||||
def rpc_get_completion_docstring(self, completion):
|
||||
proposal = self.completions.get(completion)
|
||||
if proposal is None:
|
||||
return None
|
||||
else:
|
||||
return proposal.docstring(fast=False)
|
||||
|
||||
def rpc_get_completion_location(self, completion):
|
||||
proposal = self.completions.get(completion)
|
||||
if proposal is None:
|
||||
return None
|
||||
else:
|
||||
return (proposal.module_path, proposal.line)
|
||||
|
||||
def rpc_get_docstring(self, filename, source, offset):
|
||||
line, column = pos_to_linecol(source, offset)
|
||||
locations = run_with_debug(jedi, 'goto_definitions',
|
||||
source=source, line=line, column=column,
|
||||
path=filename, encoding='utf-8')
|
||||
if locations and locations[-1].docstring():
|
||||
return ('Documentation for {0}:\n\n'.format(
|
||||
locations[-1].full_name) + locations[-1].docstring())
|
||||
else:
|
||||
return None
|
||||
|
||||
def rpc_get_definition(self, filename, source, offset):
|
||||
line, column = pos_to_linecol(source, offset)
|
||||
locations = run_with_debug(jedi, 'goto_definitions',
|
||||
source=source, line=line, column=column,
|
||||
path=filename, encoding='utf-8')
|
||||
# goto_definitions() can return silly stuff like __builtin__
|
||||
# for int variables, so we fall back on goto() in those
|
||||
# cases. See issue #76.
|
||||
if (
|
||||
locations and
|
||||
locations[0].module_path is None
|
||||
):
|
||||
locations = run_with_debug(jedi, 'goto_assignments',
|
||||
source=source, line=line,
|
||||
column=column,
|
||||
path=filename, encoding='utf-8')
|
||||
if not locations:
|
||||
return None
|
||||
else:
|
||||
loc = locations[-1]
|
||||
try:
|
||||
if loc.module_path:
|
||||
if loc.module_path == filename:
|
||||
offset = linecol_to_pos(source,
|
||||
loc.line,
|
||||
loc.column)
|
||||
else:
|
||||
with open(loc.module_path) as f:
|
||||
offset = linecol_to_pos(f.read(),
|
||||
loc.line,
|
||||
loc.column)
|
||||
else:
|
||||
return None
|
||||
except IOError:
|
||||
return None
|
||||
return (loc.module_path, offset)
|
||||
|
||||
def rpc_get_assignment(self, filename, source, offset):
|
||||
line, column = pos_to_linecol(source, offset)
|
||||
locations = run_with_debug(jedi, 'goto_assignments',
|
||||
source=source, line=line, column=column,
|
||||
path=filename, encoding='utf-8')
|
||||
if not locations:
|
||||
return None
|
||||
else:
|
||||
loc = locations[-1]
|
||||
try:
|
||||
if loc.module_path:
|
||||
if loc.module_path == filename:
|
||||
offset = linecol_to_pos(source,
|
||||
loc.line,
|
||||
loc.column)
|
||||
else:
|
||||
with open(loc.module_path) as f:
|
||||
offset = linecol_to_pos(f.read(),
|
||||
loc.line,
|
||||
loc.column)
|
||||
else:
|
||||
return None
|
||||
except IOError:
|
||||
return None
|
||||
return (loc.module_path, offset)
|
||||
|
||||
def rpc_get_calltip(self, filename, source, offset):
|
||||
line, column = pos_to_linecol(source, offset)
|
||||
calls = run_with_debug(jedi, 'call_signatures',
|
||||
source=source, line=line, column=column,
|
||||
path=filename, encoding='utf-8')
|
||||
if calls:
|
||||
call = calls[0]
|
||||
else:
|
||||
call = None
|
||||
if not call:
|
||||
return None
|
||||
try:
|
||||
call.index
|
||||
except AttributeError as e:
|
||||
if "get_definition" in str(e):
|
||||
# Bug #627 / jedi#573
|
||||
return None
|
||||
elif "get_subscope_by_name" in str(e):
|
||||
# Bug #677 / jedi#628
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
return {"name": call.name,
|
||||
"index": call.index,
|
||||
"params": [param.description for param in call.params]}
|
||||
|
||||
def rpc_get_usages(self, filename, source, offset):
|
||||
"""Return the uses of the symbol at offset.
|
||||
|
||||
Returns a list of occurrences of the symbol, as dicts with the
|
||||
fields name, filename, and offset.
|
||||
|
||||
"""
|
||||
line, column = pos_to_linecol(source, offset)
|
||||
uses = run_with_debug(jedi, 'usages',
|
||||
source=source, line=line, column=column,
|
||||
path=filename, encoding='utf-8')
|
||||
if uses is None:
|
||||
return None
|
||||
result = []
|
||||
for use in uses:
|
||||
if use.module_path == filename:
|
||||
offset = linecol_to_pos(source, use.line, use.column)
|
||||
elif use.module_path is not None:
|
||||
with open(use.module_path) as f:
|
||||
text = f.read()
|
||||
offset = linecol_to_pos(text, use.line, use.column)
|
||||
|
||||
result.append({"name": use.name,
|
||||
"filename": use.module_path,
|
||||
"offset": offset})
|
||||
|
||||
return result
|
||||
|
||||
def rpc_get_names(self, filename, source, offset):
|
||||
"""Return the list of possible names"""
|
||||
# Remove form feed characters, they confuse Jedi (jedi#424)
|
||||
source = source.replace("\f", " ")
|
||||
names = jedi.api.names(source=source,
|
||||
path=filename, encoding='utf-8',
|
||||
all_scopes=True,
|
||||
definitions=True,
|
||||
references=True)
|
||||
|
||||
result = []
|
||||
for name in names:
|
||||
if name.module_path == filename:
|
||||
offset = linecol_to_pos(source, name.line, name.column)
|
||||
elif name.module_path is not None:
|
||||
with open(name.module_path) as f:
|
||||
text = f.read()
|
||||
offset = linecol_to_pos(text, name.line, name.column)
|
||||
result.append({"name": name.name,
|
||||
"filename": name.module_path,
|
||||
"offset": offset})
|
||||
return result
|
||||
|
||||
|
||||
# From the Jedi documentation:
|
||||
#
|
||||
# line is the current line you want to perform actions on (starting
|
||||
# with line #1 as the first line). column represents the current
|
||||
# column/indent of the cursor (starting with zero). source_path
|
||||
# should be the path of your file in the file system.
|
||||
|
||||
def pos_to_linecol(text, pos):
|
||||
"""Return a tuple of line and column for offset pos in text.
|
||||
|
||||
Lines are one-based, columns zero-based.
|
||||
|
||||
This is how Jedi wants it. Don't ask me why.
|
||||
|
||||
"""
|
||||
line_start = text.rfind("\n", 0, pos) + 1
|
||||
line = text.count("\n", 0, line_start) + 1
|
||||
col = pos - line_start
|
||||
return line, col
|
||||
|
||||
|
||||
def linecol_to_pos(text, line, col):
|
||||
"""Return the offset of this line and column in text.
|
||||
|
||||
Lines are one-based, columns zero-based.
|
||||
|
||||
This is how Jedi wants it. Don't ask me why.
|
||||
|
||||
"""
|
||||
nth_newline_offset = 0
|
||||
for i in range(line - 1):
|
||||
new_offset = text.find("\n", nth_newline_offset)
|
||||
if new_offset < 0:
|
||||
raise ValueError("Text does not have {0} lines."
|
||||
.format(line))
|
||||
nth_newline_offset = new_offset + 1
|
||||
offset = nth_newline_offset + col
|
||||
if offset > len(text):
|
||||
raise ValueError("Line {0} column {1} is not within the text"
|
||||
.format(line, col))
|
||||
return offset
|
||||
|
||||
|
||||
def run_with_debug(jedi, name, *args, **kwargs):
|
||||
re_raise = kwargs.pop('re_raise', ())
|
||||
# Remove form feed characters, they confuse Jedi (jedi#424)
|
||||
if 'source' in kwargs:
|
||||
kwargs['source'] = kwargs['source'].replace("\f", " ")
|
||||
try:
|
||||
script = jedi.Script(*args, **kwargs)
|
||||
return getattr(script, name)()
|
||||
except Exception as e:
|
||||
if isinstance(e, re_raise):
|
||||
raise
|
||||
# Bug jedi#417
|
||||
if isinstance(e, TypeError) and str(e) == 'no dicts allowed':
|
||||
return None
|
||||
# Bug jedi#427
|
||||
if isinstance(e, UnicodeDecodeError):
|
||||
return None
|
||||
# Bug jedi#429
|
||||
if isinstance(e, IndexError):
|
||||
return None
|
||||
# Bug jedi#431
|
||||
if isinstance(e, AttributeError) and str(e).endswith("'end_pos'"):
|
||||
return None
|
||||
# Bug in Python 2.6, see #275
|
||||
if isinstance(e, OSError) and e.errno == 13:
|
||||
return None
|
||||
# Bug jedi#466
|
||||
if (
|
||||
isinstance(e, SyntaxError) and
|
||||
"EOL while scanning string literal" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug jedi#482
|
||||
if isinstance(e, UnicodeEncodeError):
|
||||
return None
|
||||
# Bug jedi#485
|
||||
if (
|
||||
isinstance(e, ValueError) and
|
||||
"invalid \\x escape" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug jedi#485 in Python 3
|
||||
if (
|
||||
isinstance(e, SyntaxError) and
|
||||
"truncated \\xXX escape" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug jedi#465
|
||||
if (
|
||||
isinstance(e, SyntaxError) and
|
||||
"encoding declaration in Unicode string" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #337 / jedi#471
|
||||
if (
|
||||
isinstance(e, ImportError) and
|
||||
"No module named" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #365 / jedi#486 - fixed in Jedi 0.8.2
|
||||
if (
|
||||
isinstance(e, UnboundLocalError) and
|
||||
"local variable 'path' referenced before assignment" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #366 / jedi#491
|
||||
if (
|
||||
isinstance(e, ValueError) and
|
||||
"__loader__ is None" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #353
|
||||
if (
|
||||
isinstance(e, OSError) and
|
||||
"No such file or directory" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #561, #564, #570, #588, #593, #599 / jedi#572, jedi#579, jedi#590
|
||||
if isinstance(e, KeyError):
|
||||
return None
|
||||
# Bug #519 / jedi#610
|
||||
if (
|
||||
isinstance(e, RuntimeError) and
|
||||
"maximum recursion depth exceeded" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #563 / jedi#589
|
||||
if (
|
||||
isinstance(e, AttributeError) and
|
||||
"MergedNamesDict" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #615 / jedi#592
|
||||
if (
|
||||
isinstance(e, AttributeError) and
|
||||
"ListComprehension" in str(e)
|
||||
):
|
||||
return None
|
||||
# Bug #569 / jedi#593
|
||||
if (
|
||||
isinstance(e, AttributeError) and
|
||||
"names_dict" in str(e)
|
||||
):
|
||||
return None
|
||||
|
||||
from jedi import debug
|
||||
|
||||
debug_info = []
|
||||
|
||||
def _debug(level, str_out):
|
||||
if level == debug.NOTICE:
|
||||
prefix = "[N]"
|
||||
elif level == debug.WARNING:
|
||||
prefix = "[W]"
|
||||
else:
|
||||
prefix = "[?]"
|
||||
debug_info.append(u"{0} {1}".format(prefix, str_out))
|
||||
|
||||
jedi.set_debug_function(_debug, speed=False)
|
||||
try:
|
||||
script = jedi.Script(*args, **kwargs)
|
||||
return getattr(script, name)()
|
||||
except Exception as e:
|
||||
source = kwargs.get('source')
|
||||
sc_args = []
|
||||
sc_args.extend(repr(arg) for arg in args)
|
||||
sc_args.extend("{0}={1}".format(k, "source" if k == "source"
|
||||
else repr(v))
|
||||
for (k, v) in kwargs.items())
|
||||
|
||||
data = {
|
||||
"traceback": traceback.format_exc(),
|
||||
"jedi_debug_info": {'script_args': ", ".join(sc_args),
|
||||
'source': source,
|
||||
'method': name,
|
||||
'debug_info': debug_info}
|
||||
}
|
||||
raise rpc.Fault(message=str(e),
|
||||
code=500,
|
||||
data=data)
|
||||
finally:
|
||||
jedi.set_debug_function(None)
|
||||
91
.emacs.d/elpa/elpy-20171206.847/elpy/pydocutils.py
Normal file
91
.emacs.d/elpa/elpy-20171206.847/elpy/pydocutils.py
Normal file
@@ -0,0 +1,91 @@
|
||||
import sys
|
||||
import types
|
||||
|
||||
from pydoc import safeimport, resolve, ErrorDuringImport
|
||||
from pkgutil import iter_modules
|
||||
|
||||
from elpy import compat
|
||||
|
||||
# Types we want to recurse into (nodes).
|
||||
CONTAINER_TYPES = (type, types.ModuleType)
|
||||
# Types of attributes we can get documentation for (leaves).
|
||||
PYDOC_TYPES = (type,
|
||||
types.FunctionType,
|
||||
types.BuiltinFunctionType,
|
||||
types.BuiltinMethodType,
|
||||
types.MethodType,
|
||||
types.ModuleType)
|
||||
if not compat.PYTHON3: # pragma: nocover
|
||||
# Python 2 old style classes
|
||||
CONTAINER_TYPES = tuple(list(CONTAINER_TYPES) + [types.ClassType])
|
||||
PYDOC_TYPES = tuple(list(PYDOC_TYPES) + [types.ClassType])
|
||||
|
||||
|
||||
def get_pydoc_completions(modulename):
|
||||
"""Get possible completions for modulename for pydoc.
|
||||
|
||||
Returns a list of possible values to be passed to pydoc.
|
||||
|
||||
"""
|
||||
modulename = compat.ensure_not_unicode(modulename)
|
||||
modulename = modulename.rstrip(".")
|
||||
if modulename == "":
|
||||
return sorted(get_modules())
|
||||
candidates = get_completions(modulename)
|
||||
if candidates:
|
||||
return sorted(candidates)
|
||||
needle = modulename
|
||||
if "." in needle:
|
||||
modulename, part = needle.rsplit(".", 1)
|
||||
candidates = get_completions(modulename)
|
||||
else:
|
||||
candidates = get_modules()
|
||||
return sorted(candidate for candidate in candidates
|
||||
if candidate.startswith(needle))
|
||||
|
||||
|
||||
def get_completions(modulename):
|
||||
modules = set("{0}.{1}".format(modulename, module)
|
||||
for module in get_modules(modulename))
|
||||
|
||||
try:
|
||||
module, name = resolve(modulename)
|
||||
except ImportError:
|
||||
return modules
|
||||
if isinstance(module, CONTAINER_TYPES):
|
||||
modules.update("{0}.{1}".format(modulename, name)
|
||||
for name in dir(module)
|
||||
if not name.startswith("_") and
|
||||
isinstance(getattr(module, name),
|
||||
PYDOC_TYPES))
|
||||
return modules
|
||||
|
||||
|
||||
def get_modules(modulename=None):
|
||||
"""Return a list of modules and packages under modulename.
|
||||
|
||||
If modulename is not given, return a list of all top level modules
|
||||
and packages.
|
||||
|
||||
"""
|
||||
modulename = compat.ensure_not_unicode(modulename)
|
||||
if not modulename:
|
||||
try:
|
||||
return ([modname for (importer, modname, ispkg)
|
||||
in iter_modules()
|
||||
if not modname.startswith("_")] +
|
||||
list(sys.builtin_module_names))
|
||||
except OSError:
|
||||
# Bug in Python 2.6, see #275
|
||||
return list(sys.builtin_module_names)
|
||||
try:
|
||||
module = safeimport(modulename)
|
||||
except ErrorDuringImport:
|
||||
return []
|
||||
if module is None:
|
||||
return []
|
||||
if hasattr(module, "__path__"):
|
||||
return [modname for (importer, modname, ispkg)
|
||||
in iter_modules(module.__path__)
|
||||
if not modname.startswith("_")]
|
||||
return []
|
||||
381
.emacs.d/elpa/elpy-20171206.847/elpy/refactor.py
Normal file
381
.emacs.d/elpa/elpy-20171206.847/elpy/refactor.py
Normal file
@@ -0,0 +1,381 @@
|
||||
"""Refactoring methods for elpy.
|
||||
|
||||
This interfaces directly with rope, regardless of the backend used,
|
||||
because the other backends don't really offer refactoring choices.
|
||||
Once Jedi is similarly featureful as Rope we can try and offer both.
|
||||
|
||||
|
||||
# Too complex:
|
||||
|
||||
- Restructure: Interesting, but too complex, and needs deep Rope
|
||||
knowledge to do well.
|
||||
|
||||
- ChangeSignature: Slightly less complex interface, but still to
|
||||
complex, requiring a large effort for the benefit.
|
||||
|
||||
|
||||
# Too useless:
|
||||
|
||||
I could not get these to work in any useful fashion. I might be doing
|
||||
something wrong.
|
||||
|
||||
- ExtractVariable does not replace the code extracted with the
|
||||
variable, making it a glorified copy&paste function. Emacs can do
|
||||
better than this interface by itself.
|
||||
|
||||
- EncapsulateField: Getter/setter methods are outdated, this should be
|
||||
using properties.
|
||||
|
||||
- IntroduceFactory: Inserts a trivial method to the current class.
|
||||
Cute.
|
||||
|
||||
- IntroduceParameter: Introduces a parameter correctly, but does not
|
||||
replace the old code with the parameter. So it just edits the
|
||||
argument list and adds a shiny default.
|
||||
|
||||
- LocalToField: Seems to just add "self." in front of all occurrences
|
||||
of a variable in the local scope.
|
||||
|
||||
- MethodObject: This turns the current method into a callable
|
||||
class/object. Not sure what that would be good for.
|
||||
|
||||
|
||||
# Can't even get to work:
|
||||
|
||||
- ImportOrganizer expand_star_imports, handle_long_imports,
|
||||
relatives_to_absolutes: Seem not to do anything.
|
||||
|
||||
- create_move: I was not able to figure out what it would like to see
|
||||
as its attrib argument.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from elpy.rpc import Fault
|
||||
|
||||
try:
|
||||
from rope.base.exceptions import RefactoringError
|
||||
from rope.base.project import Project
|
||||
from rope.base.libutils import path_to_resource
|
||||
from rope.base import change as rope_change
|
||||
from rope.base import worder
|
||||
from rope.refactor.importutils import ImportOrganizer
|
||||
from rope.refactor.topackage import ModuleToPackage
|
||||
from rope.refactor.rename import Rename
|
||||
from rope.refactor.move import create_move
|
||||
from rope.refactor.inline import create_inline
|
||||
from rope.refactor.extract import ExtractMethod
|
||||
from rope.refactor.usefunction import UseFunction
|
||||
ROPE_AVAILABLE = True
|
||||
except ImportError:
|
||||
ROPE_AVAILABLE = False
|
||||
|
||||
|
||||
def options(description, **kwargs):
|
||||
"""Decorator to set some options on a method."""
|
||||
def set_notes(function):
|
||||
function.refactor_notes = {'name': function.__name__,
|
||||
'category': "Miscellaneous",
|
||||
'description': description,
|
||||
'doc': getattr(function, '__doc__',
|
||||
''),
|
||||
'args': []}
|
||||
function.refactor_notes.update(kwargs)
|
||||
return function
|
||||
return set_notes
|
||||
|
||||
|
||||
class Refactor(object):
|
||||
"""The main refactoring interface.
|
||||
|
||||
Once initialized, the first call should be to get_refactor_options
|
||||
to get a list of refactoring options at a given position. The
|
||||
returned value will also list any additional options required.
|
||||
|
||||
Once you picked one, you can call get_changes to get the actual
|
||||
refactoring changes.
|
||||
|
||||
"""
|
||||
def __init__(self, project_root, filename):
|
||||
self.project_root = project_root
|
||||
if not ROPE_AVAILABLE:
|
||||
raise Fault('rope not installed, cannot refactor code.',
|
||||
code=400)
|
||||
if not os.path.exists(project_root):
|
||||
raise Fault(
|
||||
"cannot do refactoring without a local project root",
|
||||
code=400
|
||||
)
|
||||
self.project = Project(project_root, ropefolder=None)
|
||||
self.resource = path_to_resource(self.project, filename)
|
||||
|
||||
def get_refactor_options(self, start, end=None):
|
||||
"""Return a list of options for refactoring at the given position.
|
||||
|
||||
If `end` is also given, refactoring on a region is assumed.
|
||||
|
||||
Each option is a dictionary of key/value pairs. The value of
|
||||
the key 'name' is the one to be used for get_changes.
|
||||
|
||||
The key 'args' contains a list of additional arguments
|
||||
required for get_changes.
|
||||
|
||||
"""
|
||||
result = []
|
||||
for symbol in dir(self):
|
||||
if not symbol.startswith("refactor_"):
|
||||
continue
|
||||
method = getattr(self, symbol)
|
||||
if not method.refactor_notes.get('available', True):
|
||||
continue
|
||||
category = method.refactor_notes['category']
|
||||
if end is not None and category != 'Region':
|
||||
continue
|
||||
if end is None and category == 'Region':
|
||||
continue
|
||||
is_on_symbol = self._is_on_symbol(start)
|
||||
if not is_on_symbol and category in ('Symbol', 'Method'):
|
||||
continue
|
||||
requires_import = method.refactor_notes.get('only_on_imports',
|
||||
False)
|
||||
if requires_import and not self._is_on_import_statement(start):
|
||||
continue
|
||||
result.append(method.refactor_notes)
|
||||
return result
|
||||
|
||||
def _is_on_import_statement(self, offset):
|
||||
"Does this offset point to an import statement?"
|
||||
data = self.resource.read()
|
||||
bol = data.rfind("\n", 0, offset) + 1
|
||||
eol = data.find("\n", 0, bol)
|
||||
if eol == -1:
|
||||
eol = len(data)
|
||||
line = data[bol:eol]
|
||||
line = line.strip()
|
||||
if line.startswith("import ") or line.startswith("from "):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _is_on_symbol(self, offset):
|
||||
"Is this offset on a symbol?"
|
||||
if not ROPE_AVAILABLE:
|
||||
return False
|
||||
data = self.resource.read()
|
||||
if offset >= len(data):
|
||||
return False
|
||||
if data[offset] != '_' and not data[offset].isalnum():
|
||||
return False
|
||||
word = worder.get_name_at(self.resource, offset)
|
||||
if word:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_changes(self, name, *args):
|
||||
"""Return a list of changes for the named refactoring action.
|
||||
|
||||
Changes are dictionaries describing a single action to be
|
||||
taken for the refactoring to be successful.
|
||||
|
||||
A change has an action and possibly a type. In the description
|
||||
below, the action is before the slash and the type after it.
|
||||
|
||||
change: Change file contents
|
||||
- file: The path to the file to change
|
||||
- contents: The new contents for the file
|
||||
- Diff: A unified diff showing the changes introduced
|
||||
|
||||
create/file: Create a new file
|
||||
- file: The file to create
|
||||
|
||||
create/directory: Create a new directory
|
||||
- path: The directory to create
|
||||
|
||||
move/file: Rename a file
|
||||
- source: The path to the source file
|
||||
- destination: The path to the destination file name
|
||||
|
||||
move/directory: Rename a directory
|
||||
- source: The path to the source directory
|
||||
- destination: The path to the destination directory name
|
||||
|
||||
delete/file: Delete a file
|
||||
- file: The file to delete
|
||||
|
||||
delete/directory: Delete a directory
|
||||
- path: The directory to delete
|
||||
|
||||
"""
|
||||
if not name.startswith("refactor_"):
|
||||
raise ValueError("Bad refactoring name {0}".format(name))
|
||||
method = getattr(self, name)
|
||||
if not method.refactor_notes.get('available', True):
|
||||
raise RuntimeError("Method not available")
|
||||
return method(*args)
|
||||
|
||||
@options("Convert from x import y to import x.y as y", category="Imports",
|
||||
args=[("offset", "offset", None)],
|
||||
only_on_imports=True,
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_froms_to_imports(self, offset):
|
||||
"""Converting imports of the form "from ..." to "import ..."."""
|
||||
refactor = ImportOrganizer(self.project)
|
||||
changes = refactor.froms_to_imports(self.resource, offset)
|
||||
return translate_changes(changes)
|
||||
|
||||
@options("Reorganize and clean up", category="Imports",
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_organize_imports(self):
|
||||
"""Clean up and organize imports."""
|
||||
refactor = ImportOrganizer(self.project)
|
||||
changes = refactor.organize_imports(self.resource)
|
||||
return translate_changes(changes)
|
||||
|
||||
@options("Convert the current module into a package", category="Module",
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_module_to_package(self):
|
||||
"""Convert the current module into a package."""
|
||||
refactor = ModuleToPackage(self.project, self.resource)
|
||||
return self._get_changes(refactor)
|
||||
|
||||
@options("Rename symbol at point", category="Symbol",
|
||||
args=[("offset", "offset", None),
|
||||
("new_name", "string", "Rename to: "),
|
||||
("in_hierarchy", "boolean",
|
||||
"Rename in super-/subclasses as well? "),
|
||||
("docs", "boolean",
|
||||
"Replace occurences in docs and strings? ")
|
||||
],
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_rename_at_point(self, offset, new_name, in_hierarchy, docs):
|
||||
"""Rename the symbol at point."""
|
||||
try:
|
||||
refactor = Rename(self.project, self.resource, offset)
|
||||
except RefactoringError as e:
|
||||
raise Fault(str(e), code=400)
|
||||
return self._get_changes(refactor, new_name,
|
||||
in_hierarchy=in_hierarchy, docs=docs)
|
||||
|
||||
@options("Rename current module", category="Module",
|
||||
args=[("new_name", "string", "Rename to: ")],
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_rename_current_module(self, new_name):
|
||||
"""Rename the current module."""
|
||||
refactor = Rename(self.project, self.resource, None)
|
||||
return self._get_changes(refactor, new_name)
|
||||
|
||||
@options("Move the current module to a different package",
|
||||
category="Module",
|
||||
args=[("new_name", "directory", "Destination package: ")],
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_move_module(self, new_name):
|
||||
"""Move the current module."""
|
||||
refactor = create_move(self.project, self.resource)
|
||||
resource = path_to_resource(self.project, new_name)
|
||||
return self._get_changes(refactor, resource)
|
||||
|
||||
@options("Inline function call at point", category="Symbol",
|
||||
args=[("offset", "offset", None),
|
||||
("only_this", "boolean", "Only this occurrence? ")],
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_create_inline(self, offset, only_this):
|
||||
"""Inline the function call at point."""
|
||||
refactor = create_inline(self.project, self.resource, offset)
|
||||
if only_this:
|
||||
return self._get_changes(refactor, remove=False, only_current=True)
|
||||
else:
|
||||
return self._get_changes(refactor, remove=True, only_current=False)
|
||||
|
||||
@options("Extract current region as a method", category="Region",
|
||||
args=[("start", "start_offset", None),
|
||||
("end", "end_offset", None),
|
||||
("name", "string", "Method name: "),
|
||||
("make_global", "boolean", "Create global method? ")],
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_extract_method(self, start, end, name,
|
||||
make_global):
|
||||
"""Extract region as a method."""
|
||||
refactor = ExtractMethod(self.project, self.resource, start, end)
|
||||
return self._get_changes(
|
||||
refactor, name, similar=True, global_=make_global
|
||||
)
|
||||
|
||||
@options("Use the function at point wherever possible", category="Method",
|
||||
args=[("offset", "offset", None)],
|
||||
available=ROPE_AVAILABLE)
|
||||
def refactor_use_function(self, offset):
|
||||
"""Use the function at point wherever possible."""
|
||||
try:
|
||||
refactor = UseFunction(self.project, self.resource, offset)
|
||||
except RefactoringError as e:
|
||||
raise Fault(
|
||||
'Refactoring error: {}'.format(e),
|
||||
code=400
|
||||
)
|
||||
return self._get_changes(refactor)
|
||||
|
||||
def _get_changes(self, refactor, *args, **kwargs):
|
||||
try:
|
||||
changes = refactor.get_changes(*args, **kwargs)
|
||||
except Exception as e:
|
||||
raise Fault("Error during refactoring: {}".format(e),
|
||||
code=400)
|
||||
return translate_changes(changes)
|
||||
|
||||
|
||||
def translate_changes(initial_change):
|
||||
"""Translate rope.base.change.Change instances to dictionaries.
|
||||
|
||||
See Refactor.get_changes for an explanation of the resulting
|
||||
dictionary.
|
||||
|
||||
"""
|
||||
agenda = [initial_change]
|
||||
result = []
|
||||
while agenda:
|
||||
change = agenda.pop(0)
|
||||
if isinstance(change, rope_change.ChangeSet):
|
||||
agenda.extend(change.changes)
|
||||
elif isinstance(change, rope_change.ChangeContents):
|
||||
result.append({'action': 'change',
|
||||
'file': change.resource.real_path,
|
||||
'contents': change.new_contents,
|
||||
'diff': change.get_description()})
|
||||
elif isinstance(change, rope_change.CreateFile):
|
||||
result.append({'action': 'create',
|
||||
'type': 'file',
|
||||
'file': change.resource.real_path})
|
||||
elif isinstance(change, rope_change.CreateFolder):
|
||||
result.append({'action': 'create',
|
||||
'type': 'directory',
|
||||
'path': change.resource.real_path})
|
||||
elif isinstance(change, rope_change.MoveResource):
|
||||
result.append({'action': 'move',
|
||||
'type': ('directory'
|
||||
if change.new_resource.is_folder()
|
||||
else 'file'),
|
||||
'source': change.resource.real_path,
|
||||
'destination': change.new_resource.real_path})
|
||||
elif isinstance(change, rope_change.RemoveResource):
|
||||
if change.resource.is_folder():
|
||||
result.append({'action': 'delete',
|
||||
'type': 'directory',
|
||||
'path': change.resource.real_path})
|
||||
else:
|
||||
result.append({'action': 'delete',
|
||||
'type': 'file',
|
||||
'file': change.resource.real_path})
|
||||
return result
|
||||
|
||||
|
||||
class FakeResource(object):
|
||||
"""A fake resource in case Rope is absence."""
|
||||
|
||||
def __init__(self, filename):
|
||||
self.real_path = filename
|
||||
|
||||
def read(self):
|
||||
with open(self.real_path) as f:
|
||||
return f.read()
|
||||
290
.emacs.d/elpa/elpy-20171206.847/elpy/ropebackend.py
Normal file
290
.emacs.d/elpa/elpy-20171206.847/elpy/ropebackend.py
Normal file
@@ -0,0 +1,290 @@
|
||||
"""Elpy backend using the Rope library.
|
||||
|
||||
This backend uses the Rope library:
|
||||
|
||||
http://rope.sourceforge.net/
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
import rope.contrib.codeassist
|
||||
import rope.base.project
|
||||
import rope.base.libutils
|
||||
import rope.base.exceptions
|
||||
import rope.contrib.findit
|
||||
|
||||
from elpy import rpc
|
||||
import elpy.pydocutils
|
||||
|
||||
VALIDATE_EVERY_SECONDS = 5
|
||||
MAXFIXES = 5
|
||||
|
||||
|
||||
class RopeBackend(object):
|
||||
"""The Rope backend class.
|
||||
|
||||
Implements the RPC calls we can pass on to Rope. Also subclasses
|
||||
the native backend to provide methods Rope does not provide, if
|
||||
any.
|
||||
|
||||
"""
|
||||
name = "rope"
|
||||
|
||||
def __init__(self, project_root):
|
||||
super(RopeBackend, self).__init__()
|
||||
self.last_validation = 0
|
||||
if not os.path.exists(project_root):
|
||||
raise rpc.Fault(
|
||||
"rope does not support files without a local project root",
|
||||
code=400
|
||||
)
|
||||
self.project_root = project_root
|
||||
self.completions = {}
|
||||
prefs = dict(ignored_resources=['*.pyc', '*~', '.ropeproject',
|
||||
'.hg', '.svn', '_svn', '.git'],
|
||||
python_files=['*.py'],
|
||||
save_objectdb=False,
|
||||
compress_objectdb=False,
|
||||
automatic_soa=True,
|
||||
soa_followed_calls=0,
|
||||
perform_doa=True,
|
||||
validate_objectdb=True,
|
||||
max_history_items=32,
|
||||
save_history=False,
|
||||
compress_history=False,
|
||||
indent_size=4,
|
||||
extension_modules=[],
|
||||
import_dynload_stdmods=True,
|
||||
ignore_syntax_errors=False,
|
||||
ignore_bad_imports=False)
|
||||
self.project = rope.base.project.Project(self.project_root,
|
||||
ropefolder=None,
|
||||
**prefs)
|
||||
|
||||
def get_resource(self, filename):
|
||||
if filename is not None and os.path.exists(filename):
|
||||
return rope.base.libutils.path_to_resource(self.project,
|
||||
filename,
|
||||
'file')
|
||||
else:
|
||||
return None
|
||||
|
||||
def validate(self):
|
||||
"""Validate the stored project.
|
||||
|
||||
This should be called before every use of Rope. It will
|
||||
revalidate the project, but do some call throttling.
|
||||
|
||||
"""
|
||||
now = time.time()
|
||||
if now > self.last_validation + VALIDATE_EVERY_SECONDS:
|
||||
try:
|
||||
self.project.validate()
|
||||
except rope.base.exceptions.ResourceNotFoundError:
|
||||
pass
|
||||
self.last_validation = now
|
||||
|
||||
def call_rope(self, rope_function, filename, source, offset,
|
||||
**kwargs):
|
||||
self.validate()
|
||||
resource = self.get_resource(filename)
|
||||
try:
|
||||
return rope_function(self.project,
|
||||
source, offset,
|
||||
resource,
|
||||
maxfixes=MAXFIXES,
|
||||
**kwargs)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def rpc_get_completions(self, filename, source, offset):
|
||||
proposals = self.call_rope(
|
||||
rope.contrib.codeassist.code_assist,
|
||||
filename, source, offset
|
||||
)
|
||||
if proposals is None:
|
||||
return []
|
||||
try:
|
||||
starting_offset = rope.contrib.codeassist.starting_offset(source,
|
||||
offset)
|
||||
except Exception:
|
||||
return []
|
||||
prefixlen = offset - starting_offset
|
||||
try:
|
||||
self.completions = dict((proposal.name, proposal)
|
||||
for proposal in proposals)
|
||||
return [{'name': proposal.name,
|
||||
'suffix': proposal.name[prefixlen:],
|
||||
'annotation': proposal.type,
|
||||
'meta': str(proposal)}
|
||||
for proposal in proposals]
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
def rpc_get_completion_docstring(self, completion):
|
||||
proposal = self.completions.get(completion)
|
||||
if proposal is None:
|
||||
return None
|
||||
else:
|
||||
return proposal.get_doc()
|
||||
|
||||
def rpc_get_completion_location(self, completion):
|
||||
proposal = self.completions.get(completion)
|
||||
if proposal is None:
|
||||
return None
|
||||
else:
|
||||
if not proposal.pyname:
|
||||
return None
|
||||
module, lineno = proposal.pyname.get_definition_location()
|
||||
if module is None:
|
||||
return None
|
||||
resource = module.get_module().get_resource()
|
||||
return (resource.real_path, lineno)
|
||||
|
||||
def rpc_get_definition(self, filename, source, offset):
|
||||
location = self.call_rope(
|
||||
rope.contrib.findit.find_definition,
|
||||
filename, source, offset
|
||||
)
|
||||
if location is None:
|
||||
return None
|
||||
else:
|
||||
return (location.resource.real_path, location.offset)
|
||||
|
||||
def rpc_get_calltip(self, filename, source, offset):
|
||||
offset = find_called_name_offset(source, offset)
|
||||
if 0 < offset < len(source) and source[offset] == ')':
|
||||
offset -= 1
|
||||
|
||||
calltip = self.call_rope(
|
||||
rope.contrib.codeassist.get_calltip,
|
||||
filename, source, offset,
|
||||
remove_self=True
|
||||
)
|
||||
if calltip is None:
|
||||
return None
|
||||
|
||||
calltip = calltip.replace(".__init__(", "(")
|
||||
calltip = calltip.replace("(self)", "()")
|
||||
calltip = calltip.replace("(self, ", "(")
|
||||
# "elpy.tests.support.source_and_offset(source)"
|
||||
# =>
|
||||
# "support.source_and_offset(source)"
|
||||
try:
|
||||
openpos = calltip.index("(")
|
||||
period2 = calltip.rindex(".", 0, openpos)
|
||||
period1 = calltip.rindex(".", 0, period2)
|
||||
calltip = calltip[period1 + 1:]
|
||||
except ValueError:
|
||||
pass
|
||||
return calltip
|
||||
|
||||
def rpc_get_docstring(self, filename, source, offset):
|
||||
return self.call_rope(
|
||||
rope.contrib.codeassist.get_doc,
|
||||
filename, source, offset
|
||||
)
|
||||
|
||||
|
||||
def find_called_name_offset(source, orig_offset):
|
||||
"""Return the offset of a calling function.
|
||||
|
||||
This only approximates movement.
|
||||
|
||||
"""
|
||||
offset = min(orig_offset, len(source) - 1)
|
||||
paren_count = 0
|
||||
while True:
|
||||
if offset <= 1:
|
||||
return orig_offset
|
||||
elif source[offset] == '(':
|
||||
if paren_count == 0:
|
||||
return offset - 1
|
||||
else:
|
||||
paren_count -= 1
|
||||
elif source[offset] == ')':
|
||||
paren_count += 1
|
||||
offset -= 1
|
||||
|
||||
|
||||
##################################################################
|
||||
# A recurring problem in Rope for Elpy is that it searches the whole
|
||||
# project root for Python files. If the user edits a file in their
|
||||
# home directory, this can easily read a whole lot of files, making
|
||||
# Rope practically useless. We change the file finding algorithm here
|
||||
# to only recurse into directories with an __init__.py file in them.
|
||||
def find_source_folders(self, folder):
|
||||
for resource in folder.get_folders():
|
||||
if self._is_package(resource):
|
||||
return [folder]
|
||||
result = []
|
||||
for resource in folder.get_files():
|
||||
if resource.name.endswith('.py'):
|
||||
result.append(folder)
|
||||
break
|
||||
for resource in folder.get_folders():
|
||||
if self._is_package(resource):
|
||||
result.append(resource)
|
||||
return result
|
||||
|
||||
import rope.base.pycore
|
||||
rope.base.pycore.PyCore._find_source_folders = find_source_folders
|
||||
|
||||
|
||||
def get_files(self):
|
||||
if self.files is None:
|
||||
self.files = get_python_project_files(self.project)
|
||||
return self.files
|
||||
|
||||
rope.base.project._FileListCacher.get_files = get_files
|
||||
|
||||
|
||||
def get_python_project_files(project):
|
||||
for dirname, subdirs, files in os.walk(project.root.real_path):
|
||||
for filename in files:
|
||||
yield rope.base.libutils.path_to_resource(
|
||||
project, os.path.join(dirname, filename), 'file')
|
||||
subdirs[:] = [subdir for subdir in subdirs
|
||||
if os.path.exists(os.path.join(dirname, subdir,
|
||||
"__init__.py"))]
|
||||
|
||||
|
||||
##################################################################
|
||||
# Monkey patching a method in rope because it doesn't complete import
|
||||
# statements.
|
||||
|
||||
orig_code_completions = (rope.contrib.codeassist.
|
||||
_PythonCodeAssist._code_completions)
|
||||
|
||||
|
||||
def code_completions(self):
|
||||
proposals = get_import_completions(self)
|
||||
if proposals:
|
||||
return proposals
|
||||
else:
|
||||
return orig_code_completions(self)
|
||||
|
||||
|
||||
def get_import_completions(self):
|
||||
if not self.word_finder.is_import_statement(self.offset):
|
||||
return []
|
||||
modulename = self.word_finder.get_primary_at(self.offset)
|
||||
# Rope can handle modules in packages
|
||||
if "." in modulename:
|
||||
return []
|
||||
return dict((name, FakeProposal(name))
|
||||
for name in elpy.pydocutils.get_modules()
|
||||
if name.startswith(modulename))
|
||||
|
||||
|
||||
class FakeProposal(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.type = "mock"
|
||||
|
||||
def get_doc(self):
|
||||
return None
|
||||
|
||||
rope.contrib.codeassist._PythonCodeAssist._code_completions = code_completions
|
||||
151
.emacs.d/elpa/elpy-20171206.847/elpy/rpc.py
Normal file
151
.emacs.d/elpa/elpy-20171206.847/elpy/rpc.py
Normal file
@@ -0,0 +1,151 @@
|
||||
"""A simple JSON-RPC-like server.
|
||||
|
||||
The server will read and write lines of JSON-encoded method calls and
|
||||
responses.
|
||||
|
||||
See the documentation of the JSONRPCServer class for further details.
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
|
||||
class JSONRPCServer(object):
|
||||
"""Simple JSON-RPC-like server.
|
||||
|
||||
This class will read single-line JSON expressions from stdin,
|
||||
decode them, and pass them to a handler. Return values from the
|
||||
handler will be JSON-encoded and written to stdout.
|
||||
|
||||
To implement a handler, you need to subclass this class and add
|
||||
methods starting with "rpc_". Methods then will be found.
|
||||
|
||||
Method calls should be encoded like this:
|
||||
|
||||
{"id": 23, "method": "method_name", "params": ["foo", "bar"]}
|
||||
|
||||
This will call self.rpc_method("foo", "bar").
|
||||
|
||||
Responses will be encoded like this:
|
||||
|
||||
{"id": 23, "result": "foo"}
|
||||
|
||||
Errors will be encoded like this:
|
||||
|
||||
{"id": 23, "error": "Simple error message"}
|
||||
|
||||
See http://www.jsonrpc.org/ for the inspiration of the protocol.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, stdin=None, stdout=None):
|
||||
"""Return a new JSON-RPC server object.
|
||||
|
||||
It will read lines of JSON data from stdin, and write the
|
||||
responses to stdout.
|
||||
|
||||
"""
|
||||
if stdin is None:
|
||||
self.stdin = sys.stdin
|
||||
else:
|
||||
self.stdin = stdin
|
||||
if stdout is None:
|
||||
self.stdout = sys.stdout
|
||||
else:
|
||||
self.stdout = stdout
|
||||
|
||||
def read_json(self):
|
||||
"""Read a single line and decode it as JSON.
|
||||
|
||||
Can raise an EOFError() when the input source was closed.
|
||||
|
||||
"""
|
||||
line = self.stdin.readline()
|
||||
if line == '':
|
||||
raise EOFError()
|
||||
return json.loads(line)
|
||||
|
||||
def write_json(self, **kwargs):
|
||||
"""Write an JSON object on a single line.
|
||||
|
||||
The keyword arguments are interpreted as a single JSON object.
|
||||
It's not possible with this method to write non-objects.
|
||||
|
||||
"""
|
||||
self.stdout.write(json.dumps(kwargs) + "\n")
|
||||
self.stdout.flush()
|
||||
|
||||
def handle_request(self):
|
||||
"""Handle a single JSON-RPC request.
|
||||
|
||||
Read a request, call the appropriate handler method, and
|
||||
return the encoded result. Errors in the handler method are
|
||||
caught and encoded as error objects. Errors in the decoding
|
||||
phase are not caught, as we can not respond with an error
|
||||
response to them.
|
||||
|
||||
"""
|
||||
request = self.read_json()
|
||||
if 'method' not in request:
|
||||
raise ValueError("Received a bad request: {0}"
|
||||
.format(request))
|
||||
method_name = request['method']
|
||||
request_id = request.get('id', None)
|
||||
params = request.get('params') or []
|
||||
try:
|
||||
method = getattr(self, "rpc_" + method_name, None)
|
||||
if method is not None:
|
||||
result = method(*params)
|
||||
else:
|
||||
result = self.handle(method_name, params)
|
||||
if request_id is not None:
|
||||
self.write_json(result=result,
|
||||
id=request_id)
|
||||
except Fault as fault:
|
||||
error = {"message": fault.message,
|
||||
"code": fault.code}
|
||||
if fault.data is not None:
|
||||
error["data"] = fault.data
|
||||
self.write_json(error=error, id=request_id)
|
||||
except Exception as e:
|
||||
error = {"message": str(e),
|
||||
"code": 500,
|
||||
"data": {"traceback": traceback.format_exc()}}
|
||||
self.write_json(error=error, id=request_id)
|
||||
|
||||
def handle(self, method_name, args):
|
||||
"""Handle the call to method_name.
|
||||
|
||||
You should overwrite this method in a subclass.
|
||||
"""
|
||||
raise Fault("Unknown method {0}".format(method_name))
|
||||
|
||||
def serve_forever(self):
|
||||
"""Serve requests forever.
|
||||
|
||||
Errors are not caught, so this is a slight misnomer.
|
||||
|
||||
"""
|
||||
while True:
|
||||
try:
|
||||
self.handle_request()
|
||||
except (KeyboardInterrupt, EOFError, SystemExit):
|
||||
break
|
||||
|
||||
|
||||
class Fault(Exception):
|
||||
"""RPC Fault instances.
|
||||
|
||||
code defines the severity of the warning.
|
||||
|
||||
2xx: Normal behavior lead to end of operation, i.e. a warning
|
||||
4xx: An expected error occurred
|
||||
5xx: An unexpected error occurred (usually includes a traceback)
|
||||
"""
|
||||
def __init__(self, message, code=500, data=None):
|
||||
super(Fault, self).__init__(message)
|
||||
self.message = message
|
||||
self.code = code
|
||||
self.data = data
|
||||
322
.emacs.d/elpa/elpy-20171206.847/elpy/server.py
Normal file
322
.emacs.d/elpa/elpy-20171206.847/elpy/server.py
Normal file
@@ -0,0 +1,322 @@
|
||||
"""Method implementations for the Elpy JSON-RPC server.
|
||||
|
||||
This file implements the methods exported by the JSON-RPC server. It
|
||||
handles backend selection and passes methods on to the selected
|
||||
backend.
|
||||
|
||||
"""
|
||||
import io
|
||||
import os
|
||||
import pydoc
|
||||
|
||||
from elpy.pydocutils import get_pydoc_completions
|
||||
from elpy.rpc import JSONRPCServer, Fault
|
||||
from elpy.impmagic import ImportMagic, ImportMagicError
|
||||
from elpy.auto_pep8 import fix_code
|
||||
from elpy.yapfutil import fix_code as fix_code_with_yapf
|
||||
|
||||
|
||||
try:
|
||||
from elpy import jedibackend
|
||||
except ImportError: # pragma: no cover
|
||||
jedibackend = None
|
||||
|
||||
try:
|
||||
from elpy import ropebackend
|
||||
except ImportError: # pragma: no cover
|
||||
ropebackend = None
|
||||
|
||||
|
||||
class ElpyRPCServer(JSONRPCServer):
|
||||
"""The RPC server for elpy.
|
||||
|
||||
See the rpc_* methods for exported method documentation.
|
||||
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ElpyRPCServer, self).__init__(*args, **kwargs)
|
||||
self.backend = None
|
||||
self.import_magic = ImportMagic()
|
||||
self.project_root = None
|
||||
|
||||
def _call_backend(self, method, default, *args, **kwargs):
|
||||
"""Call the backend method with args.
|
||||
|
||||
If there is currently no backend, return default."""
|
||||
meth = getattr(self.backend, method, None)
|
||||
if meth is None:
|
||||
return default
|
||||
else:
|
||||
return meth(*args, **kwargs)
|
||||
|
||||
def rpc_echo(self, *args):
|
||||
"""Return the arguments.
|
||||
|
||||
This is a simple test method to see if the protocol is
|
||||
working.
|
||||
|
||||
"""
|
||||
return args
|
||||
|
||||
def rpc_init(self, options):
|
||||
self.project_root = options["project_root"]
|
||||
|
||||
if self.import_magic.is_enabled:
|
||||
self.import_magic.build_index(self.project_root)
|
||||
|
||||
if ropebackend and options["backend"] == "rope":
|
||||
self.backend = ropebackend.RopeBackend(self.project_root)
|
||||
elif jedibackend and options["backend"] == "jedi":
|
||||
self.backend = jedibackend.JediBackend(self.project_root)
|
||||
elif ropebackend:
|
||||
self.backend = ropebackend.RopeBackend(self.project_root)
|
||||
elif jedibackend:
|
||||
self.backend = jedibackend.JediBackend(self.project_root)
|
||||
else:
|
||||
self.backend = None
|
||||
|
||||
return {
|
||||
'backend': (self.backend.name if self.backend is not None
|
||||
else None)
|
||||
}
|
||||
|
||||
def rpc_get_calltip(self, filename, source, offset):
|
||||
"""Get the calltip for the function at the offset.
|
||||
|
||||
"""
|
||||
return self._call_backend("rpc_get_calltip", None, filename,
|
||||
get_source(source), offset)
|
||||
|
||||
def rpc_get_completions(self, filename, source, offset):
|
||||
"""Get a list of completion candidates for the symbol at offset.
|
||||
|
||||
"""
|
||||
results = self._call_backend("rpc_get_completions", [], filename,
|
||||
get_source(source), offset)
|
||||
# Uniquify by name
|
||||
results = list(dict((res['name'], res) for res in results)
|
||||
.values())
|
||||
results.sort(key=lambda cand: _pysymbol_key(cand["name"]))
|
||||
return results
|
||||
|
||||
def rpc_get_completion_docstring(self, completion):
|
||||
"""Return documentation for a previously returned completion.
|
||||
|
||||
"""
|
||||
return self._call_backend("rpc_get_completion_docstring",
|
||||
None, completion)
|
||||
|
||||
def rpc_get_completion_location(self, completion):
|
||||
"""Return the location for a previously returned completion.
|
||||
|
||||
This returns a list of [file name, line number].
|
||||
|
||||
"""
|
||||
return self._call_backend("rpc_get_completion_location", None,
|
||||
completion)
|
||||
|
||||
def rpc_get_definition(self, filename, source, offset):
|
||||
"""Get the location of the definition for the symbol at the offset.
|
||||
|
||||
"""
|
||||
return self._call_backend("rpc_get_definition", None, filename,
|
||||
get_source(source), offset)
|
||||
|
||||
def rpc_get_assignment(self, filename, source, offset):
|
||||
"""Get the location of the assignment for the symbol at the offset.
|
||||
|
||||
"""
|
||||
return self._call_backend("rpc_get_assignment", None, filename,
|
||||
get_source(source), offset)
|
||||
|
||||
def rpc_get_docstring(self, filename, source, offset):
|
||||
"""Get the docstring for the symbol at the offset.
|
||||
|
||||
"""
|
||||
return self._call_backend("rpc_get_docstring", None, filename,
|
||||
get_source(source), offset)
|
||||
|
||||
def rpc_get_pydoc_completions(self, name=None):
|
||||
"""Return a list of possible strings to pass to pydoc.
|
||||
|
||||
If name is given, the strings are under name. If not, top
|
||||
level modules are returned.
|
||||
|
||||
"""
|
||||
return get_pydoc_completions(name)
|
||||
|
||||
def rpc_get_pydoc_documentation(self, symbol):
|
||||
"""Get the Pydoc documentation for the given symbol.
|
||||
|
||||
Uses pydoc and can return a string with backspace characters
|
||||
for bold highlighting.
|
||||
|
||||
"""
|
||||
try:
|
||||
docstring = pydoc.render_doc(str(symbol),
|
||||
"Elpy Pydoc Documentation for %s",
|
||||
False)
|
||||
except (ImportError, pydoc.ErrorDuringImport):
|
||||
return None
|
||||
else:
|
||||
if isinstance(docstring, bytes):
|
||||
docstring = docstring.decode("utf-8", "replace")
|
||||
return docstring
|
||||
|
||||
def rpc_get_refactor_options(self, filename, start, end=None):
|
||||
"""Return a list of possible refactoring options.
|
||||
|
||||
This list will be filtered depending on whether it's
|
||||
applicable at the point START and possibly the region between
|
||||
START and END.
|
||||
|
||||
"""
|
||||
try:
|
||||
from elpy import refactor
|
||||
except:
|
||||
raise ImportError("Rope not installed, refactorings unavailable")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
return ref.get_refactor_options(start, end)
|
||||
|
||||
def rpc_refactor(self, filename, method, args):
|
||||
"""Return a list of changes from the refactoring action.
|
||||
|
||||
A change is a dictionary describing the change. See
|
||||
elpy.refactor.translate_changes for a description.
|
||||
|
||||
"""
|
||||
try:
|
||||
from elpy import refactor
|
||||
except:
|
||||
raise ImportError("Rope not installed, refactorings unavailable")
|
||||
if args is None:
|
||||
args = ()
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
return ref.get_changes(method, *args)
|
||||
|
||||
def rpc_get_usages(self, filename, source, offset):
|
||||
"""Get usages for the symbol at point.
|
||||
|
||||
"""
|
||||
source = get_source(source)
|
||||
if hasattr(self.backend, "rpc_get_usages"):
|
||||
return self.backend.rpc_get_usages(filename, source, offset)
|
||||
else:
|
||||
raise Fault("get_usages not implemented by current backend",
|
||||
code=400)
|
||||
|
||||
def rpc_get_names(self, filename, source, offset):
|
||||
"""Get all possible names
|
||||
|
||||
"""
|
||||
source = get_source(source)
|
||||
if hasattr(self.backend, "rpc_get_names"):
|
||||
return self.backend.rpc_get_names(filename, source, offset)
|
||||
else:
|
||||
raise Fault("get_names not implemented by current backend",
|
||||
code=400)
|
||||
|
||||
def _ensure_import_magic(self): # pragma: no cover
|
||||
if not self.import_magic.is_enabled:
|
||||
raise Fault("fixup_imports not enabled; install importmagic module",
|
||||
code=400)
|
||||
if not self.import_magic.symbol_index:
|
||||
raise Fault(self.import_magic.fail_message, code=200) # XXX code?
|
||||
|
||||
def rpc_get_import_symbols(self, filename, source, symbol):
|
||||
"""Return a list of modules from which the given symbol can be imported.
|
||||
|
||||
"""
|
||||
self._ensure_import_magic()
|
||||
try:
|
||||
return self.import_magic.get_import_symbols(symbol)
|
||||
except ImportMagicError as err:
|
||||
raise Fault(str(err), code=200)
|
||||
|
||||
def rpc_add_import(self, filename, source, statement):
|
||||
"""Add an import statement to the module.
|
||||
|
||||
"""
|
||||
self._ensure_import_magic()
|
||||
source = get_source(source)
|
||||
try:
|
||||
return self.import_magic.add_import(source, statement)
|
||||
except ImportMagicError as err:
|
||||
raise Fault(str(err), code=200)
|
||||
|
||||
def rpc_get_unresolved_symbols(self, filename, source):
|
||||
"""Return a list of unreferenced symbols in the module.
|
||||
|
||||
"""
|
||||
self._ensure_import_magic()
|
||||
source = get_source(source)
|
||||
try:
|
||||
return self.import_magic.get_unresolved_symbols(source)
|
||||
except ImportMagicError as err:
|
||||
raise Fault(str(err), code=200)
|
||||
|
||||
def rpc_remove_unreferenced_imports(self, filename, source):
|
||||
"""Remove unused import statements.
|
||||
|
||||
"""
|
||||
self._ensure_import_magic()
|
||||
source = get_source(source)
|
||||
try:
|
||||
return self.import_magic.remove_unreferenced_imports(source)
|
||||
except ImportMagicError as err:
|
||||
raise Fault(str(err), code=200)
|
||||
|
||||
def rpc_fix_code(self, source):
|
||||
"""Formats Python code to conform to the PEP 8 style guide.
|
||||
|
||||
"""
|
||||
source = get_source(source)
|
||||
return fix_code(source)
|
||||
|
||||
def rpc_fix_code_with_yapf(self, source):
|
||||
"""Formats Python code to conform to the PEP 8 style guide.
|
||||
|
||||
"""
|
||||
source = get_source(source)
|
||||
return fix_code_with_yapf(source)
|
||||
|
||||
|
||||
def get_source(fileobj):
|
||||
"""Translate fileobj into file contents.
|
||||
|
||||
fileobj is either a string or a dict. If it's a string, that's the
|
||||
file contents. If it's a string, then the filename key contains
|
||||
the name of the file whose contents we are to use.
|
||||
|
||||
If the dict contains a true value for the key delete_after_use,
|
||||
the file should be deleted once read.
|
||||
|
||||
"""
|
||||
if not isinstance(fileobj, dict):
|
||||
return fileobj
|
||||
else:
|
||||
try:
|
||||
with io.open(fileobj["filename"], encoding="utf-8",
|
||||
errors="ignore") as f:
|
||||
return f.read()
|
||||
finally:
|
||||
if fileobj.get('delete_after_use'):
|
||||
try:
|
||||
os.remove(fileobj["filename"])
|
||||
except: # pragma: no cover
|
||||
pass
|
||||
|
||||
|
||||
def _pysymbol_key(name):
|
||||
"""Return a sortable key index for name.
|
||||
|
||||
Sorting is case-insensitive, with the first underscore counting as
|
||||
worse than any character, but subsequent underscores do not. This
|
||||
means that dunder symbols (like __init__) are sorted after symbols
|
||||
that start with an alphabetic character, but before those that
|
||||
start with only a single underscore.
|
||||
|
||||
"""
|
||||
if name.startswith("_"):
|
||||
name = "~" + name[1:]
|
||||
return name.lower()
|
||||
8
.emacs.d/elpa/elpy-20171206.847/elpy/tests/__init__.py
Normal file
8
.emacs.d/elpa/elpy-20171206.847/elpy/tests/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Unit tests for elpy."""
|
||||
|
||||
try:
|
||||
import unittest2
|
||||
import sys
|
||||
sys.modules['unittest'] = unittest2
|
||||
except:
|
||||
pass
|
||||
18
.emacs.d/elpa/elpy-20171206.847/elpy/tests/compat.py
Normal file
18
.emacs.d/elpa/elpy-20171206.847/elpy/tests/compat.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""Python 2/3 compatibility definitions.
|
||||
|
||||
These are used by the rest of Elpy to keep compatibility definitions
|
||||
in one place.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
PYTHON3 = True
|
||||
import builtins
|
||||
from io import StringIO
|
||||
else:
|
||||
PYTHON3 = False
|
||||
import __builtin__ as builtins # noqa
|
||||
from StringIO import StringIO # noqa
|
||||
950
.emacs.d/elpa/elpy-20171206.847/elpy/tests/support.py
Normal file
950
.emacs.d/elpa/elpy-20171206.847/elpy/tests/support.py
Normal file
@@ -0,0 +1,950 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""Support classes and functions for the elpy test code.
|
||||
|
||||
Elpy uses a bit of a peculiar test setup to avoid redundancy. For the
|
||||
tests of the two backends, we provide generic test cases for generic
|
||||
tests and for specific callback tests.
|
||||
|
||||
These mixins can be included in the actual test classes. We can't add
|
||||
these tests to a BackendTestCase subclass directly because the test
|
||||
discovery would find them there and try to run them, which would fail.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from elpy.tests import compat
|
||||
|
||||
|
||||
class BackendTestCase(unittest.TestCase):
|
||||
"""Base class for backend tests.
|
||||
|
||||
This class sets up a project root directory and provides an easy
|
||||
way to create files within the project root.
|
||||
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""Create the project root and make sure it gets cleaned up."""
|
||||
super(BackendTestCase, self).setUp()
|
||||
self.project_root = tempfile.mkdtemp(prefix="elpy-test")
|
||||
self.addCleanup(shutil.rmtree, self.project_root, True)
|
||||
|
||||
def project_file(self, relname, contents):
|
||||
"""Create a file named relname within the project root.
|
||||
|
||||
Write contents into that file.
|
||||
|
||||
"""
|
||||
full_name = os.path.join(self.project_root, relname)
|
||||
try:
|
||||
os.makedirs(os.path.dirname(full_name))
|
||||
except OSError:
|
||||
pass
|
||||
if compat.PYTHON3:
|
||||
fobj = open(full_name, "w", encoding="utf-8")
|
||||
else:
|
||||
fobj = open(full_name, "w")
|
||||
with fobj as f:
|
||||
f.write(contents)
|
||||
return full_name
|
||||
|
||||
|
||||
class GenericRPCTests(object):
|
||||
"""Generic RPC test methods.
|
||||
|
||||
This is a mixin to add tests that should be run for all RPC
|
||||
methods that follow the generic (filename, source, offset) calling
|
||||
conventions.
|
||||
|
||||
"""
|
||||
METHOD = None
|
||||
|
||||
def rpc(self, filename, source, offset):
|
||||
method = getattr(self.backend, self.METHOD)
|
||||
return method(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_on_inexisting_file(self):
|
||||
filename = self.project_root + "/doesnotexist.py"
|
||||
self.rpc(filename, "", 0)
|
||||
|
||||
def test_should_not_fail_on_empty_file(self):
|
||||
filename = self.project_file("test.py", "")
|
||||
self.rpc(filename, "", 0)
|
||||
|
||||
def test_should_not_fail_if_file_is_none(self):
|
||||
self.rpc(None, "", 0)
|
||||
|
||||
def test_should_not_fail_for_module_syntax_errors(self):
|
||||
source, offset = source_and_offset(
|
||||
"class Foo(object):\n"
|
||||
" def bar(self):\n"
|
||||
" foo(_|_"
|
||||
" bar("
|
||||
"\n"
|
||||
" def a(self):\n"
|
||||
" pass\n"
|
||||
"\n"
|
||||
" def b(self):\n"
|
||||
" pass\n"
|
||||
"\n"
|
||||
" def b(self):\n"
|
||||
" pass\n"
|
||||
"\n"
|
||||
" def b(self):\n"
|
||||
" pass\n"
|
||||
"\n"
|
||||
" def b(self):\n"
|
||||
" pass\n"
|
||||
"\n"
|
||||
" def b(self):\n"
|
||||
" pass\n"
|
||||
)
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_bad_indentation(self):
|
||||
# Bug in Rope: rope#80
|
||||
source, offset = source_and_offset(
|
||||
"def foo():\n"
|
||||
" print(23)_|_\n"
|
||||
" print(17)\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
@unittest.skipIf((3, 3) <= sys.version_info < (3, 4),
|
||||
"Bug in jedi for Python 3.3")
|
||||
def test_should_not_fail_for_relative_import(self):
|
||||
# Bug in Rope: rope#81 and rope#82
|
||||
source, offset = source_and_offset(
|
||||
"from .. import foo_|_"
|
||||
)
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_on_keyword(self):
|
||||
source, offset = source_and_offset(
|
||||
"_|_try:\n"
|
||||
" pass\n"
|
||||
"except:\n"
|
||||
" pass\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_with_bad_encoding(self):
|
||||
# Bug in Rope: rope#83
|
||||
source, offset = source_and_offset(
|
||||
u'# coding: utf-8X_|_\n'
|
||||
)
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_with_form_feed_characters(self):
|
||||
# Bug in Jedi: jedi#424
|
||||
source, offset = source_and_offset(
|
||||
"\f\n"
|
||||
"class Test(object):_|_\n"
|
||||
" pass"
|
||||
)
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_dictionaries_in_weird_places(self):
|
||||
# Bug in Jedi: jedi#417
|
||||
source, offset = source_and_offset(
|
||||
"import json\n"
|
||||
"\n"
|
||||
"def foo():\n"
|
||||
" json.loads(_|_\n"
|
||||
"\n"
|
||||
" json.load.return_value = {'foo': [],\n"
|
||||
" 'bar': True}\n"
|
||||
"\n"
|
||||
" c = Foo()\n"
|
||||
)
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_break_with_binary_characters_in_docstring(self):
|
||||
# Bug in Jedi: jedi#427
|
||||
template = '''\
|
||||
class Foo(object):
|
||||
def __init__(self):
|
||||
"""
|
||||
COMMUNITY instance that this conversion belongs to.
|
||||
DISPERSY_VERSION is the dispersy conversion identifier (on the wire version; must be one byte).
|
||||
COMMUNIY_VERSION is the community conversion identifier (on the wire version; must be one byte).
|
||||
|
||||
COMMUNIY_VERSION may not be '\\x00' or '\\xff'. '\\x00' is used by the DefaultConversion until
|
||||
a proper conversion instance can be made for the Community. '\\xff' is reserved for when
|
||||
more than one byte is needed as a version indicator.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
x = Foo()
|
||||
x._|_
|
||||
'''
|
||||
source, offset = source_and_offset(template)
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_def_without_name(self):
|
||||
# Bug jedi#429
|
||||
source, offset = source_and_offset(
|
||||
"def_|_():\n"
|
||||
" if True:\n"
|
||||
" return True\n"
|
||||
" else:\n"
|
||||
" return False\n"
|
||||
)
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_on_lambda(self):
|
||||
# Bug #272 / jedi#431, jedi#572
|
||||
source, offset = source_and_offset(
|
||||
"map(lambda_|_"
|
||||
)
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_on_literals(self):
|
||||
# Bug #314, #344 / jedi#466
|
||||
source = u'lit = u"""\\\n# -*- coding: utf-8 -*-\n"""\n'
|
||||
offset = 0
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_with_args_as_args(self):
|
||||
# Bug #347 in rope_py3k
|
||||
source, offset = source_and_offset(
|
||||
"def my_function(*args):\n"
|
||||
" ret_|_"
|
||||
)
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_unicode_chars_in_string(self):
|
||||
# Bug #358 / jedi#482
|
||||
source = '''\
|
||||
# coding: utf-8
|
||||
|
||||
logging.info(u"Saving «{}»...".format(title))
|
||||
requests.get(u"https://web.archive.org/save/{}".format(url))
|
||||
'''
|
||||
offset = 57
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_bad_escape_sequence(self):
|
||||
# Bug #360 / jedi#485
|
||||
source = r"v = '\x'"
|
||||
offset = 8
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_coding_declarations_in_strings(self):
|
||||
# Bug #314 / jedi#465 / python#22221
|
||||
source = u'lit = """\\\n# -*- coding: utf-8 -*-\n"""'
|
||||
offset = 8
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_if_root_vanishes(self):
|
||||
# Bug #353
|
||||
source, offset = source_and_offset(
|
||||
"import foo\n"
|
||||
"foo._|_"
|
||||
)
|
||||
filename = self.project_file("project.py", source)
|
||||
shutil.rmtree(self.project_root)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
# For some reason, this breaks a lot of other tests. Couldn't
|
||||
# figure out why.
|
||||
#
|
||||
# def test_should_not_fail_for_sys_path(self):
|
||||
# # Bug #365 / jedi#486
|
||||
# source, offset = source_and_offset(
|
||||
# "import sys\n"
|
||||
# "\n"
|
||||
# "sys.path.index(_|_\n"
|
||||
# )
|
||||
# filename = self.project_file("project.py", source)
|
||||
#
|
||||
# self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_key_error(self):
|
||||
# Bug #561, #564, #570, #588, #593, #599 / jedi#572, jedi#579,
|
||||
# jedi#590
|
||||
source, offset = source_and_offset(
|
||||
"map(lambda_|_"
|
||||
)
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_for_badly_defined_global_variable(self):
|
||||
# Bug #519 / jedi#610
|
||||
source, offset = source_and_offset(
|
||||
"""\
|
||||
def funct1():
|
||||
global global_dict_var
|
||||
global_dict_var = dict()
|
||||
|
||||
def funct2():
|
||||
global global_dict_var
|
||||
q = global_dict_var.copy_|_()
|
||||
print(q)""")
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
def test_should_not_fail_with_mergednamesdict(self):
|
||||
# Bug #563 / jedi#589
|
||||
source, offset = source_and_offset(
|
||||
u'from email import message_|_'
|
||||
)
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
|
||||
class RPCGetCompletionsTests(GenericRPCTests):
|
||||
METHOD = "rpc_get_completions"
|
||||
|
||||
def test_should_complete_builtin(self):
|
||||
source, offset = source_and_offset("o_|_")
|
||||
|
||||
expected = self.BUILTINS
|
||||
actual = [cand['name'] for cand in
|
||||
self.backend.rpc_get_completions("test.py",
|
||||
source, offset)]
|
||||
|
||||
for candidate in expected:
|
||||
self.assertIn(candidate, actual)
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
JSON_COMPLETIONS = ["SONDecoder", "SONEncoder", "SONDecodeError"]
|
||||
else:
|
||||
JSON_COMPLETIONS = ["SONDecoder", "SONEncoder"]
|
||||
|
||||
def test_should_complete_imports(self):
|
||||
source, offset = source_and_offset("import json\n"
|
||||
"json.J_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
self.assertEqual(
|
||||
sorted([cand['suffix'] for cand in completions]),
|
||||
sorted(self.JSON_COMPLETIONS))
|
||||
|
||||
def test_should_complete_top_level_modules_for_import(self):
|
||||
source, offset = source_and_offset("import multi_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
if compat.PYTHON3:
|
||||
expected = ["processing"]
|
||||
else:
|
||||
expected = ["file", "processing"]
|
||||
self.assertEqual(sorted([cand['suffix'] for cand in completions]),
|
||||
sorted(expected))
|
||||
|
||||
def test_should_complete_packages_for_import(self):
|
||||
source, offset = source_and_offset("import email.mi_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
self.assertEqual([cand['suffix'] for cand in completions],
|
||||
["me"])
|
||||
|
||||
def test_should_not_complete_for_import(self):
|
||||
source, offset = source_and_offset("import foo.Conf_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
self.assertEqual([cand['suffix'] for cand in completions],
|
||||
[])
|
||||
|
||||
@unittest.skipIf((3, 3) <= sys.version_info < (3, 4),
|
||||
"Bug in jedi for Python 3.3")
|
||||
def test_should_not_fail_for_short_module(self):
|
||||
source, offset = source_and_offset("from .. import foo_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
self.assertIsNotNone(completions)
|
||||
|
||||
def test_should_complete_sys(self):
|
||||
source, offset = source_and_offset("import sys\nsys._|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
self.assertIn('path', [cand['suffix'] for cand in completions])
|
||||
|
||||
def test_should_find_with_trailing_text(self):
|
||||
source, offset = source_and_offset(
|
||||
"import threading\nthreading.T_|_mumble mumble")
|
||||
|
||||
expected = ["Thread", "ThreadError", "Timer"]
|
||||
actual = [cand['name'] for cand in
|
||||
self.backend.rpc_get_completions("test.py", source, offset)]
|
||||
|
||||
for candidate in expected:
|
||||
self.assertIn(candidate, actual)
|
||||
|
||||
def test_should_find_completion_different_package(self):
|
||||
# See issue #74
|
||||
self.project_file("project/__init__.py", "")
|
||||
source1 = ("class Add:\n"
|
||||
" def add(self, a, b):\n"
|
||||
" return a + b\n")
|
||||
self.project_file("project/add.py", source1)
|
||||
source2, offset = source_and_offset(
|
||||
"from project.add import Add\n"
|
||||
"class Calculator:\n"
|
||||
" def add(self, a, b):\n"
|
||||
" c = Add()\n"
|
||||
" c.ad_|_\n")
|
||||
file2 = self.project_file("project/calculator.py", source2)
|
||||
proposals = self.backend.rpc_get_completions(file2,
|
||||
source2,
|
||||
offset)
|
||||
self.assertEqual(["add"],
|
||||
[proposal["name"] for proposal in proposals])
|
||||
|
||||
|
||||
class RPCGetCompletionDocstringTests(object):
|
||||
def test_should_return_docstring(self):
|
||||
source, offset = source_and_offset("import json\n"
|
||||
"json.JSONEnc_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
completions.sort(key=lambda p: p["name"])
|
||||
prop = completions[0]
|
||||
self.assertEqual(prop["name"], "JSONEncoder")
|
||||
|
||||
docs = self.backend.rpc_get_completion_docstring("JSONEncoder")
|
||||
|
||||
self.assertIn("Extensible JSON", docs)
|
||||
|
||||
def test_should_return_none_if_unknown(self):
|
||||
docs = self.backend.rpc_get_completion_docstring("Foo")
|
||||
|
||||
self.assertIsNone(docs)
|
||||
|
||||
|
||||
class RPCGetCompletionLocationTests(object):
|
||||
def test_should_return_location(self):
|
||||
source, offset = source_and_offset("donaudampfschiff = 1\n"
|
||||
"donau_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
completions = self.backend.rpc_get_completions(filename,
|
||||
source,
|
||||
offset)
|
||||
prop = completions[0]
|
||||
self.assertEqual(prop["name"], "donaudampfschiff")
|
||||
|
||||
loc = self.backend.rpc_get_completion_location("donaudampfschiff")
|
||||
|
||||
self.assertEqual((filename, 1), loc)
|
||||
|
||||
def test_should_return_none_if_unknown(self):
|
||||
docs = self.backend.rpc_get_completion_location("Foo")
|
||||
|
||||
self.assertIsNone(docs)
|
||||
|
||||
|
||||
class RPCGetDefinitionTests(GenericRPCTests):
|
||||
METHOD = "rpc_get_definition"
|
||||
|
||||
def test_should_return_definition_location_same_file(self):
|
||||
source, offset = source_and_offset("import threading\n"
|
||||
"def test_function(a, b):\n"
|
||||
" return a + b\n"
|
||||
"\n"
|
||||
"test_func_|_tion(\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
location = self.backend.rpc_get_definition(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(location[0], filename)
|
||||
# On def or on the function name
|
||||
self.assertIn(location[1], (17, 21))
|
||||
|
||||
def test_should_return_location_in_same_file_if_not_saved(self):
|
||||
source, offset = source_and_offset(
|
||||
"import threading\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"def other_function():\n"
|
||||
" test_f_|_unction(1, 2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"def test_function(a, b):\n"
|
||||
" return a + b\n")
|
||||
filename = self.project_file("test.py", "")
|
||||
|
||||
location = self.backend.rpc_get_definition(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(location[0], filename)
|
||||
# def or function name
|
||||
self.assertIn(location[1], (67, 71))
|
||||
|
||||
def test_should_return_location_in_different_file(self):
|
||||
source1 = ("def test_function(a, b):\n"
|
||||
" return a + b\n")
|
||||
file1 = self.project_file("test1.py", source1)
|
||||
source2, offset = source_and_offset("from test1 import test_function\n"
|
||||
"test_funct_|_ion(1, 2)\n")
|
||||
file2 = self.project_file("test2.py", source2)
|
||||
|
||||
definition = self.backend.rpc_get_definition(file2,
|
||||
source2,
|
||||
offset)
|
||||
|
||||
self.assertEqual(definition[0], file1)
|
||||
# Either on the def or on the function name
|
||||
self.assertIn(definition[1], (0, 4))
|
||||
|
||||
def test_should_return_none_if_location_not_found(self):
|
||||
source, offset = source_and_offset("test_f_|_unction()\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
definition = self.backend.rpc_get_definition(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertIsNone(definition)
|
||||
|
||||
def test_should_return_none_if_outside_of_symbol(self):
|
||||
source, offset = source_and_offset("test_function(_|_)\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
definition = self.backend.rpc_get_definition(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertIsNone(definition)
|
||||
|
||||
def test_should_return_definition_location_different_package(self):
|
||||
# See issue #74
|
||||
self.project_file("project/__init__.py", "")
|
||||
source1 = ("class Add:\n"
|
||||
" def add(self, a, b):\n"
|
||||
" return a + b\n")
|
||||
file1 = self.project_file("project/add.py", source1)
|
||||
source2, offset = source_and_offset(
|
||||
"from project.add import Add\n"
|
||||
"class Calculator:\n"
|
||||
" def add(self, a, b):\n"
|
||||
" return Add_|_().add(a, b)\n")
|
||||
file2 = self.project_file("project/calculator.py", source2)
|
||||
|
||||
location = self.backend.rpc_get_definition(file2,
|
||||
source2,
|
||||
offset)
|
||||
|
||||
self.assertEqual(location[0], file1)
|
||||
# class or class name
|
||||
self.assertIn(location[1], (0, 6))
|
||||
|
||||
def test_should_find_variable_definition(self):
|
||||
source, offset = source_and_offset("SOME_VALUE = 1\n"
|
||||
"\n"
|
||||
"variable = _|_SOME_VALUE\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
self.assertEqual(self.backend.rpc_get_definition(filename,
|
||||
source,
|
||||
offset),
|
||||
(filename, 0))
|
||||
|
||||
|
||||
class RPCGetAssignmentTests(GenericRPCTests):
|
||||
METHOD = "rpc_get_assignment"
|
||||
|
||||
def test_should_return_assignment_location_same_file(self):
|
||||
source, offset = source_and_offset("import threading\n"
|
||||
"class TestClass(object):\n"
|
||||
" def __init__(self, a, b):\n"
|
||||
" self.a = a\n"
|
||||
" self.b = b\n"
|
||||
"\n"
|
||||
"testclass = TestClass(2, 4)"
|
||||
"\n"
|
||||
"testcl_|_ass(\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
location = self.backend.rpc_get_assignment(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(location[0], filename)
|
||||
# On def or on the function name
|
||||
self.assertEqual(location[1], 111)
|
||||
|
||||
def test_should_return_location_in_same_file_if_not_saved(self):
|
||||
source, offset = source_and_offset("import threading\n"
|
||||
"class TestClass(object):\n"
|
||||
" def __init__(self, a, b):\n"
|
||||
" self.a = a\n"
|
||||
" self.b = b\n"
|
||||
"\n"
|
||||
"testclass = TestClass(2, 4)"
|
||||
"\n"
|
||||
"testcl_|_ass(\n")
|
||||
filename = self.project_file("test.py", "")
|
||||
|
||||
location = self.backend.rpc_get_assignment(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(location[0], filename)
|
||||
# def or function name
|
||||
self.assertEqual(location[1], 111)
|
||||
|
||||
def test_should_return_location_in_different_file(self):
|
||||
source1 = ("class TestClass(object):\n"
|
||||
" def __init__(self, a, b):\n"
|
||||
" self.a = a\n"
|
||||
" self.b = b\n"
|
||||
"testclass = TestClass(3, 5)\n")
|
||||
file1 = self.project_file("test1.py", source1)
|
||||
source2, offset = source_and_offset("from test1 import testclass\n"
|
||||
"testcl_|_ass.a\n")
|
||||
file2 = self.project_file("test2.py", source2)
|
||||
# First jump goes to import statement
|
||||
assignment = self.backend.rpc_get_assignment(file2,
|
||||
source2,
|
||||
offset)
|
||||
# Second jump goes to test1 file
|
||||
self.assertEqual(assignment[0], file2)
|
||||
assignment = self.backend.rpc_get_assignment(file2,
|
||||
source2,
|
||||
assignment[1])
|
||||
|
||||
self.assertEqual(assignment[0], file1)
|
||||
self.assertEqual(assignment[1], 93)
|
||||
|
||||
def test_should_return_none_if_location_not_found(self):
|
||||
source, offset = source_and_offset("test_f_|_unction()\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
assignment = self.backend.rpc_get_assignment(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertIsNone(assignment)
|
||||
|
||||
def test_should_return_none_if_outside_of_symbol(self):
|
||||
source, offset = source_and_offset("testcl(_|_)ass\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
assignment = self.backend.rpc_get_assignment(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertIsNone(assignment)
|
||||
|
||||
def test_should_find_variable_assignment(self):
|
||||
source, offset = source_and_offset("SOME_VALUE = 1\n"
|
||||
"\n"
|
||||
"variable = _|_SOME_VALUE\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
self.assertEqual(self.backend.rpc_get_assignment(filename,
|
||||
source,
|
||||
offset),
|
||||
(filename, 0))
|
||||
|
||||
|
||||
class RPCGetCalltipTests(GenericRPCTests):
|
||||
METHOD = "rpc_get_calltip"
|
||||
|
||||
@unittest.skipIf(sys.version_info >= (3, 0),
|
||||
"Bug in Jedi 0.9.0")
|
||||
def test_should_get_calltip(self):
|
||||
source, offset = source_and_offset(
|
||||
"import threading\nthreading.Thread(_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
calltip = self.backend.rpc_get_calltip(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
expected = self.THREAD_CALLTIP
|
||||
|
||||
self.assertEqual(calltip, expected)
|
||||
|
||||
@unittest.skipIf(sys.version_info >= (3, 0),
|
||||
"Bug in Jedi 0.9.0")
|
||||
def test_should_get_calltip_even_after_parens(self):
|
||||
source, offset = source_and_offset(
|
||||
"import threading\nthreading.Thread(foo()_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
actual = self.backend.rpc_get_calltip(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(self.THREAD_CALLTIP, actual)
|
||||
|
||||
@unittest.skipIf(sys.version_info >= (3, 0),
|
||||
"Bug in Jedi 0.9.0")
|
||||
def test_should_get_calltip_at_closing_paren(self):
|
||||
source, offset = source_and_offset(
|
||||
"import threading\nthreading.Thread(_|_)")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
actual = self.backend.rpc_get_calltip(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(self.THREAD_CALLTIP, actual)
|
||||
|
||||
def test_should_not_missing_attribute_get_definition(self):
|
||||
# Bug #627 / jedi#573
|
||||
source, offset = source_and_offset(
|
||||
"import threading\nthreading.Thread(_|_)")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
self.backend.rpc_get_calltip(filename, source, offset)
|
||||
|
||||
def test_should_return_none_for_bad_identifier(self):
|
||||
source, offset = source_and_offset(
|
||||
"froblgoo(_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
calltip = self.backend.rpc_get_calltip(filename,
|
||||
source,
|
||||
offset)
|
||||
self.assertIsNone(calltip)
|
||||
|
||||
def test_should_remove_self_argument(self):
|
||||
source, offset = source_and_offset(
|
||||
"d = dict()\n"
|
||||
"d.keys(_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
actual = self.backend.rpc_get_calltip(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(self.KEYS_CALLTIP, actual)
|
||||
|
||||
def test_should_remove_package_prefix(self):
|
||||
source, offset = source_and_offset(
|
||||
"import decimal\n"
|
||||
"d = decimal.Decimal('1.5')\n"
|
||||
"d.radix(_|_")
|
||||
filename = self.project_file("test.py", source)
|
||||
|
||||
actual = self.backend.rpc_get_calltip(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(self.RADIX_CALLTIP, actual)
|
||||
|
||||
def test_should_return_none_outside_of_all(self):
|
||||
filename = self.project_file("test.py", "")
|
||||
source, offset = source_and_offset("import thr_|_eading\n")
|
||||
calltip = self.backend.rpc_get_calltip(filename,
|
||||
source, offset)
|
||||
self.assertIsNone(calltip)
|
||||
|
||||
def test_should_find_calltip_different_package(self):
|
||||
# See issue #74
|
||||
self.project_file("project/__init__.py", "")
|
||||
source1 = ("class Add:\n"
|
||||
" def add(self, a, b):\n"
|
||||
" return a + b\n")
|
||||
self.project_file("project/add.py", source1)
|
||||
source2, offset = source_and_offset(
|
||||
"from project.add import Add\n"
|
||||
"class Calculator:\n"
|
||||
" def add(self, a, b):\n"
|
||||
" c = Add()\n"
|
||||
" c.add(_|_\n")
|
||||
file2 = self.project_file("project/calculator.py", source2)
|
||||
|
||||
actual = self.backend.rpc_get_calltip(file2,
|
||||
source2,
|
||||
offset)
|
||||
|
||||
self.assertEqual(self.ADD_CALLTIP, actual)
|
||||
|
||||
|
||||
class RPCGetDocstringTests(GenericRPCTests):
|
||||
METHOD = "rpc_get_docstring"
|
||||
|
||||
def check_docstring(self, docstring):
|
||||
|
||||
def first_line(s):
|
||||
return s[:s.index("\n")]
|
||||
|
||||
self.assertEqual(first_line(docstring),
|
||||
self.JSON_LOADS_DOCSTRING)
|
||||
|
||||
def test_should_get_docstring(self):
|
||||
source, offset = source_and_offset(
|
||||
"import json\njson.loads_|_(")
|
||||
filename = self.project_file("test.py", source)
|
||||
docstring = self.backend.rpc_get_docstring(filename,
|
||||
source,
|
||||
offset)
|
||||
self.check_docstring(docstring)
|
||||
|
||||
def test_should_return_none_for_bad_identifier(self):
|
||||
source, offset = source_and_offset(
|
||||
"froblgoo_|_(\n")
|
||||
filename = self.project_file("test.py", source)
|
||||
docstring = self.backend.rpc_get_docstring(filename,
|
||||
source,
|
||||
offset)
|
||||
self.assertIsNone(docstring)
|
||||
|
||||
|
||||
class RPCGetNamesTests(GenericRPCTests):
|
||||
METHOD = "rpc_get_names"
|
||||
|
||||
def test_shouldreturn_names_in_same_file(self):
|
||||
filename = self.project_file("test.py", "")
|
||||
source, offset = source_and_offset(
|
||||
"def foo(x, y):\n"
|
||||
" return x + y\n"
|
||||
"c = _|_foo(5, 2)\n")
|
||||
|
||||
names = self.backend.rpc_get_names(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(names,
|
||||
[{'name': 'foo',
|
||||
'filename': filename,
|
||||
'offset': 4},
|
||||
{'name': 'x',
|
||||
'filename': filename,
|
||||
'offset': 8},
|
||||
{'name': 'y',
|
||||
'filename': filename,
|
||||
'offset': 11},
|
||||
{'name': 'x',
|
||||
'filename': filename,
|
||||
'offset': 26},
|
||||
{'name': 'y',
|
||||
'filename': filename,
|
||||
'offset': 30},
|
||||
{'name': 'c',
|
||||
'filename': filename,
|
||||
'offset': 32},
|
||||
{'name': 'foo',
|
||||
'filename': filename,
|
||||
'offset': 36}])
|
||||
|
||||
def test_should_not_fail_without_symbol(self):
|
||||
filename = self.project_file("test.py", "")
|
||||
|
||||
names = self.backend.rpc_get_names(filename,
|
||||
"",
|
||||
0)
|
||||
|
||||
self.assertEqual(names, [])
|
||||
|
||||
|
||||
class RPCGetUsagesTests(GenericRPCTests):
|
||||
METHOD = "rpc_get_usages"
|
||||
|
||||
def test_should_return_uses_in_same_file(self):
|
||||
filename = self.project_file("test.py", "")
|
||||
source, offset = source_and_offset(
|
||||
"def foo(x):\n"
|
||||
" return _|_x + x\n")
|
||||
|
||||
usages = self.backend.rpc_get_usages(filename,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(usages,
|
||||
[{'name': 'x',
|
||||
'offset': 8,
|
||||
'filename': filename},
|
||||
{'name': 'x',
|
||||
'filename': filename,
|
||||
'offset': 23},
|
||||
{'name': u'x',
|
||||
'filename': filename,
|
||||
'offset': 27}])
|
||||
|
||||
def test_should_return_uses_in_other_file(self):
|
||||
file1 = self.project_file("file1.py", "")
|
||||
file2 = self.project_file("file2.py", "\n\n\n\n\nx = 5")
|
||||
source, offset = source_and_offset(
|
||||
"import file2\n"
|
||||
"file2._|_x\n")
|
||||
|
||||
usages = self.backend.rpc_get_usages(file1,
|
||||
source,
|
||||
offset)
|
||||
|
||||
self.assertEqual(usages,
|
||||
[{'name': 'x',
|
||||
'filename': file1,
|
||||
'offset': 19},
|
||||
{'name': 'x',
|
||||
'filename': file2,
|
||||
'offset': 5}])
|
||||
|
||||
def test_should_not_fail_without_symbol(self):
|
||||
filename = self.project_file("file.py", "")
|
||||
|
||||
usages = self.backend.rpc_get_usages(filename,
|
||||
"",
|
||||
0)
|
||||
|
||||
self.assertEqual(usages, [])
|
||||
|
||||
|
||||
def source_and_offset(source):
|
||||
"""Return a source and offset from a source description.
|
||||
|
||||
>>> source_and_offset("hello, _|_world")
|
||||
("hello, world", 7)
|
||||
>>> source_and_offset("_|_hello, world")
|
||||
("hello, world", 0)
|
||||
>>> source_and_offset("hello, world_|_")
|
||||
("hello, world", 12)
|
||||
"""
|
||||
offset = source.index("_|_")
|
||||
return source[:offset] + source[offset + 3:], offset
|
||||
20
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_auto_pep8.py
Normal file
20
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_auto_pep8.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""Tests for the elpy.autopep8 module"""
|
||||
|
||||
import unittest
|
||||
|
||||
from elpy import auto_pep8
|
||||
from elpy.tests.support import BackendTestCase
|
||||
|
||||
|
||||
class Autopep8TestCase(BackendTestCase):
|
||||
|
||||
def setUp(self):
|
||||
if not auto_pep8.autopep8:
|
||||
raise unittest.SkipTest
|
||||
|
||||
def test_fix_code(self):
|
||||
code_block = 'x= 123\n'
|
||||
new_block = auto_pep8.fix_code(code_block)
|
||||
self.assertEqual(new_block, 'x = 123\n')
|
||||
73
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_impmagic.py
Normal file
73
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_impmagic.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""Tests for the elpy.impmagic module"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from elpy import impmagic
|
||||
from elpy.tests.support import BackendTestCase
|
||||
|
||||
TEST_SOURCE = '''# test file
|
||||
|
||||
import time
|
||||
import logging
|
||||
|
||||
os.getcwd()
|
||||
time.sleep(1)
|
||||
'''
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info >= (3, 5), "importmagic fails in 3.5")
|
||||
class ImportMagicTestCase(BackendTestCase):
|
||||
def setUp(self):
|
||||
if not impmagic.importmagic:
|
||||
raise unittest.SkipTest
|
||||
self.importmagic = impmagic.ImportMagic()
|
||||
super(ImportMagicTestCase, self).setUp()
|
||||
|
||||
def build_index(self):
|
||||
self.project_file('mymod.py', 'class AnUncommonName:\n pass\n')
|
||||
self.importmagic.build_index(self.project_root,
|
||||
custom_path=[self.project_root],
|
||||
blacklist_re=re.compile('^$'))
|
||||
self.importmagic._thread.join()
|
||||
|
||||
def test_get_symbols(self):
|
||||
self.build_index()
|
||||
candidates = self.importmagic.get_import_symbols('AnUncommonName')
|
||||
self.assertEqual(candidates, ['from mymod import AnUncommonName'])
|
||||
candidates = self.importmagic.get_import_symbols('mymod')
|
||||
self.assertEqual(candidates, ['import mymod'])
|
||||
|
||||
def test_add_import(self):
|
||||
self.build_index()
|
||||
start, end, newblock = self.importmagic.add_import(
|
||||
TEST_SOURCE, 'from mymod import AnUncommonName')
|
||||
self.assertEqual(start, 2)
|
||||
self.assertEqual(end, 5)
|
||||
self.assertEqual(newblock.strip(),
|
||||
'import logging\n'
|
||||
'import time\n'
|
||||
'from mymod import AnUncommonName')
|
||||
|
||||
start, end, newblock = self.importmagic.add_import(
|
||||
TEST_SOURCE, 'import mymod')
|
||||
self.assertEqual(start, 2)
|
||||
self.assertEqual(end, 5)
|
||||
self.assertEqual(newblock.strip(),
|
||||
'import logging\nimport mymod\nimport time')
|
||||
|
||||
def test_get_unresolved_symbols(self):
|
||||
self.build_index()
|
||||
symbols = self.importmagic.get_unresolved_symbols('x = a + b\ny = c.d')
|
||||
self.assertEqual(sorted(symbols), ['a', 'b', 'c.d'])
|
||||
|
||||
def test_remove_unreferenced_imports(self):
|
||||
self.build_index()
|
||||
start, end, newblock = \
|
||||
self.importmagic.remove_unreferenced_imports(TEST_SOURCE)
|
||||
self.assertEqual(start, 2)
|
||||
self.assertEqual(end, 5)
|
||||
self.assertEqual(newblock.strip(), 'import time')
|
||||
317
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_jedibackend.py
Normal file
317
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_jedibackend.py
Normal file
@@ -0,0 +1,317 @@
|
||||
"""Tests for the elpy.jedibackend module."""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import jedi
|
||||
import mock
|
||||
|
||||
from elpy import jedibackend
|
||||
from elpy import rpc
|
||||
from elpy.tests import compat
|
||||
from elpy.tests.support import BackendTestCase
|
||||
from elpy.tests.support import RPCGetCompletionsTests
|
||||
from elpy.tests.support import RPCGetCompletionDocstringTests
|
||||
from elpy.tests.support import RPCGetCompletionLocationTests
|
||||
from elpy.tests.support import RPCGetDocstringTests
|
||||
from elpy.tests.support import RPCGetDefinitionTests
|
||||
from elpy.tests.support import RPCGetAssignmentTests
|
||||
from elpy.tests.support import RPCGetCalltipTests
|
||||
from elpy.tests.support import RPCGetUsagesTests
|
||||
from elpy.tests.support import RPCGetNamesTests
|
||||
|
||||
|
||||
class JediBackendTestCase(BackendTestCase):
|
||||
def setUp(self):
|
||||
super(JediBackendTestCase, self).setUp()
|
||||
self.backend = jedibackend.JediBackend(self.project_root)
|
||||
|
||||
|
||||
class TestInit(JediBackendTestCase):
|
||||
def test_should_have_jedi_as_name(self):
|
||||
self.assertEqual(self.backend.name, "jedi")
|
||||
|
||||
|
||||
class TestRPCGetCompletions(RPCGetCompletionsTests,
|
||||
JediBackendTestCase):
|
||||
BUILTINS = ['object', 'oct', 'open', 'ord', 'OSError', 'OverflowError']
|
||||
|
||||
|
||||
class TestRPCGetCompletionDocstring(RPCGetCompletionDocstringTests,
|
||||
JediBackendTestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestRPCGetCompletionLocation(RPCGetCompletionLocationTests,
|
||||
JediBackendTestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestRPCGetDocstring(RPCGetDocstringTests,
|
||||
JediBackendTestCase):
|
||||
JSON_LOADS_DOCSTRING = (
|
||||
'loads(s, encoding=None, cls=None, '
|
||||
'object_hook=None, parse_float=None,'
|
||||
)
|
||||
|
||||
def check_docstring(self, docstring):
|
||||
lines = docstring.splitlines()
|
||||
self.assertEqual(lines[0], 'Documentation for json.loads:')
|
||||
self.assertEqual(lines[2], self.JSON_LOADS_DOCSTRING)
|
||||
|
||||
@mock.patch("elpy.jedibackend.run_with_debug")
|
||||
def test_should_not_return_empty_docstring(self, run_with_debug):
|
||||
location = mock.MagicMock()
|
||||
location.full_name = "testthing"
|
||||
location.docstring.return_value = ""
|
||||
run_with_debug.return_value = [location]
|
||||
filename = self.project_file("test.py", "print")
|
||||
docstring = self.backend.rpc_get_docstring(filename, "print", 0)
|
||||
self.assertIsNone(docstring)
|
||||
|
||||
|
||||
class TestRPCGetDefinition(RPCGetDefinitionTests,
|
||||
JediBackendTestCase):
|
||||
@mock.patch("jedi.Script")
|
||||
def test_should_not_fail_if_module_path_is_none(self, Script):
|
||||
"""Do not fail if loc.module_path is None.
|
||||
|
||||
This can happen under some circumstances I am unsure about.
|
||||
See #537 for the issue that reported this.
|
||||
|
||||
"""
|
||||
locations = [
|
||||
mock.Mock(module_path=None)
|
||||
]
|
||||
script = Script.return_value
|
||||
script.goto_definitions.return_value = locations
|
||||
script.goto_assignments.return_value = locations
|
||||
|
||||
location = self.rpc("", "", 0)
|
||||
|
||||
self.assertIsNone(location)
|
||||
|
||||
|
||||
class TestRPCGetAssignment(RPCGetAssignmentTests,
|
||||
JediBackendTestCase):
|
||||
@mock.patch("jedi.Script")
|
||||
def test_should_not_fail_if_module_path_is_none(self, Script):
|
||||
"""Do not fail if loc.module_path is None.
|
||||
|
||||
"""
|
||||
locations = [
|
||||
mock.Mock(module_path=None)
|
||||
]
|
||||
script = Script.return_value
|
||||
script.goto_assignments.return_value = locations
|
||||
script.goto_assignments.return_value = locations
|
||||
|
||||
location = self.rpc("", "", 0)
|
||||
|
||||
self.assertIsNone(location)
|
||||
|
||||
|
||||
class TestRPCGetCalltip(RPCGetCalltipTests,
|
||||
JediBackendTestCase):
|
||||
KEYS_CALLTIP = {'index': 0,
|
||||
'params': ['param '],
|
||||
'name': u'keys'}
|
||||
RADIX_CALLTIP = {'index': None,
|
||||
'params': [],
|
||||
'name': u'radix'}
|
||||
ADD_CALLTIP = {'index': 0,
|
||||
'params': [u'param a', u'param b'],
|
||||
'name': u'add'}
|
||||
if compat.PYTHON3:
|
||||
THREAD_CALLTIP = {"name": "Thread",
|
||||
"params": ["group=None",
|
||||
"target=None",
|
||||
"name=None",
|
||||
"args=()",
|
||||
"kwargs=None",
|
||||
"daemon=None"],
|
||||
"index": 0}
|
||||
else:
|
||||
THREAD_CALLTIP = {"name": "Thread",
|
||||
"params": ["param group=None",
|
||||
"param target=None",
|
||||
"param name=None",
|
||||
"param args=()",
|
||||
"param kwargs=None",
|
||||
"param verbose=None"],
|
||||
"index": 0}
|
||||
|
||||
def test_should_not_fail_with_get_subscope_by_name(self):
|
||||
# Bug #677 / jedi#628
|
||||
source = (
|
||||
u"my_lambda = lambda x: x+1\n"
|
||||
u"my_lambda(1)"
|
||||
)
|
||||
filename = self.project_file("project.py", source)
|
||||
offset = 37
|
||||
|
||||
sigs = self.backend.rpc_get_calltip(filename, source, offset)
|
||||
sigs["index"]
|
||||
|
||||
|
||||
class TestRPCGetUsages(RPCGetUsagesTests,
|
||||
JediBackendTestCase):
|
||||
def test_should_not_fail_for_missing_module(self):
|
||||
# This causes use.module_path to be None
|
||||
source = "import sys\n\nsys.path.\n" # insert()"
|
||||
offset = 21
|
||||
filename = self.project_file("project.py", source)
|
||||
|
||||
self.rpc(filename, source, offset)
|
||||
|
||||
|
||||
class TestRPCGetNames(RPCGetNamesTests,
|
||||
JediBackendTestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestPosToLinecol(unittest.TestCase):
|
||||
def test_should_handle_beginning_of_string(self):
|
||||
self.assertEqual(jedibackend.pos_to_linecol("foo", 0),
|
||||
(1, 0))
|
||||
|
||||
def test_should_handle_end_of_line(self):
|
||||
self.assertEqual(jedibackend.pos_to_linecol("foo\nbar\nbaz\nqux", 9),
|
||||
(3, 1))
|
||||
|
||||
def test_should_handle_end_of_string(self):
|
||||
self.assertEqual(jedibackend.pos_to_linecol("foo\nbar\nbaz\nqux", 14),
|
||||
(4, 2))
|
||||
|
||||
|
||||
class TestLinecolToPos(unittest.TestCase):
|
||||
def test_should_handle_beginning_of_string(self):
|
||||
self.assertEqual(jedibackend.linecol_to_pos("foo", 1, 0),
|
||||
0)
|
||||
|
||||
def test_should_handle_end_of_string(self):
|
||||
self.assertEqual(jedibackend.linecol_to_pos("foo\nbar\nbaz\nqux",
|
||||
3, 1),
|
||||
9)
|
||||
|
||||
def test_should_return_offset(self):
|
||||
self.assertEqual(jedibackend.linecol_to_pos("foo\nbar\nbaz\nqux",
|
||||
4, 2),
|
||||
14)
|
||||
|
||||
def test_should_fail_for_line_past_text(self):
|
||||
self.assertRaises(ValueError,
|
||||
jedibackend.linecol_to_pos, "foo\n", 3, 1)
|
||||
|
||||
def test_should_fail_for_column_past_text(self):
|
||||
self.assertRaises(ValueError,
|
||||
jedibackend.linecol_to_pos, "foo\n", 1, 10)
|
||||
|
||||
|
||||
class TestRunWithDebug(unittest.TestCase):
|
||||
@mock.patch('jedi.Script')
|
||||
def test_should_call_method(self, Script):
|
||||
Script.return_value.test_method.return_value = "test-result"
|
||||
|
||||
result = jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)
|
||||
|
||||
Script.assert_called_with(1, 2, arg=3)
|
||||
self.assertEqual(result, 'test-result')
|
||||
|
||||
@mock.patch('jedi.Script')
|
||||
def test_should_re_raise(self, Script):
|
||||
Script.side_effect = RuntimeError
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3,
|
||||
re_raise=(RuntimeError,))
|
||||
|
||||
@mock.patch('jedi.Script')
|
||||
@mock.patch('jedi.set_debug_function')
|
||||
def test_should_keep_debug_info(self, set_debug_function, Script):
|
||||
Script.side_effect = RuntimeError
|
||||
|
||||
try:
|
||||
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)
|
||||
except rpc.Fault as e:
|
||||
self.assertGreaterEqual(e.code, 400)
|
||||
self.assertIsNotNone(e.data)
|
||||
self.assertIn("traceback", e.data)
|
||||
jedi_debug_info = e.data["jedi_debug_info"]
|
||||
self.assertIsNotNone(jedi_debug_info)
|
||||
self.assertEqual(jedi_debug_info["script_args"],
|
||||
"1, 2, arg=3")
|
||||
self.assertEqual(jedi_debug_info["source"], None)
|
||||
self.assertEqual(jedi_debug_info["method"], "test_method")
|
||||
self.assertEqual(jedi_debug_info["debug_info"], [])
|
||||
else:
|
||||
self.fail("Fault not thrown")
|
||||
|
||||
@mock.patch('jedi.Script')
|
||||
@mock.patch('jedi.set_debug_function')
|
||||
def test_should_keep_error_text(self, set_debug_function, Script):
|
||||
Script.side_effect = RuntimeError
|
||||
|
||||
try:
|
||||
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)
|
||||
except rpc.Fault as e:
|
||||
self.assertEqual(str(e), str(RuntimeError()))
|
||||
self.assertEqual(e.message, str(RuntimeError()))
|
||||
else:
|
||||
self.fail("Fault not thrown")
|
||||
|
||||
@mock.patch('jedi.Script')
|
||||
@mock.patch('jedi.set_debug_function')
|
||||
def test_should_handle_source_special(self, set_debug_function, Script):
|
||||
Script.side_effect = RuntimeError
|
||||
|
||||
try:
|
||||
jedibackend.run_with_debug(jedi, 'test_method', source="foo")
|
||||
except rpc.Fault as e:
|
||||
self.assertEqual(e.data["jedi_debug_info"]["script_args"],
|
||||
"source=source")
|
||||
self.assertEqual(e.data["jedi_debug_info"]["source"], "foo")
|
||||
else:
|
||||
self.fail("Fault not thrown")
|
||||
|
||||
@mock.patch('jedi.Script')
|
||||
@mock.patch('jedi.set_debug_function')
|
||||
def test_should_set_debug_info(self, set_debug_function, Script):
|
||||
the_debug_function = [None]
|
||||
|
||||
def my_set_debug_function(debug_function, **kwargs):
|
||||
the_debug_function[0] = debug_function
|
||||
|
||||
def my_script(*args, **kwargs):
|
||||
the_debug_function[0](jedi.debug.NOTICE, "Notice")
|
||||
the_debug_function[0](jedi.debug.WARNING, "Warning")
|
||||
the_debug_function[0]("other", "Other")
|
||||
raise RuntimeError
|
||||
|
||||
set_debug_function.side_effect = my_set_debug_function
|
||||
Script.return_value.test_method = my_script
|
||||
|
||||
try:
|
||||
jedibackend.run_with_debug(jedi, 'test_method', source="foo")
|
||||
except rpc.Fault as e:
|
||||
self.assertEqual(e.data["jedi_debug_info"]["debug_info"],
|
||||
["[N] Notice",
|
||||
"[W] Warning",
|
||||
"[?] Other"])
|
||||
else:
|
||||
self.fail("Fault not thrown")
|
||||
|
||||
@mock.patch('jedi.set_debug_function')
|
||||
@mock.patch('jedi.Script')
|
||||
def test_should_not_fail_with_bad_data(self, Script, set_debug_function):
|
||||
import jedi.debug
|
||||
|
||||
def set_debug(function, speed=True):
|
||||
if function is not None:
|
||||
function(jedi.debug.NOTICE, u"\xab")
|
||||
|
||||
set_debug_function.side_effect = set_debug
|
||||
Script.return_value.test_method.side_effect = Exception
|
||||
|
||||
with self.assertRaises(rpc.Fault):
|
||||
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)
|
||||
@@ -0,0 +1,88 @@
|
||||
import os
|
||||
import unittest
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import mock
|
||||
|
||||
import elpy.pydocutils
|
||||
|
||||
|
||||
class TestGetPydocCompletions(unittest.TestCase):
|
||||
def test_should_return_top_level_modules(self):
|
||||
modules = elpy.pydocutils.get_pydoc_completions("")
|
||||
self.assertIn('sys', modules)
|
||||
self.assertIn('json', modules)
|
||||
|
||||
def test_should_return_submodules(self):
|
||||
modules = elpy.pydocutils.get_pydoc_completions("elpy")
|
||||
self.assertIn("elpy.rpc", modules)
|
||||
self.assertIn("elpy.server", modules)
|
||||
modules = elpy.pydocutils.get_pydoc_completions("os")
|
||||
self.assertIn("os.path", modules)
|
||||
|
||||
def test_should_find_objects_in_module(self):
|
||||
self.assertIn("elpy.tests.test_pydocutils.TestGetPydocCompletions",
|
||||
elpy.pydocutils.get_pydoc_completions
|
||||
("elpy.tests.test_pydocutils"))
|
||||
|
||||
def test_should_find_attributes_of_objects(self):
|
||||
attribs = elpy.pydocutils.get_pydoc_completions(
|
||||
"elpy.tests.test_pydocutils.TestGetPydocCompletions")
|
||||
self.assertIn("elpy.tests.test_pydocutils.TestGetPydocCompletions."
|
||||
"test_should_find_attributes_of_objects",
|
||||
attribs)
|
||||
|
||||
def test_should_return_none_for_inexisting_module(self):
|
||||
self.assertEqual([],
|
||||
elpy.pydocutils.get_pydoc_completions
|
||||
("does_not_exist"))
|
||||
|
||||
def test_should_work_for_unicode_strings(self):
|
||||
self.assertIsNotNone(elpy.pydocutils.get_pydoc_completions
|
||||
(u"sys"))
|
||||
|
||||
def test_should_find_partial_completions(self):
|
||||
self.assertIn("multiprocessing",
|
||||
elpy.pydocutils.get_pydoc_completions
|
||||
("multiprocess"))
|
||||
self.assertIn("multiprocessing.util",
|
||||
elpy.pydocutils.get_pydoc_completions
|
||||
("multiprocessing.ut"))
|
||||
|
||||
def test_should_ignore_trailing_dot(self):
|
||||
self.assertIn("elpy.pydocutils",
|
||||
elpy.pydocutils.get_pydoc_completions
|
||||
("elpy."))
|
||||
|
||||
|
||||
class TestGetModules(unittest.TestCase):
|
||||
def test_should_return_top_level_modules(self):
|
||||
modules = elpy.pydocutils.get_modules()
|
||||
self.assertIn('sys', modules)
|
||||
self.assertIn('json', modules)
|
||||
|
||||
def test_should_return_submodules(self):
|
||||
modules = elpy.pydocutils.get_modules("elpy")
|
||||
self.assertIn("rpc", modules)
|
||||
self.assertIn("server", modules)
|
||||
|
||||
@mock.patch.object(elpy.pydocutils, 'safeimport')
|
||||
def test_should_catch_import_errors(self, safeimport):
|
||||
def raise_function(message):
|
||||
raise elpy.pydocutils.ErrorDuringImport(message,
|
||||
(None, None, None))
|
||||
safeimport.side_effect = raise_function
|
||||
self.assertEqual([], elpy.pydocutils.get_modules("foo.bar"))
|
||||
|
||||
def test_should_not_fail_for_permission_denied(self):
|
||||
tmpdir = tempfile.mkdtemp(prefix="test-elpy-get-modules-")
|
||||
sys.path.append(tmpdir)
|
||||
os.chmod(tmpdir, 0o000)
|
||||
try:
|
||||
elpy.pydocutils.get_modules()
|
||||
finally:
|
||||
os.chmod(tmpdir, 0o755)
|
||||
shutil.rmtree(tmpdir)
|
||||
sys.path.remove(tmpdir)
|
||||
545
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_refactor.py
Normal file
545
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_refactor.py
Normal file
@@ -0,0 +1,545 @@
|
||||
import unittest
|
||||
import tempfile
|
||||
import shutil
|
||||
import os
|
||||
import mock
|
||||
import sys
|
||||
|
||||
from elpy import refactor
|
||||
from textwrap import dedent
|
||||
|
||||
|
||||
class RefactorTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.project_root = tempfile.mkdtemp(prefix="test-refactor-root")
|
||||
self.addCleanup(shutil.rmtree, self.project_root,
|
||||
ignore_errors=True)
|
||||
|
||||
def create_file(self, name, contents=""):
|
||||
filename = os.path.join(self.project_root, name)
|
||||
contents = dedent(contents)
|
||||
offset = contents.find("_|_")
|
||||
if offset > -1:
|
||||
contents = contents[:offset] + contents[offset + 3:]
|
||||
with open(filename, "w") as f:
|
||||
f.write(contents)
|
||||
return filename, offset
|
||||
|
||||
def assertSourceEqual(self, first, second, msg=None):
|
||||
"""Fail if the two objects are unequal, ignoring indentation."""
|
||||
self.assertEqual(dedent(first), dedent(second), msg=msg)
|
||||
|
||||
|
||||
class TestGetRefactorOptions(RefactorTestCase):
|
||||
def test_should_only_return_importsmodule_if_not_on_symbol(self):
|
||||
filename, offset = self.create_file("foo.py",
|
||||
"""\
|
||||
import foo
|
||||
_|_""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
options = ref.get_refactor_options(offset)
|
||||
self.assertTrue(all(opt['category'] in ('Imports',
|
||||
'Module')
|
||||
for opt in options))
|
||||
filename, offset = self.create_file("foo.py",
|
||||
"""\
|
||||
_|_
|
||||
import foo""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
options = ref.get_refactor_options(offset)
|
||||
self.assertTrue(all(opt['category'] in ('Imports',
|
||||
'Module')
|
||||
for opt in options))
|
||||
|
||||
def test_should_return_all_if_on_symbol(self):
|
||||
filename, offset = self.create_file("foo.py",
|
||||
"import _|_foo")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
options = ref.get_refactor_options(offset)
|
||||
self.assertTrue(all(opt['category'] in ('Imports',
|
||||
'Method',
|
||||
'Module',
|
||||
'Symbol')
|
||||
for opt in options))
|
||||
|
||||
def test_should_return_only_region_if_endoffset(self):
|
||||
filename, offset = self.create_file("foo.py",
|
||||
"import foo")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
options = ref.get_refactor_options(offset, 5)
|
||||
self.assertTrue(all(opt['category'] == 'Region'
|
||||
for opt in options))
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
def test_should_treat_from_import_special(self):
|
||||
filename, offset = self.create_file("foo.py",
|
||||
"""\
|
||||
import foo
|
||||
_|_""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
options = ref.get_refactor_options(offset)
|
||||
self.assertFalse(any(opt['name'] == "refactor_froms_to_imports"
|
||||
for opt in options))
|
||||
filename, offset = self.create_file("foo.py",
|
||||
"imp_|_ort foo")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
options = ref.get_refactor_options(offset)
|
||||
self.assertTrue(any(opt['name'] == "refactor_froms_to_imports"
|
||||
for opt in options))
|
||||
|
||||
|
||||
class TestGetChanges(RefactorTestCase):
|
||||
def test_should_fail_if_method_is_not_refactoring(self):
|
||||
filename, offset = self.create_file("foo.py")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
self.assertRaises(ValueError, ref.get_changes, "bad_name")
|
||||
|
||||
def test_should_return_method_results(self):
|
||||
filename, offset = self.create_file("foo.py")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
with mock.patch.object(ref, 'refactor_extract_method') as test:
|
||||
test.return_value = "Meep!"
|
||||
self.assertEqual(ref.get_changes("refactor_extract_method",
|
||||
1, 2),
|
||||
"Meep!")
|
||||
test.assert_called_with(1, 2)
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestIsOnSymbol(RefactorTestCase):
|
||||
def test_should_find_symbol(self):
|
||||
filename, offset = self.create_file("test.py", "__B_|_AR = 100")
|
||||
r = refactor.Refactor(self.project_root, filename)
|
||||
self.assertTrue(r._is_on_symbol(offset))
|
||||
|
||||
# Issue #111
|
||||
def test_should_find_symbol_with_underscores(self):
|
||||
filename, offset = self.create_file("test.py", "_|___BAR = 100")
|
||||
r = refactor.Refactor(self.project_root, filename)
|
||||
self.assertTrue(r._is_on_symbol(offset))
|
||||
|
||||
def test_should_not_find_weird_places(self):
|
||||
filename, offset = self.create_file("test.py", "hello = _|_ 1 + 1")
|
||||
r = refactor.Refactor(self.project_root, filename)
|
||||
self.assertFalse(r._is_on_symbol(offset))
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestFromsToImports(RefactorTestCase):
|
||||
def test_should_refactor(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
_|_from datetime import datetime
|
||||
|
||||
d = datetime(2013, 4, 7)
|
||||
""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
(change,) = ref.get_changes("refactor_froms_to_imports", offset)
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], filename)
|
||||
self.assertSourceEqual(change['contents'],
|
||||
"""\
|
||||
import datetime
|
||||
|
||||
d = datetime.datetime(2013, 4, 7)
|
||||
""")
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestOrganizeImports(RefactorTestCase):
|
||||
def test_should_refactor(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
import unittest, base64
|
||||
import datetime, json
|
||||
|
||||
obj = json.dumps(23)
|
||||
unittest.TestCase()
|
||||
""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
(change,) = ref.get_changes("refactor_organize_imports")
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], filename)
|
||||
self.assertSourceEqual(change['contents'],
|
||||
"""\
|
||||
import json
|
||||
import unittest
|
||||
|
||||
|
||||
obj = json.dumps(23)
|
||||
unittest.TestCase()
|
||||
""")
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestModuleToPackage(RefactorTestCase):
|
||||
def test_should_refactor(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"_|_import os\n")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
changes = ref.refactor_module_to_package()
|
||||
a, b, c = changes
|
||||
# Not sure why the a change is there. It's a CHANGE that
|
||||
# changes nothing...
|
||||
self.assertEqual(a['diff'], '')
|
||||
|
||||
self.assertEqual(b['action'], 'create')
|
||||
self.assertEqual(b['type'], 'directory')
|
||||
self.assertEqual(b['path'], os.path.join(self.project_root, "foo"))
|
||||
|
||||
self.assertEqual(c['action'], 'move')
|
||||
self.assertEqual(c['type'], 'file')
|
||||
self.assertEqual(c['source'], os.path.join(self.project_root,
|
||||
"foo.py"))
|
||||
self.assertEqual(c['destination'], os.path.join(self.project_root,
|
||||
"foo/__init__.py"))
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestRenameAtPoint(RefactorTestCase):
|
||||
def test_should_refactor(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
class Foo(object):
|
||||
def _|_foo(self):
|
||||
return 5
|
||||
|
||||
def bar(self):
|
||||
return self.foo()
|
||||
""")
|
||||
file2, offset2 = self.create_file(
|
||||
"bar.py",
|
||||
"""\
|
||||
import foo
|
||||
|
||||
|
||||
x = foo.Foo()
|
||||
x.foo()""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
first, second = ref.refactor_rename_at_point(offset, "frob",
|
||||
in_hierarchy=False,
|
||||
docs=False)
|
||||
if first['file'] == filename:
|
||||
a, b = first, second
|
||||
else:
|
||||
a, b = second, first
|
||||
self.assertEqual(a['action'], 'change')
|
||||
self.assertEqual(a['file'], filename)
|
||||
self.assertSourceEqual(a['contents'],
|
||||
"""\
|
||||
class Foo(object):
|
||||
def frob(self):
|
||||
return 5
|
||||
|
||||
def bar(self):
|
||||
return self.frob()
|
||||
""")
|
||||
self.assertEqual(b['action'], 'change')
|
||||
self.assertEqual(b['file'], file2)
|
||||
self.assertSourceEqual(b['contents'],
|
||||
"""\
|
||||
import foo
|
||||
|
||||
|
||||
x = foo.Foo()
|
||||
x.frob()""")
|
||||
|
||||
def test_should_refactor_in_hierarchy(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
class Foo(object):
|
||||
def _|_foo(self):
|
||||
return 5
|
||||
|
||||
def bar(self):
|
||||
return self.foo()
|
||||
|
||||
class Bar(Foo):
|
||||
def foo(self):
|
||||
return 42
|
||||
|
||||
class Baz(object):
|
||||
def foo(self):
|
||||
return 42
|
||||
""")
|
||||
file2, offset2 = self.create_file(
|
||||
"bar.py",
|
||||
"""\
|
||||
import foo
|
||||
|
||||
|
||||
x, y, z = foo.Foo(), foo.Bar(), foo.Baz()
|
||||
x.foo()
|
||||
y.foo()
|
||||
z.foo()""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
first, second = ref.refactor_rename_at_point(offset, "frob",
|
||||
in_hierarchy=True,
|
||||
docs=False)
|
||||
if first['file'] == filename:
|
||||
a, b = first, second
|
||||
else:
|
||||
a, b = second, first
|
||||
self.assertEqual(a['action'], 'change')
|
||||
self.assertEqual(a['file'], filename)
|
||||
self.assertSourceEqual(a['contents'],
|
||||
"""\
|
||||
class Foo(object):
|
||||
def frob(self):
|
||||
return 5
|
||||
|
||||
def bar(self):
|
||||
return self.frob()
|
||||
|
||||
class Bar(Foo):
|
||||
def frob(self):
|
||||
return 42
|
||||
|
||||
class Baz(object):
|
||||
def foo(self):
|
||||
return 42
|
||||
""")
|
||||
self.assertEqual(b['action'], 'change')
|
||||
self.assertEqual(b['file'], file2)
|
||||
self.assertSourceEqual(b['contents'],
|
||||
"""\
|
||||
import foo
|
||||
|
||||
|
||||
x, y, z = foo.Foo(), foo.Bar(), foo.Baz()
|
||||
x.frob()
|
||||
y.frob()
|
||||
z.foo()""")
|
||||
|
||||
def test_should_refactor_in_docstrings(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
class Foo(object):
|
||||
"Frobnicate the foo"
|
||||
def _|_foo(self):
|
||||
return 5
|
||||
|
||||
print("I'm an unrelated foo")
|
||||
""")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
(change,) = ref.refactor_rename_at_point(offset, "frob",
|
||||
in_hierarchy=False,
|
||||
docs=True)
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], filename)
|
||||
self.assertSourceEqual(change['contents'],
|
||||
"""\
|
||||
class Foo(object):
|
||||
"Frobnicate the frob"
|
||||
def frob(self):
|
||||
return 5
|
||||
|
||||
print("I'm an unrelated foo")
|
||||
""")
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestRenameCurrentModule(RefactorTestCase):
|
||||
def test_should_refactor(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"_|_import os\n")
|
||||
file2, offset = self.create_file(
|
||||
"bar.py",
|
||||
"""\
|
||||
_|_import foo
|
||||
foo.os
|
||||
""")
|
||||
dest = os.path.join(self.project_root, "frob.py")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
a, b = ref.refactor_rename_current_module("frob")
|
||||
|
||||
self.assertEqual(a['action'], 'change')
|
||||
self.assertEqual(a['file'], file2)
|
||||
self.assertEqual(a['contents'],
|
||||
"import frob\n"
|
||||
"frob.os\n")
|
||||
|
||||
self.assertEqual(b['action'], 'move')
|
||||
self.assertEqual(b['type'], 'file')
|
||||
self.assertEqual(b['source'], filename)
|
||||
self.assertEqual(b['destination'], dest)
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestMoveModule(RefactorTestCase):
|
||||
def test_should_refactor(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"_|_import os\n")
|
||||
file2, offset = self.create_file(
|
||||
"bar.py",
|
||||
"""\
|
||||
_|_import foo
|
||||
foo.os
|
||||
""")
|
||||
dest = os.path.join(self.project_root, "frob")
|
||||
os.mkdir(dest)
|
||||
with open(os.path.join(dest, "__init__.py"), "w") as f:
|
||||
f.write("")
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
a, b = ref.refactor_move_module(dest)
|
||||
|
||||
self.assertEqual(a['action'], 'change')
|
||||
self.assertEqual(a['file'], file2)
|
||||
self.assertSourceEqual(a['contents'],
|
||||
"""\
|
||||
import frob.foo
|
||||
frob.foo.os
|
||||
""")
|
||||
|
||||
self.assertEqual(b['action'], 'move')
|
||||
self.assertEqual(b['type'], 'file')
|
||||
self.assertEqual(b['source'], filename)
|
||||
self.assertEqual(b['destination'],
|
||||
os.path.join(dest, "foo.py"))
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestCreateInline(RefactorTestCase):
|
||||
def setUp(self):
|
||||
super(TestCreateInline, self).setUp()
|
||||
self.filename, self.offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
def add(a, b):
|
||||
return a + b
|
||||
|
||||
x = _|_add(2, 3)
|
||||
y = add(17, 4)
|
||||
""")
|
||||
|
||||
def test_should_refactor_single_occurrenc(self):
|
||||
ref = refactor.Refactor(self.project_root, self.filename)
|
||||
(change,) = ref.refactor_create_inline(self.offset, True)
|
||||
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], self.filename)
|
||||
self.assertSourceEqual(change['contents'],
|
||||
"""\
|
||||
def add(a, b):
|
||||
return a + b
|
||||
|
||||
x = 2 + 3
|
||||
y = add(17, 4)
|
||||
""")
|
||||
|
||||
def test_should_refactor_all_occurrencs(self):
|
||||
ref = refactor.Refactor(self.project_root, self.filename)
|
||||
(change,) = ref.refactor_create_inline(self.offset, False)
|
||||
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], self.filename)
|
||||
self.assertSourceEqual(change['contents'],
|
||||
"""\
|
||||
x = 2 + 3
|
||||
y = 17 + 4
|
||||
""")
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestExtractMethod(RefactorTestCase):
|
||||
def setUp(self):
|
||||
super(TestExtractMethod, self).setUp()
|
||||
self.filename, self.offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
class Foo(object):
|
||||
def spaghetti(self, a, b):
|
||||
_|_x = a + 5
|
||||
y = b + 23
|
||||
return y
|
||||
""")
|
||||
|
||||
@unittest.skipIf(sys.version_info >= (3, 5), "Python 3.5 not supported")
|
||||
def test_should_refactor_local(self):
|
||||
ref = refactor.Refactor(self.project_root, self.filename)
|
||||
(change,) = ref.refactor_extract_method(self.offset, 104,
|
||||
"calc", False)
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], self.filename)
|
||||
expected = """\
|
||||
class Foo(object):
|
||||
def spaghetti(self, a, b):
|
||||
return self.calc(a, b)
|
||||
|
||||
def calc(self, a, b):
|
||||
x = a + 5
|
||||
y = b + 23
|
||||
return y
|
||||
"""
|
||||
expected2 = expected.replace("return self.calc(a, b)",
|
||||
"return self.calc(b, a)")
|
||||
expected2 = expected2.replace("def calc(self, a, b)",
|
||||
"def calc(self, b, a)")
|
||||
# This is silly, but it's what we got.
|
||||
if change['contents'] == dedent(expected2):
|
||||
self.assertSourceEqual(change['contents'], expected2)
|
||||
else:
|
||||
self.assertSourceEqual(change['contents'], expected)
|
||||
|
||||
@unittest.skipIf(sys.version_info >= (3, 5), "Python 3.5 not supported")
|
||||
def test_should_refactor_global(self):
|
||||
ref = refactor.Refactor(self.project_root, self.filename)
|
||||
(change,) = ref.refactor_extract_method(self.offset, 104,
|
||||
"calc", True)
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], self.filename)
|
||||
expected = """\
|
||||
class Foo(object):
|
||||
def spaghetti(self, a, b):
|
||||
return calc(a, b)
|
||||
|
||||
def calc(a, b):
|
||||
x = a + 5
|
||||
y = b + 23
|
||||
return y
|
||||
"""
|
||||
expected2 = expected.replace("return calc(a, b)",
|
||||
"return calc(b, a)")
|
||||
expected2 = expected2.replace("def calc(a, b)",
|
||||
"def calc(b, a)")
|
||||
if change['contents'] == dedent(expected2):
|
||||
self.assertSourceEqual(change['contents'], expected2)
|
||||
else:
|
||||
self.assertSourceEqual(change['contents'], expected)
|
||||
|
||||
|
||||
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
|
||||
class TestUseFunction(RefactorTestCase):
|
||||
def test_should_refactor(self):
|
||||
filename, offset = self.create_file(
|
||||
"foo.py",
|
||||
"""\
|
||||
def _|_add_and_multiply(a, b, c):
|
||||
temp = a + b
|
||||
return temp * c
|
||||
|
||||
f = 1 + 2
|
||||
g = f * 3
|
||||
""")
|
||||
|
||||
ref = refactor.Refactor(self.project_root, filename)
|
||||
(change,) = ref.refactor_use_function(offset)
|
||||
|
||||
self.assertEqual(change['action'], 'change')
|
||||
self.assertEqual(change['file'], filename)
|
||||
self.assertSourceEqual(change['contents'],
|
||||
"""\
|
||||
def add_and_multiply(a, b, c):
|
||||
temp = a + b
|
||||
return temp * c
|
||||
|
||||
g = add_and_multiply(1, 2, 3)
|
||||
""")
|
||||
205
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_ropebackend.py
Normal file
205
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_ropebackend.py
Normal file
@@ -0,0 +1,205 @@
|
||||
"""Tests for elpy.ropebackend."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import mock
|
||||
|
||||
from elpy import ropebackend
|
||||
from elpy import rpc
|
||||
from elpy.tests import compat
|
||||
from elpy.tests.support import BackendTestCase
|
||||
from elpy.tests.support import RPCGetCompletionsTests
|
||||
from elpy.tests.support import RPCGetCompletionDocstringTests
|
||||
from elpy.tests.support import RPCGetCompletionLocationTests
|
||||
from elpy.tests.support import RPCGetDefinitionTests
|
||||
from elpy.tests.support import RPCGetCalltipTests
|
||||
from elpy.tests.support import RPCGetDocstringTests
|
||||
|
||||
|
||||
class RopeBackendTestCase(BackendTestCase):
|
||||
def setUp(self):
|
||||
super(RopeBackendTestCase, self).setUp()
|
||||
self.backend = ropebackend.RopeBackend(self.project_root)
|
||||
|
||||
|
||||
class ShouldCallValidateTest(object):
|
||||
def test_should_call_validate(self):
|
||||
with mock.patch.object(self.backend, 'validate') as validate:
|
||||
self.rpc(None, "", 0)
|
||||
|
||||
self.assertTrue(validate.called)
|
||||
|
||||
|
||||
class TestInit(RopeBackendTestCase):
|
||||
def test_should_have_rope_as_name(self):
|
||||
self.assertEqual(self.backend.name, "rope")
|
||||
|
||||
def test_should_patch_project_files(self):
|
||||
self.project_file("foo.txt", "")
|
||||
self.project_file("baddir/file.py", "")
|
||||
|
||||
self.backend.project.validate()
|
||||
|
||||
actual = [f.real_path for f in
|
||||
self.backend.project.file_list.get_files()]
|
||||
self.assertEqual([os.path.join(self.project_root, "foo.txt")],
|
||||
actual)
|
||||
|
||||
def test_should_fail_for_inexisting_project_root(self):
|
||||
with self.assertRaises(rpc.Fault):
|
||||
ropebackend.RopeBackend("/does/not/exist/")
|
||||
|
||||
|
||||
class TestValidate(RopeBackendTestCase):
|
||||
def test_should_call_validate_after_timeout(self):
|
||||
with mock.patch("time.time") as t:
|
||||
t.return_value = 10
|
||||
self.backend.validate()
|
||||
with mock.patch.object(self.backend, 'project') as project:
|
||||
t.return_value = 10 + ropebackend.VALIDATE_EVERY_SECONDS + 1
|
||||
self.backend.validate()
|
||||
|
||||
self.assertTrue(project.validate.called)
|
||||
|
||||
def test_should_not_call_validate_before_timeout(self):
|
||||
with mock.patch("time.time") as t:
|
||||
t.return_value = 10
|
||||
self.backend.validate()
|
||||
with mock.patch.object(self.backend, 'project') as project:
|
||||
t.return_value = 10 + ropebackend.VALIDATE_EVERY_SECONDS - 1
|
||||
self.backend.validate()
|
||||
|
||||
self.assertFalse(project.validate.called)
|
||||
|
||||
def test_should_not_fail_if_root_vanishes(self):
|
||||
# Bug #353
|
||||
tmpdir = tempfile.mkdtemp(prefix="elpy-test-validate-")
|
||||
try:
|
||||
backend = ropebackend.RopeBackend(tmpdir)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
backend.validate()
|
||||
|
||||
|
||||
class TestRPCGetCompletions(RPCGetCompletionsTests,
|
||||
RopeBackendTestCase):
|
||||
BUILTINS = ["object", "oct", "open", "or", "ord"]
|
||||
|
||||
|
||||
class TestRPCGetCompletionDocstring(RPCGetCompletionDocstringTests,
|
||||
RopeBackendTestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestRPCGetCompletionLocation(RPCGetCompletionLocationTests,
|
||||
RopeBackendTestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestRPCGetDefinition(RPCGetDefinitionTests,
|
||||
ShouldCallValidateTest,
|
||||
RopeBackendTestCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestRPCGetCalltip(RPCGetCalltipTests,
|
||||
ShouldCallValidateTest,
|
||||
RopeBackendTestCase):
|
||||
ADD_CALLTIP = 'Add.add(a, b)'
|
||||
RADIX_CALLTIP = "Decimal.radix()"
|
||||
if compat.PYTHON3:
|
||||
THREAD_CALLTIP = (
|
||||
"threading.Thread(group=None, target=None, "
|
||||
"name=None, args=(), kwargs=None, daemon=None, *)"
|
||||
)
|
||||
KEYS_CALLTIP = "builtins.keys()"
|
||||
else:
|
||||
THREAD_CALLTIP = (
|
||||
"threading.Thread(group=None, target=None, "
|
||||
"name=None, args=(), kwargs=None, verbose=None)"
|
||||
)
|
||||
KEYS_CALLTIP = "__builtin__.keys()"
|
||||
|
||||
|
||||
class TestRPCGetDocstring(RPCGetDocstringTests,
|
||||
ShouldCallValidateTest,
|
||||
RopeBackendTestCase):
|
||||
if sys.version_info < (2, 7):
|
||||
JSON_LOADS_DOCSTRING = (
|
||||
'loads(s, encoding=None, cls=None, object_hook=None, '
|
||||
'parse_float=None, parse_int=None, parse_constant=None, '
|
||||
'**kw):'
|
||||
)
|
||||
else:
|
||||
JSON_LOADS_DOCSTRING = (
|
||||
'loads(s, encoding=None, cls=None, object_hook=None, '
|
||||
'parse_float=None, parse_int=None, parse_constant=None, '
|
||||
'object_pairs_hook=None, **kw):'
|
||||
)
|
||||
|
||||
|
||||
class TestGetPythonProjectFiles(RopeBackendTestCase):
|
||||
def test(self):
|
||||
self.project_file("foo.txt", "")
|
||||
self.project_file("gooddir/__init__.py", "")
|
||||
self.project_file("gooddir/file.py", "")
|
||||
self.project_file("baddir/file.py", "")
|
||||
expected = set(os.path.join(self.project_root, name)
|
||||
for name in ["foo.txt", "gooddir/__init__.py",
|
||||
"gooddir/file.py"])
|
||||
project = self.backend.project
|
||||
|
||||
actual = set(resource.real_path
|
||||
for resource
|
||||
in ropebackend.get_python_project_files(project))
|
||||
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
|
||||
class TestPatchProjectFiles(RopeBackendTestCase):
|
||||
def test(self):
|
||||
self.project_file("foo.txt", "")
|
||||
self.project_file("gooddir/__init__.py", "")
|
||||
self.project_file("gooddir/file.py", "")
|
||||
self.project_file("baddir/file.py", "")
|
||||
expected = set(os.path.join(self.project_root, name)
|
||||
for name in ["foo.txt", "gooddir/__init__.py",
|
||||
"gooddir/file.py"])
|
||||
|
||||
actual = set(resource.real_path
|
||||
for resource
|
||||
in self.backend.project.get_files())
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
|
||||
class TestCallRope(RopeBackendTestCase):
|
||||
def test_should_return_value(self):
|
||||
func = mock.MagicMock()
|
||||
func.return_value = 23
|
||||
|
||||
actual = self.backend.call_rope(
|
||||
func, "foo.py", "", 0
|
||||
)
|
||||
|
||||
self.assertEqual(23, actual)
|
||||
|
||||
def test_should_raise_fault_with_data_on_exception(self):
|
||||
func = mock.MagicMock()
|
||||
func.side_effect = RuntimeError("Stuff!")
|
||||
func.__module__ = "rope.test"
|
||||
func.__name__ = "test_function"
|
||||
|
||||
try:
|
||||
self.backend.call_rope(
|
||||
func, "foo.py", "", 0
|
||||
)
|
||||
except rpc.Fault as e:
|
||||
self.assertEqual(500, e.code)
|
||||
self.assertEqual("Stuff!", e.message)
|
||||
self.assertIn("traceback", e.data)
|
||||
self.assertIn("rope_debug_info", e.data)
|
||||
self.assertEqual("rope.test.test_function",
|
||||
e.data["rope_debug_info"]["function_name"])
|
||||
209
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_rpc.py
Normal file
209
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_rpc.py
Normal file
@@ -0,0 +1,209 @@
|
||||
"""Tests for elpy.rpc."""
|
||||
|
||||
import json
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
from elpy import rpc
|
||||
from elpy.tests.compat import StringIO
|
||||
|
||||
|
||||
class TestFault(unittest.TestCase):
|
||||
def test_should_have_code_and_data(self):
|
||||
fault = rpc.Fault("Hello", code=250, data="Fnord")
|
||||
self.assertEqual(str(fault), "Hello")
|
||||
self.assertEqual(fault.code, 250)
|
||||
self.assertEqual(fault.data, "Fnord")
|
||||
|
||||
def test_should_have_defaults_for_code_and_data(self):
|
||||
fault = rpc.Fault("Hello")
|
||||
self.assertEqual(str(fault), "Hello")
|
||||
self.assertEqual(fault.code, 500)
|
||||
self.assertIsNone(fault.data)
|
||||
|
||||
|
||||
class TestJSONRPCServer(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.stdin = StringIO()
|
||||
self.stdout = StringIO()
|
||||
self.rpc = rpc.JSONRPCServer(self.stdin, self.stdout)
|
||||
|
||||
def write(self, s):
|
||||
self.stdin.seek(0)
|
||||
self.stdin.truncate()
|
||||
self.stdout.seek(0)
|
||||
self.stdout.truncate()
|
||||
self.stdin.write(s)
|
||||
self.stdin.seek(0)
|
||||
|
||||
def read(self):
|
||||
value = self.stdout.getvalue()
|
||||
self.stdin.seek(0)
|
||||
self.stdin.truncate()
|
||||
self.stdout.seek(0)
|
||||
self.stdout.truncate()
|
||||
return value
|
||||
|
||||
|
||||
class TestInit(TestJSONRPCServer):
|
||||
def test_should_use_arguments(self):
|
||||
self.assertEqual(self.rpc.stdin, self.stdin)
|
||||
self.assertEqual(self.rpc.stdout, self.stdout)
|
||||
|
||||
def test_should_default_to_sys(self):
|
||||
testrpc = rpc.JSONRPCServer()
|
||||
self.assertEqual(sys.stdin, testrpc.stdin)
|
||||
self.assertEqual(sys.stdout, testrpc.stdout)
|
||||
|
||||
|
||||
class TestReadJson(TestJSONRPCServer):
|
||||
def test_should_read_json(self):
|
||||
objlist = [{'foo': 'bar'},
|
||||
{'baz': 'qux', 'fnord': 'argl\nbargl'},
|
||||
"beep\r\nbeep\r\nbeep"]
|
||||
self.write("".join([(json.dumps(obj) + "\n")
|
||||
for obj in objlist]))
|
||||
for obj in objlist:
|
||||
self.assertEqual(self.rpc.read_json(),
|
||||
obj)
|
||||
|
||||
def test_should_raise_eof_on_eof(self):
|
||||
self.assertRaises(EOFError, self.rpc.read_json)
|
||||
|
||||
def test_should_fail_on_malformed_json(self):
|
||||
self.write("malformed json\n")
|
||||
self.assertRaises(ValueError,
|
||||
self.rpc.read_json)
|
||||
|
||||
|
||||
class TestWriteJson(TestJSONRPCServer):
|
||||
def test_should_write_json_line(self):
|
||||
objlist = [{'foo': 'bar'},
|
||||
{'baz': 'qux', 'fnord': 'argl\nbargl'},
|
||||
]
|
||||
for obj in objlist:
|
||||
self.rpc.write_json(**obj)
|
||||
self.assertEqual(json.loads(self.read()),
|
||||
obj)
|
||||
|
||||
|
||||
class TestHandleRequest(TestJSONRPCServer):
|
||||
def test_should_fail_if_json_does_not_contain_a_method(self):
|
||||
self.write(json.dumps(dict(params=[],
|
||||
id=23)))
|
||||
self.assertRaises(ValueError,
|
||||
self.rpc.handle_request)
|
||||
|
||||
def test_should_call_right_method(self):
|
||||
self.write(json.dumps(dict(method='foo',
|
||||
params=[1, 2, 3],
|
||||
id=23)))
|
||||
self.rpc.rpc_foo = lambda *params: params
|
||||
self.rpc.handle_request()
|
||||
self.assertEqual(json.loads(self.read()),
|
||||
dict(id=23,
|
||||
result=[1, 2, 3]))
|
||||
|
||||
def test_should_pass_defaults_for_missing_parameters(self):
|
||||
def test_method(*params):
|
||||
self.args = params
|
||||
|
||||
self.write(json.dumps(dict(method='foo')))
|
||||
self.rpc.rpc_foo = test_method
|
||||
self.rpc.handle_request()
|
||||
self.assertEqual(self.args, ())
|
||||
self.assertEqual(self.read(), "")
|
||||
|
||||
def test_should_return_error_for_missing_method(self):
|
||||
self.write(json.dumps(dict(method='foo',
|
||||
id=23)))
|
||||
self.rpc.handle_request()
|
||||
result = json.loads(self.read())
|
||||
|
||||
self.assertEqual(result["id"], 23)
|
||||
self.assertEqual(result["error"]["message"],
|
||||
"Unknown method foo")
|
||||
|
||||
def test_should_return_error_for_exception_in_method(self):
|
||||
def test_method():
|
||||
raise ValueError("An error was raised")
|
||||
|
||||
self.write(json.dumps(dict(method='foo',
|
||||
id=23)))
|
||||
self.rpc.rpc_foo = test_method
|
||||
|
||||
self.rpc.handle_request()
|
||||
result = json.loads(self.read())
|
||||
|
||||
self.assertEqual(result["id"], 23)
|
||||
self.assertEqual(result["error"]["message"], "An error was raised")
|
||||
self.assertIn("traceback", result["error"]["data"])
|
||||
|
||||
def test_should_not_include_traceback_for_faults(self):
|
||||
def test_method():
|
||||
raise rpc.Fault("This is a fault")
|
||||
|
||||
self.write(json.dumps(dict(method="foo",
|
||||
id=23)))
|
||||
self.rpc.rpc_foo = test_method
|
||||
|
||||
self.rpc.handle_request()
|
||||
result = json.loads(self.read())
|
||||
|
||||
self.assertEqual(result["id"], 23)
|
||||
self.assertEqual(result["error"]["message"], "This is a fault")
|
||||
self.assertNotIn("traceback", result["error"])
|
||||
|
||||
def test_should_add_data_for_faults(self):
|
||||
def test_method():
|
||||
raise rpc.Fault("St. Andreas' Fault",
|
||||
code=12345, data="Yippieh")
|
||||
|
||||
self.write(json.dumps(dict(method="foo", id=23)))
|
||||
self.rpc.rpc_foo = test_method
|
||||
|
||||
self.rpc.handle_request()
|
||||
result = json.loads(self.read())
|
||||
|
||||
self.assertEqual(result["error"]["data"], "Yippieh")
|
||||
|
||||
def test_should_call_handle_for_unknown_method(self):
|
||||
def test_handle(method_name, args):
|
||||
return "It works"
|
||||
self.write(json.dumps(dict(method="doesnotexist",
|
||||
id=23)))
|
||||
self.rpc.handle = test_handle
|
||||
self.rpc.handle_request()
|
||||
self.assertEqual(json.loads(self.read()),
|
||||
dict(id=23,
|
||||
result="It works"))
|
||||
|
||||
|
||||
class TestServeForever(TestJSONRPCServer):
|
||||
def handle_request(self):
|
||||
self.hr_called += 1
|
||||
if self.hr_called > 10:
|
||||
raise self.error()
|
||||
|
||||
def setUp(self):
|
||||
super(TestServeForever, self).setUp()
|
||||
self.hr_called = 0
|
||||
self.error = KeyboardInterrupt
|
||||
self.rpc.handle_request = self.handle_request
|
||||
|
||||
def test_should_call_handle_request_repeatedly(self):
|
||||
self.rpc.serve_forever()
|
||||
self.assertEqual(self.hr_called, 11)
|
||||
|
||||
def test_should_return_on_some_errors(self):
|
||||
self.error = KeyboardInterrupt
|
||||
self.rpc.serve_forever()
|
||||
self.error = EOFError
|
||||
self.rpc.serve_forever()
|
||||
self.error = SystemExit
|
||||
self.rpc.serve_forever()
|
||||
|
||||
def test_should_fail_on_most_errors(self):
|
||||
self.error = RuntimeError
|
||||
self.assertRaises(RuntimeError,
|
||||
self.rpc.serve_forever)
|
||||
441
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_server.py
Normal file
441
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_server.py
Normal file
@@ -0,0 +1,441 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""Tests for the elpy.server module"""
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
|
||||
from elpy import rpc
|
||||
from elpy import server
|
||||
from elpy.tests import compat
|
||||
from elpy.tests.support import BackendTestCase
|
||||
import elpy.refactor
|
||||
|
||||
|
||||
class ServerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.srv = server.ElpyRPCServer()
|
||||
|
||||
|
||||
class BackendCallTestCase(ServerTestCase):
|
||||
def assert_calls_backend(self, method):
|
||||
with mock.patch("elpy.server.get_source") as get_source:
|
||||
with mock.patch.object(self.srv, "backend") as backend:
|
||||
get_source.return_value = "transformed source"
|
||||
|
||||
getattr(self.srv, method)("filename", "source", "offset")
|
||||
|
||||
get_source.assert_called_with("source")
|
||||
getattr(backend, method).assert_called_with(
|
||||
"filename", "transformed source", "offset"
|
||||
)
|
||||
|
||||
|
||||
class TestInit(ServerTestCase):
|
||||
def test_should_not_select_a_backend_by_default(self):
|
||||
self.assertIsNone(self.srv.backend)
|
||||
|
||||
|
||||
class TestRPCEcho(ServerTestCase):
|
||||
def test_should_return_arguments(self):
|
||||
self.assertEqual(("hello", "world"),
|
||||
self.srv.rpc_echo("hello", "world"))
|
||||
|
||||
|
||||
class TestRPCInit(ServerTestCase):
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_set_project_root(self, RopeBackend, JediBackend):
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": "rope"})
|
||||
|
||||
self.assertEqual("/project/root", self.srv.project_root)
|
||||
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_initialize_rope(self, RopeBackend, JediBackend):
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": "rope"})
|
||||
|
||||
RopeBackend.assert_called_with("/project/root")
|
||||
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_initialize_jedi(self, RopeBackend, JediBackend):
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": "jedi"})
|
||||
|
||||
JediBackend.assert_called_with("/project/root")
|
||||
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_use_rope_if_available_and_requested(
|
||||
self, RopeBackend, JediBackend):
|
||||
RopeBackend.return_value.name = "rope"
|
||||
JediBackend.return_value.name = "jedi"
|
||||
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": "rope"})
|
||||
|
||||
self.assertEqual("rope", self.srv.backend.name)
|
||||
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_use_jedi_if_available_and_requested(
|
||||
self, RopeBackend, JediBackend):
|
||||
RopeBackend.return_value.name = "rope"
|
||||
JediBackend.return_value.name = "jedi"
|
||||
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": "jedi"})
|
||||
|
||||
self.assertEqual("jedi", self.srv.backend.name)
|
||||
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_use_rope_if_available_and_nothing_requested(
|
||||
self, RopeBackend, JediBackend):
|
||||
RopeBackend.return_value.name = "rope"
|
||||
JediBackend.return_value.name = "jedi"
|
||||
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": None})
|
||||
|
||||
self.assertEqual("rope", self.srv.backend.name)
|
||||
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_use_jedi_if_rope_not_available_and_nothing_requested(
|
||||
self, RopeBackend, JediBackend):
|
||||
RopeBackend.return_value.name = "rope"
|
||||
JediBackend.return_value.name = "jedi"
|
||||
old_rope = server.ropebackend
|
||||
server.ropebackend = None
|
||||
|
||||
try:
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": None})
|
||||
finally:
|
||||
server.ropebackend = old_rope
|
||||
|
||||
self.assertEqual("jedi", self.srv.backend.name)
|
||||
|
||||
@mock.patch("elpy.jedibackend.JediBackend")
|
||||
@mock.patch("elpy.ropebackend.RopeBackend")
|
||||
def test_should_use_none_if_nothing_available(
|
||||
self, RopeBackend, JediBackend):
|
||||
RopeBackend.return_value.name = "rope"
|
||||
JediBackend.return_value.name = "jedi"
|
||||
old_rope = server.ropebackend
|
||||
old_jedi = server.jedibackend
|
||||
server.ropebackend = None
|
||||
server.jedibackend = None
|
||||
|
||||
try:
|
||||
self.srv.rpc_init({"project_root": "/project/root",
|
||||
"backend": None})
|
||||
finally:
|
||||
server.ropebackend = old_rope
|
||||
server.jedibackend = old_jedi
|
||||
|
||||
self.assertIsNone(self.srv.backend)
|
||||
|
||||
|
||||
class TestRPCGetCalltip(BackendCallTestCase):
|
||||
def test_should_call_backend(self):
|
||||
self.assert_calls_backend("rpc_get_calltip")
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
self.assertIsNone(self.srv.rpc_get_calltip("filname", "source",
|
||||
"offset"))
|
||||
|
||||
|
||||
class TestRPCGetCompletions(BackendCallTestCase):
|
||||
def test_should_call_backend(self):
|
||||
self.assert_calls_backend("rpc_get_completions")
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
self.assertEqual([],
|
||||
self.srv.rpc_get_completions("filname", "source",
|
||||
"offset"))
|
||||
|
||||
def test_should_sort_results(self):
|
||||
with mock.patch.object(self.srv, 'backend') as backend:
|
||||
backend.rpc_get_completions.return_value = [
|
||||
{'name': '_e'},
|
||||
{'name': '__d'},
|
||||
{'name': 'c'},
|
||||
{'name': 'B'},
|
||||
{'name': 'a'},
|
||||
]
|
||||
expected = list(reversed(backend.rpc_get_completions.return_value))
|
||||
|
||||
actual = self.srv.rpc_get_completions("filename", "source",
|
||||
"offset")
|
||||
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_should_uniquify_results(self):
|
||||
with mock.patch.object(self.srv, 'backend') as backend:
|
||||
backend.rpc_get_completions.return_value = [
|
||||
{'name': 'a'},
|
||||
{'name': 'a'},
|
||||
]
|
||||
expected = [{'name': 'a'}]
|
||||
|
||||
actual = self.srv.rpc_get_completions("filename", "source",
|
||||
"offset")
|
||||
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
|
||||
class TestRPCGetCompletionDocs(ServerTestCase):
|
||||
def test_should_call_backend(self):
|
||||
with mock.patch.object(self.srv, "backend") as backend:
|
||||
self.srv.rpc_get_completion_docstring("completion")
|
||||
|
||||
(backend.rpc_get_completion_docstring
|
||||
.assert_called_with("completion"))
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
self.assertIsNone(self.srv.rpc_get_completion_docstring("foo"))
|
||||
|
||||
|
||||
class TestRPCGetCompletionLocation(ServerTestCase):
|
||||
def test_should_call_backend(self):
|
||||
with mock.patch.object(self.srv, "backend") as backend:
|
||||
self.srv.rpc_get_completion_location("completion")
|
||||
|
||||
(backend.rpc_get_completion_location
|
||||
.assert_called_with("completion"))
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
self.assertIsNone(self.srv.rpc_get_completion_location("foo"))
|
||||
|
||||
|
||||
class TestRPCGetDefinition(BackendCallTestCase):
|
||||
def test_should_call_backend(self):
|
||||
self.assert_calls_backend("rpc_get_definition")
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
self.assertIsNone(self.srv.rpc_get_definition("filname", "source",
|
||||
"offset"))
|
||||
|
||||
|
||||
class TestRPCGetAssignment(BackendCallTestCase):
|
||||
def test_should_call_backend(self):
|
||||
self.assert_calls_backend("rpc_get_assignment")
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
self.assertIsNone(self.srv.rpc_get_assignment("filname", "source",
|
||||
"offset"))
|
||||
|
||||
|
||||
class TestRPCGetDocstring(BackendCallTestCase):
|
||||
def test_should_call_backend(self):
|
||||
self.assert_calls_backend("rpc_get_docstring")
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
self.assertIsNone(self.srv.rpc_get_docstring("filname", "source",
|
||||
"offset"))
|
||||
|
||||
|
||||
class TestRPCGetPydocCompletions(ServerTestCase):
|
||||
@mock.patch.object(server, 'get_pydoc_completions')
|
||||
def test_should_call_pydoc_completions(self, get_pydoc_completions):
|
||||
srv = server.ElpyRPCServer()
|
||||
srv.rpc_get_pydoc_completions()
|
||||
get_pydoc_completions.assert_called_with(None)
|
||||
srv.rpc_get_pydoc_completions("foo")
|
||||
get_pydoc_completions.assert_called_with("foo")
|
||||
|
||||
|
||||
class TestGetPydocDocumentation(ServerTestCase):
|
||||
@mock.patch("pydoc.render_doc")
|
||||
def test_should_find_documentation(self, render_doc):
|
||||
render_doc.return_value = "expected"
|
||||
|
||||
actual = self.srv.rpc_get_pydoc_documentation("open")
|
||||
|
||||
render_doc.assert_called_with("open",
|
||||
"Elpy Pydoc Documentation for %s",
|
||||
False)
|
||||
self.assertEqual("expected", actual)
|
||||
|
||||
def test_should_return_none_for_unknown_module(self):
|
||||
actual = self.srv.rpc_get_pydoc_documentation("frob.open")
|
||||
|
||||
self.assertIsNone(actual)
|
||||
|
||||
def test_should_return_valid_unicode(self):
|
||||
import json
|
||||
|
||||
docstring = self.srv.rpc_get_pydoc_documentation("tarfile")
|
||||
|
||||
json.dumps(docstring)
|
||||
|
||||
|
||||
class TestRPCGetRefactorOptions(BackendTestCase):
|
||||
@mock.patch.object(compat.builtins, '__import__')
|
||||
def test_should_fail_if_rope_is_not_available(self, import_):
|
||||
import_.side_effect = ImportError
|
||||
filename = self.project_file("foo.py", "")
|
||||
srv = server.ElpyRPCServer()
|
||||
self.assertRaises(ImportError, srv.rpc_get_refactor_options,
|
||||
filename, 0)
|
||||
|
||||
@mock.patch.object(elpy.refactor, 'Refactor')
|
||||
def test_should_initialize_and_call_refactor_object(self, Refactor):
|
||||
filename = self.project_file("foo.py", "import foo")
|
||||
srv = server.ElpyRPCServer()
|
||||
srv.project_root = self.project_root
|
||||
|
||||
srv.rpc_get_refactor_options(filename, 5)
|
||||
|
||||
Refactor.assert_called_with(self.project_root, filename)
|
||||
Refactor.return_value.get_refactor_options.assert_called_with(5, None)
|
||||
|
||||
|
||||
class TestRPCRefactor(BackendTestCase):
|
||||
@mock.patch.object(compat.builtins, '__import__')
|
||||
def test_should_fail_if_rope_is_not_available(self, import_):
|
||||
import_.side_effect = ImportError
|
||||
filename = self.project_file("foo.py", "")
|
||||
srv = server.ElpyRPCServer()
|
||||
self.assertRaises(ImportError, srv.rpc_refactor,
|
||||
filename, 'foo', ())
|
||||
|
||||
@mock.patch.object(elpy.refactor, 'Refactor')
|
||||
def test_should_initialize_and_call_refactor_object_with_args(
|
||||
self, Refactor):
|
||||
filename = self.project_file("foo.py", "import foo")
|
||||
srv = server.ElpyRPCServer()
|
||||
srv.project_root = self.project_root
|
||||
|
||||
srv.rpc_refactor(filename, 'foo', (1, 2, 3))
|
||||
|
||||
Refactor.assert_called_with(self.project_root, filename)
|
||||
Refactor.return_value.get_changes.assert_called_with('foo', 1, 2, 3)
|
||||
|
||||
@mock.patch.object(elpy.refactor, 'Refactor')
|
||||
def test_should_initialize_and_call_refactor_object_without_args(
|
||||
self, Refactor):
|
||||
filename = self.project_file("foo.py", "import foo")
|
||||
srv = server.ElpyRPCServer()
|
||||
srv.project_root = self.project_root
|
||||
|
||||
srv.rpc_refactor(filename, 'foo', None)
|
||||
|
||||
Refactor.assert_called_with(self.project_root, filename)
|
||||
Refactor.return_value.get_changes.assert_called_with('foo')
|
||||
|
||||
|
||||
class TestRPCGetUsages(BackendCallTestCase):
|
||||
def test_should_call_backend(self):
|
||||
self.assert_calls_backend("rpc_get_usages")
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
with self.assertRaises(rpc.Fault):
|
||||
self.assertIsNone(self.srv.rpc_get_usages("filname", "source",
|
||||
"offset"))
|
||||
|
||||
|
||||
class TestRPCGetNames(BackendCallTestCase):
|
||||
def test_should_call_backend(self):
|
||||
self.assert_calls_backend("rpc_get_names")
|
||||
|
||||
def test_should_handle_no_backend(self):
|
||||
self.srv.backend = None
|
||||
with self.assertRaises(rpc.Fault):
|
||||
self.assertIsNone(self.srv.rpc_get_names("filname", "source", 0))
|
||||
|
||||
|
||||
class TestRPCImportMagic(ServerTestCase):
|
||||
def test_should_call_importmagic(self):
|
||||
with mock.patch.object(self.srv, "import_magic") as impmagic:
|
||||
self.srv.rpc_get_import_symbols("filename", "source", "os")
|
||||
impmagic.get_import_symbols.assert_called_with("os")
|
||||
self.srv.rpc_add_import("filename", "source", "import os")
|
||||
impmagic.add_import.assert_called_with("source", "import os")
|
||||
self.srv.rpc_get_unresolved_symbols("filename", "source")
|
||||
impmagic.get_unresolved_symbols.assert_called_with("source")
|
||||
self.srv.rpc_remove_unreferenced_imports("filename", "source")
|
||||
impmagic.remove_unreferenced_imports.assert_called_with("source")
|
||||
|
||||
|
||||
class TestGetSource(unittest.TestCase):
|
||||
def test_should_return_string_by_default(self):
|
||||
self.assertEqual(server.get_source("foo"),
|
||||
"foo")
|
||||
|
||||
def test_should_return_file_contents(self):
|
||||
fd, filename = tempfile.mkstemp(prefix="elpy-test-")
|
||||
self.addCleanup(os.remove, filename)
|
||||
with open(filename, "w") as f:
|
||||
f.write("file contents")
|
||||
|
||||
fileobj = {'filename': filename}
|
||||
|
||||
self.assertEqual(server.get_source(fileobj),
|
||||
"file contents")
|
||||
|
||||
def test_should_clean_up_tempfile(self):
|
||||
fd, filename = tempfile.mkstemp(prefix="elpy-test-")
|
||||
with open(filename, "w") as f:
|
||||
f.write("file contents")
|
||||
|
||||
fileobj = {'filename': filename,
|
||||
'delete_after_use': True}
|
||||
|
||||
self.assertEqual(server.get_source(fileobj),
|
||||
"file contents")
|
||||
self.assertFalse(os.path.exists(filename))
|
||||
|
||||
def test_should_support_utf8(self):
|
||||
fd, filename = tempfile.mkstemp(prefix="elpy-test-")
|
||||
self.addCleanup(os.remove, filename)
|
||||
with open(filename, "wb") as f:
|
||||
f.write(u"möp".encode("utf-8"))
|
||||
|
||||
source = server.get_source({'filename': filename})
|
||||
|
||||
self.assertEqual(source, u"möp")
|
||||
|
||||
|
||||
class TestPysymbolKey(BackendTestCase):
|
||||
def keyLess(self, a, b):
|
||||
self.assertLess(b, a)
|
||||
self.assertLess(server._pysymbol_key(a),
|
||||
server._pysymbol_key(b))
|
||||
|
||||
def test_should_be_case_insensitive(self):
|
||||
self.keyLess("bar", "Foo")
|
||||
|
||||
def test_should_sort_private_symbols_after_public_symbols(self):
|
||||
self.keyLess("foo", "_bar")
|
||||
|
||||
def test_should_sort_private_symbols_after_dunder_symbols(self):
|
||||
self.assertLess(server._pysymbol_key("__foo__"),
|
||||
server._pysymbol_key("_bar"))
|
||||
|
||||
def test_should_sort_dunder_symbols_after_public_symbols(self):
|
||||
self.keyLess("bar", "__foo")
|
||||
|
||||
|
||||
class Autopep8TestCase(ServerTestCase):
|
||||
|
||||
def test_rpc_fix_code_should_return_formatted_string(self):
|
||||
code_block = 'x= 123\n'
|
||||
new_block = self.srv.rpc_fix_code(code_block)
|
||||
self.assertEqual(new_block, 'x = 123\n')
|
||||
19
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_support.py
Normal file
19
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_support.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Tests for elpy.tests.support. Yep, we test test code."""
|
||||
|
||||
import unittest
|
||||
|
||||
from elpy.tests.support import source_and_offset
|
||||
|
||||
|
||||
class TestSourceAndOffset(unittest.TestCase):
|
||||
def test_should_return_source_and_offset(self):
|
||||
self.assertEqual(source_and_offset("hello, _|_world"),
|
||||
("hello, world", 7))
|
||||
|
||||
def test_should_handle_beginning_of_string(self):
|
||||
self.assertEqual(source_and_offset("_|_hello, world"),
|
||||
("hello, world", 0))
|
||||
|
||||
def test_should_handle_end_of_string(self):
|
||||
self.assertEqual(source_and_offset("hello, world_|_"),
|
||||
("hello, world", 12))
|
||||
32
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_yapf.py
Normal file
32
.emacs.d/elpa/elpy-20171206.847/elpy/tests/test_yapf.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# coding: utf-8
|
||||
"""Tests for the elpy.yapf module"""
|
||||
|
||||
import unittest
|
||||
|
||||
from elpy import yapfutil
|
||||
from elpy.rpc import Fault
|
||||
from elpy.tests.support import BackendTestCase
|
||||
|
||||
|
||||
@unittest.skipIf(yapfutil.YAPF_NOT_SUPPORTED,
|
||||
'yapf not supported for current python version')
|
||||
class YAPFTestCase(BackendTestCase):
|
||||
def setUp(self):
|
||||
if yapfutil.YAPF_NOT_SUPPORTED:
|
||||
raise unittest.SkipTest
|
||||
|
||||
def test_fix_code_should_throw_error_for_invalid_code(self):
|
||||
src = 'x = '
|
||||
self.assertRaises(Fault, yapfutil.fix_code, src)
|
||||
|
||||
def test_fix_code(self):
|
||||
testdata = [
|
||||
('x= 123\n', 'x = 123\n'),
|
||||
('x=1; \ny=2 \n', 'x = 1\ny = 2\n'),
|
||||
]
|
||||
for src, expected in testdata:
|
||||
self._assert_format(src, expected)
|
||||
|
||||
def _assert_format(self, src, expected):
|
||||
new_block = yapfutil.fix_code(src)
|
||||
self.assertEqual(new_block, expected)
|
||||
38
.emacs.d/elpa/elpy-20171206.847/elpy/yapfutil.py
Normal file
38
.emacs.d/elpa/elpy-20171206.847/elpy/yapfutil.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""Glue for the "yapf" library.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from elpy.rpc import Fault
|
||||
|
||||
YAPF_NOT_SUPPORTED = sys.version_info < (2, 7) or (
|
||||
sys.version_info >= (3, 0) and sys.version_info < (3, 4))
|
||||
|
||||
try:
|
||||
if YAPF_NOT_SUPPORTED:
|
||||
yapf_api = None
|
||||
else:
|
||||
from yapf.yapflib import yapf_api
|
||||
from yapf.yapflib import file_resources
|
||||
except ImportError: # pragma: no cover
|
||||
yapf_api = None
|
||||
|
||||
|
||||
def fix_code(code):
|
||||
"""Formats Python code to conform to the PEP 8 style guide.
|
||||
|
||||
"""
|
||||
if not yapf_api:
|
||||
raise Fault('yapf not installed', code=400)
|
||||
style_config = file_resources.GetDefaultStyleForDir(os.getcwd())
|
||||
try:
|
||||
reformatted_source, _ = yapf_api.FormatCode(code,
|
||||
filename='<stdin>',
|
||||
style_config=style_config,
|
||||
verify=False)
|
||||
return reformatted_source
|
||||
except Exception as e:
|
||||
raise Fault("Error during formatting: {}".format(e),
|
||||
code=400)
|
||||
@@ -0,0 +1,68 @@
|
||||
(defun elpy-snippet-split-args (arg-string)
|
||||
"Split a python argument string into ((name, default)..) tuples"
|
||||
(mapcar (lambda (x)
|
||||
(split-string x "[[:blank:]]*=[[:blank:]]*" t))
|
||||
(split-string arg-string "[[:blank:]]*,[[:blank:]]*" t)))
|
||||
|
||||
(defun elpy-snippet-current-method-and-args ()
|
||||
"Return information on the current definition."
|
||||
(let ((current-defun (python-info-current-defun))
|
||||
(current-arglist
|
||||
(save-excursion
|
||||
(python-nav-beginning-of-defun)
|
||||
(when (re-search-forward "(" nil t)
|
||||
(let* ((start (point))
|
||||
(end (progn
|
||||
(forward-char -1)
|
||||
(forward-sexp)
|
||||
(- (point) 1))))
|
||||
(elpy-snippet-split-args
|
||||
(buffer-substring-no-properties start end))))))
|
||||
class method args)
|
||||
(when (not current-arglist)
|
||||
(setq current-arglist '(("self"))))
|
||||
(if (and current-defun
|
||||
(string-match "^\\(.*\\)\\.\\(.*\\)$" current-defun))
|
||||
(setq class (match-string 1 current-defun)
|
||||
method (match-string 2 current-defun))
|
||||
(setq class "Class"
|
||||
method "method"))
|
||||
(setq args (mapcar #'car current-arglist))
|
||||
(list class method args)))
|
||||
|
||||
(defun elpy-snippet-init-assignments (arg-string)
|
||||
"Return the typical __init__ assignments for arguments."
|
||||
(let ((indentation (make-string (save-excursion
|
||||
(goto-char start-point)
|
||||
(current-indentation))
|
||||
?\s)))
|
||||
(mapconcat (lambda (arg)
|
||||
(if (string-match "^\\*" (car arg))
|
||||
""
|
||||
(format "self.%s = %s\n%s"
|
||||
(car arg)
|
||||
(car arg)
|
||||
indentation)))
|
||||
(elpy-snippet-split-args arg-string)
|
||||
"")))
|
||||
|
||||
(defun elpy-snippet-super-form ()
|
||||
"Return (Class, first-arg).method if Py2.
|
||||
Else return ().method for Py3."
|
||||
(let* ((defun-info (elpy-snippet-current-method-and-args))
|
||||
(class (nth 0 defun-info))
|
||||
(method (nth 1 defun-info))
|
||||
(args (nth 2 defun-info))
|
||||
(first-arg (nth 0 args))
|
||||
(py-version-command " -c 'import sys ; print(sys.version_info.major)'")
|
||||
;; Get the python version. Either 2 or 3
|
||||
(py-version-num (substring (shell-command-to-string (concat elpy-rpc-python-command py-version-command))0 1)))
|
||||
(if (string-match py-version-num "2")
|
||||
(format "(%s, %s).%s" class first-arg method)
|
||||
(format "().%s" method))))
|
||||
|
||||
(defun elpy-snippet-super-arguments ()
|
||||
"Return the argument list for the current method."
|
||||
(mapconcat (lambda (x) x)
|
||||
(cdr (nth 2 (elpy-snippet-current-method-and-args)))
|
||||
", "))
|
||||
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __abs__
|
||||
# key: __abs__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __abs__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __add__
|
||||
# key: __add__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __add__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __and__
|
||||
# key: __and__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __and__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __bool__
|
||||
# key: __bool__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __bool__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __call__
|
||||
# key: __call__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __call__(self, ${1:*args}):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __cmp__
|
||||
# key: __cmp__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __cmp__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __coerce__
|
||||
# key: __coerce__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __coerce__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __complex__
|
||||
# key: __complex__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __complex__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __contains__
|
||||
# key: __contains__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __contains__(self, item):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __del__
|
||||
# key: __del__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __del__(self):
|
||||
$0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __delattr__
|
||||
# key: __delattr__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __delattr__(self, name):
|
||||
$0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __delete__
|
||||
# key: __delete__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __delete__(self, instance):
|
||||
$0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __delitem__
|
||||
# key: __delitem__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __delitem__(self, key):
|
||||
$0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __div__
|
||||
# key: __div__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __div__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __divmod__
|
||||
# key: __divmod__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __divmod__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,9 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __enter__
|
||||
# key: __enter__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __enter__(self):
|
||||
$0
|
||||
|
||||
return self
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __eq__
|
||||
# key: __eq__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __eq__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __exit__
|
||||
# key: __exit__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
$0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __float__
|
||||
# key: __float__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __float__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __floordiv__
|
||||
# key: __floordiv__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __floordiv__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __ge__
|
||||
# key: __ge__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __ge__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __get__
|
||||
# key: __get__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __get__(self, instance, owner):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __getattr__
|
||||
# key: __getattr__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __getattr__(self, name):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __getattribute__
|
||||
# key: __getattribute__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __getattribute__(self, name):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __getitem__
|
||||
# key: __getitem__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __getitem__(self, key):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __gt__
|
||||
# key: __gt__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __gt__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __hash__
|
||||
# key: __hash__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __hash__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __hex__
|
||||
# key: __hex__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __hex__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __iadd__
|
||||
# key: __iadd__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __iadd__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __iand__
|
||||
# key: __iand__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __iand__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __idiv__
|
||||
# key: __idiv__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __idiv__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __ifloordiv__
|
||||
# key: __ifloordiv__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __ifloordiv__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __ilshift__
|
||||
# key: __ilshift__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __ilshift__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __imod__
|
||||
# key: __imod__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __imod__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __imul__
|
||||
# key: __imul__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __imul__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __index__
|
||||
# key: __index__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __index__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,10 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __init__ with assignment
|
||||
# key: __init__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __init__(self${1:, args}):
|
||||
"""$2
|
||||
|
||||
"""
|
||||
${1:$(elpy-snippet-init-assignments yas-text)}
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __instancecheck__
|
||||
# key: __instancecheck__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __instancecheck__(self, instance):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __int__
|
||||
# key: __int__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __int__(self):
|
||||
$0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __invert__
|
||||
# key: __invert__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __invert__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __ior__
|
||||
# key: __ior__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __ior__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __ipow__
|
||||
# key: __ipow__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __ipow__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __irshift__
|
||||
# key: __irshift__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __irshift__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __isub__
|
||||
# key: __isub__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __isub__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __iter__
|
||||
# key: __iter__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __iter__(self):
|
||||
$0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __itruediv__
|
||||
# key: __itruediv__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __itruediv__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __ixor__
|
||||
# key: __ixor__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __ixor__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __le__
|
||||
# key: __le__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __le__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __len__
|
||||
# key: __len__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __len__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __long__
|
||||
# key: __long__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __long__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __lshift__
|
||||
# key: __lshift__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __lshift__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __lt__
|
||||
# key: __lt__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __lt__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __mod__
|
||||
# key: __mod__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __mod__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __mul__
|
||||
# key: __mul__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __mul__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __ne__
|
||||
# key: __ne__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __ne__(self, other):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __neg__
|
||||
# key: __neg__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __neg__(self):
|
||||
return $0
|
||||
10
.emacs.d/elpa/elpy-20171206.847/snippets/python-mode/__new__
Normal file
10
.emacs.d/elpa/elpy-20171206.847/snippets/python-mode/__new__
Normal file
@@ -0,0 +1,10 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __new__
|
||||
# key: __new__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __new__(cls${1:, args}):
|
||||
"""$2
|
||||
|
||||
"""
|
||||
${1:$(elpy-snippet-init-assignments yas-text)}
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __nonzero__
|
||||
# key: __nonzero__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __nonzero__(self):
|
||||
return $0
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: __oct__
|
||||
# key: __oct__
|
||||
# group: Special methods
|
||||
# --
|
||||
def __oct__(self):
|
||||
return $0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user