trodo-python 2.25.0__tar.gz → 2.26.1__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.
Files changed (74) hide show
  1. {trodo_python-2.25.0 → trodo_python-2.26.1}/PKG-INFO +1 -1
  2. {trodo_python-2.25.0 → trodo_python-2.26.1}/pyproject.toml +1 -1
  3. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_datasets.py +44 -0
  4. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/__init__.py +26 -1
  5. trodo_python-2.26.1/trodo/_version.py +1 -0
  6. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/api/http_client.py +39 -0
  7. trodo_python-2.26.1/trodo/managers/dataset_manager.py +134 -0
  8. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo_python.egg-info/PKG-INFO +1 -1
  9. trodo_python-2.25.0/trodo/_version.py +0 -1
  10. trodo_python-2.25.0/trodo/managers/dataset_manager.py +0 -74
  11. {trodo_python-2.25.0 → trodo_python-2.26.1}/README.md +0 -0
  12. {trodo_python-2.25.0 → trodo_python-2.26.1}/setup.cfg +0 -0
  13. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_anon_distinct_id.py +0 -0
  14. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_auto_instrument_fixes.py +0 -0
  15. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_cross_process_session.py +0 -0
  16. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_end_run.py +0 -0
  17. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_error_enrichment.py +0 -0
  18. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_experiments.py +0 -0
  19. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_framework_deference.py +0 -0
  20. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_get_prompt_version_types.py +0 -0
  21. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_instrumentor_resolution.py +0 -0
  22. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_llm_usage_cost.py +0 -0
  23. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_multi_agent_shape.py +0 -0
  24. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_processor_methods.py +0 -0
  25. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_prompt_fingerprint.py +0 -0
  26. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_prompt_trace.py +0 -0
  27. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_prompts.py +0 -0
  28. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_register_otel.py +0 -0
  29. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_sender.py +0 -0
  30. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_start_run.py +0 -0
  31. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_user_traits.py +0 -0
  32. {trodo_python-2.25.0 → trodo_python-2.26.1}/tests/test_wrap_agent_unchanged.py +0 -0
  33. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/api/__init__.py +0 -0
  34. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/api/_retry.py +0 -0
  35. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/api/async_client.py +0 -0
  36. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/api/endpoints.py +0 -0
  37. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/auto/__init__.py +0 -0
  38. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/auto/auto_event_manager.py +0 -0
  39. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/client.py +0 -0
  40. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/delivery/__init__.py +0 -0
  41. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/delivery/sender.py +0 -0
  42. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/managers/__init__.py +0 -0
  43. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/managers/experiment_manager.py +0 -0
  44. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/managers/group_manager.py +0 -0
  45. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/managers/people_manager.py +0 -0
  46. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/managers/prompt_manager.py +0 -0
  47. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/managers/user_manager.py +0 -0
  48. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/__init__.py +0 -0
  49. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/auto_instrument.py +0 -0
  50. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/context.py +0 -0
  51. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/helpers.py +0 -0
  52. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/processor.py +0 -0
  53. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/prompt_trace.py +0 -0
  54. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/register.py +0 -0
  55. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/transport.py +0 -0
  56. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/otel/wrap_agent.py +0 -0
  57. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/prompts/__init__.py +0 -0
  58. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/prompts/compile.py +0 -0
  59. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/prompts/template.py +0 -0
  60. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/prompts/types.py +0 -0
  61. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/queue/__init__.py +0 -0
  62. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/queue/batch_flusher.py +0 -0
  63. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/queue/event_queue.py +0 -0
  64. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/session/__init__.py +0 -0
  65. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/session/server_session.py +0 -0
  66. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/session/session_manager.py +0 -0
  67. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/types.py +0 -0
  68. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/user_context.py +0 -0
  69. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/util/__init__.py +0 -0
  70. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo/util/lru.py +0 -0
  71. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo_python.egg-info/SOURCES.txt +0 -0
  72. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo_python.egg-info/dependency_links.txt +0 -0
  73. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo_python.egg-info/requires.txt +0 -0
  74. {trodo_python-2.25.0 → trodo_python-2.26.1}/trodo_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trodo-python
3
- Version: 2.25.0
3
+ Version: 2.26.1
4
4
  Summary: Trodo Analytics SDK for Python — server-side event tracking
