Skip to content

Commit 59f9164

Browse files
committed
Improve documentation organization and readability
- Split NAMING_AND_TYPING.md into TYPES.md and NAMING.md - Split VALIDATIONS_AND_EXCEPTIONS.md into VALIDATIONS.md and ERROR_HANDLING.md - Update README.md with organized documentation links - Fix intraday data support information in DEVELOPMENT.md - Add information about disabling data logging to LOGGING.md - Update TODO.md to reflect completed documentation work
1 parent af3993a commit 59f9164

File tree

9 files changed

+578
-448
lines changed

9 files changed

+578
-448
lines changed

README.md

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,24 @@ between sessions. If provided, the client will:
8989
3. Set Callback URL to "https://localhost:8080" (or your preferred local URL)
9090
4. Copy your Client ID and Client Secret
9191

92-
Additional documentation:
93-
94-
- To understand the logging implemementation, see [LOGGING](docs/LOGGING.md)
95-
- To understand validations and the exception hierarchy, see
96-
[VALIDATIONS_AND_EXCEPTIONS](docs/VALIDATIONS_AND_EXCEPTIONS.md)
97-
- It's work checking out
98-
[Fitbit's Best Practices](https://dev.fitbit.com/build/reference/web-api/developer-guide/best-practices/)
99-
- For some general development guidelines, see
100-
[DEVELOPMENT](docs/DEVELOPMENT.md).
101-
- For style guidelines (mostly enforced through varius linters and formatters)
102-
see [STYLE](docs/STYLE.md).
92+
## Additional Documentation
93+
94+
### For API Library Users
95+
96+
- [LOGGING.md](docs/LOGGING.md): Understanding the dual-logger system
97+
- [TYPES.md](docs/TYPES.md): JSON type system and method return types
98+
- [NAMING.md](docs/NAMING.md): API method naming conventions
99+
- [VALIDATIONS.md](docs/VALIDATIONS.md): Input parameter validation
100+
- [ERROR_HANDLING.md](docs/ERROR_HANDLING.md): Exception hierarchy and handling
101+
102+
It's also worth reviewing
103+
[Fitbit's Best Practices](https://dev.fitbit.com/build/reference/web-api/developer-guide/best-practices/)
104+
for API usage.
105+
106+
### Project Best Practices
107+
108+
- [DEVELOPMENT.md](docs/DEVELOPMENT.md): Development environment and guidelines
109+
- [STYLE.md](docs/STYLE.md): Code style and formatting standards
103110

104111
## Important Note - Subscription Support
105112

TODO.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## TODOs:
44

5+
- Create and Test that all methods have an alias in `Client` and that the
6+
signatures match
7+
58
- Improve README for end users:
69

710
- Add more common use cases examples beyond basic profile retrieval
@@ -10,14 +13,15 @@
1013
- Verify correct callback URI guidance (check if "https://localhost:8080" is
1114
actually the correct/optimal value to recommend)
1215

13-
- Review and improve all documentation files in docs/ from an end-user
14-
perspective:
16+
- Review and improve all documentation files in docs/ from an end-user
17+
perspective
1518

16-
- DEVELOPMENT.md
17-
- LOGGING.md
18-
- NAMING_AND_TYPING.md
19-
- STYLE.md
20-
- VALIDATIONS_AND_EXCEPTIONS.md
19+
- ✅ Split NAMING_AND_TYPING.md into TYPES.md and NAMING.md
20+
- ✅ Split VALIDATIONS_AND_EXCEPTIONS.md into VALIDATIONS.md and
21+
ERROR_HANDLING.md
22+
- ✅ Update cross-references between documentation files
23+
- ✅ Fix intraday data support information in DEVELOPMENT.md
24+
- ✅ Add information about disabling data logging to LOGGING.md
2125

2226
- PyPi deployment
2327

@@ -34,11 +38,6 @@
3438
- Rename to `_base`? Files it first, makes it clearer that everything in it is
3539
private
3640

37-
- client.py:
38-
39-
- Creat and Test that all methods have an alias in `Client` and that the
40-
signatures match
41-
4241
- CI:
4342

4443
* Read and implement:

docs/DEVELOPMENT.md

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -339,18 +339,32 @@ TODO
339339
- Use issue templates when reporting bugs
340340
- Include Python version and environment details in bug reports
341341

342-
## Scope and Limitations - Intraday Data Support
342+
## Intraday Data Support
343343

344-
This client explicitly does not implement intraday data endpoints (detailed
345-
heart rate, steps, etc). These endpoints:
344+
This client implements intraday data endpoints (detailed heart rate, steps, etc)
345+
through the `IntradayResource` class. These endpoints:
346346

347347
- Require special access from Fitbit (typically limited to research
348348
applications)
349349
- Have different rate limits than standard endpoints
350-
- Need additional OAuth2 scopes
351-
- Often require institutional review board (IRB) approval
352-
353-
If you need intraday data access:
354-
355-
1. Apply through Fitbit's developer portal
356-
2. Pull requests welcome!
350+
- Need additional OAuth2 scopes (specifically the 'activity' and 'heartrate'
351+
scopes)
352+
- Often require institutional review board (IRB) approval for research
353+
applications
354+
355+
To use intraday data:
356+
357+
1. Apply for intraday access through the
358+
[Fitbit developer portal](https://dev.fitbit.com/)
359+
2. Ensure your application requests the appropriate scopes
360+
3. Use the intraday methods with appropriate detail level parameters:
361+
```python
362+
client.intraday.get_heartrate_intraday_by_date(
363+
date="today",
364+
detail_level="1min" # or "1sec" depending on your access level
365+
)
366+
```
367+
368+
See the
369+
[Intraday API documentation](https://dev.fitbit.com/build/reference/web-api/intraday/)
370+
for more details on available endpoints and access requirements.

docs/ERROR_HANDLING.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# Exception Handling
2+
3+
The library implements a comprehensive exception system to help you handle
4+
errors effectively. Understanding these exceptions will help you write more
5+
robust code.
6+
7+
## Exception Hierarchy
8+
9+
```
10+
Exception
11+
├── ValueError
12+
│ └── ClientValidationException # Superclass for validations that take place before
13+
│ │ # making a request
14+
│ ├── InvalidDateException # Raised when a date string is not in the correct
15+
│ │ # format or not a valid calendar date
16+
│ ├── InvalidDateRangeException # Raised when a date range is invalid (e.g., end is
17+
│ │ # before start, exceeds max days)
18+
│ ├── PaginationException # Raised when pagination parameters are invalid
19+
│ ├── IntradayValidationException # Raised when intraday request parameters are invalid
20+
│ ├── ParameterValidationException # Raised when a parameter value is invalid
21+
│ │ # (e.g., negative when positive required)
22+
│ └── MissingParameterException # Raised when required parameters are missing or
23+
│ # parameter combinations are invalid
24+
25+
└── FitbitAPIException # Base exception for all Fitbit API errors
26+
27+
├── OAuthException # Superclass for all authentication flow exceptions
28+
│ ├── ExpiredTokenException # Raised when the OAuth token has expired
29+
│ ├── InvalidGrantException # Raised when the grant_type value is invalid
30+
│ ├── InvalidTokenException # Raised when the OAuth token is invalid
31+
│ └── InvalidClientException # Raised when the client_id is invalid
32+
33+
└── RequestException # Superclass for all API request exceptions
34+
├── InvalidRequestException # Raised when the request syntax is invalid
35+
├── AuthorizationException # Raised when there are authorization-related errors
36+
├── InsufficientPermissionsException # Raised when the application has insufficient permissions
37+
├── InsufficientScopeException # Raised when the application is missing a required scope
38+
├── NotFoundException # Raised when the requested resource does not exist
39+
├── RateLimitExceededException # Raised when the application hits rate limiting quotas
40+
├── SystemException # Raised when there is a system-level failure
41+
└── ValidationException # Raised when a request parameter is invalid or missing
42+
```
43+
44+
## Client Validation Exceptions
45+
46+
Client validation exceptions (`ClientValidationException` and its subclasses)
47+
are raised *before* any API call is made:
48+
49+
1. They reflect problems with your input parameters that can be detected locally
50+
2. No network requests have been initiated when these exceptions occur
51+
3. They help you fix issues before consuming API rate limits
52+
53+
```python
54+
from fitbit_client.exceptions import InvalidDateException, InvalidDateRangeException
55+
56+
try:
57+
client.sleep.get_sleep_log_by_date_range(
58+
start_date="2024-01-01",
59+
end_date="2023-12-31" # End date before start date
60+
)
61+
except InvalidDateRangeException as e:
62+
print(f"Date range error: {e.message}")
63+
print(f"Start date: {e.start_date}, End date: {e.end_date}")
64+
print(f"Resource: {e.resource_name}, Max days: {e.max_days}")
65+
```
66+
67+
### Common Client Validation Exceptions
68+
69+
- **InvalidDateException**: Raised when a date string is not valid
70+
- **InvalidDateRangeException**: Raised when a date range is invalid
71+
- **ParameterValidationException**: Raised when a parameter value is invalid
72+
- **MissingParameterException**: Raised when required parameters are missing
73+
- **PaginationException**: Raised when pagination parameters are invalid
74+
- **IntradayValidationException**: Raised when intraday request parameters are
75+
invalid
76+
77+
## API Exceptions
78+
79+
API exceptions (`FitbitAPIException` and its subclasses) are raised in response
80+
to errors returned by the Fitbit API:
81+
82+
```python
83+
from fitbit_client.exceptions import AuthorizationException, RateLimitExceededException
84+
85+
try:
86+
client.activity.get_lifetime_stats()
87+
except AuthorizationException as e:
88+
print(f"Auth error ({e.status_code}): {e.message}")
89+
# Handle authentication error (e.g., refresh token, prompt for re-auth)
90+
except RateLimitExceededException as e:
91+
retry_after = int(e.headers.get("Retry-After", 60))
92+
print(f"Rate limit exceeded. Retry after {retry_after} seconds")
93+
# Implement backoff strategy
94+
```
95+
96+
### Common API Exceptions
97+
98+
- **AuthorizationException**: Authentication or authorization issues
99+
- **InvalidRequestException**: Invalid request syntax or parameters
100+
- **RateLimitExceededException**: API rate limits exceeded
101+
- **NotFoundException**: Requested resource doesn't exist
102+
- **SystemException**: Fitbit API server-side errors
103+
104+
## Exception Properties
105+
106+
### Client Validation Exceptions
107+
108+
All client validation exceptions have these properties:
109+
110+
- `message`: Human-readable error description
111+
- `field_name`: Name of the invalid field (if applicable)
112+
113+
Specific validation exception types add additional properties:
114+
115+
- **InvalidDateException**: `date_str` (the invalid date string)
116+
- **InvalidDateRangeException**: `start_date`, `end_date`, `max_days`,
117+
`resource_name`
118+
- **IntradayValidationException**: `allowed_values`, `resource_name`
119+
120+
### API Exceptions
121+
122+
All API exceptions have these properties:
123+
124+
- `message`: Human-readable error description
125+
- `status_code`: HTTP status code (if applicable)
126+
- `error_type`: Type of error from the API
127+
- `field_name`: Name of the invalid field (for validation errors)
128+
- `headers`: Response headers (useful for rate limiting info)
129+
130+
## Usage Patterns
131+
132+
### Catching Specific Exceptions
133+
134+
Target specific exceptions for tailored error handling:
135+
136+
```python
137+
try:
138+
client.activity.create_activity_goals(
139+
period=ActivityGoalPeriod.DAILY,
140+
type=ActivityGoalType.STEPS,
141+
value=-1000
142+
)
143+
except ParameterValidationException as e:
144+
print(f"Invalid value for {e.field_name}: {e.message}")
145+
except AuthorizationException as e:
146+
print(f"Authorization error: {e.message}")
147+
except RateLimitExceededException as e:
148+
print(f"Rate limit error: {e.message}")
149+
```
150+
151+
### Catching Base Exception Classes
152+
153+
Catch base classes to handle related exceptions together:
154+
155+
```python
156+
try:
157+
client.activity.get_daily_activity_summary("today")
158+
except ClientValidationException as e:
159+
print(f"Invalid input: {e.message}") # Catches all input validation errors
160+
except OAuthException as e:
161+
print(f"OAuth error: {e.message}") # Catches all OAuth-related errors
162+
except FitbitAPIException as e:
163+
print(f"API error: {e.message}") # Catches all other API errors
164+
```
165+
166+
## Debugging APIs
167+
168+
Every method accepts a `debug` parameter that prints the equivalent cURL
169+
command:
170+
171+
```python
172+
client.activity.get_daily_activity_summary(
173+
date="today",
174+
debug=True
175+
)
176+
# Prints:
177+
# curl -X GET -H "Authorization: Bearer <token>" ...
178+
```
179+
180+
This helps troubleshoot API interactions by showing the exact request being
181+
made.

docs/LOGGING.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ The data logger uses INFO level for all entries, with a structured JSON format:
7979
```
8080

8181
As you can see, this is really just summary of the response body that makes it
82-
easy to get back in information you may not have captured in a one-off script.
82+
easy to get back information you may not have captured in a one-off script.
8383

84-
Note that the log will not be valid JSON file, but each line will be a valid
85-
object and it is be trivial to read it in at as `List[Dict[str, Any]]`.
84+
Note that the log will not be a valid JSON file, but each line will be a valid
85+
JSON object and it is trivial to read it in as `List[Dict[str, Any]]`.
8686

8787
## Important Fields
8888

@@ -129,6 +129,24 @@ data_logger.setLevel("INFO")
129129
data_logger.propagate = False # Prevent duplicate logging
130130
```
131131

132+
### Disabling Data Logging
133+
134+
If you don't need the data logging feature, you can disable it completely by
135+
setting the level to CRITICAL:
136+
137+
```python
138+
data_logger = getLogger("fitbit_client.data")
139+
data_logger.setLevel("CRITICAL") # Effectively disables data logging
140+
```
141+
142+
You can also disable it by not adding any handlers to the data logger:
143+
144+
```python
145+
data_logger = getLogger("fitbit_client.data")
146+
data_logger.propagate = False # Ensures logs don't propagate to parent loggers
147+
# No handlers added = no logging output
148+
```
149+
132150
## Error Logging
133151

134152
The client automatically logs all API errors with rich context including:
@@ -138,3 +156,8 @@ The client automatically logs all API errors with rich context including:
138156
- Affected resource/endpoint
139157
- Field-specific validation errors
140158
- Raw error response when available
159+
160+
## Cross-References
161+
162+
For more information on error handling, see
163+
[ERROR_HANDLING.md](ERROR_HANDLING.md).

0 commit comments

Comments
 (0)