otf-api 0.11.1__tar.gz → 0.12.0__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.11.1/src/otf_api.egg-info → otf_api-0.12.0}/PKG-INFO +1 -1
- {otf_api-0.11.1 → otf_api-0.12.0}/pyproject.toml +1 -1
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/__init__.py +1 -1
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/api.py +15 -15
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/bookings.py +10 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/bookings_v2.py +21 -1
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/utils.py +5 -3
- {otf_api-0.11.1 → otf_api-0.12.0/src/otf_api.egg-info}/PKG-INFO +1 -1
- {otf_api-0.11.1 → otf_api-0.12.0}/LICENSE +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/README.md +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/setup.cfg +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/auth/__init__.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/auth/auth.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/auth/user.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/auth/utils.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/exceptions.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/filters.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/logging.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/__init__.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/base.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/body_composition_list.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/challenge_tracker_content.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/challenge_tracker_detail.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/classes.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/enums.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/lifetime_stats.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/member_detail.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/member_membership.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/member_purchases.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/mixins.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/notifications.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/out_of_studio_workout_history.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/performance_summary.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/ratings.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/studio_detail.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/studio_services.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/telemetry.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/models/workout.py +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api/py.typed +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api.egg-info/SOURCES.txt +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api.egg-info/dependency_links.txt +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api.egg-info/requires.txt +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/src/otf_api.egg-info/top_level.txt +0 -0
- {otf_api-0.11.1 → otf_api-0.12.0}/tests/test_filters.py +0 -0
@@ -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,
|
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
|
-
|
448
|
-
|
449
|
-
|
447
|
+
start_date: datetime | str | None = None,
|
448
|
+
end_date: datetime | 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
|
-
|
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
|
471
|
+
include_canceled = not exclude_cancelled
|
472
472
|
|
473
|
-
|
474
|
-
|
473
|
+
end_date = ensure_datetime(end_date, time(23, 59, 59))
|
474
|
+
start_date = ensure_datetime(start_date)
|
475
475
|
|
476
|
-
|
477
|
-
|
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=
|
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,
|
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
|
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")
|
@@ -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 | 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,
|
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
|
|
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
|