mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-05-04 23:52:14 +00:00
Implemented the changes to pass the review, implemented consistent variable naming, adjusted unit tests
This commit is contained in:
232
setup.ps1
232
setup.ps1
@@ -1,8 +1,7 @@
|
||||
Clear-Host
|
||||
|
||||
# Set the log file path and initialize variables
|
||||
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||
$Global:LogFilePath = Join-Path $env:TEMP "script_log_$timestamp.txt"
|
||||
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||
$Global:LogFilePath = Join-Path $env:TEMP "script_log_$Timestamp.txt"
|
||||
|
||||
$RequirementFiles = @("requirements.txt", "requirements-dev.txt", "requirements-hyperopt.txt", "requirements-freqai.txt", "requirements-freqai-rl.txt", "requirements-plot.txt")
|
||||
$VenvName = ".venv"
|
||||
@@ -24,6 +23,7 @@ function Write-Log {
|
||||
'ERROR' { Write-Host $Message -ForegroundColor Red }
|
||||
'PROMPT' { Write-Host $Message -ForegroundColor Cyan }
|
||||
}
|
||||
|
||||
"${Level}: $Message" | Out-File $LogFilePath -Append
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ function Get-UserSelection {
|
||||
)
|
||||
|
||||
Write-Log "$Prompt`n" -Level 'PROMPT'
|
||||
for ($i = 0; $i -lt $Options.Length; $i++) {
|
||||
Write-Log "$([char](65 + $i)). $($Options[$i])" -Level 'PROMPT'
|
||||
for ($I = 0; $I -lt $Options.Length; $I++) {
|
||||
Write-Log "$([char](65 + $I)). $($Options[$I])" -Level 'PROMPT'
|
||||
}
|
||||
|
||||
if ($AllowMultipleSelections) {
|
||||
@@ -47,53 +47,53 @@ function Get-UserSelection {
|
||||
Write-Log "`nSelect an option by typing the corresponding letter." -Level 'PROMPT'
|
||||
}
|
||||
|
||||
$userInput = Read-Host
|
||||
if ([string]::IsNullOrEmpty($userInput)) {
|
||||
$userInput = $DefaultChoice
|
||||
[string]$UserInput = Read-Host
|
||||
if ([string]::IsNullOrEmpty($UserInput)) {
|
||||
$UserInput = $DefaultChoice
|
||||
}
|
||||
|
||||
if ($AllowMultipleSelections) {
|
||||
# Ensure $userInput is treated as a string and split it by commas
|
||||
$userInput = [string]$userInput
|
||||
$selections = $userInput.Split(',') | ForEach-Object {
|
||||
$Selections = $UserInput.Split(',') | ForEach-Object {
|
||||
$_.Trim().ToUpper()
|
||||
}
|
||||
|
||||
# Convert each selection from letter to index and validate
|
||||
$selectedIndices = @()
|
||||
foreach ($selection in $selections) {
|
||||
if ($selection -match '^[A-Z]$') {
|
||||
$index = [int][char]$selection - [int][char]'A'
|
||||
if ($index -ge 0 -and $index -lt $Options.Length) {
|
||||
$selectedIndices += $index
|
||||
$ErrorMessage = "Invalid input: $Selection. Please enter letters within the valid range of options."
|
||||
|
||||
# Convert each Selection from letter to Index and validate
|
||||
$SelectedIndices = @()
|
||||
foreach ($Selection in $Selections) {
|
||||
if ($Selection -match '^[A-Z]$') {
|
||||
$Index = [int][char]$Selection - [int][char]'A'
|
||||
if ($Index -ge 0 -and $Index -lt $Options.Length) {
|
||||
$SelectedIndices += $Index
|
||||
}
|
||||
else {
|
||||
Write-Log "Invalid input: $selection. Please enter letters within the valid range of options." -Level 'ERROR'
|
||||
Write-Log $ErrorMessage -Level 'ERROR'
|
||||
return -1
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Log "Invalid input: $selection. Please enter letters between A and Z." -Level 'ERROR'
|
||||
Write-Log $ErrorMessage -Level 'ERROR'
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
return $selectedIndices
|
||||
return $SelectedIndices
|
||||
}
|
||||
else {
|
||||
# Convert the selection from letter to index and validate
|
||||
if ($userInput -match '^[A-Z]$') {
|
||||
$selectedIndex = [int][char]$userInput - [int][char]'A'
|
||||
if ($selectedIndex -ge 0 -and $selectedIndex -lt $Options.Length) {
|
||||
return $selectedIndex
|
||||
# Convert the Selection from letter to Index and validate
|
||||
if ($UserInput -match '^[A-Z]$') {
|
||||
$SelectedIndex = [int][char]$UserInput - [int][char]'A'
|
||||
if ($SelectedIndex -ge 0 -and $SelectedIndex -lt $Options.Length) {
|
||||
return $SelectedIndex
|
||||
}
|
||||
else {
|
||||
Write-Log "Invalid input: $userInput. Please enter a letter within the valid range of options." -Level 'ERROR'
|
||||
Write-Log "Invalid input: $UserInput. Please enter a letter within the valid range of options." -Level 'ERROR'
|
||||
return -1
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Log "Invalid input: $userInput. Please enter a letter between A and Z." -Level 'ERROR'
|
||||
Write-Log "Invalid input: $UserInput. Please enter a letter between A and Z." -Level 'ERROR'
|
||||
return -1
|
||||
}
|
||||
}
|
||||
@@ -105,9 +105,8 @@ function Exit-Script {
|
||||
[bool]$WaitForKeypress = $true
|
||||
)
|
||||
|
||||
if ($Global:OldVirtualPath) {
|
||||
$env:PATH = $Global:OldVirtualPath
|
||||
}
|
||||
# Disable virtual environment
|
||||
deactivate
|
||||
|
||||
if ($ExitCode -ne 0) {
|
||||
Write-Log "Script failed. Would you like to open the log file? (Y/N)" -Level 'PROMPT'
|
||||
@@ -124,37 +123,18 @@ function Exit-Script {
|
||||
return $ExitCode
|
||||
}
|
||||
|
||||
# Function to install requirements
|
||||
function Install-Requirements {
|
||||
param ([string]$RequirementsPath)
|
||||
|
||||
if (-not $RequirementsPath) {
|
||||
Write-Log "No requirements path provided for installation." -Level 'ERROR'
|
||||
Exit-Script -ExitCode 1
|
||||
}
|
||||
|
||||
Write-Log "Installing requirements from $RequirementsPath..."
|
||||
$installCmd = if (Test-Path $RequirementsPath) { & $VenvPip install -r $RequirementsPath } else { & $VenvPip install $RequirementsPath }
|
||||
$output = & $installCmd[0] $installCmd[1..$installCmd.Length] 2>&1
|
||||
$output | Out-File $LogFilePath -Append
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Log "Conflict detected. Exiting now..." -Level 'ERROR'
|
||||
Exit-Script -ExitCode 1
|
||||
}
|
||||
}
|
||||
|
||||
function Test-PythonExecutable {
|
||||
param(
|
||||
[string]$PythonExecutable
|
||||
)
|
||||
|
||||
$pythonCmd = Get-Command $PythonExecutable -ErrorAction SilentlyContinue
|
||||
if ($pythonCmd) {
|
||||
$command = "$($pythonCmd.Source) --version 2>&1"
|
||||
$versionOutput = Invoke-Expression $command
|
||||
$PythonCmd = Get-Command $PythonExecutable -ErrorAction SilentlyContinue
|
||||
if ($PythonCmd) {
|
||||
$Command = "$($PythonCmd.Source) --version 2>&1"
|
||||
$VersionOutput = Invoke-Expression $Command
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$version = $versionOutput | Select-String -Pattern "Python (\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }
|
||||
Write-Log "Python version $version found using executable '$PythonExecutable'."
|
||||
$Version = $VersionOutput | Select-String -Pattern "Python (\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }
|
||||
Write-Log "Python version $Version found using executable '$PythonExecutable'."
|
||||
return $true
|
||||
}
|
||||
else {
|
||||
@@ -169,58 +149,35 @@ function Test-PythonExecutable {
|
||||
}
|
||||
|
||||
function Find-PythonExecutable {
|
||||
$PythonExecutables = @("python", "python3.12", "python3.11", "python3.10", "python3.9", "python3", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python312\python.exe", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python311\python.exe", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python310\python.exe", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python39\python.exe", "C:\Python311\python.exe", "C:\Python310\python.exe", "C:\Python39\python.exe")
|
||||
|
||||
$pythonExecutables = @("python", "python3", "python3.9", "python3.10", "python3.11", "C:\Python39\python.exe", "C:\Python310\python.exe", "C:\Python311\python.exe")
|
||||
|
||||
foreach ($executable in $pythonExecutables) {
|
||||
if (Test-PythonExecutable -PythonExecutable $executable) {
|
||||
return $executable
|
||||
foreach ($Executable in $PythonExecutables) {
|
||||
if (Test-PythonExecutable -PythonExecutable $Executable) {
|
||||
return $Executable
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
# Function to get the list of requirements from a file
|
||||
function Get-Requirements($file) {
|
||||
$requirements = @()
|
||||
$lines = Get-Content $file
|
||||
foreach ($line in $lines) {
|
||||
if ($line.StartsWith("-r ")) {
|
||||
$nestedFile = $line.Substring(3).Trim()
|
||||
$nestedFilePath = Join-Path (Split-Path $file -Parent) $nestedFile
|
||||
if (Test-Path $nestedFilePath) {
|
||||
$requirements += Get-Requirements $nestedFilePath
|
||||
}
|
||||
}
|
||||
elseif (-not $line.StartsWith("#")) {
|
||||
$requirements += $line
|
||||
}
|
||||
}
|
||||
return $requirements
|
||||
}
|
||||
|
||||
function Main {
|
||||
"Starting the operations..." | Out-File $LogFilePath -Append
|
||||
"Current directory: $(Get-Location)" | Out-File $LogFilePath -Append
|
||||
|
||||
# Exit on lower versions than Python 3.9 or when Python executable not found
|
||||
$pythonExecutable = Find-PythonExecutable
|
||||
if ($null -eq $pythonExecutable) {
|
||||
$PythonExecutable = Find-PythonExecutable
|
||||
if ($null -eq $PythonExecutable) {
|
||||
Write-Host "Error: No suitable Python executable found. Please ensure that Python 3.9 or higher is installed and available in the system PATH."
|
||||
Exit 1
|
||||
}
|
||||
|
||||
"Starting the < operations..." | Out-File $LogFilePath -Append
|
||||
|
||||
# Navigate to the project directory
|
||||
Set-Location -Path $PSScriptRoot
|
||||
"Current directory: $(Get-Location)" | Out-File $LogFilePath -Append
|
||||
|
||||
# Define the path to the Python executable in the virtual environment
|
||||
$VenvPython = "$VenvDir\Scripts\python.exe"
|
||||
$VenvPython = "$VenvDir\Scripts\Activate.ps1"
|
||||
|
||||
# Check if the virtual environment exists, if not, create it
|
||||
if (-Not (Test-Path $VenvPython)) {
|
||||
Write-Log "Virtual environment not found. Creating virtual environment..." -Level 'ERROR'
|
||||
& $pythonExecutable -m venv "$VenvName"
|
||||
& $PythonExecutable -m venv $VenvName
|
||||
if (-Not (Test-Path $VenvPython)) {
|
||||
Write-Log "Failed to create virtual environment." -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
@@ -228,106 +185,79 @@ function Main {
|
||||
Write-Log "Virtual environment created successfully."
|
||||
}
|
||||
|
||||
# Activate the virtual environment
|
||||
$Global:OldVirtualPath = $env:PATH
|
||||
$env:PATH = "$VenvDir\Scripts;$env:PATH"
|
||||
|
||||
# Pull latest updates
|
||||
Write-Log "Pulling latest updates..."
|
||||
& "C:\Program Files\Git\cmd\git.exe" pull | Out-File $LogFilePath -Append 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Log "Failed to pull updates from Git." -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
# Pull latest updates only if the repository state is not dirty
|
||||
Write-Log "Checking if the repository is clean..."
|
||||
$status = & "C:\Program Files\Git\cmd\git.exe" status --porcelain
|
||||
if ($status) {
|
||||
Write-Log "Repository is dirty. Skipping pull."
|
||||
}
|
||||
else {
|
||||
Write-Log "Pulling latest updates..."
|
||||
& "C:\Program Files\Git\cmd\git.exe" pull | Out-File $LogFilePath -Append 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Log "Failed to pull updates from Git." -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (-not (Test-Path "$VenvDir\Lib\site-packages\talib")) {
|
||||
# Install TA-Lib using the virtual environment's pip
|
||||
Write-Log "Installing TA-Lib using virtual environment's pip..."
|
||||
& $VenvPython -m pip install --find-links=build_helpers\ --prefer-binary TA-Lib | Out-File $LogFilePath -Append 2>&1
|
||||
python -m pip install --find-links=build_helpers\ --prefer-binary TA-Lib | Out-File $LogFilePath -Append 2>&1
|
||||
}
|
||||
|
||||
# Present options for requirement files
|
||||
$selectedIndices = Get-UserSelection -prompt "Select which requirement files to install:" -options $RequirementFiles -defaultChoice 'A'
|
||||
$SelectedIndices = Get-UserSelection -prompt "Select which requirement files to install:" -options $RequirementFiles -defaultChoice 'A'
|
||||
|
||||
# Cache the selected requirement files
|
||||
$selectedRequirementFiles = @()
|
||||
foreach ($index in $selectedIndices) {
|
||||
if ($index -lt 0 -or $index -ge $RequirementFiles.Length) {
|
||||
Write-Log "Invalid selection. Please try again using the allowed letters." -Level 'ERROR'
|
||||
continue
|
||||
}
|
||||
|
||||
$filePath = Join-Path $PSScriptRoot $RequirementFiles[$index]
|
||||
if (Test-Path $filePath) {
|
||||
$selectedRequirementFiles += $filePath
|
||||
$SelectedRequirementFiles = @()
|
||||
$PipInstallArguments = ""
|
||||
foreach ($Index in $SelectedIndices) {
|
||||
$FilePath = Join-Path $PSScriptRoot $RequirementFiles[$Index]
|
||||
if (Test-Path $FilePath) {
|
||||
$SelectedRequirementFiles += $FilePath
|
||||
$PipInstallArguments += " -r $FilePath"
|
||||
}
|
||||
else {
|
||||
Write-Log "Requirement file not found: $filePath" -Level 'ERROR'
|
||||
Write-Log "Requirement file not found: $FilePath" -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
}
|
||||
}
|
||||
|
||||
# Merge the contents of the selected requirement files
|
||||
if ($selectedRequirementFiles.Count -gt 0) {
|
||||
Write-Log "Merging selected requirement files..."
|
||||
$mergedDependencies = @()
|
||||
foreach ($file in $selectedRequirementFiles) {
|
||||
$mergedDependencies += Get-Requirements $file
|
||||
}
|
||||
# Avoid duplicate dependencies
|
||||
$mergedDependencies = $mergedDependencies | Select-Object -Unique
|
||||
|
||||
# Create a temporary directory
|
||||
$tempDir = Join-Path $env:TEMP "freqtrade_requirements"
|
||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||
|
||||
# Create a temporary file with the merged dependencies
|
||||
$tempFile = Join-Path $tempDir "requirements.txt"
|
||||
$mergedDependencies | Out-File $tempFile
|
||||
|
||||
# Install the merged dependencies
|
||||
Write-Log "Installing merged dependencies..."
|
||||
& $VenvPython -m pip install -r $tempFile
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Log "Failed to install merged dependencies. Exiting now..." -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
}
|
||||
|
||||
# Remove the temporary directory
|
||||
Remove-Item $tempDir -Recurse -Force
|
||||
if ($PipInstallArguments -ne "") {
|
||||
python -m pip install $PipInstallArguments
|
||||
}
|
||||
|
||||
# Install freqtrade from setup using the virtual environment's Python
|
||||
Write-Log "Installing freqtrade from setup..."
|
||||
$setupInstallCommand = "$VenvPython -m pip install -e ."
|
||||
Invoke-Expression $setupInstallCommand | Out-File $LogFilePath -Append 2>&1
|
||||
python -m pip install -e . | Out-File $LogFilePath -Append 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Log "Failed to install freqtrade." -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
}
|
||||
|
||||
$uiOptions = @("Yes", "No")
|
||||
$installUI = Get-UserSelection -prompt "Do you want to install the freqtrade UI?" -options $uiOptions -defaultChoice 'B' -allowMultipleSelections $false
|
||||
$UiOptions = @("Yes", "No")
|
||||
$InstallUi = Get-UserSelection -prompt "Do you want to install the freqtrade UI?" -options $UiOptions -defaultChoice 'B' -allowMultipleSelections $false
|
||||
|
||||
if ($installUI -eq 0) {
|
||||
if ($InstallUi -eq 0) {
|
||||
# User selected "Yes"
|
||||
# Install freqtrade UI using the virtual environment's install-ui command
|
||||
Write-Log "Installing freqtrade UI..."
|
||||
& $VenvPython 'freqtrade', 'install-ui' | Out-File $LogFilePath -Append 2>&1
|
||||
python 'freqtrade', 'install-ui' | Out-File $LogFilePath -Append 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Log "Failed to install freqtrade UI." -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
}
|
||||
}
|
||||
elseif ($installUI -eq 1) {
|
||||
elseif ($InstallUi -eq 1) {
|
||||
# User selected "No"
|
||||
# Skip installing freqtrade UI
|
||||
Write-Log "Skipping freqtrade UI installation."
|
||||
}
|
||||
else {
|
||||
# Invalid selection
|
||||
# Invalid Selection
|
||||
# Handle the error case
|
||||
Write-Log "Invalid selection for freqtrade UI installation." -Level 'ERROR'
|
||||
Write-Log "Invalid Selection for freqtrade UI installation." -Level 'ERROR'
|
||||
Exit-Script -exitCode 1
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user