diff options
author | Siddhant Kumar <skumar619@bloomberg.net> | 2020-08-23 14:25:50 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-23 14:25:50 +0100 |
commit | 6c098d8daa3ed2b34723b62eef9411bded6460b0 (patch) | |
tree | d236bacf2c552ab96eca8d34328e914973d281fb | |
parent | 7de4f3f904746cbdc31a4bc764d5adfcfb3c61e5 (diff) | |
download | virtualenv-6c098d8daa3ed2b34723b62eef9411bded6460b0.tar.gz |
Use unix line-endings in bash activate script (#1924)
Co-authored-by: Bernat Gabor <bgabor8@bloomberg.net>
-rw-r--r-- | .gitattributes | 4 | ||||
-rw-r--r-- | docs/changelog/1818.bugfix.rst | 1 | ||||
-rw-r--r-- | src/virtualenv/activation/powershell/activate.ps1 | 120 | ||||
-rw-r--r-- | src/virtualenv/activation/via_template.py | 12 | ||||
-rw-r--r-- | src/virtualenv/create/via_global_ref/api.py | 5 | ||||
-rw-r--r-- | src/virtualenv/util/path/_pathlib/via_os_path.py | 7 | ||||
-rw-r--r-- | tests/unit/activation/conftest.py | 11 | ||||
-rw-r--r-- | tests/unit/activation/test_bash.py | 5 | ||||
-rw-r--r-- | tests/unit/activation/test_batch.py | 1 | ||||
-rw-r--r-- | tests/unit/activation/test_python_activator.py | 3 |
10 files changed, 96 insertions, 73 deletions
diff --git a/.gitattributes b/.gitattributes index 69b47b5..c925e26 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,5 @@ *.bat text eol=crlf +*.ps1 text eol=lf +*.fish text eol=lf +*.csh text eol=lf +*.sh text eol=lf diff --git a/docs/changelog/1818.bugfix.rst b/docs/changelog/1818.bugfix.rst new file mode 100644 index 0000000..8396cb9 --- /dev/null +++ b/docs/changelog/1818.bugfix.rst @@ -0,0 +1 @@ +For activation scripts always use UNIX line endings (unless it's BATCH shell related) - by :user:`saytosid`. diff --git a/src/virtualenv/activation/powershell/activate.ps1 b/src/virtualenv/activation/powershell/activate.ps1 index 85b2103..a370a63 100644 --- a/src/virtualenv/activation/powershell/activate.ps1 +++ b/src/virtualenv/activation/powershell/activate.ps1 @@ -1,60 +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)
- }
- }
-}
+$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/via_template.py b/src/virtualenv/activation/via_template.py index 7a9d3c8..14f0979 100644 --- a/src/virtualenv/activation/via_template.py +++ b/src/virtualenv/activation/via_template.py @@ -11,9 +11,9 @@ from virtualenv.util.six import ensure_text from .activator import Activator if sys.version_info >= (3, 7): - from importlib.resources import read_text + from importlib.resources import read_binary else: - from importlib_resources import read_text + from importlib_resources import read_binary @add_metaclass(ABCMeta) @@ -44,7 +44,8 @@ class ViaTemplateActivator(Activator): for template in templates: text = self.instantiate_template(replacements, template, creator) dest = to_folder / self.as_name(template) - dest.write_text(text, encoding="utf-8") + # use write_bytes to avoid platform specific line normalization (\n -> \r\n) + dest.write_bytes(text.encode("utf-8")) generated.append(dest) return generated @@ -52,8 +53,9 @@ class ViaTemplateActivator(Activator): return template.name def instantiate_template(self, replacements, template, creator): - # read text and do replacements - text = read_text(self.__module__, str(template), encoding="utf-8", errors="strict") + # read content as binary to avoid platform specific line normalization (\n -> \r\n) + binary = read_binary(self.__module__, str(template)) + text = binary.decode("utf-8", errors="strict") for key, value in replacements.items(): value = self._repr_unicode(creator, value) text = text.replace(key, value) diff --git a/src/virtualenv/create/via_global_ref/api.py b/src/virtualenv/create/via_global_ref/api.py index c9eab3c..6f296f4 100644 --- a/src/virtualenv/create/via_global_ref/api.py +++ b/src/virtualenv/create/via_global_ref/api.py @@ -8,6 +8,7 @@ from six import add_metaclass from virtualenv.info import fs_supports_symlink from virtualenv.util.path import Path +from virtualenv.util.six import ensure_text from ..creator import Creator, CreatorMeta @@ -91,10 +92,10 @@ class ViaGlobalRefApi(Creator): text = self.env_patch_text() if text: pth = self.purelib / "_virtualenv.pth" - logging.debug("create virtualenv import hook file %s", pth) + logging.debug("create virtualenv import hook file %s", ensure_text(str(pth))) pth.write_text("import _virtualenv") dest_path = self.purelib / "_virtualenv.py" - logging.debug("create %s", dest_path) + logging.debug("create %s", ensure_text(str(dest_path))) dest_path.write_text(text) def env_patch_text(self): diff --git a/src/virtualenv/util/path/_pathlib/via_os_path.py b/src/virtualenv/util/path/_pathlib/via_os_path.py index d11aeaa..ac78d4f 100644 --- a/src/virtualenv/util/path/_pathlib/via_os_path.py +++ b/src/virtualenv/util/path/_pathlib/via_os_path.py @@ -87,9 +87,12 @@ class Path(object): with open(self._path, "rb") as file_handler: return file_handler.read() - def write_text(self, text, encoding="utf-8"): + def write_bytes(self, content): with open(self._path, "wb") as file_handler: - file_handler.write(text.encode(encoding)) + file_handler.write(content) + + def write_text(self, text, encoding="utf-8"): + self.write_bytes(text.encode(encoding)) def iterdir(self): for p in os.listdir(self._path): diff --git a/tests/unit/activation/conftest.py b/tests/unit/activation/conftest.py index 98c3fda..bb3e292 100644 --- a/tests/unit/activation/conftest.py +++ b/tests/unit/activation/conftest.py @@ -31,6 +31,7 @@ class ActivationTester(object): self.pydoc_call = "pydoc -w pydoc_test" self.script_encoding = "utf-8" self._version = None + self.unix_line_ending = True def get_version(self, raise_on_fail): if self._version is None: @@ -63,6 +64,16 @@ class ActivationTester(object): def __call__(self, monkeypatch, tmp_path): activate_script = self._creator.bin_dir / self.activate_script + + # check line endings are correct type + script_content = activate_script.read_bytes() + for line in script_content.split(b"\n")[:-1]: + cr = b"\r" if sys.version_info.major == 2 else 13 + if self.unix_line_ending: + assert line == b"" or line[-1] != cr, script_content.decode("utf-8") + else: + assert line[-1] == cr, script_content.decode("utf-8") + test_script = self._generate_test_script(activate_script, tmp_path) monkeypatch.chdir(ensure_text(str(tmp_path))) diff --git a/tests/unit/activation/test_bash.py b/tests/unit/activation/test_bash.py index 5246be0..51498ed 100644 --- a/tests/unit/activation/test_bash.py +++ b/tests/unit/activation/test_bash.py @@ -1,13 +1,12 @@ from __future__ import absolute_import, unicode_literals -import sys - import pytest from virtualenv.activation import BashActivator +from virtualenv.info import IS_WIN -@pytest.mark.skipif(sys.platform == "win32", reason="Github Actions ships with WSL bash") +@pytest.mark.skipif(IS_WIN, reason="Github Actions ships with WSL bash") def test_bash(raise_on_non_source_class, activation_tester): class Bash(raise_on_non_source_class): def __init__(self, session): diff --git a/tests/unit/activation/test_batch.py b/tests/unit/activation/test_batch.py index 92b141b..e10d902 100644 --- a/tests/unit/activation/test_batch.py +++ b/tests/unit/activation/test_batch.py @@ -17,6 +17,7 @@ def test_batch(activation_tester_class, activation_tester, tmp_path, activation_ self.deactivate = "call deactivate" self.activate_cmd = "call" self.pydoc_call = "call {}".format(self.pydoc_call) + self.unix_line_ending = False def _get_test_lines(self, activate_script): # for BATCH utf-8 support need change the character code page to 650001 diff --git a/tests/unit/activation/test_python_activator.py b/tests/unit/activation/test_python_activator.py index 6abf255..859fad6 100644 --- a/tests/unit/activation/test_python_activator.py +++ b/tests/unit/activation/test_python_activator.py @@ -6,7 +6,7 @@ from ast import literal_eval from textwrap import dedent from virtualenv.activation import PythonActivator -from virtualenv.info import WIN_CPYTHON_2 +from virtualenv.info import IS_WIN, WIN_CPYTHON_2 from virtualenv.util.six import ensure_text @@ -21,6 +21,7 @@ def test_python(raise_on_non_source_class, activation_tester): extension="py", non_source_fail_message="You must use exec(open(this_file).read(), {'__file__': this_file}))", ) + self.unix_line_ending = not IS_WIN def env(self, tmp_path): env = os.environ.copy() |