Python Development Configuration

Check out the final code here.

What we’ll cover:

  • python-mode
  • lsp-mode
  • Debugging with dap-mode
  • Running tests with Projectile
  • Using virtualenv

Our example project

Installing requirements

pip install -r requirements.txt

Using python-mode

(use-package python-mode
  :ensure nil
  :custom
  (python-shell-interpreter "python3"))

Commands:

  • Interactive Python shell: M-x run-python (C-c C-p or g z in evil-mode)
  • python-shell-send-file (C-c C-l)
  • python-shell-send-buffer (C-c C-c)
  • python-shell-send-region (C-c C-r)

Setting up lsp-mode

Installing pyls

https://emacs-lsp.github.io/lsp-mode/page/languages/

pip install --user python-language-server[all]

Ensure that it’s on the PATH! If not, you may need to add ~/.local/bin to PATH

Activating lsp-mode

We are starting with the lsp-mode configuration from “Build Your Own IDE with lsp-mode”, check that out for more details on lsp-mode!

:hook (python-mode . lsp-deferred))

Completion error!

If you see an error complaining about company-capf, this may be a bug with lsp-mode.

As a workaround, run package-reinstall to reinstall lsp-mode and lsp-ui packages and then restart Emacs.

lsp-mode features

Completions

Documentation hover

Signature help

Linting / diagnostics - flycheck-list-errors

Code navigation - lsp-find-definition and lsp-find-references

Symbol renaming - lsp-rename

Code formatting - lsp-format-buffer

Symbol tree - lsp-treemacs-symbols

Running unit tests

Using pytest:

pip install pytest

Skip test_results.py, it’s slow!

Use Projectile’s projectile-test-project command:

  • Set a directory-local variable for projectile-project-test-cmd with add-dir-local-variable
  • Set compilation-read-command to nil to skip asking every time you want to run the test (might be unsafe!)
  • You can use g r inside of the unit test buffer to rerun the tests or call recompile interactively

Induce a failure!

Debugging

I recommend watching “Emacs IDE - How to Debug Your Code with dap-mode” to learn more about the features!

Configuration instructions: https://emacs-lsp.github.io/dap-mode/page/configuration/#python

However, we will use debugpy (ptvsd is deprecated):

pip install debugpy
(dap-python-debugger 'debugpy)

Run dap-debug and select the pytest configuration. Fails due to python2!

Set dap-python-executable to python3

(dap-python-executable "python3")

Running the default pytest configuration doesn’t launch from the correct path, let’s edit the configuration with dap-debug-edit-template:

(dap-register-debug-template
  "Python :: Run pytest (gallery-dl)"
  (list :type "python"
        :cwd "/home/daviwil/Projects/Code/gallery-dl"
        :module "pytest"
        :request "launch"
              :debugger 'debugpy
        :name "Python :: Run pytest (gallery-dl)"))

However, this still doesn’t work correctly from within a file in the project folder. dap-mode bug?

Virtual Environments

This part is only necessary if you use virtualenv in your Python development workflow!

virtualenv env
. env/bin/activate

Use pyvenv for setting up the right virtualenv in Emacs:

(use-package pyvenv
  :config
  (pyvenv-mode 1))

Run pyvenv-activate and select the env folder, now lsp-mode and dap-mode will use it!

Subscribe to the System Crafters Newsletter!
Stay up to date with the latest System Crafters news and updates! Read the Newsletter page for more information.
Name (optional)
Email Address