stresszero 1.0.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.
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: stresszero
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for StressZero Intelligence API — Burnout risk scoring for entrepreneurs
5
+ Project-URL: Homepage, https://stresszeroentrepreneur.fr/intelligence-api
6
+ Project-URL: Documentation, https://stresszeroentrepreneur.fr/docs
7
+ Project-URL: Repository, https://github.com/StressZeroEntrepreneur/stresszero-sdk-python
8
+ Project-URL: Issues, https://github.com/StressZeroEntrepreneur/stresszero-sdk-python/issues
9
+ Author-email: Emmanuel Gomes Soares <hello@stresszeroentrepreneur.fr>
10
+ License-Expression: MIT
11
+ Keywords: api,burnout,entrepreneur,scoring,sdk,stress,wellness
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.8
23
+ Requires-Dist: httpx>=0.24.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
26
+ Requires-Dist: pytest>=7.0; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # StressZero Python SDK
30
+
31
+ Official Python SDK for [StressZero Intelligence API](https://stresszeroentrepreneur.fr/intelligence-api) — Burnout risk scoring for entrepreneurs.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install stresszero
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```python
42
+ from stresszero import StressZero, ResponseItem, AnalysisContext
43
+
44
+ sz = StressZero("sz_live_your_key_here")
45
+
46
+ # Quick 3-score check
47
+ result = sz.quick_check(physical=65, emotional=70, effectiveness=55)
48
+ if result.ok:
49
+ print(f"Score: {result.data['score']['total']}/100")
50
+ print(f"Risk: {result.data['risk']['level']}")
51
+
52
+ # Full analysis
53
+ result = sz.analyze_burnout(
54
+ responses=[
55
+ ResponseItem("physical", "sleep_quality", 65, weight=3),
56
+ ResponseItem("emotional", "motivation", 70, weight=2),
57
+ ResponseItem("effectiveness", "productivity", 55, weight=2),
58
+ ],
59
+ context=AnalysisContext(profession="entrepreneur", hours_per_week=55),
60
+ )
61
+
62
+ # Predictive scoring (J+30)
63
+ from stresszero.types import PredictiveContext
64
+
65
+ result = sz.analyze_burnout_with_prediction(
66
+ responses=[
67
+ ResponseItem("physical", "sleep", 65, weight=3),
68
+ ResponseItem("emotional", "stress", 70, weight=2),
69
+ ResponseItem("effectiveness", "focus", 55, weight=2),
70
+ ],
71
+ predictive_context=PredictiveContext(
72
+ sleep_hours=6,
73
+ exercise_days_per_week=1,
74
+ has_support_network=False,
75
+ ),
76
+ )
77
+ if result.ok:
78
+ pred = result.data["prediction"]
79
+ print(f"Score J+30: {pred['prediction']['score_j30']}")
80
+ print(f"Trajectory: {pred['prediction']['trajectory']}")
81
+ ```
82
+
83
+ ## Sandbox Testing
84
+
85
+ Use `sz_test_` prefixed keys for sandbox mode (no DB, no quota):
86
+
87
+ ```python
88
+ sz = StressZero("sz_test_free") # Free tier sandbox
89
+ sz = StressZero("sz_test_pro") # Pro tier sandbox
90
+ ```
91
+
92
+ ## API Reference
93
+
94
+ | Method | Tier | Description |
95
+ |--------|------|-------------|
96
+ | `analyze_burnout()` | Free+ | Individual burnout scoring |
97
+ | `analyze_burnout_with_prediction()` | Free+ | Scoring + J+30 prediction |
98
+ | `analyze_team()` | Starter+ | Team analysis |
99
+ | `generate_report()` | Starter+ | Detailed report |
100
+ | `quick_check()` | Free+ | Quick 3-score check |
101
+ | `health()` | Public | API health status |
102
+
103
+ ## License
104
+
105
+ MIT — [StressZero Entrepreneur](https://stresszeroentrepreneur.fr)
@@ -0,0 +1,77 @@
1
+ # StressZero Python SDK
2
+
3
+ Official Python SDK for [StressZero Intelligence API](https://stresszeroentrepreneur.fr/intelligence-api) — Burnout risk scoring for entrepreneurs.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install stresszero
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from stresszero import StressZero, ResponseItem, AnalysisContext
15
+
16
+ sz = StressZero("sz_live_your_key_here")
17
+
18
+ # Quick 3-score check
19
+ result = sz.quick_check(physical=65, emotional=70, effectiveness=55)
20
+ if result.ok:
21
+ print(f"Score: {result.data['score']['total']}/100")
22
+ print(f"Risk: {result.data['risk']['level']}")
23
+
24
+ # Full analysis
25
+ result = sz.analyze_burnout(
26
+ responses=[
27
+ ResponseItem("physical", "sleep_quality", 65, weight=3),
28
+ ResponseItem("emotional", "motivation", 70, weight=2),
29
+ ResponseItem("effectiveness", "productivity", 55, weight=2),
30
+ ],
31
+ context=AnalysisContext(profession="entrepreneur", hours_per_week=55),
32
+ )
33
+
34
+ # Predictive scoring (J+30)
35
+ from stresszero.types import PredictiveContext
36
+
37
+ result = sz.analyze_burnout_with_prediction(
38
+ responses=[
39
+ ResponseItem("physical", "sleep", 65, weight=3),
40
+ ResponseItem("emotional", "stress", 70, weight=2),
41
+ ResponseItem("effectiveness", "focus", 55, weight=2),
42
+ ],
43
+ predictive_context=PredictiveContext(
44
+ sleep_hours=6,
45
+ exercise_days_per_week=1,
46
+ has_support_network=False,
47
+ ),
48
+ )
49
+ if result.ok:
50
+ pred = result.data["prediction"]
51
+ print(f"Score J+30: {pred['prediction']['score_j30']}")
52
+ print(f"Trajectory: {pred['prediction']['trajectory']}")
53
+ ```
54
+
55
+ ## Sandbox Testing
56
+
57
+ Use `sz_test_` prefixed keys for sandbox mode (no DB, no quota):
58
+
59
+ ```python
60
+ sz = StressZero("sz_test_free") # Free tier sandbox
61
+ sz = StressZero("sz_test_pro") # Pro tier sandbox
62
+ ```
63
+
64
+ ## API Reference
65
+
66
+ | Method | Tier | Description |
67
+ |--------|------|-------------|
68
+ | `analyze_burnout()` | Free+ | Individual burnout scoring |
69
+ | `analyze_burnout_with_prediction()` | Free+ | Scoring + J+30 prediction |
70
+ | `analyze_team()` | Starter+ | Team analysis |
71
+ | `generate_report()` | Starter+ | Detailed report |
72
+ | `quick_check()` | Free+ | Quick 3-score check |
73
+ | `health()` | Public | API health status |
74
+
75
+ ## License
76
+
77
+ MIT — [StressZero Entrepreneur](https://stresszeroentrepreneur.fr)
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "stresszero"
7
+ version = "1.0.0"
8
+ description = "Official Python SDK for StressZero Intelligence API — Burnout risk scoring for entrepreneurs"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.8"
12
+ authors = [
13
+ { name = "Emmanuel Gomes Soares", email = "hello@stresszeroentrepreneur.fr" },
14
+ ]
15
+ keywords = ["burnout", "stress", "api", "sdk", "wellness", "entrepreneur", "scoring"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ ]
28
+ dependencies = [
29
+ "httpx>=0.24.0",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "pytest>=7.0",
35
+ "pytest-asyncio>=0.21",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://stresszeroentrepreneur.fr/intelligence-api"
40
+ Documentation = "https://stresszeroentrepreneur.fr/docs"
41
+ Repository = "https://github.com/StressZeroEntrepreneur/stresszero-sdk-python"
42
+ Issues = "https://github.com/StressZeroEntrepreneur/stresszero-sdk-python/issues"
@@ -0,0 +1,34 @@
1
+ """StressZero SDK — Official Python SDK for StressZero Intelligence API."""
2
+
3
+ from .client import StressZero
4
+ from .types import (
5
+ Dimension,
6
+ RiskLevel,
7
+ Language,
8
+ ResponseItem,
9
+ AnalysisContext,
10
+ AnalysisOptions,
11
+ AnalysisResult,
12
+ ReportResult,
13
+ TeamAnalysisResult,
14
+ PredictiveResult,
15
+ HealthResult,
16
+ ApiResponse,
17
+ )
18
+
19
+ __version__ = "1.0.0"
20
+ __all__ = [
21
+ "StressZero",
22
+ "Dimension",
23
+ "RiskLevel",
24
+ "Language",
25
+ "ResponseItem",
26
+ "AnalysisContext",
27
+ "AnalysisOptions",
28
+ "AnalysisResult",
29
+ "ReportResult",
30
+ "TeamAnalysisResult",
31
+ "PredictiveResult",
32
+ "HealthResult",
33
+ "ApiResponse",
34
+ ]
@@ -0,0 +1,259 @@
1
+ """StressZero API client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import asdict
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ import httpx
9
+
10
+ from .types import (
11
+ AnalysisContext,
12
+ AnalysisOptions,
13
+ ApiResponse,
14
+ HealthResult,
15
+ Language,
16
+ PredictiveContext,
17
+ PreviousScore,
18
+ ResponseItem,
19
+ )
20
+
21
+
22
+ class StressZero:
23
+ """Official Python client for StressZero Intelligence API.
24
+
25
+ Example::
26
+
27
+ from stresszero import StressZero, ResponseItem
28
+
29
+ sz = StressZero("sz_live_your_key_here")
30
+
31
+ result = sz.analyze_burnout(
32
+ responses=[
33
+ ResponseItem("physical", "sleep", 65, weight=3),
34
+ ResponseItem("emotional", "motivation", 70, weight=2),
35
+ ResponseItem("effectiveness", "productivity", 55, weight=2),
36
+ ],
37
+ context=AnalysisContext(profession="entrepreneur", hours_per_week=55),
38
+ )
39
+
40
+ if result.ok:
41
+ print(result.data["score"]["total"])
42
+ print(result.data["risk"]["level"])
43
+
44
+ Docs: https://stresszeroentrepreneur.fr/intelligence-api
45
+ """
46
+
47
+ BASE_URL = "https://stresszeroentrepreneur.fr"
48
+ VERSION = "1.0.0"
49
+
50
+ def __init__(
51
+ self,
52
+ api_key: str,
53
+ *,
54
+ base_url: Optional[str] = None,
55
+ timeout: float = 30.0,
56
+ ):
57
+ if not api_key or not (api_key.startswith("sz_live_") or api_key.startswith("sz_test_")):
58
+ raise ValueError(
59
+ "Invalid API key. Must start with 'sz_live_' or 'sz_test_'. "
60
+ "Get your free key at: https://stresszeroentrepreneur.fr/intelligence-api"
61
+ )
62
+
63
+ self._api_key = api_key
64
+ self._base_url = (base_url or self.BASE_URL).rstrip("/")
65
+ self._client = httpx.Client(
66
+ base_url=self._base_url,
67
+ timeout=timeout,
68
+ headers={
69
+ "Authorization": f"Bearer {api_key}",
70
+ "Content-Type": "application/json",
71
+ "User-Agent": f"stresszero-python/{self.VERSION}",
72
+ },
73
+ )
74
+
75
+ def _request(self, method: str, path: str, json: Optional[Dict[str, Any]] = None) -> ApiResponse:
76
+ try:
77
+ resp = self._client.request(method, path, json=json)
78
+ data = resp.json()
79
+ return ApiResponse(
80
+ success=data.get("success", False),
81
+ data=data.get("data"),
82
+ error=data.get("error"),
83
+ meta=data.get("meta"),
84
+ )
85
+ except httpx.TimeoutException:
86
+ return ApiResponse(success=False, error={"message": "Request timed out"})
87
+ except Exception as e:
88
+ return ApiResponse(success=False, error={"message": str(e)})
89
+
90
+ def analyze_burnout(
91
+ self,
92
+ responses: List[ResponseItem],
93
+ *,
94
+ context: Optional[AnalysisContext] = None,
95
+ options: Optional[AnalysisOptions] = None,
96
+ ) -> ApiResponse:
97
+ """Score burnout risk across 3 dimensions (physical, emotional, effectiveness).
98
+
99
+ Args:
100
+ responses: List of ResponseItem (min 3, max 20).
101
+ context: Professional context (profession, hours, experience).
102
+ options: Output options (language, recommendations, dimensions).
103
+
104
+ Returns:
105
+ ApiResponse with score, risk, recommendations, suggested product.
106
+ """
107
+ payload: Dict[str, Any] = {
108
+ "responses": [asdict(r) for r in responses],
109
+ }
110
+ if context:
111
+ payload["context"] = {k: v for k, v in asdict(context).items() if v is not None}
112
+ if options:
113
+ payload["options"] = {k: v for k, v in asdict(options).items() if v is not None}
114
+
115
+ return self._request("POST", "/api/v1/analyze-burnout", json=payload)
116
+
117
+ def analyze_burnout_with_prediction(
118
+ self,
119
+ responses: List[ResponseItem],
120
+ *,
121
+ context: Optional[AnalysisContext] = None,
122
+ predictive_context: Optional[PredictiveContext] = None,
123
+ previous_scores: Optional[List[PreviousScore]] = None,
124
+ language: Language = "fr",
125
+ ) -> ApiResponse:
126
+ """Analyze burnout with J+30 predictive trajectory.
127
+
128
+ Args:
129
+ responses: List of ResponseItem.
130
+ context: Professional context.
131
+ predictive_context: Lifestyle factors for prediction.
132
+ previous_scores: Historical scores for trend detection.
133
+ language: Response language ('fr' or 'en').
134
+
135
+ Returns:
136
+ ApiResponse with score, risk, recommendations + prediction.
137
+ """
138
+ payload: Dict[str, Any] = {
139
+ "responses": [asdict(r) for r in responses],
140
+ "options": {"include_prediction": True, "language": language},
141
+ }
142
+ if context:
143
+ payload["context"] = {k: v for k, v in asdict(context).items() if v is not None}
144
+ if predictive_context:
145
+ payload["predictive_context"] = {k: v for k, v in asdict(predictive_context).items() if v is not None}
146
+ if previous_scores:
147
+ payload["previous_scores"] = [asdict(s) for s in previous_scores]
148
+
149
+ return self._request("POST", "/api/v1/analyze-burnout", json=payload)
150
+
151
+ def analyze_team(
152
+ self,
153
+ members: List[Dict[str, Any]],
154
+ *,
155
+ team_name: Optional[str] = None,
156
+ anonymize: bool = True,
157
+ language: Language = "fr",
158
+ ) -> ApiResponse:
159
+ """Analyze burnout risk across a team. Requires Starter+ tier.
160
+
161
+ Args:
162
+ members: List of team member data (responses + context).
163
+ team_name: Optional team name.
164
+ anonymize: Anonymize member IDs in response.
165
+ language: Response language.
166
+
167
+ Returns:
168
+ ApiResponse with team stats, distribution, alerts, recommendations.
169
+ """
170
+ payload: Dict[str, Any] = {
171
+ "members": members,
172
+ "options": {"anonymize": anonymize, "language": language},
173
+ }
174
+ if team_name:
175
+ payload["team_name"] = team_name
176
+
177
+ return self._request("POST", "/api/v1/analyze-team", json=payload)
178
+
179
+ def generate_report(
180
+ self,
181
+ responses: List[ResponseItem],
182
+ *,
183
+ context: Optional[Dict[str, Any]] = None,
184
+ language: Language = "fr",
185
+ format: str = "json",
186
+ ) -> ApiResponse:
187
+ """Generate a detailed burnout report. Requires Starter+ tier.
188
+
189
+ Args:
190
+ responses: List of ResponseItem.
191
+ context: Report context (profession, company, employee name).
192
+ language: Report language.
193
+ format: Output format ('json' or 'html').
194
+
195
+ Returns:
196
+ ApiResponse with full report (summary, dimensions, action plan, resources).
197
+ """
198
+ payload: Dict[str, Any] = {
199
+ "responses": [asdict(r) for r in responses],
200
+ "language": language,
201
+ "format": format,
202
+ }
203
+ if context:
204
+ payload["context"] = context
205
+
206
+ return self._request("POST", "/api/v1/generate-report", json=payload)
207
+
208
+ def quick_check(
209
+ self,
210
+ physical: int,
211
+ emotional: int,
212
+ effectiveness: int,
213
+ *,
214
+ profession: Optional[str] = None,
215
+ hours_per_week: Optional[int] = None,
216
+ ) -> ApiResponse:
217
+ """Quick 3-score burnout check.
218
+
219
+ Args:
220
+ physical: Physical exhaustion score (0-100).
221
+ emotional: Emotional depletion score (0-100).
222
+ effectiveness: Reduced effectiveness score (0-100).
223
+
224
+ Returns:
225
+ ApiResponse with score, risk level, recommendations.
226
+ """
227
+ responses = [
228
+ ResponseItem("physical", "overall", physical, weight=2),
229
+ ResponseItem("emotional", "overall", emotional, weight=2),
230
+ ResponseItem("effectiveness", "overall", effectiveness, weight=2),
231
+ ]
232
+ context = AnalysisContext(profession=profession, hours_per_week=hours_per_week)
233
+ return self.analyze_burnout(responses, context=context)
234
+
235
+ def health(self) -> HealthResult:
236
+ """Check API health status (no auth required).
237
+
238
+ Returns:
239
+ HealthResult with status, version, checks.
240
+ """
241
+ resp = httpx.get(f"{self._base_url}/api/v1/health", timeout=10)
242
+ data = resp.json()
243
+ return HealthResult(
244
+ status=data.get("status", "unknown"),
245
+ version=data.get("version", ""),
246
+ timestamp=data.get("timestamp", ""),
247
+ latency_ms=data.get("latency_ms", 0),
248
+ checks=data.get("checks", {}),
249
+ )
250
+
251
+ def close(self) -> None:
252
+ """Close the HTTP client."""
253
+ self._client.close()
254
+
255
+ def __enter__(self):
256
+ return self
257
+
258
+ def __exit__(self, *args):
259
+ self.close()
@@ -0,0 +1,156 @@
1
+ """Type definitions for StressZero SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from typing import Any, Dict, List, Literal, Optional, Union
7
+
8
+
9
+ Dimension = Literal["physical", "emotional", "effectiveness"]
10
+ RiskLevel = Literal["low", "moderate", "high", "critical"]
11
+ Language = Literal["fr", "en"]
12
+ Trajectory = Literal["improving", "stable", "worsening", "critical_acceleration"]
13
+
14
+
15
+ @dataclass
16
+ class ResponseItem:
17
+ dimension: Dimension
18
+ question_id: str
19
+ value: int
20
+ weight: int = 1
21
+
22
+
23
+ @dataclass
24
+ class AnalysisContext:
25
+ profession: Optional[str] = None
26
+ hours_per_week: Optional[int] = None
27
+ team_size: Optional[int] = None
28
+ years_experience: Optional[int] = None
29
+
30
+
31
+ @dataclass
32
+ class AnalysisOptions:
33
+ include_recommendations: bool = True
34
+ include_dimensions: bool = True
35
+ include_prediction: bool = False
36
+ language: Language = "fr"
37
+
38
+
39
+ @dataclass
40
+ class PredictiveContext:
41
+ has_support_network: Optional[bool] = None
42
+ has_morning_routine: Optional[bool] = None
43
+ exercise_days_per_week: Optional[int] = None
44
+ sleep_hours: Optional[float] = None
45
+
46
+
47
+ @dataclass
48
+ class PreviousScore:
49
+ physical: int
50
+ emotional: int
51
+ effectiveness: int
52
+ measured_at: str
53
+
54
+
55
+ @dataclass
56
+ class DimensionScore:
57
+ physical: int
58
+ emotional: int
59
+ effectiveness: int
60
+
61
+
62
+ @dataclass
63
+ class RiskAssessment:
64
+ level: RiskLevel
65
+ factors: List[str]
66
+ urgency: int
67
+
68
+
69
+ @dataclass
70
+ class SuggestedProduct:
71
+ id: str
72
+ url: str
73
+
74
+
75
+ @dataclass
76
+ class PredictiveResult:
77
+ prediction: Dict[str, Any]
78
+ risk_factors: List[Dict[str, Any]]
79
+ intervention_urgency: Dict[str, Any]
80
+
81
+
82
+ @dataclass
83
+ class AnalysisResult:
84
+ score: Dict[str, Any]
85
+ risk: Dict[str, Any]
86
+ recommendations: Optional[List[str]] = None
87
+ suggested_product: Optional[Dict[str, str]] = None
88
+ disclaimer: Optional[str] = None
89
+ prediction: Optional[PredictiveResult] = None
90
+
91
+
92
+ @dataclass
93
+ class ReportResult:
94
+ report: Dict[str, Any]
95
+ summary: Dict[str, Any]
96
+ dimensions: Dict[str, Any]
97
+ action_plan: Dict[str, Any]
98
+ context_factors: Optional[Dict[str, Any]] = None
99
+ resources: Optional[Dict[str, Any]] = None
100
+
101
+
102
+ @dataclass
103
+ class TeamMember:
104
+ member_id: str
105
+ score: int
106
+ risk_level: RiskLevel
107
+ dimensions: DimensionScore
108
+
109
+
110
+ @dataclass
111
+ class TeamAnalysisResult:
112
+ team: Dict[str, Any]
113
+ distribution: Optional[Dict[str, int]] = None
114
+ department_breakdown: Optional[Dict[str, Any]] = None
115
+ alerts: List[str] = field(default_factory=list)
116
+ recommendations: List[str] = field(default_factory=list)
117
+ members: List[Dict[str, Any]] = field(default_factory=list)
118
+
119
+
120
+ @dataclass
121
+ class HealthResult:
122
+ status: str
123
+ version: str
124
+ timestamp: str
125
+ latency_ms: float
126
+ checks: Dict[str, Any] = field(default_factory=dict)
127
+
128
+
129
+ @dataclass
130
+ class ApiMeta:
131
+ api_version: str
132
+ latency_ms: float
133
+ quota: Dict[str, Any] = field(default_factory=dict)
134
+
135
+
136
+ @dataclass
137
+ class ApiResponse:
138
+ success: bool
139
+ data: Optional[Any] = None
140
+ error: Optional[Dict[str, Any]] = None
141
+ meta: Optional[ApiMeta] = None
142
+
143
+ @property
144
+ def ok(self) -> bool:
145
+ return self.success
146
+
147
+ def raise_for_error(self) -> None:
148
+ if not self.success and self.error:
149
+ raise StressZeroError(self.error.get("message", "Unknown error"), self.error.get("status"))
150
+
151
+
152
+ class StressZeroError(Exception):
153
+ def __init__(self, message: str, status: Optional[int] = None):
154
+ self.message = message
155
+ self.status = status
156
+ super().__init__(f"[{status}] {message}" if status else message)