trodo-python 2.25.0__py3-none-any.whl → 2.26.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.
trodo/__init__.py CHANGED
@@ -41,7 +41,7 @@ Downstream microservice (join the caller's run instead of making a new one):
41
41
 
42
42
  from __future__ import annotations
43
43
 
44
- __version__ = "2.25.0"
44
+ __version__ = "2.26.0"
45
45
 
46
46
  from typing import Any, Callable, Dict, List, Optional, Union
47
47
 
@@ -122,6 +122,7 @@ __all__ = [
122
122
  "PromptSummary",
123
123
  # Datasets & experiments
124
124
  "append_dataset",
125
+ "export_dataset",
125
126
  "ingest_experiment",
126
127
  "create_experiment",
127
128
  "run_experiment",
@@ -435,6 +436,30 @@ def append_dataset(
435
436
  return _get_client().datasets.append(ref, items, create=create)
436
437
 
437
438
 
439
+ def export_dataset(
440
+ ref: str,
441
+ token: str,
442
+ labels: str = "all",
443
+ include_unlabelled: bool = False,
444
+ version: Optional[int] = None,
445
+ since: Optional[str] = None,
446
+ ) -> Dict[str, Any]:
447
+ """Read a dataset's labelled export with an export token (Settings → Datasets).
448
+
449
+ Rows carry ``input``, ``output``, ``expected``, ``evaluations``,
450
+ ``label_source`` / ``label_status`` / ``label_weight`` and ``source``::
451
+
452
+ out = trodo.export_dataset("support-failures", token=os.environ["TRODO_EXPORT_TOKEN"], labels="confirmed")
453
+ for row in out["rows"]:
454
+ ...
455
+
456
+ Returns ``{"rows": [...], "version": int | None}``.
457
+ """
458
+ return _get_client().datasets.export(
459
+ ref, token, labels=labels, include_unlabelled=include_unlabelled, version=version, since=since,
460
+ )
461
+
462
+
438
463
  def ingest_experiment(
439
464
  dataset: str,
440
465
  outputs: List[Dict[str, Any]],
trodo/_version.py CHANGED
@@ -1 +1 @@
1
- SDK_VERSION = "2.25.0"
1
+ SDK_VERSION = "2.26.0"
trodo/api/http_client.py CHANGED
@@ -180,6 +180,45 @@ class HttpClient:
180
180
  f"/api/sdk/datasets/{quote(str(ref), safe='')}/items", body
181
181
  )
182
182
 
183
+ def export_dataset(self, ref: str, params: Dict[str, Any], token: str) -> Dict[str, Any]:
184
+ """Read a dataset's labelled export (GET /datasets/:ref/export) as JSONL
185
+ text, authenticated with an EXPORT TOKEN (``trodo_dx_…``), never the
186
+ site id. Returns ``{"text", "status", "rows", "version"}`` or
187
+ ``{"__error": True, "status", ...}``. No retries on 4xx."""
188
+ from urllib.parse import quote
189
+ url = f"{self.api_base}/api/sdk/datasets/{quote(str(ref), safe='')}/export"
190
+ clean = {k: v for k, v in (params or {}).items() if v is not None and v != ""}
191
+ self._log(f"GET {url}")
192
+ try:
193
+ resp = requests.get(
194
+ url,
195
+ params=clean,
196
+ headers={"Authorization": f"Bearer {token}", "User-Agent": f"trodo-python/{SDK_VERSION}"},
197
+ timeout=max(self.timeout, 60),
198
+ )
199
+ except Exception as exc: # network
200
+ self._log(f"Error: {exc}")
201
+ if self.on_error:
202
+ self.on_error(exc)
203
+ return {"__error": True, "message": str(exc)}
204
+ if resp.status_code >= 400:
205
+ base: Dict[str, Any] = {"__error": True, "status": resp.status_code}
206
+ try:
207
+ data = resp.json()
208
+ if isinstance(data, dict):
209
+ base.update(data)
210
+ except Exception:
211
+ base["message"] = resp.text[:300]
212
+ return base
213
+ rows = resp.headers.get("x-trodo-export-rows")
214
+ version = resp.headers.get("x-trodo-dataset-version")
215
+ return {
216
+ "text": resp.text,
217
+ "status": resp.status_code,
218
+ "rows": int(rows) if rows and rows.isdigit() else None,
219
+ "version": int(version) if version and version.isdigit() else None,
220
+ }
221
+
183
222
  def ingest_experiment(self, body: Dict[str, Any]) -> ApiResult:
184
223
  return self._request("/api/sdk/experiments/ingest", body)
185
224
 
@@ -12,7 +12,8 @@ Mirrors ``sdks/trodo-node-sdk/src/managers/DatasetManager.ts`` in shape.
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- from typing import Any, Dict, List, Union
15
+ import json
16
+ from typing import Any, Dict, List, Optional, Union
16
17
 
17
18
  __all__ = ["DatasetManager"]
18
19
 
@@ -72,3 +73,50 @@ class DatasetManager:
72
73
  "create": bool(create),
73
74
  }
74
75
  return self._http.append_dataset_items(ref, body)
76
+
77
+ def export(
78
+ self,
79
+ ref: str,
80
+ token: str,
81
+ labels: str = "all",
82
+ include_unlabelled: bool = False,
83
+ version: Optional[int] = None,
84
+ since: Optional[str] = None,
85
+ ) -> Dict[str, Any]:
86
+ """Read the dataset *ref*'s labelled export.
87
+
88
+ Each row is the dataset's training shape: ``input``, ``output``,
89
+ ``expected``, ``evaluations`` (the Evals v3 verdicts snapshotted onto
90
+ the row), ``label_source`` / ``label_status`` / ``label_weight``,
91
+ ``source``. *token* is an export token from Settings → Datasets
92
+ (``trodo_dx_…``); the site id cannot read exports. *labels* is one of
93
+ ``all, confirmed, explicit, derived, implicit, proposed, unlabelled,
94
+ failed_only, passed_only``; *version* pins a snapshot.
95
+
96
+ Returns ``{"rows": [...], "version": int | None}``.
97
+
98
+ :raises ValueError: if *ref* or *token* is empty.
99
+ :raises RuntimeError: on a non-2xx response (the message carries the status and body).
100
+ """
101
+ if not ref:
102
+ raise ValueError("trodo: export_dataset(ref) requires a dataset ref")
103
+ if not token:
104
+ raise ValueError("trodo: export_dataset requires an export token (Settings → Datasets)")
105
+ params: Dict[str, Any] = {"labels": labels}
106
+ if include_unlabelled:
107
+ params["include_unlabelled"] = 1
108
+ if version is not None:
109
+ params["version"] = int(version)
110
+ if since:
111
+ params["since"] = since
112
+ res = self._http.export_dataset(ref, params, token)
113
+ if res.get("__error"):
114
+ raise RuntimeError(
115
+ f"trodo: export of {ref!r} failed: HTTP {res.get('status')} {res.get('message') or res.get('error') or ''}".strip()
116
+ )
117
+ rows: List[Dict[str, Any]] = []
118
+ for line in (res.get("text") or "").split("\n"):
119
+ line = line.strip()
120
+ if line:
121
+ rows.append(json.loads(line))
122
+ return {"rows": rows, "version": res.get("version")}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trodo-python
3
- Version: 2.25.0
3
+ Version: 2.26.0
4
4
  Summary: Trodo Analytics SDK for Python — server-side event tracking
5
5
  License: ISC
6
6
  Keywords: analytics,tracking,trodo,server-side
@@ -1,5 +1,5 @@
1
- trodo/__init__.py,sha256=ftnDcQvvOi9VnJoynkzzZCNwqHRhC7pbXS836bTwizo,27913
2
- trodo/_version.py,sha256=50fFgmf3lAeDxqh-LvVujTqoWvZoG7fTVAY5gKvc-yQ,23
1
+ trodo/__init__.py,sha256=P8tsY10bg0h-A8TjIYYEiFuYpo-jGSbDzViEsKbnKsU,28752
2
+ trodo/_version.py,sha256=MX7IGM5dYbXPeFIXOWPhV7DPbCslhEe8Q7DCvxwKmhY,23
3
3
  trodo/client.py,sha256=6k6HeKrGV2720kK17--u6BjbhAUFZNUzpd9yEYiaQOs,24137
4
4
  trodo/types.py,sha256=eySgUvCXROG2TxtxgiU0MNr5iH0DEcduK8bmYtTKG44,3138
5
5
  trodo/user_context.py,sha256=uHCI2WYoOI3cNwdIUEuZdX4VYSu14pzm348ksn6hn_c,8195
@@ -7,13 +7,13 @@ trodo/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  trodo/api/_retry.py,sha256=mHhuzfe3QuYa6j9BqRYVClvnYH0o3WkXXngmSwqWfgY,1214
8
8
  trodo/api/async_client.py,sha256=qF97NbvoYbNhem8uXtPh14EG4JVAhEAzUCYn7busaaA,3609
9
9
  trodo/api/endpoints.py,sha256=SGgVELcVfwuCrRwlVPW2j0KYkaMtwLFPpdMtGtlqPeA,1574
10
- trodo/api/http_client.py,sha256=Vnw8l_QyoslCF2lJIxoH2uoUNFAK-8S_YfnWN8f4ZS0,11362
10
+ trodo/api/http_client.py,sha256=iOG9D4ackVAz0nQD5ZjwfIvRiEmgxga9uXgxrRQX6L4,13185
11
11
  trodo/auto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  trodo/auto/auto_event_manager.py,sha256=cztuRsRkNoJE5R4NfSfTrTJTGl4jx2Yb-Ncy0aVAPo8,4247
13
13
  trodo/delivery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  trodo/delivery/sender.py,sha256=urO7m6mRMnSEW7_cNAmJ4A6jtDNxuihZHOxCx1jQScI,21348
15
15
  trodo/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- trodo/managers/dataset_manager.py,sha256=gx0S8ujG3cbw4IskBNMdceBjDbcEh_nebwKSzEvm7hE,2827
16
+ trodo/managers/dataset_manager.py,sha256=kR3aoyuq1gcZ5Gpr6bf2Mz_cqv275dXlO6cGL5qfwEA,4902
17
17
  trodo/managers/experiment_manager.py,sha256=V-vemLtenfSI5VIcP0HPiXzEy8AyTrRrbJVCA9Z6wjo,10579
18
18
  trodo/managers/group_manager.py,sha256=ki3Se3qEoSZfREX63oeDeBmEfZF-ISHLE8azEtLg0tM,3542
19
19
  trodo/managers/people_manager.py,sha256=mMVnx40Mlifx6NGgChvohC9ViK6dQu2mkXNHbV8pK1E,2882
@@ -40,7 +40,7 @@ trodo/session/server_session.py,sha256=McsudEiq33XDq3nqxgzBcUvIjQxCMscwEuAPnYXrT
40
40
  trodo/session/session_manager.py,sha256=7ht5LeeZX1HLLfPeNV_a8NkXGbHl3up0CRtCGr3EzjQ,2995
41
41
  trodo/util/__init__.py,sha256=Z9c4rPPdKg06Kk3byKheDqksSgR4WNvS475oQ5sNljc,54
42
42
  trodo/util/lru.py,sha256=QIsM7s6J_E9ZjiXatSyReZIEeGypTAcgrPWWy8YsRa4,2465
43
- trodo_python-2.25.0.dist-info/METADATA,sha256=_e2LmqFYjaZQdhh6Nr-Uj9wr_f88ZYLZDlD17N431as,25308
44
- trodo_python-2.25.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
45
- trodo_python-2.25.0.dist-info/top_level.txt,sha256=VCQu1CJWFmNsqTs1YxMcw4Mq35Tc3z3uI9RwHEXAayQ,6
46
- trodo_python-2.25.0.dist-info/RECORD,,
43
+ trodo_python-2.26.0.dist-info/METADATA,sha256=RE-9yCbqYEzBYYWCQuyXOGsyhGTSPw6rLpiv9cfEdF4,25308
44
+ trodo_python-2.26.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
45
+ trodo_python-2.26.0.dist-info/top_level.txt,sha256=VCQu1CJWFmNsqTs1YxMcw4Mq35Tc3z3uI9RwHEXAayQ,6
46
+ trodo_python-2.26.0.dist-info/RECORD,,