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.
Files changed (65) hide show
  1. {otf_api-0.13.3/src/otf_api.egg-info → otf_api-0.14.1}/PKG-INFO +1 -1
  2. {otf_api-0.13.3 → otf_api-0.14.1}/pyproject.toml +3 -4
  3. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/__init__.py +1 -1
  4. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/client.py +15 -0
  5. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/members/member_client.py +1 -1
  6. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/studios/studio_client.py +1 -1
  7. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/workouts/workout_client.py +2 -2
  8. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/auth.py +14 -7
  9. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/cache.py +10 -0
  10. {otf_api-0.13.3 → otf_api-0.14.1/src/otf_api.egg-info}/PKG-INFO +1 -1
  11. {otf_api-0.13.3 → otf_api-0.14.1}/LICENSE +0 -0
  12. {otf_api-0.13.3 → otf_api-0.14.1}/README.md +0 -0
  13. {otf_api-0.13.3 → otf_api-0.14.1}/setup.cfg +0 -0
  14. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/__init__.py +0 -0
  15. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/_compat.py +0 -0
  16. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/api.py +0 -0
  17. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/bookings/__init__.py +0 -0
  18. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/bookings/booking_api.py +0 -0
  19. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/bookings/booking_client.py +0 -0
  20. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/members/__init__.py +0 -0
  21. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/members/member_api.py +0 -0
  22. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/studios/__init__.py +0 -0
  23. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/studios/studio_api.py +0 -0
  24. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/utils.py +0 -0
  25. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/workouts/__init__.py +0 -0
  26. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/api/workouts/workout_api.py +0 -0
  27. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/__init__.py +0 -0
  28. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/user.py +0 -0
  29. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/auth/utils.py +0 -0
  30. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/exceptions.py +0 -0
  31. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/__init__.py +0 -0
  32. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/base.py +0 -0
  33. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/__init__.py +0 -0
  34. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/bookings.py +0 -0
  35. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/bookings_v2.py +0 -0
  36. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/classes.py +0 -0
  37. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/enums.py +0 -0
  38. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/filters.py +0 -0
  39. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/bookings/ratings.py +0 -0
  40. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/__init__.py +0 -0
  41. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/member_detail.py +0 -0
  42. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/member_membership.py +0 -0
  43. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/member_purchases.py +0 -0
  44. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/members/notifications.py +0 -0
  45. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/mixins.py +0 -0
  46. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/__init__.py +0 -0
  47. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/enums.py +0 -0
  48. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/studio_detail.py +0 -0
  49. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/studios/studio_services.py +0 -0
  50. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/__init__.py +0 -0
  51. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/body_composition_list.py +0 -0
  52. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/challenge_tracker_content.py +0 -0
  53. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/challenge_tracker_detail.py +0 -0
  54. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/enums.py +0 -0
  55. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/lifetime_stats.py +0 -0
  56. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/out_of_studio_workout_history.py +0 -0
  57. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/performance_summary.py +0 -0
  58. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/telemetry.py +0 -0
  59. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/models/workouts/workout.py +0 -0
  60. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api/py.typed +0 -0
  61. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/SOURCES.txt +0 -0
  62. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/dependency_links.txt +0 -0
  63. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/requires.txt +0 -0
  64. {otf_api-0.13.3 → otf_api-0.14.1}/src/otf_api.egg-info/top_level.txt +0 -0
  65. {otf_api-0.13.3 → otf_api-0.14.1}/tests/test_filters.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: otf-api
3
- Version: 0.13.3
3
+ Version: 0.14.1
4
4
  Summary: Python OrangeTheory Fitness API Client
5
5
  Author-email: Jessica Smith <j.smith.git1@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "otf-api"
3
- version = "0.13.3"
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==8.3.0",
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 >= 61.0"]
74
+ requires = ["setuptools >= 80.0"]
76
75
  build-backend = "setuptools.build_meta"
@@ -36,7 +36,7 @@ def _setup_logging() -> None:
36
36
 
37
37
  _setup_logging()
38
38
 
39
- __version__ = "0.13.3"
39
+ __version__ = "0.14.1"
40
40
 
41
41
 
42
42
  __all__ = ["Otf", "OtfUser", "models"]
@@ -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", ignore=(0,))
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", ignore=(0,))
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", ignore=(0,))
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", ignore=(0,))
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.idp_client: CognitoIdentityProviderClient = Session().client(
123
- "cognito-idp", config=BOTO_CONFIG, region_name=REGION
124
- ) # type: ignore
123
+ self.handle_login(password)
125
124
 
126
- self.id_client: CognitoIdentityClient = Session().client(
127
- "cognito-identity", config=BOTO_CONFIG, region_name=REGION
128
- ) # type: ignore
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
- self.handle_login(password)
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")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: otf-api
3
- Version: 0.13.3
3
+ Version: 0.14.1
4
4
  Summary: Python OrangeTheory Fitness API Client
5
5
  Author-email: Jessica Smith <j.smith.git1@gmail.com>
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes
File without changes