Skip to content

Tracks down the correct Python tooling executables from your virtualenvs so you can glue the binaries to Emacs and delete code in init.el

License

Notifications You must be signed in to change notification settings

wyuenho/emacs-pet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CI Status

P ython E xecutable T racker

Greetings fellow Pythonistas and Emacs users!

Have you ever worked on a project that uses one of the many Python package managers and/or virtual environments, where all the linters, formatters and commit hooks are set up meticulously, and then when you fire up Emacs, packages like flycheck or lsp-mode are either unable to find the binary in your virtualenv, or are using the wrong one?

Have you ever tried one of the 11+ Emacs virtualenv packages to help you fix this problem, but are still at a loss as to why your other favorite Emacs packages still can't find the right binaries, or they stop working when you switch to a different project using a different flavor of virtualenv?

If you answer "yes" for any of these questions, you've come to the right place.

How does pet work?

The first key insight is to recognize the paths to the executables of many Python linting and formatting Emacs packages are configurable.

The second key insight is Emacs allows you to setup a different value for the executable path on a per buffer basis, and that these packages work with these buffer-local values.

The hardest problem is finding the correct executable, this is what pet tries to solve.

pet solves this through automatic detection and configuration:

Detect your project
Uses Projectile or built-in project.el to find your project root
Find your virtualenv
Searches for virtualenvs using multiple methods: configuration files (pyproject.toml, Pipfile, etc.), standard directories (.venv, venv), environment variables (VIRTUAL_ENV), and tool-specific detection
Set executable paths
Once a virtualenv is found, pet sets buffer-local variables so your Emacs packages (flycheck, lsp-mode, formatters, etc.) use the correct executables from that virtualenv's bin directory
Remote file support
For Python files accessed via TRAMP, pet detects remote virtualenvs and configures executables with proper state isolation to prevent cross-project interference

This happens automatically with zero Emacs configuration necessary. The detection runs once per project and results are cached for performance.

Supported Python Virtual Environment Tools

See doc/SUPPORTED.rst for the complete list and integration notes.

Supported Emacs Packages

See doc/SUPPORTED.rst for the complete list and integration caveats.

System Requirements

pet has minimal system requirements and requires Emacs 27.1+.

For TOML and YAML configuration file parsing, pet supports multiple options:

External Programs (Optional)

Emacs Lisp Parsers (Optional)

pet will automatically detect and use the first available parser for each format, preferring external programs for performance, then falling back to pure Emacs Lisp implementations.

Additional Requirements

If you are using Emacs < 29, the sqlite3 command is required for pre-commit database parsing.

Installation Tips

# Install dasel (cross-platform)
# macOS
brew install dasel
# Linux (various package managers)
sudo apt install dasel        # Ubuntu/Debian
sudo dnf install dasel        # Fedora
sudo pacman -S dasel          # Arch Linux

Alternatively, install tomlparse.el and yaml.el via MELPA:

M-x package-install RET tomlparse RET

Or:

M-x package-install RET yaml RET

Usage

If you are using Emacs on macOS, install exec-path-from-shell first to ensure Python tools are available in your exec-path.

Basic Setup

(use-package pet
  :config
  (add-hook 'python-base-mode-hook 'pet-mode -10))

This automatically configures all supported packages for both python-mode and python-ts-mode.

Environment Switching

For projects using conda, mamba, or pixi, you can now switch environments interactively:

M-x pet-conda-switch-environment
M-x pet-mamba-switch-environment
M-x pet-pixi-switch-environment

When you enable pet-mode on a fresh project using these tools, pet will automatically prompt you to select an environment if none is currently active.

Manual Configuration

For packages pet doesn't yet support, or when you need fine-grained control:

(add-hook 'python-mode-hook
          (lambda ()
            (setq-local python-shell-interpreter (pet-executable-find "python")
                        python-shell-virtualenv-root (pet-virtualenv-root))))

For flycheck setup: (add-hook 'python-mode-hook 'pet-flycheck-setup)

See doc/SUPPORTED.rst for a complete configuration example with lsp-mode, flycheck, formatters, and testing tools.

Performance

pet caches virtualenv detection results and works efficiently on most projects. For large projects or performance issues, see doc/PERFORMANCE.rst for detailed optimization strategies.

Customization

For configuration options including file search methods, external tool settings, parser selection, and project-specific settings, see doc/CUSTOMIZATION.rst.

Troubleshooting

Pet didn't detect my virtualenv

pet doesn't create virtualenvs - create your virtualenv and install dependencies first, then pet will detect it automatically.

Wrong Python version or missing executables

Enable debug mode with (setq pet-debug t) and watch the *Messages* buffer. Use M-x pet-verify-setup in your Python buffers to see what was detected.

Verify setup for specific packages:

  • lsp-mode: M-x lsp-describe-session
  • eglot: M-x eglot-show-workspace-configuration
  • flycheck: M-x flycheck-verify-setup

Slow performance on large projects

Install fd for faster file searches: brew install fd (macOS) or sudo apt install fd-find (Ubuntu). See doc/PERFORMANCE.rst for optimization strategies.

Direnv integration issues

Use envrc instead of other direnv packages. See doc/SUPPORTED.rst for detailed integration notes.

Why doesn't pet use buffer-local exec-path?

Many Python projects use development tools in different virtualenvs (e.g., pre-commit hooks). Managing multiple virtualenv paths in exec-path reliably is complex. Using absolute executable paths is simpler and more performant.

Do I still need other virtualenv packages?

No, you can uninstall them all - this is the main purpose of pet.

License

GPLv3

About

Tracks down the correct Python tooling executables from your virtualenvs so you can glue the binaries to Emacs and delete code in init.el

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 10