2

I am aware of additional Lisp libraries that are able to activate a Python virtual environment without typing the following from an eshell command prompt: source /path/to/virtualenv/bin/activate. However, I would like to understand what the limitation is that prevents eshell from being able to execute that command. [Once I get beyond that initial hurdle, I can craft my own function to modify the process-environment, etc.]

ESHELL:

Welcome to the Emacs shell

/ $ (setq debug-on-error t)
t
/ $ (setenv "LANG" "UTF-8")
UTF-8
/ $ /path/to/bin/virtualenv-3.8 -v /path/to/.0.virtualenvs/tda_api
find interpreter for spec PythonSpec(path=/path/to/Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8)
proposed PythonInfo(spec=CPython3.8.6.final.0-64, exe=/path/to/Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8, platform=darwin, version='3.8.6 (default, Dec 18 2021, 14:27:40) \n[Clang 8.0.0 (clang-800.0.42.1)]', encoding_fs_io=utf-8-utf-8)
create virtual environment via CPython3Posix(dest=/path/to/.0.virtualenvs/tda_api, clear=False, no_vcs_ignore=False, global=False)
add seed packages via FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/HOME/Library/Application Support/virtualenv)
add activators for Bash, CShell, Fish, PowerShell, Python, Xonsh
created virtual environment CPython3.8.6.final.0-64 in 326ms
  creator CPython3Posix(dest=/path/to/.0.virtualenvs/tda_api, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/HOME/Library/Application Support/virtualenv)
    added seed packages: pip==20.3.1, setuptools==51.0.0, wheel==0.36.1
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
/ $ source /path/to/.0.virtualenvs/tda_api/bin/activate
/ $ # This file must be used with "source bin/activate" *from bash*
# you cannot run it directly


if [ "${BASH_SOURCE-}" = "$0" ]; then
    echo "You must source this script: \$ source $0" >&2
    exit 33
fi

deactivate () {
    unset -f pydoc >/dev/null 2>&1

    # reset old environment variables
    # ! [ -z ${VAR+_} ] returns true if VAR is declared at all
    if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then
        PATH="$_OLD_VIRTUAL_PATH"
        export PATH
        unset _OLD_VIRTUAL_PATH
    fi
    if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then
        PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
        export PYTHONHOME
        unset _OLD_VIRTUAL_PYTHONHOME
    fi

    # This should detect bash and zsh, which have a hash command that must
    # be called to get it to forget past commands.  Without forgetting
    # past commands the $PATH changes we made may not be respected
    if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
        hash -r 2>/dev/null
    fi

    if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then
        PS1="$_OLD_VIRTUAL_PS1"
        export PS1
        unset _OLD_VIRTUAL_PS1
    fi

    unset VIRTUAL_ENV
    if [ ! "${1-}" = "nondestructive" ] ; then
    # Self destruct!
        unset -f deactivate
    fi
}

# unset irrelevant variables
deactivate nondestructive

VIRTUAL_ENV='/path/to/.0.virtualenvs/tda_api'
if ([ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]) && $(command -v cygpath &> /dev/null) ; then
    VIRTUAL_ENV=$(cygpath -u "$VIRTUAL_ENV")
fi
export VIRTUAL_ENV

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

# unset PYTHONHOME if set
if ! [ -z "${PYTHONHOME+_}" ] ; then
    _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
    unset PYTHONHOME
fi

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
    _OLD_VIRTUAL_PS1="${PS1-}"
    if [ "x" != x ] ; then
        PS1="${PS1-}"
    else
        PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}"
    fi
    export PS1
fi

# Make sure to unalias pydoc if it's already there
alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true

pydoc () {
    python -m pydoc "$@"
}

# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands.  Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
    hash -r 2>/dev/null
fi

DEBUGGER:

