virtualenv activation hooks?

Asked by Nathan Typanski on 2014-06-11

When I set up my virtual environment in emacs, I also configure flycheck's pylint to point to the executable that's in the virtual environment. The way I'm doing this right now is:

    (defun my-set-pylint-from-venv ()
      "Change flycheck pylint executable to virtualenv executable"
      (if (and (boundp 'virtualenv-name)
               (virtualenv-p (py--normalize-directory virtualenv-name)))
          (let ((pylintpath
                 (concat (py--normalize-directory virtualenv-name) "bin/pylint")

                 ))
            (setq flycheck-python-pylint-executable pylintpath)
            )))
    (add-hook 'python-mode-hook 'my-set-pylint-from-venv)

but this means if I open a Python file, then go "oh yeah, I need to set the virtual environment" and set it with (virtualenv-workon), then I also need to do (python-mode) again in order to hit the pylint executable hook.

The way I'd rather do this is make it a hook to (virtualenv-activate) or (virtualenv-workon) so I can stop restarting python-mode every time I switch venvs.

Is there a way to automate this that actually supports the workflow I've described?

Question information

Language:
English Edit question
Status:
Answered
For:
python-mode.el Edit question
Assignee:
Andreas Roehler Edit question
Last query:
2014-06-11
Last reply:
2014-06-14
Andreas Roehler (a-roehler) said : #1

As several virtualenv tools are out there, it's difficult to answer.
Maybe give some details of configuration, which files wherefrom in use etc.

For the moment some work-around advising `virtualenv-activate':

;; (add-hook 'python-mode-hook 'my-set-pylint-from-venv)
(defvar py-pylint-default (executable-find "pylint"))

(defun my-set-pylint-from-venv ()
  "Change flycheck pylint executable to virtualenv executable"
  ;; virtualenv-name might be nil
  (when (and (boundp 'virtualenv-name)(stringp virtualenv-name)
      (virtualenv-p (py--normalize-directory
       virtualenv-name)))
    (let ((pylintpath
    (concat (py--normalize-directory virtualenv-name)
     "bin/pylint")))
      (setq flycheck-python-pylint-executable pylintpath))))

;; IMO the inverse is needed also
(defun my-reset-pylint ()
  "Set flycheck `pylint' executable to default value. "
  (interactive)
  (setq flycheck-python-pylint-executable py-pylint-default))

(defadvice virtualenv-activate (after my-set-pylint-from-venv activate)
  (my-set-pylint-from-venv))
(ad-activate 'virtualenv-activate)

(defadvice virtualenv-deactivate (after my-reset-pylint activate)
  (my-reset-pylint))
(ad-activate 'virtualenv-deactivate)

;;;;

Andreas

Nathan Typanski (ntypanski) said : #2

Thanks for the workaround, and glad to see you're working on a real solution also!

For reference, I use virtualenvwrapper to configure my virtualenvs. Everything from my Python environment is in `~/.virtualenvs/[virtualenvname]/` when I activate it, essentially. I'm running Emacs bzr from a few days ago (pulled from Git mirror, ce70b2e) + python-mode bzr revno 1515 (2014-06-04). I'm using python 3.4 from Debian Testing with all Python packages pulled via pip.

Unfortunately, the above as posted isn't loading in the current buffer, but works on all future buffers. I could chock that up to running development versions of absolutely everything, but I do think advising is the way to go and I think I should be able to find a configuration that works.

Thanks for the tips - and I agree with you, saving and restoring the pylint executable is necessary also. You wouldn't want to be using a venv pylint after deactivating it.

Can you help with this problem?

Provide an answer of your own, or ask Nathan Typanski for more information if necessary.

To post a message you must log in.