Skip to content

Commit c505bbd

Browse files
authored
Docs (#14)
* Update and streamline README * 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 5ecc6e1 commit c505bbd

File tree

9 files changed

+603
-468
lines changed

9 files changed

+603
-468
lines changed

README.md

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -59,63 +59,54 @@ The response will always be the body of the API response, and is almost always a
5959
`Dict`, `List` or `None`. `nutrition.get_activity_tcx` is the exception. It
6060
returns XML (as a `str`).
6161

62-
## Authentication Methods
63-
64-
### 1. Automatic (Recommended)
62+
## Authentication
6563

6664
Uses a local callback server to automatically handle the OAuth2 flow:
6765

6866
```python
6967
client = FitbitClient(
7068
client_id="YOUR_CLIENT_ID",
7169
client_secret="YOUR_CLIENT_SECRET",
72-
redirect_uri="https://localhost:8080",
73-
use_callback_server=True # default is True
70+
redirect_uri="YOUR_REGISTERED_REDIRECT_URI",
71+
token_cache_path="/tmp/fb_tokens.json" # Optional: saves tokens between sessions
7472
)
7573

7674
# Will open browser and handle callback automatically
7775
client.authenticate()
7876
```
7977

80-
### 2. Manual URL Copy/Paste
81-
82-
If you prefer not to use a local server:
78+
The `token_cache_path` parameter allows you to persist authentication tokens
79+
between sessions. If provided, the client will:
8380

84-
```python
85-
client = FitbitClient(
86-
client_id="YOUR_CLIENT_ID",
87-
client_secret="YOUR_CLIENT_SECRET",
88-
redirect_uri="YOUR_REGISTERED_REDIRECT_URI",
89-
token_cache_path="/tmp/fb_tokens.json",
90-
use_callback_server=True
91-
)
92-
93-
# Will open a browser and start a server to complete the flow (default), or
94-
# prompt you on the command line to copy/paste the callback URL from the
95-
# browser (see `use_callback_server`)
96-
client.authenticate()
97-
```
81+
1. Load existing tokens from this file if available (avoiding re-authentication)
82+
2. Save new or refreshed tokens to this file automatically
83+
3. Handle token refresh when expired tokens are detected
9884

9985
## Setting Up Your Fitbit App
10086

10187
1. Go to dev.fitbit.com and create a new application
10288
2. Set OAuth 2.0 Application Type to "Personal"
103-
3. Set Callback URL to:
104-
- For automatic method: "https://localhost:8080"
105-
- For manual method: Your preferred redirect URI
89+
3. Set Callback URL to "https://localhost:8080" (or your preferred local URL)
10690
4. Copy your Client ID and Client Secret
10791

108-
Additional documentation:
92+
## Additional Documentation
93+
94+
### For API Library Users
10995

110-
- To understand the logging implemementation, see [LOGGING](docs/LOGGING.md)
111-
- To understand validations and the exception hierarchy, see
112-
[VALIDATIONS_AND_EXCEPTIONS](docs/VALIDATIONS_AND_EXCEPTIONS.md)
113-
- It's work checking out
114-
[Fitbit's Best Practices](https://dev.fitbit.com/build/reference/web-api/developer-guide/best-practices/)
115-
- For some general development guidelines, see
116-
[DEVELOPMENT](docs/DEVELOPMENT.md).
117-
- For style guidelines (mostly enforced through varius linters and formatters)
118-
see [STYLE](docs/STYLE.md).
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
119110

120111
## Important Note - Subscription Support
121112

@@ -124,9 +115,13 @@ This client does not currently support the
124115
and
125116
[deletion](https://dev.fitbit.com/build/reference/web-api/subscription/delete-subscription/)
126117
of
127-
[webhook subscrptions](https://dev.fitbit.com/build/reference/web-api/developer-guide/using-subscriptions/).
128-
The methods are implemented in comments and _should_ work, but I have not had a
129-
chance to verify a user confirm this.
118+
[webhook subscriptions](https://dev.fitbit.com/build/reference/web-api/developer-guide/using-subscriptions/).
119+
The methods are implemented in comments and should work, but I have not had a
120+
chance to verify them since this requires a publicly accessible server to
121+
receive webhook notifications.
122+
123+
If you're using this library with subscriptions and would like to help test and
124+
implement this functionality, please open an issue or pull request!
130125

131126
## License
132127

TODO.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@
22

33
## TODOs:
44

5+
- Create and Test that all methods have an alias in `Client` and that the
6+
signatures match
7+
8+
- Improve README for end users:
9+
10+
- Add more common use cases examples beyond basic profile retrieval
11+
- Explain token persistence between sessions (DONE)
12+
- Provide overview of available resources/endpoints
13+
- Verify correct callback URI guidance (check if "https://localhost:8080" is
14+
actually the correct/optimal value to recommend)
15+
16+
- ✅ Review and improve all documentation files in docs/ from an end-user
17+
perspective
18+
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
25+
526
- PyPi deployment
627

728
- For all `create_...`methods, add the ID from the response to logs and maybe
@@ -17,11 +38,6 @@
1738
- Rename to `_base`? Files it first, makes it clearer that everything in it is
1839
private
1940

20-
- client.py:
21-
22-
- Creat and Test that all methods have an alias in `Client` and that the
23-
signatures match
24-
2541
- CI:
2642

2743
* 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.

0 commit comments

Comments
 (0)