sweatstack 0.37.0__py3-none-any.whl → 0.38.0__py3-none-any.whl

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/schemas.py CHANGED
@@ -1,5 +1,104 @@
1
1
  from enum import Enum
2
+ from typing import List, Union
2
3
 
3
4
  from .openapi_schemas import (
4
- ActivityDetails, ActivitySummary, Metric, Scope, Sport, TraceDetails, UserInfoResponse, UserSummary
5
- )
5
+ ActivityDetails, ActivitySummary, Metric, Scope, Sport,
6
+ TraceDetails, UserInfoResponse, UserSummary
7
+ )
8
+
9
+
10
+ def parent_sport(sport: Sport) -> Sport:
11
+ """Returns the parent sport of a given sport.
12
+
13
+ For sports with a hierarchical structure (e.g., 'cycling.road'), returns the parent sport
14
+ ('cycling'). If the sport has no parent (is already a root sport), returns the sport itself.
15
+
16
+ Args:
17
+ sport (Sport): The sport enum value to find the parent of.
18
+
19
+ Returns:
20
+ Sport: The parent sport enum value, or the original sport if it has no parent.
21
+ """
22
+ parts = sport.value.split(".")
23
+ if len(parts) == 1:
24
+ return sport
25
+ return sport.__class__(".".join(parts[:-1]))
26
+
27
+
28
+ def root_sport(sport: Sport) -> Sport:
29
+ """Returns the root sport of a given sport.
30
+
31
+ For sports with a hierarchical structure (e.g., 'cycling.road' or 'cycling.road.gravel'),
32
+ returns the root sport ('cycling'). If the sport is already a root sport, returns the sport itself.
33
+
34
+ Args:
35
+ sport (Sport): The sport enum value to find the root of.
36
+
37
+ Returns:
38
+ Sport: The root sport enum value.
39
+ """
40
+ return sport.__class__(sport.value.split(".")[0])
41
+
42
+
43
+ def is_root_sport(sport: Sport) -> bool:
44
+ """Determines if a sport is a root sport.
45
+
46
+ A root sport is one that doesn't have a parent sport in the hierarchy
47
+ (e.g., 'cycling' is a root sport, while 'cycling.road' is not).
48
+
49
+ Args:
50
+ sport (Sport): The sport enum value to check.
51
+
52
+ Returns:
53
+ bool: True if the sport is a root sport, False otherwise.
54
+ """
55
+ return sport == root_sport(sport)
56
+
57
+
58
+ def is_sub_sport_of(sport: Sport, sport_or_sports: Union[Sport, List[Sport]]) -> bool:
59
+ """Determines if a sport is a sub-sport of another sport or list of sports.
60
+
61
+ For example, 'cycling.road' is a sub-sport of 'cycling', but not of 'running'.
62
+
63
+ Args:
64
+ sport (Sport): The sport to check.
65
+ sport_or_sports (Union[Sport, List[Sport]]): A sport or list of sports to check against.
66
+
67
+ Returns:
68
+ bool: True if the sport is a sub-sport of any of the provided sports, False otherwise.
69
+
70
+ Raises:
71
+ ValueError: If sport_or_sports is not a Sport or a list of Sports.
72
+ """
73
+ if isinstance(sport_or_sports, Sport):
74
+ return sport.value.startswith(sport_or_sports.value)
75
+ elif isinstance(sport_or_sports, (list, tuple)):
76
+ return any(is_sub_sport_of(sport, sport) for sport in sport_or_sports)
77
+ else:
78
+ raise ValueError(f"Invalid type for sport_or_sports: {type(sport_or_sports)}")
79
+
80
+
81
+ def display_name(sport: Sport) -> str:
82
+ """Returns a human-readable display name for a sport.
83
+
84
+ This function converts a Sport enum value into a formatted string suitable for display.
85
+
86
+ Args:
87
+ sport (Sport): The sport enum value to format.
88
+
89
+ Returns:
90
+ str: A human-readable display name for the sport.
91
+ """
92
+ parts = sport.value.split(".")
93
+ base_sport = parts[0]
94
+ base_sport = base_sport.replace("_", " ")
95
+ if len(parts) == 1:
96
+ return base_sport
97
+ the_rest = " ".join(parts[1:]).replace("_", " ")
98
+ return f"{base_sport} ({the_rest})"
99
+
100
+
101
+ Sport.root_sport = root_sport
102
+ Sport.parent_sport = parent_sport
103
+ Sport.is_sub_sport_of = is_sub_sport_of
104
+ Sport.display_name = display_name
sweatstack/utils.py CHANGED
@@ -52,29 +52,4 @@ def make_dataframe_streamlit_compatible(df: pd.DataFrame) -> pd.DataFrame:
52
52
  lambda x: x.value if isinstance(x, Enum) else x
