Coverage for health / models / activity.py: 100%

33 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-02 17:44 +0800

1""" 

2Pydantic models for exercise activities and workouts. 

3""" 

4 

5from datetime import datetime, date as date_type 

6from typing import Optional, List, Dict, Any 

7from pydantic import BaseModel, Field 

8 

9 

10class Activity(BaseModel): 

11 """Exercise activity summary.""" 

12 

13 activity_id: str = Field(..., description="Unique activity ID") 

14 activity_type: str = Field(..., description="Type of activity (running, cycling, etc.)") 

15 activity_name: Optional[str] = Field(default=None, description="Activity name") 

16 date: date_type = Field(..., description="Date of the activity") 

17 start_time: Optional[datetime] = Field(default=None, description="Activity start time") 

18 duration_seconds: Optional[float] = Field( 

19 default=None, description="Activity duration in seconds" 

20 ) 

21 distance_meters: Optional[float] = Field( 

22 default=None, description="Distance covered in meters" 

23 ) 

24 elevation_gain_meters: Optional[float] = Field( 

25 default=None, description="Elevation gain in meters" 

26 ) 

27 elevation_loss_meters: Optional[float] = Field( 

28 default=None, description="Elevation loss in meters" 

29 ) 

30 calories: Optional[int] = Field(default=None, description="Calories burned") 

31 average_heart_rate: Optional[int] = Field( 

32 default=None, description="Average heart rate in bpm" 

33 ) 

34 max_heart_rate: Optional[int] = Field( 

35 default=None, description="Maximum heart rate in bpm" 

36 ) 

37 average_speed_mps: Optional[float] = Field( 

38 default=None, description="Average speed in meters per second" 

39 ) 

40 max_speed_mps: Optional[float] = Field( 

41 default=None, description="Maximum speed in meters per second" 

42 ) 

43 average_pace_min_per_km: Optional[float] = Field( 

44 default=None, description="Average pace in minutes per kilometer" 

45 ) 

46 average_cadence: Optional[float] = Field( 

47 default=None, description="Average cadence (steps/min or rpm)" 

48 ) 

49 training_effect: Optional[float] = Field( 

50 default=None, description="Aerobic training effect" 

51 ) 

52 anaerobic_training_effect: Optional[float] = Field( 

53 default=None, description="Anaerobic training effect" 

54 ) 

55 location_name: Optional[str] = Field( 

56 default=None, description="Location of the activity" 

57 ) 

58 description: Optional[str] = Field( 

59 default=None, description="Activity description" 

60 ) 

61 raw_data: Optional[Dict[str, Any]] = Field( 

62 default=None, description="Raw API response" 

63 ) 

64 

65 

66class ActivityDetail(BaseModel): 

67 """Detailed activity data including splits and laps.""" 

68 

69 activity_id: str = Field(..., description="Activity ID") 

70 summary: Activity = Field(..., description="Activity summary") 

71 laps: Optional[List[Dict[str, Any]]] = Field( 

72 default=None, description="Lap data" 

73 ) 

74 splits: Optional[List[Dict[str, Any]]] = Field( 

75 default=None, description="Split data" 

76 ) 

77 samples: Optional[List[Dict[str, Any]]] = Field( 

78 default=None, description="Time-series samples (HR, speed, etc.)" 

79 ) 

80 gear: Optional[str] = Field(default=None, description="Gear used") 

81 raw_data: Optional[Dict[str, Any]] = Field( 

82 default=None, description="Raw API response" 

83 )