datoon 1.7.4__tar.gz → 1.8.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.
Files changed (127) hide show
  1. {datoon-1.7.4 → datoon-1.8.0}/CHANGELOG.md +7 -0
  2. {datoon-1.7.4 → datoon-1.8.0}/PKG-INFO +1 -1
  3. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/_version.py +3 -3
  4. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/cli.py +15 -1
  5. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/__init__.py +10 -4
  6. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/PKG-INFO +1 -1
  7. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/scm_version.json +2 -2
  8. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_cli.py +35 -0
  9. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_readers.py +30 -0
  10. {datoon-1.7.4 → datoon-1.8.0}/.agents/plugins/marketplace.json +0 -0
  11. {datoon-1.7.4 → datoon-1.8.0}/.claude-plugin/marketplace.json +0 -0
  12. {datoon-1.7.4 → datoon-1.8.0}/.claude-plugin/plugin.json +0 -0
  13. {datoon-1.7.4 → datoon-1.8.0}/.editorconfig +0 -0
  14. {datoon-1.7.4 → datoon-1.8.0}/.gitattributes +0 -0
  15. {datoon-1.7.4 → datoon-1.8.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  16. {datoon-1.7.4 → datoon-1.8.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  17. {datoon-1.7.4 → datoon-1.8.0}/.github/dependabot.yml +0 -0
  18. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/package-installer-smoke.yml +0 -0
  19. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/pages.yml +0 -0
  20. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/pre-commit.yml +0 -0
  21. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/publish-mcp.yml +0 -0
  22. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/publish.yml +0 -0
  23. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/release.yml +0 -0
  24. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/tests.yml +0 -0
  25. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/validate-artifacts.yml +0 -0
  26. {datoon-1.7.4 → datoon-1.8.0}/.github/workflows/workflow-lint.yml +0 -0
  27. {datoon-1.7.4 → datoon-1.8.0}/.gitignore +0 -0
  28. {datoon-1.7.4 → datoon-1.8.0}/.pre-commit-config.yaml +0 -0
  29. {datoon-1.7.4 → datoon-1.8.0}/.releaserc.yaml +0 -0
  30. {datoon-1.7.4 → datoon-1.8.0}/CLAUDE.md +0 -0
  31. {datoon-1.7.4 → datoon-1.8.0}/CONTRIBUTING.md +0 -0
  32. {datoon-1.7.4 → datoon-1.8.0}/INSTALL.md +0 -0
  33. {datoon-1.7.4 → datoon-1.8.0}/LICENSE +0 -0
  34. {datoon-1.7.4 → datoon-1.8.0}/MARKETPLACES.md +0 -0
  35. {datoon-1.7.4 → datoon-1.8.0}/README.md +0 -0
  36. {datoon-1.7.4 → datoon-1.8.0}/SECURITY.md +0 -0
  37. {datoon-1.7.4 → datoon-1.8.0}/SKILL.md +0 -0
  38. {datoon-1.7.4 → datoon-1.8.0}/assets/datoon-banner.svg +0 -0
  39. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/REPORT.md +0 -0
  40. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/agent_results.json +0 -0
  41. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/expected_answers.json +0 -0
  42. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/generate_payloads.py +0 -0
  43. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/1_large.json +0 -0
  44. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/1_medium.json +0 -0
  45. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/1_small.json +0 -0
  46. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/2_large.json +0 -0
  47. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/2_medium.json +0 -0
  48. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/2_small.json +0 -0
  49. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/3_large.json +0 -0
  50. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/3_medium.json +0 -0
  51. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/payloads/3_small.json +0 -0
  52. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/1_large.report.json +0 -0
  53. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/1_medium.report.json +0 -0
  54. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/1_small.report.json +0 -0
  55. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/2_large.report.json +0 -0
  56. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/2_medium.report.json +0 -0
  57. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/2_small.report.json +0 -0
  58. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/3_large.report.json +0 -0
  59. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/3_medium.report.json +0 -0
  60. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/reports/3_small.report.json +0 -0
  61. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/scored_agent_results.json +0 -0
  62. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/1_large.toon +0 -0
  63. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/1_medium.toon +0 -0
  64. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/1_small.toon +0 -0
  65. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/2_large.toon +0 -0
  66. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/2_medium.toon +0 -0
  67. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/2_small.toon +0 -0
  68. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/3_large.toon +0 -0
  69. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/3_medium.toon +0 -0
  70. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/agent_skill_eval/toon/3_small.toon +0 -0
  71. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/payloads.json +0 -0
  72. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/results/.gitkeep +0 -0
  73. {datoon-1.7.4 → datoon-1.8.0}/benchmarks/run.py +0 -0
  74. {datoon-1.7.4 → datoon-1.8.0}/datoon/SKILL.md +0 -0
  75. {datoon-1.7.4 → datoon-1.8.0}/datoon.skill +0 -0
  76. {datoon-1.7.4 → datoon-1.8.0}/docs/.nojekyll +0 -0
  77. {datoon-1.7.4 → datoon-1.8.0}/docs/app.js +0 -0
  78. {datoon-1.7.4 → datoon-1.8.0}/docs/assets/datoon-banner.svg +0 -0
  79. {datoon-1.7.4 → datoon-1.8.0}/docs/index.html +0 -0
  80. {datoon-1.7.4 → datoon-1.8.0}/docs/styles.css +0 -0
  81. {datoon-1.7.4 → datoon-1.8.0}/glama.json +0 -0
  82. {datoon-1.7.4 → datoon-1.8.0}/install.sh +0 -0
  83. {datoon-1.7.4 → datoon-1.8.0}/plugins/datoon/.codex-plugin/plugin.json +0 -0
  84. {datoon-1.7.4 → datoon-1.8.0}/plugins/datoon/skills/datoon/SKILL.md +0 -0
  85. {datoon-1.7.4 → datoon-1.8.0}/pyproject.toml +0 -0
  86. {datoon-1.7.4 → datoon-1.8.0}/scripts/ab_skill_benchmark.py +0 -0
  87. {datoon-1.7.4 → datoon-1.8.0}/scripts/install.py +0 -0
  88. {datoon-1.7.4 → datoon-1.8.0}/scripts/summarize_agent_skill_eval.py +0 -0
  89. {datoon-1.7.4 → datoon-1.8.0}/scripts/validate_plugin_metadata.py +0 -0
  90. {datoon-1.7.4 → datoon-1.8.0}/scripts/validate_skill_sync.py +0 -0
  91. {datoon-1.7.4 → datoon-1.8.0}/server.json +0 -0
  92. {datoon-1.7.4 → datoon-1.8.0}/setup.cfg +0 -0
  93. {datoon-1.7.4 → datoon-1.8.0}/setup.sh +0 -0
  94. {datoon-1.7.4 → datoon-1.8.0}/skills/datoon/README.md +0 -0
  95. {datoon-1.7.4 → datoon-1.8.0}/skills/datoon/SKILL.md +0 -0
  96. {datoon-1.7.4 → datoon-1.8.0}/smithery.yaml +0 -0
  97. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/__init__.py +0 -0
  98. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/analyzer.py +0 -0
  99. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/converter.py +0 -0
  100. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/mcp_server.py +0 -0
  101. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/models.py +0 -0
  102. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/py.typed +0 -0
  103. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/_coerce.py +0 -0
  104. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/_tabular.py +0 -0
  105. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/columnar.py +0 -0
  106. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/csv.py +0 -0
  107. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/excel.py +0 -0
  108. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/jsonl.py +0 -0
  109. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/numbers.py +0 -0
  110. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/xml.py +0 -0
  111. {datoon-1.7.4 → datoon-1.8.0}/src/datoon/readers/yaml.py +0 -0
  112. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/SOURCES.txt +0 -0
  113. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/dependency_links.txt +0 -0
  114. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/entry_points.txt +0 -0
  115. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/requires.txt +0 -0
  116. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/scm_file_list.json +0 -0
  117. {datoon-1.7.4 → datoon-1.8.0}/src/datoon.egg-info/top_level.txt +0 -0
  118. {datoon-1.7.4 → datoon-1.8.0}/tests/fixtures/users.expected.toon +0 -0
  119. {datoon-1.7.4 → datoon-1.8.0}/tests/fixtures/users.json +0 -0
  120. {datoon-1.7.4 → datoon-1.8.0}/tests/integration/test_toon_cli_integration.py +0 -0
  121. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_analyzer.py +0 -0
  122. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_converter_policy.py +0 -0
  123. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_installer.py +0 -0
  124. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_mcp_server.py +0 -0
  125. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_models.py +0 -0
  126. {datoon-1.7.4 → datoon-1.8.0}/tests/unit/test_tabular_rows.py +0 -0
  127. {datoon-1.7.4 → datoon-1.8.0}/uv.lock +0 -0
@@ -1,3 +1,10 @@
1
+ # [1.8.0](https://github.com/andrii-su/datoon/compare/v1.7.4...v1.8.0) (2026-07-07)
2
+
3
+
4
+ ### Features
5
+
6
+ * **cli:** add --sheet and --table for excel/numbers input ([#39](https://github.com/andrii-su/datoon/issues/39)) ([4799712](https://github.com/andrii-su/datoon/commit/4799712b003ca4fae25cd555aec83b2b1cece136))
7
+
1
8
  ## [1.7.4](https://github.com/andrii-su/datoon/compare/v1.7.3...v1.7.4) (2026-07-07)
2
9
 
3
10
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datoon
3
- Version: 1.7.4
3
+ Version: 1.8.0
4
4
  Summary: Smart structured-data-to-TOON gateway with pragmatic auto-gating for LLM prompts.
5
5
  Author-email: Andrii Suruhov <andrii.suruhov@gmail.com>
6
6
  License: MIT License
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.7.4'
22
- __version_tuple__ = version_tuple = (1, 7, 4)
21
+ __version__ = version = '1.8.0'
22
+ __version_tuple__ = version_tuple = (1, 8, 0)
23
23
 
24
- __commit_id__ = commit_id = 'g9c1017702'
24
+ __commit_id__ = commit_id = 'gacb329fb8'
@@ -75,6 +75,18 @@ def build_parser() -> argparse.ArgumentParser:
75
75
  default=30,
76
76
  help="Seconds to wait for the TOON CLI before aborting (default: 30).",
77
77
  )
78
+ parser.add_argument(
79
+ "--sheet",
80
+ type=int,
81
+ default=0,
82
+ help="Worksheet index for excel/numbers input (default: 0).",
83
+ )
84
+ parser.add_argument(
85
+ "--table",
86
+ type=int,
87
+ default=0,
88
+ help="Table index within a Numbers sheet (default: 0).",
89
+ )
78
90
  parser.add_argument(
79
91
  "--report",
80
92
  help="Optional path to write conversion report as JSON.",
@@ -172,7 +184,9 @@ def main(argv: Sequence[str] | None = None) -> int:
172
184
  f"datoon error: --format {fmt} requires a file path, not stdin.\n"
173
185
  )
174
186
  return 1
175
- rows = read_tabular(fmt, path=Path(args.input))
187
+ rows = read_tabular(
188
+ fmt, path=Path(args.input), sheet=args.sheet, table=args.table
189
+ )
176
190
  json_text = json.dumps(rows, ensure_ascii=False, separators=(",", ":"))
177
191
  outcome = convert_json_for_llm(json_text, config)
178
192
  else:
@@ -37,16 +37,20 @@ def read_tabular(
37
37
  *,
38
38
  text: str | None = None,
39
39
  path: Path | None = None,
40
+ sheet: int = 0,
41
+ table: int = 0,
40
42
  ) -> list[dict[str, Any]]:
41
43
  """Read structured data and return rows as a list of dicts.
42
44
 
43
45
  Text formats (csv, jsonl, yaml, xml) require ``text``.
44
46
  Binary formats (excel, parquet, orc, avro, numbers) require ``path``.
47
+ ``sheet`` selects the worksheet for excel/numbers; ``table`` selects the
48
+ table within a Numbers sheet. Both are ignored by columnar formats.
45
49
  """
46
50
  if fmt in BINARY_FORMATS:
47
51
  if path is None:
48
52
  raise ValueError(f"Format '{fmt}' requires a file path, not text input.")
49
- return _read_binary(fmt, path)
53
+ return _read_binary(fmt, path, sheet=sheet, table=table)
50
54
  if fmt in TEXT_FORMATS:
51
55
  if text is None:
52
56
  raise ValueError(f"Format '{fmt}' requires text input.")
@@ -74,11 +78,13 @@ def _read_text(fmt: str, text: str) -> list[dict[str, Any]]:
74
78
  raise ValueError(f"Unknown text format: {fmt}")
75
79
 
76
80
 
77
- def _read_binary(fmt: str, path: Path) -> list[dict[str, Any]]:
81
+ def _read_binary(
82
+ fmt: str, path: Path, *, sheet: int = 0, table: int = 0
83
+ ) -> list[dict[str, Any]]:
78
84
  if fmt == "excel":
79
85
  from datoon.readers.excel import read_excel
80
86
 
81
- return read_excel(path)
87
+ return read_excel(path, sheet=sheet)
82
88
  if fmt == "parquet":
83
89
  from datoon.readers.columnar import read_parquet
84
90
 
@@ -94,5 +100,5 @@ def _read_binary(fmt: str, path: Path) -> list[dict[str, Any]]:
94
100
  if fmt == "numbers":
95
101
  from datoon.readers.numbers import read_numbers
96
102
 
97
- return read_numbers(path)
103
+ return read_numbers(path, sheet=sheet, table=table)
98
104
  raise ValueError(f"Unknown binary format: {fmt}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datoon
3
- Version: 1.7.4
3
+ Version: 1.8.0
4
4
  Summary: Smart structured-data-to-TOON gateway with pragmatic auto-gating for LLM prompts.
5
5
  Author-email: Andrii Suruhov <andrii.suruhov@gmail.com>
6
6
  License: MIT License
@@ -1,7 +1,7 @@
1
1
  {
2
- "tag": "1.7.4",
2
+ "tag": "1.8.0",
3
3
  "distance": 0,
4
- "node": "g9c10177027b097628e6bb075bb54501482175b78",
4
+ "node": "gacb329fb8ab013fc074f180d839e72bc2381dad3",
5
5
  "dirty": false,
6
6
  "branch": "HEAD",
7
7
  "node_date": "2026-07-07"
@@ -280,3 +280,38 @@ def test_mcp_subcommand_missing_extra_errors(
280
280
  rc = main(["mcp"])
281
281
  assert rc == 1
282
282
  assert "mcp" in capsys.readouterr().err
283
+
284
+
285
+ # ---------------------------------------------------------------------------
286
+ # --sheet / --table passthrough for spreadsheet formats
287
+ # ---------------------------------------------------------------------------
288
+
289
+
290
+ def test_main_forwards_sheet_and_table_for_binary(
291
+ monkeypatch: pytest.MonkeyPatch,
292
+ tmp_path: Path,
293
+ ) -> None:
294
+ captured: dict[str, int] = {}
295
+
296
+ def fake_read_tabular(
297
+ fmt: str,
298
+ *,
299
+ text: str | None = None,
300
+ path: Path | None = None,
301
+ sheet: int = 0,
302
+ table: int = 0,
303
+ ) -> list[dict[str, object]]:
304
+ captured["sheet"] = sheet
305
+ captured["table"] = table
306
+ return [{"id": 1, "v": "a"}]
307
+
308
+ monkeypatch.setattr("datoon.cli.read_tabular", fake_read_tabular)
309
+ monkeypatch.setattr("datoon.converter._run_toon_cli", lambda _, **kw: "x\n")
310
+ xlsx = tmp_path / "data.xlsx"
311
+ xlsx.write_bytes(b"")
312
+
313
+ rc = main(
314
+ ["--format", "excel", "--sheet", "2", "--table", "1", "--force", str(xlsx)]
315
+ )
316
+ assert rc == 0
317
+ assert captured == {"sheet": 2, "table": 1}
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import sys
6
+ from pathlib import Path
6
7
  from unittest.mock import MagicMock
7
8
 
8
9
  import pytest
@@ -317,6 +318,35 @@ def test_read_tabular_text_without_text_raises() -> None:
317
318
  read_tabular(fmt, path=None)
318
319
 
319
320
 
321
+ def test_read_tabular_forwards_sheet_to_excel(monkeypatch: pytest.MonkeyPatch) -> None:
322
+ captured: dict[str, int] = {}
323
+
324
+ def fake_read_excel(path: Path, *, sheet: int = 0) -> list[dict[str, int]]:
325
+ captured["sheet"] = sheet
326
+ return [{"a": 1}]
327
+
328
+ monkeypatch.setattr("datoon.readers.excel.read_excel", fake_read_excel)
329
+ read_tabular("excel", path=Path("x.xlsx"), sheet=2)
330
+ assert captured["sheet"] == 2
331
+
332
+
333
+ def test_read_tabular_forwards_sheet_and_table_to_numbers(
334
+ monkeypatch: pytest.MonkeyPatch,
335
+ ) -> None:
336
+ captured: dict[str, int] = {}
337
+
338
+ def fake_read_numbers(
339
+ path: Path, *, sheet: int = 0, table: int = 0
340
+ ) -> list[dict[str, int]]:
341
+ captured["sheet"] = sheet
342
+ captured["table"] = table
343
+ return [{"a": 1}]
344
+
345
+ monkeypatch.setattr("datoon.readers.numbers.read_numbers", fake_read_numbers)
346
+ read_tabular("numbers", path=Path("x.numbers"), sheet=1, table=3)
347
+ assert captured == {"sheet": 1, "table": 3}
348
+
349
+
320
350
  # ---------------------------------------------------------------------------
321
351
  # Format sets sanity
322
352
  # ---------------------------------------------------------------------------
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
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
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
File without changes
File without changes
File without changes
File without changes
File without changes