#+TITLE: Python layer #+TAGS: general|layer|multi-paradigm|programming [[file:img/python.png]] * Table of Contents :TOC_5_gh:noexport: - [[#description][Description]] - [[#features][Features:]] - [[#install][Install]] - [[#layer][Layer]] - [[#choosing-a-backend][Choosing a backend]] - [[#backends][Backends]] - [[#anaconda][Anaconda]] - [[#language-server-protocol][Language Server Protocol]] - [[#additional-tools][Additional tools]] - [[#syntax-checking][Syntax checking]] - [[#test-runner][Test runner]] - [[#buffer-formatting][Buffer formatting]] - [[#automatic-buffer-formatting-on-save][Automatic buffer formatting on save]] - [[#automatic-save-of-buffer-when-testing][Automatic save of buffer when testing]] - [[#autoflake][autoflake]] - [[#pylookup][pylookup]] - [[#dap-mode-debugger-only-for-lsp-backend][dap-mode debugger (only for lsp backend)]] - [[#configuration][Configuration]] - [[#fill-column][Fill column]] - [[#sort-imports][Sort imports]] - [[#importmagic][Importmagic]] - [[#management-of-python-versions-and-virtual-environments][Management of Python versions and virtual environments]] - [[#manage-virtual-environments-with-pyvenv][Manage virtual environments with pyvenv]] - [[#manage-multiple-python-versions-with-pyenv][Manage multiple Python versions with pyenv]] - [[#automatic-activation-of-local-pyenv-version][Automatic activation of local pyenv version]] - [[#key-bindings][Key bindings]] - [[#inferior-repl-process][Inferior REPL process]] - [[#running-python-script-in-shell][Running Python Script in shell]] - [[#testing][Testing]] - [[#refactoring][Refactoring]] - [[#pip-package-management][Pip package management]] - [[#live-coding][Live coding]] - [[#other-python-commands][Other Python commands]] - [[#debugger][Debugger]] * Description This layer adds support for the Python language. ** Features: - Support for the following backends: - [[https://github.com/proofit404/anaconda-mode][anaconda]] (default), - [[https://github.com/emacs-lsp/lsp-python][Language Server Protocol]] (experimental), - Auto-completion - Code Navigation - Documentation Lookup using [[https://github.com/proofit404/anaconda-mode][anaconda-mode]] and [[https://github.com/tsgates/pylookup][pylookup]] - Test Runners using [[https://github.com/syl20bnr/nose.el][nose.el]] or [[https://github.com/ionrock/pytest-el][pytest]] - Virtual Environment using [[https://github.com/jorgenschaefer/pyvenv][pyvenv]] and [[https://github.com/yyuu/pyenv][pyenv]] - semantic mode is enabled - PEP8 compliant formatting via [[https://github.com/google/yapf][YAPF]] or [[https://github.com/ambv/black][black]] - PEP8 checks with [[https://pypi.python.org/pypi/flake8][flake8]] or [[https://pypi.python.org/pypi/pylint/1.6.4][pylint]] - Suppression of unused import with [[https://github.com/myint/autoflake][autoflake]] - Use the ~%~ key to jump between blocks with [[https://github.com/redguardtoo/evil-matchit][evil-matchit]] - Sort imports with [[https://pypi.python.org/pypi/isort][isort]] - Fix a missing import statement with [[https://github.com/anachronic/importmagic.el][importmagic]] - Pip package manager with [[https://github.com/brotzeit/pippel][pippel]] * Install ** Layer To use this configuration layer, add it to your =~/.spacemacs=. You will need to add =python= to the existing =dotspacemacs-configuration-layers= list in this file. ** Choosing a backend To choose a default backend set the layer variable =python-backend=: #+BEGIN_SRC elisp (python :variables python-backend 'anaconda) #+END_SRC Backend can be chosen on a per project basis using directory local variables (files named =.dir-locals.el= at the root of a project), an example to use the =lsp= backend: #+BEGIN_SRC elisp ;;; Directory Local Variables ;;; For more information see (info "(emacs) Directory Variables") ((python-mode (python-backend . lsp))) #+END_SRC *Note:* you can easily add a directory local variable with ~SPC f v d~. * Backends ** Anaconda =anaconda-mode= tries to install the dependencies itself but sometimes it does not work and you may encounter the following message when opening a python buffer: #+BEGIN_EXAMPLE Blocking call to accept-process-output with quit inhibited!! #+END_EXAMPLE To fix this, install the =anaconda-mode= [[https://github.com/proofit404/anaconda-mode/wiki][anaconda-deps]] by hand: #+BEGIN_SRC sh pip install --upgrade "jedi>=0.9.0" "json-rpc>=1.8.1" "service_factory>=0.1.5" #+END_SRC If you encounter problems with Jedi 1.0 consider downgrading to 0.9.0. See [[https://github.com/davidhalter/jedi/issues/873][this issue]] for details. Source: [[https://github.com/proofit404/anaconda-mode#issues]] If you are facing errors such as "Unable to run anaconda-mode server", try setting your =PYTHONPATH= as explained at [[https://github.com/proofit404/anaconda-mode#pythonpath]] ** Language Server Protocol You just have to install python language server package: #+BEGIN_SRC sh pip install python-language-server #+END_SRC Additionally you can install the following other packages: #+BEGIN_SRC sh # for import sorting pip install pyls-isort # for mypy checking (python 3.4+ is needed) pip install pyls-mypy #+END_SRC If you've installed the language server and related packages as development dependencies in a pipenv environment, you'll want to set the ~python-pipenv-activate~ config variable to ~t~. This activates your pipenv before enabling the lsp backend. * Additional tools ** Syntax checking Syntax checking uses =flake8= package: #+BEGIN_SRC sh pip install flake8 #+END_SRC ** Test runner Both =nose= and =pytest= are supported. By default =nose= is used. To choose your test runner set the layer variable =python-test-runner= to either =nose= or =pytest=. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((python :variables python-test-runner 'pytest))) #+END_SRC If you need both then you can set =python-test-runner= to a list like this: #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((python :variables python-test-runner '(pytest nose)))) #+END_SRC This means that =pytest= is your primary test runner. To use the secondary test runner you can call the test functions with a prefix argument e.g. ~SPC u SPC m t t~ to run one test with =nose=. To set project specific test runners you can set =python-test-runner= in a directory local variable in your project root. ~SPC f v d~ in Spacemacs. See [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html][the official documentation]] for more information. The root of the project is detected with a =.git= directory or a =setup.cfg= file. ** Buffer formatting One of [[https://github.com/google/yapf][YAPF]] (the default) or [[https://github.com/ambv/black][black]] may be selected as the formatter, via =python-formatter=, as ='yapf= or ='black= respectively. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (python :variables python-formatter 'yapf))) #+END_SRC The key binding ~SPC m =~ invokes the selected formatter on the current buffer when in python mode. Note that YAPF and black may also be invoked unconditionally via =yapfify-buffer= and =blacken-buffer=, respectively, provided that they are installed. ** Automatic buffer formatting on save To enable automatic buffer formatting on save set the variable =python-format-on-save= to =t=. The formatter specified by =python-formatter= will be used. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (python :variables python-format-on-save t))) #+END_SRC ** Automatic save of buffer when testing By default a buffer is automatically saved before tests are executed upon it, you can disable this feature by setting =python-save-before-test= to =nil=. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (python :variables python-save-before-test nil))) #+END_SRC ** autoflake To be able to suppress unused imports easily, install [[https://github.com/myint/autoflake][autoflake]]: #+BEGIN_SRC sh pip install autoflake #+END_SRC ** pylookup To use =pylookup= on ~SPC m h H~, make sure you update the database first, using ~SPC SPC pylookup-update~. ** dap-mode debugger (only for lsp backend) To use =dap-mode= for debugging do: #+BEGIN_SRC bash pip install "ptvsd>=4.2" #+END_SRC * Configuration ** Fill column If you want to customize the fill column value, use something like this inside the =user-init= function in your =.spacemacs=: #+BEGIN_SRC elisp (setq-default dotspacemacs-configuration-layers '( (python :variables python-fill-column 99))) #+END_SRC ** Sort imports If you want imports to be automatically sorted when you save a file (using [[https://pypi.python.org/pypi/isort][isort]]), set the =python-sort-imports-on-save= variable in the python layer config section: #+BEGIN_SRC elisp (setq-default dotspacemacs-configuration-layers '((python :variables python-sort-imports-on-save t))) #+END_SRC or as a directory-local variable (for per-project settings). ** Importmagic Install importmagic and epc for importmagic functionality. #+BEGIN_SRC sh pip install importmagic epc #+END_SRC * Management of Python versions and virtual environments ** Manage virtual environments with pyvenv A virtual environment provides isolation of your Python package versions. For a general overview see [[http://docs.python-guide.org/en/latest/dev/virtualenvs/][this site]]. [[http://virtualenvwrapper.readthedocs.io/en/latest/index.html][Virtualenvwrapper]] which is also explained in the previous link, is a program which manages your virtual environments in a central location set by the =WORKON_HOME= environment variable. Spacemacs integration of virtual environments and virtualenvwrapper is provided by the [[https://github.com/jorgenschaefer/pyvenv][pyvenv]] package. It provides the following key bindings: | Key binding | Description | |-------------+-------------------------------------------------| | ~SPC m V a~ | activate a virtual environment in any directory | | ~SPC m V d~ | deactivate active virtual environment | | ~SPC m V w~ | work on virtual environment in =WORKON_HOME= | ** Manage multiple Python versions with pyenv If you need multiple Python versions (e.g. Python 2 and Python 3) then take a look at [[https://github.com/yyuu/pyenv][pyenv]]. It enables the installation and managment of multiple Python versions. [[https://www.brianthicks.com/post/2015/04/15/automate-your-python-environment-with-pyenv/][This blogpost]] gives a good overview on how to use the tool. Spacemacs integration is provided by [[https://github.com/proofit404/pyenv-mode][pyenv mode]] which has the following key bindings. | Key binding | Description | |-------------+--------------------------------------| | ~SPC m v s~ | set a pyenv environment with [[https://github.com/pyenv/pyenv][pyenv]] | | ~SPC m v u~ | unset a pyenv environment with [[https://github.com/pyenv/pyenv][pyenv]] | Pyenv can also manage virtual environments for each of the Python versions it has installed. Those will be listed alongside your Python versions. *** Automatic activation of local pyenv version A project-specific pyenv version may be written to a file called =.python-version= using the [[https://github.com/yyuu/pyenv/blob/master/COMMANDS.md#user-content-pyenv-local][pyenv local]] command. Spacemacs can search in parent directories for this file, and automatically set the pyenv version. The behavior can be set with the variable =python-auto-set-local-pyenv-version= to: - =on-visit= (default) set the version when you visit a python buffer, - =on-project-switch= set the version when you switch projects, - =nil= to disable. The same is also possible on pyvenv with a file called =.venv=. The behavior can be set with the variable =python-auto-set-local-pyvenv-virtualenv== to: - =on-visit= (default) set the virtualenv when you visit a python buffer, - =on-project-switch= set the virtualenv when you switch projects, - =nil= to disable. * Key bindings ** Inferior REPL process Start a Python or iPython inferior REPL process with ~SPC m s i~. If =ipython= is available in system executable search paths, =ipython= will be used to launch python shell; otherwise, default =python= interpreter will be used. You may change your system executable search path by activating a virtual environment. Send code to inferior process commands: | Key binding | Description | |-------------+-------------------------------------------------| | ~SPC m s b~ | send buffer and keep code buffer focused | | ~SPC m s B~ | send buffer and switch to REPL in insert mode | | ~SPC m s f~ | send function and keep code buffer focused | | ~SPC m s F~ | send function and switch to REPL in insert mode | | ~SPC m s i~ | start inferior REPL process | | ~SPC m s r~ | send region and keep code buffer focused | | ~SPC m s R~ | send region and switch to REPL in insert mode | | ~CTRL+j~ | next item in REPL history | | ~CTRL+k~ | previous item in REPL history | ** Running Python Script in shell To run a Python script like you would in the shell press ~SPC m c c~ to start the Python script in comint mode. This is useful when working with multiple Python files since the REPL does not reload changes made in other modules. | Key binding | Description | |-------------+---------------------------------------------------------------------------| | ~SPC m c c~ | Execute current file in a comint shell | | ~SPC m c C~ | Execute current file in a comint shell and switch to it in =insert state= | *Note:* With the universal argument ~SPC u~ you can enter a new compilation command. ** Testing Test commands start with ~m t~. To use the secondary test runner call the function with a prefix argument, for example ~SPC u SPC m t a~. | No Debug | Description | |-------------+----------------------------------------------------------| | ~SPC m t a~ | launch all tests of the project | | ~SPC m t b~ | launch all tests of the current buffer (same as module) | | ~SPC m t l~ | launch last tests | | ~SPC m t m~ | launch all tests of the current module | | ~SPC m t s~ | launch all tests of the current suite (only with =nose=) | | ~SPC m t t~ | launch the current test (function) | | Debug | Description | |-------------+------------------------------------------------------------------------| | ~SPC m t A~ | launch all tests of the project in debug mode | | ~SPC m t B~ | launch all tests of the current buffer (module) in debug mode | | ~SPC m t M~ | launch all tests of the current module in debug mode | | ~SPC m t S~ | launch all tests of the current suite in debug mode (only with =nose=) | | ~SPC m t T~ | launch the current test (function) in debug mode | ** Refactoring | Key binding | Description | |-------------+-------------------------------------------------| | ~SPC m r f~ | fix a missing import statement with [[https://pypi.python.org/pypi/importmagic][importmagic]] | | ~SPC m r i~ | remove unused imports with [[https://github.com/myint/autoflake][autoflake]] | | ~SPC m r I~ | sort imports with [[https://pypi.python.org/pypi/isort][isort]] | ** Pip package management In python buffer type ~SPC m P~ to open buffer listing all installed =pip= packages in the currently activated virtual environment. *Note:* To open this menu from outside a python buffer type ~SPC SPC pippel-list-packages RET~. In the package list buffer: | Key binding | Description | |-------------+-------------------------------------------------------------| | ~RET~ | follow link (=pippel-menu-visit-homepage=) | | ~d~ | mark for deletion (=pippel-menu-mark-delete=) | | ~i~ | prompt user for packages (=pippel-install-package=) | | ~m~ | remove mark (=pippel-menu-mark-unmark=) | | ~r~ | refresh package list (=pippel-list-packages=) | | ~U~ | mark all upgradable (=pippel-menu-mark-all-upgrades=) | | ~u~ | mark for upgrade (=pippel-menu-mark-upgrade=) | | ~x~ | perform marked package menu actions (=pippel-menu-execute=) | ** Live coding Live coding is provided by the [[https://github.com/donkirkby/live-py-plugin][live-py-plugin.]] | Key binding | Description | |-------------+---------------------| | ~SPC m l~ | Toggle live-py-mode | ** Other Python commands | Key binding | Description | |---------------+-----------------------------------------------------------------------------------| | ~SPC m =~ | reformat the buffer using formatter specified in =python-formatter= | | ~SPC m d b~ | toggle a breakpoint using =wdb=, =ipdb=, =pudb=, =pdb= or =python3.7= (and above) | | ~SPC m g a~ | go to assignment using =anaconda-mode-find-assignments= (~C-o~ to jump back) | | ~SPC m g b~ | jump back | | ~SPC m g g~ | go to definition using =anaconda-mode-find-definitions= (~C-o~ to jump back) | | ~SPC m g u~ | navigate between usages with =anaconda-mode-find-references= | | ~SPC m h d~ | look for documentation using =helm-pydoc= | | ~SPC m h h~ | quick documentation using anaconda | | ~SPC m h H~ | open documentation in =firefox= using [[https://github.com/tsgates/pylookup][pylookup]] | | ~SPC m v a~ | activate a virtual environment in any directory | | ~SPC m v d~ | deactivate active virtual environment | | ~SPC m v s~ | set a pyenv environment with [[https://github.com/pyenv/pyenv][pyenv]] | | ~SPC m v u~ | unset a pyenv environment with [[https://github.com/pyenv/pyenv][pyenv]] | | ~SPC m v w~ | work on virtual environment in =WORKON_HOME= | | ~SPC m v p a~ | activate pipenv in current project | | ~SPC m v p d~ | deactivate pipenv in current project | | ~SPC m v p i~ | install module into pipenv environment | | ~SPC m v p o~ | open pipenv module in buffer | | ~SPC m v p s~ | launch pipenv shell in current project | | ~SPC m v p u~ | uninstall module from pipenv environment | ** Debugger | Key binding | Description | |---------------+---------------------------------| | ~SPC m d d d~ | start debugging | | ~SPC m d d l~ | debug last configuration | | ~SPC m d d r~ | debug recent configuration | |---------------+---------------------------------| | ~SPC m d c~ | continue | | ~SPC m d i~ | step in | | ~SPC m d o~ | step out | | ~SPC m d s~ | next step | | ~SPC m d v~ | inspect value at point | | ~SPC m d r~ | restart frame | |---------------+---------------------------------| | ~SPC m d .~ | debug transient state | |---------------+---------------------------------| | ~SPC m d a~ | abandon current session | | ~SPC m d A~ | abandon all process | |---------------+---------------------------------| | ~SPC m d e e~ | eval | | ~SPC m d e r~ | eval region | | ~SPC m d e t~ | eval value at point | |---------------+---------------------------------| | ~SPC m d S s~ | switch session | | ~SPC m d S t~ | switch thread | | ~SPC m d S f~ | switch frame | |---------------+---------------------------------| | ~SPC m d I i~ | inspect | | ~SPC m d I r~ | inspect region | | ~SPC m d I t~ | inspect value at point | |---------------+---------------------------------| | ~SPC m d b b~ | toggle a breakpoint | | ~SPC m d b c~ | change breakpoint condition | | ~SPC m d b l~ | change breakpoint log condition | | ~SPC m d b h~ | change breakpoint hit count | | ~SPC m d b a~ | add a breakpoint | | ~SPC m d b d~ | delete a breakpoint | | ~SPC m d b D~ | clear all breakpoints | |---------------+---------------------------------| | ~SPC m d '_~ | Run debug REPL | |---------------+---------------------------------| | ~SPC m d w l~ | list local variables | | ~SPC m d w o~ | goto output buffer if present | | ~SPC m d w s~ | list sessions | | ~SPC m d w b~ | list breakpoints |