Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
ignore = E501
2 changes: 1 addition & 1 deletion example.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def main():
with open("heart_rate_data.json", "w") as f:
json.dump(heart_rate_raw, f, indent=2)

print(f"Saved raw heart rate data to heart_rate_data.json")
print("Saved raw heart rate data to heart_rate_data.json")

# Get personal info
personal_info = client.personal.get_personal_info()
Expand Down
3 changes: 1 addition & 2 deletions oura_api_client/api/client.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""Oura API client implementation."""

import requests
from typing import Optional, Dict, Any, List
from datetime import date, datetime
from typing import Optional, Dict, Any

from .heartrate import HeartRateEndpoints
from .personal import PersonalEndpoints
Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/daily_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.daily_activity import DailyActivityResponse, DailyActivityModel


class DailyActivity(BaseRouter):
def get_daily_activity_documents(
self,
Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/daily_cardiovascular_age.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.daily_cardiovascular_age import DailyCardiovascularAgeResponse, DailyCardiovascularAgeModel


class DailyCardiovascularAge(BaseRouter):
def get_daily_cardiovascular_age_documents(
self,
Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/daily_readiness.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.daily_readiness import DailyReadinessResponse, DailyReadinessModel


class DailyReadiness(BaseRouter):
def get_daily_readiness_documents(
self,
Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/daily_resilience.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.daily_resilience import DailyResilienceResponse, DailyResilienceModel


class DailyResilience(BaseRouter):
def get_daily_resilience_documents(
self,
Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/daily_sleep.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.daily_sleep import DailySleepResponse, DailySleepModel


class DailySleep(BaseRouter):
def get_daily_sleep_documents(
self,
Expand Down
9 changes: 5 additions & 4 deletions oura_api_client/api/daily_spo2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.daily_spo2 import DailySpO2Response, DailySpO2Model

class DailySpo2(BaseRouter): # Renamed class to DailySpo2
def get_daily_spo2_documents( # Renamed method

class DailySpo2(BaseRouter): # Renamed class to DailySpo2
def get_daily_spo2_documents( # Renamed method
self,
start_date: Optional[Union[str, date]] = None,
end_date: Optional[Union[str, date]] = None,
next_token: Optional[str] = None,
) -> DailySpO2Response: # Updated return type
) -> DailySpO2Response: # Updated return type
"""
Get daily SpO2 documents.

