otf-api 0.11.1__py3-none-any.whl → 0.12.1__py3-none-any.whl

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/__init__.py CHANGED
@@ -4,7 +4,7 @@ from otf_api.api import Otf
4
4
  from otf_api import models
5
5
  from otf_api.auth import OtfUser
6
6
 
7
- __version__ = "0.11.1"
7
+ __version__ = "0.12.1"
8
8
 
9
9
 
10
10
  __all__ = ["Otf", "OtfUser", "models"]
otf_api/api.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import atexit
2
2
  import contextlib
3
3
  from concurrent.futures import ThreadPoolExecutor
4
- from datetime import date, datetime, timedelta
4
+ from datetime import date, datetime, time, timedelta
5
5
  from functools import partial
6
6
  from json import JSONDecodeError
7
7
  from logging import getLogger
@@ -437,16 +437,16 @@ class Otf:
437
437
  """Get bookings from the new endpoint with no date filters."""
438
438
  start_date = pendulum.datetime(1970, 1, 1)
439
439
  end_date = pendulum.today().start_of("day").add(days=45)
440
- return self.get_bookings_new(start_date, end_date, exclude_canceled=False)
440
+ return self.get_bookings_new(start_date, end_date, exclude_cancelled=False)
441
441
 
442
442
  def _get_app_config_raw(self) -> dict[str, Any]:
443
443
  return self._default_request("GET", "/member/app-configurations", headers={"SIGV4AUTH_REQUIRED": "true"})
444
444
 
445
445
  def get_bookings_new(
446
446
  self,
447
- start_dtme: datetime | str | None = None,
448
- end_dtme: datetime | str | None = None,
449
- exclude_canceled: bool = True,
447
+ start_date: datetime | date | str | None = None,
448
+ end_date: datetime | date | str | None = None,
449
+ exclude_cancelled: bool = True,
450
450
  ) -> list[models.BookingV2]:
451
451
  """Get the bookings for the user. If no dates are provided, it will return all bookings
452
452
  between today and 45 days from now.
@@ -458,9 +458,9 @@ class Otf:
458
458
  new class, which is normally transparent to the user.
459
459
 
460
460
  Args:
461
- start_dtme (datetime | str | None): The start date for the bookings. Default is None.
462
- end_dtme (datetime | str | None): The end date for the bookings. Default is None.
463
- exclude_canceled (bool): Whether to exclude canceled bookings. Default is True.
461
+ start_dtme (datetime | date | str | None): The start date for the bookings. Default is None.
462
+ end_dtme (datetime | date | str | None): The end date for the bookings. Default is None.
463
+ exclude_cancelled (bool): Whether to exclude canceled bookings. Default is True.
464
464
  Returns:
465
465
  list[BookingV2]: The bookings for the user.
466
466
  """
@@ -468,16 +468,16 @@ class Otf:
468
468
  expand = True # this doesn't seem to have an effect? so leaving it out of the argument list
469
469
 
470
470
  # leaving the parameter as `exclude_canceled` for backwards compatibility
471
- include_canceled = not exclude_canceled
471
+ include_canceled = not exclude_cancelled
472
472
 
473
- end_dtme = ensure_datetime(end_dtme)
474
- start_dtme = ensure_datetime(start_dtme)
473
+ end_date = ensure_datetime(end_date, time(23, 59, 59))
474
+ start_date = ensure_datetime(start_date)
475
475
 
476
- end_dtme = end_dtme or pendulum.today().start_of("day").add(days=45)
477
- start_dtme = start_dtme or pendulum.datetime(1970, 1, 1).start_of("day")
476
+ end_date = end_date or pendulum.today().start_of("day").add(days=45)
477
+ start_date = start_date or pendulum.datetime(1970, 1, 1).start_of("day")
478
478
 
479
479
  bookings_resp = self._get_bookings_new_raw(
480
- ends_before=end_dtme, starts_after=start_dtme, include_canceled=include_canceled, expand=expand
480
+ ends_before=end_date, starts_after=start_date, include_canceled=include_canceled, expand=expand
481
481
  )
482
482
 
483
483
  return [models.BookingV2(**b) for b in bookings_resp["items"]]
@@ -1557,7 +1557,7 @@ class Otf:
1557
1557
  start_dtme = pendulum.datetime(start_date.year, start_date.month, start_date.day, 0, 0, 0)
1558
1558
  end_dtme = pendulum.datetime(end_date.year, end_date.month, end_date.day, 23, 59, 59)
1559
1559
 
1560
- bookings = self.get_bookings_new(start_dtme, end_dtme, exclude_canceled=False)
1560
+ bookings = self.get_bookings_new(start_dtme, end_dtme, exclude_cancelled=False)
1561
1561
  bookings_dict = {b.workout.id: b for b in bookings if b.workout}
1562
1562
 
1563
1563
  perf_summaries_dict = self._get_perf_summaries_threaded(list(bookings_dict.keys()))
@@ -36,6 +36,11 @@ class OtfClass(OtfItemBase):
36
36
  program_name: str | None = Field(None, alias="programName", exclude=True, repr=False)
