From f61353e852aae5518e777a5ea0908c707f66eb7e Mon Sep 17 00:00:00 2001 From: Dhananjay2799 Date: Sat, 29 Aug 2026 11:46:12 -0400 Subject: [PATCH 1/2] fix Windows installer Scripts path detection --- install.bat | 4 ++-- tests/unit/test_windows_installer.py | 30 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/unit/test_windows_installer.py diff --git a/install.bat b/install.bat index 8ab7fb35..fa8a479b 100644 --- a/install.bat +++ b/install.bat @@ -52,10 +52,10 @@ if %ERRORLEVEL% equ 0 ( ) REM Step 4: Find the Scripts directory and add to PATH -for /f "delims=" %%i in ('%PYTHON% -c "import site; print(site.getusersitepackages().replace(chr(92)+chr(39)lib'+chr(92)+'site-packages', chr(92)+'Scripts'))"') do set SCRIPTS_DIR=%%i +for /f "delims=" %%i in ('%PYTHON% -c "import sysconfig; print(sysconfig.get_path('scripts', scheme='nt_user'))"') do set SCRIPTS_DIR=%%i if not exist "%SCRIPTS_DIR%\ebuild.exe" ( - for /f "delims=" %%i in ('%PYTHON% -c "import sys; import os; print(os.path.join(os.path.dirname(sys.executable), chr(39)Scripts'))"') do set SCRIPTS_DIR=%%i + for /f "delims=" %%i in ('%PYTHON% -c "import sysconfig; print(sysconfig.get_path('scripts'))"') do set SCRIPTS_DIR=%%i ) if exist "%SCRIPTS_DIR%\ebuild.exe" ( diff --git a/tests/unit/test_windows_installer.py b/tests/unit/test_windows_installer.py new file mode 100644 index 00000000..0a83f0d9 --- /dev/null +++ b/tests/unit/test_windows_installer.py @@ -0,0 +1,30 @@ +from pathlib import Path + + +INSTALLER = Path(__file__).resolve().parents[2] / "install.bat" + + +def test_embedded_python_commands_are_syntactically_valid(): + """Python snippets embedded in the Windows installer must be valid.""" + content = INSTALLER.read_text(encoding="utf-8") + commands = [] + + for line in content.splitlines(): + marker = '-c "' + + if marker not in line: + continue + + start = line.index(marker) + len(marker) + end = line.rfind('"') + + assert end > start, ( + f"Malformed embedded Python command in install.bat: {line}" + ) + + commands.append(line[start:end]) + + assert commands, "No embedded Python commands found in install.bat" + + for command in commands: + compile(command, "", "exec") From c93910ca6fc4525440ff962e17880f5fc6f39932 Mon Sep 17 00:00:00 2001 From: Dhananjay2799 Date: Thu, 3 Sep 2026 21:01:26 -0400 Subject: [PATCH 2/2] address Windows installer review feedback --- install.bat | 4 +- tests/unit/test_windows_installer.py | 96 +++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 18 deletions(-) diff --git a/install.bat b/install.bat index fa8a479b..a7a73dd1 100644 --- a/install.bat +++ b/install.bat @@ -52,10 +52,10 @@ if %ERRORLEVEL% equ 0 ( ) REM Step 4: Find the Scripts directory and add to PATH -for /f "delims=" %%i in ('%PYTHON% -c "import sysconfig; print(sysconfig.get_path('scripts', scheme='nt_user'))"') do set SCRIPTS_DIR=%%i +for /f "delims=" %%i in ('%PYTHON% -c "import sysconfig; print(sysconfig.get_path('scripts'))"') do set SCRIPTS_DIR=%%i if not exist "%SCRIPTS_DIR%\ebuild.exe" ( - for /f "delims=" %%i in ('%PYTHON% -c "import sysconfig; print(sysconfig.get_path('scripts'))"') do set SCRIPTS_DIR=%%i + for /f "delims=" %%i in ('%PYTHON% -c "import sysconfig; print(sysconfig.get_path('scripts', scheme='nt_user'))"') do set SCRIPTS_DIR=%%i ) if exist "%SCRIPTS_DIR%\ebuild.exe" ( diff --git a/tests/unit/test_windows_installer.py b/tests/unit/test_windows_installer.py index 0a83f0d9..2975cd7d 100644 --- a/tests/unit/test_windows_installer.py +++ b/tests/unit/test_windows_installer.py @@ -1,30 +1,94 @@ -from pathlib import Path +import os +from pathlib import Path +import re +import subprocess +import sys + +import pytest INSTALLER = Path(__file__).resolve().parents[2] / "install.bat" +BATCH_COMMAND_PATTERN = re.compile( + r'^\s*for /f "delims=" %%i in \(\'' + r'%PYTHON% -c "(?P.+)"\'\) ' + r'do set SCRIPTS_DIR=%%i\s*$' +) + -def test_embedded_python_commands_are_syntactically_valid(): - """Python snippets embedded in the Windows installer must be valid.""" +def _installer_python_commands(): content = INSTALLER.read_text(encoding="utf-8") - commands = [] - for line in content.splitlines(): - marker = '-c "' + return [ + line + for line in content.splitlines() + if '-c "' in line + ] - if marker not in line: - continue - start = line.index(marker) + len(marker) - end = line.rfind('"') +def test_embedded_python_commands_are_well_formed(): + """Installer Python commands must have valid batch and Python syntax.""" + lines = _installer_python_commands() - assert end > start, ( - f"Malformed embedded Python command in install.bat: {line}" - ) + assert lines, "No embedded Python commands found in install.bat" - commands.append(line[start:end]) + for line in lines: + match = BATCH_COMMAND_PATTERN.fullmatch(line) - assert commands, "No embedded Python commands found in install.bat" + assert match is not None, ( + f"Malformed FOR /F Python command in install.bat: {line}" + ) - for command in commands: + command = match.group("python") compile(command, "", "exec") + + +@pytest.mark.skipif( + os.name != "nt", + reason="Windows cmd.exe validation", +) +def test_embedded_python_commands_execute_in_cmd(tmp_path): + """The complete FOR /F commands must execute successfully in cmd.exe.""" + lines = _installer_python_commands() + + assert len(lines) == 2 + + batch_file = tmp_path / "validate_installer_commands.bat" + + script = "\r\n".join( + [ + "@echo off", + "setlocal", + f'set "PYTHON={sys.executable}"', + 'set "SCRIPTS_DIR="', + lines[0], + "if not defined SCRIPTS_DIR exit /b 11", + "echo FIRST=%SCRIPTS_DIR%", + 'set "SCRIPTS_DIR="', + lines[1], + "if not defined SCRIPTS_DIR exit /b 12", + "echo SECOND=%SCRIPTS_DIR%", + "endlocal", + ] + ) + + batch_file.write_text( + script, + encoding="utf-8", + newline="", + ) + + result = subprocess.run( + ["cmd.exe", "/d", "/c", str(batch_file)], + capture_output=True, + text=True, + check=False, + ) + + assert result.returncode == 0, ( + f"cmd.exe failed\nSTDOUT:\n{result.stdout}\n" + f"STDERR:\n{result.stderr}" + ) + + assert "FIRST=" in result.stdout + assert "SECOND=" in result.stdout