Skip to content

Commit 1c9d5b7

Browse files
authored
Corruption cleanup; merges a few commits:
Corruption cleanup; merges a few commits: - Ignore TODO - Bring back resource method aliases - 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 c505bbd commit 1c9d5b7

File tree

5 files changed

+333
-24
lines changed

5 files changed

+333
-24
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,5 @@ _scripts
5858
_cov_html
5959
secrets.json
6060
tokens.json
61+
TODO.mdø
62+

README.md

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ try:
4848
client.authenticate()
4949

5050
# Make a request (e.g., get user profile)
51+
# You can access resources directly:
5152
profile = client.user.get_profile()
53+
# Or use method aliases for shorter syntax:
54+
profile = client.get_profile()
5255
print(dumps(profile, indent=2))
5356

5457
except Exception as e:
@@ -59,6 +62,29 @@ The response will always be the body of the API response, and is almost always a
5962
`Dict`, `List` or `None`. `nutrition.get_activity_tcx` is the exception. It
6063
returns XML (as a `str`).
6164

65+
## Method Aliases
66+
67+
All resource methods are available directly from the client instance. This means
68+
you can use:
69+
70+
```python
71+
# Short form with method aliases
72+
client.get_profile()
73+
client.get_daily_activity_summary(date="2025-03-06")
74+
client.get_sleep_log_by_date(date="2025-03-06")
75+
```
76+
77+
Instead of the longer form:
78+
79+
```python
80+
# Standard resource access
81+
client.user.get_profile()
82+
client.activity.get_daily_activity_summary(date="2025-03-06")
83+
client.sleep.get_sleep_log_by_date(date="2025-03-06")
84+
```
85+
86+
Both approaches are equivalent, but aliases provide a more concise syntax.
87+
6288
## Authentication
6389

6490
Uses a local callback server to automatically handle the OAuth2 flow:
@@ -69,6 +95,8 @@ client = FitbitClient(
6995
client_secret="YOUR_CLIENT_SECRET",
7096
redirect_uri="YOUR_REGISTERED_REDIRECT_URI",
7197
token_cache_path="/tmp/fb_tokens.json" # Optional: saves tokens between sessions
98+
redirect_uri="YOUR_REGISTERED_REDIRECT_URI",
99+
token_cache_path="/tmp/fb_tokens.json" # Optional: saves tokens between sessions
72100
)
73101

74102
# Will open browser and handle callback automatically
@@ -79,15 +107,45 @@ The `token_cache_path` parameter allows you to persist authentication tokens
79107
between sessions. If provided, the client will:
80108

81109
1. Load existing tokens from this file if available (avoiding re-authentication)
110+
82111
2. Save new or refreshed tokens to this file automatically
83-
3. Handle token refresh when expired tokens are detected
112+
113+
3. Handle token refresh when expired tokens are detected The `token_cache_path`
114+
parameter allows you to persist authentication tokens between sessions. If
115+
provided, the client will:
116+
117+
4. Load existing tokens from this file if available (avoiding re-authentication)
118+
119+
5. Save new or refreshed tokens to this file automatically
120+
121+
6. Handle token refresh when expired tokens are detected
84122

85123
## Setting Up Your Fitbit App
86124

