Skip to content
/ pydor Public

Emacs Lisp package to run the Python doctests at point

Notifications You must be signed in to change notification settings

swinkels/pydor

Repository files navigation

This repo contains Emacs package pydor, which is short for “Python doctest runner”. This package lets you execute the Python doctests in the docstring at point. The following animated GIF shows how it works in Spacemacs:

./pydor-runs-doctests.gif

Background

I use Emacs configuration framework Spacemacs - its develop branch to be precise. That framework configures several key bindings to run Python unit tests, such as “run test at point” and “run tests in current module”. However, it lacks functions to run doctests. This package provides a function to run the doctests in the docstring at point.

Prerequisites

pydor is implemented in Emacs Lisp and Python. It uses

  • Python to find & run all doctests in a docstring in a given Python module and at a given line, and
  • Emacs Lisp to call that Python code for the docstring at point.

pydor has been developed using Emacs 28.1, Python 3.11.3 on Manjaro Linux 23.0.0. Probably it will work with older (or newer) Emacs and Python versions, but that hasn’t been tested explicitly.

Installation when using Spacemacs

As mentioned, I use Spacemacs so I provide the installation instructions for that context. It should be relatively straightforward to adapt these instructions for “plain Emacs”.

Spacemacs will automatically retrieve the package from its GitHub repo if you add the following entry to the list of “additional packages” in ~~/.spacemacs~:

dotspacemacs-additional-packages
`(
  (pydor :location (recipe :fetcher github :repo "swinkels/pydor" :files ("pydor.el" "execute_doctests.py"))
  )

At this point the package will be available to Spacemacs but will not yet be loaded. The following use-package expression for dotspacemacs/user-config in ~~/.spacemacs~ takes care of that:

(use-package pydor
  :commands (pydor-execute-doctest)
  :init
    (spacemacs/set-leader-keys-for-major-mode 'python-mode "td" 'pydor-execute-doctest))

This expression establishes two things:

  • pydor will be loaded when you call pydor-execute-doctest for the first time;
  • function pydor-execute-doctest is bound to , t d in Python mode.

Adding directories to your Python sys.path

pydor imports the module that contains the docstring at point. For this to succeed, the module should be in a directory of the Python sys.path or it should be part of a package in such a directory. If that is not the case, the import will fail and pydor will abort. This is where variable pydor-pythonpath-directories comes in: before pydor tries to import the module, it extends sys.path with the directories in this list.

To give an example, I often have several Python scripts in the root of my repo to try out things in the Python REPL. In general, that directory is not a directory of sys.path and pydor won’t be able to import these scripts. To help pydor, I set pydor-pythonpath-directories as a directory-local variable in file .dir-locals.el in the root of the repo:

;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")

((python-mode . ((pydor-pythonpath-directories . ("/home/swinkels/repo/oss/pydor")))))

Note that the paths on pydor-pythonpath-directories should be absolute.

Finally, pydor tries to import the module with its full module name, so package.subpackage.module. To determine that name, it assumes that each directory in the Python package has an __init__.py. This means that pydor will only work with regular Python packages and not with namespace packages, which don’t have that file.

Development

The Emacs part of pydor is developed using Emacs Eask, a “CLI for building, running, testing, and managing your Emacs Lisp dependencies”. For information about the installation of Eask I refer to its documentation. In this README I only show how to use Eask for the development of pydor.

In the directory of your clone of pydor, execute the following command to download its Emacs Lisp development dependencies and run the Emacs Lisp unit tests:

$> eask test ert-runner -L . -L test

If you want to add unit tests to pydor, place them in subdirectory test/.

There is a Makefile in the root of the repo that offers several targets as shortcuts to these Eask commands. The Eask command above is accessible as target unit-test of the Makefile. This is the default target, so just calling make runs the unit tests.

If you develop pydor, you will want to work with a local Git checkout instead of the installed version. One way to do so is by pointing the pydor entry in dotspacemacs-additional-packages to your local checkout:

dotspacemacs-additional-packages
`(
  (pydor :location local)
  )

Whith this entry, Spacemacs expects the Git checkout to be present as ~~/.emacs.d/private/local/pydor~. That means you either checkout pydor in that directory, or use a link to the right directory.

If you change pydor.el and want to test these changes, you have to evaluate that file again. To do so, either load that file in Emacs and execute command eval-buffer, or restart Emacs.

There is another approach if you want to use a local Git checkout for the only for your current Emacs session: you evaluate the checked out pydor.el before your first call to main function pydor-execute-doctest [fn:1]. Don’t forget to re-evaluate pydor.el when you want to test your changes.

[fn:1] If you evaluate pydor.el after Emacs has evaluated the installed version, Emacs will still use the installed Python script instead of the one in your checkout.

About

Emacs Lisp package to run the Python doctests at point

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published