summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSiddhant Kumar <saytosid@gmail.com>2019-12-15 19:13:08 +0000
committerBernat Gabor <bgabor8@bloomberg.net>2020-01-10 15:38:36 +0000
commitc72cd301583aebcd8f0565673ac1847ee9fe0faa (patch)
tree487d4f9db9ea0ca990a834076664d5b43995efee /src
parent7928094d2df6910802a638e6919cf5e30977956d (diff)
downloadvirtualenv-c72cd301583aebcd8f0565673ac1847ee9fe0faa.tar.gz
Activation scripts for next-gen virtualenv (#1454)
Diffstat (limited to 'src')
-rw-r--r--src/virtualenv/activation/__init__.py18
-rw-r--r--src/virtualenv/activation/activator.py11
-rw-r--r--src/virtualenv/activation/bash/__init__.py14
-rw-r--r--src/virtualenv/activation/bash/activate.sh84
-rw-r--r--src/virtualenv/activation/batch/__init__.py16
-rw-r--r--src/virtualenv/activation/batch/activate.bat35
-rw-r--r--src/virtualenv/activation/batch/deactivate.bat19
-rw-r--r--src/virtualenv/activation/batch/pydoc.bat1
-rw-r--r--src/virtualenv/activation/cshell/__init__.py14
-rw-r--r--src/virtualenv/activation/cshell/activate.csh55
-rw-r--r--src/virtualenv/activation/fish/__init__.py14
-rw-r--r--src/virtualenv/activation/fish/activate.fish102
-rw-r--r--src/virtualenv/activation/powershell/__init__.py10
-rw-r--r--src/virtualenv/activation/powershell/activate.ps160
-rw-r--r--src/virtualenv/activation/python/__init__.py19
-rw-r--r--src/virtualenv/activation/python/activate_this.py45
-rw-r--r--src/virtualenv/activation/via_template.py38
-rw-r--r--src/virtualenv/activation/xonosh/__init__.py14
-rw-r--r--src/virtualenv/activation/xonosh/activate.xsh46
-rw-r--r--src/virtualenv/config/cli/parser.py2
-rw-r--r--src/virtualenv/interpreters/create/cpython/common.py4
-rw-r--r--src/virtualenv/interpreters/create/creator.py12
-rw-r--r--src/virtualenv/run.py26
-rw-r--r--src/virtualenv/seed/embed/link_app_data.py2
-rw-r--r--src/virtualenv/session.py2
25 files changed, 637 insertions, 26 deletions
diff --git a/src/virtualenv/activation/__init__.py b/src/virtualenv/activation/__init__.py
index 01e6d4f..dbe54fc 100644
--- a/src/virtualenv/activation/__init__.py
+++ b/src/virtualenv/activation/__init__.py
@@ -1 +1,19 @@
from __future__ import absolute_import, unicode_literals
+
+from .bash import BashActivator
+from .batch import BatchActivator
+from .cshell import CShellActivator
+from .fish import FishActivator
+from .powershell import PowerShellActivator
+from .python import PythonActivator
+from .xonosh import XonoshActivator
+
+__all__ = [
+ BashActivator,
+ PowerShellActivator,
+ XonoshActivator,
+ CShellActivator,
+ PythonActivator,
+ BatchActivator,
+ FishActivator,
+]
diff --git a/src/virtualenv/activation/activator.py b/src/virtualenv/activation/activator.py
index be8deed..d5cd10c 100644
--- a/src/virtualenv/activation/activator.py
+++ b/src/virtualenv/activation/activator.py
@@ -12,13 +12,12 @@ class Activator(object):
@classmethod
def add_parser_arguments(cls, parser):
- pass
+ """add activator options"""
- def run(self, creator):
- self.generate()
- if self.flag_prompt is not None:
- creator.pyenv_cfg["prompt"] = self.flag_prompt
+ @classmethod
+ def supports(cls, interpreter):
+ return True
@abstractmethod
- def generate(self):
+ def generate(self, creator):
raise NotImplementedError
diff --git a/src/virtualenv/activation/bash/__init__.py b/src/virtualenv/activation/bash/__init__.py
new file mode 100644
index 0000000..fd53741
--- /dev/null
+++ b/src/virtualenv/activation/bash/__init__.py
@@ -0,0 +1,14 @@
+from __future__ import absolute_import, unicode_literals
+
+from pathlib2 import Path
+
+from ..via_template import ViaTemplateActivator
+
+
+class BashActivator(ViaTemplateActivator):
+ @classmethod
+ def supports(cls, interpreter):
+ return interpreter.os != "nt"
+
+ def templates(self):
+ yield Path("activate.sh")
diff --git a/src/virtualenv/activation/bash/activate.sh b/src/virtualenv/activation/bash/activate.sh
new file mode 100644
index 0000000..d9b8781
--- /dev/null
+++ b/src/virtualenv/activation/bash/activate.sh
@@ -0,0 +1,84 @@
+# 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="__VIRTUAL_ENV__"
+export VIRTUAL_ENV
+
+_OLD_VIRTUAL_PATH="$PATH"
+PATH="$VIRTUAL_ENV/__BIN_NAME__:$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__VIRTUAL_PROMPT__" != x ] ; then
+ PS1="__VIRTUAL_PROMPT__${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
diff --git a/src/virtualenv/activation/batch/__init__.py b/src/virtualenv/activation/batch/__init__.py
new file mode 100644
index 0000000..4e4b839
--- /dev/null
+++ b/src/virtualenv/activation/batch/__init__.py
@@ -0,0 +1,16 @@
+from __future__ import absolute_import, unicode_literals
+
+from pathlib2 import Path
+
+from ..via_template import ViaTemplateActivator
+
+
+class BatchActivator(ViaTemplateActivator):
+ @classmethod
+ def supports(cls, interpreter):
+ return interpreter.os == "nt"
+
+ def templates(self):
+ yield Path("activate.bat")
+ yield Path("deactivate.bat")
+ yield Path("pydoc.bat")
diff --git a/src/virtualenv/activation/batch/activate.bat b/src/virtualenv/activation/batch/activate.bat
new file mode 100644
index 0000000..96e835b
--- /dev/null
+++ b/src/virtualenv/activation/batch/activate.bat
@@ -0,0 +1,35 @@
+@echo off
+
+set "VIRTUAL_ENV=__VIRTUAL_ENV__"
+
+if defined _OLD_VIRTUAL_PROMPT (
+ set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
+) else (
+ if not defined PROMPT (
+ set "PROMPT=$P$G"
+ )
+ if not defined VIRTUAL_ENV_DISABLE_PROMPT (
+ set "_OLD_VIRTUAL_PROMPT=%PROMPT%"
+ )
+)
+if not defined VIRTUAL_ENV_DISABLE_PROMPT (
+ set "PROMPT=__VIRTUAL_PROMPT__%PROMPT%"
+)
+
+REM Don't use () to avoid problems with them in %PATH%
+if defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME
+ set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%"
+:ENDIFVHOME
+
+set PYTHONHOME=
+
+REM if defined _OLD_VIRTUAL_PATH (
+if not defined _OLD_VIRTUAL_PATH goto ENDIFVPATH1
+ set "PATH=%_OLD_VIRTUAL_PATH%"
+:ENDIFVPATH1
+REM ) else (
+if defined _OLD_VIRTUAL_PATH goto ENDIFVPATH2
+ set "_OLD_VIRTUAL_PATH=%PATH%"
+:ENDIFVPATH2
+
+set "PATH=%VIRTUAL_ENV%\__BIN_NAME__;%PATH%"
diff --git a/src/virtualenv/activation/batch/deactivate.bat b/src/virtualenv/activation/batch/deactivate.bat
new file mode 100644
index 0000000..7bbc568
--- /dev/null
+++ b/src/virtualenv/activation/batch/deactivate.bat
@@ -0,0 +1,19 @@
+@echo off
+
+set VIRTUAL_ENV=
+
+REM Don't use () to avoid problems with them in %PATH%
+if not defined _OLD_VIRTUAL_PROMPT goto ENDIFVPROMPT
+ set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
+ set _OLD_VIRTUAL_PROMPT=
+:ENDIFVPROMPT
+
+if not defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME
+ set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%"
+ set _OLD_VIRTUAL_PYTHONHOME=
+:ENDIFVHOME
+
+if not defined _OLD_VIRTUAL_PATH goto ENDIFVPATH
+ set "PATH=%_OLD_VIRTUAL_PATH%"
+ set _OLD_VIRTUAL_PATH=
+:ENDIFVPATH
diff --git a/src/virtualenv/activation/batch/pydoc.bat b/src/virtualenv/activation/batch/pydoc.bat
new file mode 100644
index 0000000..3d46a23
--- /dev/null
+++ b/src/virtualenv/activation/batch/pydoc.bat
@@ -0,0 +1 @@
+python.exe -m pydoc %*
diff --git a/src/virtualenv/activation/cshell/__init__.py b/src/virtualenv/activation/cshell/__init__.py
new file mode 100644
index 0000000..e818ede
--- /dev/null
+++ b/src/virtualenv/activation/cshell/__init__.py
@@ -0,0 +1,14 @@
+from __future__ import absolute_import, unicode_literals
+
+from pathlib2 import Path
+
+from ..via_template import ViaTemplateActivator
+
+
+class CShellActivator(ViaTemplateActivator):
+ @classmethod
+ def supports(cls, interpreter):
+ return interpreter.os != "nt"
+
+ def templates(self):
+ yield Path("activate.csh")
diff --git a/src/virtualenv/activation/cshell/activate.csh b/src/virtualenv/activation/cshell/activate.csh
new file mode 100644
index 0000000..c4a6d58
--- /dev/null
+++ b/src/virtualenv/activation/cshell/activate.csh
@@ -0,0 +1,55 @@
+# This file must be used with "source bin/activate.csh" *from csh*.
+# You cannot run it directly.
+# Created by Davide Di Blasi <davidedb@gmail.com>.
+
+set newline='\
+'
+
+alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc'
+
+# Unset irrelevant variables.
+deactivate nondestructive
+
+setenv VIRTUAL_ENV "__VIRTUAL_ENV__"
+
+set _OLD_VIRTUAL_PATH="$PATH:q"
+setenv PATH "$VIRTUAL_ENV:q/__BIN_NAME__:$PATH:q"
+
+
+
+if ("__VIRTUAL_PROMPT__" != "") then
+ set env_name = "__VIRTUAL_PROMPT__"
+else
+ set env_name = '('"$VIRTUAL_ENV:t:q"') '
+endif
+
+if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then
+ if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then
+ set do_prompt = "1"
+ else
+ set do_prompt = "0"
+ endif
+else
+ set do_prompt = "1"
+endif
+
+if ( $do_prompt == "1" ) then
+ # Could be in a non-interactive environment,
+ # in which case, $prompt is undefined and we wouldn't
+ # care about the prompt anyway.
+ if ( $?prompt ) then
+ set _OLD_VIRTUAL_PROMPT="$prompt:q"
+ if ( "$prompt:q" =~ *"$newline:q"* ) then
+ :
+ else
+ set prompt = "$env_name:q$prompt:q"
+ endif
+ endif
+endif
+
+unset env_name
+unset do_prompt
+
+alias pydoc python -m pydoc
+
+rehash
diff --git a/src/virtualenv/activation/fish/__init__.py b/src/virtualenv/activation/fish/__init__.py
new file mode 100644
index 0000000..0e54406
--- /dev/null
+++ b/src/virtualenv/activation/fish/__init__.py
@@ -0,0 +1,14 @@
+from __future__ import absolute_import, unicode_literals
+
+from pathlib2 import Path
+
+from ..via_template import ViaTemplateActivator
+
+
+class FishActivator(ViaTemplateActivator):
+ def templates(self):
+ yield Path("activate.fish")
+
+ @classmethod
+ def supports(cls, interpreter):
+ return interpreter.os != "nt"
diff --git a/src/virtualenv/activation/fish/activate.fish b/src/virtualenv/activation/fish/activate.fish
new file mode 100644
index 0000000..4e29768
--- /dev/null
+++ b/src/virtualenv/activation/fish/activate.fish
@@ -0,0 +1,102 @@
+# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*.
+# Do not run it directly.
+
+function _bashify_path -d "Converts a fish path to something bash can recognize"
+ set fishy_path $argv
+ set bashy_path $fishy_path[1]
+ for path_part in $fishy_path[2..-1]
+ set bashy_path "$bashy_path:$path_part"
+ end
+ echo $bashy_path
+end
+
+function _fishify_path -d "Converts a bash path to something fish can recognize"
+ echo $argv | tr ':' '\n'
+end
+
+function deactivate -d 'Exit virtualenv mode and return to the normal environment.'
+ # reset old environment variables
+ if test -n "$_OLD_VIRTUAL_PATH"
+ # https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling
+ if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3
+ set -gx PATH (_fishify_path $_OLD_VIRTUAL_PATH)
+ else
+ set -gx PATH $_OLD_VIRTUAL_PATH
+ end
+ set -e _OLD_VIRTUAL_PATH
+ end
+
+ if test -n "$_OLD_VIRTUAL_PYTHONHOME"
+ set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
+ set -e _OLD_VIRTUAL_PYTHONHOME
+ end
+
+ if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
+ and functions -q _old_fish_prompt
+ # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`.
+ set -l fish_function_path
+
+ # Erase virtualenv's `fish_prompt` and restore the original.
+ functions -e fish_prompt
+ functions -c _old_fish_prompt fish_prompt
+ functions -e _old_fish_prompt
+ set -e _OLD_FISH_PROMPT_OVERRIDE
+ end
+
+ set -e VIRTUAL_ENV
+
+ if test "$argv[1]" != 'nondestructive'
+ # Self-destruct!
+ functions -e pydoc
+ functions -e deactivate
+ functions -e _bashify_path
+ functions -e _fishify_path
+ end
+end
+
+# Unset irrelevant variables.
+deactivate nondestructive
+
+set -gx VIRTUAL_ENV "__VIRTUAL_ENV__"
+
+# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling
+if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3
+ set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH)
+else
+ set -gx _OLD_VIRTUAL_PATH $PATH
+end
+set -gx PATH "$VIRTUAL_ENV/__BIN_NAME__" $PATH
+
+# Unset `$PYTHONHOME` if set.
+if set -q PYTHONHOME
+ set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
+ set -e PYTHONHOME
+end
+
+function pydoc
+ python -m pydoc $argv
+end
+
+if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
+ # Copy the current `fish_prompt` function as `_old_fish_prompt`.
+ functions -c fish_prompt _old_fish_prompt
+
+ function fish_prompt
+ # Save the current $status, for fish_prompts that display it.
+ set -l old_status $status
+
+ # Prompt override provided?
+ # If not, just prepend the environment name.
+ if test -n "__VIRTUAL_PROMPT__"
+ printf '%s%s' "__VIRTUAL_PROMPT__" (set_color normal)
+ else
+ printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV")
+ end
+
+ # Restore the original $status
+ echo "exit $old_status" | source
+ _old_fish_prompt
+ end
+
+ set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
+end
diff --git a/src/virtualenv/activation/powershell/__init__.py b/src/virtualenv/activation/powershell/__init__.py
new file mode 100644
index 0000000..b5b0a75
--- /dev/null
+++ b/src/virtualenv/activation/powershell/__init__.py
@@ -0,0 +1,10 @@
+from __future__ import absolute_import, unicode_literals
+
+from pathlib2 import Path
+
+from ..via_template import ViaTemplateActivator
+
+
+class PowerShellActivator(ViaTemplateActivator):
+ def templates(self):
+ yield Path("activate.ps1")
diff --git a/src/virtualenv/activation/powershell/activate.ps1 b/src/virtualenv/activation/powershell/activate.ps1
new file mode 100644
index 0000000..85b2103
--- /dev/null
+++ b/src/virtualenv/activation/powershell/activate.ps1
@@ -0,0 +1,60 @@
+$script:THIS_PATH = $myinvocation.mycommand.path
+$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
+
+function global:deactivate([switch] $NonDestructive) {
+ if (Test-Path variable:_OLD_VIRTUAL_PATH) {
+ $env:PATH = $variable:_OLD_VIRTUAL_PATH
+ Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
+ }
+
+ if (Test-Path function:_old_virtual_prompt) {
+ $function:prompt = $function:_old_virtual_prompt
+ Remove-Item function:\_old_virtual_prompt
+ }
+
+ if ($env:VIRTUAL_ENV) {
+ Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
+ }
+
+ if (!$NonDestructive) {
+ # Self destruct!
+ Remove-Item function:deactivate
+ Remove-Item function:pydoc
+ }
+}
+
+function global:pydoc {
+ python -m pydoc $args
+}
+
+# unset irrelevant variables
+deactivate -nondestructive
+
+$VIRTUAL_ENV = $BASE_DIR
+$env:VIRTUAL_ENV = $VIRTUAL_ENV
+
+New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
+
+$env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH
+if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
+ function global:_old_virtual_prompt {
+ ""
+ }
+ $function:_old_virtual_prompt = $function:prompt
+
+ if ("__VIRTUAL_PROMPT__" -ne "") {
+ function global:prompt {
+ # Add the custom prefix to the existing prompt
+ $previous_prompt_value = & $function:_old_virtual_prompt
+ ("__VIRTUAL_PROMPT__" + $previous_prompt_value)
+ }
+ }
+ else {
+ function global:prompt {
+ # Add a prefix to the current prompt, but don't discard it.
+ $previous_prompt_value = & $function:_old_virtual_prompt
+ $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) "
+ ($new_prompt_value + $previous_prompt_value)
+ }
+ }
+}
diff --git a/src/virtualenv/activation/python/__init__.py b/src/virtualenv/activation/python/__init__.py
new file mode 100644
index 0000000..1d73e99
--- /dev/null
+++ b/src/virtualenv/activation/python/__init__.py
@@ -0,0 +1,19 @@
+from __future__ import absolute_import, unicode_literals
+
+import json
+import os
+
+from pathlib2 import Path
+
+from ..via_template import ViaTemplateActivator
+
+
+class PythonActivator(ViaTemplateActivator):
+ def templates(self):
+ yield Path("activate_this.py")
+
+ def replacements(self, creator, dest_folder):
+ replacements = super(PythonActivator, self).replacements(creator, dest_folder)
+ site_dump = json.dumps([os.path.relpath(str(i), str(dest_folder)) for i in creator.site_packages], indent=2)
+ replacements.update({"__SITE_PACKAGES__": site_dump})
+ return replacements
diff --git a/src/virtualenv/activation/python/activate_this.py b/src/virtualenv/activation/python/activate_this.py
new file mode 100644
index 0000000..fc8d449
--- /dev/null
+++ b/src/virtualenv/activation/python/activate_this.py
@@ -0,0 +1,45 @@
+"""Activate virtualenv for current interpreter:
+
+Use exec(open(this_file).read(), {'__file__': this_file}).
+
+This can be used when you must use an existing Python interpreter, not the virtualenv bin/python.
+"""
+import json
+import os
+import site
+import sys
+
+try:
+ __file__
+except NameError:
+ raise AssertionError("You must use exec(open(this_file).read(), {'__file__': this_file}))")
+
+# prepend bin to PATH (this file is inside the bin directory)
+bin_dir = os.path.dirname(os.path.abspath(__file__))
+os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep))
+
+base = os.path.dirname(bin_dir)
+
+# virtual env is right above bin directory
+os.environ["VIRTUAL_ENV"] = base
+
+# add the virtual environments site-packages to the host python import mechanism
+prev = set(sys.path)
+
+# fmt: off
+# turn formatter off as json dumps will contain " characters - so we really need here ' black
+site_packages = r'''
+__SITE_PACKAGES__
+'''
+
+for site_package in json.loads(site_packages):
+ path = os.path.realpath(os.path.join(os.path.dirname(__file__), site_package))
+ site.addsitedir(path)
+# fmt: on
+
+sys.real_prefix = sys.prefix
+sys.prefix = base
+
+# Move the added items to the front of the path, in place
+new = list(sys.path)
+sys.path[:] = [i for i in new if i not in prev] + [i for i in new if i in prev]
diff --git a/src/virtualenv/activation/via_template.py b/src/virtualenv/activation/via_template.py
new file mode 100644
index 0000000..864454f
--- /dev/null
+++ b/src/virtualenv/activation/via_template.py
@@ -0,0 +1,38 @@
+from __future__ import absolute_import, unicode_literals
+
+import os
+import pkgutil
+from abc import ABCMeta, abstractmethod
+
+import six
+
+from .activator import Activator
+
+
+@six.add_metaclass(ABCMeta)
+class ViaTemplateActivator(Activator):
+ @abstractmethod
+ def templates(self):
+ raise NotImplementedError
+
+ def generate(self, creator):
+ dest_folder = creator.bin_dir
+ self._generate(self.replacements(creator, dest_folder), self.templates(), dest_folder)
+ if self.flag_prompt is not None:
+ creator.pyenv_cfg["prompt"] = self.flag_prompt
+
+ def replacements(self, creator, dest_folder):
+ return {
+ "__VIRTUAL_PROMPT__": "" if self.flag_prompt is None else self.flag_prompt,
+ "__VIRTUAL_ENV__": str(creator.dest_dir),
+ "__VIRTUAL_NAME__": str(creator.env_name),
+ "__BIN_NAME__": str(creator.bin_name),
+ "__PATH_SEP__": os.pathsep,
+ }
+
+ def _generate(self, replacements, templates, to_folder):
+ for template in templates:
+ text = pkgutil.get_data(self.__module__, str(template)).decode("utf-8")
+ for start, end in replacements.items():
+ text = text.replace(start, end)
+ (to_folder / template).write_text(text)
diff --git a/src/virtualenv/activation/xonosh/__init__.py b/src/virtualenv/activation/xonosh/__init__.py
new file mode 100644
index 0000000..ceb5340
--- /dev/null
+++ b/src/virtualenv/activation/xonosh/__init__.py
@@ -0,0 +1,14 @@
+from __future__ import absolute_import, unicode_literals
+
+from pathlib2 import Path
+
+from ..via_template import ViaTemplateActivator
+
+
+class XonoshActivator(ViaTemplateActivator):
+ def templates(self):
+ yield Path("activate.xsh")
+
+ @classmethod
+ def supports(cls, interpreter):
+ return True if interpreter.version_info >= (3, 5) else False
diff --git a/src/virtualenv/activation/xonosh/activate.xsh b/src/virtualenv/activation/xonosh/activate.xsh
new file mode 100644
index 0000000..c77ea62
--- /dev/null
+++ b/src/virtualenv/activation/xonosh/activate.xsh
@@ -0,0 +1,46 @@
+"""Xonsh activate script for virtualenv"""
+from xonsh.tools import get_sep as _get_sep
+
+def _deactivate(args):
+ if "pydoc" in aliases:
+ del aliases["pydoc"]
+
+ if ${...}.get("_OLD_VIRTUAL_PATH", ""):
+ $PATH = $_OLD_VIRTUAL_PATH
+ del $_OLD_VIRTUAL_PATH
+
+ if ${...}.get("_OLD_VIRTUAL_PYTHONHOME", ""):
+ $PYTHONHOME = $_OLD_VIRTUAL_PYTHONHOME
+ del $_OLD_VIRTUAL_PYTHONHOME
+
+ if "VIRTUAL_ENV" in ${...}:
+ del $VIRTUAL_ENV
+
+ if "VIRTUAL_ENV_PROMPT" in ${...}:
+ del $VIRTUAL_ENV_PROMPT
+
+ if "nondestructive" not in args:
+ # Self destruct!
+ del aliases["deactivate"]
+
+
+# unset irrelevant variables
+_deactivate(["nondestructive"])
+aliases["deactivate"] = _deactivate
+
+$VIRTUAL_ENV = r"__VIRTUAL_ENV__"
+
+$_OLD_VIRTUAL_PATH = $PATH
+$PATH = $PATH[:]
+$PATH.add($VIRTUAL_ENV + _get_sep() + "__BIN_NAME__", front=True, replace=True)
+
+if ${...}.get("PYTHONHOME", ""):
+ # unset PYTHONHOME if set
+ $_OLD_VIRTUAL_PYTHONHOME = $PYTHONHOME
+ del $PYTHONHOME
+
+$VIRTUAL_ENV_PROMPT = "__VIRTUAL_PROMPT__"
+if not $VIRTUAL_ENV_PROMPT:
+ del $VIRTUAL_ENV_PROMPT
+
+aliases["pydoc"] = ["python", "-m", "pydoc"]
diff --git a/src/virtualenv/config/cli/parser.py b/src/virtualenv/config/cli/parser.py
index 083bda8..e817a42 100644
--- a/src/virtualenv/config/cli/parser.py
+++ b/src/virtualenv/config/cli/parser.py
@@ -52,7 +52,7 @@ class VirtualEnvConfigParser(ArgumentParser):
class HelpFormatter(ArgumentDefaultsHelpFormatter):
def __init__(self, prog):
- super(HelpFormatter, self).__init__(prog, max_help_position=35, width=240)
+ super(HelpFormatter, self).__init__(prog, max_help_position=37, width=240)
def _get_help_string(self, action):
# noinspection PyProtectedMember
diff --git a/src/virtualenv/interpreters/create/cpython/common.py b/src/virtualenv/interpreters/create/cpython/common.py
index b322be1..d05d47b 100644
--- a/src/virtualenv/interpreters/create/cpython/common.py
+++ b/src/virtualenv/interpreters/create/cpython/common.py
@@ -34,7 +34,7 @@ class CPython(ViaGlobalRef):
self.system_site_package = true_system_site
def ensure_directories(self):
- dirs = [self.env_dir, self.bin_dir]
+ dirs = [self.dest_dir, self.bin_dir]
dirs.extend(self.site_packages)
return dirs
@@ -53,7 +53,7 @@ class CPython(ViaGlobalRef):
@property
def lib_dir(self):
- return self.env_dir / self.lib_base
+ return self.dest_dir / self.lib_base
@property
def system_stdlib(self):
diff --git a/src/virtualenv/interpreters/create/creator.py b/src/virtualenv/interpreters/create/creator.py
index 079aad9..872d8d1 100644
--- a/src/virtualenv/interpreters/create/creator.py
+++ b/src/virtualenv/interpreters/create/creator.py
@@ -103,12 +103,8 @@ class Creator(object):
}
@property
- def env_dir(self):
- return Path(self.dest_dir)
-
- @property
def env_name(self):
- return self.env_dir.parts[-1]
+ return self.dest_dir.parts[-1]
@property
def bin_name(self):
@@ -116,7 +112,7 @@ class Creator(object):
@property
def bin_dir(self):
- return self.env_dir / self.bin_name
+ return self.dest_dir / self.bin_name
@property
def lib_dir(self):
@@ -127,13 +123,13 @@ class Creator(object):
return [self.lib_dir / "site-packages"]
@property
- def env_exe(self):
+ def exe(self):
return self.bin_dir / "python{}".format(".exe" if IS_WIN else "")
@property
def debug(self):
if self._debug is None:
- self._debug = get_env_debug_info(self.env_exe, self.debug_script())
+ self._debug = get_env_debug_info(self.exe, self.debug_script())
return self._debug
# noinspection PyMethodMayBeStatic
diff --git a/src/virtualenv/run.py b/src/virtualenv/run.py
index e6f0a22..96ad7d7 100644
--- a/src/virtualenv/run.py
+++ b/src/virtualenv/run.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import, unicode_literals
import logging
+from argparse import ArgumentTypeError
from entrypoints import get_group_named
@@ -134,17 +135,28 @@ def _collect_seeders():
def _get_activation(interpreter, parser, options):
activator_parser = parser.add_argument_group("activation script generator")
- activators = _collect_activators(interpreter)
+ compatible = collect_activators(interpreter)
+ default = ",".join(compatible.keys())
+
+ def _extract_activators(entered_str):
+ elements = [e.strip() for e in entered_str.split(",") if e.strip()]
+ missing = [e for e in elements if e not in compatible]
+ if missing:
+ raise ArgumentTypeError("the following activators are not available {}".format(",".join(missing)))
+ return elements
+
activator_parser.add_argument(
"--activators",
- choices=list(activators.keys()),
- default=list(activators.keys()),
+ default=default,
+ metavar="comma_separated_list",
required=False,
- nargs="*",
- help="activators to generate",
+ help="activators to generate together with virtual environment - default is all available and compatible",
+ type=_extract_activators,
)
yield
- active_activators = {k: v for k, v in activators.items() if k in options.activators}
+
+ selected_activators = _extract_activators(default) if options.activators is default else options.activators
+ active_activators = {k: v for k, v in compatible.items() if k in selected_activators}
activator_parser.add_argument(
"--prompt",
dest="prompt",
@@ -160,7 +172,7 @@ def _get_activation(interpreter, parser, options):
yield activator_instances
-def _collect_activators(interpreter):
+def collect_activators(interpreter):
all_activators = {e.name: e.load() for e in get_group_named("virtualenv.activate").values()}
activators = {k: v for k, v in all_activators.items() if v.supports(interpreter)}
return activators
diff --git a/src/virtualenv/seed/embed/link_app_data.py b/src/virtualenv/seed/embed/link_app_data.py
index f961a4c..c400da7 100644
--- a/src/virtualenv/seed/embed/link_app_data.py
+++ b/src/virtualenv/seed/embed/link_app_data.py
@@ -35,7 +35,7 @@ class LinkFromAppData(BaseEmbed):
def pip_install(wheels, creator, cache):
- site_package, bin_dir, env_exe = creator.site_packages[0], creator.bin_dir, creator.env_exe
+ site_package, bin_dir, env_exe = creator.site_packages[0], creator.bin_dir, creator.exe
folder_link_method, folder_linked = link_folder()
for name, wheel in wheels.items():
logging.debug("install %s from wheel %s", name, wheel)
diff --git a/src/virtualenv/session.py b/src/virtualenv/session.py
index 74a50f2..d69fc8f 100644
--- a/src/virtualenv/session.py
+++ b/src/virtualenv/session.py
@@ -29,7 +29,7 @@ class Session(object):
def _activate(self):
for activator in self.activators:
- activator.run(self.creator)
+ activator.generate(self.creator)
_DEBUG_MARKER = "=" * 30 + " target debug " + "=" * 30