otf-api 0.13.3__tar.gz → 0.14.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {otf_api-0.13.3/src/otf_api.egg-info → otf_api-0.14.1}/PKG-INFO +1 -1
- {otf_api-0.13.3 → otf_api-0.14.1}/pyproject.toml +3 -4
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/__init__.py +1 -1
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/client.py +15 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/members/member_client.py +1 -1
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/studios/studio_client.py +1 -1
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/workouts/workout_client.py +2 -2
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/auth.py +14 -7
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/cache.py +10 -0
- {otf_api-0.13.3 → otf_api-0.14.1/src/otf_api.egg-info}/PKG-INFO +1 -1
- {otf_api-0.13.3 → otf_api-0.14.1}/LICENSE +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/README.md +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/setup.cfg +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/_compat.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/api.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/bookings/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/bookings/booking_api.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/bookings/booking_client.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/members/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/members/member_api.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/studios/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/studios/studio_api.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/utils.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/workouts/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/workouts/workout_api.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/user.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/utils.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/exceptions.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/base.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/bookings.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/bookings_v2.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/classes.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/enums.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/filters.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/ratings.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/member_detail.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/member_membership.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/member_purchases.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/notifications.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/mixins.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/enums.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/studio_detail.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/studio_services.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/__init__.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/body_composition_list.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/challenge_tracker_content.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/challenge_tracker_detail.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/enums.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/lifetime_stats.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/out_of_studio_workout_history.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/performance_summary.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/telemetry.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/workout.py +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/py.typed +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/SOURCES.txt +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/dependency_links.txt +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/requires.txt +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/top_level.txt +0 -0
- {otf_api-0.13.3 → otf_api-0.14.1}/tests/test_filters.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "otf-api"
|
3
|
-
version = "0.
|
3
|
+
version = "0.14.1"
|
4
4
|
description = "Python OrangeTheory Fitness API Client"
|
5
5
|
authors = [{ name = "Jessica Smith", email = "j.smith.git1@gmail.com" }]
|
6
6
|
requires-python = ">=3.11"
|
@@ -39,7 +39,6 @@ Documentation = "https://otf-api.readthedocs.io/en/stable/"
|
|
39
39
|
dev = [
|
40
40
|
"build==1.2.1",
|
41
41
|
"bump-my-version>=0.23.0,<0.24",
|
42
|
-
"mypy==1.10.0",
|
43
42
|
"mypy-boto3-cognito-identity>=1.38.0",
|
44
43
|
"mypy-boto3-cognito-idp>=1.35.93,<2",
|
45
44
|
"pre-commit==3.7.1",
|
@@ -51,7 +50,7 @@ dev = [
|
|
51
50
|
docs = [
|
52
51
|
"autodoc-pydantic>=2.2.0",
|
53
52
|
"furo>=2024.8.6",
|
54
|
-
"sphinx
|
53
|
+
"sphinx>=8.3.0",
|
55
54
|
"sphinx-autobuild==2024.10.3",
|
56
55
|
"sphinx-autodoc-typehints==3.2.0",
|
57
56
|
"sphinx-autodoc2==0.5.0",
|
@@ -72,5 +71,5 @@ default-groups = ["dev"]
|
|
72
71
|
pythonpath = ["src"]
|
73
72
|
|
74
73
|
[build-system]
|
75
|
-
requires = ["setuptools >=
|
74
|
+
requires = ["setuptools >= 80.0"]
|
76
75
|
build-backend = "setuptools.build_meta"
|
@@ -49,6 +49,21 @@ class OtfClient:
|
|
49
49
|
)
|
50
50
|
atexit.register(self.session.close)
|
51
51
|
|
52
|
+
def __getstate__(self):
|
53
|
+
"""Get the state of the OtfClient instance for serialization."""
|
54
|
+
state = self.__dict__.copy()
|
55
|
+
# Remove circular references
|
56
|
+
state.pop("session", None)
|
57
|
+
return state
|
58
|
+
|
59
|
+
def __setstate__(self, state): # noqa
|
60
|
+
"""Set the state of the OtfClient instance from serialized data."""
|
61
|
+
self.__dict__.update(state)
|
62
|
+
self.session = httpx.Client(
|
63
|
+
headers=HEADERS, auth=self.user.httpx_auth, timeout=httpx.Timeout(20.0, connect=60.0)
|
64
|
+
)
|
65
|
+
atexit.register(self.session.close)
|
66
|
+
|
52
67
|
def _build_request(
|
53
68
|
self,
|
54
69
|
method: str,
|
@@ -14,7 +14,7 @@ class MemberClient:
|
|
14
14
|
self.client = client
|
15
15
|
self.member_uuid = client.member_uuid
|
16
16
|
|
17
|
-
@CACHE.memoize(expire=600, tag="member_detail"
|
17
|
+
@CACHE.memoize(expire=600, tag="member_detail")
|
18
18
|
def get_member_detail(self) -> dict:
|
19
19
|
"""Retrieve raw member details."""
|
20
20
|
return self.client.default_request(
|
@@ -15,7 +15,7 @@ class StudioClient:
|
|
15
15
|
self.client = client
|
16
16
|
self.member_uuid = client.member_uuid
|
17
17
|
|
18
|
-
@CACHE.memoize(expire=600, tag="studio_detail"
|
18
|
+
@CACHE.memoize(expire=600, tag="studio_detail")
|
19
19
|
def get_studio_detail(self, studio_uuid: str) -> dict:
|
20
20
|
"""Retrieve raw studio details."""
|
21
21
|
return self.client.default_request("GET", f"/mobile/v1/studios/{studio_uuid}")["data"]
|
@@ -43,7 +43,7 @@ class WorkoutClient:
|
|
43
43
|
params = {"limit": limit} if limit else {}
|
44
44
|
return self.performance_summary_request("GET", "/v1/performance-summaries", params=params)
|
45
45
|
|
46
|
-
@CACHE.memoize(expire=600, tag="performance_summary"
|
46
|
+
@CACHE.memoize(expire=600, tag="performance_summary")
|
47
47
|
def get_performance_summary(self, performance_summary_id: str) -> dict:
|
48
48
|
"""Retrieve raw performance summary data."""
|
49
49
|
return self.performance_summary_request("GET", f"/v1/performance-summaries/{performance_summary_id}")
|
@@ -54,7 +54,7 @@ class WorkoutClient:
|
|
54
54
|
"history"
|
55
55
|
]
|
56
56
|
|
57
|
-
@CACHE.memoize(expire=600, tag="telemetry"
|
57
|
+
@CACHE.memoize(expire=600, tag="telemetry")
|
58
58
|
def get_telemetry(self, performance_summary_id: str, max_data_points: int = 150) -> dict:
|
59
59
|
"""Retrieve raw telemetry data."""
|
60
60
|
return self.telemetry_request(
|
@@ -3,6 +3,7 @@ import platform
|
|
3
3
|
import typing
|
4
4
|
from collections.abc import Generator
|
5
5
|
from datetime import datetime
|
6
|
+
from functools import lru_cache
|
6
7
|
from logging import getLogger
|
7
8
|
from time import sleep
|
8
9
|
from typing import Any, ClassVar
|
@@ -119,15 +120,21 @@ class OtfCognito(Cognito):
|
|
119
120
|
self.mfa_tokens: dict[str, Any] = {}
|
120
121
|
self.pool_domain_url: str | None = None
|
121
122
|
|
122
|
-
self.
|
123
|
-
"cognito-idp", config=BOTO_CONFIG, region_name=REGION
|
124
|
-
) # type: ignore
|
123
|
+
self.handle_login(password)
|
125
124
|
|
126
|
-
|
127
|
-
|
128
|
-
|
125
|
+
@property
|
126
|
+
@lru_cache(maxsize=1)
|
127
|
+
def idp_client(self) -> "CognitoIdentityProviderClient":
|
128
|
+
"""Returns the Cognito Identity Provider client."""
|
129
|
+
LOGGER.debug("Creating Cognito Identity Provider client")
|
130
|
+
return Session().client("cognito-idp", config=BOTO_CONFIG, region_name=REGION) # type: ignore
|
129
131
|
|
130
|
-
|
132
|
+
@property
|
133
|
+
@lru_cache(maxsize=1)
|
134
|
+
def id_client(self) -> "CognitoIdentityClient":
|
135
|
+
"""Returns the Cognito Identity client."""
|
136
|
+
LOGGER.debug("Creating Cognito Identity client")
|
137
|
+
return Session().client("cognito-identity", config=BOTO_CONFIG, region_name=REGION) # type: ignore
|
131
138
|
|
132
139
|
def handle_login(self, password: str | None = None) -> None:
|
133
140
|
"""Handles the login process for the user.
|
@@ -130,3 +130,13 @@ def get_cache() -> OtfCache:
|
|
130
130
|
LOGGER.debug("Using cache directory: %s", cache_dir)
|
131
131
|
_CACHE = OtfCache(cache_dir)
|
132
132
|
return _CACHE
|
133
|
+
|
134
|
+
|
135
|
+
def clear_cache() -> None:
|
136
|
+
"""Clears the cache."""
|
137
|
+
try:
|
138
|
+
cache = get_cache()
|
139
|
+
cache.clear_device_data()
|
140
|
+
cache.clear_tokens()
|
141
|
+
except Exception:
|
142
|
+
LOGGER.exception("Failed to clear cache")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/out_of_studio_workout_history.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|