Following this post, I have a PowerShell script that aims to interact with the Python Package Index (PyPI) to find the latest release of a specified package that is compatible with the current Python environment. The script has several key functionalities:
- Determines the currently installed Python version and adjusts it to only include the major and minor version numbers (e.g.,
3.8from3.8.5). - Fetches package data from PyPI using the package name.
- Parses the JSON response to find the latest release compatible with the determined Python version. Compatibility is based on each release's
requires_pythonfield. - Outputs the details of the found release or indicates if no compatible release is found.
Here is the PowerShell script:
# The Python version to match or find a slightly lower version for
$targetPythonVersion = [version](python --version 2>&1 | ForEach-Object { $_ -replace '^Python\s', '' } | ForEach-Object { ($_.Split('.')[0..1]) -join '.' })
function Get-Json {
param (
[Parameter(mandatory = $true)]
[string]$PackageName
)
$url = "https://pypi.org/pypi/$PackageName/json"
$response = Invoke-RestMethod -Uri $url
return $response
}
# Function to check if a version satisfies the requirement
function Test-VersionCompatibility {
param (
[Parameter(mandatory = $true)]
[version]$requiredVersion,
[Parameter(mandatory = $true)]
[string]$requiresPython
)
# Split the requirement string into versions, assuming the format is ">=2.6,!=3.0.*,!=3.1.*,!=3.2.*"
$versionConditions = $requiresPython -split ','
foreach ($condition in $versionConditions) {
if ($condition -match '>=?(\d\.\d+)(\.(\d+))?') {
$minVersion = [version]$Matches[1]
if ($requiredVersion -lt $minVersion) {
return $false
}
}
elseif ($condition -match '<=?(\d\.\d+)(\.(\d+))?') {
$maxVersion = [version]$Matches[1]
if ($requiredVersion -gt $maxVersion) {
return $false
}
}
elseif ($condition -match '!=?(\d\.\d+)(\.(\d+))?') {
$notVersion = [version]$Matches[1]
if ($requiredVersion -eq $notVersion) {
return $false
}
}
}
return $true
}
function Get-Latest {
param (
[Parameter(mandatory = $true)]
[version]$requiredVersion,
[Parameter(mandatory = $true)]
[string]$PackageName
)
# Read the JSON content
$jsonContent = Get-Json -PackageName $PackageName
# Iterate through releases in reverse chronological order
$latestCompatibleRelease = $null
foreach ($release in ($jsonContent.releases.PSObject.Properties | Sort-Object Name -Descending)) {
foreach ($package in $release.Value) {
if ($null -ne $package.requires_python -and (Test-VersionCompatibility -requiredVersion $requiredVersion -requiresPython $package.requires_python)) {
$latestCompatibleRelease = $release
break
}
}
if ($latestCompatibleRelease) {
break
}
}
# Output the found release
if ($latestCompatibleRelease) {
# $latestCompatibleRelease.Name
return ($latestCompatibleRelease.Value | ConvertTo-Json)
}
else {
Write-Output "No compatible release found for Python $requiredVersion"
}
}
$release = Get-Latest -requiredVersion $targetPythonVersion -PackageName "setuptools"
Write-Output $release
I'm seeking feedback on the following:
- Best practices for PowerShell scripting, especially regarding error handling and JSON parsing.
- Any potential performance improvements, particularly in parsing and iterating over the JSON response.
- Ways to enhance the version comparison logic to determine compatibility, especially considering Python's versioning scheme more accurately.