Skip to content

Commit c468066

Browse files
committed
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 642d7f2 commit c468066

26 files changed

+1224
-647
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ coverage.xml
4444
htmlcov/
4545
.pytest_cache/
4646
.mypy_cache/
47+
*,cover
4748

4849
# Mac
4950
.DS_Store
@@ -57,3 +58,5 @@ _scripts
5758
_cov_html
5859
secrets.json
5960
tokens.json
61+
TODO.mdø
62+

README.md

Lines changed: 98 additions & 38 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,63 +62,109 @@ 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

62-
## Authentication Methods
65+
## Method Aliases
6366

64-
### 1. Automatic (Recommended)
65-
66-
Uses a local callback server to automatically handle the OAuth2 flow:
67+
All resource methods are available directly from the client instance. This means
68+
you can use:
6769

6870
```python
69-
client = FitbitClient(
70-
client_id="YOUR_CLIENT_ID",
71-
client_secret="YOUR_CLIENT_SECRET",
72-
redirect_uri="https://localhost:8080",
73-
use_callback_server=True # default is True
74-
)
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+
```
7576

76-
# Will open browser and handle callback automatically
77-
client.authenticate()
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")
7884
```
7985

80-
### 2. Manual URL Copy/Paste
86+
Both approaches are equivalent, but aliases provide a more concise syntax.
8187

82-
If you prefer not to use a local server:
88+
## Authentication
89+
90+
Uses a local callback server to automatically handle the OAuth2 flow:
8391

8492
```python
8593
client = FitbitClient(
8694
client_id="YOUR_CLIENT_ID",
8795
client_secret="YOUR_CLIENT_SECRET",
8896
redirect_uri="YOUR_REGISTERED_REDIRECT_URI",
89-
token_cache_path="/tmp/fb_tokens.json",
90-
use_callback_server=True
97+
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
91100
)
92101

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`)
102+
# Will open browser and handle callback automatically
96103
client.authenticate()
97104
```
98105

106+
The `token_cache_path` parameter allows you to persist authentication tokens
107+
between sessions. If provided, the client will:
108+
109+
1. Load existing tokens from this file if available (avoiding re-authentication)
110+
111+
2. Save new or refreshed tokens to this file automatically
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
122+
99123
## Setting Up Your Fitbit App
100124

