diff --git a/scripts/build_rayforge_windows_checkpoint.ps1 b/scripts/build_rayforge_windows_checkpoint.ps1 index ba8d1b8..724ac80 100644 --- a/scripts/build_rayforge_windows_checkpoint.ps1 +++ b/scripts/build_rayforge_windows_checkpoint.ps1 @@ -79,6 +79,12 @@ if ($PSCmdlet.ShouldProcess($addonDestination, "Stage no-device addon")) { New-Item -ItemType Directory -Force -Path $addonDestination | Out-Null Copy-Item -Path (Join-Path $addonSource "*") ` -Destination $addonDestination -Recurse -Force + Get-ChildItem -LiteralPath $addonDestination -Recurse -Directory -Force | + Where-Object { $_.Name -eq "__pycache__" } | + Remove-Item -Recurse -Force + Get-ChildItem -LiteralPath $addonDestination -Recurse -File -Force | + Where-Object { $_.Extension -eq ".pyc" } | + Remove-Item -Force } $prepareArguments = @{ @@ -86,9 +92,20 @@ $prepareArguments = @{ BuildWindowsBundle = $true AllowStagedPirateRayAddon = $true } -& (Join-Path $PSScriptRoot "prepare_rayforge_build.ps1") @prepareArguments -if ($LASTEXITCODE -ne 0) { - throw "Pinned Rayforge Windows bundle build failed" +$pyInstallerSiteCustomize = Join-Path $PSScriptRoot "pyinstaller-sitecustomize" +$previousPythonPath = $env:PYTHONPATH +try { + $env:PYTHONPATH = if ($previousPythonPath) { + "$pyInstallerSiteCustomize;$previousPythonPath" + } else { + $pyInstallerSiteCustomize + } + & (Join-Path $PSScriptRoot "prepare_rayforge_build.ps1") @prepareArguments + if ($LASTEXITCODE -ne 0) { + throw "Pinned Rayforge Windows bundle build failed" + } +} finally { + $env:PYTHONPATH = $previousPythonPath } $bundleName = "rayforge-vpirateray-$shortCommit" @@ -132,6 +149,10 @@ if ($PSCmdlet.ShouldProcess($archive, "Create portable checkpoint archive")) { } $addonFiles = Get-ChildItem -LiteralPath $addonSource -Recurse -File | + Where-Object { + $_.Extension -ne ".pyc" -and + $_.FullName -notmatch '[\\/]__pycache__[\\/]' + } | Sort-Object FullName | ForEach-Object { [ordered]@{ diff --git a/scripts/pyinstaller-sitecustomize/sitecustomize.py b/scripts/pyinstaller-sitecustomize/sitecustomize.py new file mode 100644 index 0000000..b392b62 --- /dev/null +++ b/scripts/pyinstaller-sitecustomize/sitecustomize.py @@ -0,0 +1,6 @@ +"""Keep PyInstaller's isolated analysis from initializing a GTK display.""" + +import gi + + +gi.disable_legacy_autoinit() diff --git a/tests/test_m1_acceptance_pipeline.py b/tests/test_m1_acceptance_pipeline.py index 808d1df..a9525ee 100644 --- a/tests/test_m1_acceptance_pipeline.py +++ b/tests/test_m1_acceptance_pipeline.py @@ -6,6 +6,9 @@ from pathlib import Path ROOT = Path(__file__).resolve().parents[1] ACCEPTANCE = ROOT / "scripts" / "run_m1_no_device_acceptance.py" BUILD = ROOT / "scripts" / "build_rayforge_windows_checkpoint.ps1" +PYINSTALLER_SITE_CUSTOMIZE = ( + ROOT / "scripts" / "pyinstaller-sitecustomize" / "sitecustomize.py" +) VERIFY = ROOT / "scripts" / "verify_rayforge_windows_checkpoint.py" UPSTREAM = ROOT / "upstreams" / "rayforge.json" @@ -54,6 +57,14 @@ class M1AcceptancePipelineTests(unittest.TestCase): self.assertIn("-LiteralPath $artifactInstaller", source) self.assertIn("checkout must be clean", source) self.assertIn("Artifact root must be absent or empty", source) + self.assertIn('Name -eq "__pycache__"', source) + self.assertIn('Extension -eq ".pyc"', source) + self.assertIn('Extension -ne ".pyc"', source) + self.assertIn("pyinstaller-sitecustomize", source) + self.assertIn("$env:PYTHONPATH", source) + + site_customize = PYINSTALLER_SITE_CUSTOMIZE.read_text(encoding="utf-8") + self.assertIn("gi.disable_legacy_autoinit()", site_customize) def test_acceptance_has_no_hardware_commands(self): source = ACCEPTANCE.read_text(encoding="utf-8").lower()