Expand All @@ -34,7 +35,7 @@ def get_daily_spo2_documents( # Renamed method
response = self.client._make_request("/v2/usercollection/daily_spo2", params=params)
return DailySpO2Response(**response)

def get_daily_spo2_document(self, document_id: str) -> DailySpO2Model: # Renamed method and updated return type
def get_daily_spo2_document(self, document_id: str) -> DailySpO2Model: # Renamed method and updated return type
"""
Get a single daily SpO2 document.

Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/daily_stress.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.daily_stress import DailyStressResponse, DailyStressModel


class DailyStress(BaseRouter):
def get_daily_stress_documents(
self,
Expand Down
3 changes: 2 additions & 1 deletion oura_api_client/api/enhanced_tag.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Optional, Union
from datetime import date # Using date for start_date and end_date
from datetime import date # Using date for start_date and end_date
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.enhanced_tag import EnhancedTagResponse, EnhancedTagModel


class EnhancedTag(BaseRouter):
def get_enhanced_tag_documents(
self,
Expand Down
1 change: 0 additions & 1 deletion oura_api_client/api/heartrate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Heart rate endpoint implementations."""

from typing import Optional, Dict, Any, Union
from datetime import date, datetime

from ..models.heartrate import HeartRateResponse

Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/rest_mode_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.rest_mode_period import RestModePeriodResponse, RestModePeriodModel


class RestModePeriod(BaseRouter):
def get_rest_mode_period_documents(
self,
Expand Down
11 changes: 6 additions & 5 deletions oura_api_client/api/ring_configuration.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
from typing import Optional, Union # Union is not strictly needed here but kept for consistency
from datetime import date # date is not used by ring_configuration but kept for consistency
from typing import Optional, Union # Union is not strictly needed here but kept for consistency
from datetime import date # date is not used by ring_configuration but kept for consistency
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.ring_configuration import RingConfigurationResponse, RingConfigurationModel


class RingConfiguration(BaseRouter):
def get_ring_configuration_documents(
self,
# Ring Configuration usually doesn't have start/end_date or pagination in typical REST APIs
# as it often returns a single current configuration or a list of all historical ones.
# However, if the API supports it (e.g. for historical configurations):
start_date: Optional[Union[str, date]] = None, # Kept for potential future use or specific API design
end_date: Optional[Union[str, date]] = None, # Kept for potential future use
start_date: Optional[Union[str, date]] = None, # Kept for potential future use or specific API design
end_date: Optional[Union[str, date]] = None, # Kept for potential future use
next_token: Optional[str] = None,
) -> RingConfigurationResponse:
"""
Expand Down Expand Up @@ -40,7 +41,7 @@ def get_ring_configuration_documents(
params["end_date"] = end_date
if next_token:
params["next_token"] = next_token

# Remove None params manually as empty dict evaluates to False
final_params = {k: v for k, v in params.items() if v is not None}

Expand Down
5 changes: 3 additions & 2 deletions oura_api_client/api/session.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from typing import Optional, Union
from datetime import date # Using date for start_date and end_date as per other endpoints
from datetime import date # Using date for start_date and end_date as per other endpoints
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.session import SessionResponse, SessionModel


class Session(BaseRouter):
def get_session_documents(
self,
start_date: Optional[Union[str, date]] = None, # Changed from start_datetime for consistency
start_date: Optional[Union[str, date]] = None, # Changed from start_datetime for consistency
end_date: Optional[Union[str, date]] = None, # Changed from end_datetime for consistency
next_token: Optional[str] = None,
) -> SessionResponse:
Expand Down
15 changes: 8 additions & 7 deletions oura_api_client/api/sleep.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from typing import Optional, Union
from datetime import date # Keep date for start/end_date
from datetime import date # Keep date for start/end_date
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.sleep import SleepResponse, SleepModel # Updated model import
from oura_api_client.models.sleep import SleepResponse, SleepModel # Updated model import

class Sleep(BaseRouter): # Renamed class to Sleep
def get_sleep_documents( # Renamed method

class Sleep(BaseRouter): # Renamed class to Sleep
def get_sleep_documents( # Renamed method
self,
start_date: Optional[Union[str, date]] = None, # Changed parameter name for clarity
start_date: Optional[Union[str, date]] = None, # Changed parameter name for clarity
end_date: Optional[Union[str, date]] = None, # Changed parameter name for clarity
next_token: Optional[str] = None,
) -> SleepResponse: # Updated return type
) -> SleepResponse: # Updated return type
"""
Get sleep documents.

Expand All @@ -35,7 +36,7 @@ def get_sleep_documents( # Renamed method
response = self.client._make_request("/v2/usercollection/sleep", params=params)
return SleepResponse(**response)

def get_sleep_document(self, document_id: str) -> SleepModel: # Renamed method and updated return type
def get_sleep_document(self, document_id: str) -> SleepModel: # Renamed method and updated return type
"""
Get a single sleep document.

Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/sleep_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.sleep_time import SleepTimeResponse, SleepTimeModel


class SleepTime(BaseRouter):
def get_sleep_time_documents(
self,
Expand Down
3 changes: 2 additions & 1 deletion oura_api_client/api/tag.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Optional, Union
from datetime import date # Using date for start_date and end_date
from datetime import date # Using date for start_date and end_date
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.tag import TagResponse, TagModel


class Tag(BaseRouter):
def get_tag_documents(
self,
Expand Down
1 change: 1 addition & 0 deletions oura_api_client/api/vo2_max.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.vo2_max import Vo2MaxResponse, Vo2MaxModel


class Vo2Max(BaseRouter):
def get_vo2_max_documents(
self,
Expand Down
3 changes: 1 addition & 2 deletions oura_api_client/api/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ExtApiV2DataType
)


class Webhook(BaseRouter):
def _get_webhook_headers(self) -> dict:
"""Helper to construct headers for webhook requests."""
Expand Down Expand Up @@ -149,5 +150,3 @@ def renew_webhook_subscription(self, subscription_id: str) -> WebhookSubscriptio
# unless the spec implies a body, which it does not for this path.
)
return WebhookSubscriptionModel(**response_data)

[end of oura_api_client/api/webhook.py]
3 changes: 2 additions & 1 deletion oura_api_client/api/workout.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Optional, Union
from datetime import date # Using date for start_date and end_date
from datetime import date # Using date for start_date and end_date
from oura_api_client.api.base import BaseRouter
from oura_api_client.models.workout import WorkoutResponse, WorkoutModel


class Workout(BaseRouter):
def get_workout_documents(
self,
Expand Down
3 changes: 3 additions & 0 deletions oura_api_client/models/daily_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import List, Optional
from datetime import date, datetime


class ActivityContributors(BaseModel):
meet_daily_targets: Optional[int] = Field(None, alias="meet_daily_targets")
move_every_hour: Optional[int] = Field(None, alias="move_every_hour")
Expand All @@ -10,6 +11,7 @@ class ActivityContributors(BaseModel):
training_frequency: Optional[int] = Field(None, alias="training_frequency")
training_volume: Optional[int] = Field(None, alias="training_volume")


class DailyActivityModel(BaseModel):
id: str
class_5_min: Optional[str] = Field(None, alias="class_5_min")
Expand Down Expand Up @@ -38,6 +40,7 @@ class DailyActivityModel(BaseModel):
day: date
timestamp: datetime


class DailyActivityResponse(BaseModel):
data: List[DailyActivityModel]
next_token: Optional[str] = None
13 changes: 8 additions & 5 deletions oura_api_client/models/daily_cardiovascular_age.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@
from typing import List, Optional
from datetime import date, datetime


class DailyCardiovascularAgeModel(BaseModel):
id: str
day: date
# Based on typical cardiovascular age report from Oura:
cardiovascular_age: Optional[float] = Field(None, alias="cardiovascular_age") # The user's estimated cardiovascular age
age_lower_bound: Optional[float] = Field(None, alias="age_lower_bound") # Lower bound of the estimated age range
age_upper_bound: Optional[float] = Field(None, alias="age_upper_bound") # Upper bound of the estimated age range
cardiovascular_age: Optional[int] = None # Age in years
age_difference: Optional[int] = None # Difference from chronological age
age_upper_bound: Optional[float] = Field(None, alias="age_upper_bound") # Upper bound of the estimated age range
# Other potential fields, depending on API detail:
# arterial_stiffness_index: Optional[float] = Field(None, alias="arterial_stiffness_index")
confidence: Optional[float] = None # Confidence score
# pulse_wave_velocity: Optional[float] = Field(None, alias="pulse_wave_velocity")
timestamp: datetime # Timestamp of the summary
timestamp: datetime # Timestamp of the summary


class DailyCardiovascularAgeResponse(BaseModel):
data: List[DailyCardiovascularAgeModel]
next_token: Optional[str] = None
source: Optional[str] = None # Data source
17 changes: 10 additions & 7 deletions oura_api_client/models/daily_readiness.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from pydantic import BaseModel, Field
from typing import List, Optional # Added List
from typing import List, Optional
from datetime import date, datetime


class ReadinessContributors(BaseModel):
activity_balance: Optional[int] = Field(None, alias="activity_balance")
body_temperature: Optional[int] = Field(None, alias="body_temperature")
Expand All @@ -12,23 +13,25 @@ class ReadinessContributors(BaseModel):
resting_heart_rate: Optional[int] = Field(None, alias="resting_heart_rate")
sleep_balance: Optional[int] = Field(None, alias="sleep_balance")


class DailyReadinessModel(BaseModel):
id: str
contributors: ReadinessContributors
day: date
score: Optional[int] = Field(None, alias="score")
temperature_deviation: Optional[float] = Field(None, alias="temperature_deviation") # Deprecated
temperature_deviation: Optional[float] = Field(None, alias="temperature_deviation") # Deprecated
temperature_trend_deviation: Optional[float] = Field(None, alias="temperature_trend_deviation")
timestamp: datetime
# New fields from OpenAPI spec not in original snippet
activity_class_5_min: Optional[str] = Field(None, alias="activity_class_5_min") # New
hrv_balance_data: Optional[str] = Field(None, alias="hrv_balance_data") # New, assuming string, adjust if different type
spo2_percentage: Optional[float] = Field(None, alias="spo2_percentage") # New
activity_class_5_min: Optional[str] = Field(None, alias="activity_class_5_min") # New
hrv_balance_data: Optional[str] = Field(None, alias="hrv_balance_data") # New, assuming string, adjust if different type
spo2_percentage: Optional[float] = Field(None, alias="spo2_percentage") # New
# Fields from original DailyActivity/Sleep that might be relevant or were missed in initial Readiness scope
# Assuming these are not part of readiness based on typical Oura data separation,
# but including as comments if they need to be reviewed from a more comprehensive spec
# sleep_average: Optional[int] = Field(None, alias="sleep_average") # Example if there was a sleep_average field
# readiness_score_delta: Optional[int] = Field(None, alias="readiness_score_delta") # This was in sleep, likely not here
# sleep_average: Optional[int] = Field(None, alias="sleep_average") # Example if there was a sleep_average field
# readiness_score_delta: Optional[int] = Field(None, alias="readiness_score_delta") # This was in sleep, likely not here


class DailyReadinessResponse(BaseModel):
data: List[DailyReadinessModel]
Expand Down
8 changes: 5 additions & 3 deletions oura_api_client/models/daily_resilience.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
from pydantic import BaseModel, Field
from typing import List, Optional

from datetime import date, datetime


class DailyResilienceModel(BaseModel):
id: str
day: date
resilience_score: Optional[float] = Field(None, alias="resilience_score") # Overall resilience score
resilience_score: Optional[float] = Field(None, alias="resilience_score") # Overall resilience score
# Based on typical resilience metrics, fields could include:
# stress_regulation: Optional[float] = Field(None, alias="stress_regulation")
# recovery_patterns: Optional[float] = Field(None, alias="recovery_patterns")
# emotional_balance: Optional[float] = Field(None, alias="emotional_balance")
# These are examples; actual fields depend on the Oura API's definition of resilience.
# For now, focusing on a core `resilience_score`.
timestamp: datetime # Timestamp of the summary
timestamp: datetime # Timestamp of the summary


class DailyResilienceResponse(BaseModel):
data: List[DailyResilienceModel]
Expand Down
Loading
Loading