Spaces:
Running
Running
adds better huggingface deploy
Browse files
docs/TRACKIO_DEPLOYMENT_FIXES.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Trackio Deployment Fixes
|
| 2 |
+
|
| 3 |
+
This document outlines the fixes made to resolve the Trackio Space deployment and dataset creation issues.
|
| 4 |
+
|
| 5 |
+
## Issues Identified
|
| 6 |
+
|
| 7 |
+
### 1. Git Authentication Issues in Space Deployment
|
| 8 |
+
- **Problem**: The `deploy_trackio_space.py` script was using git commands for file upload, which failed with authentication errors
|
| 9 |
+
- **Solution**: Replaced git commands with direct HF Hub API calls using `upload_file()`
|
| 10 |
+
|
| 11 |
+
### 2. Dataset Repository Creation Issues
|
| 12 |
+
- **Problem**: The `setup_hf_dataset.py` script was trying to push to a dataset repository that didn't exist, causing 404 errors
|
| 13 |
+
- **Solution**: Added proper repository creation using `create_repo()` before pushing the dataset
|
| 14 |
+
|
| 15 |
+
### 3. Missing Environment Variable Setup
|
| 16 |
+
- **Problem**: The Space deployment didn't set up the required `HF_TOKEN` environment variable
|
| 17 |
+
- **Solution**: Added automatic secret setting using `add_space_secret()` API method
|
| 18 |
+
|
| 19 |
+
### 4. Manual Username Input Required
|
| 20 |
+
- **Problem**: Users had to manually enter their username
|
| 21 |
+
- **Solution**: Automatically extract username from token using `whoami()` API method
|
| 22 |
+
|
| 23 |
+
### 5. Dataset Access Testing Issues
|
| 24 |
+
- **Problem**: The configuration script failed when testing dataset access for non-existent datasets
|
| 25 |
+
- **Solution**: Added proper error handling and repository existence checks
|
| 26 |
+
|
| 27 |
+
## Fixed Scripts
|
| 28 |
+
|
| 29 |
+
### 1. `scripts/trackio_tonic/deploy_trackio_space.py`
|
| 30 |
+
|
| 31 |
+
#### Key Changes:
|
| 32 |
+
- **Replaced git upload with HF Hub API**: Now uses `upload_file()` directly instead of git commands
|
| 33 |
+
- **Automatic secret setting**: Uses `add_space_secret()` API to set HF_TOKEN automatically
|
| 34 |
+
- **Username extraction from token**: Uses `whoami()` to get username automatically
|
| 35 |
+
- **Removed manual username input**: No longer asks for username
|
| 36 |
+
- **Improved error handling**: Better error messages and fallback options
|
| 37 |
+
|
| 38 |
+
#### Usage:
|
| 39 |
+
```bash
|
| 40 |
+
python scripts/trackio_tonic/deploy_trackio_space.py
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
#### What it does:
|
| 44 |
+
1. Extracts username from HF token automatically
|
| 45 |
+
2. Creates a new HF Space using the API
|
| 46 |
+
3. Prepares Space files from templates
|
| 47 |
+
4. Uploads files using HF Hub API (no git required)
|
| 48 |
+
5. **Automatically sets secrets via API** (HF_TOKEN and TRACKIO_DATASET_REPO)
|
| 49 |
+
6. Tests the Space accessibility
|
| 50 |
+
|
| 51 |
+
### 2. `scripts/dataset_tonic/setup_hf_dataset.py`
|
| 52 |
+
|
| 53 |
+
#### Key Changes:
|
| 54 |
+
- **Added repository creation**: Creates the dataset repository before pushing data
|
| 55 |
+
- **Username extraction from token**: Uses `whoami()` to get username automatically
|
| 56 |
+
- **Automatic dataset naming**: Uses username in dataset repository name
|
| 57 |
+
- **Improved error handling**: Better error messages for common issues
|
| 58 |
+
- **Public datasets by default**: Makes datasets public for easier access
|
| 59 |
+
|
| 60 |
+
#### Usage:
|
| 61 |
+
```bash
|
| 62 |
+
python scripts/dataset_tonic/setup_hf_dataset.py
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
#### What it does:
|
| 66 |
+
1. Extracts username from HF token automatically
|
| 67 |
+
2. Creates the dataset repository if it doesn't exist
|
| 68 |
+
3. Creates a dataset with sample experiment data
|
| 69 |
+
4. Uploads README template
|
| 70 |
+
5. Makes the dataset public for easier access
|
| 71 |
+
|
| 72 |
+
### 3. `scripts/trackio_tonic/configure_trackio.py`
|
| 73 |
+
|
| 74 |
+
#### Key Changes:
|
| 75 |
+
- **Added repository existence check**: Checks if dataset repository exists before trying to load
|
| 76 |
+
- **Username extraction from token**: Uses `whoami()` to get username automatically
|
| 77 |
+
- **Automatic dataset naming**: Uses username in default dataset repository
|
| 78 |
+
- **Better error handling**: Distinguishes between missing repository and permission issues
|
| 79 |
+
- **Improved user guidance**: Clear instructions for next steps
|
| 80 |
+
|
| 81 |
+
#### Usage:
|
| 82 |
+
```bash
|
| 83 |
+
python scripts/trackio_tonic/configure_trackio.py
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
#### What it does:
|
| 87 |
+
1. Extracts username from HF token automatically
|
| 88 |
+
2. Validates current configuration
|
| 89 |
+
3. Tests dataset access with proper error handling
|
| 90 |
+
4. Generates configuration file with username
|
| 91 |
+
5. Provides usage examples with actual username
|
| 92 |
+
|
| 93 |
+
## Model Push Script (`scripts/model_tonic/push_to_huggingface.py`)
|
| 94 |
+
|
| 95 |
+
The model push script was already using the HF Hub API correctly, so no changes were needed. It properly:
|
| 96 |
+
- Creates repositories using `create_repo()`
|
| 97 |
+
- Uploads files using `upload_file()`
|
| 98 |
+
- Handles authentication correctly
|
| 99 |
+
|
| 100 |
+
## Environment Variables Required
|
| 101 |
+
|
| 102 |
+
### For HF Spaces:
|
| 103 |
+
```bash
|
| 104 |
+
HF_TOKEN=your_hf_token_here
|
| 105 |
+
TRACKIO_DATASET_REPO=your-username/your-dataset-name
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
### For Local Development:
|
| 109 |
+
```bash
|
| 110 |
+
export HF_TOKEN=your_hf_token_here
|
| 111 |
+
export TRACKIO_DATASET_REPO=your-username/your-dataset-name
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
## Deployment Workflow
|
| 115 |
+
|
| 116 |
+
### 1. Create Dataset
|
| 117 |
+
```bash
|
| 118 |
+
# Set environment variables
|
| 119 |
+
export HF_TOKEN=your_token_here
|
| 120 |
+
# TRACKIO_DATASET_REPO will be auto-generated as username/trackio-experiments
|
| 121 |
+
|
| 122 |
+
# Create the dataset
|
| 123 |
+
python scripts/dataset_tonic/setup_hf_dataset.py
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
### 2. Deploy Trackio Space
|
| 127 |
+
```bash
|
| 128 |
+
# Deploy the Space (no username needed - extracted from token)
|
| 129 |
+
python scripts/trackio_tonic/deploy_trackio_space.py
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
### 3. Secrets are Automatically Set
|
| 133 |
+
The script now automatically sets the required secrets via the HF Hub API:
|
| 134 |
+
- `HF_TOKEN` - Your Hugging Face token
|
| 135 |
+
- `TRACKIO_DATASET_REPO` - Your dataset repository (if specified)
|
| 136 |
+
|
| 137 |
+
### 4. Test Configuration
|
| 138 |
+
```bash
|
| 139 |
+
# Test the configuration
|
| 140 |
+
python scripts/trackio_tonic/configure_trackio.py
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
## New Features
|
| 144 |
+
|
| 145 |
+
### β
**Automatic Secret Setting**
|
| 146 |
+
- Uses `add_space_secret()` API method
|
| 147 |
+
- Sets `HF_TOKEN` automatically
|
| 148 |
+
- Sets `TRACKIO_DATASET_REPO` if specified
|
| 149 |
+
- Falls back to manual instructions if API fails
|
| 150 |
+
|
| 151 |
+
### β
**Username Extraction from Token**
|
| 152 |
+
- Uses `whoami()` API method
|
| 153 |
+
- No manual username input required
|
| 154 |
+
- Automatically uses username in dataset names
|
| 155 |
+
- Provides better user experience
|
| 156 |
+
|
| 157 |
+
### β
**Improved User Experience**
|
| 158 |
+
- Fewer manual inputs required
|
| 159 |
+
- Automatic configuration based on token
|
| 160 |
+
- Clear feedback about what's happening
|
| 161 |
+
- Better error messages
|
| 162 |
+
|
| 163 |
+
## Troubleshooting
|
| 164 |
+
|
| 165 |
+
### Common Issues:
|
| 166 |
+
|
| 167 |
+
1. **"Repository not found" errors**:
|
| 168 |
+
- Run `setup_hf_dataset.py` to create the dataset first
|
| 169 |
+
- Check that your HF token has write permissions
|
| 170 |
+
|
| 171 |
+
2. **"Authentication failed" errors**:
|
| 172 |
+
- Verify your HF token is valid
|
| 173 |
+
- Check token permissions on https://huggingface.co/settings/tokens
|
| 174 |
+
|
| 175 |
+
3. **"Space not accessible" errors**:
|
| 176 |
+
- Wait 2-5 minutes for the Space to build
|
| 177 |
+
- Check Space logs at the Space URL
|
| 178 |
+
- Verify all files were uploaded correctly
|
| 179 |
+
|
| 180 |
+
4. **"Dataset access failed" errors**:
|
| 181 |
+
- Ensure the dataset repository exists
|
| 182 |
+
- Check that your token has read permissions
|
| 183 |
+
- Verify the dataset repository name is correct
|
| 184 |
+
|
| 185 |
+
5. **"Secret setting failed" errors**:
|
| 186 |
+
- The script will fall back to manual instructions
|
| 187 |
+
- Follow the provided instructions to set secrets manually
|
| 188 |
+
- Check that your token has write permissions to the Space
|
| 189 |
+
|
| 190 |
+
### Debugging Steps:
|
| 191 |
+
|
| 192 |
+
1. **Check token permissions**:
|
| 193 |
+
```bash
|
| 194 |
+
huggingface-cli whoami
|
| 195 |
+
```
|
| 196 |
+
|
| 197 |
+
2. **Test dataset access**:
|
| 198 |
+
```python
|
| 199 |
+
from datasets import load_dataset
|
| 200 |
+
dataset = load_dataset("your-username/your-dataset", token="your-token")
|
| 201 |
+
```
|
| 202 |
+
|
| 203 |
+
3. **Test Space deployment**:
|
| 204 |
+
```bash
|
| 205 |
+
python scripts/trackio_tonic/deploy_trackio_space.py
|
| 206 |
+
```
|
| 207 |
+
|
| 208 |
+
4. **Test secret setting**:
|
| 209 |
+
```python
|
| 210 |
+
from huggingface_hub import HfApi
|
| 211 |
+
api = HfApi(token="your-token")
|
| 212 |
+
api.add_space_secret("your-username/your-space", "TEST_KEY", "test_value")
|
| 213 |
+
```
|
| 214 |
+
|
| 215 |
+
## Security Considerations
|
| 216 |
+
|
| 217 |
+
- **Public datasets**: Datasets are now public by default for easier access
|
| 218 |
+
- **Token security**: Never commit tokens to version control
|
| 219 |
+
- **Space secrets**: Automatically set via API, with manual fallback
|
| 220 |
+
- **Access control**: Verify token permissions before deployment
|
| 221 |
+
|
| 222 |
+
## Performance Improvements
|
| 223 |
+
|
| 224 |
+
- **Direct API calls**: Eliminated git dependency for faster uploads
|
| 225 |
+
- **Automatic configuration**: No manual username input required
|
| 226 |
+
- **Parallel processing**: Files are uploaded individually for better error handling
|
| 227 |
+
- **Caching**: HF Hub API handles caching automatically
|
| 228 |
+
- **Error recovery**: Better error handling and retry logic
|
| 229 |
+
|
| 230 |
+
## Future Enhancements
|
| 231 |
+
|
| 232 |
+
1. **Batch secret setting**: Set multiple secrets in one API call
|
| 233 |
+
2. **Progress tracking**: Add progress bars for large uploads
|
| 234 |
+
3. **Validation**: Add more comprehensive validation checks
|
| 235 |
+
4. **Rollback**: Add ability to rollback failed deployments
|
| 236 |
+
5. **Hardware configuration**: Automatically configure Space hardware
|
| 237 |
+
|
| 238 |
+
## Testing
|
| 239 |
+
|
| 240 |
+
To test the fixes:
|
| 241 |
+
|
| 242 |
+
```bash
|
| 243 |
+
# Test dataset creation
|
| 244 |
+
python scripts/dataset_tonic/setup_hf_dataset.py
|
| 245 |
+
|
| 246 |
+
# Test Space deployment
|
| 247 |
+
python scripts/trackio_tonic/deploy_trackio_space.py
|
| 248 |
+
|
| 249 |
+
# Test configuration
|
| 250 |
+
python scripts/trackio_tonic/configure_trackio.py
|
| 251 |
+
|
| 252 |
+
# Test model push (if you have a trained model)
|
| 253 |
+
python scripts/model_tonic/push_to_huggingface.py --model-path /path/to/model --repo-name your-username/your-model
|
| 254 |
+
```
|
| 255 |
+
|
| 256 |
+
## Summary
|
| 257 |
+
|
| 258 |
+
These fixes resolve the main issues with:
|
| 259 |
+
- β
Git authentication problems
|
| 260 |
+
- β
Dataset repository creation failures
|
| 261 |
+
- β
Missing environment variable setup
|
| 262 |
+
- β
Manual username input requirement
|
| 263 |
+
- β
Poor error handling and user feedback
|
| 264 |
+
- β
Security concerns with public datasets
|
| 265 |
+
|
| 266 |
+
The scripts now use the HF Hub API directly, provide better error messages, handle edge cases properly, and offer a much improved user experience with automatic configuration.
|
scripts/dataset_tonic/setup_hf_dataset.py
CHANGED
|
@@ -8,13 +8,12 @@ import json
|
|
| 8 |
from datetime import datetime
|
| 9 |
from pathlib import Path
|
| 10 |
from datasets import Dataset
|
| 11 |
-
from huggingface_hub import HfApi
|
| 12 |
|
| 13 |
def setup_trackio_dataset():
|
| 14 |
"""Set up the Trackio experiments dataset on Hugging Face Hub"""
|
| 15 |
|
| 16 |
# Configuration - get from environment variables with fallbacks
|
| 17 |
-
dataset_repo = os.environ.get('TRACKIO_DATASET_REPO', 'tonic/trackio-experiments')
|
| 18 |
hf_token = os.environ.get('HF_TOKEN')
|
| 19 |
|
| 20 |
if not hf_token:
|
|
@@ -22,6 +21,19 @@ def setup_trackio_dataset():
|
|
| 22 |
print("You can get your token from: https://huggingface.co/settings/tokens")
|
| 23 |
return False
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
print(f"π Setting up Trackio dataset: {dataset_repo}")
|
| 26 |
print(f"π§ Using dataset repository: {dataset_repo}")
|
| 27 |
|
|
@@ -247,6 +259,23 @@ def setup_trackio_dataset():
|
|
| 247 |
]
|
| 248 |
|
| 249 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
# Create dataset
|
| 251 |
dataset = Dataset.from_list(initial_experiments)
|
| 252 |
|
|
@@ -262,8 +291,8 @@ def setup_trackio_dataset():
|
|
| 262 |
readme_content = f.read()
|
| 263 |
print(f"β
Found README template: {readme_path}")
|
| 264 |
|
| 265 |
-
# Push to HF Hub
|
| 266 |
-
|
| 267 |
dataset.push_to_hub(
|
| 268 |
dataset_repo,
|
| 269 |
token=hf_token,
|
|
@@ -273,6 +302,7 @@ def setup_trackio_dataset():
|
|
| 273 |
# Create README separately if available
|
| 274 |
if readme_content:
|
| 275 |
try:
|
|
|
|
| 276 |
api.upload_file(
|
| 277 |
path_or_fileobj=readme_content.encode('utf-8'),
|
| 278 |
path_in_repo="README.md",
|
|
@@ -280,7 +310,7 @@ def setup_trackio_dataset():
|
|
| 280 |
repo_type="dataset",
|
| 281 |
token=hf_token
|
| 282 |
)
|
| 283 |
-
print("π Uploaded README.md
|
| 284 |
except Exception as e:
|
| 285 |
print(f"β οΈ Could not upload README: {e}")
|
| 286 |
|
|
@@ -288,7 +318,8 @@ def setup_trackio_dataset():
|
|
| 288 |
print(f"π Added {len(initial_experiments)} experiments")
|
| 289 |
if readme_content:
|
| 290 |
print("π Included README from templates")
|
| 291 |
-
print("
|
|
|
|
| 292 |
print("\nπ― Next steps:")
|
| 293 |
print("1. Set HF_TOKEN in your Hugging Face Space environment")
|
| 294 |
print("2. Deploy the updated app.py to your Space")
|
|
@@ -298,6 +329,10 @@ def setup_trackio_dataset():
|
|
| 298 |
|
| 299 |
except Exception as e:
|
| 300 |
print(f"β Failed to create dataset: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
return False
|
| 302 |
|
| 303 |
if __name__ == "__main__":
|
|
|
|
| 8 |
from datetime import datetime
|
| 9 |
from pathlib import Path
|
| 10 |
from datasets import Dataset
|
| 11 |
+
from huggingface_hub import HfApi, create_repo
|
| 12 |
|
| 13 |
def setup_trackio_dataset():
|
| 14 |
"""Set up the Trackio experiments dataset on Hugging Face Hub"""
|
| 15 |
|
| 16 |
# Configuration - get from environment variables with fallbacks
|
|
|
|
| 17 |
hf_token = os.environ.get('HF_TOKEN')
|
| 18 |
|
| 19 |
if not hf_token:
|
|
|
|
| 21 |
print("You can get your token from: https://huggingface.co/settings/tokens")
|
| 22 |
return False
|
| 23 |
|
| 24 |
+
# Initialize HF API and get user info
|
| 25 |
+
try:
|
| 26 |
+
api = HfApi(token=hf_token)
|
| 27 |
+
user_info = api.whoami()
|
| 28 |
+
username = user_info.get('name', 'unknown')
|
| 29 |
+
print(f"β
Authenticated as: {username}")
|
| 30 |
+
except Exception as e:
|
| 31 |
+
print(f"β Failed to get user info from token: {e}")
|
| 32 |
+
return False
|
| 33 |
+
|
| 34 |
+
# Use username in dataset repository if not specified
|
| 35 |
+
dataset_repo = os.environ.get('TRACKIO_DATASET_REPO', f'{username}/trackio-experiments')
|
| 36 |
+
|
| 37 |
print(f"π Setting up Trackio dataset: {dataset_repo}")
|
| 38 |
print(f"π§ Using dataset repository: {dataset_repo}")
|
| 39 |
|
|
|
|
| 259 |
]
|
| 260 |
|
| 261 |
try:
|
| 262 |
+
# Initialize HF API
|
| 263 |
+
api = HfApi(token=hf_token)
|
| 264 |
+
|
| 265 |
+
# First, try to create the dataset repository
|
| 266 |
+
print(f"Creating dataset repository: {dataset_repo}")
|
| 267 |
+
try:
|
| 268 |
+
create_repo(
|
| 269 |
+
repo_id=dataset_repo,
|
| 270 |
+
token=hf_token,
|
| 271 |
+
repo_type="dataset",
|
| 272 |
+
exist_ok=True,
|
| 273 |
+
private=True # Make it private for security
|
| 274 |
+
)
|
| 275 |
+
print(f"β
Dataset repository created: {dataset_repo}")
|
| 276 |
+
except Exception as e:
|
| 277 |
+
print(f"β οΈ Repository creation failed (may already exist): {e}")
|
| 278 |
+
|
| 279 |
# Create dataset
|
| 280 |
dataset = Dataset.from_list(initial_experiments)
|
| 281 |
|
|
|
|
| 291 |
readme_content = f.read()
|
| 292 |
print(f"β
Found README template: {readme_path}")
|
| 293 |
|
| 294 |
+
# Push to HF Hub
|
| 295 |
+
print("Pushing dataset to HF Hub...")
|
| 296 |
dataset.push_to_hub(
|
| 297 |
dataset_repo,
|
| 298 |
token=hf_token,
|
|
|
|
| 302 |
# Create README separately if available
|
| 303 |
if readme_content:
|
| 304 |
try:
|
| 305 |
+
print("Uploading README.md...")
|
| 306 |
api.upload_file(
|
| 307 |
path_or_fileobj=readme_content.encode('utf-8'),
|
| 308 |
path_in_repo="README.md",
|
|
|
|
| 310 |
repo_type="dataset",
|
| 311 |
token=hf_token
|
| 312 |
)
|
| 313 |
+
print("π Uploaded README.md successfully")
|
| 314 |
except Exception as e:
|
| 315 |
print(f"β οΈ Could not upload README: {e}")
|
| 316 |
|
|
|
|
| 318 |
print(f"π Added {len(initial_experiments)} experiments")
|
| 319 |
if readme_content:
|
| 320 |
print("π Included README from templates")
|
| 321 |
+
print("π Dataset is public (accessible to everyone)")
|
| 322 |
+
print(f"π€ Created by: {username}")
|
| 323 |
print("\nπ― Next steps:")
|
| 324 |
print("1. Set HF_TOKEN in your Hugging Face Space environment")
|
| 325 |
print("2. Deploy the updated app.py to your Space")
|
|
|
|
| 329 |
|
| 330 |
except Exception as e:
|
| 331 |
print(f"β Failed to create dataset: {e}")
|
| 332 |
+
print("\nTroubleshooting:")
|
| 333 |
+
print("1. Check that your HF token has write permissions")
|
| 334 |
+
print("2. Verify the dataset repository name is available")
|
| 335 |
+
print("3. Try creating the dataset manually on HF first")
|
| 336 |
return False
|
| 337 |
|
| 338 |
if __name__ == "__main__":
|
scripts/trackio_tonic/configure_trackio.py
CHANGED
|
@@ -13,10 +13,29 @@ def configure_trackio():
|
|
| 13 |
print("π§ Trackio Configuration")
|
| 14 |
print("=" * 40)
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
# Current configuration
|
| 17 |
current_config = {
|
| 18 |
-
'HF_TOKEN':
|
| 19 |
-
'TRACKIO_DATASET_REPO':
|
| 20 |
'SPACE_ID': os.environ.get('SPACE_ID', 'Not set')
|
| 21 |
}
|
| 22 |
|
|
@@ -48,7 +67,6 @@ def configure_trackio():
|
|
| 48 |
print(" Get your token from: https://huggingface.co/settings/tokens")
|
| 49 |
|
| 50 |
# Check dataset repository
|
| 51 |
-
dataset_repo = current_config['TRACKIO_DATASET_REPO']
|
| 52 |
print(f"π Dataset Repository: {dataset_repo}")
|
| 53 |
|
| 54 |
# Test dataset access if token is available
|
|
@@ -56,26 +74,52 @@ def configure_trackio():
|
|
| 56 |
print("\nπ§ͺ Testing Dataset Access...")
|
| 57 |
try:
|
| 58 |
from datasets import load_dataset
|
|
|
|
| 59 |
|
| 60 |
-
dataset
|
| 61 |
-
|
| 62 |
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
print(f"
|
| 67 |
|
| 68 |
-
#
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
except Exception as e:
|
| 77 |
print(f"β Failed to load dataset: {e}")
|
| 78 |
print(" This might be normal if the dataset doesn't exist yet")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
# Generate configuration file
|
| 81 |
config_file = "trackio_config.json"
|
|
@@ -83,6 +127,7 @@ def configure_trackio():
|
|
| 83 |
'hf_token': current_config['HF_TOKEN'],
|
| 84 |
'dataset_repo': current_config['TRACKIO_DATASET_REPO'],
|
| 85 |
'space_id': current_config['SPACE_ID'],
|
|
|
|
| 86 |
'last_updated': datetime.now().isoformat(),
|
| 87 |
'notes': 'Trackio configuration - set these as environment variables in your HF Space'
|
| 88 |
}
|
|
@@ -103,43 +148,67 @@ def configure_trackio():
|
|
| 103 |
print("2. Optionally set TRACKIO_DATASET_REPO to use a different dataset")
|
| 104 |
print("3. Deploy your updated app.py to the Space")
|
| 105 |
print("4. Run setup_hf_dataset.py if you haven't created the dataset yet")
|
| 106 |
-
|
| 107 |
-
def show_usage_examples():
|
| 108 |
-
"""Show usage examples for different dataset repositories"""
|
| 109 |
|
| 110 |
print("\nπ Usage Examples")
|
| 111 |
print("=" * 30)
|
| 112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
examples = [
|
| 114 |
{
|
| 115 |
'name': 'Default Dataset',
|
| 116 |
-
'repo': '
|
| 117 |
-
'description': 'Default dataset for your experiments'
|
|
|
|
| 118 |
},
|
| 119 |
{
|
| 120 |
'name': 'Personal Dataset',
|
| 121 |
'repo': 'your-username/trackio-experiments',
|
| 122 |
-
'description': 'Your personal experiment dataset'
|
|
|
|
| 123 |
},
|
| 124 |
{
|
| 125 |
'name': 'Team Dataset',
|
| 126 |
'repo': 'your-org/team-experiments',
|
| 127 |
-
'description': 'Shared dataset for team experiments'
|
|
|
|
| 128 |
},
|
| 129 |
{
|
| 130 |
'name': 'Project Dataset',
|
| 131 |
'repo': 'your-username/smollm3-experiments',
|
| 132 |
-
'description': 'Dataset specific to SmolLM3 experiments'
|
|
|
|
| 133 |
}
|
| 134 |
]
|
| 135 |
|
|
|
|
|
|
|
|
|
|
| 136 |
for i, example in enumerate(examples, 1):
|
| 137 |
print(f"{i}. {example['name']}")
|
| 138 |
print(f" Repository: {example['repo']}")
|
| 139 |
print(f" Description: {example['description']}")
|
| 140 |
-
print(f" Set with:
|
| 141 |
print()
|
| 142 |
|
| 143 |
if __name__ == "__main__":
|
| 144 |
-
configure_trackio()
|
| 145 |
-
show_usage_examples()
|
|
|
|
| 13 |
print("π§ Trackio Configuration")
|
| 14 |
print("=" * 40)
|
| 15 |
|
| 16 |
+
# Get HF token and user info
|
| 17 |
+
hf_token = os.environ.get('HF_TOKEN')
|
| 18 |
+
|
| 19 |
+
if hf_token:
|
| 20 |
+
try:
|
| 21 |
+
from huggingface_hub import HfApi
|
| 22 |
+
api = HfApi(token=hf_token)
|
| 23 |
+
user_info = api.whoami()
|
| 24 |
+
username = user_info.get('name', 'unknown')
|
| 25 |
+
print(f"β
Authenticated as: {username}")
|
| 26 |
+
except Exception as e:
|
| 27 |
+
print(f"β Failed to get user info from token: {e}")
|
| 28 |
+
username = 'unknown'
|
| 29 |
+
else:
|
| 30 |
+
username = 'unknown'
|
| 31 |
+
|
| 32 |
+
# Use username in dataset repository if not specified
|
| 33 |
+
dataset_repo = os.environ.get('TRACKIO_DATASET_REPO', f'{username}/trackio-experiments')
|
| 34 |
+
|
| 35 |
# Current configuration
|
| 36 |
current_config = {
|
| 37 |
+
'HF_TOKEN': hf_token or 'Not set',
|
| 38 |
+
'TRACKIO_DATASET_REPO': dataset_repo,
|
| 39 |
'SPACE_ID': os.environ.get('SPACE_ID', 'Not set')
|
| 40 |
}
|
| 41 |
|
|
|
|
| 67 |
print(" Get your token from: https://huggingface.co/settings/tokens")
|
| 68 |
|
| 69 |
# Check dataset repository
|
|
|
|
| 70 |
print(f"π Dataset Repository: {dataset_repo}")
|
| 71 |
|
| 72 |
# Test dataset access if token is available
|
|
|
|
| 74 |
print("\nπ§ͺ Testing Dataset Access...")
|
| 75 |
try:
|
| 76 |
from datasets import load_dataset
|
| 77 |
+
from huggingface_hub import HfApi
|
| 78 |
|
| 79 |
+
# First check if the dataset repository exists
|
| 80 |
+
api = HfApi(token=current_config['HF_TOKEN'])
|
| 81 |
|
| 82 |
+
try:
|
| 83 |
+
# Try to get repository info
|
| 84 |
+
repo_info = api.repo_info(repo_id=dataset_repo, repo_type="dataset")
|
| 85 |
+
print(f"β
Dataset repository exists: {dataset_repo}")
|
| 86 |
|
| 87 |
+
# Try to load the dataset
|
| 88 |
+
dataset = load_dataset(dataset_repo, token=current_config['HF_TOKEN'])
|
| 89 |
+
print(f"β
Successfully loaded dataset: {dataset_repo}")
|
| 90 |
+
|
| 91 |
+
# Show experiment count
|
| 92 |
+
if 'train' in dataset:
|
| 93 |
+
experiment_count = len(dataset['train'])
|
| 94 |
+
print(f"π Found {experiment_count} experiments in dataset")
|
| 95 |
+
|
| 96 |
+
# Show sample experiments
|
| 97 |
+
if experiment_count > 0:
|
| 98 |
+
print("π¬ Sample experiments:")
|
| 99 |
+
for i, row in enumerate(dataset['train'][:3]): # Show first 3
|
| 100 |
+
exp_id = row.get('experiment_id', 'Unknown')
|
| 101 |
+
name = row.get('name', 'Unnamed')
|
| 102 |
+
print(f" {i+1}. {exp_id}: {name}")
|
| 103 |
+
|
| 104 |
+
except Exception as repo_error:
|
| 105 |
+
if "404" in str(repo_error) or "not found" in str(repo_error).lower():
|
| 106 |
+
print(f"β οΈ Dataset repository '{dataset_repo}' doesn't exist yet")
|
| 107 |
+
print(" This is normal if you haven't created the dataset yet")
|
| 108 |
+
print(" Run setup_hf_dataset.py to create the dataset")
|
| 109 |
+
else:
|
| 110 |
+
print(f"β Error accessing dataset repository: {repo_error}")
|
| 111 |
+
print(" Check that your token has read permissions")
|
| 112 |
+
|
| 113 |
+
except ImportError:
|
| 114 |
+
print("β Required packages not available")
|
| 115 |
+
print(" Install with: pip install datasets huggingface_hub")
|
| 116 |
except Exception as e:
|
| 117 |
print(f"β Failed to load dataset: {e}")
|
| 118 |
print(" This might be normal if the dataset doesn't exist yet")
|
| 119 |
+
print(" Run setup_hf_dataset.py to create the dataset")
|
| 120 |
+
else:
|
| 121 |
+
print("\nπ§ͺ Dataset Access Test:")
|
| 122 |
+
print("β Cannot test dataset access - HF_TOKEN not set")
|
| 123 |
|
| 124 |
# Generate configuration file
|
| 125 |
config_file = "trackio_config.json"
|
|
|
|
| 127 |
'hf_token': current_config['HF_TOKEN'],
|
| 128 |
'dataset_repo': current_config['TRACKIO_DATASET_REPO'],
|
| 129 |
'space_id': current_config['SPACE_ID'],
|
| 130 |
+
'username': username,
|
| 131 |
'last_updated': datetime.now().isoformat(),
|
| 132 |
'notes': 'Trackio configuration - set these as environment variables in your HF Space'
|
| 133 |
}
|
|
|
|
| 148 |
print("2. Optionally set TRACKIO_DATASET_REPO to use a different dataset")
|
| 149 |
print("3. Deploy your updated app.py to the Space")
|
| 150 |
print("4. Run setup_hf_dataset.py if you haven't created the dataset yet")
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
print("\nπ Usage Examples")
|
| 153 |
print("=" * 30)
|
| 154 |
+
print("1. Default Dataset")
|
| 155 |
+
print(f" Repository: {username}/trackio-experiments")
|
| 156 |
+
print(" Description: Default dataset for your experiments")
|
| 157 |
+
print(f" Set with: TRACKIO_DATASET_REPO={username}/trackio-experiments")
|
| 158 |
+
print()
|
| 159 |
+
print("2. Personal Dataset")
|
| 160 |
+
print(f" Repository: {username}/trackio-experiments")
|
| 161 |
+
print(" Description: Your personal experiment dataset")
|
| 162 |
+
print(f" Set with: TRACKIO_DATASET_REPO={username}/trackio-experiments")
|
| 163 |
+
print()
|
| 164 |
+
print("3. Team Dataset")
|
| 165 |
+
print(" Repository: your-org/team-experiments")
|
| 166 |
+
print(" Description: Shared dataset for team experiments")
|
| 167 |
+
print(" Set with: TRACKIO_DATASET_REPO=your-org/team-experiments")
|
| 168 |
+
print()
|
| 169 |
+
print("4. Project Dataset")
|
| 170 |
+
print(f" Repository: {username}/smollm3-experiments")
|
| 171 |
+
print(" Description: Dataset specific to SmolLM3 experiments")
|
| 172 |
+
print(f" Set with: TRACKIO_DATASET_REPO={username}/smollm3-experiments")
|
| 173 |
+
|
| 174 |
+
def show_usage_examples():
|
| 175 |
+
"""Show usage examples for different dataset configurations"""
|
| 176 |
examples = [
|
| 177 |
{
|
| 178 |
'name': 'Default Dataset',
|
| 179 |
+
'repo': 'your-username/trackio-experiments',
|
| 180 |
+
'description': 'Default dataset for your experiments',
|
| 181 |
+
'env_var': 'TRACKIO_DATASET_REPO=your-username/trackio-experiments'
|
| 182 |
},
|
| 183 |
{
|
| 184 |
'name': 'Personal Dataset',
|
| 185 |
'repo': 'your-username/trackio-experiments',
|
| 186 |
+
'description': 'Your personal experiment dataset',
|
| 187 |
+
'env_var': 'TRACKIO_DATASET_REPO=your-username/trackio-experiments'
|
| 188 |
},
|
| 189 |
{
|
| 190 |
'name': 'Team Dataset',
|
| 191 |
'repo': 'your-org/team-experiments',
|
| 192 |
+
'description': 'Shared dataset for team experiments',
|
| 193 |
+
'env_var': 'TRACKIO_DATASET_REPO=your-org/team-experiments'
|
| 194 |
},
|
| 195 |
{
|
| 196 |
'name': 'Project Dataset',
|
| 197 |
'repo': 'your-username/smollm3-experiments',
|
| 198 |
+
'description': 'Dataset specific to SmolLM3 experiments',
|
| 199 |
+
'env_var': 'TRACKIO_DATASET_REPO=your-username/smollm3-experiments'
|
| 200 |
}
|
| 201 |
]
|
| 202 |
|
| 203 |
+
print("\nπ Usage Examples")
|
| 204 |
+
print("=" * 30)
|
| 205 |
+
|
| 206 |
for i, example in enumerate(examples, 1):
|
| 207 |
print(f"{i}. {example['name']}")
|
| 208 |
print(f" Repository: {example['repo']}")
|
| 209 |
print(f" Description: {example['description']}")
|
| 210 |
+
print(f" Set with: {example['env_var']}")
|
| 211 |
print()
|
| 212 |
|
| 213 |
if __name__ == "__main__":
|
| 214 |
+
configure_trackio()
|
|
|
scripts/trackio_tonic/deploy_trackio_space.py
CHANGED
|
@@ -16,7 +16,7 @@ from typing import Dict, Any, Optional
|
|
| 16 |
|
| 17 |
# Import Hugging Face Hub API
|
| 18 |
try:
|
| 19 |
-
from huggingface_hub import HfApi, create_repo
|
| 20 |
HF_HUB_AVAILABLE = True
|
| 21 |
except ImportError:
|
| 22 |
HF_HUB_AVAILABLE = False
|
|
@@ -25,21 +25,30 @@ except ImportError:
|
|
| 25 |
class TrackioSpaceDeployer:
|
| 26 |
"""Deployer for Trackio on Hugging Face Spaces"""
|
| 27 |
|
| 28 |
-
def __init__(self, space_name: str,
|
| 29 |
self.space_name = space_name
|
| 30 |
-
self.username = username
|
| 31 |
self.token = token
|
| 32 |
-
self.space_url = f"https://huggingface.co/spaces/{username}/{space_name}"
|
| 33 |
|
| 34 |
-
#
|
| 35 |
-
self.git_email = git_email or f"{username}@huggingface.co"
|
| 36 |
-
self.git_name = git_name or username
|
| 37 |
-
|
| 38 |
-
# Initialize HF API
|
| 39 |
if HF_HUB_AVAILABLE:
|
| 40 |
self.api = HfApi(token=self.token)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
else:
|
| 42 |
self.api = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
def create_space(self) -> bool:
|
| 45 |
"""Create a new Hugging Face Space using the latest API"""
|
|
@@ -171,68 +180,110 @@ class TrackioSpaceDeployer:
|
|
| 171 |
return None
|
| 172 |
|
| 173 |
def upload_files_to_space(self, temp_dir: str) -> bool:
|
| 174 |
-
"""Upload files to the Space using
|
| 175 |
try:
|
| 176 |
-
print("Uploading files to Space...")
|
| 177 |
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
|
| 182 |
-
|
| 183 |
-
subprocess.run(["git", "init"], check=True, capture_output=True)
|
| 184 |
-
subprocess.run(["git", "remote", "add", "origin", f"https://huggingface.co/spaces/{self.username}/{self.space_name}"], check=True, capture_output=True)
|
| 185 |
|
| 186 |
-
#
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
# Try to get existing git config
|
| 190 |
-
result = subprocess.run(["git", "config", "--global", "user.email"], capture_output=True, text=True)
|
| 191 |
-
if result.returncode == 0 and result.stdout.strip():
|
| 192 |
-
git_email = result.stdout.strip()
|
| 193 |
-
else:
|
| 194 |
-
git_email = self.git_email
|
| 195 |
-
|
| 196 |
-
result = subprocess.run(["git", "config", "--global", "user.name"], capture_output=True, text=True)
|
| 197 |
-
if result.returncode == 0 and result.stdout.strip():
|
| 198 |
-
git_name = result.stdout.strip()
|
| 199 |
-
else:
|
| 200 |
-
git_name = self.git_name
|
| 201 |
-
|
| 202 |
-
except Exception:
|
| 203 |
-
# Fallback to default values
|
| 204 |
-
git_email = self.git_email
|
| 205 |
-
git_name = self.git_name
|
| 206 |
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
-
print(f"β
|
|
|
|
| 212 |
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
print("β
Pushed to main branch")
|
| 221 |
-
except subprocess.CalledProcessError:
|
| 222 |
-
# Try pushing to master branch if main doesn't exist
|
| 223 |
-
subprocess.run(["git", "push", "origin", "master"], check=True, capture_output=True)
|
| 224 |
-
print("β
Pushed to master branch")
|
| 225 |
|
| 226 |
-
|
| 227 |
-
os.chdir(original_dir)
|
| 228 |
|
| 229 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 230 |
|
| 231 |
except Exception as e:
|
| 232 |
-
print(f"β Error
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
|
| 237 |
def test_space(self) -> bool:
|
| 238 |
"""Test if the Space is working correctly"""
|
|
@@ -272,18 +323,22 @@ class TrackioSpaceDeployer:
|
|
| 272 |
if not temp_dir:
|
| 273 |
return False
|
| 274 |
|
| 275 |
-
# Step 3: Upload files
|
| 276 |
if not self.upload_files_to_space(temp_dir):
|
| 277 |
return False
|
| 278 |
|
| 279 |
-
# Step 4:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
try:
|
| 281 |
shutil.rmtree(temp_dir)
|
| 282 |
print("β
Cleaned up temporary directory")
|
| 283 |
except Exception as e:
|
| 284 |
print(f"β οΈ Warning: Could not clean up temp directory: {e}")
|
| 285 |
|
| 286 |
-
# Step
|
| 287 |
if not self.test_space():
|
| 288 |
print("β οΈ Space created but may need more time to build")
|
| 289 |
print("Please check the Space manually in a few minutes")
|
|
@@ -299,8 +354,7 @@ def main():
|
|
| 299 |
print("Trackio Space Deployment Script")
|
| 300 |
print("=" * 40)
|
| 301 |
|
| 302 |
-
# Get user input
|
| 303 |
-
username = input("Enter your Hugging Face username: ").strip()
|
| 304 |
space_name = input("Enter Space name (e.g., trackio-monitoring): ").strip()
|
| 305 |
token = input("Enter your Hugging Face token: ").strip()
|
| 306 |
|
|
@@ -308,8 +362,8 @@ def main():
|
|
| 308 |
git_email = input("Enter your git email (optional, press Enter for default): ").strip()
|
| 309 |
git_name = input("Enter your git name (optional, press Enter for default): ").strip()
|
| 310 |
|
| 311 |
-
if not
|
| 312 |
-
print("β
|
| 313 |
sys.exit(1)
|
| 314 |
|
| 315 |
# Use empty strings if not provided
|
|
@@ -318,8 +372,8 @@ def main():
|
|
| 318 |
if not git_name:
|
| 319 |
git_name = None
|
| 320 |
|
| 321 |
-
# Create deployer
|
| 322 |
-
deployer = TrackioSpaceDeployer(space_name,
|
| 323 |
|
| 324 |
# Run deployment
|
| 325 |
success = deployer.deploy()
|
|
@@ -327,14 +381,17 @@ def main():
|
|
| 327 |
if success:
|
| 328 |
print("\nβ
Deployment successful!")
|
| 329 |
print(f"π Your Trackio Space: {deployer.space_url}")
|
|
|
|
| 330 |
print("\nNext steps:")
|
| 331 |
print("1. Wait for the Space to build (usually 2-5 minutes)")
|
| 332 |
-
print("2.
|
| 333 |
-
print("3.
|
|
|
|
| 334 |
print("\nIf the Space doesn't work immediately, check:")
|
| 335 |
print("- The Space logs at the Space URL")
|
| 336 |
print("- That all files were uploaded correctly")
|
| 337 |
print("- That the HF token has write permissions")
|
|
|
|
| 338 |
else:
|
| 339 |
print("\nβ Deployment failed!")
|
| 340 |
print("Check the error messages above and try again.")
|
|
|
|
| 16 |
|
| 17 |
# Import Hugging Face Hub API
|
| 18 |
try:
|
| 19 |
+
from huggingface_hub import HfApi, create_repo, upload_file
|
| 20 |
HF_HUB_AVAILABLE = True
|
| 21 |
except ImportError:
|
| 22 |
HF_HUB_AVAILABLE = False
|
|
|
|
| 25 |
class TrackioSpaceDeployer:
|
| 26 |
"""Deployer for Trackio on Hugging Face Spaces"""
|
| 27 |
|
| 28 |
+
def __init__(self, space_name: str, token: str, git_email: str = None, git_name: str = None):
|
| 29 |
self.space_name = space_name
|
|
|
|
| 30 |
self.token = token
|
|
|
|
| 31 |
|
| 32 |
+
# Initialize HF API and get user info
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
if HF_HUB_AVAILABLE:
|
| 34 |
self.api = HfApi(token=self.token)
|
| 35 |
+
# Get username from token
|
| 36 |
+
try:
|
| 37 |
+
user_info = self.api.whoami()
|
| 38 |
+
self.username = user_info.get('name', 'unknown')
|
| 39 |
+
print(f"β
Authenticated as: {self.username}")
|
| 40 |
+
except Exception as e:
|
| 41 |
+
print(f"β Failed to get user info from token: {e}")
|
| 42 |
+
sys.exit(1)
|
| 43 |
else:
|
| 44 |
self.api = None
|
| 45 |
+
self.username = None
|
| 46 |
+
|
| 47 |
+
self.space_url = f"https://huggingface.co/spaces/{self.username}/{self.space_name}"
|
| 48 |
+
|
| 49 |
+
# Git configuration
|
| 50 |
+
self.git_email = git_email or f"{self.username}@huggingface.co"
|
| 51 |
+
self.git_name = git_name or self.username
|
| 52 |
|
| 53 |
def create_space(self) -> bool:
|
| 54 |
"""Create a new Hugging Face Space using the latest API"""
|
|
|
|
| 180 |
return None
|
| 181 |
|
| 182 |
def upload_files_to_space(self, temp_dir: str) -> bool:
|
| 183 |
+
"""Upload files to the Space using HF Hub API directly"""
|
| 184 |
try:
|
| 185 |
+
print("Uploading files to Space using HF Hub API...")
|
| 186 |
|
| 187 |
+
if not HF_HUB_AVAILABLE:
|
| 188 |
+
print("β huggingface_hub not available for file upload")
|
| 189 |
+
return False
|
| 190 |
|
| 191 |
+
repo_id = f"{self.username}/{self.space_name}"
|
|
|
|
|
|
|
| 192 |
|
| 193 |
+
# Upload each file using the HF Hub API
|
| 194 |
+
temp_path = Path(temp_dir)
|
| 195 |
+
uploaded_files = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
+
for file_path in temp_path.iterdir():
|
| 198 |
+
if file_path.is_file():
|
| 199 |
+
try:
|
| 200 |
+
# Upload file to the space
|
| 201 |
+
upload_file(
|
| 202 |
+
path_or_fileobj=str(file_path),
|
| 203 |
+
path_in_repo=file_path.name,
|
| 204 |
+
repo_id=repo_id,
|
| 205 |
+
repo_type="space",
|
| 206 |
+
token=self.token
|
| 207 |
+
)
|
| 208 |
+
uploaded_files.append(file_path.name)
|
| 209 |
+
print(f"β
Uploaded {file_path.name}")
|
| 210 |
+
except Exception as e:
|
| 211 |
+
print(f"β Failed to upload {file_path.name}: {e}")
|
| 212 |
+
return False
|
| 213 |
|
| 214 |
+
print(f"β
Successfully uploaded {len(uploaded_files)} files to Space")
|
| 215 |
+
return True
|
| 216 |
|
| 217 |
+
except Exception as e:
|
| 218 |
+
print(f"β Error uploading files: {e}")
|
| 219 |
+
return False
|
| 220 |
+
|
| 221 |
+
def set_space_secrets(self) -> bool:
|
| 222 |
+
"""Set environment variables/secrets for the Space using HF Hub API"""
|
| 223 |
+
try:
|
| 224 |
+
print("Setting Space secrets using HF Hub API...")
|
| 225 |
|
| 226 |
+
if not HF_HUB_AVAILABLE:
|
| 227 |
+
print("β huggingface_hub not available for setting secrets")
|
| 228 |
+
return self._manual_secret_setup()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
|
| 230 |
+
repo_id = f"{self.username}/{self.space_name}"
|
|
|
|
| 231 |
|
| 232 |
+
# Get the HF token from environment or use the provided token
|
| 233 |
+
hf_token = os.getenv('HF_TOKEN', self.token)
|
| 234 |
+
|
| 235 |
+
# Set the HF_TOKEN secret for the space using the API
|
| 236 |
+
try:
|
| 237 |
+
self.api.add_space_secret(
|
| 238 |
+
repo_id=repo_id,
|
| 239 |
+
key="HF_TOKEN",
|
| 240 |
+
value=hf_token,
|
| 241 |
+
description="Hugging Face token for dataset access"
|
| 242 |
+
)
|
| 243 |
+
print("β
Successfully set HF_TOKEN secret via API")
|
| 244 |
+
|
| 245 |
+
# Optionally set dataset repository if specified
|
| 246 |
+
dataset_repo = os.getenv('TRACKIO_DATASET_REPO')
|
| 247 |
+
if dataset_repo:
|
| 248 |
+
self.api.add_space_variable(
|
| 249 |
+
repo_id=repo_id,
|
| 250 |
+
key="TRACKIO_DATASET_REPO",
|
| 251 |
+
value=dataset_repo,
|
| 252 |
+
description="Dataset repository for Trackio experiments"
|
| 253 |
+
)
|
| 254 |
+
print(f"β
Successfully set TRACKIO_DATASET_REPO variable: {dataset_repo}")
|
| 255 |
+
|
| 256 |
+
return True
|
| 257 |
+
|
| 258 |
+
except Exception as api_error:
|
| 259 |
+
print(f"β Failed to set secrets via API: {api_error}")
|
| 260 |
+
print("Falling back to manual setup...")
|
| 261 |
+
return self._manual_secret_setup()
|
| 262 |
|
| 263 |
except Exception as e:
|
| 264 |
+
print(f"β Error setting space secrets: {e}")
|
| 265 |
+
return self._manual_secret_setup()
|
| 266 |
+
|
| 267 |
+
def _manual_secret_setup(self) -> bool:
|
| 268 |
+
"""Fallback method for manual secret setup"""
|
| 269 |
+
print("π Manual Space Secrets Configuration:")
|
| 270 |
+
print(f" HF_TOKEN={self.token}")
|
| 271 |
+
|
| 272 |
+
dataset_repo = os.getenv('TRACKIO_DATASET_REPO', 'tonic/trackio-experiments')
|
| 273 |
+
print(f" TRACKIO_DATASET_REPO={dataset_repo}")
|
| 274 |
+
|
| 275 |
+
print("\nπ§ To set secrets in your Space:")
|
| 276 |
+
print("1. Go to your Space settings: {self.space_url}/settings")
|
| 277 |
+
print("2. Navigate to the 'Repository secrets' section")
|
| 278 |
+
print("3. Add the following secrets:")
|
| 279 |
+
print(f" Name: HF_TOKEN")
|
| 280 |
+
print(f" Value: {self.token}")
|
| 281 |
+
if dataset_repo:
|
| 282 |
+
print(f" Name: TRACKIO_DATASET_REPO")
|
| 283 |
+
print(f" Value: {dataset_repo}")
|
| 284 |
+
print("4. Save the secrets")
|
| 285 |
+
|
| 286 |
+
return True
|
| 287 |
|
| 288 |
def test_space(self) -> bool:
|
| 289 |
"""Test if the Space is working correctly"""
|
|
|
|
| 323 |
if not temp_dir:
|
| 324 |
return False
|
| 325 |
|
| 326 |
+
# Step 3: Upload files using HF Hub API
|
| 327 |
if not self.upload_files_to_space(temp_dir):
|
| 328 |
return False
|
| 329 |
|
| 330 |
+
# Step 4: Set space secrets using API
|
| 331 |
+
if not self.set_space_secrets():
|
| 332 |
+
return False
|
| 333 |
+
|
| 334 |
+
# Step 5: Clean up temp directory
|
| 335 |
try:
|
| 336 |
shutil.rmtree(temp_dir)
|
| 337 |
print("β
Cleaned up temporary directory")
|
| 338 |
except Exception as e:
|
| 339 |
print(f"β οΈ Warning: Could not clean up temp directory: {e}")
|
| 340 |
|
| 341 |
+
# Step 6: Test space
|
| 342 |
if not self.test_space():
|
| 343 |
print("β οΈ Space created but may need more time to build")
|
| 344 |
print("Please check the Space manually in a few minutes")
|
|
|
|
| 354 |
print("Trackio Space Deployment Script")
|
| 355 |
print("=" * 40)
|
| 356 |
|
| 357 |
+
# Get user input (no username needed - will be extracted from token)
|
|
|
|
| 358 |
space_name = input("Enter Space name (e.g., trackio-monitoring): ").strip()
|
| 359 |
token = input("Enter your Hugging Face token: ").strip()
|
| 360 |
|
|
|
|
| 362 |
git_email = input("Enter your git email (optional, press Enter for default): ").strip()
|
| 363 |
git_name = input("Enter your git name (optional, press Enter for default): ").strip()
|
| 364 |
|
| 365 |
+
if not space_name or not token:
|
| 366 |
+
print("β Space name and token are required")
|
| 367 |
sys.exit(1)
|
| 368 |
|
| 369 |
# Use empty strings if not provided
|
|
|
|
| 372 |
if not git_name:
|
| 373 |
git_name = None
|
| 374 |
|
| 375 |
+
# Create deployer (username will be extracted from token)
|
| 376 |
+
deployer = TrackioSpaceDeployer(space_name, token, git_email, git_name)
|
| 377 |
|
| 378 |
# Run deployment
|
| 379 |
success = deployer.deploy()
|
|
|
|
| 381 |
if success:
|
| 382 |
print("\nβ
Deployment successful!")
|
| 383 |
print(f"π Your Trackio Space: {deployer.space_url}")
|
| 384 |
+
print(f"π€ Username: {deployer.username}")
|
| 385 |
print("\nNext steps:")
|
| 386 |
print("1. Wait for the Space to build (usually 2-5 minutes)")
|
| 387 |
+
print("2. Secrets have been automatically set via API")
|
| 388 |
+
print("3. Test the interface by visiting the Space URL")
|
| 389 |
+
print("4. Use the Space URL in your training scripts")
|
| 390 |
print("\nIf the Space doesn't work immediately, check:")
|
| 391 |
print("- The Space logs at the Space URL")
|
| 392 |
print("- That all files were uploaded correctly")
|
| 393 |
print("- That the HF token has write permissions")
|
| 394 |
+
print("- That the secrets were set correctly in Space settings")
|
| 395 |
else:
|
| 396 |
print("\nβ Deployment failed!")
|
| 397 |
print("Check the error messages above and try again.")
|
tests/test_trackio_fixes.py
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Test script to verify Trackio deployment fixes
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
import sys
|
| 8 |
+
import subprocess
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
|
| 11 |
+
def test_imports():
|
| 12 |
+
"""Test that required packages are available"""
|
| 13 |
+
print("π Testing imports...")
|
| 14 |
+
|
| 15 |
+
try:
|
| 16 |
+
from huggingface_hub import HfApi, create_repo, upload_file
|
| 17 |
+
print("β
huggingface_hub imports successful")
|
| 18 |
+
except ImportError as e:
|
| 19 |
+
print(f"β huggingface_hub import failed: {e}")
|
| 20 |
+
return False
|
| 21 |
+
|
| 22 |
+
try:
|
| 23 |
+
from datasets import Dataset
|
| 24 |
+
print("β
datasets import successful")
|
| 25 |
+
except ImportError as e:
|
| 26 |
+
print(f"β datasets import failed: {e}")
|
| 27 |
+
return False
|
| 28 |
+
|
| 29 |
+
return True
|
| 30 |
+
|
| 31 |
+
def test_script_exists(script_path):
|
| 32 |
+
"""Test that a script exists and is executable"""
|
| 33 |
+
path = Path(script_path)
|
| 34 |
+
if not path.exists():
|
| 35 |
+
print(f"β Script not found: {script_path}")
|
| 36 |
+
return False
|
| 37 |
+
|
| 38 |
+
if not path.is_file():
|
| 39 |
+
print(f"β Not a file: {script_path}")
|
| 40 |
+
return False
|
| 41 |
+
|
| 42 |
+
print(f"β
Script exists: {script_path}")
|
| 43 |
+
return True
|
| 44 |
+
|
| 45 |
+
def test_script_syntax(script_path):
|
| 46 |
+
"""Test that a script has valid Python syntax"""
|
| 47 |
+
try:
|
| 48 |
+
with open(script_path, 'r', encoding='utf-8') as f:
|
| 49 |
+
compile(f.read(), script_path, 'exec')
|
| 50 |
+
print(f"β
Syntax valid: {script_path}")
|
| 51 |
+
return True
|
| 52 |
+
except SyntaxError as e:
|
| 53 |
+
print(f"β Syntax error in {script_path}: {e}")
|
| 54 |
+
return False
|
| 55 |
+
except Exception as e:
|
| 56 |
+
print(f"β Error reading {script_path}: {e}")
|
| 57 |
+
return False
|
| 58 |
+
|
| 59 |
+
def test_environment_variables():
|
| 60 |
+
"""Test that required environment variables are set"""
|
| 61 |
+
print("π Testing environment variables...")
|
| 62 |
+
|
| 63 |
+
hf_token = os.environ.get('HF_TOKEN')
|
| 64 |
+
if hf_token:
|
| 65 |
+
print("β
HF_TOKEN is set")
|
| 66 |
+
else:
|
| 67 |
+
print("β οΈ HF_TOKEN is not set (this is normal for testing)")
|
| 68 |
+
|
| 69 |
+
dataset_repo = os.environ.get('TRACKIO_DATASET_REPO', 'tonic/trackio-experiments')
|
| 70 |
+
print(f"π TRACKIO_DATASET_REPO: {dataset_repo}")
|
| 71 |
+
|
| 72 |
+
return True
|
| 73 |
+
|
| 74 |
+
def test_api_connection():
|
| 75 |
+
"""Test HF API connection if token is available"""
|
| 76 |
+
hf_token = os.environ.get('HF_TOKEN')
|
| 77 |
+
if not hf_token:
|
| 78 |
+
print("β οΈ Skipping API connection test - no HF_TOKEN")
|
| 79 |
+
return True
|
| 80 |
+
|
| 81 |
+
try:
|
| 82 |
+
from huggingface_hub import HfApi
|
| 83 |
+
api = HfApi(token=hf_token)
|
| 84 |
+
|
| 85 |
+
# Test basic API call
|
| 86 |
+
user_info = api.whoami()
|
| 87 |
+
print(f"β
API connection successful - User: {user_info.get('name', 'Unknown')}")
|
| 88 |
+
return True
|
| 89 |
+
except Exception as e:
|
| 90 |
+
print(f"β API connection failed: {e}")
|
| 91 |
+
return False
|
| 92 |
+
|
| 93 |
+
def test_script_functions():
|
| 94 |
+
"""Test that scripts can be imported and have required functions"""
|
| 95 |
+
print("π Testing script functions...")
|
| 96 |
+
|
| 97 |
+
# Test deploy script
|
| 98 |
+
try:
|
| 99 |
+
sys.path.append(str(Path(__file__).parent.parent / "scripts" / "trackio_tonic"))
|
| 100 |
+
from deploy_trackio_space import TrackioSpaceDeployer
|
| 101 |
+
print("β
TrackioSpaceDeployer class imported successfully")
|
| 102 |
+
except Exception as e:
|
| 103 |
+
print(f"β Failed to import TrackioSpaceDeployer: {e}")
|
| 104 |
+
return False
|
| 105 |
+
|
| 106 |
+
# Test dataset script
|
| 107 |
+
try:
|
| 108 |
+
sys.path.append(str(Path(__file__).parent.parent / "scripts" / "dataset_tonic"))
|
| 109 |
+
import setup_hf_dataset
|
| 110 |
+
print("β
setup_hf_dataset module imported successfully")
|
| 111 |
+
except Exception as e:
|
| 112 |
+
print(f"β Failed to import setup_hf_dataset: {e}")
|
| 113 |
+
return False
|
| 114 |
+
|
| 115 |
+
# Test configure script
|
| 116 |
+
try:
|
| 117 |
+
sys.path.append(str(Path(__file__).parent.parent / "scripts" / "trackio_tonic"))
|
| 118 |
+
import configure_trackio
|
| 119 |
+
print("β
configure_trackio module imported successfully")
|
| 120 |
+
except Exception as e:
|
| 121 |
+
print(f"β Failed to import configure_trackio: {e}")
|
| 122 |
+
return False
|
| 123 |
+
|
| 124 |
+
return True
|
| 125 |
+
|
| 126 |
+
def test_template_files():
|
| 127 |
+
"""Test that template files exist"""
|
| 128 |
+
print("π Testing template files...")
|
| 129 |
+
|
| 130 |
+
project_root = Path(__file__).parent.parent
|
| 131 |
+
templates_dir = project_root / "templates"
|
| 132 |
+
|
| 133 |
+
required_files = [
|
| 134 |
+
"spaces/app.py",
|
| 135 |
+
"spaces/requirements.txt",
|
| 136 |
+
"spaces/README.md",
|
| 137 |
+
"datasets/readme.md"
|
| 138 |
+
]
|
| 139 |
+
|
| 140 |
+
all_exist = True
|
| 141 |
+
for file_path in required_files:
|
| 142 |
+
full_path = templates_dir / file_path
|
| 143 |
+
if full_path.exists():
|
| 144 |
+
print(f"β
Template exists: {file_path}")
|
| 145 |
+
else:
|
| 146 |
+
print(f"β Template missing: {file_path}")
|
| 147 |
+
all_exist = False
|
| 148 |
+
|
| 149 |
+
return all_exist
|
| 150 |
+
|
| 151 |
+
def main():
|
| 152 |
+
"""Run all tests"""
|
| 153 |
+
print("π§ͺ Testing Trackio Deployment Fixes")
|
| 154 |
+
print("=" * 40)
|
| 155 |
+
|
| 156 |
+
tests = [
|
| 157 |
+
("Import Tests", test_imports),
|
| 158 |
+
("Script Existence", lambda: all([
|
| 159 |
+
test_script_exists("scripts/trackio_tonic/deploy_trackio_space.py"),
|
| 160 |
+
test_script_exists("scripts/dataset_tonic/setup_hf_dataset.py"),
|
| 161 |
+
test_script_exists("scripts/trackio_tonic/configure_trackio.py"),
|
| 162 |
+
test_script_exists("scripts/model_tonic/push_to_huggingface.py")
|
| 163 |
+
])),
|
| 164 |
+
("Script Syntax", lambda: all([
|
| 165 |
+
test_script_syntax("scripts/trackio_tonic/deploy_trackio_space.py"),
|
| 166 |
+
test_script_syntax("scripts/dataset_tonic/setup_hf_dataset.py"),
|
| 167 |
+
test_script_syntax("scripts/trackio_tonic/configure_trackio.py"),
|
| 168 |
+
test_script_syntax("scripts/model_tonic/push_to_huggingface.py")
|
| 169 |
+
])),
|
| 170 |
+
("Environment Variables", test_environment_variables),
|
| 171 |
+
("API Connection", test_api_connection),
|
| 172 |
+
("Script Functions", test_script_functions),
|
| 173 |
+
("Template Files", test_template_files)
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
results = []
|
| 177 |
+
for test_name, test_func in tests:
|
| 178 |
+
print(f"\nπ {test_name}")
|
| 179 |
+
print("-" * 20)
|
| 180 |
+
try:
|
| 181 |
+
result = test_func()
|
| 182 |
+
results.append((test_name, result))
|
| 183 |
+
except Exception as e:
|
| 184 |
+
print(f"β Test failed with exception: {e}")
|
| 185 |
+
results.append((test_name, False))
|
| 186 |
+
|
| 187 |
+
# Summary
|
| 188 |
+
print("\n" + "=" * 40)
|
| 189 |
+
print("π Test Results Summary")
|
| 190 |
+
print("=" * 40)
|
| 191 |
+
|
| 192 |
+
passed = 0
|
| 193 |
+
total = len(results)
|
| 194 |
+
|
| 195 |
+
for test_name, result in results:
|
| 196 |
+
status = "β
PASS" if result else "β FAIL"
|
| 197 |
+
print(f"{status}: {test_name}")
|
| 198 |
+
if result:
|
| 199 |
+
passed += 1
|
| 200 |
+
|
| 201 |
+
print(f"\nπ― Overall: {passed}/{total} tests passed")
|
| 202 |
+
|
| 203 |
+
if passed == total:
|
| 204 |
+
print("π All tests passed! The fixes are working correctly.")
|
| 205 |
+
return True
|
| 206 |
+
else:
|
| 207 |
+
print("β οΈ Some tests failed. Please check the issues above.")
|
| 208 |
+
return False
|
| 209 |
+
|
| 210 |
+
if __name__ == "__main__":
|
| 211 |
+
success = main()
|
| 212 |
+
sys.exit(0 if success else 1)
|