sql-harness 0.2.3__tar.gz → 0.2.4__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.
- {sql_harness-0.2.3 → sql_harness-0.2.4}/PKG-INFO +1 -1
- {sql_harness-0.2.3 → sql_harness-0.2.4}/pyproject.toml +1 -1
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/cli.py +10 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/test_cli.py +54 -3
- {sql_harness-0.2.3 → sql_harness-0.2.4}/uv.lock +1 -1
- {sql_harness-0.2.3 → sql_harness-0.2.4}/.claude-plugin/marketplace.json +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/.claude-plugin/plugin.json +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/.env.example +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/.gitignore +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/AGENTS.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/README.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/SKILL.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/README.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/agent_helpers.example.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/agent_helpers.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/zones/example_pg/scripts/sh_demo_crud.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/zones/example_pg/skills/sh_demo-schema.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/zones/meta/skills/pool.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/zones/meta/skills/workspace.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docker-services/coturn/README.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docker-services/coturn/docker-compose.yml +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docker-services/coturn/turnserver.conf +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docker-services/mysql/docker-compose.yml +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docker-services/redis/docker-compose.yml +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docs/connections-toml-example.toml +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docs/headless-notes.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docs/maintainer.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/docs/standalone-install.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/install.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/aggregations.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/docker-via-ssh.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/encoding-and-charset.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/indexes-and-explain.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/joins.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/json-columns.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/large-result-sets.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/migrations.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/pooling.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/postgres/btree-indexes.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/postgres/plan-reading.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/postgres/slow-queries-joins.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/postgres/specialized-indexes.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/postgres/table-optimization.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/recursive-ctes.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/references/aggregations-advanced.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/references/joins-advanced.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/references/recursive-ctes-patterns.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/references/window-functions-catalog.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/save-run-cycle.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/schema-introspection.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/ssh.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/timeouts-and-cancellation.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/transactions.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/window-functions.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/zone-skill-auto-surface.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/practice/pgexercises/README.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/skills/sql-harness/README.txt +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/skills/sql-harness/SKILL.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/skills/sql-harness/references/install.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/sql-harness +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/SKILL.md +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/__init__.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/agent_loader.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/config.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/drivers/__init__.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/drivers/mysql.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/drivers/postgres.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/drivers/redis.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/drivers/sqlite.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/drivers/ssh.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/helpers.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/manager.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/paths.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/src/sql_harness/run.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/__init__.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/conftest.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/integration/__init__.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/integration/test_mysql.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/integration/test_pg_optimization.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/integration/test_pgexercises_practice.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/integration/test_postgres.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/integration/test_ssh.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/__init__.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/test_agent_loader.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/test_config.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/test_helpers.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/test_manager.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/test_paths.py +0 -0
- {sql_harness-0.2.3 → sql_harness-0.2.4}/tests/unit/test_ssh.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sql-harness
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Single-process SQL + SSH CLI for LLM agents. PostgreSQL/MySQL/SSH via SQLAlchemy + paramiko. Plaintext credentials in one TOML file. Helpers auto-injected into the heredoc namespace.
|
|
5
5
|
Project-URL: Source, https://github.com/zhaoliuxue/much_bigpy/tree/master/lab/sql_harness
|
|
6
6
|
Project-URL: Issues, https://github.com/zhaoliuxue/much_bigpy/issues
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sql-harness"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.4"
|
|
4
4
|
description = "Single-process SQL + SSH CLI for LLM agents. PostgreSQL/MySQL/SSH via SQLAlchemy + paramiko. Plaintext credentials in one TOML file. Helpers auto-injected into the heredoc namespace."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -558,6 +558,13 @@ def cmd_save(args, _harness: SqlHarness) -> int:
|
|
|
558
558
|
conn, code = _require_connection_or_fail(args)
|
|
559
559
|
if code:
|
|
560
560
|
return code
|
|
561
|
+
# Read stdin as UTF-8 on Windows (default locale is GBK/CP936, which
|
|
562
|
+
# mangles non-ASCII bytes into surrogates that write_text rejects).
|
|
563
|
+
# Mirrors run.py's heredoc-mode stdin handling.
|
|
564
|
+
try:
|
|
565
|
+
sys.stdin.reconfigure(encoding="utf-8", errors="replace")
|
|
566
|
+
except (AttributeError, OSError):
|
|
567
|
+
pass
|
|
561
568
|
body = sys.stdin.read()
|
|
562
569
|
if not body.strip():
|
|
563
570
|
print("error: stdin is empty; nothing to save", file=sys.stderr)
|
|
@@ -616,6 +623,9 @@ def cmd_run(args, harness: SqlHarness) -> int:
|
|
|
616
623
|
for n, v in vars(helpers).items():
|
|
617
624
|
if not n.startswith("_"):
|
|
618
625
|
namespace[n] = v
|
|
626
|
+
# Parity with heredoc mode (run.py globals): expose `sys` so saved
|
|
627
|
+
# scripts can use sys.stdout.write etc. without importing it.
|
|
628
|
+
namespace["sys"] = sys
|
|
619
629
|
code_text = path.read_text(encoding="utf-8")
|
|
620
630
|
try:
|
|
621
631
|
exec(compile(code_text, str(path), "exec"), namespace)
|
|
@@ -10,8 +10,14 @@ from pathlib import Path
|
|
|
10
10
|
import pytest
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def _run_cli(
|
|
14
|
-
|
|
13
|
+
def _run_cli(
|
|
14
|
+
*args: str, env: dict | None = None, input: str | None = None
|
|
15
|
+
) -> subprocess.CompletedProcess:
|
|
16
|
+
"""Run sql-harness in a subprocess; capture UTF-8 output.
|
|
17
|
+
|
|
18
|
+
`input` (when given) is piped to the child's stdin as UTF-8 — used to
|
|
19
|
+
exercise `save`, which reads its heredoc body from stdin.
|
|
20
|
+
"""
|
|
15
21
|
import os
|
|
16
22
|
|
|
17
23
|
full_env = os.environ.copy()
|
|
@@ -24,6 +30,7 @@ def _run_cli(*args: str, env: dict | None = None) -> subprocess.CompletedProcess
|
|
|
24
30
|
encoding="utf-8",
|
|
25
31
|
errors="replace",
|
|
26
32
|
env=full_env,
|
|
33
|
+
input=input,
|
|
27
34
|
)
|
|
28
35
|
|
|
29
36
|
|
|
@@ -219,4 +226,48 @@ def test_open_scripts_requires_connection(tmp_path: Path) -> None:
|
|
|
219
226
|
"""`open scripts` without --connection errors with guidance."""
|
|
220
227
|
p = _run_cli("open", "scripts", env={"BH_SQL_HOME": str(tmp_path)})
|
|
221
228
|
assert p.returncode == 2
|
|
222
|
-
assert "zone-scoped" in p.stderr
|
|
229
|
+
assert "zone-scoped" in p.stderr
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _write_sqlite_cfg(tmp_path: Path) -> None:
|
|
233
|
+
"""Seed an isolated BH_SQL_HOME with a single sqlite connection."""
|
|
234
|
+
(tmp_path / "connections.toml").write_text(
|
|
235
|
+
'[[connections]]\n'
|
|
236
|
+
'name = "mem"\n'
|
|
237
|
+
'driver = "sqlite"\n'
|
|
238
|
+
'url = "sqlite:///:memory:"\n',
|
|
239
|
+
encoding="utf-8",
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def test_save_preserves_utf8_stdin(tmp_path: Path) -> None:
|
|
244
|
+
"""`save` reads stdin as UTF-8 even on Windows (cp936 default locale).
|
|
245
|
+
|
|
246
|
+
Regression: non-ASCII bytes in the heredoc body were decoded into
|
|
247
|
+
surrogates and write_text(utf-8) raised UnicodeEncodeError.
|
|
248
|
+
"""
|
|
249
|
+
_write_sqlite_cfg(tmp_path)
|
|
250
|
+
body = "# 服务器内存检查\nprint('ok')\n"
|
|
251
|
+
p = _run_cli(
|
|
252
|
+
"save", "utf8", "-c", "mem", input=body, env={"BH_SQL_HOME": str(tmp_path)}
|
|
253
|
+
)
|
|
254
|
+
assert p.returncode == 0, p.stderr
|
|
255
|
+
saved = Path(json.loads(p.stdout)["path"])
|
|
256
|
+
assert "服务器内存检查" in saved.read_text(encoding="utf-8")
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def test_run_namespace_exposes_sys(tmp_path: Path) -> None:
|
|
260
|
+
"""`run` exec namespace includes `sys`, matching heredoc mode.
|
|
261
|
+
|
|
262
|
+
Regression: saved scripts that used `sys.stdout.write` without
|
|
263
|
+
`import sys` (as ssh.md documents) failed with NameError.
|
|
264
|
+
"""
|
|
265
|
+
_write_sqlite_cfg(tmp_path)
|
|
266
|
+
body = "sys.stdout.write('ok-from-sys')\n" # relies on pre-imported sys
|
|
267
|
+
p = _run_cli(
|
|
268
|
+
"save", "usesys", "-c", "mem", input=body, env={"BH_SQL_HOME": str(tmp_path)}
|
|
269
|
+
)
|
|
270
|
+
assert p.returncode == 0, p.stderr
|
|
271
|
+
p2 = _run_cli("run", "usesys", "-c", "mem", env={"BH_SQL_HOME": str(tmp_path)})
|
|
272
|
+
assert p2.returncode == 0, p2.stderr
|
|
273
|
+
assert "ok-from-sys" in p2.stdout
|
|
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
|
{sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/zones/example_pg/scripts/sh_demo_crud.py
RENAMED
|
File without changes
|
{sql_harness-0.2.3 → sql_harness-0.2.4}/agent-workspace/zones/example_pg/skills/sh_demo-schema.md
RENAMED
|
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
|
{sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/references/aggregations-advanced.md
RENAMED
|
File without changes
|
|
File without changes
|
{sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/references/recursive-ctes-patterns.md
RENAMED
|
File without changes
|
{sql_harness-0.2.3 → sql_harness-0.2.4}/interaction-skills/references/window-functions-catalog.md
RENAMED
|
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
|