Skip to content

Commit 6b362cb

Browse files
committed
Coderabbit fixes
1 parent 7a66df1 commit 6b362cb

File tree

2 files changed

+28
-27
lines changed

2 files changed

+28
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Select a category:
2727
Make your selection:
2828
```
2929

30-
## API Coverage Statistics (as of 2025-08-31)
30+
## API Coverage Statistics
3131

3232
- **Total API Methods**: 101 unique endpoints (snapshot)
3333
- **Categories**: 11 organized sections

garminconnect/__init__.py

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ def _validate_positive_number(
5555
if not isinstance(value, numbers.Real):
5656
raise ValueError(f"{param_name} must be a number")
5757

58+
if isinstance(value, bool):
59+
raise ValueError(f"{param_name} must be a number, not bool")
60+
5861
if value <= 0:
5962
raise ValueError(f"{param_name} must be positive, got: {value}")
6063

@@ -63,7 +66,7 @@ def _validate_positive_number(
6366

6467
def _validate_non_negative_integer(value: int, param_name: str = "value") -> int:
6568
"""Validate that a value is a non-negative integer."""
66-
if not isinstance(value, int):
69+
if not isinstance(value, int) or isinstance(value, bool):
6770
raise ValueError(f"{param_name} must be an integer")
6871

6972
if value < 0:
@@ -74,7 +77,7 @@ def _validate_non_negative_integer(value: int, param_name: str = "value") -> int
7477

7578
def _validate_positive_integer(value: int, param_name: str = "value") -> int:
7679
"""Validate that a value is a positive integer."""
77-
if not isinstance(value, int):
80+
if not isinstance(value, int) or isinstance(value, bool):
7881
raise ValueError(f"{param_name} must be an integer")
7982
if value <= 0:
8083
raise ValueError(f"{param_name} must be a positive integer, got: {value}")
@@ -968,44 +971,42 @@ def add_hydration_data(
968971
timestamp = _fmt_ts(raw_ts)
969972

970973
elif cdate is not None and timestamp is None:
971-
# If cdate is not null, validate and use timestamp associated with midnight
974+
# If cdate is provided, validate and use midnight local time
972975
cdate = _validate_date_format(cdate, "cdate")
973-
try:
974-
raw_ts = datetime.fromisoformat(cdate)
975-
except ValueError:
976-
# if cdate is just a date, parse with format and set time to 00:00:00
977-
raw_ts = datetime.strptime(cdate, DATE_FORMAT_STR)
978-
timestamp = raw_ts.replace(
979-
hour=0, minute=0, second=0, microsecond=0
980-
).isoformat(timespec="microseconds")
976+
raw_ts = datetime.strptime(cdate, DATE_FORMAT_STR) # midnight local
977+
timestamp = _fmt_ts(raw_ts)
981978

982979
elif cdate is None and timestamp is not None:
983-
# If timestamp is not null, validate and set cdate equal to date part of timestamp
980+
# If timestamp is provided, normalize and set cdate to its date part
984981
if not isinstance(timestamp, str):
985982
raise ValueError("timestamp must be a string")
986983
try:
987-
raw_ts = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f")
988-
cdate = str(raw_ts.date())
984+
try:
985+
raw_ts = datetime.fromisoformat(timestamp)
986+
except ValueError:
987+
raw_ts = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S")
988+
cdate = raw_ts.date().isoformat()
989+
timestamp = _fmt_ts(raw_ts)
989990
except ValueError as e:
990-
raise ValueError(
991-
f"Invalid timestamp format (expected YYYY-MM-DDTHH:MM:SS.mmm): {e}"
992-
) from e
991+
raise ValueError("Invalid timestamp format (expected ISO 8601)") from e
993992
else:
994-
# Both provided - validate consistency
993+
# Both provided - validate consistency and normalize
995994
cdate = _validate_date_format(cdate, "cdate")
996995
if not isinstance(timestamp, str):
997996
raise ValueError("timestamp must be a string")
998997
try:
999-
raw_ts = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f")
1000-
ts_date = str(raw_ts.date())
998+
try:
999+
raw_ts = datetime.fromisoformat(timestamp)
1000+
except ValueError:
1001+
raw_ts = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S")
1002+
ts_date = raw_ts.date().isoformat()
10011003
if ts_date != cdate:
10021004
raise ValueError(
10031005
f"timestamp date ({ts_date}) doesn't match cdate ({cdate})"
10041006
)
1005-
except ValueError as e:
1006-
if "doesn't match" in str(e):
1007-
raise
1008-
raise ValueError(f"invalid timestamp format: {e}") from e
1007+
timestamp = _fmt_ts(raw_ts)
1008+
except ValueError:
1009+
raise
10091010

10101011
payload = {
10111012
"calendarDate": cdate,
@@ -1523,7 +1524,7 @@ def create_manual_activity(
15231524
Create a private activity manually with a few basic parameters.
15241525
type_key - Garmin field representing type of activity. See https://connect.garmin.com/modern/main/js/properties/activity_types/activity_types.properties
15251526
Value to use is the key without 'activity_type_' prefix, e.g. 'resort_skiing'
1526-
start_datetime - timestamp in this pattern "2023-12-02T10:00:00.00"
1527+
start_datetime - timestamp in this pattern "2023-12-02T10:00:00.000"
15271528
time_zone - local timezone of the activity, e.g. 'Europe/Paris'
15281529
distance_km - distance of the activity in kilometers
15291530
duration_min - duration of the activity in minutes
@@ -1928,7 +1929,7 @@ def get_gear_activities(
19281929
) -> list[dict[str, Any]]:
19291930
"""Return activities where gear uuid was used.
19301931
:param gearUUID: UUID of the gear to get activities for
1931-
:param limit: Maximum number of activities to return (default: 9999)
1932+
:param limit: Maximum number of activities to return (default: 1000)
19321933
:return: List of activities where the specified gear was used
19331934
"""
19341935
gearUUID = str(gearUUID)

0 commit comments

Comments
 (0)