summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Skinn <brian.skinn@gmail.com>2019-04-10 09:38:28 -0400
committerBernát Gábor <gaborjbernat@gmail.com>2019-04-10 09:38:28 -0400
commitc787671ec455e3212fd78126cea558b318f48806 (patch)
treeef62de3e986e33b8c79738640e8ed56aa4202def
parent124d0eda3f376e0a34544f0dc07f7b557eb69e34 (diff)
downloadvirtualenv-c787671ec455e3212fd78126cea558b318f48806.tar.gz
Implement prompt consistency tests and harmonize all activate scripts (#1330)
See history of [bskinn/virtualenv:all-prompts branch](https://github.com/bskinn/virtualenv/commits/all-prompts), tip at bskinn/virtualenv@67cda5f, for the actual sequence of development of the prompt tests, leading to the first commit of the PR (e6a2b99)
-rw-r--r--CONTRIBUTING.rst9
-rw-r--r--docs/changelog/1330.bugfix.rst2
-rw-r--r--docs/development.rst7
-rw-r--r--docs/reference.rst6
-rw-r--r--tests/activation/test_prompts.py440
-rwxr-xr-xvirtualenv.py74
-rw-r--r--virtualenv_embedded/activate.bat9
-rw-r--r--virtualenv_embedded/activate.csh31
-rw-r--r--virtualenv_embedded/activate.ps122
-rw-r--r--virtualenv_embedded/activate.xsh7
10 files changed, 550 insertions, 57 deletions
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 29c52c2..cd53c35 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -13,8 +13,13 @@ Contributor notes
* Pull requests should be made against ``master`` branch, which is also our
latest stable version.
-* All changes to files inside virtualenv_embedded should be integrated to
- ``virtualenv.py`` with ``tox -e embed``
+* All changes to files inside virtualenv_embedded must be integrated to
+ ``virtualenv.py`` with ``tox -e embed``. The tox run will report failure
+ when changes are integrated, as a flag for CI.
+
+* The codebase must be linted with ``tox -e fix_lint`` before being merged.
+ The tox run will report failure when the linters revise code, as a flag
+ for CI.
.. _git-flow: https://github.com/nvie/gitflow
.. _coordinate development: http://nvie.com/posts/a-successful-git-branching-model/
diff --git a/docs/changelog/1330.bugfix.rst b/docs/changelog/1330.bugfix.rst
new file mode 100644
index 0000000..0d7072b
--- /dev/null
+++ b/docs/changelog/1330.bugfix.rst
@@ -0,0 +1,2 @@
+Add tests covering prompt manipulation during activation/deactivation,
+and harmonize behavior of all supported shells - by ``bskinn``
diff --git a/docs/development.rst b/docs/development.rst
index 6eee7d3..a7d72d1 100644
--- a/docs/development.rst
+++ b/docs/development.rst
@@ -17,7 +17,12 @@ Files in the ``virtualenv_embedded/`` subdirectory are embedded into
single-file use of ``virtualenv.py`` without installing it). If your patch
changes any file in ``virtualenv_embedded/``, run ``tox -e embed`` to update
the embedded version of that file in ``virtualenv.py``; commit that and submit
-it as part of your patch / pull request.
+it as part of your patch / pull request. The tox run will report failure
+when changes are embedded, as a flag for CI.
+
+The codebase should be linted before a pull request is merged by running
+``tox -e fix_lint``. The tox run will report failure when any linting
+revisions are required, as a flag for CI.
.. _pip development: https://pip.pypa.io/en/latest/development/
.. _virtualenv repo: https://github.com/pypa/virtualenv/
diff --git a/docs/reference.rst b/docs/reference.rst
index e623a91..deec504 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -148,8 +148,10 @@ is the same as calling::
.. envvar:: VIRTUAL_ENV_DISABLE_PROMPT
- Any virtualenv created when this is set to a non-empty value will not have
- it's :ref:`activate` modify the shell prompt.
+ Any virtualenv *activated* when this is set to a non-empty value will leave
+ the shell prompt unchanged during processing of the
+ :ref:`activate script <activate>`, rather than modifying it to indicate
+ the newly activated environment.
Configuration File
diff --git a/tests/activation/test_prompts.py b/tests/activation/test_prompts.py
new file mode 100644
index 0000000..8db4662
--- /dev/null
+++ b/tests/activation/test_prompts.py
@@ -0,0 +1,440 @@
+"""test that prompt behavior is correct in supported shells"""
+from __future__ import absolute_import, unicode_literals
+
+import os
+import subprocess
+import sys
+from textwrap import dedent
+
+import pytest
+
+import virtualenv
+from virtualenv import IS_DARWIN, IS_WIN
+
+try:
+ from pathlib import Path
+except ImportError:
+ from pathlib2 import Path
+
+VIRTUAL_ENV_DISABLE_PROMPT = "VIRTUAL_ENV_DISABLE_PROMPT"
+
+# This must match the DEST_DIR provided in the ../conftest.py:clean_python fixture
+ENV_DEFAULT = "env"
+
+# This can be anything
+ENV_CUSTOM = "env_custom"
+
+# Standard prefix, surround the env name in parentheses and separate by a space
+PREFIX_DEFAULT = "({}) ".format(ENV_DEFAULT)
+
+# Arbitrary prefix for the environment that's provided a 'prompt' arg
+PREFIX_CUSTOM = "---ENV---"
+
+# Temp script filename template: {shell}.script.(normal|suppress).(default|custom)[extension]
+SCRIPT_TEMPLATE = "{}.script.{}.{}{}"
+
+# Temp output filename template: {shell}.out.(normal|suppress).(default|custom)
+OUTPUT_TEMPLATE = "{}.out.{}.{}"
+
+# For skipping shells not installed by default if absent on a contributor's system
+IS_INSIDE_CI = "CI_RUN" in os.environ
+
+
+# Py2 doesn't like unicode in the environment
+def env_compat(string):
+ return string.encode("utf-8") if sys.version_info.major < 3 else string
+
+
+class ShellInfo(object):
+ """Parent class for shell information for prompt testing."""
+
+ # Typo insurance
+ __slots__ = []
+
+ # Equality check based on .name, but only if both are not None
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return False
+ if self.name is None or other.name is None:
+ return False
+ return self.name == other.name
+
+ # Helper formatting string
+ @property
+ def platform_incompat_msg(self):
+ return "No sane provision for {} on {{}} yet".format(self.name)
+
+ # Each shell must specify
+ name = None
+ avail_cmd = None
+ execute_cmd = None
+ prompt_cmd = None
+ activate_script = None
+
+ # Default values defined here
+ # 'preamble_cmd' *MUST NOT* emit anything to stdout!
+ testscript_extension = ""
+ preamble_cmd = ""
+ activate_cmd = "source "
+ deactivate_cmd = "deactivate"
+ clean_env_update = {}
+
+ # Skip check function; must be specified per-shell
+ platform_check_skip = None
+
+ # Test assert method for comparing activated prompt to deactivated.
+ # Default defined, but can be overridden per-shell. Takes the captured
+ # lines of output as the lone argument.
+ def overall_prompt_test(self, lines, prefix):
+ """Perform all tests on (de)activated prompts.
+
+ From a Python 3 perspective, 'lines' is expected to be *bytes*,
+ and 'prefix' is expected to be *str*.
+
+ Happily, this all seems to translate smoothly enough to 2.7.
+
+ """
+ # Prompts before activation and after deactivation should be identical.
+ assert lines[1] == lines[3], lines
+
+ # The .partition here operates on the environment marker text expected to occur
+ # in the prompt. A non-empty 'env_marker' thus tests that the correct marker text
+ # has been applied into the prompt string.
+ before, env_marker, after = lines[2].partition(prefix.encode("utf-8"))
+ assert env_marker != b"", lines
+
+ # Some shells need custom activated-prompt tests, so this is split into
+ # its own submethod.
+ self.activated_prompt_test(lines, after)
+
+ def activated_prompt_test(self, lines, after):
+ """Perform just the check for the deactivated prompt contents in the activated prompt text.
+
+ The default is a strict requirement that the portion of the activated prompt following the environment
+ marker must exactly match the non-activated prompt.
+
+ Some shells require weaker tests, due to idiosyncrasies.
+
+ """
+ assert after == lines[1], lines
+
+
+class BashInfo(ShellInfo):
+ name = "bash"
+ avail_cmd = "bash -c 'echo foo'"
+ execute_cmd = "bash"
+ prompt_cmd = 'echo "$PS1"'
+ activate_script = "activate"
+
+ def platform_check_skip(self):
+ if IS_WIN:
+ return self.platform_incompat_msg.format(sys.platform)
+
+
+class FishInfo(ShellInfo):
+ name = "fish"
+ avail_cmd = "fish -c 'echo foo'"
+ execute_cmd = "fish"
+ prompt_cmd = "fish_prompt; echo ' '"
+ activate_script = "activate.fish"
+
+ # Azure Devops doesn't set a terminal type, which breaks fish's colorization
+ # machinery in a way that spuriously fouls the activation script.
+ clean_env_update = {"TERM": "linux"}
+
+ def platform_check_skip(self):
+ if IS_WIN:
+ return self.platform_incompat_msg.format(sys.platform)
+
+ def activated_prompt_test(self, lines, after):
+ """Require a looser match here, due to interposed ANSI color codes.
+
+ This construction allows coping with the messiness of fish's ANSI codes for colorizing.
+ It's not as rigorous as I would like---it doesn't ensure no space is inserted between
+ a custom env prompt (argument to --prompt) and the base prompt---but it does provide assurance as
+ to the key pieces of content that should be present.
+
+ """
+ assert lines[1] in after, lines
+
+
+class CshInfo(ShellInfo):
+ name = "csh"
+ avail_cmd = "csh -c 'echo foo'"
+ execute_cmd = "csh"
+ prompt_cmd = r"set | grep -E 'prompt\s' | sed -E 's/^prompt\s+(.*)$/\1/'"
+ activate_script = "activate.csh"
+
+ # csh defaults to an unset 'prompt' in non-interactive shells
+ preamble_cmd = "set prompt=%"
+
+ def platform_check_skip(self):
+ if IS_WIN:
+ return self.platform_incompat_msg.format(sys.platform)
+
+ def activated_prompt_test(self, lines, after):
+ """Test with special handling on MacOS, which does funny things to stdout under (t)csh."""
+ if IS_DARWIN:
+ # Looser assert for (t)csh on MacOS, which prepends extra text to
+ # what gets sent to stdout
+ assert lines[1].endswith(after), lines
+ else:
+ # Otherwise, use the rigorous default
+ # Full 2-arg form for super() used for 2.7 compat
+ super(CshInfo, self).activated_prompt_test(lines, after)
+
+
+class XonshInfo(ShellInfo):
+ name = "xonsh"
+ avail_cmd = "xonsh -c 'echo foo'"
+ execute_cmd = "xonsh"
+ prompt_cmd = "print(__xonsh__.shell.prompt)"
+ activate_script = "activate.xsh"
+
+ # Sets consistent initial state
+ preamble_cmd = (
+ "$VIRTUAL_ENV = ''; $PROMPT = '{env_name}$ '; "
+ "$PROMPT_FIELDS['env_prefix'] = '('; $PROMPT_FIELDS['env_postfix'] = ') '"
+ )
+
+ def platform_check_skip(self):
+ if IS_WIN:
+ return "Provisioning xonsh on windows is unreliable"
+
+ if sys.version_info < (3, 4):
+ return "xonsh requires Python 3.4 at least"
+
+
+class CmdInfo(ShellInfo):
+ name = "cmd"
+ avail_cmd = "echo foo"
+ execute_cmd = ""
+ prompt_cmd = "echo %PROMPT%"
+ activate_script = "activate.bat"
+
+ testscript_extension = ".bat"
+ preamble_cmd = "@echo off & set PROMPT=$P$G" # For consistent initial state
+ activate_cmd = "call "
+ deactivate_cmd = "call deactivate"
+
+ def platform_check_skip(self):
+ if not IS_WIN:
+ return self.platform_incompat_msg.format(sys.platform)
+
+
+class PoshInfo(ShellInfo):
+ name = "posh"
+ avail_cmd = "powershell 'echo foo'"
+ execute_cmd = "powershell -File "
+ prompt_cmd = "prompt"
+ activate_script = "activate.ps1"
+
+ testscript_extension = ".ps1"
+ activate_cmd = ". "
+
+ def platform_check_skip(self):
+ if not IS_WIN:
+ return self.platform_incompat_msg.format(sys.platform)
+
+
+SHELLINFO_LIST = [BashInfo(), FishInfo(), CshInfo(), XonshInfo(), CmdInfo(), PoshInfo()]
+
+
+@pytest.fixture(scope="module")
+def posh_execute_enabled(tmp_path_factory):
+ """Return check value for whether Powershell script execution is enabled.
+
+ Posh may be available interactively, but the security settings may not allow
+ execution of script files.
+
+ # Enable with: PS> Set-ExecutionPolicy -scope currentuser -ExecutionPolicy Bypass -Force;
+ # Disable with: PS> Set-ExecutionPolicy -scope currentuser -ExecutionPolicy Restricted -Force;
+
+ """
+ if not IS_WIN:
+ return False
+
+ test_ps1 = tmp_path_factory.mktemp("posh_test") / "test.ps1"
+ with open(str(test_ps1), "w") as f:
+ f.write("echo 'foo bar baz'\n")
+
+ out = subprocess.check_output(["powershell", "-File", "{}".format(str(test_ps1))], shell=True)
+ return b"foo bar baz" in out
+
+
+@pytest.fixture(scope="module")
+def shell_avail(posh_execute_enabled):
+ """Generate mapping of ShellInfo.name strings to bools of shell availability."""
+ retvals = {si.name: subprocess.call(si.avail_cmd, shell=True) for si in SHELLINFO_LIST}
+ avails = {si.name: retvals[si.name] == 0 for si in SHELLINFO_LIST}
+
+ # Extra check for whether powershell scripts are enabled
+ avails[PoshInfo().name] = avails[PoshInfo().name] and posh_execute_enabled
+
+ return avails
+
+
+@pytest.fixture(scope="module")
+def custom_prompt_root(tmp_path_factory):
+ """Provide Path to root with default and custom venvs created."""
+ root = tmp_path_factory.mktemp("custom_prompt")
+ virtualenv.create_environment(
+ str(root / ENV_CUSTOM), prompt=PREFIX_CUSTOM, no_setuptools=True, no_pip=True, no_wheel=True
+ )
+
+ _, _, _, bin_dir = virtualenv.path_locations(str(root / ENV_DEFAULT))
+
+ bin_dir_name = os.path.split(bin_dir)[-1]
+
+ return root, bin_dir_name
+
+
+@pytest.fixture(scope="module")
+def clean_python_root(clean_python):
+ root = Path(clean_python[0]).resolve().parent
+ bin_dir_name = os.path.split(clean_python[1])[-1]
+
+ return root, bin_dir_name
+
+
+@pytest.fixture(scope="module")
+def get_work_root(clean_python_root, custom_prompt_root):
+ def pick_root(env):
+ if env == ENV_DEFAULT:
+ return clean_python_root
+ elif env == ENV_CUSTOM:
+ return custom_prompt_root
+ else:
+ raise ValueError("Invalid test virtualenv")
+
+ return pick_root
+
+
+@pytest.fixture(scope="function")
+def clean_env():
+ """Provide a fresh copy of the shell environment.
+
+ VIRTUAL_ENV_DISABLE_PROMPT is always removed, if present, because
+ the prompt tests assume it to be unset.
+
+ """
+ clean_env = os.environ.copy()
+ clean_env.pop(env_compat(VIRTUAL_ENV_DISABLE_PROMPT), None)
+ return clean_env
+
+
+SHELLINFO_LIST = [BashInfo(), FishInfo(), CshInfo(), XonshInfo(), CmdInfo(), PoshInfo()]
+
+
+@pytest.mark.parametrize("shell_info", SHELLINFO_LIST, ids=(lambda si: si.name))
+@pytest.mark.parametrize("env", [ENV_DEFAULT, ENV_CUSTOM])
+@pytest.mark.parametrize(("value", "disable"), [("", False), ("0", True), ("1", True)])
+def test_suppressed_prompt(shell_info, shell_avail, env, value, disable, get_work_root, clean_env):
+ """Confirm non-empty VIRTUAL_ENV_DISABLE_PROMPT suppresses prompt changes on activate."""
+ skip_test = shell_info.platform_check_skip()
+ if skip_test:
+ pytest.skip(skip_test)
+
+ if not IS_INSIDE_CI and not shell_avail[shell_info.name]:
+ pytest.skip(
+ "Shell '{}' not provisioned".format(shell_info.name)
+ + (" - is Powershell script execution disabled?" if shell_info == PoshInfo() else "")
+ )
+
+ script_name = SCRIPT_TEMPLATE.format(shell_info.name, "suppress", env, shell_info.testscript_extension)
+ output_name = OUTPUT_TEMPLATE.format(shell_info.name, "suppress", env)
+
+ clean_env.update({env_compat(VIRTUAL_ENV_DISABLE_PROMPT): env_compat(value)})
+
+ work_root = get_work_root(env)
+
+ # The extra "{prompt}" here copes with some oddity of xonsh in certain emulated terminal
+ # contexts: xonsh can dump stuff into the first line of the recorded script output,
+ # so we have to include a dummy line of output that can get munged w/o consequence.
+ with open(str(work_root[0] / script_name), "w") as f:
+ f.write(
+ dedent(
+ """\
+ {preamble}
+ {prompt}
+ {prompt}
+ {act_cmd}{env}/{bindir}/{act_script}
+ {prompt}
+ """.format(
+ env=env,
+ act_cmd=shell_info.activate_cmd,
+ preamble=shell_info.preamble_cmd,
+ prompt=shell_info.prompt_cmd,
+ act_script=shell_info.activate_script,
+ bindir=work_root[1],
+ )
+ )
+ )
+
+ command = "{} {} > {}".format(shell_info.execute_cmd, script_name, output_name)
+
+ assert 0 == subprocess.call(command, cwd=str(work_root[0]), shell=True, env=clean_env)
+
+ with open(str(work_root[0] / output_name), "rb") as f:
+ lines = f.read().split(b"\n")
+
+ # Is the prompt suppressed based on the env var value?
+ assert (lines[1] == lines[2]) == disable, lines
+
+
+@pytest.mark.parametrize("shell_info", SHELLINFO_LIST, ids=(lambda si: si.name))
+@pytest.mark.parametrize(["env", "prefix"], [(ENV_DEFAULT, PREFIX_DEFAULT), (ENV_CUSTOM, PREFIX_CUSTOM)])
+def test_activated_prompt(shell_info, shell_avail, env, prefix, get_work_root, clean_env):
+ """Confirm prompt modification behavior with and without --prompt specified."""
+ skip_test = shell_info.platform_check_skip()
+ if skip_test:
+ pytest.skip(skip_test)
+
+ if not IS_INSIDE_CI and not shell_avail[shell_info.name]:
+ pytest.skip(
+ "Shell '{}' not provisioned".format(shell_info.name)
+ + (" - is Powershell script execution disabled?" if shell_info == PoshInfo() else "")
+ )
+
+ for k, v in shell_info.clean_env_update.items():
+ clean_env.update({env_compat(k): env_compat(v)})
+
+ script_name = SCRIPT_TEMPLATE.format(shell_info.name, "normal", env, shell_info.testscript_extension)
+ output_name = OUTPUT_TEMPLATE.format(shell_info.name, "normal", env)
+
+ work_root = get_work_root(env)
+
+ # The extra "{prompt}" here copes with some oddity of xonsh in certain emulated terminal
+ # contexts: xonsh can dump stuff into the first line of the recorded script output,
+ # so we have to include a dummy line of output that can get munged w/o consequence.
+ with open(str(work_root[0] / script_name), "w") as f:
+ f.write(
+ dedent(
+ """\
+ {preamble}
+ {prompt}
+ {prompt}
+ {act_cmd}{env}/{bindir}/{act_script}
+ {prompt}
+ {deactivate}
+ {prompt}
+ """.format(
+ env=env,
+ act_cmd=shell_info.activate_cmd,
+ deactivate=shell_info.deactivate_cmd,
+ preamble=shell_info.preamble_cmd,
+ prompt=shell_info.prompt_cmd,
+ act_script=shell_info.activate_script,
+ bindir=work_root[1],
+ )
+ )
+ )
+
+ command = "{} {} > {}".format(shell_info.execute_cmd, script_name, output_name)
+
+ assert 0 == subprocess.call(command, cwd=str(work_root[0]), shell=True, env=clean_env)
+
+ with open(str(work_root[0] / output_name), "rb") as f:
+ lines = f.read().split(b"\n")
+
+ shell_info.overall_prompt_test(lines, prefix)
diff --git a/virtualenv.py b/virtualenv.py
index 061e0d5..8184e86 100755
--- a/virtualenv.py
+++ b/virtualenv.py
@@ -1698,7 +1698,7 @@ def install_files(home_dir, bin_dir, prompt, files):
virtualenv_name = os.path.basename(home_dir)
for name, content in files.items():
content = content.replace("__VIRTUAL_PROMPT__", prompt or "")
- content = content.replace("__VIRTUAL_WINPROMPT__", prompt or "({})".format(virtualenv_name))
+ content = content.replace("__VIRTUAL_WINPROMPT__", prompt or "({}) ".format(virtualenv_name))
content = content.replace("__VIRTUAL_ENV__", home_dir)
content = content.replace("__VIRTUAL_NAME__", virtualenv_name)
content = content.replace("__BIN_NAME__", os.path.basename(bin_dir))
@@ -2282,42 +2282,43 @@ a6FOZy1jZzukdvvqN1kPccDLjbwGdtJ8m72rgeki+xOnXcf/CzFcuJM=
# file activate.csh
ACTIVATE_CSH = convert(
"""
-eJx9k9tq20AQhu/3Kf7IJm5N4vRarts6caCBxAnBCZSmLCtpXC1IK2e1svFNn72zklzkA9WFkOb0
-z34708Mi1SWWOiPkVekQEaqSEmy0SxGURWVjQqTNlYqdXitHo7hMAwyXtsjBn8OR6OFHUSFWxhQO
-tjLQDom2FLts6703ljgvQbTFTK11QphpXGeq1Pic1IYk+vY7VzobxUX+ZSRESQ6GNpk2NBm8iYEQ
-KtOqREK7LjBwxN32v8rH+5l8vXtevEzv5dN08R1nE3zC+Tm4CJk1alvQP4oL3wMfVRkvduQdw1Kq
-ynSMkzrPjw9Pi64SVsxj5SaHQnXgf6Rq/7hx+W53jtv5aysdvJ2Fw8BrBaYwCZts5SFQW/OITMe6
-2iZFzPR6eKm1tbWU0VoZh7WyWkUZlSPRyd1XqC/ioCsEUnZ+pQya6zoiyChazGL/JjrZ4fuVlNd3
-czmfPtxKGf7L4Ecv8aGj1ZBiuZpE8BEuJSPAj1fn8tKonDDBqRxBWUkng/e6cV6aTKKXHtlNUWWJ
-3wdtoDyZS20c2ZoV+SLaFiYn4y44mGM2qY5TXoOSLtBvxgG8WhUTXfIgJ1CG14qw8XXNwHFWrCxB
-RUXl/HHaGeK47Ubx5ngCPHmt9eDEJ8aIiTex/hh1cseAyR8Mg367VWwYdiuG+4RaSebzs7+jFb7/
-Qqd+g6mF1Uz2LnK3rfX08dulhcFl3vwL0SyW+At+C2qe
+eJx9VNtO4zAQffdXDKEiUEFhX8t22bJFWqRyEVuQVkKy3Hi6sZQ44Dit+sK379hJittG5KGqPZdz
+fOZyCLNUlbBQGUJelRbmCFWJElbKphCVRWUShLnS5yKxaiksDpIyjaC/MEUO9Lc/YIfwt6ggEVoX
+FkylQVmQymBis7Wz/jJIcRLma5iIpZIIEwXXmSgVfJf+Qs5//suFygZJkf8YMFaiBY2rTGkcxa8s
+ZkxkSpQgsWUBsUVi27viD9MJf7l9mj2Pp/xxPPsNByO4gKMjoCSol+Dvot6e3/A9cl6VdmB71ksw
+mIoyvYROnKeHu8dZiARvpMebHe0CeccvoLz9sjY5tq3h5v6lgY5eD4b9yGFFutCSrkzlRMAm554y
+we3bWhYJqXcIzx5bGYMZLoW2sBRGiXmG5YAFsdsIvhA7rCDiPDhyHtXl2lOQpGhkZtuVCKKH7+ec
+X9/e8/vx3Q3nw00EfWoBxwFWrRTBeSWiE7Apagb0OXRKz7XIEUbQFcMwK7HLOT6OtwlZQo9PIGao
+pVrULKj64Ysnt3/G19ObtgkCJrXzF74jRz2MaCnJgtcN5B7wLfK2DedOp4vGydPcet5urq2XBEZv
+DcnQpBZVJt0KUBqEa4YzpS0a3x7odFOm0Dlqe9oEkN8qVUlK01/iKfSa3LRRKmqkBc2vBKFpmyCs
+XG4d2yYyEQZBzIvKOgLN+JDveiVoaXyqedVYOkTrmCRqutrfNVHr6xMFBhh9QD/qNQuGLvq72d03
+3Jy2CtGCf0rca/tp+N4BXqsflKquRr0L2sjmuClOu+/8/NKvTQsNZ3l9ZqxeTew//1a6EA==
"""
)
# file activate.xsh
ACTIVATE_XSH = convert(
"""
-eJyFU11rwjAUfc+vuIt9sMz1Bwg+OCYoaB2bkw2RkNlbLdSkJLFsjP33JdV+aN2Wh5L7eW7PuaGU
-vkqhd8A3Jsm5QdAblWQGYqkgT5Q58BRFTiklsZJ7+HDJgZEy1ZDsM6kMbNEwjRlwDex0JyTCGFiE
-ZdcuV1vt9wnYk8RAs89IbigkAniacI36GHInwrR0rk55a1IWel9BEHwHFqZL2Xz6wJaTp8XLcMoe
-h4sx7QGlft3Jc04YgNfKPAO7Ev4f7m0xnofj+WzUBq1Cbegq9NcAdVJFVxkbhcuCtONc55x5jaS6
-UkgRoTbq4IRACkKagnUrR13egWdMYygTb65rUavpBCEdOAiNtptSmGLOhYGcq4S/p6hJU/rV5RBr
-n1xtavlq1BHS/CMbU5SxhocxalNa2jnSCw29prXqr4+OgEdR96zxbbW1Xd8aFuR+ErJwOBtZhB7Y
-rRdmsFAH7IHCLOUbLCyfkIsFub4TJU2NtbB11lNEf5O+mPt8WwqNm8tx+UhsjbubnRRugLu9+5YP
-6AcvDiI9
+eJyNU11PwjAUfe+vuNY9sIj7ASQ+YCSBRD6i02gIaSq7gyWjXdqyaIz/3XYwVmB+9GFZ78c57T2n
+lNIXKfQa+NJkJTcIeqmywkAqFZSZMlueoygppSRVcgPvrjgyUuYask0hlYEVGqaxAK6B7f8JSTAF
+lmCN2uFqpcMeAbuyFGjxkcglhUwAzzOuUe9SbiWY18H5vm5B6sbgM4qir8jSdCib3t+x59FD/NS/
+Z7N+PKRdoDRskAIXhBsIziqPyFrSf9O9xsPpZDgdD85JD6lz6kPqtwM0RYdx1bnB5Lka2u5cxzML
+vKLWTjZ7mI5n8b8A9rUNjpAiQW3U1gmKFIQ0lXpW1gblEh4xT6EuvGjXtHGFE5ZcwlZotGhKYY4l
+FwZKrjL+lqMmvoXmp4dYhKQV1M7d6yPEv5jNKcqYf1VGbcmZB5x4lRcCfzfvLXaBiCdJ5wj46uD+
+Tmg3luR2NGGT/nhgGbpgX48wN7HaYhcUFjlfYrULCTkxWru36jF59rJ9NlJlf7JQde5j11VS+yZr
+0d22eUPaxdycLKMTvqWjR3610emDtgTu36ylcJe83rhv/di/AYN1UZY=
"""
)
# file activate.bat
ACTIVATE_BAT = convert(
"""
-eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV
-mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O
-CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5
-xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ
-MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U
-+g8CsNTr
+eJyVk1FLhEAUhd8X/A8XWSkf28dCyMUpBR3FzAiCS+WYwq4TOdXfb0Z3dTJdyCfveO85n8frNXut
+OPCyNFbGqmUCzDxIs3s3REJzB1GrEE3VVJdQsLJuWAEYh97QkaRxlGRwbqxAXp1Uf+RYM32W1LKB
+7Vp2nJC6DReD9m+5qeQ6Wd+a/SN7dlzn9oI7dxsSXJCcoXOskfLgYXdv/j8LnXiM8iGg/RmiZmOr
+bFMSgcebMwGfKhgbBIfnL14X8P7BX3Zs38J3LSoQFdtD3YCVuJlvnfgmj5kfUz+OCLxxqUWoF9zk
+qtYAFyZkBsO9ArzUh/td0ZqP9IskElTFMsnwb4/GqeoLPUlZT5dJvf8Id5hQIONynUSa2G0Wc+m8
+Z+w2w4/Tt2hbYT0hbgOK1I0I4tUw/QOTZfLE
"""
)
@@ -2334,17 +2335,18 @@ pk+k4fAba/wd0Pr4P2CqyLeOlJ4iKfkJo6v/iaH9YzfPMEoeMG2RUA==
# file activate.ps1
ACTIVATE_PS = convert(
"""
-eJyNVMtu2zAQvOsrNrLQ2miloFcXPdiwgRhwHCN2c2kLgqZWMQGKFEhKqVHky3LoJ/UXSlqWX3LS
-8ibtzHJ2d5Z/Xn53YLnmBjIuEPLSWFghpMqCUaVmmEKmVQ5ztVh/ho0qgVEpXVSXEriFlGtkVmwS
-GCmwLk8fEkiuKbO8ohaTwnwKgsgwzQvbX95MFmQ+WN7AF4jyDZeVYtRyJZN8w1SeU5kmBbXrPWE4
-WIzJaHLv8KYQ3MY+Cl2NRokK668w2qe9TpKwB/GcapQ2CLJSMp8dHoVaUdFPsZHV/WaeuGXrHxDN
-lByhsbr0IewFvwJwh2fQte53fUVFNacrgX1yNx2Rh8n98utgur2xt0XXHH8ilFW/qfB12h6vMVeu
-kAYJYQsaQmyYKnBXxJb5HFwQ2VTbJ0qkpOLallSQwg2vsC2Ze3Ad92rf4p/r5Rbzw4XfX2Mc6dw2
-pqlrPHtoKfIpHOZ00ucsiAXS7KKaFhK1VprWBjDO29K5lClpuSzxXN1Vywan6jqwQJFBukNcvd2P
-g8/exhWbVLGdlOe2XetwLaLY2LWLxDls/0JE9aPxpA6U0qAFrjUKrKi0e7ea4CAEYqlkeijQ7eRx
-s9z4m1ULWj13waNPx9zpa1nVIxv/B8ebEJ7nvCZkOJmR2eB2TNzxMLIYzwkJ4cNRjno0Z1wncjEY
-Tsdkfn93O182G3vevdc8eRhqGO56f7oRF4gn63GUqzWxS9d0YJCmQKHQmPGfYP0zicBK7R8pqCkf
-YVW6t1TJ9/5FNYzq1D2uyT7Hk3bOidfKPc5hN+r+e0Wg14NwO3R8ElwejPjuPxbdu/EvkRDrCw==
+eJytVcFu2zAMvfsrWNfYEmx2sWuGHVIkQAO0adBkvWyDoMh0I0CWDElOGwz598p2HDt20w3YdLP5
+SD2Sj9QlrDbcQMIFQpobC2uEWFkwKtcMY0i0SmGhlpuvsFM5MCqls+pcArcQc43Mil0EEwXWxRlB
+BNEVZZZvqcUoM188LzBM88yOVjezJVmMVzfwDYJ0x+VWMWq5klG6YypNqYyjjNrN0eF6vJySyezB
+4U0muA0LKww0GiW2WH35wTHsVRT5QwgXVKO0npfkkhXR4UmoNRWjGGtagx/mmVu2+QXBXMkJGqvz
+woRD77cH7vAEBtb9rq7YUs3pWuCI3N9OyOPsYfV9fFveOCzRlU9xApTbUZ3hebcjXmOqXCI1Evwe
+1IfQMJXhIYnSc++9QbLOdkSUiMmWa5tTQTLXvMz2aB7Blb1g+55/ly+3mDYX/jzn0eJZFqbOazp/
+7DEqQjjMaae7XhAKpMmbbHpI1FppWgnAOG1Lp1KmpOUyxy67i54MTtldwhJFAvEBcfF+PRqdvY/L
+drFiByr7vlwrc0Ui29mNs4QplH8hoPrJFE6XkEuDFrjWKHBLpT2q1XgNEQilknGToJvJdrFc++tR
+83o1d8bWp/M88OtJtUDW+vfak+B3Y14Rcj2bk/n4bkrcKWBkOV0Q4sOnVoyqNR1fR3I5vr6dksXD
+/d1iVU9st3rnNNk01fcPtT+diDccT8ajFavg55OmBiWhIolQulH2uyrqNfh0thpgJblxHLuNisDc
+TnYbONOY8BewqvyJL9w4KT9BJ0hxnrXTWbhRbpWfYackPgsu8cTtw1/ugH2rbCgM/nuWtJMcy3Wx
+wQ+5fYZ17h4aJT8Wz41hVMfu5YnOpjwIBn/eITAcwn+rxN57BRHvOEk=
"""
)
diff --git a/virtualenv_embedded/activate.bat b/virtualenv_embedded/activate.bat
index ed42021..9c5d372 100644
--- a/virtualenv_embedded/activate.bat
+++ b/virtualenv_embedded/activate.bat
@@ -1,4 +1,5 @@
@echo off
+
set "VIRTUAL_ENV=__VIRTUAL_ENV__"
if defined _OLD_VIRTUAL_PROMPT (
@@ -7,9 +8,13 @@ if defined _OLD_VIRTUAL_PROMPT (
if not defined PROMPT (
set "PROMPT=$P$G"
)
- set "_OLD_VIRTUAL_PROMPT=%PROMPT%"
+ if not defined VIRTUAL_ENV_DISABLE_PROMPT (
+ set "_OLD_VIRTUAL_PROMPT=%PROMPT%"
+ )
+)
+if not defined VIRTUAL_ENV_DISABLE_PROMPT (
+ set "PROMPT=__VIRTUAL_WINPROMPT__%PROMPT%"
)
-set "PROMPT=__VIRTUAL_WINPROMPT__ %PROMPT%"
REM Don't use () to avoid problems with them in %PATH%
if defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME
diff --git a/virtualenv_embedded/activate.csh b/virtualenv_embedded/activate.csh
index e3dc553..c4a6d58 100644
--- a/virtualenv_embedded/activate.csh
+++ b/virtualenv_embedded/activate.csh
@@ -20,22 +20,35 @@ 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"
+ set env_name = '('"$VIRTUAL_ENV:t:q"') '
endif
-# 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
- :
+if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then
+ if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then
+ set do_prompt = "1"
+ else
+ set do_prompt = "0"
+ endif
else
- set prompt = "[$env_name:q] $prompt:q"
+ 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
diff --git a/virtualenv_embedded/activate.ps1 b/virtualenv_embedded/activate.ps1
index 48b947d..3bbf9a6 100644
--- a/virtualenv_embedded/activate.ps1
+++ b/virtualenv_embedded/activate.ps1
@@ -1,4 +1,4 @@
-# This file must be dot sourced from PoSh; you cannot run it directly. Do this: . ./activate.ps1
+# This file must be dot sourced from PoSh; you cannot run it directly. Do this: . ./activate.ps1
$script:THIS_PATH = $myinvocation.mycommand.path
$script:BASE_DIR = split-path (resolve-path "$THIS_PATH/..") -Parent
@@ -51,10 +51,22 @@ if (!$env:VIRTUAL_ENV_DISABLE_PROMPT)
""
}
$function:_old_virtual_prompt = $function:prompt
- function global:prompt
+ if ("__VIRTUAL_PROMPT__" -ne "")
{
- # Add a prefix to the current prompt, but don't discard it.
- write-host "($( split-path $env:VIRTUAL_ENV -leaf )) " -nonewline
- & $function:_old_virtual_prompt
+ function global:prompt
+ {
+ # Add the custom prefix to the existing prompt
+ write-host "__VIRTUAL_PROMPT__" -nonewline
+ & $function:_old_virtual_prompt
+ }
+ }
+ else
+ {
+ function global:prompt
+ {
+ # Add a prefix to the current prompt, but don't discard it.
+ write-host "($( split-path $env:VIRTUAL_ENV -leaf )) " -nonewline
+ & $function:_old_virtual_prompt
+ }
}
}
diff --git a/virtualenv_embedded/activate.xsh b/virtualenv_embedded/activate.xsh
index 6eb0d59..c77ea62 100644
--- a/virtualenv_embedded/activate.xsh
+++ b/virtualenv_embedded/activate.xsh
@@ -16,6 +16,9 @@ def _deactivate(args):
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"]
@@ -36,4 +39,8 @@ if ${...}.get("PYTHONHOME", ""):
$_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"]