5
5
  License: ISC
6
6
  Keywords: analytics,tracking,trodo,server-side
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "trodo-python"
7
- version = "2.25.0"
7
+ version = "2.26.1"
8
8
  description = "Trodo Analytics SDK for Python — server-side event tracking"
9
9
  readme = "README.md"
10
10
  license = { text = "ISC" }
@@ -100,3 +100,47 @@ def test_append_requires_items():
100
100
  def test_append_requires_input_on_each_item():
101
101
  with pytest.raises(ValueError, match="requires an 'input'"):
102
102
  DatasetManager(FakeHttp()).append("ds", [{"expected_output": "x"}])
103
+
104
+
105
+ # ---------------------------------------------------------------------------
106
+ # export — DatasetManager.export (the labelled JSONL, read with an export token)
107
+ # ---------------------------------------------------------------------------
108
+
109
+ class FakeExportHttp:
110
+ def __init__(self, response):
111
+ self._response = response
112
+ self.last = None
113
+
114
+ def export_dataset(self, ref, params, token):
115
+ self.last = (ref, params, token)
116
+ return self._response
117
+
118
+
119
+ def test_export_sends_token_and_filters_and_parses_jsonl():
120
+ http = FakeExportHttp({"text": '{"id":"a","expected":"x"}\n{"id":"b","expected":null}\n', "status": 200, "rows": 2, "version": 3})
121
+ out = DatasetManager(http).export("support-eval", "trodo_dx_abc", labels="confirmed", include_unlabelled=True, version=3, since="2026-01-01T00:00:00Z")
122
+ assert http.last == ("support-eval", {"labels": "confirmed", "include_unlabelled": 1, "version": 3, "since": "2026-01-01T00:00:00Z"}, "trodo_dx_abc")
123
+ assert out == {"rows": [{"id": "a", "expected": "x"}, {"id": "b", "expected": None}], "version": 3}
124
+
125
+
126
+ def test_export_requires_a_token_and_raises_on_http_errors():
127
+ with pytest.raises(ValueError):
128
+ DatasetManager(FakeExportHttp({})).export("ds", "")
129
+ with pytest.raises(RuntimeError, match="HTTP 404"):
130
+ DatasetManager(FakeExportHttp({"__error": True, "status": 404, "error": "not_found"})).export("ds", "trodo_dx_abc")
131
+
132
+
133
+ def test_append_accepts_unit_references_without_input():
134
+ http = FakeHttp()
135
+ DatasetManager(http).append("ds", [
136
+ {"span_id": "s1", "tags": ["hard"]},
137
+ {"run_id": "r1"},
138
+ {"conversation_id": "c1", "metadata": {"k": 1}},
139
+ {"eval_run_id": "v1"},
140
+ ])
141
+ assert http.last_body["items"] == [
142
+ {"span_id": "s1", "tags": ["hard"]},
143
+ {"run_id": "r1"},
144
+ {"conversation_id": "c1", "metadata": {"k": 1}},
145
+ {"eval_run_id": "v1"},
146
+ ]
@@ -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.1"
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]],
@@ -0,0 +1 @@
1
+ SDK_VERSION = "2.26.0"
@@ -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
 