37
37
  virtual_class: bool | None = Field(None, alias="virtualClass", exclude=True, repr=False)
38
38
 
39
+ @property
40
+ def coach_name(self) -> str:
41
+ """Shortcut to get the coach's name, to be compatible with new BookingV2Class"""
42
+ return self.coach.first_name or ""
43
+
39
44
  def __str__(self) -> str:
40
45
  starts_at_str = self.starts_at.strftime("%a %b %d, %I:%M %p")
41
46
  return f"Class: {starts_at_str} {self.name} - {self.coach.first_name}"
@@ -90,6 +95,11 @@ class Booking(OtfItemBase):
90
95
  """Shortcut to get the class end time"""
91
96
  return self.otf_class.ends_at
92
97
 
98
+ @property
99
+ def id_value(self) -> str:
100
+ """Returns the booking_uuid, to be compatible with new BookingV2 model"""
101
+ return self.booking_uuid
102
+
93
103
  def __str__(self) -> str:
94
104
  starts_at_str = self.otf_class.starts_at.strftime("%a %b %d, %I:%M %p")
95
105
  class_name = self.otf_class.name
@@ -72,6 +72,16 @@ class BookingV2Class(OtfItemBase):
72
72
  )
73
73
  starts_at_utc: datetime | None = Field(None, alias="starts_at", exclude=True, repr=False)
74
74
 
75
+ @property
76
+ def coach_name(self) -> str:
77
+ """Shortcut to get the coach's name, to be compatible with old Booking OtfClass model"""
78
+ return self.coach or ""
79
+
80
+ @property
81
+ def ends_at(self) -> datetime:
82
+ """Emulates the end time of the class, to be compatible with old Booking OtfClass model"""
83
+ return get_end_time(self.starts_at, self.class_type)
84
+
75
85
  def __str__(self) -> str:
76
86
  starts_at_str = self.starts_at.strftime("%a %b %d, %I:%M %p")
77
87
  return f"Class: {starts_at_str} {self.name} - {self.coach}"
@@ -160,7 +170,17 @@ class BookingV2(OtfItemBase):
160
170
  @property
161
171
  def ends_at(self) -> datetime:
162
172
  """Shortcut to get the class end time"""
163
- return get_end_time(self.otf_class.starts_at, self.otf_class.class_type)
173
+ return self.otf_class.ends_at
174
+
175
+ @property
176
+ def cancelled_date(self) -> datetime | None:
177
+ """Returns the canceled_at value in a backward-compatible way"""
178
+ return self.canceled_at
179
+
180
+ @property
181
+ def id_value(self) -> str:
182
+ """Returns the booking_id, to be compatible with old Booking model"""
183
+ return self.booking_id
164
184
 
165
185
  def __str__(self) -> str:
166
186
  starts_at_str = self.otf_class.starts_at.strftime("%a %b %d, %I:%M %p")
otf_api/utils.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  import typing
3
- from datetime import date, datetime
3
+ from datetime import date, datetime, time
4
4
  from logging import getLogger
5
5
  from pathlib import Path
6
6
  from typing import Any
@@ -12,6 +12,8 @@ if typing.TYPE_CHECKING:
12
12
 
13
13
  LOGGER = getLogger(__name__)
14
14
 
15
+ MIN_TIME = datetime.min.time()
16
+
15
17
 
16
18
  def get_booking_uuid(booking_or_uuid: "str | models.Booking") -> str:
17
19
  from otf_api.models.bookings import Booking
@@ -58,7 +60,7 @@ def ensure_list(obj: list | Any | None) -> list:
58
60
  return obj
59
61
 
60
62
 
61
- def ensure_datetime(date_str: str | datetime | None) -> datetime | None:
63
+ def ensure_datetime(date_str: str | datetime | date | None, combine_with: time = MIN_TIME) -> datetime | None:
62
64
  if not date_str:
63
65
  return None
64
66
 
@@ -69,7 +71,7 @@ def ensure_datetime(date_str: str | datetime | None) -> datetime | None:
69
71
  return date_str
70
72
 
71
73
  if isinstance(date_str, date):
72
- return datetime.combine(date_str, datetime.min.time())
74
+ return datetime.combine(date_str, combine_with)
73
75
 
74
76
  raise ValueError(f"Expected str or datetime, got {type(date_str)}")
75
77
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: otf-api
3
- Version: 0.11.1
3
+ Version: 0.12.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,10 +1,10 @@
1
- otf_api/__init__.py,sha256=VlLjNep7gdvPfnIDl1YbY8uY5eRM1vE4XJvNhI4mIB8,205
2
- otf_api/api.py,sha256=95qIszuc2zjneEk-VhS9e-F5f2EnUs4lHGehL7rU2G4,67511
1
+ otf_api/__init__.py,sha256=Xp0zKth_NrmagVP6LiblO8dgapMBsx2rJ360uaDBa9k,205
2
+ otf_api/api.py,sha256=bDl9HOo_JPsiA_YR0HgkA2IL-4M0RwbpNla6VLYqKQE,67568
3
3
  otf_api/exceptions.py,sha256=GISekwF5dPt0Ol0WCU55kE5ODc5VxicNEEhmlguuE0U,1815