Debugger entered--Lisp error: (error "Missing redirection target")
  signal(error ("Missing redirection target"))
  error("Missing redirection target")
  eshell-strip-redirections(("unset" "-f" "pydoc" (eshell-set-output-handle 2 'overwrite)))
  run-hook-with-args(eshell-strip-redirections ("unset" "-f" "pydoc" (eshell-set-output-handle 2 'overwrite)))
  eshell-parse-pipeline(("unset" "-f" "pydoc" (eshell-set-output-handle 1 'overwrite) "/dev/null" (eshell-set-output-handle 2 'overwrite)))
  #f(compiled-function (cmd) #<bytecode 0x41814335>)(("unset" "-f" "pydoc" (eshell-set-output-handle 1 'overwrite) "/dev/null" (eshell-set-output-handle 2 'overwrite)))
  mapcar(#f(compiled-function (cmd) #<bytecode 0x41814335>) (nil ("unset" "-f" "pydoc" (eshell-set-output-handle 1 'overwrite) "/dev/null" (eshell-set-output-handle 2 'overwrite)) nil nil nil ("if" "!" "[" "-z" (eshell-escape-arg (eshell-escape-arg (let ((indices ...)) (eshell-convert (eshell-command-to-value ...))))) (eshell-extended-glob "]")) ("then") ((eshell-convert (concat "PATH=" (eshell-to-flat-string (eshell-escape-arg (eshell-convert ...)))))) ("export" "PATH") ("unset" "_OLD_VIRTUAL_PATH") ("fi") ("if" "!" "[" "-z" (eshell-escape-arg (eshell-escape-arg (let ((indices ...)) (eshell-convert (eshell-command-to-value ...))))) (eshell-extended-glob "]")) ("then") ((eshell-convert (concat "PYTHONHOME=" (eshell-to-flat-string (eshell-escape-arg (eshell-convert ...)))))) ("export" "PYTHONHOME") ("unset" "_OLD_VIRTUAL_PYTHONHOME") ("fi") nil nil nil nil ("if" "[" "-n" (eshell-escape-arg (eshell-escape-arg (let ((indices ...)) (eshell-convert (eshell-command-to-value ...))))) (eshell-extended-glob "]") (eshell-operator "||") "[" "-n" (eshell-escape-arg (eshell-escape-arg (let ((indices ...)) (eshell-convert (eshell-command-to-value ...))))) (eshell-extended-glob "]")) ("then") ("hash" "-r" (eshell-set-output-handle 2 'overwrite) "/dev/null") ("fi") nil ("if" "!" "[" "-z" (eshell-escape-arg (eshell-escape-arg (let ((indices ...)) (eshell-convert (eshell-command-to-value ...))))) (eshell-extended-glob "]")) ("then") ((eshell-convert (concat "PS1=" (eshell-to-flat-string (eshell-escape-arg (eshell-convert ...)))))) ("export" "PS1") ("unset" "_OLD_VIRTUAL_PS1") ("fi") nil ("unset" "VIRTUAL_ENV") ("if" "[" "!" (eshell-escape-arg (eshell-escape-arg (let ((indices ...)) (eshell-convert (eshell-command-to-value ...))))) "=" (eshell-escape-arg "nondestructive") (eshell-extended-glob "]")) ("then") nil ("unset" "-f" "deactivate") ("fi")))
  eshell-parse-command((1877 . 2900))
  eshell-parse-subcommand-argument()
  run-hook-with-args-until-success(eshell-parse-subcommand-argument)
  eshell-parse-argument()
  eshell-parse-arguments(1656 4045)
  eshell-parse-command((1656 . 4045))
  eshell-source-file("/path/to/.0.virtualenvs/tda_ap..." nil t)
  eshell/source("/path/to/.0.virtualenvs/tda_ap...")
  apply(eshell/source "/path/to/.0.virtualenvs/tda_ap...")
  eshell-exec-lisp(eshell-print eshell-error eshell/source ("/path/to/.0.virtualenvs/tda_ap...") nil)
  eshell-lisp-command(eshell/source ("/path/to/.0.virtualenvs/tda_ap..."))
  eshell-plain-command("source" ("/path/to/.0.virtualenvs/tda_ap..."))
  eshell-named-command("source" ("/path/to/.0.virtualenvs/tda_ap..."))
  eval((eshell-named-command '"source" '("/path/to/.0.virtualenvs/tda_ap...")))
  eshell-do-eval((eshell-named-command '"source" '("/path/to/.0.virtualenvs/tda_ap...")) nil)
  eshell-do-eval((prog1 (eshell-named-command '"source" '("/path/to/.0.virtualenvs/tda_ap...")) (mapc #'funcall eshell-this-command-hook)) nil)
  (condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"source" '("/path/to/.0.virtualenvs/tda_ap...")) (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1)))
  eval((condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"source" '("/path/to/.0.virtualenvs/tda_ap...")) (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))
  eshell-do-eval((condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"source" '("/path/to/.0.virtualenvs/tda_ap...")) (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))) nil)
  #f(compiled-function () #<bytecode 0x4142fda9>)()
  funcall(#f(compiled-function () #<bytecode 0x4142fda9>))
  (let ((eshell-this-command-hook '(ignore))) (funcall '#f(compiled-function () #<bytecode 0x4142fda9>)))
  eval((let ((eshell-this-command-hook '(ignore))) (funcall '#f(compiled-function () #<bytecode 0x4142fda9>))))
  eshell-do-eval((let ((eshell-this-command-hook '(ignore))) (condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"source" '...) (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1)))) nil)
  eshell-do-eval((progn (let ((eshell-this-command-hook '(ignore))) (condition-case err (eshell-do-eval '(prog1 (eshell-named-command ... ...) (mapc ... eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))) nil)
  (catch 'top-level (eshell-do-eval '(progn (let ((eshell-this-command-hook '...)) (condition-case err (eshell-do-eval '... nil) ((debug error) (mapc ... eshell-this-command-hook) (eshell-errorn ...) (eshell-close-handles 1))))) nil))
  eval((catch 'top-level (eshell-do-eval '(progn (let ((eshell-this-command-hook ...)) (condition-case err (eshell-do-eval ... nil) (... ... ... ...)))) nil)))
  eshell-do-eval((catch 'top-level (eshell-do-eval '(progn (let ((eshell-this-command-hook ...)) (condition-case err (eshell-do-eval ... nil) (... ... ... ...)))) nil)) nil)
  eshell-do-eval((progn 'nil (catch 'top-level (eshell-do-eval '(progn (let (...) (condition-case err ... ...))) nil)) (run-hooks 'eshell-post-command-hook)) nil)
  #f(compiled-function () #<bytecode 0x4142fd89>)()
  funcall(#f(compiled-function () #<bytecode 0x4142fd89>))
  (let ((eshell-current-subjob-p 'nil) (eshell-current-handles '[nil (t . 1) (t . 1)])) (funcall '#f(compiled-function () #<bytecode 0x4142fd89>)))
  eval((let ((eshell-current-subjob-p 'nil) (eshell-current-handles '[nil (t . 1) (t . 1)])) (funcall '#f(compiled-function () #<bytecode 0x4142fd89>))))
  eshell-do-eval((let ((eshell-current-handles '[nil (t . 1) (t . 1)]) eshell-current-subjob-p) (progn 'nil (catch 'top-level (eshell-do-eval '(progn (let ... ...)) nil)) (run-hooks 'eshell-post-command-hook))))
  eshell-resume-eval()
  eshell-eval-command((let ((eshell-current-handles '[nil (t . 1) (t . 1)]) eshell-current-subjob-p) (progn 'nil (catch 'top-level (eshell-do-eval '(progn (let ... ...)) nil)) (run-hooks 'eshell-post-command-hook))) "source /path/to/.0.virtualenvs...")
  eshell-send-input(nil)
  funcall-interactively(eshell-send-input nil)
  call-interactively(eshell-send-input nil nil)
  command-execute(eshell-send-input)

1 Answer 1

2

The source command reads in a file and executes it within the current environment. When you run source foo in a Bash shell, it expects the file called foo to have bash syntax in it. When you run source foo in Eshell, it expects the file to have eshell syntax in it. These syntaxes are not the same!

You tried to execute a Bash script inside Eshell, which just isn’t going to work. Since Bash is so popular, virtualenv assumes that you aren’t going to use something else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.