101125
1. Go to dev.fitbit.com and create a new application
102126
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
106-
4. Copy your Client ID and Client Secret
107-
108-
Additional documentation:
109-
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).
127+
3. Set Callback URL to "https://localhost:8080" (or your preferred local URL)
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
149+
150+
## Additional Documentation
151+
152+
### For API Library Users
153+
154+
- [LOGGING.md](docs/LOGGING.md): Understanding the dual-logger system
155+
- [TYPES.md](docs/TYPES.md): JSON type system and method return types
156+
- [NAMING.md](docs/NAMING.md): API method naming conventions
157+
- [VALIDATIONS.md](docs/VALIDATIONS.md): Input parameter validation
158+
- [ERROR_HANDLING.md](docs/ERROR_HANDLING.md): Exception hierarchy and handling
159+
160+
It's also worth reviewing
161+
[Fitbit's Best Practices](https://dev.fitbit.com/build/reference/web-api/developer-guide/best-practices/)
162+
for API usage.
163+
164+
### Project Best Practices
165+
166+
- [DEVELOPMENT.md](docs/DEVELOPMENT.md): Development environment and guidelines
167+
- [STYLE.md](docs/STYLE.md): Code style and formatting standards
119168

120169
## Important Note - Subscription Support
121170

@@ -124,9 +173,20 @@ This client does not currently support the
124173
and
125174
[deletion](https://dev.fitbit.com/build/reference/web-api/subscription/delete-subscription/)
126175
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.
176+
[webhook subscriptions](https://dev.fitbit.com/build/reference/web-api/developer-guide/using-subscriptions/).
177+
The methods are implemented in comments and should work, but I have not had a
178+
chance to verify them since this requires a publicly accessible server to
179+
receive webhook notifications.
180+
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+
188+
If you're using this library with subscriptions and would like to help test and
189+
implement this functionality, please open an issue or pull request!
130190

131191
## License
132192

TODO.md

Lines changed: 12 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,31 @@
11
# Project TODO and Notes
22

3-
## Refactoring TODOs
3+
## TODOs:
44

5-
- Typing
5+
- PyPi deployment
66

7-
- Try to get rid of `Optional[Dict[str, Any]]` args
7+
- For all `create_...`methods, add the ID from the response to logs and maybe
8+
something human readable, like the first n characters of the name??. Right
9+
now:
10+
11+
```log
12+
[2025-02-05 06:09:34,828] INFO [fitbit_client.NutritionResource] create_food_log succeeded for foods/log.json (status 201)
13+
```
814

915
- base.py: reorganize and see what we can move out.
1016

1117
- Rename to `_base`? Files it first, makes it clearer that everything in it is
1218
private
13-
- Move the methods for building `curl` commands into a mixin? It's a lot of
14-
code for an isolated and tightly scoped feature.
15-
- refactor `_make_request`.
16-
- do we need both `data` and `json`? Also, could we simplify a lot of typing
17-
if we separated GET, POST, and DELETE methods? Maybe even a separate,
18-
second non-auth GET? Could use `@overload`
19-
- we had to makee a `ParamDict` type in `nutrition.py`. Use this everywhere?
20-
- start by looking at how many methods use which params
2119

2220
- client.py:
2321

2422
- Creat and Test that all methods have an alias in `Client` and that the
2523
signatures match
2624

27-
```python
28-
if not food_id and not (food_name and calories):
29-
raise ClientValidationException(
30-
"Must provide either food_id or (food_name and calories)"
31-
)
32-
```
33-
34-
- nutrition.py:
35-
- It doesn't seem like this should be passing tests when CALORIES is not an int:
25+
- CI:
3626

37-
```python
38-
# Handle both enum and string nutritional values
39-
for key, value in nutritional_values.items():
40-
if isinstance(key, NutritionalValue):
41-
params[key.value] = float(value)
42-
else:
43-
params[str(key)] = float(value)
44-
```
45-
46-
see: test_create_food_calories_from_fat_must_be_integer(nutrition_resource)
27+
* Read and implement:
28+
https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/configuring-advanced-setup-for-code-scanning#configuring-advanced-setup-for-code-scanning-with-codeql
4729

4830
- exceptions.py Consider:
4931
- Add automatic token refresh for ExpiredTokenException
@@ -77,14 +59,6 @@ see: test_create_food_calories_from_fat_must_be_integer(nutrition_resource)
7759
be reused.
7860
- We may need a public version of a generic `make_request` method.
7961

80-
- For all `create_...`methods, add the ID from the response to logs and maybe
81-
something human readable, like the first n characters of the name??. Right
82-
now:
83-
84-
```log
85-
[2025-02-05 06:09:34,828] INFO [fitbit_client.NutritionResource] create_food_log succeeded for foods/log.json (status 201)
86-
```
87-
8862
- Form to change scopes are part of OAuth flow? Maybe get rid of the cut and
8963
paste method altogether? It's less to test...
9064

@@ -101,19 +75,4 @@ see: test_create_food_calories_from_fat_must_be_integer(nutrition_resource)
10175
one. (there might be several of these that make sense--just take an ID and
10276
then the signature of the "create" method).
10377

104-
- PyPI deployment
105-
10678
- Enum for units? (it'll be big, maybe just common ones?)
107-
108-
## CI/CD/Linting
109-
110-
- GitHub Actions Setup
111-
112-
- Linting
113-
- black
114-
- isort
115-
- mdformat
116-
- mypy
117-
- Test running (TBD)
118-
- Coverage reporting (TBD)
119-
- Automated PyPI deployment

0 commit comments

Comments
 (0)