You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

329 lines
11 KiB

#!/usr/bin/env python3
"""
Virtual Environment Setup Script for MIDI Arpeggiator
This script creates and configures a virtual environment for the project.
"""
import subprocess
import sys
import os
import platform
import shutil
def run_command(cmd, cwd=None, check=True):
"""Run a command and return the result"""
try:
print(f"Running: {' '.join(cmd)}")
result = subprocess.run(cmd, cwd=cwd, check=check, capture_output=True, text=True)
if result.stdout:
print(result.stdout)
return result
except subprocess.CalledProcessError as e:
print(f"Error running command: {e}")
if e.stderr:
print(f"Error output: {e.stderr}")
if check:
raise
return e
def check_python_version():
"""Check if Python version is compatible"""
version = sys.version_info
if version.major < 3 or (version.major == 3 and version.minor < 8):
print(f"ERROR: Python {version.major}.{version.minor} is not supported")
print("Please use Python 3.8 or newer")
return False
print(f"OK: Python {version.major}.{version.minor}.{version.micro} is compatible")
return True
def create_virtual_environment():
"""Create a virtual environment"""
project_dir = os.path.dirname(os.path.abspath(__file__))
venv_dir = os.path.join(project_dir, "venv")
if os.path.exists(venv_dir):
print(f"Virtual environment already exists at {venv_dir}")
response = input("Do you want to recreate it? (y/N): ")
if response.lower().startswith('y'):
print("Removing existing virtual environment...")
shutil.rmtree(venv_dir)
else:
print("Using existing virtual environment")
return venv_dir
print("Creating virtual environment...")
run_command([sys.executable, "-m", "venv", "venv"], cwd=project_dir)
print(f"OK: Virtual environment created at {venv_dir}")
return venv_dir
def get_venv_python(venv_dir):
"""Get the path to the Python executable in the virtual environment"""
if platform.system() == "Windows":
return os.path.join(venv_dir, "Scripts", "python.exe")
else:
return os.path.join(venv_dir, "bin", "python")
def get_venv_pip(venv_dir):
"""Get the path to pip in the virtual environment"""
if platform.system() == "Windows":
return os.path.join(venv_dir, "Scripts", "pip.exe")
else:
return os.path.join(venv_dir, "bin", "pip")
def install_dependencies(venv_dir):
"""Install dependencies in the virtual environment"""
project_dir = os.path.dirname(os.path.abspath(__file__))
pip_exe = get_venv_pip(venv_dir)
python_exe = get_venv_python(venv_dir)
# Upgrade pip first
print("Upgrading pip...")
run_command([python_exe, "-m", "pip", "install", "--upgrade", "pip"])
# Choose requirements file based on platform
if platform.system() == "Windows":
requirements_file = "requirements-windows.txt"
print("Using Windows-specific requirements...")
else:
requirements_file = "requirements.txt"
print("Using standard requirements...")
requirements_path = os.path.join(project_dir, requirements_file)
if not os.path.exists(requirements_path):
print(f"ERROR: Requirements file not found: {requirements_path}")
return False
# Install core packages first
core_packages = [
"PyQt5>=5.15.0",
"numpy>=1.21.0",
"pygame>=2.1.0",
"mido>=1.2.10"
]
print("Installing core packages...")
for package in core_packages:
try:
run_command([pip_exe, "install", package])
print(f"OK: Installed {package}")
except subprocess.CalledProcessError as e:
print(f"ERROR: Failed to install {package}")
return False
# Try to install RTMIDI (may fail on some systems)
rtmidi_packages = [
"python-rtmidi>=1.5.0",
"python-rtmidi",
"rtmidi-python>=1.1.0"
]
rtmidi_installed = False
for package in rtmidi_packages:
try:
print(f"Trying to install {package}...")
run_command([pip_exe, "install", package])
rtmidi_installed = True
print(f"OK: Successfully installed {package}")
break
except subprocess.CalledProcessError:
print(f"WARNING: Failed to install {package}, trying next option...")
if not rtmidi_installed:
print("\nWARNING: Could not install any RTMIDI package.")
print("The application will still work in simulator mode.")
print("OK: Dependencies installation completed!")
return True
def create_activation_scripts():
"""Create convenient activation scripts"""
project_dir = os.path.dirname(os.path.abspath(__file__))
venv_dir = os.path.join(project_dir, "venv")
if platform.system() == "Windows":
# Windows batch file
activate_script = os.path.join(project_dir, "activate.bat")
with open(activate_script, 'w') as f:
f.write(f'@echo off\n')
f.write(f'call "{venv_dir}\\Scripts\\activate.bat"\n')
f.write(f'echo Virtual environment activated!\n')
f.write(f'echo Run "python run.py" to start the arpeggiator\n')
# PowerShell script
activate_ps_script = os.path.join(project_dir, "activate.ps1")
with open(activate_ps_script, 'w') as f:
f.write(f'& "{venv_dir}\\Scripts\\Activate.ps1"\n')
f.write(f'Write-Host "Virtual environment activated!" -ForegroundColor Green\n')
f.write(f'Write-Host "Run \'python run.py\' to start the arpeggiator" -ForegroundColor Cyan\n')
run_script = os.path.join(project_dir, "run_in_venv.bat")
with open(run_script, 'w') as f:
f.write(f'@echo off\n')
f.write(f'call "{venv_dir}\\Scripts\\activate.bat"\n')
f.write(f'python run.py\n')
print("OK: Created Windows activation scripts:")
print(f" - {activate_script}")
print(f" - {activate_ps_script}")
print(f" - {run_script}")
else:
# Unix shell script
activate_script = os.path.join(project_dir, "activate.sh")
with open(activate_script, 'w') as f:
f.write('#!/bin/bash\n')
f.write(f'source "{venv_dir}/bin/activate"\n')
f.write('echo "Virtual environment activated!"\n')
f.write('echo "Run \'python run.py\' to start the arpeggiator"\n')
os.chmod(activate_script, 0o755)
run_script = os.path.join(project_dir, "run_in_venv.sh")
with open(run_script, 'w') as f:
f.write('#!/bin/bash\n')
f.write(f'source "{venv_dir}/bin/activate"\n')
f.write('python run.py\n')
os.chmod(run_script, 0o755)
print("OK: Created Unix activation scripts:")
print(f" - {activate_script}")
print(f" - {run_script}")
def create_dev_requirements():
"""Create development requirements file"""
project_dir = os.path.dirname(os.path.abspath(__file__))
dev_requirements_path = os.path.join(project_dir, "requirements-dev.txt")
dev_packages = [
"# Development dependencies",
"pytest>=7.0.0",
"pytest-qt>=4.0.0",
"black>=22.0.0",
"flake8>=4.0.0",
"mypy>=0.950",
"coverage>=6.0.0"
]
with open(dev_requirements_path, 'w') as f:
f.write('\n'.join(dev_packages))
print(f"OK: Created development requirements: {dev_requirements_path}")
def verify_installation(venv_dir):
"""Verify that the installation works"""
python_exe = get_venv_python(venv_dir)
print("\nVerifying installation...")
test_imports = [
("PyQt5", "PyQt5"),
("numpy", "NumPy"),
("pygame", "Pygame"),
("mido", "Mido")
]
all_good = True
for module, display_name in test_imports:
try:
result = run_command([python_exe, "-c", f"import {module}; print('OK')"], check=False)
if result.returncode == 0:
print(f"OK: {display_name}")
else:
print(f"ERROR: {display_name}")
all_good = False
except:
print(f"ERROR: {display_name}")
all_good = False
# Test RTMIDI (optional)
try:
result = run_command([python_exe, "-c", "import rtmidi; print('OK')"], check=False)
if result.returncode == 0:
print("OK: RTMIDI")
else:
print("WARNING: RTMIDI (will use simulator mode)")
except:
print("WARNING: RTMIDI (will use simulator mode)")
return all_good
def main():
"""Main setup function"""
# Handle Unicode issues on Windows console
try:
print("🎹 MIDI Arpeggiator - Virtual Environment Setup")
except UnicodeEncodeError:
print("MIDI Arpeggiator - Virtual Environment Setup")
print("=" * 50)
# Check Python version
if not check_python_version():
return 1
# Create virtual environment
try:
venv_dir = create_virtual_environment()
except Exception as e:
print(f"ERROR: Failed to create virtual environment: {e}")
return 1
# Install dependencies
try:
if not install_dependencies(venv_dir):
print("ERROR: Failed to install some dependencies")
return 1
except Exception as e:
print(f"ERROR: Failed to install dependencies: {e}")
return 1
# Create activation scripts
try:
create_activation_scripts()
create_dev_requirements()
except Exception as e:
print(f"ERROR: Failed to create scripts: {e}")
return 1
# Verify installation
if not verify_installation(venv_dir):
print("WARNING: Some packages failed to install properly")
print("The application may still work in simulator mode")
try:
print("\n🎉 Virtual environment setup completed successfully!")
except UnicodeEncodeError:
print("\nVirtual environment setup completed successfully!")
try:
print("\n📋 Next steps:")
except UnicodeEncodeError:
print("\nNext steps:")
if platform.system() == "Windows":
print(" 1. Activate the environment:")
print(" • Command Prompt: activate.bat")
print(" • PowerShell: .\\activate.ps1")
print(" 2. Run the application:")
print(" • In activated environment: python run.py")
print(" • Direct run: run_in_venv.bat")
else:
print(" 1. Activate the environment: source activate.sh")
print(" 2. Run the application: python run.py")
print(" Or directly: ./run_in_venv.sh")
try:
print("\n💡 Tips:")
except UnicodeEncodeError:
print("\nTips:")
print(" • The virtual environment is in the 'venv' folder")
print(" • Use 'deactivate' to exit the virtual environment")
print(" • Delete 'venv' folder to completely remove the environment")
return 0
if __name__ == "__main__":
exit(main())