@@ -0,0 +1,134 @@
1
+ """Dataset ingest — append evaluation items to a Trodo dataset.
2
+
3
+ Datasets are the fixed inputs an experiment runs against: each item is a set of
4
+ variable values (``input``) plus an optional gold answer (``expected_output``)
5
+ and free-form ``metadata``. This manager appends items to a dataset addressed by
6
+ UUID or by name; when a name is used and no such dataset exists it is
7
+ auto-created (``create=True``, the default), so a first append bootstraps the
8
+ dataset without a separate create call.
9
+
10
+ Mirrors ``sdks/trodo-node-sdk/src/managers/DatasetManager.ts`` in shape.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ from typing import Any, Dict, List, Optional, Union
17
+
18
+ __all__ = ["DatasetManager"]
19
+
20
+ # The optional per-item fields, in wire order. ``input`` is required on a row.
21
+ _ITEM_OPTIONAL = ("output", "expected_output", "metadata", "source_trace_ref", "tags")
22
+ # A reference to production instead of content: the item becomes that unit's
23
+ # row (Input, Output and Evaluations filled by Trodo). ``eval_run_id`` names a
24
+ # verdict: Output is what the eval said, Expected its correction.
25
+ _UNIT_REF_KEYS = ("span_id", "run_id", "conversation_id", "eval_run_id")
26
+ _UNIT_REF_OPTIONAL = ("tags", "metadata")
27
+
28
+
29
+ def _clean_item(item: Dict[str, Any]) -> Dict[str, Any]:
30
+ if not isinstance(item, dict):
31
+ raise ValueError("trodo: each dataset item must be a dict")
32
+ ref = [k for k in _UNIT_REF_KEYS if item.get(k)]
33
+ if ref and ("input" not in item or item["input"] is None):
34
+ out: Dict[str, Any] = {ref[0]: str(item[ref[0]])}
35
+ for key in _UNIT_REF_OPTIONAL:
36
+ if item.get(key) is not None:
37
+ out[key] = item[key]
38
+ return out
39
+ if "input" not in item or item["input"] is None:
40
+ raise ValueError("trodo: each dataset item requires an 'input' dict, or a span_id / run_id / conversation_id / eval_run_id")
41
+ out = {"input": item["input"]}
42
+ for key in _ITEM_OPTIONAL:
43
+ if item.get(key) is not None:
44
+ out[key] = item[key]
45
+ return out
46
+
47
+
48
+ class DatasetManager:
49
+ """Append items to the team's evaluation datasets."""
50
+
51
+ def __init__(self, http_client: Any) -> None:
52
+ self._http = http_client
53
+
54
+ def append(
55
+ self,
56
+ ref: str,
57
+ items: Union[Dict[str, Any], List[Dict[str, Any]]],
58
+ create: bool = True,
59
+ ) -> Dict[str, Any]:
60
+ """Append one or more items to the dataset *ref* (a UUID or a name).
61
+
62
+ *items* is a list of dicts shaped ``{"input": {<var>: value, ...},
63
+ "expected_output"?: str, "metadata"?: dict, "source_trace_ref"?: dict}``;
64
+ a single dict is accepted and wrapped into a one-item list. ``None``
65
+ optional fields are dropped from the wire payload.
66
+
67
+ When *ref* is a name that doesn't exist yet, ``create=True`` (default)
68
+ auto-creates the dataset; pass ``create=False`` to require it to exist.
69
+
70
+ Returns the parsed response dict:
71
+ ``{"dataset_id", "dataset_name", "appended", "item_count"}``.
72
+
73
+ :raises ValueError: if *ref* is empty, *items* is empty, or an item has
74
+ no ``input``.
75
+ """
76
+ if not ref:
77
+ raise ValueError("trodo: append_dataset(ref) requires a dataset ref")
78
+ if isinstance(items, dict):
79
+ items = [items]
80
+ if not items:
81
+ raise ValueError("trodo: append_dataset(ref, items) requires items")
82
+
83
+ body = {
84
+ "items": [_clean_item(i) for i in items],
85
+ "create": bool(create),
86
+ }
87
+ return self._http.append_dataset_items(ref, body)
88
+
89
+ def export(
90
+ self,
91
+ ref: str,
92
+ token: str,
93
+ labels: str = "all",
94
+ include_unlabelled: bool = False,
95
+ version: Optional[int] = None,
96
+ since: Optional[str] = None,
97
+ ) -> Dict[str, Any]:
98
+ """Read the dataset *ref*'s labelled export.
99
+
100
+ Each row is the dataset's training shape: ``input``, ``output``,
101
+ ``expected``, ``evaluations`` (the Evals v3 verdicts snapshotted onto
102
+ the row), ``label_source`` / ``label_status`` / ``label_weight``,
103
+ ``source``. *token* is an export token from Settings → Datasets
104
+ (``trodo_dx_…``); the site id cannot read exports. *labels* is one of
105
+ ``all, confirmed, explicit, derived, implicit, proposed, unlabelled,
106
+ failed_only, passed_only``; *version* pins a snapshot.
107
+
108
+ Returns ``{"rows": [...], "version": int | None}``.
109
+
110
+ :raises ValueError: if *ref* or *token* is empty.
111
+ :raises RuntimeError: on a non-2xx response (the message carries the status and body).
112
+ """
113
+ if not ref:
114
+ raise ValueError("trodo: export_dataset(ref) requires a dataset ref")
115
+ if not token:
116
+ raise ValueError("trodo: export_dataset requires an export token (Settings → Datasets)")
117
+ params: Dict[str, Any] = {"labels": labels}
118
+ if include_unlabelled:
119
+ params["include_unlabelled"] = 1
120
+ if version is not None:
121
+ params["version"] = int(version)
122
+ if since:
123
+ params["since"] = since
124
+ res = self._http.export_dataset(ref, params, token)
125
+ if res.get("__error"):
126
+ raise RuntimeError(
127
+ f"trodo: export of {ref!r} failed: HTTP {res.get('status')} {res.get('message') or res.get('error') or ''}".strip()
128
+ )
129
+ rows: List[Dict[str, Any]] = []
130
+ for line in (res.get("text") or "").split("\n"):
131
+ line = line.strip()
132
+ if line:
133
+ rows.append(json.loads(line))
134
+ 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.1
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 +0,0 @@
1
- SDK_VERSION = "2.25.0"
@@ -1,74 +0,0 @@
1
- """Dataset ingest — append evaluation items to a Trodo dataset.
2
-
3
- Datasets are the fixed inputs an experiment runs against: each item is a set of
4
- variable values (``input``) plus an optional gold answer (``expected_output``)
5
- and free-form ``metadata``. This manager appends items to a dataset addressed by
6
- UUID or by name; when a name is used and no such dataset exists it is
7
- auto-created (``create=True``, the default), so a first append bootstraps the
8
- dataset without a separate create call.
9
-
10
- Mirrors ``sdks/trodo-node-sdk/src/managers/DatasetManager.ts`` in shape.
11
- """
12
-
13
- from __future__ import annotations
14
-
15
- from typing import Any, Dict, List, Union
16
-
17
- __all__ = ["DatasetManager"]
18
-
19
- # The optional per-item fields, in wire order. ``input`` is always required.
20
- _ITEM_OPTIONAL = ("expected_output", "metadata", "source_trace_ref")
21
-
22
-
23
- def _clean_item(item: Dict[str, Any]) -> Dict[str, Any]:
24
- if not isinstance(item, dict):
25
- raise ValueError("trodo: each dataset item must be a dict")
26
- if "input" not in item or item["input"] is None:
27
- raise ValueError("trodo: each dataset item requires an 'input' dict")
28
- out: Dict[str, Any] = {"input": item["input"]}
29
- for key in _ITEM_OPTIONAL:
30
- if item.get(key) is not None:
31
- out[key] = item[key]
32
- return out
33
-
34
-
35
- class DatasetManager:
36
- """Append items to the team's evaluation datasets."""
37
-
38
- def __init__(self, http_client: Any) -> None:
39
- self._http = http_client
40
-
41
- def append(
42
- self,
43
- ref: str,
44
- items: Union[Dict[str, Any], List[Dict[str, Any]]],
45
- create: bool = True,
46
- ) -> Dict[str, Any]:
47
- """Append one or more items to the dataset *ref* (a UUID or a name).
48
-
49
- *items* is a list of dicts shaped ``{"input": {<var>: value, ...},
50
- "expected_output"?: str, "metadata"?: dict, "source_trace_ref"?: dict}``;
51
- a single dict is accepted and wrapped into a one-item list. ``None``
52
- optional fields are dropped from the wire payload.
53
-
54
- When *ref* is a name that doesn't exist yet, ``create=True`` (default)
55
- auto-creates the dataset; pass ``create=False`` to require it to exist.
56
-
57
- Returns the parsed response dict:
58
- ``{"dataset_id", "dataset_name", "appended", "item_count"}``.
59
-
60
- :raises ValueError: if *ref* is empty, *items* is empty, or an item has
61
- no ``input``.
62
- """
63
- if not ref:
64
- raise ValueError("trodo: append_dataset(ref) requires a dataset ref")
65
- if isinstance(items, dict):
66
- items = [items]
67
- if not items:
68
- raise ValueError("trodo: append_dataset(ref, items) requires items")
69
-
70
- body = {
71
- "items": [_clean_item(i) for i in items],
72
- "create": bool(create),
73
- }
74
- return self._http.append_dataset_items(ref, body)
File without changes
File without changes