Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autodetect .venv file in root of a project and switch automatically #51

Closed
korayal opened this issue Oct 14, 2016 · 12 comments
Closed

Autodetect .venv file in root of a project and switch automatically #51

korayal opened this issue Oct 14, 2016 · 12 comments
Labels

Comments

@korayal
Copy link

korayal commented Oct 14, 2016

I'm using VirtualFish on my fish terminal and it can automatically detect the .venv file at the root of the project and can automatically activate the virtualenv accordingly.

But on Spacemacs, I always have to choose the virtualenv manually via pyvenv-workon. Am i missing something here? Is there any other way to accomplish this?

@jorgenschaefer
Copy link
Owner

Hello! You are not missing anything – VirtualFish is a program for your shell, so your shell does some magic. Emacs is not your shell, so the magic does not work with Emacs.

I am not aware of any port of VirtualFish to Emacs. You can use pyvenv-mode to set the virtualenv based on a pyvenv-mode file or directory variable (see the Emacs manual on how to set those).

Does that answer your question?

@korayal
Copy link
Author

korayal commented Oct 14, 2016

yeah! thanks.

I guess I can add a hook for python-mode to activate the pyvenv if the root of the project of that file has a .venv file. But I'm too bad on elisp :) and it seems the command pyvenv-workon "myvenv" doesn't work on me.

@jorgenschaefer
Copy link
Owner

pyvenv-workon mimics virtualenvwrapper in trying to find named virtualenvs. For virtualenv directories, you can use pyvenv-activate :-)

@korayal
Copy link
Author

korayal commented Oct 14, 2016

I couldn't also manage to make it work automatically. So initially, what I'm trying to do is to manually set the virtualenv when the python-mode major mode is loaded:

(add-hook 'python-mode '(pyvenv-workon "myvenv"))

or

(add-hook 'python-mode '(pyvenv-activate "~/.virtualenv/myvenv"))

but both pyvenv-workon and pyvenv-activate require a prompt from the user (via interactive I guess) and since I can't bypass that, I couldn't make it work without my interference :/

@jorgenschaefer
Copy link
Owner

add-hook needs a function, not a list. Try (lambda () (pyvenv-workon "myvenv")).

@korayal
Copy link
Author

korayal commented Oct 14, 2016

Thanks, that did the trick. and i was also adding hook to the wrong place:

  (add-hook 'python-mode-hook (lambda() (pyvenv-workon "myvenv")))

so my next step will be to check if there is a .venv file, read that and run the command for that virtualenv.

@korayal
Copy link
Author

korayal commented Oct 14, 2016

It took some time but finally got what I wanted :)

  (defun pyvenv-autoload ()
    (require 'projectile)
    (let* ((pdir (projectile-project-root)) (pfile (concat pdir ".venv")))
      (if (file-exists-p pfile)
          (pyvenv-workon (with-temp-buffer
                           (insert-file-contents pfile)
                           (nth 0 (split-string (buffer-string))))))))
  (add-hook 'python-mode-hook 'pyvenv-autoload)

@captain-kark
Copy link

I modified this a bit to get it working for me:

(defun pyvenv-autoload ()
  "Automatically activates pyvenv version if .venv directory exists."
  (f-traverse-upwards
   (lambda (path)
     (let ((venv-path (f-expand ".venv" path)))
       (if (f-exists? venv-path)
           (progn
             (pyvenv-workon venv-path))
             t)))))

(add-hook 'python-mode-hook 'pyvenv-autoload)

@rhoit
Copy link

rhoit commented Oct 29, 2020

my mod for venv

(require 'pyvenv)

(defun pyvenv-autoload ()
          (interactive)
          "auto activate venv directory if exists"
          (f-traverse-upwards (lambda (path)
              (let ((venv-path (f-expand "venv" path)))
              (when (f-exists? venv-path)
              (pyvenv-activate venv-path))))))

(add-hook 'python-mode-hook 'pyvenv-autoload)

@hongyi-zhao
Copy link

hongyi-zhao commented Sep 29, 2021

My version for working with pyenv, python-mode, comint-mime, and ipython:

(use-package comint-mime
  :straight (:host github :repo "astoff/comint-mime"
             :files (:defaults "*.py" "*.sh"))
  :hook ((shell-mode inferior-python-mode) . comint-mime-setup))

(use-package pyvenv
  :init
  (setenv "WORKON_HOME" "~/.pyenv/versions")
  ;https://lists.gnu.org/archive/html/help-gnu-emacs/2021-09/msg00535.html
  (defun try/pyvenv-workon ()
    (when (buffer-file-name)
      (let* ((python-version ".python-version")
             (project-dir (locate-dominating-file (buffer-file-name) python-version)))
        (when project-dir
          (pyvenv-workon
            (with-temp-buffer
              (insert-file-contents (expand-file-name python-version project-dir))
              (car (split-string (buffer-string)))))))))

  :config
  (pyvenv-mode 1)
    (setq pyvenv-post-activate-hooks
        (list (lambda ()
                ;https://github.com/astoff/comint-mime#usage 
                ;https://github.com/astoff/comint-mime/issues/2#issuecomment-922462074
                (when (executable-find "ipython3")
                  (setq python-shell-interpreter "ipython3"
                        ;python-shell-interpreter-args "--simple-prompt --classic"
                        ;https://elpy.readthedocs.io/en/latest/ide.html#interpreter-setup
                        python-shell-interpreter-args "-i --simple-prompt --classic --pprint")))))              
  (setq pyvenv-post-deactivate-hooks
        (list (lambda ()
                (setq python-shell-interpreter "python3")))))

(use-package python-mode
  :hook (python-mode . try/pyvenv-workon))

Testing by hitting C-c C-c with the following python code opened in Emacs:

import matplotlib.pyplot as plt
from numpy import arange, pi, sin
from sympy import Symbol, integrate

t = arange(0, 2 * pi, .01)
plt.plot(sin(4 * t), sin(5 * t))
x = Symbol('x')
integrate(1/(1+x ** 3))

image

@xz-dev
Copy link

xz-dev commented Jan 23, 2023

my mod for venv

(require 'pyvenv)

(defun pyvenv-autoload ()
          (interactive)
          "auto activate venv directory if exists"
          (f-traverse-upwards (lambda (path)
              (let ((venv-path (f-expand "venv" path)))
              (when (f-exists? venv-path)
              (pyvenv-activate venv-path))))))

(add-hook 'python-mode-hook 'pyvenv-autoload)

If home path have a venv, that will enable it
So I change it like

(cl-defun pyvenv-autoload ()
  "auto activate venv directory if exists"
  (f-traverse-upwards (lambda (path)
                        (let ((venv-path (f-expand ".venv" path)))
                          (when (f-exists? venv-path)
                            (pyvenv-activate venv-path)
                            (cl-return-from pyvenv-autoload))))))

(add-hook 'python-mode-hook 'pyvenv-autoload)

@hongyi-zhao
Copy link

@xz-dev What is the difference between your method and my following configuration in the final effect?

#51 (comment)

(use-package pyvenv
  :init
  (setenv "WORKON_HOME" "~/.pyenv/versions")
  ;https://lists.gnu.org/archive/html/help-gnu-emacs/2021-09/msg00535.html
  (defun try/pyvenv-workon ()
    (when (buffer-file-name)
      (let* ((python-version ".python-version")
             (project-dir (locate-dominating-file (buffer-file-name) python-version)))
        (when project-dir
          (pyvenv-workon
            (with-temp-buffer
              (insert-file-contents (expand-file-name python-version project-dir))
              (car (split-string (buffer-string)))))))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants