Browse Source

Add comprehensive virtual environment support

Features:
- Automated virtual environment setup with setup_venv.py
- Cross-platform activation scripts (Windows batch/PowerShell, Unix shell)
- Direct run scripts for easy execution without manual activation
- Development requirements with testing and linting tools
- Comprehensive documentation in README_VENV.md
- Proper .gitignore for Python projects

Setup Process:
- One-command setup: python setup_venv.py
- Handles dependency installation with fallbacks for MIDI libraries
- Creates platform-specific activation scripts automatically
- Verifies installation and provides troubleshooting guidance
- Updated main README with virtual environment instructions

Benefits:
- Dependency isolation from other Python projects
- Reproducible installations across different machines
- Easy cleanup and environment management
- Development tool integration for testing and code quality
- Graceful handling of problematic MIDI library installations

Usage:
Windows: run_in_venv.bat or activate.bat && python run.py
Linux/Mac: ./run_in_venv.sh or source activate.sh && python run.py

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
master
melancholytron 2 months ago
parent
commit
f11e5ebe17
  1. 91
      .gitignore
  2. 57
      README.md
  3. 187
      README_VENV.md
  4. 4
      activate.bat
  5. 3
      activate.ps1
  6. 7
      requirements-dev.txt
  7. 3
      run_in_venv.bat
  8. 329
      setup_venv.py

91
.gitignore

@ -0,0 +1,91 @@
# Virtual Environment
venv/
env/
.env
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyQt5
*.ui~
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
# Logs
*.log
# Configuration backups
config.json.bak
config.json.old
# Temporary files
*.tmp
*.temp
# Coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Black
.black
# Generated activation scripts (optional - user can choose to track these)
# activate.bat
# activate.ps1
# activate.sh
# run_in_venv.bat
# run_in_venv.sh

57
README.md

@ -37,24 +37,77 @@ A modular MIDI arpeggiator application with integrated lighting control and Nati
## Installation
### Requirements
- Python 3.7+
- Python 3.8+
- PyQt5
- pygame (for audio synthesis)
- python-rtmidi (for MIDI I/O)
- mido (for MIDI message handling)
- numpy (for audio processing)
### Setup
### Quick Setup (Recommended - Virtual Environment)
**Automatic setup with isolated environment:**
```bash
# Clone the project
git clone <repository-url>
cd arppegiator
# Run the virtual environment setup script
python setup_venv.py
# Activate the virtual environment and run
# Windows:
activate.bat && python run.py
# Or directly:
run_in_venv.bat
# Linux/Mac:
source activate.sh && python run.py
# Or directly:
./run_in_venv.sh
```
See [README_VENV.md](README_VENV.md) for detailed virtual environment documentation.
### Manual Setup (Global Environment)
1. Clone or download the project
2. Install dependencies:
```bash
# Standard installation
pip install -r requirements.txt
# Windows-specific (if above fails)
pip install -r requirements-windows.txt
```
3. Run the application:
```bash
python run.py
```
### Platform-Specific Installation
**Windows:**
```bash
# If you get compilation errors, use the Windows installer:
python install_windows.py
# Then run:
python run.py
```
**Linux/Mac:**
```bash
# Standard installation should work:
pip install -r requirements.txt
python run.py
```
### Troubleshooting Installation
If you encounter issues, see:
- [README_VENV.md](README_VENV.md) - Virtual environment setup and troubleshooting
- [INSTALL_WINDOWS.md](INSTALL_WINDOWS.md) - Windows-specific installation guide
## Module Structure
### Core Modules (`core/`)

187
README_VENV.md

@ -0,0 +1,187 @@
# Virtual Environment Setup
This project now supports virtual environment setup for better dependency management and isolation.
## Quick Setup
### Windows
```bash
# Run the setup script
python setup_venv.py
# Activate the virtual environment (choose one)
activate.bat # Command Prompt
.\activate.ps1 # PowerShell
# Run the application
python run.py
# Or run directly without manual activation
run_in_venv.bat
```
### Linux/Mac
```bash
# Run the setup script
python3 setup_venv.py
# Activate the virtual environment
source activate.sh
# Run the application
python run.py
# Or run directly without manual activation
./run_in_venv.sh
```
## What the Setup Script Does
1. **Creates a virtual environment** in the `venv` folder
2. **Installs all dependencies** from requirements files
3. **Creates activation scripts** for easy environment management
4. **Verifies installation** to ensure everything works
5. **Handles MIDI library issues** gracefully (falls back to simulator mode)
## File Structure After Setup
```
arppegiator/
├── venv/ # Virtual environment (created)
├── activate.bat # Windows activation (created)
├── activate.ps1 # PowerShell activation (created)
├── activate.sh # Unix activation (created)
├── run_in_venv.bat # Windows direct run (created)
├── run_in_venv.sh # Unix direct run (created)
├── setup_venv.py # Setup script (created)
├── requirements-dev.txt # Development dependencies (created)
├── requirements.txt # Main dependencies
├── requirements-windows.txt # Windows-specific dependencies
└── ... (rest of project files)
```
## Manual Virtual Environment Setup
If the setup script doesn't work, you can set up manually:
```bash
# Create virtual environment
python -m venv venv
# Activate it
# Windows:
venv\Scripts\activate.bat
# Linux/Mac:
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Run the application
python run.py
```
## Development Setup
For development with additional tools:
```bash
# After setting up the main environment, install dev dependencies
pip install -r requirements-dev.txt
```
This includes:
- `pytest` - Testing framework
- `pytest-qt` - Qt application testing
- `black` - Code formatting
- `flake8` - Code linting
- `mypy` - Type checking
- `coverage` - Code coverage analysis
## Troubleshooting
### Common Issues
**1. Python version too old**
- Requires Python 3.8 or newer
- Check with: `python --version`
**2. Virtual environment creation fails**
- Make sure `venv` module is available: `python -m venv --help`
- On Ubuntu/Debian: `sudo apt install python3-venv`
**3. Permission errors on Windows**
- Run Command Prompt/PowerShell as Administrator
- Or use: `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser`
**4. MIDI libraries fail to install**
- This is normal on some systems
- The application will work in simulator mode
- For hardware MIDI, you may need Visual Studio Build Tools
**5. PyQt5 installation fails**
- Try: `pip install --only-binary=PyQt5 PyQt5`
- Or install from conda: `conda install pyqt`
### Verifying Installation
Test that everything is working:
```bash
# With environment activated
python -c "
import PyQt5; print('✅ PyQt5 OK')
import numpy; print('✅ NumPy OK')
import pygame; print('✅ Pygame OK')
import mido; print('✅ Mido OK')
try:
import rtmidi; print('✅ RTMIDI OK - Hardware MIDI available')
except: print('⚠️ RTMIDI not available - Simulator mode only')
print('🎹 Ready to run!')
"
```
### Removing the Virtual Environment
To completely remove the virtual environment:
```bash
# Make sure you're not in the environment
deactivate
# Delete the environment folder
# Windows:
rmdir /s venv
# Linux/Mac:
rm -rf venv
# Also remove the activation scripts if desired
# Windows:
del activate.bat activate.ps1 run_in_venv.bat
# Linux/Mac:
rm activate.sh run_in_venv.sh
```
## Benefits of Virtual Environment
**Isolation**: Dependencies don't conflict with other Python projects
**Reproducibility**: Exact same versions across different machines
**Cleanliness**: Easy to remove everything without affecting system Python
**Testing**: Test with different dependency versions safely
**Distribution**: Share exact environment with others
## IDE Integration
### VS Code
1. Open the project folder
2. VS Code should auto-detect the virtual environment in `venv/`
3. Select the Python interpreter: `Ctrl+Shift+P` → "Python: Select Interpreter"
4. Choose the one in `venv/Scripts/python.exe` (Windows) or `venv/bin/python` (Unix)
### PyCharm
1. File → Settings → Project → Python Interpreter
2. Add → Existing Environment
3. Choose `venv/Scripts/python.exe` (Windows) or `venv/bin/python` (Unix)
### Other IDEs
Point your IDE's Python interpreter to the one inside the `venv` folder.

4
activate.bat

@ -0,0 +1,4 @@
@echo off
call "C:\git\arppegiator\venv\Scripts\activate.bat"
echo Virtual environment activated!
echo Run "python run.py" to start the arpeggiator

3
activate.ps1

@ -0,0 +1,3 @@
& "C:\git\arppegiator\venv\Scripts\Activate.ps1"
Write-Host "Virtual environment activated!" -ForegroundColor Green
Write-Host "Run 'python run.py' to start the arpeggiator" -ForegroundColor Cyan

7
requirements-dev.txt

@ -0,0 +1,7 @@
# 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

3
run_in_venv.bat

@ -0,0 +1,3 @@
@echo off
call "C:\git\arppegiator\venv\Scripts\activate.bat"
python run.py

329
setup_venv.py

@ -0,0 +1,329 @@
#!/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())
Loading…
Cancel
Save