diff --git a/docs/changelog/2801.bugfix.rst b/docs/changelog/2801.bugfix.rst new file mode 100644 index 000000000..e06dd8ca5 --- /dev/null +++ b/docs/changelog/2801.bugfix.rst @@ -0,0 +1 @@ +no longer forcibly echo off during windows batch activation diff --git a/src/virtualenv/activation/batch/activate.bat b/src/virtualenv/activation/batch/activate.bat index 3e34ee4db..36b0a8bd7 100644 --- a/src/virtualenv/activation/batch/activate.bat +++ b/src/virtualenv/activation/batch/activate.bat @@ -1,8 +1,6 @@ @REM This file is UTF-8 encoded, so we need to update the current code page while executing it -@echo off -@for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( - @set _OLD_CODEPAGE=%%a -) +@for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do @set _OLD_CODEPAGE=%%a + @if defined _OLD_CODEPAGE ( "%SystemRoot%\System32\chcp.com" 65001 > nul ) diff --git a/tests/unit/activation/test_batch.py b/tests/unit/activation/test_batch.py index 1d22767c3..13d84442e 100644 --- a/tests/unit/activation/test_batch.py +++ b/tests/unit/activation/test_batch.py @@ -33,3 +33,50 @@ def print_prompt(self): return 'echo "%PROMPT%"' activation_tester(Batch) + + +@pytest.mark.usefixtures("activation_python") +def test_batch_output(activation_tester_class, activation_tester, tmp_path): + version_script = tmp_path / "version.bat" + version_script.write_text("ver", encoding="utf-8") + + class Batch(activation_tester_class): + def __init__(self, session) -> None: + super().__init__(BatchActivator, session, None, "activate.bat", "bat") + self._version_cmd = [str(version_script)] + self._invoke_script = [] + self.deactivate = "call deactivate" + self.activate_cmd = "call" + self.pydoc_call = f"call {self.pydoc_call}" + self.unix_line_ending = False + + def _get_test_lines(self, activate_script): + """ + Build intermediary script which will be then called. + In the script just activate environment, call echo to get current + echo setting, and then deactivate. This ensures that echo setting + is preserved and no unwanted output appears. + """ + intermediary_script_path = str(tmp_path / "intermediary.bat") + activate_script_quoted = self.quote(str(activate_script)) + return [ + "@echo on", + f"@echo @call {activate_script_quoted} > {intermediary_script_path}", + f"@echo @echo >> {intermediary_script_path}", + f"@echo @deactivate >> {intermediary_script_path}", + f"@call {intermediary_script_path}", + ] + + def assert_output(self, out, raw, tmp_path): # noqa: ARG002 + assert out[0] == "ECHO is on.", raw + + def quote(self, s): + if '"' in s or " " in s: + text = s.replace('"', r"\"") + return f'"{text}"' + return s + + def print_prompt(self): + return 'echo "%PROMPT%"' + + activation_tester(Batch)