dirsql 0.4.83__tar.gz → 0.4.85__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.4.83 → dirsql-0.4.85}/Cargo.lock +2 -2
- {dirsql-0.4.83 → dirsql-0.4.85}/PKG-INFO +1 -1
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/_async.py +27 -7
- {dirsql-0.4.83/packages/rust → dirsql-0.4.85}/docs/reference/config.md +4 -0
- {dirsql-0.4.83/packages/rust → dirsql-0.4.85}/docs/reference/http-api.md +1 -1
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/sdk.md +4 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/Cargo.toml +1 -1
- dirsql-0.4.85/packages/python/changelog.d/2026-10-06-one-glob-compiler.md +3 -0
- dirsql-0.4.85/packages/python/changelog.d/2026-10-06-watch-broadcast.md +3 -0
- dirsql-0.4.85/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +3 -0
- {dirsql-0.4.83 → dirsql-0.4.85/packages/python}/docs/reference/config.md +4 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/http-api.md +1 -1
- {dirsql-0.4.83/packages/rust → dirsql-0.4.85/packages/python}/docs/reference/sdk.md +4 -0
- dirsql-0.4.85/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +7 -0
- dirsql-0.4.85/packages/python/e2e-attestations/bot-1398-inotify-error.json +7 -0
- dirsql-0.4.85/packages/python/e2e-attestations/bot-1407-child-place-depth.json +7 -0
- dirsql-0.4.85/packages/python/e2e-attestations/claude-1232-zero-match.json +7 -0
- dirsql-0.4.85/packages/python/e2e-attestations/claude-1258-one-pattern.json +7 -0
- dirsql-0.4.85/packages/python/e2e-attestations/claude-1330-vtab-prefetch-flag.json +7 -0
- dirsql-0.4.85/packages/python/migrations.d/2026-10-06-one-glob-compiler.md +28 -0
- dirsql-0.4.85/packages/python/migrations.d/2026-10-06-watch-broadcast.md +46 -0
- dirsql-0.4.85/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +25 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/Cargo.toml +1 -1
- {dirsql-0.4.83/packages/python → dirsql-0.4.85/packages/rust}/docs/reference/config.md +4 -0
- {dirsql-0.4.83 → dirsql-0.4.85/packages/rust}/docs/reference/http-api.md +1 -1
- {dirsql-0.4.83/packages/python → dirsql-0.4.85/packages/rust}/docs/reference/sdk.md +4 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/router.rs +19 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/server.rs +39 -11
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/lib.rs +69 -5
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/matcher.rs +3 -2
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/scanner.rs +29 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/vtab_scaffold.rs +1 -1
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/watcher.rs +74 -2
- {dirsql-0.4.83 → dirsql-0.4.85}/Cargo.toml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/README.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/plan_entry_path.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/py.typed +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/read_config.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/resolve_configs_extension_specs.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/resolve_package.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/AGENTS.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/.gitattributes +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/recipes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/usage.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/explanation.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/getting-started.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/embed.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/persist.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/query-json.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/index.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/package.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/plugins.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/cli.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/columns.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/README.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/conftest.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/.gitattributes +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/recipes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/usage.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/query-json.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/cli.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1232-config-anchor.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1232-multi-watch.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/src/lib.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/testing-conventions.toml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/speed_of_light.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/README.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/.gitattributes +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/recipes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/usage.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/query-json.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/cli.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/brace.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/context.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/repl.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/run.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/table.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/command.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/config.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/db.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/extension_resolution.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/launcher.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/listing.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/on_file.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/parsed_vtab.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/path_table.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/posix_class.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/progress.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/row_event_flat.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/sql_literal.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/tree_walk.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.83 → dirsql-0.4.85}/pyproject.toml +0 -0
|
@@ -552,7 +552,7 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
|
|
552
552
|
|
|
553
553
|
[[package]]
|
|
554
554
|
name = "dirsql"
|
|
555
|
-
version = "0.4.
|
|
555
|
+
version = "0.4.85"
|
|
556
556
|
dependencies = [
|
|
557
557
|
"assert_cmd",
|
|
558
558
|
"axum",
|
|
@@ -602,7 +602,7 @@ dependencies = [
|
|
|
602
602
|
|
|
603
603
|
[[package]]
|
|
604
604
|
name = "dirsql-py-ext"
|
|
605
|
-
version = "0.4.
|
|
605
|
+
version = "0.4.85"
|
|
606
606
|
dependencies = [
|
|
607
607
|
"dirsql",
|
|
608
608
|
"pyo3",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import os
|
|
5
|
+
import weakref
|
|
5
6
|
|
|
6
7
|
from dirsql._dirsql import DirSQL as _RustDirSQL
|
|
7
8
|
from dirsql.resolve_configs_extension_specs import resolve_configs_extension_specs
|
|
@@ -9,13 +10,18 @@ from dirsql.resolve_extension import resolve_extension_path
|
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class _WatchStream:
|
|
12
|
-
"""Async iterator
|
|
13
|
+
"""Async iterator of file events.
|
|
14
|
+
|
|
15
|
+
Every stream on one ``DirSQL`` receives every event observed after it
|
|
16
|
+
was created: one shared poll fills the buffer of each live stream.
|
|
17
|
+
"""
|
|
13
18
|
|
|
14
19
|
def __init__(self, owner):
|
|
15
20
|
self._owner = owner
|
|
16
21
|
self._db = None
|
|
17
22
|
self._started = False
|
|
18
23
|
self._buffer = []
|
|
24
|
+
owner._watch_streams.add(self)
|
|
19
25
|
|
|
20
26
|
def __aiter__(self):
|
|
21
27
|
return self
|
|
@@ -29,14 +35,22 @@ class _WatchStream:
|
|
|
29
35
|
await asyncio.to_thread(db._start_watcher)
|
|
30
36
|
self._started = True
|
|
31
37
|
|
|
38
|
+
owner = self._owner
|
|
39
|
+
while not self._buffer:
|
|
40
|
+
poll = owner._watch_poll
|
|
41
|
+
if poll is None or poll.done():
|
|
42
|
+
poll = owner._watch_poll = asyncio.ensure_future(self._poll())
|
|
43
|
+
# Shielded so a cancelled consumer cannot drop a batch that the
|
|
44
|
+
# other streams are still waiting on.
|
|
45
|
+
await asyncio.shield(poll)
|
|
46
|
+
return self._buffer.pop(0)
|
|
47
|
+
|
|
48
|
+
async def _poll(self):
|
|
32
49
|
db = self._db
|
|
33
50
|
assert db is not None
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
events = await asyncio.to_thread(db._poll_events, 200)
|
|
38
|
-
if events:
|
|
39
|
-
self._buffer.extend(events)
|
|
51
|
+
events = await asyncio.to_thread(db._poll_events, 200)
|
|
52
|
+
for stream in list(self._owner._watch_streams):
|
|
53
|
+
stream._buffer.extend(events)
|
|
40
54
|
|
|
41
55
|
|
|
42
56
|
class DirSQL:
|
|
@@ -107,6 +121,8 @@ class DirSQL:
|
|
|
107
121
|
self._db = None
|
|
108
122
|
self._ready_event = asyncio.Event()
|
|
109
123
|
self._init_error = None
|
|
124
|
+
self._watch_streams = weakref.WeakSet()
|
|
125
|
+
self._watch_poll = None
|
|
110
126
|
self._task = asyncio.ensure_future(self._init_bg())
|
|
111
127
|
|
|
112
128
|
async def _init_bg(self):
|
|
@@ -218,5 +234,9 @@ class DirSQL:
|
|
|
218
234
|
before an explicit ``await db.ready()`` waits for the background scan
|
|
219
235
|
(and surfaces any initialization error) instead of failing on a
|
|
220
236
|
still-``None`` ``_db``.
|
|
237
|
+
|
|
238
|
+
Each call returns an independent stream, and every stream receives
|
|
239
|
+
every event observed after it was created, so several consumers
|
|
240
|
+
(one per client, say) can share one instance.
|
|
221
241
|
"""
|
|
222
242
|
return _WatchStream(self)
|
|
@@ -274,6 +274,10 @@ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
|
|
|
274
274
|
writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
|
|
275
275
|
columns, `{root}`, and `ignore` are all relative to its anchor.
|
|
276
276
|
|
|
277
|
+
A table whose glob matches no files prints
|
|
278
|
+
`dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under <anchor>`
|
|
279
|
+
to stderr; the exit code is unchanged. Path-tables and programmatic tables do not warn.
|
|
280
|
+
|
|
277
281
|
### Batch `ddl`
|
|
278
282
|
|
|
279
283
|
`ddl` is handed to SQLite whole, so a table declaration is not limited to one
|
|
@@ -112,4 +112,4 @@ Row values serialize as in [`POST /query`](#value-serialization).
|
|
|
112
112
|
|---|---|
|
|
113
113
|
| `200` | Stream opened (`text/event-stream`). |
|
|
114
114
|
| `405` | `POST /events`. Plain-text body `method not allowed`. |
|
|
115
|
-
| `503` | The server is in [degraded mode](./cli.md#degraded-mode). JSON `{"error": …}` body. |
|
|
115
|
+
| `503` | The server is in [degraded mode](./cli.md#degraded-mode), or its filesystem watcher failed to start (for example, the inotify limit is exhausted). JSON `{"error": …}` body; for a watcher failure the message starts `filesystem watcher failed to start:` and gives the reason. `POST /query` keeps working. |
|
|
@@ -301,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
|
|
|
301
301
|
or at the `watch()` call (Rust). The stream never terminates on its own;
|
|
302
302
|
stop consuming it to stop.
|
|
303
303
|
|
|
304
|
+
Python: each `watch()` call returns an independent stream, and every stream
|
|
305
|
+
on one instance receives every event observed after it was created, so
|
|
306
|
+
several consumers (one per client, say) can share one instance.
|
|
307
|
+
|
|
304
308
|
Rust: `watch()` may be called once per instance and is mutually exclusive
|
|
305
309
|
with the polling API below — mixing them returns an error, since both drain
|
|
306
310
|
the same underlying filesystem watcher.
|
|
@@ -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.4.
|
|
7
|
+
version = "0.4.85"
|
|
8
8
|
# abi3 note: the `abi3-py310` pyo3 feature (below) builds ONE stable-ABI
|
|
9
9
|
# `cp310-abi3` wheel per platform that loads on every CPython >= 3.10
|
|
10
10
|
# (matching `pyproject.toml`'s `requires-python = ">=3.10"`), instead of
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
**Added**
|
|
2
|
+
|
|
3
|
+
- **A config `[[table]]` whose glob matches no files now prints a warning to stderr.** `dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under /home/u/.claude` names the table, the glob and the directory it was matched under, so a glob that silently indexes nothing is visible. The exit code is unchanged, and path-tables and programmatic tables do not warn. (#1232)
|
|
@@ -274,6 +274,10 @@ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
|
|
|
274
274
|
writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
|
|
275
275
|
columns, `{root}`, and `ignore` are all relative to its anchor.
|
|
276
276
|
|
|
277
|
+
A table whose glob matches no files prints
|
|
278
|
+
`dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under <anchor>`
|
|
279
|
+
to stderr; the exit code is unchanged. Path-tables and programmatic tables do not warn.
|
|
280
|
+
|
|
277
281
|
### Batch `ddl`
|
|
278
282
|
|
|
279
283
|
`ddl` is handed to SQLite whole, so a table declaration is not limited to one
|
|
@@ -112,4 +112,4 @@ Row values serialize as in [`POST /query`](#value-serialization).
|
|
|
112
112
|
|---|---|
|
|
113
113
|
| `200` | Stream opened (`text/event-stream`). |
|
|
114
114
|
| `405` | `POST /events`. Plain-text body `method not allowed`. |
|
|
115
|
-
| `503` | The server is in [degraded mode](./cli.md#degraded-mode). JSON `{"error": …}` body. |
|
|
115
|
+
| `503` | The server is in [degraded mode](./cli.md#degraded-mode), or its filesystem watcher failed to start (for example, the inotify limit is exhausted). JSON `{"error": …}` body; for a watcher failure the message starts `filesystem watcher failed to start:` and gives the reason. `POST /query` keeps working. |
|
|
@@ -301,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
|
|
|
301
301
|
or at the `watch()` call (Rust). The stream never terminates on its own;
|
|
302
302
|
stop consuming it to stop.
|
|
303
303
|
|
|
304
|
+
Python: each `watch()` call returns an independent stream, and every stream
|
|
305
|
+
on one instance receives every event observed after it was created, so
|
|
306
|
+
several consumers (one per client, say) can share one instance.
|
|
307
|
+
|
|
304
308
|
Rust: `watch()` may be called once per instance and is mutually exclusive
|
|
305
309
|
with the polling API below — mixing them returns an error, since both drain
|
|
306
310
|
the same underlying filesystem watcher.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/on_file_query_test.py tests/e2e/fanout_test.py tests/e2e/query_contract_test.py tests/integration/binding/async_dirsql_test.py -x -q",
|
|
3
|
+
"ran_at": 1791309204,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "9a473a8812b974362a7c408132a9724aac50605a",
|
|
6
|
+
"branch": "bot/1397-watch-broadcast"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/fanout_test.py tests/e2e/capture_collision_test.py tests/e2e/declared_table_name_test.py tests/e2e/extension_package_test.py tests/e2e/plugin_discovery_test.py tests/e2e/use_case_notebook_test.py tests/e2e/on_file_query_test.py tests/e2e/use_case_transcripts_test.py tests/e2e/plugin_extension_discovery_test.py tests/e2e/use_case_join_test.py tests/e2e/use_case_dossier_test.py tests/e2e/sigint_interrupt_test.py tests/e2e/query_contract_test.py -x -q",
|
|
3
|
+
"ran_at": 1791306078,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "8b587de39902adf33e4ebaa957a8fd0005875029",
|
|
6
|
+
"branch": "claude/1232-zero-match"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/capture_collision_test.py tests/e2e/declared_table_name_test.py tests/e2e/extension_package_test.py tests/e2e/query_contract_test.py tests/e2e/plugin_discovery_test.py tests/e2e/sigint_interrupt_test.py tests/e2e/fanout_test.py tests/e2e/use_case_transcripts_test.py tests/e2e/plugin_extension_discovery_test.py -x -q",
|
|
3
|
+
"ran_at": 1791301900,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "14d2a11edd69bb0715bbffdb085b1d6582728dd8",
|
|
6
|
+
"branch": "claude/1258-one-pattern"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/query_contract_test.py tests/e2e/declared_table_name_test.py tests/e2e/fanout_test.py -x -q",
|
|
3
|
+
"ran_at": 1791310416,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "bcedde49401cf6f9cc01deb2d95af1d1e907f0f7",
|
|
6
|
+
"branch": "claude/1330-vtab-prefetch-flag"
|
|
7
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
### Config table globs share the path-table glob compiler
|
|
2
|
+
|
|
3
|
+
#### Summary
|
|
4
|
+
|
|
5
|
+
A declared `[[table]] glob` is now compiled by the same compiler as a
|
|
6
|
+
path-table. A brace range such as `f{1..3}.md` expands as in bash instead of
|
|
7
|
+
matching nothing. Nothing else changes.
|
|
8
|
+
|
|
9
|
+
#### Required changes
|
|
10
|
+
|
|
11
|
+
_None._
|
|
12
|
+
|
|
13
|
+
#### Deprecations removed
|
|
14
|
+
|
|
15
|
+
_None._
|
|
16
|
+
|
|
17
|
+
#### Behavior changes without code changes
|
|
18
|
+
|
|
19
|
+
- `glob = "f{1..3}.md"` matches `f1.md`, `f2.md` and `f3.md`.
|
|
20
|
+
|
|
21
|
+
#### Verification
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cd "$(mktemp -d)"
|
|
25
|
+
touch f1.md f2.md f3.md f4.md
|
|
26
|
+
dirsql query "SELECT path FROM './f{1..3}.md' ORDER BY path"
|
|
27
|
+
# expected: [{"path":"f1.md"},{"path":"f2.md"},{"path":"f3.md"}]
|
|
28
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
### Every Python `watch()` stream receives every event (#1397)
|
|
2
|
+
|
|
3
|
+
#### Summary
|
|
4
|
+
|
|
5
|
+
Several `DirSQL.watch()` streams on one Python instance each receive every event, instead of splitting them. A single stream behaves as before. Nothing breaks.
|
|
6
|
+
|
|
7
|
+
#### Required changes
|
|
8
|
+
|
|
9
|
+
_None._
|
|
10
|
+
|
|
11
|
+
#### Deprecations removed
|
|
12
|
+
|
|
13
|
+
_None._
|
|
14
|
+
|
|
15
|
+
#### Behavior changes without code changes
|
|
16
|
+
|
|
17
|
+
- With more than one `watch()` stream on one instance, each stream now yields every event observed after it was created. Code that hand-rolled fan-out over one stream keeps working.
|
|
18
|
+
|
|
19
|
+
#### Verification
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import asyncio, pathlib, tempfile
|
|
23
|
+
from dirsql import DirSQL, Table
|
|
24
|
+
|
|
25
|
+
async def main():
|
|
26
|
+
root = pathlib.Path(tempfile.mkdtemp())
|
|
27
|
+
table = Table(
|
|
28
|
+
name="files",
|
|
29
|
+
ddl="CREATE TABLE files (n INTEGER)",
|
|
30
|
+
glob="*.json",
|
|
31
|
+
on_file=lambda path: [{"n": 1}],
|
|
32
|
+
)
|
|
33
|
+
db = DirSQL(str(root), tables=[table])
|
|
34
|
+
await db.ready()
|
|
35
|
+
|
|
36
|
+
async def first(stream):
|
|
37
|
+
async for event in stream:
|
|
38
|
+
return event.action
|
|
39
|
+
|
|
40
|
+
tasks = [asyncio.create_task(first(db.watch())) for _ in range(2)]
|
|
41
|
+
await asyncio.sleep(0.3)
|
|
42
|
+
(root / "a.json").write_text("{}")
|
|
43
|
+
print(await asyncio.wait_for(asyncio.gather(*tasks), 5)) # ['insert', 'insert']
|
|
44
|
+
|
|
45
|
+
asyncio.run(main())
|
|
46
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
### Empty config tables warn on stderr (#1232)
|
|
2
|
+
|
|
3
|
+
#### Summary
|
|
4
|
+
|
|
5
|
+
A config `[[table]]` whose glob matches no files writes one line to stderr at startup. Nothing else changes: the query still runs and the exit code is the same.
|
|
6
|
+
|
|
7
|
+
#### Required changes
|
|
8
|
+
|
|
9
|
+
_None._ A script that treats any stderr output as failure should fix the glob or drop the table.
|
|
10
|
+
|
|
11
|
+
#### Deprecations removed
|
|
12
|
+
|
|
13
|
+
_None._
|
|
14
|
+
|
|
15
|
+
#### Behavior changes without code changes
|
|
16
|
+
|
|
17
|
+
- stderr gains `dirsql: table '<name>': glob '<glob>' matched no files under <anchor>` for each config table that matched nothing.
|
|
18
|
+
|
|
19
|
+
#### Verification
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
mkdir -p /tmp/cfg /tmp/elsewhere
|
|
23
|
+
printf '[[table]]\nname = "t"\nddl = "CREATE TABLE t (n TEXT)"\nglob = "nothing/*.jsonl"\non-file = "printf []"\n' > /tmp/cfg/.dirsql.toml
|
|
24
|
+
cd /tmp/elsewhere && dirsql query "SELECT COUNT(*) AS n FROM t" -c /tmp/cfg/.dirsql.toml # stderr: dirsql: table 't': glob 'nothing/*.jsonl' matched no files under /tmp/cfg
|
|
25
|
+
```
|
|
@@ -6,7 +6,7 @@ description = "Ephemeral SQL index over a local directory"
|
|
|
6
6
|
# version stays for the binding crates (publish = false). The literal
|
|
7
7
|
# intentionally lags the published version: putitoutthere rewrites it to
|
|
8
8
|
# the planned release version at build time and never commits it back.
|
|
9
|
-
version = "0.4.
|
|
9
|
+
version = "0.4.85"
|
|
10
10
|
edition.workspace = true
|
|
11
11
|
# Literal `license` (not `license.workspace = true`) because
|
|
12
12
|
# putitoutthere's preflight check reads `[package].license` directly
|
|
@@ -274,6 +274,10 @@ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
|
|
|
274
274
|
writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
|
|
275
275
|
columns, `{root}`, and `ignore` are all relative to its anchor.
|
|
276
276
|
|
|
277
|
+
A table whose glob matches no files prints
|
|
278
|
+
`dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under <anchor>`
|
|
279
|
+
to stderr; the exit code is unchanged. Path-tables and programmatic tables do not warn.
|
|
280
|
+
|
|
277
281
|
### Batch `ddl`
|
|
278
282
|
|
|
279
283
|
`ddl` is handed to SQLite whole, so a table declaration is not limited to one
|
|
@@ -112,4 +112,4 @@ Row values serialize as in [`POST /query`](#value-serialization).
|
|
|
112
112
|
|---|---|
|
|
113
113
|
| `200` | Stream opened (`text/event-stream`). |
|
|
114
114
|
| `405` | `POST /events`. Plain-text body `method not allowed`. |
|
|
115
|
-
| `503` | The server is in [degraded mode](./cli.md#degraded-mode). JSON `{"error": …}` body. |
|
|
115
|
+
| `503` | The server is in [degraded mode](./cli.md#degraded-mode), or its filesystem watcher failed to start (for example, the inotify limit is exhausted). JSON `{"error": …}` body; for a watcher failure the message starts `filesystem watcher failed to start:` and gives the reason. `POST /query` keeps working. |
|
|
@@ -301,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
|
|
|
301
301
|
or at the `watch()` call (Rust). The stream never terminates on its own;
|
|
302
302
|
stop consuming it to stop.
|
|
303
303
|
|
|
304
|
+
Python: each `watch()` call returns an independent stream, and every stream
|
|
305
|
+
on one instance receives every event observed after it was created, so
|
|
306
|
+
several consumers (one per client, say) can share one instance.
|
|
307
|
+
|
|
304
308
|
Rust: `watch()` may be called once per instance and is mutually exclusive
|
|
305
309
|
with the polling API below — mixing them returns an error, since both drain
|
|
306
310
|
the same underlying filesystem watcher.
|
|
@@ -26,6 +26,7 @@ use super::execute::{QueryFailure, execute_query, require_ready};
|
|
|
26
26
|
pub(super) struct AppContext {
|
|
27
27
|
pub state: AppState,
|
|
28
28
|
pub events: broadcast::Sender<String>,
|
|
29
|
+
pub watch_failure: Option<String>,
|
|
29
30
|
pub cancel: watch::Receiver<bool>,
|
|
30
31
|
pub query_timeout: Duration,
|
|
31
32
|
}
|
|
@@ -72,6 +73,9 @@ async fn handle_events(State(ctx): State<SharedCtx>) -> Response {
|
|
|
72
73
|
if let Err(failure) = require_ready(&ctx.state) {
|
|
73
74
|
return failure_response(&failure);
|
|
74
75
|
}
|
|
76
|
+
if let Some(reason) = &ctx.watch_failure {
|
|
77
|
+
return failure_response(&QueryFailure::Unavailable(reason.clone()));
|
|
78
|
+
}
|
|
75
79
|
|
|
76
80
|
// Subscribe BEFORE anything that might block so we don't drop events
|
|
77
81
|
// that fire between subscribing and the first poll.
|
|
@@ -163,6 +167,21 @@ mod tests {
|
|
|
163
167
|
);
|
|
164
168
|
}
|
|
165
169
|
|
|
170
|
+
#[tokio::test]
|
|
171
|
+
async fn events_return_503_while_the_server_is_unavailable() {
|
|
172
|
+
let (events, _) = broadcast::channel::<String>(1);
|
|
173
|
+
let (_cancel_tx, cancel) = watch::channel(false);
|
|
174
|
+
let ctx = Arc::new(AppContext {
|
|
175
|
+
state: AppState::Unavailable("config failed to load".into()),
|
|
176
|
+
events,
|
|
177
|
+
watch_failure: None,
|
|
178
|
+
cancel,
|
|
179
|
+
query_timeout: Duration::from_secs(1),
|
|
180
|
+
});
|
|
181
|
+
let resp = handle_events(State(ctx)).await;
|
|
182
|
+
assert_eq!(resp.status(), StatusCode::SERVICE_UNAVAILABLE);
|
|
183
|
+
}
|
|
184
|
+
|
|
166
185
|
#[test]
|
|
167
186
|
fn error_response_sets_json_content_type() {
|
|
168
187
|
let resp = error_response(StatusCode::BAD_REQUEST, "boom");
|
|
@@ -38,14 +38,16 @@ pub async fn serve_with_state(
|
|
|
38
38
|
// the underlying notify watcher (which `DirSQL::watch` only permits
|
|
39
39
|
// once per instance).
|
|
40
40
|
let (event_tx, _) = broadcast::channel::<String>(256);
|
|
41
|
-
|
|
42
|
-
start_watch_task(db.clone(), event_tx.clone())
|
|
43
|
-
|
|
41
|
+
let watch_failure = match state {
|
|
42
|
+
AppState::Ready(ref db) => start_watch_task(db.clone(), event_tx.clone()),
|
|
43
|
+
AppState::Unavailable(_) => None,
|
|
44
|
+
};
|
|
44
45
|
|
|
45
46
|
let (cancel_tx, cancel_rx) = watch::channel(false);
|
|
46
47
|
let shared = Arc::new(AppContext {
|
|
47
48
|
state,
|
|
48
49
|
events: event_tx,
|
|
50
|
+
watch_failure,
|
|
49
51
|
cancel: cancel_rx,
|
|
50
52
|
query_timeout: config.query_timeout,
|
|
51
53
|
});
|
|
@@ -69,18 +71,20 @@ pub async fn serve_with_state(
|
|
|
69
71
|
})
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
/// Returns the reason `/events` must refuse requests when the watcher
|
|
75
|
+
/// could not attach.
|
|
76
|
+
fn start_watch_task(db: DirSQL, tx: broadcast::Sender<String>) -> Option<String> {
|
|
73
77
|
// `db.watch()` spawns its own OS thread and returns an async stream.
|
|
74
78
|
// We pump the stream into the broadcast channel. If no subscribers
|
|
75
79
|
// exist, send() errors but we keep pumping (future subscribers
|
|
76
80
|
// will get subsequent events).
|
|
77
|
-
let
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
let mut stream = match db.watch() {
|
|
82
|
+
Ok(stream) => stream,
|
|
83
|
+
Err(err) => {
|
|
84
|
+
let reason = format!("filesystem watcher failed to start: {err}");
|
|
85
|
+
eprintln!("dirsql: {reason}; /events will return 503");
|
|
86
|
+
return Some(reason);
|
|
87
|
+
}
|
|
84
88
|
};
|
|
85
89
|
tokio::spawn(async move {
|
|
86
90
|
while let Some(event) = stream.next().await {
|
|
@@ -88,6 +92,7 @@ fn start_watch_task(db: DirSQL, tx: broadcast::Sender<String>) {
|
|
|
88
92
|
let _ = tx.send(payload);
|
|
89
93
|
}
|
|
90
94
|
});
|
|
95
|
+
None
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
#[cfg(test)]
|
|
@@ -122,6 +127,29 @@ mod tests {
|
|
|
122
127
|
handle.shutdown().await.expect("graceful shutdown");
|
|
123
128
|
}
|
|
124
129
|
|
|
130
|
+
#[tokio::test]
|
|
131
|
+
async fn start_watch_task_reports_no_failure_once_the_watcher_attaches() {
|
|
132
|
+
let dir = tempfile::tempdir().unwrap();
|
|
133
|
+
let db = DirSQL::new(dir.path(), Vec::new()).unwrap();
|
|
134
|
+
let (tx, _) = broadcast::channel::<String>(1);
|
|
135
|
+
assert_eq!(start_watch_task(db, tx), None);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// `poll_events` locks out `watch`, the one deterministic way to make the
|
|
139
|
+
// watcher refuse to attach without exhausting inotify.
|
|
140
|
+
#[tokio::test]
|
|
141
|
+
async fn start_watch_task_returns_the_reason_when_the_watcher_cannot_attach() {
|
|
142
|
+
let dir = tempfile::tempdir().unwrap();
|
|
143
|
+
let db = DirSQL::new(dir.path(), Vec::new()).unwrap();
|
|
144
|
+
db.poll_events(std::time::Duration::ZERO).unwrap();
|
|
145
|
+
let (tx, _) = broadcast::channel::<String>(1);
|
|
146
|
+
let reason = start_watch_task(db, tx).expect("watch() must fail");
|
|
147
|
+
assert!(
|
|
148
|
+
reason.starts_with("filesystem watcher failed to start: "),
|
|
149
|
+
"got: {reason}"
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
125
153
|
// Binding to a non-local TEST-NET address (RFC 5737) fails with
|
|
126
154
|
// "cannot assign requested address", surfacing `ServerError::Bind` rather
|
|
127
155
|
// than panicking — deterministic and DNS-free.
|