update instalelr

This commit is contained in:
Nose
2026-07-10 21:17:41 -07:00
parent e748c21e2e
commit fa03f1e63b
4 changed files with 90 additions and 565 deletions
+14 -9
View File
@@ -53,27 +53,32 @@ Use `.config` from inside the CLI instead:
This keeps configuration inside the same table-and-selection model as the rest of the app.
## Installation From A Git Checkout
## Installation
Requirements:
- Python 3.9 through 3.13
- Git
- Git (the bootstrap uses it to download the project)
- PowerShell on Windows
- `mpv` recommended for playback workflows
From the repository root, run:
On Windows, run the bootstrap directly from PowerShell. It downloads the project
and starts the installation for you:
```powershell
Set-Location C:\path\to\Medios-Macina
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\scripts\bootstrap.ps1 -Editable
.\.venv\Scripts\Activate.ps1
mm
irm "https://code.glowers.club/goyimnose/Medios-Macina/raw/branch/main/scripts/bootstrap.ps1" | iex
```
For an existing checkout, run this from the repository root:
```powershell
.\scripts\bootstrap.ps1 -Editable
```
Use `-NoMpv`, `-NoDeno`, or `-NoPlaywright` to skip optional external runtime
installation when those components are already managed separately.
Notes:
- The bootstrap script creates `.venv`, installs the project, and exposes the `mm` and `medeia` console commands.
+63 -551
View File
@@ -1,30 +1,29 @@
<#
<#!
.SYNOPSIS
Bootstrap a Python virtualenv and install the project on Windows (PowerShell).
Bootstrap Medios-Macina on Windows.
.DESCRIPTION
Creates a Python virtual environment (default: .venv), upgrades pip, installs the project
(either editable or normal), and optionally creates Desktop and Start Menu shortcuts.
When run from a checkout, this wrapper delegates to scripts/bootstrap.py. When
the script is piped from the web, it downloads the canonical Python bootstrap
to a temporary file so a checkout is not required first.
.EXAMPLE
# Create .venv and install in editable mode, create Desktop shortcut
.\scripts\bootstrap.ps1 -Editable -CreateDesktopShortcut
irm "https://code.glowers.club/goyimnose/Medios-Macina/raw/branch/main/scripts/bootstrap.ps1" | iex
.EXAMPLE
# Use a specific python executable and force overwrite existing venv
.\scripts\bootstrap.ps1 -Python "C:\\Python39\\python.exe" -Force
# Note: you may need to run PowerShell with ExecutionPolicy Bypass:
# powershell -ExecutionPolicy Bypass -File .\scripts\bootstrap.ps1 -Editable
.\scripts\bootstrap.ps1 -Editable -NoPlaywright
#>
param(
[switch]$Editable,
[switch]$CreateDesktopShortcut,
[switch]$CreateStartMenuShortcut,
[string]$VenvPath = ".venv",
[string]$VenvPath = "",
[string]$Python = "",
[switch]$Force,
[switch]$NoInstall,
[switch]$NoMpv,
[switch]$NoDeno,
[switch]$NoPlaywright,
[string]$PlaywrightBrowsers = "chromium",
[switch]$FixUrllib3,
@@ -32,556 +31,69 @@ param(
[switch]$Quiet
)
# Resolve OS detection in a broad-compatible way
try { $IsWindowsPlatform = [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Windows) } catch { $IsWindowsPlatform = $env:OS -match 'Windows' }
$ErrorActionPreference = "Stop"
$bootstrapUrl = "https://code.glowers.club/goyimnose/Medios-Macina/raw/branch/main/scripts/bootstrap.py"
$scriptPath = $MyInvocation.MyCommand.Path
$repoRoot = $null
$bootstrapPath = $null
$temporaryBootstrap = $false
function Write-Log {
param([string]$msg,[string]$lvl="INFO")
if (-not $Quiet) {
if ($lvl -eq "ERROR") { Write-Host "[$lvl] $msg" -ForegroundColor Red } else { Write-Host "[$lvl] $msg" }
if ($scriptPath) {
$scriptDir = Split-Path -Parent $scriptPath
$candidateRoot = (Resolve-Path (Join-Path $scriptDir "..")).Path
if ((Test-Path (Join-Path $candidateRoot "CLI.py")) -and (Test-Path (Join-Path $candidateRoot "scripts\bootstrap.py"))) {
$repoRoot = $candidateRoot
$bootstrapPath = Join-Path $repoRoot "scripts\bootstrap.py"
}
}
function Ensure-Mpv {
# mpv is used by some pipelines; try to ensure it's available on PATH.
try {
$mpvCmd = Get-Command mpv -ErrorAction SilentlyContinue
if ($mpvCmd) {
try {
$v = & mpv --version 2>$null | Select-Object -First 1
if ($v) { Write-Log "mpv found: $v" "INFO" } else { Write-Log "mpv found: $($mpvCmd.Path)" "INFO" }
} catch {
Write-Log "mpv found: $($mpvCmd.Path)" "INFO"
}
return
}
} catch {}
Write-Log "mpv not found on PATH; attempting to install..." "INFO"
try {
if (Get-Command choco -ErrorAction SilentlyContinue) {
& choco install mpv -y --no-progress | Out-Null
} elseif (Get-Command scoop -ErrorAction SilentlyContinue) {
& scoop install mpv | Out-Null
} elseif (Get-Command winget -ErrorAction SilentlyContinue) {
# Best-effort: winget may require a specific id depending on environment.
& winget install --silent --accept-package-agreements --accept-source-agreements mpv | Out-Null
} else {
Write-Log "mpv not found and no supported package manager found (choco/scoop/winget). Install mpv and ensure it's on PATH." "ERROR"
return
}
} catch {
Write-Log "mpv install attempt failed: $_" "ERROR"
return
}
try {
$mpvCmd2 = Get-Command mpv -ErrorAction SilentlyContinue
if ($mpvCmd2) {
try {
$v2 = & mpv --version 2> $null | Select-Object -First 1
if ($v2) { Write-Log "mpv installed: $v2" "INFO" } else { Write-Log "mpv installed: $($mpvCmd2.Path)" "INFO" }
} catch {
Write-Log "mpv installed: $($mpvCmd2.Path)" "INFO"
}
} else {
Write-Log "mpv install attempted but mpv is still not on PATH. Install mpv manually." "ERROR"
}
} catch {}
if (-not $bootstrapPath) {
$bootstrapPath = Join-Path ([IO.Path]::GetTempPath()) ("medios-macina-bootstrap-{0}.py" -f ([guid]::NewGuid()))
Invoke-WebRequest -Uri $bootstrapUrl -OutFile $bootstrapPath -UseBasicParsing
$temporaryBootstrap = $true
}
if ($IsWindowsPlatform) {
Ensure-Mpv
$pythonArgs = @()
if ($Editable) { $pythonArgs += "--install-editable" }
if ($NoInstall) { $pythonArgs += "--skip-deps" }
if ($NoMpv) { $pythonArgs += "--no-mpv" }
if ($NoDeno) { $pythonArgs += "--no-deno" }
if ($NoPlaywright) { $pythonArgs += "--no-playwright" }
if ($PlaywrightBrowsers) { $pythonArgs += @("--browsers", $PlaywrightBrowsers) }
if ($Quiet) { $pythonArgs += "--quiet" }
if ($Force) { $pythonArgs += "--yes" }
if ($VenvPath) {
Write-Warning "-VenvPath is handled by the Python bootstrap's repository-local .venv setting."
}
if ($CreateDesktopShortcut -or $CreateStartMenuShortcut -or $FixUrllib3 -or $RemovePth) {
Write-Warning "One or more legacy PowerShell-only options were ignored by the canonical Python bootstrap."
}
# Track whether the user chose an interactive auto-fix (so we can auto-remove .pth files)
$AutoFixInteractive = $false
function Find-Python {
param([string]$preferred)
$candidates = @()
if ($preferred -and $preferred.Trim()) { $candidates += $preferred }
$candidates += @("python","python3","py")
foreach ($c in $candidates) {
try {
if ($c -eq "py") {
$out = & py -3 -c "import sys, json; print(sys.executable)" 2>$null
if ($out) { return $out.Trim() }
} else {
$out = & $c -c "import sys, json; print(sys.executable)" 2>$null
if ($out) { return $out.Trim() }
}
} catch {}
}
return $null
}
# operate from repo root (parent of scripts dir)
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoRoot = (Resolve-Path (Join-Path $scriptDir "..")).Path
Set-Location $repoRoot
$scriptsDir = Join-Path $repoRoot 'scripts'
$pythonExe = Find-Python -preferred $Python
if (-not $pythonExe) { Write-Log "No Python interpreter found. Specify -Python <path> or install Python." "ERROR"; exit 2 }
Write-Log "Using Python: $pythonExe"
# Full venv path
try { $venvFull = (Resolve-Path -LiteralPath $VenvPath -ErrorAction SilentlyContinue).Path } catch { $venvFull = $null }
if (-not $venvFull) { $venvFull = (Join-Path $repoRoot $VenvPath) }
# Handle existing venv
$venvExists = Test-Path $venvFull
if ($venvExists) {
if ($Force) {
Write-Log "Removing existing venv at $venvFull"
Remove-Item -Recurse -Force $venvFull
$venvExists = $false
} else {
# Quick health check: does the existing venv have a python executable?
$venvPy1 = Join-Path $venvFull "Scripts\python.exe"
$venvPy2 = Join-Path $venvFull "bin/python"
$venvHasPython = $false
try {
if (Test-Path $venvPy1 -PathType Leaf -ErrorAction SilentlyContinue) { $venvHasPython = $true }
elseif (Test-Path $venvPy2 -PathType Leaf -ErrorAction SilentlyContinue) { $venvHasPython = $true }
} catch {}
if (-not $venvHasPython) {
if ($Quiet) {
Write-Log "Existing venv appears incomplete or broken and quiet mode prevents prompting. Use -Force to recreate." "ERROR"
exit 4
}
$ans = Read-Host "$venvFull exists but appears invalid (no python executable). Overwrite to recreate? (y/N)"
if ($ans -eq 'y' -or $ans -eq 'Y') {
Write-Log "Removing broken venv at $venvFull"
Remove-Item -Recurse -Force $venvFull
$venvExists = $false
} else {
Write-Log "Aborted due to broken venv." "ERROR"; exit 4
}
} else {
if ($Quiet) {
Write-Log "Using existing venv at $venvFull (quiet mode)" "INFO"
} else {
$ans = Read-Host "$venvFull already exists. Overwrite? (y/N) (default: use existing venv)"
if ($ans -eq 'y' -or $ans -eq 'Y') {
Write-Log "Removing existing venv at $venvFull"
Remove-Item -Recurse -Force $venvFull
$venvExists = $false
} else {
Write-Log "Continuing using existing venv at $venvFull" "INFO"
}
}
}
}
}
if (-not (Test-Path $venvFull)) {
Write-Log "Creating venv at $venvFull"
try {
& $pythonExe -m venv $venvFull
} catch {
Write-Log "Failed to create venv: $_" "ERROR"; exit 3
}
} else {
Write-Log "Using existing venv at $venvFull" "INFO"
}
# Determine venv python executable
$venvPython = Join-Path $venvFull "Scripts\python.exe"
if (-not (Test-Path $venvPython)) { $venvPython = Join-Path $venvFull "bin/python" }
if (-not (Test-Path $venvPython)) { Write-Log "Created venv but could not find python inside it." "ERROR"; exit 4 }
Write-Log "Using venv python: $venvPython"
if (-not $NoInstall) {
# Suggest editable install for development checkouts (interactive git clones)
if (-not $Editable) {
$isGit = $false
try {
if (Test-Path (Join-Path $repoRoot '.git')) { $isGit = $true }
elseif ((Get-Command git -ErrorAction SilentlyContinue) -ne $null) {
try { $gitOut = & git -C $repoRoot rev-parse --is-inside-work-tree 2>$null; if ($gitOut -eq 'true') { $isGit = $true } } catch {}
}
} catch {}
if ($isGit) {
$Editable = $true
Write-Log "Detected development checkout; installing in editable mode for development." "INFO"
}
}
Write-Log "Upgrading pip, setuptools, wheel"
try { & $venvPython -m pip install -U pip setuptools wheel } catch { Write-Log "pip upgrade failed: $_" "ERROR"; exit 5 }
if ($Editable) { $editable_label = "(editable)" } else { $editable_label = "" }
Write-Log ("Installing project {0}" -f $editable_label)
try {
if ($Editable) { & $venvPython -m pip install -e $scriptsDir } else { & $venvPython -m pip install $scriptsDir }
} catch {
Write-Log "pip install failed: $_" "ERROR"; exit 6
}
# Verify top-level 'CLI' import and (if missing) attempt to make it available
Write-Log "Verifying installed CLI import..."
try {
& $venvPython -c "import importlib; importlib.import_module('scripts.cli_entry')" 2>$null
if ($LASTEXITCODE -eq 0) { Write-Log "OK: 'scripts.cli_entry' is importable in the venv." }
} catch {}
try {
& $venvPython -c "import importlib; importlib.import_module('CLI')" 2>$null
if ($LASTEXITCODE -eq 0) { Write-Log "Top-level 'CLI' is importable in the venv." }
else {
Write-Log "Top-level 'CLI' not importable; writing venv site-packages .pth pointing at repo root..." "INFO"
$siteDir = (& $venvPython -c "import sysconfig; print(sysconfig.get_paths().get('purelib',''))" 2>$null).Trim()
if (-not $siteDir -or -not (Test-Path $siteDir)) {
Write-Log "ERROR: unable to determine venv site-packages directory (purelib='$siteDir'); aborting." "ERROR"
exit 6
}
$pth = Join-Path $siteDir 'medeia_repo.pth'
Set-Content -LiteralPath $pth -Value $repoRoot -Encoding UTF8
Write-Log "Wrote .pth adding repo root to venv site-packages: $pth" "INFO"
& $venvPython -c "import importlib; importlib.import_module('CLI')" 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Log "OK: top-level 'CLI' is now importable (after .pth)." "INFO"
} else {
Write-Log "ERROR: top-level 'CLI' still not importable after writing .pth ($pth); aborting." "ERROR"
exit 6
}
}
} catch {
Write-Log "Failed to verify top-level 'CLI': $_" "ERROR"
exit 6
}
# Install Playwright browsers (default: chromium) unless explicitly disabled
if (-not $NoPlaywright) {
Write-Log "Ensuring Playwright browsers are installed (browsers=$PlaywrightBrowsers)..."
try {
& $venvPython -c "import importlib; importlib.import_module('playwright')" 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Log "'playwright' package not found in venv; installing via pip..."
& $venvPython -m pip install playwright
}
} catch {
Write-Log "Failed to check/install 'playwright' package: $_" "ERROR"
}
try {
if ($PlaywrightBrowsers -eq 'all') {
Write-Log "Installing all Playwright browsers..."
& $venvPython -m playwright install
} else {
$list = $PlaywrightBrowsers -split ','
foreach ($b in $list) {
$btrim = $b.Trim()
if ($btrim) {
Write-Log "Installing Playwright browser: $btrim"
& $venvPython -m playwright install $btrim
}
}
}
} catch {
Write-Log "Playwright browser install failed: $_" "ERROR"
}
}
# Verify environment for known package conflicts (urllib3 compatibility)
Write-Log "Verifying environment for known package conflicts (urllib3 compatibility)..."
try {
& $venvPython -c "import sys; from SYS.env_check import check_urllib3_compat; ok, msg = check_urllib3_compat(); print(msg); sys.exit(0 if ok else 2)"
if ($LASTEXITCODE -ne 0) {
Write-Log "Bootstrap detected a potentially broken 'urllib3' installation. See message above." "ERROR"
Write-Log "Suggested fixes (activate the venv first):" "INFO"
Write-Log " $ $venvPython -m pip uninstall urllib3-future -y" "INFO"
Write-Log " $ $venvPython -m pip install --upgrade --force-reinstall urllib3" "INFO"
Write-Log " $ $venvPython -m pip install niquests -U" "INFO"
function Get-SitePackages {
param($python)
try {
$json = & $python -c "import site, sysconfig, json; p=[];
try:
p.extend(site.getsitepackages())
except Exception:
pass
try:
pp = sysconfig.get_paths().get('purelib')
if pp:
p.append(pp)
except Exception:
pass
seen = []
out = []
for s in p:
if s and s not in seen:
seen.append(s)
out.append(s)
print(json.dumps(out))"
return $json | ConvertFrom-Json
} catch {
return @()
}
}
function Find-InterferingPth {
param($python)
$pths = @()
$sps = Get-SitePackages -python $python
foreach ($sp in $sps) {
if (Test-Path $sp) {
Get-ChildItem -Path $sp -Filter *.pth -File -ErrorAction SilentlyContinue | ForEach-Object {
$c = Get-Content -Path $_.FullName -ErrorAction SilentlyContinue | Out-String
if ($c -match 'urllib3_future' -or $c -match 'urllib3-future') {
$pths += $_.FullName
}
}
}
}
return $pths
}
# Helper to try removal and re-verify
function RemovePthAndVerify {
param($python, $paths)
foreach ($p in $paths) { Remove-Item -Force $p -ErrorAction SilentlyContinue }
try { & $python -m pip install --upgrade --force-reinstall urllib3 } catch { Write-Log "pip install failed: $_" "ERROR"; return $false }
& $python -c "import sys; from SYS.env_check import check_urllib3_compat; ok, msg = check_urllib3_compat(); print(msg); sys.exit(0 if ok else 2)"
return ($LASTEXITCODE -eq 0)
}
if ($FixUrllib3) {
Write-Log "Attempting automatic fix (--FixUrllib3)..." "INFO"
try { & $venvPython -m pip uninstall urllib3-future -y } catch {}
try { & $venvPython -m pip install --upgrade --force-reinstall urllib3 } catch { Write-Log "pip install failed: $_" "ERROR"; exit 7 }
try { & $venvPython -m pip install niquests -U } catch { Write-Log "pip install niquests failed: $_" "ERROR" }
& $venvPython -c "import sys; from SYS.env_check import check_urllib3_compat; ok, msg = check_urllib3_compat(); print(msg); sys.exit(0 if ok else 2)"
if ($LASTEXITCODE -eq 0) {
Write-Log "Success: urllib3 problems appear resolved; continuing." "INFO"
} else {
Write-Log "Initial automatic fix did not resolve the issue; searching for interfering .pth files..." "INFO"
$pths = Find-InterferingPth -python $venvPython
if ($pths.Count -eq 0) {
Write-Log "No interfering .pth files found; aborting." "ERROR"
exit 7
}
Write-Log ("Found interfering .pth files:`n" + ($pths -join "`n")) "ERROR"
if ($RemovePth) {
Write-Log "Removing .pth files as requested..." "INFO"
if (RemovePthAndVerify -python $venvPython -paths $pths) {
Write-Log "Success: urllib3 problems resolved after .pth removal; continuing." "INFO"
} else {
Write-Log "Automatic fix failed even after .pth removal; aborting." "ERROR"
exit 7
}
} else {
if ($Quiet) { Write-Log "Detected interfering .pth files but cannot prompt in quiet mode. Use -RemovePth to remove them automatically." "ERROR"; exit 7 }
$ans = Read-Host "Remove these files now? (y/N)"
if ($ans -eq 'y' -or $ans -eq 'Y') {
if (RemovePthAndVerify -python $venvPython -paths $pths) {
Write-Log "Success: urllib3 problems resolved after .pth removal; continuing." "INFO"
} else {
Write-Log "Automatic fix failed even after .pth removal; aborting." "ERROR"
exit 7
}
} else {
Write-Log "User declined to remove .pth files. Aborting." "ERROR"
exit 7
}
}
}
} else {
if ($Quiet) {
Write-Log "Bootstrap detected a potentially broken 'urllib3' installation. Use -FixUrllib3 to attempt an automatic fix." "ERROR"
exit 7
}
$ans = Read-Host "Attempt automatic fix now? (y/N)"
if ($ans -eq 'y' -or $ans -eq 'Y') {
$AutoFixInteractive = $true
try { & $venvPython -m pip uninstall urllib3-future -y } catch {}
try { & $venvPython -m pip install --upgrade --force-reinstall urllib3 } catch { Write-Log "pip install failed: $_" "ERROR"; exit 7 }
try { & $venvPython -m pip install niquests -U } catch { Write-Log "pip install niquests failed: $_" "ERROR" }
& $venvPython -c "import sys; from SYS.env_check import check_urllib3_compat; ok, msg = check_urllib3_compat(); print(msg); sys.exit(0 if ok else 2)"
if ($LASTEXITCODE -eq 0) {
Write-Log "Success: urllib3 problems appear resolved; continuing." "INFO"
} else {
Write-Log "Initial automatic fix did not resolve the issue; searching for interfering .pth files..." "INFO"
$pths = Find-InterferingPth -python $venvPython
if ($pths.Count -eq 0) {
Write-Log "No interfering .pth files found; aborting." "ERROR"
exit 7
}
Write-Log ("Found interfering .pth files:`n" + ($pths -join "`n")) "ERROR"
if ($RemovePth -or $AutoFixInteractive -or $FixUrllib3) {
Write-Log "Removing .pth files automatically..." "INFO"
if (RemovePthAndVerify -python $venvPython -paths $pths) {
Write-Log "Success: urllib3 problems resolved after .pth removal; continuing." "INFO"
} else {
Write-Log "Automatic fix failed even after .pth removal; aborting." "ERROR"
exit 7
}
} else {
$ans2 = Read-Host "Remove these files now? (y/N)"
if ($ans2 -eq 'y' -or $ans2 -eq 'Y') {
if (RemovePthAndVerify -python $venvPython -paths $pths) {
Write-Log "Success: urllib3 problems resolved after .pth removal; continuing." "INFO"
} else {
Write-Log "Automatic fix failed even after .pth removal; aborting." "ERROR"
exit 7
}
} else {
Write-Log "User declined to remove .pth files. Aborting." "ERROR"
exit 7
}
}
}
} else {
Write-Log "Aborting bootstrap to avoid leaving a broken environment." "ERROR"
exit 7
}
}
}
} catch {
Write-Log "Failed to run environment verification: $_" "ERROR"
}
Write-Log "Deno is already installed: $($denoCmd.Path)"
} else {
Write-Log "Installing Deno via official installer (https://deno.land)"
try {
try {
irm https://deno.land/install.ps1 | iex
} catch {
iwr https://deno.land/install.ps1 -UseBasicParsing | iex
}
# Ensure common install locations are on PATH for this session
$denoCandidatePaths = @(
Join-Path $env:USERPROFILE ".deno\bin",
Join-Path $env:LOCALAPPDATA "deno\bin"
)
foreach ($p in $denoCandidatePaths) {
if (Test-Path $p) {
if ($env:PATH -notmatch [regex]::Escape($p)) {
$env:PATH = $env:PATH + ";" + $p
}
}
}
$v = & deno --version 2>$null
if ($v) {
Write-Log "Deno installed: $v"
} else {
Write-Log "Deno installer completed but 'deno' not found on PATH; you may need to restart your shell or add the Deno bin folder to PATH." "ERROR"
}
} catch {
Write-Log "Deno install failed: $_" "ERROR"
}
}
# Shortcuts (Windows only)
if ($IsWindowsPlatform) {
if ($CreateDesktopShortcut -or $CreateStartMenuShortcut) {
$wsh = New-Object -ComObject WScript.Shell
$mmExe = Join-Path $venvFull "Scripts\mm.exe"
$target = $null
$args = ""
if (Test-Path $mmExe) {
$target = $mmExe
} else {
$target = $venvPython
$args = "-m scripts.cli_entry"
}
if ($CreateDesktopShortcut) {
$desk = [Environment]::GetFolderPath('Desktop')
$link = Join-Path $desk "Medeia-Macina.lnk"
Write-Log "Creating Desktop shortcut: $link"
$sc = $wsh.CreateShortcut($link)
$sc.TargetPath = $target
$sc.Arguments = $args
$sc.WorkingDirectory = $repoRoot
$sc.IconLocation = "$target,0"
$sc.Save()
}
if ($CreateStartMenuShortcut) {
$start = Join-Path ([Environment]::GetFolderPath('ApplicationData')) 'Microsoft\Windows\Start Menu\Programs'
$dir = Join-Path $start "Medeia-Macina"
New-Item -ItemType Directory -Path $dir -Force | Out-Null
$link2 = Join-Path $dir "Medeia-Macina.lnk"
Write-Log "Creating Start Menu shortcut: $link2"
$sc2 = $wsh.CreateShortcut($link2)
$sc2.TargetPath = $target
$sc2.Arguments = $args
$sc2.WorkingDirectory = $repoRoot
$sc2.IconLocation = "$target,0"
$sc2.Save()
}
}
}
# Install global 'mm' launcher into the user's bin directory so it can be invoked from any shell.
try {
$globalBin = Join-Path $env:USERPROFILE 'bin'
New-Item -ItemType Directory -Path $globalBin -Force | Out-Null
$pythonCommand = $null
if ($Python) {
$pythonCommand = $Python
} elseif (Get-Command py -ErrorAction SilentlyContinue) {
$pythonCommand = "py"
} elseif (Get-Command python -ErrorAction SilentlyContinue) {
$pythonCommand = "python"
}
$mmPs1 = Join-Path $globalBin 'mm.ps1'
if (-not $pythonCommand) {
throw "No Python 3 interpreter found. Install Python 3 and run the bootstrap again."
}
$repo = $repoRoot
# PowerShell shim: use single-quoted here-string so literal PowerShell variables
# (like $args) are not expanded by this script when writing the file.
$ps1Text = @'
Param([Parameter(ValueFromRemainingArguments=$true)] $args)
$repo = "__REPO__"
$venv = Join-Path $repo '.venv'
$exe = Join-Path $venv 'Scripts\mm.exe'
if (Test-Path $exe) { & $exe @args; exit $LASTEXITCODE }
$py = Join-Path $venv 'Scripts\python.exe'
if ($env:MM_DEBUG) {
Write-Host "MM_DEBUG: diagnostics" -ForegroundColor Yellow
if (Test-Path $py) { & $py -c "import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);" }
else { python -c "import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);" }
}
if (Test-Path $py) { & $py -m scripts.cli_entry @args; exit $LASTEXITCODE }
if (Test-Path (Join-Path $repo 'CLI.py')) { & python (Join-Path $repo 'CLI.py') @args; exit $LASTEXITCODE }
# fallback
python -m scripts.cli_entry @args
'@
# Thin wrapper: prefer the canonical Python bootstrap installer
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repo = (Resolve-Path (Join-Path $scriptDir "..")).Path
$venvPy = Join-Path $repo '.venv\Scripts\python.exe'
# Normalize incoming quiet flag (-Quiet) into -q for the Python script
$forwardArgs = @()
foreach ($a in $args) {
if ($a -eq '-Quiet') { $forwardArgs += '-q' } else { $forwardArgs += $a }
if ($pythonCommand -eq "py") {
& py -3 $bootstrapPath @pythonArgs
} else {
& $pythonCommand $bootstrapPath @pythonArgs
}
$exitCode = $LASTEXITCODE
} finally {
if ($temporaryBootstrap -and (Test-Path $bootstrapPath)) {
Remove-Item -LiteralPath $bootstrapPath -Force -ErrorAction SilentlyContinue
}
}
# Debug helper
if ($env:MM_DEBUG) { Write-Host "MM_DEBUG: invoking python installer with args: $forwardArgs" -ForegroundColor Yellow }
if (Test-Path $venvPy) {
& $venvPy (Join-Path $repo 'scripts\bootstrap.py') --no-delegate @forwardArgs
exit $LASTEXITCODE
}
# Fall back to any system Python (py -3 -> python3 -> python)
if (Get-Command -Name py -ErrorAction SilentlyContinue) {
& py -3 (Join-Path $repo 'scripts\bootstrap.py') --no-delegate @forwardArgs
exit $LASTEXITCODE
}
if (Get-Command -Name python3 -ErrorAction SilentlyContinue) {
& python3 (Join-Path $repo 'scripts\bootstrap.py') --no-delegate @forwardArgs
exit $LASTEXITCODE
}
if (Get-Command -Name python -ErrorAction SilentlyContinue) {
& python (Join-Path $repo 'scripts\bootstrap.py') --no-delegate @forwardArgs
exit $LASTEXITCODE
}
Write-Host 'Error: no suitable Python 3 interpreter found. Please install Python 3 or use the venv.' -ForegroundColor Red
exit 127
exit $exitCode
+13 -1
View File
@@ -315,7 +315,19 @@ def _install_mpv() -> int:
# Windows: use winget (built-in package manager)
if shutil.which("winget"):
print("Installing MPV via winget...")
run(["winget", "install", "--id=mpv.net", "-e"])
run(
[
"winget",
"install",
"--id=mpv.net",
"-e",
"--source",
"winget",
"--accept-source-agreements",
"--accept-package-agreements",
"--silent",
]
)
else:
print(
"MPV not found and winget not available.\n"
-4
View File
@@ -120,12 +120,8 @@ packages = [
"cmdlet",
"cmdnat",
"API",
"Store",
"PluginCore",
"SYS",
"tool",
"TUI",
"MPV",
]
package-dir = {"" = ".."}