sweatstack 0.32.0__tar.gz → 0.34.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sweatstack-0.32.0 → sweatstack-0.34.0}/PKG-INFO +1 -1
- {sweatstack-0.32.0 → sweatstack-0.34.0}/pyproject.toml +1 -1
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/client.py +29 -27
- {sweatstack-0.32.0 → sweatstack-0.34.0}/.gitignore +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/.python-version +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/DEVELOPMENT.md +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/Makefile +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/README.md +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/playground/.ipynb_checkpoints/Untitled-checkpoint.ipynb +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/playground/README.md +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/playground/Sweat Stack examples/Getting started.ipynb +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/playground/Untitled.ipynb +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/playground/hello.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/playground/pyproject.toml +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/Sweat Stack examples/Getting started.ipynb +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/__init__.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/cli.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/constants.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/ipython_init.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/jupyterlab_oauth2_startup.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/openapi_schemas.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/py.typed +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/schemas.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/streamlit.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/sweatshell.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/utils.py +0 -0
- {sweatstack-0.32.0 → sweatstack-0.34.0}/uv.lock +0 -0
|
@@ -115,7 +115,7 @@ class OAuth2Mixin:
|
|
|
115
115
|
data=token_data,
|
|
116
116
|
)
|
|
117
117
|
try:
|
|
118
|
-
|
|
118
|
+
self._raise_for_status(response)
|
|
119
119
|
except httpx.HTTPStatusError as e:
|
|
120
120
|
raise Exception(f"SweatStack Python login failed. Please try again.") from e
|
|
121
121
|
token_response = response.json()
|
|
@@ -142,7 +142,7 @@ class DelegationMixin:
|
|
|
142
142
|
"/api/v1/oauth/delegated-token",
|
|
143
143
|
json={"sub": user_id},
|
|
144
144
|
)
|
|
145
|
-
|
|
145
|
+
self._raise_for_status(response)
|
|
146
146
|
|
|
147
147
|
return response.json()
|
|
148
148
|
|
|
@@ -156,7 +156,7 @@ class DelegationMixin:
|
|
|
156
156
|
response = client.get(
|
|
157
157
|
"/api/v1/oauth/principal-token",
|
|
158
158
|
)
|
|
159
|
-
|
|
159
|
+
self._raise_for_status(response)
|
|
160
160
|
return response.json()
|
|
161
161
|
|
|
162
162
|
def switch_back(self):
|
|
@@ -207,7 +207,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
207
207
|
},
|
|
208
208
|
)
|
|
209
209
|
|
|
210
|
-
|
|
210
|
+
self._raise_for_status(response)
|
|
211
211
|
return response.json()["access_token"]
|
|
212
212
|
|
|
213
213
|
def _check_token_expiry(self, token: str) -> str:
|
|
@@ -287,6 +287,12 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
287
287
|
with httpx.Client(base_url=self.url, headers=headers) as client:
|
|
288
288
|
yield client
|
|
289
289
|
|
|
290
|
+
def _raise_for_status(self, response: httpx.Response):
|
|
291
|
+
if response.status_code == 422:
|
|
292
|
+
raise ValueError(response.json())
|
|
293
|
+
else:
|
|
294
|
+
response.raise_for_status()
|
|
295
|
+
|
|
290
296
|
def _enums_to_strings(self, values: list[Enum | str]) -> list[str]:
|
|
291
297
|
return [value.value if isinstance(value, Enum) else value for value in values]
|
|
292
298
|
|
|
@@ -320,7 +326,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
320
326
|
url="/api/v1/activities/",
|
|
321
327
|
params=params,
|
|
322
328
|
)
|
|
323
|
-
|
|
329
|
+
self._raise_for_status(response)
|
|
324
330
|
activities = response.json()
|
|
325
331
|
for activity in activities:
|
|
326
332
|
yield ActivitySummary.model_validate(activity)
|
|
@@ -386,7 +392,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
386
392
|
def get_activity(self, activity_id: str) -> ActivityDetails:
|
|
387
393
|
with self._http_client() as client:
|
|
388
394
|
response = client.get(url=f"/api/v1/activities/{activity_id}")
|
|
389
|
-
|
|
395
|
+
self._raise_for_status(response)
|
|
390
396
|
return ActivityDetails.model_validate(response.json())
|
|
391
397
|
|
|
392
398
|
def get_activity_data(
|
|
@@ -403,8 +409,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
403
409
|
url=f"/api/v1/activities/{activity_id}/data",
|
|
404
410
|
params=params,
|
|
405
411
|
)
|
|
406
|
-
|
|
407
|
-
response.raise_for_status()
|
|
412
|
+
self._raise_for_status(response)
|
|
408
413
|
|
|
409
414
|
df = pd.read_parquet(BytesIO(response.content))
|
|
410
415
|
return self._postprocess_dataframe(df)
|
|
@@ -412,7 +417,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
412
417
|
def get_activity_mean_max(
|
|
413
418
|
self,
|
|
414
419
|
activity_id: str,
|
|
415
|
-
metric: Metric |
|
|
420
|
+
metric: Literal[Metric.power, Metric.speed] | Literal["power", "speed"],
|
|
416
421
|
adaptive_sampling: bool = False,
|
|
417
422
|
) -> pd.DataFrame:
|
|
418
423
|
metric = self._enums_to_strings([metric])[0]
|
|
@@ -424,7 +429,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
424
429
|
"adaptive_sampling": adaptive_sampling,
|
|
425
430
|
},
|
|
426
431
|
)
|
|
427
|
-
|
|
432
|
+
self._raise_for_status(response)
|
|
428
433
|
df = pd.read_parquet(BytesIO(response.content))
|
|
429
434
|
return self._postprocess_dataframe(df)
|
|
430
435
|
|
|
@@ -438,7 +443,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
438
443
|
|
|
439
444
|
def get_latest_activity_mean_max(
|
|
440
445
|
self,
|
|
441
|
-
metric: Metric |
|
|
446
|
+
metric: Literal[Metric.power, Metric.speed] | Literal["power", "speed"],
|
|
442
447
|
sport: Sport | str | None = None,
|
|
443
448
|
adaptive_sampling: bool = False,
|
|
444
449
|
) -> pd.DataFrame:
|
|
@@ -453,7 +458,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
453
458
|
start: date | str,
|
|
454
459
|
end: date | str | None = None,
|
|
455
460
|
metrics: list[Metric | str] | None = None,
|
|
456
|
-
adaptive_sampling_on: Literal["power", "speed"] | None = None,
|
|
461
|
+
adaptive_sampling_on: Literal[Metric.power, Metric.speed] | Literal["power", "speed"] | None = None,
|
|
457
462
|
) -> pd.DataFrame:
|
|
458
463
|
if sport and sports:
|
|
459
464
|
raise ValueError("Cannot specify both sport and sports")
|
|
@@ -462,26 +467,23 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
462
467
|
elif sports is None:
|
|
463
468
|
sports = []
|
|
464
469
|
|
|
465
|
-
sports = self._enums_to_strings(sports)
|
|
466
|
-
metrics = self._enums_to_strings(metrics)
|
|
467
|
-
|
|
468
470
|
params = {
|
|
469
|
-
"sports": sports,
|
|
470
|
-
"start": start
|
|
471
|
+
"sports": self._enums_to_strings(sports),
|
|
472
|
+
"start": start
|
|
471
473
|
}
|
|
472
474
|
if end is not None:
|
|
473
475
|
params["end"] = end
|
|
474
476
|
if metrics is not None:
|
|
475
|
-
params["metrics"] = metrics
|
|
477
|
+
params["metrics"] = self._enums_to_strings(metrics)
|
|
476
478
|
if adaptive_sampling_on is not None:
|
|
477
|
-
params["adaptive_sampling_on"] = adaptive_sampling_on
|
|
479
|
+
params["adaptive_sampling_on"] = self._enums_to_strings([adaptive_sampling_on])[0]
|
|
478
480
|
|
|
479
481
|
with self._http_client() as client:
|
|
480
482
|
response = client.get(
|
|
481
483
|
url="/api/v1/activities/longitudinal-data",
|
|
482
484
|
params=params,
|
|
483
485
|
)
|
|
484
|
-
|
|
486
|
+
self._raise_for_status(response)
|
|
485
487
|
|
|
486
488
|
df = pd.read_parquet(BytesIO(response.content))
|
|
487
489
|
return self._postprocess_dataframe(df)
|
|
@@ -490,7 +492,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
490
492
|
self,
|
|
491
493
|
*,
|
|
492
494
|
sport: Sport | str,
|
|
493
|
-
metric: Metric |
|
|
495
|
+
metric: Literal[Metric.power, Metric.speed] | Literal["power", "speed"],
|
|
494
496
|
date: date | str | None = None,
|
|
495
497
|
window_days: int | None = None,
|
|
496
498
|
) -> pd.DataFrame:
|
|
@@ -511,7 +513,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
511
513
|
url="/api/v1/activities/longitudinal-mean-max",
|
|
512
514
|
params=params,
|
|
513
515
|
)
|
|
514
|
-
|
|
516
|
+
self._raise_for_status(response)
|
|
515
517
|
|
|
516
518
|
df = pd.read_parquet(BytesIO(response.content))
|
|
517
519
|
return self._postprocess_dataframe(df)
|
|
@@ -546,7 +548,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
546
548
|
url="/api/v1/traces/",
|
|
547
549
|
params=params,
|
|
548
550
|
)
|
|
549
|
-
|
|
551
|
+
self._raise_for_status(response)
|
|
550
552
|
traces = response.json()
|
|
551
553
|
for trace in traces:
|
|
552
554
|
yield TraceDetails.model_validate(trace)
|
|
@@ -645,7 +647,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
645
647
|
"tags": tags,
|
|
646
648
|
},
|
|
647
649
|
)
|
|
648
|
-
|
|
650
|
+
self._raise_for_status(response)
|
|
649
651
|
return TraceDetails.model_validate(response.json())
|
|
650
652
|
|
|
651
653
|
def get_sports(self, only_root: bool = False) -> list[Sport]:
|
|
@@ -654,7 +656,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
654
656
|
url="/api/v1/profile/sports/",
|
|
655
657
|
params={"only_root": only_root},
|
|
656
658
|
)
|
|
657
|
-
|
|
659
|
+
self._raise_for_status(response)
|
|
658
660
|
return [Sport(sport) for sport in response.json()]
|
|
659
661
|
|
|
660
662
|
def get_tags(self) -> list[str]:
|
|
@@ -662,7 +664,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
662
664
|
response = client.get(
|
|
663
665
|
url="/api/v1/profile/tags/",
|
|
664
666
|
)
|
|
665
|
-
|
|
667
|
+
self._raise_for_status(response)
|
|
666
668
|
return response.json()
|
|
667
669
|
|
|
668
670
|
def get_users(self) -> list[UserSummary]:
|
|
@@ -670,7 +672,7 @@ class Client(OAuth2Mixin, DelegationMixin):
|
|
|
670
672
|
response = client.get(
|
|
671
673
|
url="/api/v1/users/",
|
|
672
674
|
)
|
|
673
|
-
|
|
675
|
+
self._raise_for_status(response)
|
|
674
676
|
return [UserSummary.model_validate(user) for user in response.json()]
|
|
675
677
|
|
|
676
678
|
_default_client = Client()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sweatstack-0.32.0 → sweatstack-0.34.0}/playground/.ipynb_checkpoints/Untitled-checkpoint.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
{sweatstack-0.32.0 → sweatstack-0.34.0}/playground/Sweat Stack examples/Getting started.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sweatstack-0.32.0 → sweatstack-0.34.0}/src/sweatstack/Sweat Stack examples/Getting started.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|