53
53
  )
54
54
 
55
- return df_copy if df_copy is not None else df
56
-
57
-
58
- def format_sport(sport: Sport):
59
- """Formats a sport enum value into a human-readable string.
60
-
61
- This function takes a Sport enum and converts it to a formatted string representation.
62
- For example, "cycling.road" becomes "cycling (road)" and "running" remains "running".
63
- Underscores in sport names are replaced with spaces.
64
-
65
- Args:
66
- sport: A Sport enum value to format.
67
-
68
- Returns:
69
- str: A human-readable formatted string representation of the sport.
70
- """
71
- parts = sport.value.split(".")
72
- base_sport = parts[0]
73
- base_sport = base_sport.replace("_", " ")
74
-
75
- if len(parts) == 1:
76
- return base_sport
77
-
78
- remainder = " ".join(parts[1:]).replace("_", " ")
79
-
80
- return f"{base_sport} ({remainder})"
55
+ return df_copy if df_copy is not None else df
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sweatstack
3
- Version: 0.37.0
3
+ Version: 0.38.0
4
4
  Summary: The official Python client for SweatStack
5
5
  Author-email: Aart Goossens <aart@gssns.io>
6
6
  Requires-Python: >=3.9
@@ -6,12 +6,12 @@ sweatstack/ipython_init.py,sha256=zBGUlMFkdpLvsNpOpwrNaKRUpUZhzaICvH8ODJgMPcI,22
6
6
  sweatstack/jupyterlab_oauth2_startup.py,sha256=eZ6xi0Sa4hO4vUanimq0SqjduHtiywCURSDNWk_I-7s,1200
7
7
  sweatstack/openapi_schemas.py,sha256=rB_gdkob49AISTebZXmNjOOz3it28Y42_PEKcBF24c0,13576
8
8
  sweatstack/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- sweatstack/schemas.py,sha256=zRxssFvsXmCTtLr69a7n_EHUUbfAG27w6cTr730ZeUY,159
9
+ sweatstack/schemas.py,sha256=d6KRMJalaABO61CPm3afs-hM6zUcwbGrZ5mc6SVuc54,3370
10
10
  sweatstack/streamlit.py,sha256=dtli4RpBiS8cH4GAQ9lDI_ZRDMLoU7GnTc676nLV_4A,13008
11
11
  sweatstack/sweatshell.py,sha256=MYLNcWbOdceqKJ3S0Pe8dwHXEeYsGJNjQoYUXpMTftA,333
12
- sweatstack/utils.py,sha256=WMY0THAfktzeDNH3kuwYNtVaoS1OQMaobONtGhpLI2E,2547
12
+ sweatstack/utils.py,sha256=AwHRdC1ziOZ5o9RBIB21Uxm-DoClVRAJSVvgsmSmvps,1801
13
13
  sweatstack/Sweat Stack examples/Getting started.ipynb,sha256=k2hiSffWecoQ0VxjdpDcgFzBXDQiYEebhnAYlu8cgX8,6335204
14
- sweatstack-0.37.0.dist-info/METADATA,sha256=MQf29vXxKG9b22yMQvH9apE5uWwljU1RY0NQRVSuUng,779
15
- sweatstack-0.37.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- sweatstack-0.37.0.dist-info/entry_points.txt,sha256=kCzOUQI3dqbTpEYqtgYDeiKFaqaA7BMlV6D24BMzCFU,208
17
- sweatstack-0.37.0.dist-info/RECORD,,
14
+ sweatstack-0.38.0.dist-info/METADATA,sha256=z3dU5Jjlozd1kyYvIb7ELhNYN-a1hKcsl-efEEQyCbU,779
15
+ sweatstack-0.38.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ sweatstack-0.38.0.dist-info/entry_points.txt,sha256=kCzOUQI3dqbTpEYqtgYDeiKFaqaA7BMlV6D24BMzCFU,208
17
+ sweatstack-0.38.0.dist-info/RECORD,,