Types/OpenPackage.Source/Python.ps1
|
<# .SYNOPSIS Gets a python package .DESCRIPTION Gets a python package as an open package #> param( # A python package. # This can be the name of the package in PyPi or a package link from `PyPi.org` [Parameter(ValueFromPipelineByPropertyName)] [Alias('PyPi', 'Pip')] [string[]] $PythonPackage, # A list of file wildcards to include. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Include, # A list of file wildcards to exclude. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Exclude, # The base path within the package. # Content should be added beneath this base path. [string] $BasePath = '/', # A content type map. # This maps extensions and URIs to a content type. [Collections.IDictionary] $TypeMap = $( ([PSCustomObject]@{PSTypeName='OpenPackage.ContentTypeMap'}).TypeMap ), # The compression option. [IO.Packaging.CompressionOption] [Alias('CompressionLevel')] $CompressionOption = 'Superfast', # If set, will force the redownload of various resources and remove existing files or directories [switch] $Force, # If set, will include hidden files and folders, except for files beneath `.git` [Alias('IncludeDotFiles')] [switch] $IncludeHidden, # If set, will include the `.git` directory contents if found. # By default, this content will be excluded. [Alias('IncludeGitFile','IncludeGitFiles','IncludeGitDirectory')] [switch] $IncludeGit, # If set, will include any content found in `/node_modules`. # By default, this content will be excluded. [Alias('IncludeNodeModules')] [switch] $IncludeNodeModule, # If set, will include any content found in `/_site`. # By default, this content will be excluded. [Alias('IncludeWebsite')] [switch] $IncludeSite, [string[]] $PythonPackageIndexDomain = @( 'pypi.org' 'www.pypi.org' ) ) $pipApp = $ExecutionContext.SessionState.InvokeCommand.GetCommand('pip', 'Application') if (-not $pipApp) { throw "pip not installed or in path"} # Collect all named parameters to this, # so we can pass most of them to the next step. $namedParameters = [Ordered]@{} foreach ($key in $MyInvocation.MyCommand.Parameters.Keys) { $var = $ExecutionContext.SessionState.PSVariable.Get($key) if (-not [string]::IsNullOrEmpty($var.value)) { $namedParameters[$key] = $var.value } } # Remove any node package specific parameters. $namedParameters.Remove('PythonPackage') $namedParameters.Remove('PythonPackageIndexDomain') # We want to if (-not $env:OpenPackagePath) {throw "No Open Package Path"} # Get our first OpenPackage package path $myAppData = @($env:OpenPackagePath -split $( if ($IsLinux -or $IsMacOS) { ':' } else { ';' } ))[0] # and put all python packages beneathh this location. $pythonPackageRoot = Join-Path $myAppData "python" # If we do not have this directory already, create it if (-not (Test-Path $pythonPackageRoot)) { $null = New-Item -ItemType Directory -Path $pythonPackageRoot -Force } # Push into this location Push-Location $pythonPackageRoot # Go over each package we want to get. foreach ($pythonPack in $PythonPackage) { # Packages can be in direct named form, or in a url $pythonPackUri = $pythonPack -as [uri] # If the url was absolute if ($pythonPackUri.IsAbsoluteUri) { # check it against possible domain names. if ($pythonPackUri.DnsSafeHost -notin $PythonPackageIndexDomain) { Write-Error "Can only use an absolute url from $PythonPackageIndexDomain" continue } # If the url was versioned if ($pythonPackUri.Segments[-1] -match '^\d+\.') { $pythonPack = $pythonPackUri.Segments[-2,-1] -replace '/' -join '==' } else { # Otherwise, split off the package segment of the url $pythonPack = $pythonPackUri.Segments[2] -replace '/' } } # `pip` will download a package as .whl # (with a number of messages on standard error) $pipOutput = @(& $pipApp download '-d' $pythonPackageRoot $pythonPack *>&1) # some of these may actually be errors, so create a collection. $pipErrors = @() # and make sure we track if the package has been downloaded # (for it will actually provide the name twice) $packageDownloaded = $false # Go over each output. :gotPackage foreach ($pipOut in $pipOutput) { # If any of the output is an error record if ($pipOut -is [Management.Automation.ErrorRecord]) { # add it to our list $pipErrors += $pipOut } # If the output is not .whl if ($pipOut -notmatch '\S+\.whl$') { continue # continue } # Get the file path from our match $whlFile = $matches.0 # If the file does not exist if (-not (Test-Path $whlFile)) { # output our errors $pipErrors } else { # Otherwise, get the whl file as an open package. $pipPackage = Get-OpenPackage -FilePath $whlFile @namedParameters # If the output was a package if ($pipPackage -is [IO.Packaging.Package]) { # mark that we've downloaded it, $packageDownloaded = $true $pipPackage # emit the package, break gotPackage # and take a break. } } } # If the packge was not downloaded, output errors. if (-not $packageDownloaded) { Write-Error $( $pipErrors -replace '^ERROR:\s' -join [Environment]::NewLine ) continue } } Pop-Location |