Private/Logic/RuntimeKernel/Supply/Manifested.PythonSupply.ps1
|
function Get-ManifestedPythonReleaseCandidates { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [pscustomobject]$Definition, [Parameter(Mandatory = $true)] [pscustomobject]$VersionSpec ) $supplyBlock = Get-ManifestedDefinitionBlock -Definition $Definition -SectionName 'supply' -BlockName 'pythonEmbed' if (-not $supplyBlock) { return @() } $releaseCandidatesPattern = if ($supplyBlock.PSObject.Properties.Match('releaseCandidatesPattern').Count -gt 0 -and $supplyBlock.releaseCandidatesPattern) { [string]$supplyBlock.releaseCandidatesPattern } else { '(?is)<a href="/downloads/release/python-(?<slug>\d+)/">Python (?<version>\d+\.\d+\.\d+) - (?<releaseDate>[^<]+)</a>' } $response = Invoke-WebRequestEx -Uri 'https://www.python.org/downloads/windows/' -Headers @{ 'User-Agent' = 'Eigenverft.Manifested.Sandbox' } -UseBasicParsing $matches = [regex]::Matches($response.Content, $releaseCandidatesPattern) $items = New-Object System.Collections.Generic.List[object] $seenVersions = @{} foreach ($match in $matches) { $versionText = $match.Groups['version'].Value.Trim() if ([string]::IsNullOrWhiteSpace($versionText) -or $seenVersions.ContainsKey($versionText)) { continue } $versionObject = ConvertTo-ManifestedVersionObjectFromRule -VersionText $versionText -Rule $VersionSpec.RuntimeVersionRule if (-not $versionObject -or -not (Test-ManifestedManagedVersion -Version $versionObject -VersionPolicy $VersionSpec.VersionPolicy -Rule $VersionSpec.RuntimeVersionRule)) { continue } $seenVersions[$versionText] = $true $items.Add([pscustomobject]@{ ReleaseId = $match.Groups['slug'].Value.Trim() Version = $versionText ReleaseDate = $match.Groups['releaseDate'].Value.Trim() ReleaseUrl = ('https://www.python.org/downloads/release/python-{0}/' -f $match.Groups['slug'].Value.Trim()) }) | Out-Null } return @( $items | Sort-Object -Descending -Property @{ Expression = { ConvertTo-ManifestedVersionObjectFromRule -VersionText $_.Version -Rule $VersionSpec.RuntimeVersionRule } } ) } function Get-ManifestedPythonReleaseAssetDetails { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$ReleaseUrl, [Parameter(Mandatory = $true)] [string]$Flavor, [Parameter(Mandatory = $true)] [pscustomobject]$Definition ) $supplyBlock = Get-ManifestedDefinitionBlock -Definition $Definition -SectionName 'supply' -BlockName 'pythonEmbed' if (-not $supplyBlock) { throw "The pythonEmbed supply block for '$($Definition.commandName)' was not available." } $descriptionPattern = Get-ManifestedFlavorMappedValue -Map $supplyBlock.descriptionPatternByFlavor -Flavor $Flavor if ([string]::IsNullOrWhiteSpace($descriptionPattern)) { throw "Unsupported Python flavor '$Flavor'." } $response = Invoke-WebRequestEx -Uri $ReleaseUrl -Headers @{ 'User-Agent' = 'Eigenverft.Manifested.Sandbox' } -UseBasicParsing $pattern = '(?is)<tr>\s*<td><a href="(?<url>[^"]+)">' + $descriptionPattern + '</a>.*?<td><code class="checksum">(?<checksumHtml>.*?)</code></td>\s*</tr>' $match = [regex]::Match($response.Content, $pattern) if (-not $match.Success) { throw "Could not find the Python embeddable package row for flavor '$Flavor' in $ReleaseUrl." } $downloadUrl = $match.Groups['url'].Value.Trim() $checksumText = ($match.Groups['checksumHtml'].Value -replace '<[^>]+>', '') $checksum = ($checksumText -replace '[^0-9a-fA-F]', '').ToLowerInvariant() if ($checksum.Length -ne 64) { throw "Could not resolve a trusted SHA256 checksum for '$downloadUrl'." } return [pscustomobject]@{ DownloadUrl = $downloadUrl FileName = [System.IO.Path]::GetFileName(([uri]$downloadUrl).AbsolutePath) Sha256 = $checksum ShaSource = 'ReleaseHtml' } } |