Skip to content

Commit 3aff078

Browse files
committed
Added all workout methods, and demo menu options
1 parent c079f7b commit 3aff078

File tree

10 files changed

+954
-1
lines changed

10 files changed

+954
-1
lines changed

demo.py

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,26 @@ def __init__(self):
301301
"desc": "Count activities for current user",
302302
"key": "count_activities",
303303
},
304+
"v": {
305+
"desc": "Upload typed running workout (sample)",
306+
"key": "upload_running_workout",
307+
},
308+
"w": {
309+
"desc": "Upload typed cycling workout (sample)",
310+
"key": "upload_cycling_workout",
311+
},
312+
"x": {
313+
"desc": "Upload typed swimming workout (sample)",
314+
"key": "upload_swimming_workout",
315+
},
316+
"y": {
317+
"desc": "Upload typed walking workout (sample)",
318+
"key": "upload_walking_workout",
319+
},
320+
"z": {
321+
"desc": "Upload typed hiking workout (sample)",
322+
"key": "upload_hiking_workout",
323+
},
304324
},
305325
},
306326
"6": {
@@ -2017,6 +2037,191 @@ def clean_step_ids(workout_segments):
20172037
print("💡 Workout data validation failed")
20182038

20192039

2040+
def upload_running_workout_data(api: Garmin) -> None:
2041+
"""Upload a typed running workout."""
2042+
try:
2043+
import sys
2044+
from pathlib import Path
2045+
2046+
# Add test_data to path for imports
2047+
test_data_path = Path(__file__).parent / "test_data"
2048+
if str(test_data_path) not in sys.path:
2049+
sys.path.insert(0, str(test_data_path))
2050+
2051+
from sample_running_workout import create_sample_running_workout
2052+
2053+
print("🏃 Creating and uploading running workout...")
2054+
workout = create_sample_running_workout()
2055+
print(f"📤 Uploading workout: {workout.workoutName}")
2056+
2057+
result = api.upload_running_workout(workout)
2058+
2059+
if result:
2060+
print("✅ Running workout uploaded successfully!")
2061+
call_and_display(
2062+
lambda: result,
2063+
method_name="upload_running_workout",
2064+
api_call_desc="api.upload_running_workout(workout)",
2065+
)
2066+
else:
2067+
print("❌ Failed to upload running workout")
2068+
except ImportError as e:
2069+
print(f"❌ Error: {e}")
2070+
print(
2071+
"💡 Install pydantic with: pip install pydantic or pip install garminconnect[workout]"
2072+
)
2073+
except Exception as e:
2074+
print(f"❌ Error uploading running workout: {e}")
2075+
2076+
2077+
def upload_cycling_workout_data(api: Garmin) -> None:
2078+
"""Upload a typed cycling workout."""
2079+
try:
2080+
import sys
2081+
from pathlib import Path
2082+
2083+
# Add test_data to path for imports
2084+
test_data_path = Path(__file__).parent / "test_data"
2085+
if str(test_data_path) not in sys.path:
2086+
sys.path.insert(0, str(test_data_path))
2087+
2088+
from sample_cycling_workout import create_sample_cycling_workout
2089+
2090+
print("🚴 Creating and uploading cycling workout...")
2091+
workout = create_sample_cycling_workout()
2092+
print(f"📤 Uploading workout: {workout.workoutName}")
2093+
2094+
result = api.upload_cycling_workout(workout)
2095+
2096+
if result:
2097+
print("✅ Cycling workout uploaded successfully!")
2098+
call_and_display(
2099+
lambda: result,
2100+
method_name="upload_cycling_workout",
2101+
api_call_desc="api.upload_cycling_workout(workout)",
2102+
)
2103+
else:
2104+
print("❌ Failed to upload cycling workout")
2105+
except ImportError as e:
2106+
print(f"❌ Error: {e}")
2107+
print(
2108+
"💡 Install pydantic with: pip install pydantic or pip install garminconnect[workout]"
2109+
)
2110+
except Exception as e:
2111+
print(f"❌ Error uploading cycling workout: {e}")
2112+
2113+
2114+
def upload_swimming_workout_data(api: Garmin) -> None:
2115+
"""Upload a typed swimming workout."""
2116+
try:
2117+
import sys
2118+
from pathlib import Path
2119+
2120+
# Add test_data to path for imports
2121+
test_data_path = Path(__file__).parent / "test_data"
2122+
if str(test_data_path) not in sys.path:
2123+
sys.path.insert(0, str(test_data_path))
2124+
2125+
from sample_swimming_workout import create_sample_swimming_workout
2126+
2127+
print("🏊 Creating and uploading swimming workout...")
2128+
workout = create_sample_swimming_workout()
2129+
print(f"📤 Uploading workout: {workout.workoutName}")
2130+
2131+
result = api.upload_swimming_workout(workout)
2132+
2133+
if result:
2134+
print("✅ Swimming workout uploaded successfully!")
2135+
call_and_display(
2136+
lambda: result,
2137+
method_name="upload_swimming_workout",
2138+
api_call_desc="api.upload_swimming_workout(workout)",
2139+
)
2140+
else:
2141+
print("❌ Failed to upload swimming workout")
2142+
except ImportError as e:
2143+
print(f"❌ Error: {e}")
2144+
print(
2145+
"💡 Install pydantic with: pip install pydantic or pip install garminconnect[workout]"
2146+
)
2147+
except Exception as e:
2148+
print(f"❌ Error uploading swimming workout: {e}")
2149+
2150+
2151+
def upload_walking_workout_data(api: Garmin) -> None:
2152+
"""Upload a typed walking workout."""
2153+
try:
2154+
import sys
2155+
from pathlib import Path
2156+
2157+
# Add test_data to path for imports
2158+
test_data_path = Path(__file__).parent / "test_data"
2159+
if str(test_data_path) not in sys.path:
2160+
sys.path.insert(0, str(test_data_path))
2161+
2162+
from sample_walking_workout import create_sample_walking_workout
2163+
2164+
print("🚶 Creating and uploading walking workout...")
2165+
workout = create_sample_walking_workout()
2166+
print(f"📤 Uploading workout: {workout.workoutName}")
2167+
2168+
result = api.upload_walking_workout(workout)
2169+
2170+
if result:
2171+
print("✅ Walking workout uploaded successfully!")
2172+
call_and_display(
2173+
lambda: result,
2174+
method_name="upload_walking_workout",
2175+
api_call_desc="api.upload_walking_workout(workout)",
2176+
)
2177+
else:
2178+
print("❌ Failed to upload walking workout")
2179+
except ImportError as e:
2180+
print(f"❌ Error: {e}")
2181+
print(
2182+
"💡 Install pydantic with: pip install pydantic or pip install garminconnect[workout]"
2183+
)
2184+
except Exception as e:
2185+
print(f"❌ Error uploading walking workout: {e}")
2186+
2187+
2188+
def upload_hiking_workout_data(api: Garmin) -> None:
2189+
"""Upload a typed hiking workout."""
2190+
try:
2191+
import sys
2192+
from pathlib import Path
2193+
2194+
# Add test_data to path for imports
2195+
test_data_path = Path(__file__).parent / "test_data"
2196+
if str(test_data_path) not in sys.path:
2197+
sys.path.insert(0, str(test_data_path))
2198+
2199+
from sample_hiking_workout import create_sample_hiking_workout
2200+
2201+
print("🥾 Creating and uploading hiking workout...")
2202+
workout = create_sample_hiking_workout()
2203+
print(f"📤 Uploading workout: {workout.workoutName}")
2204+
2205+
result = api.upload_hiking_workout(workout)
2206+
2207+
if result:
2208+
print("✅ Hiking workout uploaded successfully!")
2209+
call_and_display(
2210+
lambda: result,
2211+
method_name="upload_hiking_workout",
2212+
api_call_desc="api.upload_hiking_workout(workout)",
2213+
)
2214+
else:
2215+
print("❌ Failed to upload hiking workout")
2216+
except ImportError as e:
2217+
print(f"❌ Error: {e}")
2218+
print(
2219+
"💡 Install pydantic with: pip install pydantic or pip install garminconnect[workout]"
2220+
)
2221+
except Exception as e:
2222+
print(f"❌ Error uploading hiking workout: {e}")
2223+
2224+
20202225
def get_scheduled_workout_by_id_data(api: Garmin) -> None:
20212226
"""Get scheduled workout by ID."""
20222227
try:
@@ -3337,6 +3542,11 @@ def execute_api_call(api: Garmin, key: str) -> None:
33373542
"get_workout_by_id": lambda: get_workout_by_id_data(api),
33383543
"download_workout": lambda: download_workout_data(api),
33393544
"upload_workout": lambda: upload_workout_data(api),
3545+
"upload_running_workout": lambda: upload_running_workout_data(api),
3546+
"upload_cycling_workout": lambda: upload_cycling_workout_data(api),
3547+
"upload_swimming_workout": lambda: upload_swimming_workout_data(api),
3548+
"upload_walking_workout": lambda: upload_walking_workout_data(api),
3549+
"upload_hiking_workout": lambda: upload_hiking_workout_data(api),
33403550
"get_scheduled_workout_by_id": lambda: get_scheduled_workout_by_id_data(
33413551
api
33423552
),

garminconnect/__init__.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2319,6 +2319,143 @@ def upload_workout(
23192319
raise ValueError("workout_json must be a JSON object or array")
23202320
return self.garth.post("connectapi", url, json=payload, api=True).json()
23212321

2322+
def upload_running_workout(self, workout: Any) -> dict[str, Any]:
2323+
"""Upload a typed running workout.
2324+
2325+
Args:
2326+
workout: RunningWorkout instance from garminconnect.workout
2327+
2328+
Returns:
2329+
Dictionary containing the uploaded workout data
2330+
2331+
Example:
2332+
from garminconnect.workout import RunningWorkout, WorkoutSegment, create_warmup_step
2333+
2334+
workout = RunningWorkout(
2335+
workoutName="Easy Run",
2336+
estimatedDurationInSecs=1800,
2337+
workoutSegments=[
2338+
WorkoutSegment(
2339+
segmentOrder=1,
2340+
sportType={"sportTypeId": 1, "sportTypeKey": "running"},
2341+
workoutSteps=[create_warmup_step(300.0)]
2342+
)
2343+
]
2344+
)
2345+
api.upload_running_workout(workout)
2346+
"""
2347+
try:
2348+
from .workout import RunningWorkout
2349+
2350+
if not isinstance(workout, RunningWorkout):
2351+
raise TypeError("workout must be a RunningWorkout instance")
2352+
return self.upload_workout(workout.to_dict())
2353+
except ImportError:
2354+
raise ImportError(
2355+
"Pydantic is required for typed workouts. "
2356+
"Install it with: pip install pydantic or pip install garminconnect[workout]"
2357+
) from None
2358+
2359+
def upload_cycling_workout(self, workout: Any) -> dict[str, Any]:
2360+
"""Upload a typed cycling workout.
2361+
2362+
Args:
2363+
workout: CyclingWorkout instance from garminconnect.workout
2364+
2365+
Returns:
2366+
Dictionary containing the uploaded workout data
2367+
2368+
Example:
2369+
from garminconnect.workout import CyclingWorkout, WorkoutSegment, create_warmup_step
2370+
2371+
workout = CyclingWorkout(
2372+
workoutName="Interval Ride",
2373+
estimatedDurationInSecs=3600,
2374+
workoutSegments=[
2375+
WorkoutSegment(
2376+
segmentOrder=1,
2377+
sportType={"sportTypeId": 2, "sportTypeKey": "cycling"},
2378+
workoutSteps=[create_warmup_step(600.0)]
2379+
)
2380+
]
2381+
)
2382+
api.upload_cycling_workout(workout)
2383+
"""
2384+
try:
2385+
from .workout import CyclingWorkout
2386+
2387+
if not isinstance(workout, CyclingWorkout):
2388+
raise TypeError("workout must be a CyclingWorkout instance")
2389+
return self.upload_workout(workout.to_dict())
2390+
except ImportError:
2391+
raise ImportError(
2392+
"Pydantic is required for typed workouts. "
2393+
"Install it with: pip install pydantic or pip install garminconnect[workout]"
2394+
) from None
2395+
2396+
def upload_swimming_workout(self, workout: Any) -> dict[str, Any]:
2397+
"""Upload a typed swimming workout.
2398+
2399+
Args:
2400+
workout: SwimmingWorkout instance from garminconnect.workout
2401+
2402+
Returns:
2403+
Dictionary containing the uploaded workout data
2404+
"""
2405+
try:
2406+
from .workout import SwimmingWorkout
2407+
2408+
if not isinstance(workout, SwimmingWorkout):
2409+
raise TypeError("workout must be a SwimmingWorkout instance")
2410+
return self.upload_workout(workout.to_dict())
2411+
except ImportError:
2412+
raise ImportError(
2413+
"Pydantic is required for typed workouts. "
2414+
"Install it with: pip install pydantic or pip install garminconnect[workout]"
2415+
) from None
2416+
2417+
def upload_walking_workout(self, workout: Any) -> dict[str, Any]:
2418+
"""Upload a typed walking workout.
2419+
2420+
Args:
2421+
workout: WalkingWorkout instance from garminconnect.workout
2422+
2423+
Returns:
2424+
Dictionary containing the uploaded workout data
2425+
"""
2426+
try:
2427+
from .workout import WalkingWorkout
2428+
2429+
if not isinstance(workout, WalkingWorkout):
2430+
raise TypeError("workout must be a WalkingWorkout instance")
2431+
return self.upload_workout(workout.to_dict())
2432+
except ImportError:
2433+
raise ImportError(
2434+
"Pydantic is required for typed workouts. "
2435+
"Install it with: pip install pydantic or pip install garminconnect[workout]"
2436+
) from None
2437+
2438+
def upload_hiking_workout(self, workout: Any) -> dict[str, Any]:
2439+
"""Upload a typed hiking workout.
2440+
2441+
Args:
2442+
workout: HikingWorkout instance from garminconnect.workout
2443+
2444+
Returns:
2445+
Dictionary containing the uploaded workout data
2446+
"""
2447+
try:
2448+
from .workout import HikingWorkout
2449+
2450+
if not isinstance(workout, HikingWorkout):
2451+
raise TypeError("workout must be a HikingWorkout instance")
2452+
return self.upload_workout(workout.to_dict())
2453+
except ImportError:
2454+
raise ImportError(
2455+
"Pydantic is required for typed workouts. "
2456+
"Install it with: pip install pydantic or pip install garminconnect[workout]"
2457+
) from None
2458+
23222459
def get_scheduled_workout_by_id(
23232460
self, scheduled_workout_id: int | str
23242461
) -> dict[str, Any]:

0 commit comments

Comments
 (0)