A Python library for creating, parsing, and converting structured workout formats with support for parametrization.
Project description
Structured Workouts
A Python library for creating, parsing, and converting structured workout formats. Built around the Structured Workout Format (SWF), this package enables you to work with workouts from various platforms and convert between different file formats.
Quick Start
Installation
pip install structured-workouts
Or using uv:
uv add structured-workouts
Basic Usage
Creating a Workout
from structured_workouts import Workout
from structured_workouts.base import (
Interval, Section, FixedValue,
VolumeQuantity, IntensityQuantity
)
# Create a simple 30-minute threshold workout
workout = Workout(
title="Threshold Test",
description="30-minute sustained effort at threshold power",
content=[
Section(
name="Warmup",
content=[
Interval(
volume=FixedValue(value=10*60, quantity=VolumeQuantity.duration), # 10 minutes (in seconds)
intensity=FixedValue(
variable="threshold",
fraction=0.6,
quantity=IntensityQuantity.power
)
)
]
),
Section(
name="Main Set",
content=[
Interval(
volume=FixedValue(value=30*60, quantity=VolumeQuantity.duration), # 30 minutes
intensity=FixedValue(
variable="threshold",
fraction=1.0,
quantity=IntensityQuantity.power
)
)
]
),
Section(
name="Cooldown",
content=[
Interval(
volume=FixedValue(value=10*60, quantity=VolumeQuantity.duration), # 10 minutes
intensity=FixedValue(
variable="threshold",
fraction=0.5,
quantity=IntensityQuantity.power
)
)
]
)
]
)
print(f"Created workout: {workout.title}")
Converting Between Formats
from structured_workouts.parsers import IntervalsICUTextParser
# Export to intervals.icu text format
parser = IntervalsICUTextParser()
intervals_icu_text = parser.to_format(workout)
print("Intervals.icu format:")
print(intervals_icu_text)
Output:
Warmup
- 10m 60%
Main Set
- 30m 100%
Cooldown
- 10m 50%
Using the Command Line Interface
Convert workouts between formats using the CLI:
# Convert from SWF to intervals.icu text format
structured-workouts --from swf --from-file my_workout.json --to intervals-icu-text
# List all available formats
structured-workouts --list-formats
# Convert with automatic format detection
structured-workouts --from-file workout.json
Structured Workout Format (SWF)
The Structured Workout Format (SWF) is a JSON-based format designed to be:
- Simple and readable: Easy to understand and modify
- Flexible: Supports complex workout structures with repeats, sections, and variable intensities
- Convertible: Can serve as an intermediate format for converting between other workout formats
- Parametrizable: Supports variables for power zones, heart rate zones, etc.
Key Concepts
- Duration: Always specified in seconds (e.g.,
600for 10 minutes) - Intensity: Power or speed, specified as absolute values or as fractions of variables like "threshold"
- Variables: Named references like "threshold", "vo2max" for flexible intensity targeting
For detailed format specification, see README_SWF.md.
Supported Formats
✅ Currently Supported
| Format | Import | Export | Notes |
|---|---|---|---|
| SWF (JSON) | ✅ | ✅ | Native format |
| Intervals.icu Text | ⚠️ | ✅ | Import is experimental and not feature complete |
| Intervals.icu API JSON | ⚠️ | ✅ | Import is experimental and not feature complete |
🚧 Planned Support
- ERG files
- MRC files
- ZWO files (Zwift)
- Garmin Connect JSON format
- FIT files
Advanced Usage
Working with Variables
# Create a workout using power zones
workout = Workout(
title="Power Zone Training",
content=[
Interval(
volume=FixedValue(value=20*60, quantity=VolumeQuantity.duration),
intensity=FixedValue(
variable="ftp", # Functional Threshold Power
fraction=0.85, # 85% of FTP
quantity=IntensityQuantity.power
)
)
]
)
Complex Workouts with Repeats
from structured_workouts.base import Repeat, RepeatQuantity
# Create intervals: 5x (4 minutes on, 2 minutes recovery)
intervals = Repeat(
type="repeat",
count=FixedValue(value=5, quantity=RepeatQuantity.NUMBER),
content=[
Interval(
volume=FixedValue(value=4*60, quantity=VolumeQuantity.duration),
intensity=FixedValue(variable="threshold", fraction=1.05, quantity=IntensityQuantity.power)
),
Interval(
volume=FixedValue(value=2*60, quantity=VolumeQuantity.duration),
intensity=FixedValue(variable="threshold", fraction=0.6, quantity=IntensityQuantity.power)
)
]
)
workout = Workout(
title="VO2 Max Intervals",
content=[Section(name="Intervals", content=[intervals])]
)
Development
Running Tests
make test
Project Structure
src/structured_workouts/
├── __init__.py # Main package exports
├── base.py # Core data structures (Interval, Section, etc.)
├── schema.py # Pydantic models and validation
├── structured_workout_format.py # SWF format implementation
├── validation.py # Additional validation logic
└── parsers/
├── base.py # Abstract parser base class
├── intervals_icu_text.py # Intervals.icu text format parser
└── intervals_icu_api.py # Intervals.icu API JSON parser
Upload to Intervals.icu
The package includes a complete example script that creates a workout and uploads it to intervals.icu:
# Set up your API credentials
export INTERVALS_ICU_API_KEY="your_api_key"
export INTERVALS_ICU_ATHLETE_ID="i"
# Run the upload script
uv run scripts/upload_to_intervals_icu.py
See scripts/upload_to_intervals_icu.py for a complete working example.
Contributing
Contributions are welcome! Areas where help is especially appreciated:
- New format parsers (ERG, MRC, ZWO, etc.)
- Improving import functionality for intervals.icu formats
- Test coverage for edge cases
- Documentation and examples
License
This project is licensed under the MIT License - see the LICENSE file for details.
Background
Although structured-workouts is developed by and integrated with SweatStack, it is designed to be a general-purpose library not tied to any specific platform or service.
The main goal is to provide a flexible, standardized way to represent structured workouts that can serve as an intermediate format for converting between different platforms and training systems.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file structured_workouts-0.1.0.tar.gz.
File metadata
- Download URL: structured_workouts-0.1.0.tar.gz
- Upload date:
- Size: 51.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e4921c34e82dead989fe79a0535f2ca3f53337f3973b788799b6c494adf78aa
|
|
| MD5 |
de813f16de687c2d561354a6aba58f78
|
|
| BLAKE2b-256 |
8a0fce4d2cd84bf7d3b8ec8296f1e3a8a584b3e08a36a6944db864670001138d
|
File details
Details for the file structured_workouts-0.1.0-py3-none-any.whl.
File metadata
- Download URL: structured_workouts-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1f3453075866413de8c1348de126d009abd15258e61fc3c0504bd085e76d984
|
|
| MD5 |
c5671801e4e31bc4287032ea26f0cff9
|
|
| BLAKE2b-256 |
1f9512ff259cfdb034bc6515316f58844a3aaa47bfa9badbb1a64673965e3a48
|