87125
1. Go to dev.fitbit.com and create a new application
88126
2. Set OAuth 2.0 Application Type to "Personal"
89127
3. Set Callback URL to "https://localhost:8080" (or your preferred local URL)
90-
4. Copy your Client ID and Client Secret
128+
4. Set Callback URL to "https://localhost:8080" (or your preferred local URL)
129+
5. Copy your Client ID and Client Secret
130+
131+
## Additional Documentation
132+
133+
### For API Library Users
134+
135+
- [LOGGING.md](docs/LOGGING.md): Understanding the dual-logger system
136+
- [TYPES.md](docs/TYPES.md): JSON type system and method return types
137+
- [NAMING.md](docs/NAMING.md): API method naming conventions
138+
- [VALIDATIONS.md](docs/VALIDATIONS.md): Input parameter validation
139+
- [ERROR_HANDLING.md](docs/ERROR_HANDLING.md): Exception hierarchy and handling
140+
141+
It's also worth reviewing
142+
[Fitbit's Best Practices](https://dev.fitbit.com/build/reference/web-api/developer-guide/best-practices/)
143+
for API usage.
144+
145+
### Project Best Practices
146+
147+
- [DEVELOPMENT.md](docs/DEVELOPMENT.md): Development environment and guidelines
148+
- [STYLE.md](docs/STYLE.md): Code style and formatting standards
91149

92150
## Additional Documentation
93151

@@ -120,6 +178,13 @@ The methods are implemented in comments and should work, but I have not had a
120178
chance to verify them since this requires a publicly accessible server to
121179
receive webhook notifications.
122180

181+
If you're using this library with subscriptions and would like to help test and
182+
implement this functionality, please open an issue or pull request!
183+
[webhook subscriptions](https://dev.fitbit.com/build/reference/web-api/developer-guide/using-subscriptions/).
184+
The methods are implemented in comments and should work, but I have not had a
185+
chance to verify them since this requires a publicly accessible server to
186+
receive webhook notifications.
187+
123188
If you're using this library with subscriptions and would like to help test and
124189
implement this functionality, please open an issue or pull request!
125190

TODO.md

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,6 @@
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-
265
- PyPi deployment
276

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

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

4327
* Read and implement:

docs/DEVELOPMENT.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
- [Logging System](#logging-system)
1717
- [Application Logger](#application-logger)
1818
- [Data Logger](#data-logger)
19+
- [API Design](#api-design)
20+
- [Resource-Based API](#resource-based-api)
21+
- [Method Aliases](#method-aliases)
1922
- [Testing](#testing)
2023
- [Test Organization](#test-organization)
2124
- [Standard Test Fixtures](#standard-test-fixtures)
@@ -235,6 +238,63 @@ Data log entries contain:
235238
This logging system provides both operational visibility through the application
236239
logger and structured data capture through the data logger.
237240

241+
## API Design
242+
243+
The client implements a dual-level API design pattern that balances both
244+
organization and ease-of-use.
245+
246+
### Resource-Based API
247+
248+
The primary API structure is resource-based, organizing related endpoints into
249+
dedicated resource classes:
250+
251+
- `client.user` - User profile and badges endpoints
252+
- `client.activity` - Activity tracking, goals, and summaries
253+
- `client.sleep` - Sleep logs and goals
254+
- etc.
255+
256+
This organization provides a clean separation of concerns and makes the code
257+
more maintainable by grouping related functionality.
258+
259+
### Method Aliases
260+
261+
To improve developer experience, all resource methods are also available
262+
directly from the client instance through aliases. This means developers can
263+
choose between two equivalent approaches:
264+
265+
```python
266+
# Standard resource-based access
267+
client.user.get_profile()
268+
client.activity.get_daily_activity_summary(date="2025-03-06")
269+
270+
# Direct access via method aliases
271+
client.get_profile()
272+
client.get_daily_activity_summary(date="2025-03-06")
273+
```
274+
275+
#### Rationale for Method Aliases
276+
277+
Method aliases were implemented for several important reasons:
278+
279+
1. **Reduced Verbosity**: Typing `client.resource_name.method_name(...)` with
280+
many parameters can be tedious, especially when used frequently.
281+
282+
2. **Flatter API Surface**: Many modern APIs prefer a flatter design that avoids
283+
deep nesting, making the API more straightforward to use.
284+
285+
3. **Method Name Uniqueness**: All resource methods in the Fitbit API have
286+
unique names (e.g., there's only one `get_profile()` method), making it safe
287+
to expose these methods directly on the client.
288+
289+
4. **Preserve Both Options**: By maintaining both the resource-based access and
290+
direct aliases, developers can choose the approach that best fits their needs
291+
\- organization or conciseness.
292+
293+
All method aliases are set up in the `_setup_method_aliases()` method in the
294+
`FitbitClient` class, which is called during initialization. Each alias is a
295+
direct reference to the corresponding resource method, ensuring consistent
296+
behavior regardless of how the method is accessed.
297+
238298
## Testing
239299

240300
The project uses pytest for testing and follows a consistent testing approach

0 commit comments

Comments
 (0)