4
4
  otf_api/filters.py,sha256=fk2bFGi3srjS96qZlaDx-ARZRaj93NUTUdMJ01TX420,3702
5
5
  otf_api/logging.py,sha256=PRZpCaJ1F1Xya3L9Efkt3mKS5_QNr3sXjEUERSxYjvE,563
6
6
  otf_api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- otf_api/utils.py,sha256=TATPgb5-t3nEAqo_iGY2p2PKzJA564alN1skb23OCMQ,4817
7
+ otf_api/utils.py,sha256=zO8J95StaTnt_VmxLrzb8IFtQJfJDqs9ioqTMDrkkRE,4886
8
8
  otf_api/auth/__init__.py,sha256=PuhtiZ02GVP8zVSn1O-fhaYm7JM_tq5yUFATk_-8upk,132
9
9
  otf_api/auth/auth.py,sha256=5cPELC9Soif5knDDHm55ii1OMEPkJlGUphAdbOEmaRo,13278
10
10
  otf_api/auth/user.py,sha256=XlK3nbqJA4fF5UFmw2tt0eAle4QOQd6trnW72QrBsx4,2681
@@ -12,8 +12,8 @@ otf_api/auth/utils.py,sha256=vc2pEyU-3yKdv0mR6r_zSHZyMw92j5UeIN_kzcb6TeE,2909
12
12
  otf_api/models/__init__.py,sha256=MSinaMQaBTGscL-YRKJ3axFiItQ1HoH62wC2xdaBMgk,1876
13
13
  otf_api/models/base.py,sha256=KJlIxl_sRj6f-g5vKYPw4yV6fGDk-fwZ93EO0JGPYMw,202
14
14
  otf_api/models/body_composition_list.py,sha256=jGdR-9ScvIOtULJNB99aYh2INk2ihoHAnTWtbQCIea4,12202
15
- otf_api/models/bookings.py,sha256=Lj-IHN1k-w4vF-5aIKbsiQ6Uq-I5_ELoPUKXPGkfbgM,4440
16
- otf_api/models/bookings_v2.py,sha256=9HyXGnDNDmIqmr4r0_3pR1mFtN_Lfp9nP-4bCiwe5QA,5865
15
+ otf_api/models/bookings.py,sha256=fnHZmN2F8fVSWS_tco3IwjO9SJbbxzuIs2WJcCC0gNs,4781
16
+ otf_api/models/bookings_v2.py,sha256=PFSlORNZF45TRvgLwewbVGoiOd3oDG1YGvvFMtXtbpo,6533
17
17
  otf_api/models/challenge_tracker_content.py,sha256=5Ucu1n4W15v1rzhoXNvAD9tCSg3JTUiR92HHiDAxRec,2597
18
18
  otf_api/models/challenge_tracker_detail.py,sha256=c2Ds7Kv2-VaPtxoXSUTI5zrmU1A1dcSaM1UIolwSVxU,4323
19
19
  otf_api/models/classes.py,sha256=aKV6LGEh0YiPxyOaoMD0gaQOSHqs69cYHhP9H_2p_jY,3051
@@ -31,8 +31,8 @@ otf_api/models/studio_detail.py,sha256=2gq0A27NOZGz_PTBvsB-dkzm01nYc9FHmx1NON6xp
31
31
  otf_api/models/studio_services.py,sha256=aGLQMQmjGVpI6YxzAl-mcp3Y9cHPXuH9dIqrl6E-78E,1665
32
32
  otf_api/models/telemetry.py,sha256=PQ_CbADW5-t-U2iEQJGugNy-c4rD0q76TfyIqeFnTho,3170
33
33
  otf_api/models/workout.py,sha256=P3xVTvcYrm_RdU6qi3Xm2BXTxxvhvF0dgoEcODY41AA,3678
34
- otf_api-0.11.1.dist-info/licenses/LICENSE,sha256=UaPT9ynYigC3nX8n22_rC37n-qmTRKLFaHrtUwF9ktE,1071
35
- otf_api-0.11.1.dist-info/METADATA,sha256=BEppb5v_YlMUirZck7aKOtVkTemE7Uvantq2Gk8_00Y,2145
36
- otf_api-0.11.1.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
37
- otf_api-0.11.1.dist-info/top_level.txt,sha256=KAhYg1X2YG0LkTuVRhUV1I_AReNZUVNdEan7cp0pEE4,8
38
- otf_api-0.11.1.dist-info/RECORD,,
34
+ otf_api-0.12.1.dist-info/licenses/LICENSE,sha256=UaPT9ynYigC3nX8n22_rC37n-qmTRKLFaHrtUwF9ktE,1071
35
+ otf_api-0.12.1.dist-info/METADATA,sha256=p8fnmEMCyWsqvkYuILlZlxblozmyH7ilGPeM5BkT_zE,2145
36
+ otf_api-0.12.1.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
37
+ otf_api-0.12.1.dist-info/top_level.txt,sha256=KAhYg1X2YG0LkTuVRhUV1I_AReNZUVNdEan7cp0pEE4,8
38
+ otf_api-0.12.1.dist-info/RECORD,,