Upgrading¶
How to update your code for each release with breaking changes, newest first. Every release's full list of changes is in the changelog.
A name the SDK removed raises an AttributeError that names its replacement, so running your code points at each change. To have a coding agent do the upgrade, give it the migration prompt in the release's section.
0.91¶
Upgrading¶
Removed names raise an AttributeError naming the replacement, so running your code points at
each change. The module-level functions moved the same way: sweatstack.get_activities() is
sweatstack.activities.list().
| 0.90 | 0.91 |
|---|---|
get_activities |
client.activities.list() |
get_activity |
client.activities.retrieve(activity_id) |
get_latest_activity |
client.activities.latest() |
get_activity_data |
client.activities.data(activity_id) |
get_activity_mean_max |
client.activities.mean_max(activity_id, metric=...) |
get_activity_awd |
client.activities.awd(activity_id) |
get_latest_activity_data |
client.activities.data(client.activities.latest().id) |
get_latest_activity_mean_max |
client.activities.mean_max(client.activities.latest().id, metric=...) |
get_longitudinal_data |
client.activities.longitudinal.data(...) |
get_longitudinal_mean_max |
client.activities.longitudinal.mean_max(...) |
get_longitudinal_awd |
client.activities.longitudinal.awd(...) |
upload |
client.activities.upload(files) |
get_backfill_status |
client.activities.backfill_status() |
watch_backfill_status |
client.activities.watch_backfill_status() |
set_activity_app_metadata |
client.activities.app_metadata.set(activity_id, data=...) |
delete_activity_app_metadata |
client.activities.app_metadata.delete(activity_id) |
get_traces |
client.traces.list() |
create_trace |
client.traces.create(...) |
update_trace |
client.traces.replace(trace_id, ...) |
delete_trace |
client.traces.delete(trace_id) |
set_trace_app_metadata |
client.traces.app_metadata.set(trace_id, data=...) |
delete_trace_app_metadata |
client.traces.app_metadata.delete(trace_id) |
get_tests |
client.tests.list() |
get_test |
client.tests.retrieve(test_id) |
create_test |
client.tests.create(...) |
update_test |
client.tests.replace(test_id, ...) |
delete_test |
client.tests.delete(test_id) |
set_test_app_metadata |
client.tests.app_metadata.set(test_id, data=...) |
delete_test_app_metadata |
client.tests.app_metadata.delete(test_id) |
get_dailies |
client.dailies.list(measure, start=..., end=...) |
set_daily |
client.dailies.set(measure, date=..., value=...) |
delete_daily |
client.dailies.delete(measure, date=...) |
get_profile_status |
client.profile.status() |
get_sports |
client.profile.sports() |
get_tags |
client.profile.tags() |
set_user_app_metadata |
client.profile.app_metadata.set(data=...) |
delete_user_app_metadata |
client.profile.app_metadata.delete() |
get_users |
client.users.list() |
get_user |
client.users.list(name=...): every match, so check the length |
create_user |
client.users.create(first_name=...) |
get_teams |
client.teams.list() |
get_team_users |
client.teams.users(team_id) |
get_team_user |
client.teams.users(team_id, name=...): every match |
get_authorized_teams |
client.teams.authorized() |
authorize_team |
client.teams.authorize(team_id) |
create_portal_session |
client.portal.sessions.create(destination) |
get_userinfo |
client.oauth.userinfo() |
get_authorization_url |
client.oauth.authorization_url(...) |
exchange_code_for_token |
client.oauth.exchange_code(...) |
generate_pkce_params |
client.oauth.generate_pkce_params() |
switch_user |
client.delegated_client(user): a new client; this one is left unchanged |
switch_back |
keep the original client, or client.principal_client() |
client.jwt |
client.api_key |
Changes that a rename alone doesn't cover. Most raise a TypeError naming the argument; the
ones marked silent don't fail loudly, so check for them.
| 0.90 | 0.91 |
|---|---|
sports=["cycling"] (every filter, and StreamlitAuth.select_activity) |
sport="cycling" or sport=["cycling", "running"] |
get_activity_mean_max(id, "power"), get_activity_awd(id, "power") |
activities.mean_max(id, metric="power"), activities.awd(id, metric="power") |
get_activity_data(id, "power", ["power"]) |
activities.data(id, segmentation_on="power", metrics=["power"]) |
create_user("Carla", "Smith") |
users.create(first_name="Carla", last_name="Smith") |
get_sports(True), authorize_team(id, scopes) |
profile.sports(only_root=True), teams.authorize(id, scopes=scopes) |
Positional arguments to get_authorization_url() / exchange_code_for_token() |
Keywords: oauth.authorization_url(client_id=..., ...) |
get_latest_activity(start=, end=, tag=) |
activities.latest(sport=); for the rest, activities.list(start=..., end=..., tags=..., limit=1) |
get_latest_activity() raising StopIteration when there is none |
Silent: activities.latest() returns None; check before using .id |
get_longitudinal_*(date=..., window_days=...) |
start= and end= |
get_longitudinal_*(...) without sport |
sport= is required (the API already rejected a request without one) |
upload(files, sport=...) |
activities.upload(files): no sport=; a CSV needs a sport column |
upload(...) returning a dict |
Silent: activities.upload(...) returns list[SourceResponse]; read .status / .error |
exchange_code_for_token(..., redirect_uri=...) |
oauth.exchange_code(...) without redirect_uri= |
get_user("Carla") returning one UserSummary |
Silent: users.list(name="Carla") returns a list, every match; search_mode= is gone |
switch_user("Carla") (a name) |
client.delegated_client(users.list(name="Carla")[0]): a name is not accepted |
client.jwt |
client.api_key |
sweatlab, sweatshell, pip install "sweatstack[jupyter]" |
uv add "sweatstack[pandas]" jupyterlab; sweatstack.authenticate() in the first cell |
New defaults that change behaviour without changing code: GET, PUT and DELETE requests are
retried (Client(max_retries=0) restores single attempts), and requests time out after 60 s
(Client(timeout=...)).
Migration prompt. Paste this into your coding agent:
Upgrade this codebase to sweatstack 0.91, which moved every method to a resource namespace.
The full upgrade guide, with both tables, is the "Upgrading" section of the 0.91.0 entry in
https://github.com/SweatStack/sweatstack-python/blob/main/CHANGELOG.md
(also at https://docs.sweatstack.no/learn/python/upgrading/). Read it first.
Find every use of the sweatstack client (a Client instance, the sweatstack module, and
StreamlitAuth or FastAPI user clients) and:
1. Rename calls per the first table, e.g. get_activities() -> activities.list(),
get_activity_data(id) -> activities.data(id),
get_longitudinal_mean_max(...) -> activities.longitudinal.mean_max(...),
update_trace(id, ...) -> traces.replace(id, ...), get_users() -> users.list().
2. Apply every row of the second table. In particular:
- sports= -> sport= (one value or a list).
- Pass by keyword: metric= (mean_max, awd), segmentation_on= and metrics= (data),
first_name= and last_name= (users.create), only_root= (profile.sports),
scopes= (teams.authorize), and all arguments of oauth.authorization_url() and
oauth.exchange_code().
- Longitudinal methods: sport= is required, and date=/window_days= become start=/end=
(datetime.date objects).
- activities.latest() takes only sport= and returns None when there is no activity:
handle None.
- activities.upload() takes no sport= (a CSV needs a sport column) and returns
list[SourceResponse], not a dict.
- oauth.exchange_code() takes no redirect_uri=.
- get_user(x) -> users.list(name=x), which returns a list of every match.
- switch_user(user) -> athlete = client.delegated_client(user_id_or_summary); use that
new client for the athlete's calls. It doesn't accept a name: look the user up first.
switch_back() -> keep using the original client.
- client.jwt -> client.api_key.
3. Replace get_latest_activity_data(...) with activities.data(activities.latest().id, ...),
after checking that latest() returned an activity.
4. If the project used sweatlab, sweatshell or the [jupyter] extra, depend on
"sweatstack[pandas]" (or [polars]) and jupyterlab instead.
Then run the code and the tests. Fix any AttributeError (its message names the replacement)
and TypeError (a renamed or keyword-only argument). Do not add compatibility shims.