dirsql 0.3.57__tar.gz → 0.3.58__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.
- {dirsql-0.3.57 → dirsql-0.3.58}/Cargo.lock +1 -1
- {dirsql-0.3.57 → dirsql-0.3.58}/PKG-INFO +1 -1
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/Cargo.toml +1 -1
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/e2e-attestation.json +2 -2
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/cli/init.rs +17 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/cli/server.rs +29 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/command.rs +99 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/lib.rs +559 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/persist.rs +70 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/Cargo.toml +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/README.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/_async.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/cli/binary_path.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/cli/interpret/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/cli/is_windows.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/cli/main.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/py.typed +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/AGENTS.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/api/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/cli/config.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/cli/http-api.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/cli/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/cli/init.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/cli/server.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/getting-started.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/guide/async.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/guide/crdt.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/guide/persistence.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/guide/querying.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/guide/tables.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/guide/watching.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/migrations.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/package.json +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/playwright.config.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/docs/vitest.config.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/README.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/conftest.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/api/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/cli/config.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/cli/http-api.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/cli/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/cli/init.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/cli/server.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/guide/async.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/guide/crdt.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/guide/persistence.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/guide/querying.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/guide/tables.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/guide/watching.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/package.json +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/playwright.config.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/docs/vitest.config.ts +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/src/lib.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/tests/binding/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/python/tests/smoke/__init__.py +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/README.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/api/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/cli/config.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/cli/http-api.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/cli/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/cli/init.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/cli/server.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/guide/async.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/guide/crdt.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/guide/persistence.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/guide/querying.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/guide/tables.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/guide/watching.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/index.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/config.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/db.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.3.57 → dirsql-0.3.58}/pyproject.toml +0 -0
|
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
|
|
|
4
4
|
# pypi/maturin handler can rewrite it via `write-version` before
|
|
5
5
|
# `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
|
|
6
6
|
# and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.58"
|
|
8
8
|
edition.workspace = true
|
|
9
9
|
publish = false
|
|
10
10
|
readme = "README.md"
|
|
@@ -149,4 +149,21 @@ mod tests {
|
|
|
149
149
|
let msg = format!("{err}").to_lowercase();
|
|
150
150
|
assert!(msg.contains("claude"));
|
|
151
151
|
}
|
|
152
|
+
|
|
153
|
+
/// `run` bails before spawning the agent when the output already exists and
|
|
154
|
+
/// `--force` was not passed (the temp dir itself is an existing path).
|
|
155
|
+
#[test]
|
|
156
|
+
fn run_bails_when_output_exists_without_force() {
|
|
157
|
+
let dir = tempfile::tempdir().unwrap();
|
|
158
|
+
let opts = InitOptions {
|
|
159
|
+
root: dir.path().to_path_buf(),
|
|
160
|
+
output: dir.path().to_path_buf(),
|
|
161
|
+
force: false,
|
|
162
|
+
};
|
|
163
|
+
let err = run(opts).unwrap_err();
|
|
164
|
+
assert!(
|
|
165
|
+
matches!(err, InitError::AlreadyExists { .. }),
|
|
166
|
+
"got: {err:?}"
|
|
167
|
+
);
|
|
168
|
+
}
|
|
152
169
|
}
|
|
@@ -114,4 +114,33 @@ mod tests {
|
|
|
114
114
|
|
|
115
115
|
handle.shutdown().await.expect("graceful shutdown");
|
|
116
116
|
}
|
|
117
|
+
|
|
118
|
+
// A `Ready` state drives the `serve` convenience wrapper plus
|
|
119
|
+
// `start_watch_task` (which attaches `DirSQL::watch` and pumps its stream
|
|
120
|
+
// into the broadcast channel). Built over an empty temp dir so the scan
|
|
121
|
+
// touches nothing; the port-0 bind and graceful shutdown are real.
|
|
122
|
+
#[tokio::test]
|
|
123
|
+
async fn serve_with_a_ready_db_attaches_the_watcher_then_shuts_down() {
|
|
124
|
+
let dir = tempfile::tempdir().unwrap();
|
|
125
|
+
let db = DirSQL::new(dir.path(), Vec::new()).unwrap();
|
|
126
|
+
let config = ServerConfig::bind("127.0.0.1".to_string(), 0);
|
|
127
|
+
let handle = serve(config, db).await.expect("bind on an ephemeral port");
|
|
128
|
+
assert_ne!(handle.local_addr().port(), 0);
|
|
129
|
+
handle.shutdown().await.expect("graceful shutdown");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Binding to a non-local TEST-NET address (RFC 5737) fails with
|
|
133
|
+
// "cannot assign requested address", surfacing `ServerError::Bind` rather
|
|
134
|
+
// than panicking — deterministic and DNS-free.
|
|
135
|
+
#[tokio::test]
|
|
136
|
+
async fn serve_with_state_surfaces_a_bind_error_for_a_nonlocal_address() {
|
|
137
|
+
let config = ServerConfig::bind("192.0.2.1".to_string(), 9);
|
|
138
|
+
// `serve_with_state` returns `Result<ServerHandle, _>`; ServerHandle is
|
|
139
|
+
// not Debug, so match rather than `unwrap_err`.
|
|
140
|
+
let err = match serve_with_state(config, AppState::Unavailable("x".to_string())).await {
|
|
141
|
+
Ok(_) => panic!("expected a bind error"),
|
|
142
|
+
Err(e) => e,
|
|
143
|
+
};
|
|
144
|
+
assert!(matches!(err, ServerError::Bind { .. }), "got: {err:?}");
|
|
145
|
+
}
|
|
117
146
|
}
|
|
@@ -484,4 +484,103 @@ mod tests {
|
|
|
484
484
|
assert!(!Placeholder::new("a", "b").append_if_absent);
|
|
485
485
|
assert!(Placeholder::append("a", "b").append_if_absent);
|
|
486
486
|
}
|
|
487
|
+
|
|
488
|
+
// ----- run_command end-to-end (spawns trivial POSIX commands) ----------
|
|
489
|
+
//
|
|
490
|
+
// `run_command` can only be exercised by actually spawning a child, so
|
|
491
|
+
// these drive `sh`/`echo`/`cat` — universally present on the Linux CI
|
|
492
|
+
// runners. The test code itself statically references only `super::` items,
|
|
493
|
+
// `Duration`, and `std::path::Path`, so the `unit lint` isolation rule is
|
|
494
|
+
// satisfied; the effectful process/thread work lives in production code.
|
|
495
|
+
|
|
496
|
+
fn cwd() -> std::path::PathBuf {
|
|
497
|
+
std::path::PathBuf::from(".")
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
#[test]
|
|
501
|
+
fn run_command_returns_last_nonempty_stdout_line() {
|
|
502
|
+
let out = run_command(
|
|
503
|
+
"sh -c 'echo chatter; echo PAYLOAD'",
|
|
504
|
+
&[],
|
|
505
|
+
&cwd(),
|
|
506
|
+
Duration::from_secs(30),
|
|
507
|
+
None,
|
|
508
|
+
)
|
|
509
|
+
.unwrap();
|
|
510
|
+
assert_eq!(out.payload, "PAYLOAD");
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
#[test]
|
|
514
|
+
fn run_command_writes_stdin_payload_to_the_child() {
|
|
515
|
+
// `cat` echoes its stdin, so the payload round-trips through the
|
|
516
|
+
// stdin-writer thread and the stdout drain.
|
|
517
|
+
let out = run_command(
|
|
518
|
+
"cat",
|
|
519
|
+
&[],
|
|
520
|
+
&cwd(),
|
|
521
|
+
Duration::from_secs(30),
|
|
522
|
+
Some(b"hello-stdin"),
|
|
523
|
+
)
|
|
524
|
+
.unwrap();
|
|
525
|
+
assert_eq!(out.payload, "hello-stdin");
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
#[test]
|
|
529
|
+
fn run_command_reports_nonzero_exit_with_stderr_tail() {
|
|
530
|
+
let err = run_command(
|
|
531
|
+
"sh -c 'echo oops >&2; exit 3'",
|
|
532
|
+
&[],
|
|
533
|
+
&cwd(),
|
|
534
|
+
Duration::from_secs(30),
|
|
535
|
+
None,
|
|
536
|
+
)
|
|
537
|
+
.unwrap_err();
|
|
538
|
+
match err {
|
|
539
|
+
CommandError::NonZeroExit {
|
|
540
|
+
code, stderr_tail, ..
|
|
541
|
+
} => {
|
|
542
|
+
assert_eq!(code, "3");
|
|
543
|
+
assert!(stderr_tail.contains("oops"), "got: {stderr_tail}");
|
|
544
|
+
}
|
|
545
|
+
other => panic!("expected NonZeroExit, got {other:?}"),
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
#[test]
|
|
550
|
+
fn run_command_reports_empty_output_when_stdout_is_blank() {
|
|
551
|
+
let err = run_command("true", &[], &cwd(), Duration::from_secs(30), None).unwrap_err();
|
|
552
|
+
assert!(
|
|
553
|
+
matches!(err, CommandError::EmptyOutput { .. }),
|
|
554
|
+
"got: {err:?}"
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
#[test]
|
|
559
|
+
fn run_command_reports_spawn_failure_for_a_missing_program() {
|
|
560
|
+
let err = run_command(
|
|
561
|
+
"definitely-not-a-real-binary-xyzzy",
|
|
562
|
+
&[],
|
|
563
|
+
&cwd(),
|
|
564
|
+
Duration::from_secs(30),
|
|
565
|
+
None,
|
|
566
|
+
)
|
|
567
|
+
.unwrap_err();
|
|
568
|
+
assert!(matches!(err, CommandError::Spawn { .. }), "got: {err:?}");
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
#[test]
|
|
572
|
+
fn run_command_kills_and_reports_timeout_even_with_stdin() {
|
|
573
|
+
// A short timeout against a long sleep drives the timeout branch,
|
|
574
|
+
// including joining the stdin-writer thread. `sh` ignoring stdin closes
|
|
575
|
+
// the pipe early, which the writer treats as a clean EOF.
|
|
576
|
+
let err = run_command(
|
|
577
|
+
"sh -c 'sleep 30'",
|
|
578
|
+
&[],
|
|
579
|
+
&cwd(),
|
|
580
|
+
Duration::from_millis(50),
|
|
581
|
+
Some(b"x"),
|
|
582
|
+
)
|
|
583
|
+
.unwrap_err();
|
|
584
|
+
assert!(matches!(err, CommandError::Timeout { .. }), "got: {err:?}");
|
|
585
|
+
}
|
|
487
586
|
}
|