dirsql 0.4.42__tar.gz → 0.4.44__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.42 → dirsql-0.4.44}/Cargo.lock +41 -2
- {dirsql-0.4.42 → dirsql-0.4.44}/PKG-INFO +1 -1
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/reference/cli.md +5 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/Cargo.toml +1 -1
- {dirsql-0.4.42/packages/rust → dirsql-0.4.44/packages/python}/docs/reference/cli.md +5 -0
- dirsql-0.4.44/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +7 -0
- dirsql-0.4.44/packages/python/e2e-attestations/claude-1119-ext-plan.json +7 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/Cargo.toml +3 -1
- {dirsql-0.4.42/packages/python → dirsql-0.4.44/packages/rust}/docs/reference/cli.md +5 -0
- dirsql-0.4.44/packages/rust/src/extension_resolution.rs +421 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/lib.rs +2 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/progress.rs +339 -126
- {dirsql-0.4.42 → dirsql-0.4.44}/Cargo.toml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/README.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/_async.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/discover_plugins/user_passed_config.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/has_bare_name.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/is_bare_name.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/load_extension_entries.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/platform_patterns.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/py.typed +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/resolve_configs_extension_specs.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/resolve_entries.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/resolve_package.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/dirsql/toml_module.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/AGENTS.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/explanation.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/getting-started.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/embed.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/persist.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/query-json.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/index.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/package.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/plugins.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/reference/columns.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/reference/config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/reference/http-api.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/docs/reference/sdk.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/README.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/conftest.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/query-json.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/reference/config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/src/lib.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/testing-conventions.toml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/README.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/query-json.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/reference/config.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/repl.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/run.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/cli/table.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/command.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/config.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/db.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/launcher.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/parsed_cache.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/parsed_vtab.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/path_table.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/sql_literal.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/vtab_scaffold.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.4.42 → dirsql-0.4.44}/pyproject.toml +0 -0
|
@@ -350,6 +350,18 @@ version = "1.0.5"
|
|
|
350
350
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
351
351
|
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
|
352
352
|
|
|
353
|
+
[[package]]
|
|
354
|
+
name = "console"
|
|
355
|
+
version = "0.16.6"
|
|
356
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
357
|
+
checksum = "e96a4956774c13c126a8b5af4daa79384f4d826534c95a02d76afb39e2ab64e3"
|
|
358
|
+
dependencies = [
|
|
359
|
+
"encode_unicode",
|
|
360
|
+
"libc",
|
|
361
|
+
"unicode-width",
|
|
362
|
+
"windows-sys 0.61.2",
|
|
363
|
+
]
|
|
364
|
+
|
|
353
365
|
[[package]]
|
|
354
366
|
name = "constant_time_eq"
|
|
355
367
|
version = "0.4.2"
|
|
@@ -540,12 +552,13 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
|
|
540
552
|
|
|
541
553
|
[[package]]
|
|
542
554
|
name = "dirsql"
|
|
543
|
-
version = "0.4.
|
|
555
|
+
version = "0.4.44"
|
|
544
556
|
dependencies = [
|
|
545
557
|
"assert_cmd",
|
|
546
558
|
"axum",
|
|
547
559
|
"blake3",
|
|
548
560
|
"clap",
|
|
561
|
+
"console",
|
|
549
562
|
"criterion",
|
|
550
563
|
"eventsource-client",
|
|
551
564
|
"futures",
|
|
@@ -554,6 +567,7 @@ dependencies = [
|
|
|
554
567
|
"futures-util",
|
|
555
568
|
"globset",
|
|
556
569
|
"ignore",
|
|
570
|
+
"indicatif",
|
|
557
571
|
"libc",
|
|
558
572
|
"notify",
|
|
559
573
|
"predicates",
|
|
@@ -583,7 +597,7 @@ dependencies = [
|
|
|
583
597
|
|
|
584
598
|
[[package]]
|
|
585
599
|
name = "dirsql-py-ext"
|
|
586
|
-
version = "0.4.
|
|
600
|
+
version = "0.4.44"
|
|
587
601
|
dependencies = [
|
|
588
602
|
"dirsql",
|
|
589
603
|
"pyo3",
|
|
@@ -630,6 +644,12 @@ version = "1.15.0"
|
|
|
630
644
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
631
645
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
|
632
646
|
|
|
647
|
+
[[package]]
|
|
648
|
+
name = "encode_unicode"
|
|
649
|
+
version = "1.0.0"
|
|
650
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
651
|
+
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
|
652
|
+
|
|
633
653
|
[[package]]
|
|
634
654
|
name = "equivalent"
|
|
635
655
|
version = "1.0.2"
|
|
@@ -1294,6 +1314,19 @@ dependencies = [
|
|
|
1294
1314
|
"serde_core",
|
|
1295
1315
|
]
|
|
1296
1316
|
|
|
1317
|
+
[[package]]
|
|
1318
|
+
name = "indicatif"
|
|
1319
|
+
version = "0.18.6"
|
|
1320
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1321
|
+
checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c"
|
|
1322
|
+
dependencies = [
|
|
1323
|
+
"console",
|
|
1324
|
+
"portable-atomic",
|
|
1325
|
+
"unicode-width",
|
|
1326
|
+
"unit-prefix",
|
|
1327
|
+
"web-time",
|
|
1328
|
+
]
|
|
1329
|
+
|
|
1297
1330
|
[[package]]
|
|
1298
1331
|
name = "inotify"
|
|
1299
1332
|
version = "0.10.2"
|
|
@@ -2902,6 +2935,12 @@ version = "0.2.6"
|
|
|
2902
2935
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2903
2936
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
2904
2937
|
|
|
2938
|
+
[[package]]
|
|
2939
|
+
name = "unit-prefix"
|
|
2940
|
+
version = "0.5.2"
|
|
2941
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2942
|
+
checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3"
|
|
2943
|
+
|
|
2905
2944
|
[[package]]
|
|
2906
2945
|
name = "untrusted"
|
|
2907
2946
|
version = "0.9.0"
|
|
@@ -536,6 +536,11 @@ Override with `DIRSQL_PROGRESS`:
|
|
|
536
536
|
Values are case-insensitive and surrounding whitespace is ignored; anything
|
|
537
537
|
unrecognized reads as `auto`, so a typo cannot stop a scan from running.
|
|
538
538
|
|
|
539
|
+
Each redraw clears the line and pads the new one out to the full width (the
|
|
540
|
+
terminal's, or 80 columns when there is none), so a capture of an `always` run
|
|
541
|
+
carries trailing spaces. It carries no escape sequences, and the summary that
|
|
542
|
+
survives the phase is a whole, newline-terminated line.
|
|
543
|
+
|
|
539
544
|
The setting is read by the **core**, not the CLI, so it governs an index built
|
|
540
545
|
from any SDK as well — a Python or TypeScript program that builds a `DirSQL`
|
|
541
546
|
with a terminal attached gets the same two phases on stderr, and the same
|
|
@@ -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.44"
|
|
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
|
|
@@ -536,6 +536,11 @@ Override with `DIRSQL_PROGRESS`:
|
|
|
536
536
|
Values are case-insensitive and surrounding whitespace is ignored; anything
|
|
537
537
|
unrecognized reads as `auto`, so a typo cannot stop a scan from running.
|
|
538
538
|
|
|
539
|
+
Each redraw clears the line and pads the new one out to the full width (the
|
|
540
|
+
terminal's, or 80 columns when there is none), so a capture of an `always` run
|
|
541
|
+
carries trailing spaces. It carries no escape sequences, and the summary that
|
|
542
|
+
survives the phase is a whole, newline-terminated line.
|
|
543
|
+
|
|
539
544
|
The setting is read by the **core**, not the CLI, so it governs an index built
|
|
540
545
|
from any SDK as well — a Python or TypeScript program that builds a `DirSQL`
|
|
541
546
|
with a terminal attached gets the same two phases on stderr, and the same
|
|
@@ -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.44"
|
|
10
10
|
edition.workspace = true
|
|
11
11
|
# Literal `license` (not `license.workspace = true`) because
|
|
12
12
|
# putitoutthere's preflight check reads `[package].license` directly
|
|
@@ -59,12 +59,14 @@ cli = [
|
|
|
59
59
|
axum = { version = "0.8", optional = true }
|
|
60
60
|
blake3 = "1"
|
|
61
61
|
clap = { version = "4", features = ["derive"], optional = true }
|
|
62
|
+
console = "0.16.6"
|
|
62
63
|
futures = { version = "0.3", optional = true }
|
|
63
64
|
futures-channel.workspace = true
|
|
64
65
|
globset = "0.4"
|
|
65
66
|
# Hierarchical `.gitignore` matching for path-table scans (the fd/ripgrep
|
|
66
67
|
# semantics), without adopting its walker: the scan keeps `walkdir`.
|
|
67
68
|
ignore = "0.4"
|
|
69
|
+
indicatif = "0.18.6"
|
|
68
70
|
notify = "7"
|
|
69
71
|
# The REPL's interactive line editor (history, Ctrl+R, multi-line entry).
|
|
70
72
|
# CLI-only: a library consumer never pulls crossterm.
|
|
@@ -536,6 +536,11 @@ Override with `DIRSQL_PROGRESS`:
|
|
|
536
536
|
Values are case-insensitive and surrounding whitespace is ignored; anything
|
|
537
537
|
unrecognized reads as `auto`, so a typo cannot stop a scan from running.
|
|
538
538
|
|
|
539
|
+
Each redraw clears the line and pads the new one out to the full width (the
|
|
540
|
+
terminal's, or 80 columns when there is none), so a capture of an `always` run
|
|
541
|
+
carries trailing spaces. It carries no escape sequences, and the summary that
|
|
542
|
+
survives the phase is a whole, newline-terminated line.
|
|
543
|
+
|
|
539
544
|
The setting is read by the **core**, not the CLI, so it governs an index built
|
|
540
545
|
from any SDK as well — a Python or TypeScript program that builds a `DirSQL`
|
|
541
546
|
with a terminal attached gets the same two phases on stderr, and the same
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
//! Planning the resolution of `[[dirsql.extension]]` entries.
|
|
2
|
+
//!
|
|
3
|
+
//! Each launcher used to carry its own port of this: read the configs, decide
|
|
4
|
+
//! whether any entry names a package rather than a file, resolve the rest
|
|
5
|
+
//! against the config's directory. Only "where is package `X` installed on
|
|
6
|
+
//! this host" is genuinely host-specific (`importlib.util.find_spec` /
|
|
7
|
+
//! `require.resolve`), so that stays with the launcher and comes back here as
|
|
8
|
+
//! a set of directories.
|
|
9
|
+
//!
|
|
10
|
+
//! The suffix list is a parameter because it differs per host: Python counts
|
|
11
|
+
//! `.pyd` as a loadable, Node counts `.node`.
|
|
12
|
+
|
|
13
|
+
use std::fmt;
|
|
14
|
+
use std::path::{Path, PathBuf};
|
|
15
|
+
|
|
16
|
+
use crate::config::{ExtensionSpec, load_config_str};
|
|
17
|
+
|
|
18
|
+
/// One config file's contents, or `None` when it is missing or unreadable.
|
|
19
|
+
///
|
|
20
|
+
/// `path` must be absolute: entry paths and the bare-name shadow probe resolve
|
|
21
|
+
/// against its parent directory.
|
|
22
|
+
#[derive(Debug, Clone, Copy)]
|
|
23
|
+
pub struct ConfigSource<'a> {
|
|
24
|
+
pub path: &'a Path,
|
|
25
|
+
pub contents: Option<&'a str>,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// One planned extension entry.
|
|
29
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
30
|
+
pub enum PlanEntry {
|
|
31
|
+
/// A concrete path, already absolute against its config's directory.
|
|
32
|
+
Literal {
|
|
33
|
+
path: PathBuf,
|
|
34
|
+
entrypoint: Option<String>,
|
|
35
|
+
},
|
|
36
|
+
/// A bare package name. Use `shadow` when it is a file on disk; otherwise
|
|
37
|
+
/// locate the package on the host and hand its directories, plus every
|
|
38
|
+
/// file found under them, to [`select_loadable`].
|
|
39
|
+
Package {
|
|
40
|
+
name: String,
|
|
41
|
+
shadow: PathBuf,
|
|
42
|
+
entrypoint: Option<String>,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// Why a package's loadable file could not be picked.
|
|
47
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
48
|
+
pub enum SelectError {
|
|
49
|
+
NotFound {
|
|
50
|
+
name: String,
|
|
51
|
+
suffixes: Vec<String>,
|
|
52
|
+
dirs: Vec<PathBuf>,
|
|
53
|
+
},
|
|
54
|
+
Ambiguous {
|
|
55
|
+
name: String,
|
|
56
|
+
matches: Vec<PathBuf>,
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fn join_display(paths: &[PathBuf], sep: &str) -> String {
|
|
61
|
+
paths
|
|
62
|
+
.iter()
|
|
63
|
+
.map(|p| p.display().to_string())
|
|
64
|
+
.collect::<Vec<_>>()
|
|
65
|
+
.join(sep)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
impl fmt::Display for SelectError {
|
|
69
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
70
|
+
match self {
|
|
71
|
+
SelectError::NotFound {
|
|
72
|
+
name,
|
|
73
|
+
suffixes,
|
|
74
|
+
dirs,
|
|
75
|
+
} => {
|
|
76
|
+
let patterns = suffixes
|
|
77
|
+
.iter()
|
|
78
|
+
.map(|s| format!("*{s}"))
|
|
79
|
+
.collect::<Vec<_>>()
|
|
80
|
+
.join(" / ");
|
|
81
|
+
write!(
|
|
82
|
+
f,
|
|
83
|
+
"no loadable extension file ({patterns}) found in package '{name}' (searched {})",
|
|
84
|
+
join_display(dirs, ", ")
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
SelectError::Ambiguous { name, matches } => write!(
|
|
88
|
+
f,
|
|
89
|
+
"multiple loadable extension files found in package '{name}': {}; disambiguate with a literal path",
|
|
90
|
+
join_display(matches, ", ")
|
|
91
|
+
),
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
impl std::error::Error for SelectError {}
|
|
97
|
+
|
|
98
|
+
/// True when `path` names a package rather than a file.
|
|
99
|
+
///
|
|
100
|
+
/// Both separators count regardless of host, so a Windows-style path is a path
|
|
101
|
+
/// everywhere.
|
|
102
|
+
pub fn is_bare_name(path: &str, suffixes: &[&str]) -> bool {
|
|
103
|
+
if path.contains('/') || path.contains('\\') {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
!suffixes.iter().any(|s| path.ends_with(s))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Plan the extension entries of several configs, in order.
|
|
110
|
+
///
|
|
111
|
+
/// `None` means "do not intervene": no config names an extension by bare
|
|
112
|
+
/// package name, so the core's own config loading (and its error reporting)
|
|
113
|
+
/// handles every entry. Otherwise **every** config's entries are planned, each
|
|
114
|
+
/// against its own directory, concatenated in `configs` order — once the
|
|
115
|
+
/// caller suppresses the core's config-extension loading it must supply the
|
|
116
|
+
/// literal entries too.
|
|
117
|
+
///
|
|
118
|
+
/// A config whose contents are absent or do not parse is skipped rather than
|
|
119
|
+
/// reported, leaving the error to the core.
|
|
120
|
+
pub fn plan_config_extensions(
|
|
121
|
+
configs: &[ConfigSource<'_>],
|
|
122
|
+
suffixes: &[&str],
|
|
123
|
+
) -> Option<Vec<PlanEntry>> {
|
|
124
|
+
let loaded: Vec<(PathBuf, Vec<ExtensionSpec>)> = configs
|
|
125
|
+
.iter()
|
|
126
|
+
.filter_map(|source| {
|
|
127
|
+
let config = load_config_str(source.contents?).ok()?;
|
|
128
|
+
Some((source.path.parent()?.to_path_buf(), config.extensions))
|
|
129
|
+
})
|
|
130
|
+
.collect();
|
|
131
|
+
|
|
132
|
+
if !loaded
|
|
133
|
+
.iter()
|
|
134
|
+
.flat_map(|(_, extensions)| extensions)
|
|
135
|
+
.any(|extension| spec_is_bare_name(extension, suffixes))
|
|
136
|
+
{
|
|
137
|
+
return None;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
Some(
|
|
141
|
+
loaded
|
|
142
|
+
.into_iter()
|
|
143
|
+
.flat_map(|(base, extensions)| {
|
|
144
|
+
extensions.into_iter().map(move |extension| {
|
|
145
|
+
let name = extension.path.to_string_lossy().into_owned();
|
|
146
|
+
if is_bare_name(&name, suffixes) {
|
|
147
|
+
PlanEntry::Package {
|
|
148
|
+
shadow: base.join(&name),
|
|
149
|
+
name,
|
|
150
|
+
entrypoint: extension.entrypoint,
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
// `join` already yields an absolute path verbatim.
|
|
154
|
+
PlanEntry::Literal {
|
|
155
|
+
path: base.join(&extension.path),
|
|
156
|
+
entrypoint: extension.entrypoint,
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
.collect(),
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
fn spec_is_bare_name(extension: &ExtensionSpec, suffixes: &[&str]) -> bool {
|
|
166
|
+
extension
|
|
167
|
+
.path
|
|
168
|
+
.to_str()
|
|
169
|
+
.is_some_and(|path| is_bare_name(path, suffixes))
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/// Pick the single loadable file for package `name` out of a host's listing.
|
|
173
|
+
///
|
|
174
|
+
/// `dirs` are the package's directories (used only for the not-found message);
|
|
175
|
+
/// `candidates` is every file found under them. Zero matches and more than one
|
|
176
|
+
/// are both errors — the user must disambiguate with a literal path.
|
|
177
|
+
pub fn select_loadable(
|
|
178
|
+
name: &str,
|
|
179
|
+
dirs: &[PathBuf],
|
|
180
|
+
candidates: &[PathBuf],
|
|
181
|
+
suffixes: &[&str],
|
|
182
|
+
) -> Result<PathBuf, SelectError> {
|
|
183
|
+
let mut matches: Vec<PathBuf> = candidates
|
|
184
|
+
.iter()
|
|
185
|
+
.filter(|candidate| {
|
|
186
|
+
candidate
|
|
187
|
+
.to_str()
|
|
188
|
+
.is_some_and(|path| suffixes.iter().any(|suffix| path.ends_with(suffix)))
|
|
189
|
+
})
|
|
190
|
+
.cloned()
|
|
191
|
+
.collect();
|
|
192
|
+
matches.sort();
|
|
193
|
+
matches.dedup();
|
|
194
|
+
|
|
195
|
+
match matches.len() {
|
|
196
|
+
0 => Err(SelectError::NotFound {
|
|
197
|
+
name: name.to_owned(),
|
|
198
|
+
suffixes: suffixes.iter().map(|s| (*s).to_owned()).collect(),
|
|
199
|
+
dirs: dirs.to_vec(),
|
|
200
|
+
}),
|
|
201
|
+
1 => Ok(matches.remove(0)),
|
|
202
|
+
_ => Err(SelectError::Ambiguous {
|
|
203
|
+
name: name.to_owned(),
|
|
204
|
+
matches,
|
|
205
|
+
}),
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
#[cfg(test)]
|
|
210
|
+
mod tests {
|
|
211
|
+
use super::{
|
|
212
|
+
ConfigSource, PlanEntry, SelectError, is_bare_name, plan_config_extensions, select_loadable,
|
|
213
|
+
};
|
|
214
|
+
use std::path::{Path, PathBuf};
|
|
215
|
+
|
|
216
|
+
const PY: &[&str] = &[".so", ".dylib", ".dll", ".pyd"];
|
|
217
|
+
const NODE: &[&str] = &[".so", ".dylib", ".dll", ".node"];
|
|
218
|
+
|
|
219
|
+
fn source<'a>(path: &'a Path, contents: &'a str) -> ConfigSource<'a> {
|
|
220
|
+
ConfigSource {
|
|
221
|
+
path,
|
|
222
|
+
contents: Some(contents),
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
#[test]
|
|
227
|
+
fn a_value_with_no_separator_and_no_loadable_suffix_is_a_bare_name() {
|
|
228
|
+
assert!(is_bare_name("sqlite_vec", PY));
|
|
229
|
+
assert!(is_bare_name("vec0", NODE));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
#[test]
|
|
233
|
+
fn a_value_carrying_either_separator_is_a_path() {
|
|
234
|
+
assert!(!is_bare_name("ext/vec0", PY));
|
|
235
|
+
assert!(!is_bare_name("ext\\vec0", PY));
|
|
236
|
+
assert!(!is_bare_name("/abs/vec0", PY));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
#[test]
|
|
240
|
+
fn a_value_ending_in_a_loadable_suffix_is_a_path() {
|
|
241
|
+
for suffix in [".so", ".dylib", ".dll"] {
|
|
242
|
+
assert!(!is_bare_name(&format!("vec0{suffix}"), PY));
|
|
243
|
+
assert!(!is_bare_name(&format!("vec0{suffix}"), NODE));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
#[test]
|
|
248
|
+
fn the_suffix_list_is_the_hosts_own() {
|
|
249
|
+
assert!(!is_bare_name("vec0.pyd", PY));
|
|
250
|
+
assert!(is_bare_name("vec0.pyd", NODE));
|
|
251
|
+
assert!(!is_bare_name("vec0.node", NODE));
|
|
252
|
+
assert!(is_bare_name("vec0.node", PY));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
#[test]
|
|
256
|
+
fn configs_using_only_literal_paths_are_left_to_the_core() {
|
|
257
|
+
let path = Path::new("/project/.dirsql.toml");
|
|
258
|
+
let config = "[[dirsql.extension]]\npath = \"ext/vec0.so\"\n";
|
|
259
|
+
assert_eq!(plan_config_extensions(&[source(path, config)], PY), None);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#[test]
|
|
263
|
+
fn a_config_with_no_extension_array_is_left_to_the_core() {
|
|
264
|
+
let path = Path::new("/project/.dirsql.toml");
|
|
265
|
+
assert_eq!(
|
|
266
|
+
plan_config_extensions(&[source(path, "[dirsql]\nignore = [\"*.tmp\"]\n")], PY),
|
|
267
|
+
None
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
#[test]
|
|
272
|
+
fn an_absent_or_unparseable_config_is_skipped_rather_than_reported() {
|
|
273
|
+
let path = Path::new("/project/.dirsql.toml");
|
|
274
|
+
let missing = ConfigSource {
|
|
275
|
+
path,
|
|
276
|
+
contents: None,
|
|
277
|
+
};
|
|
278
|
+
assert_eq!(plan_config_extensions(&[missing], PY), None);
|
|
279
|
+
assert_eq!(
|
|
280
|
+
plan_config_extensions(&[source(path, "not valid = [")], PY),
|
|
281
|
+
None
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
#[test]
|
|
286
|
+
fn a_bare_name_plans_a_package_lookup_shadowed_by_the_configs_own_directory() {
|
|
287
|
+
let path = Path::new("/project/conf/.dirsql.toml");
|
|
288
|
+
let plan = plan_config_extensions(
|
|
289
|
+
&[source(
|
|
290
|
+
path,
|
|
291
|
+
"[[dirsql.extension]]\npath = \"sqlite_vec\"\n",
|
|
292
|
+
)],
|
|
293
|
+
PY,
|
|
294
|
+
)
|
|
295
|
+
.expect("a bare name makes the SDK intervene");
|
|
296
|
+
|
|
297
|
+
assert_eq!(
|
|
298
|
+
plan,
|
|
299
|
+
vec![PlanEntry::Package {
|
|
300
|
+
name: "sqlite_vec".into(),
|
|
301
|
+
shadow: PathBuf::from("/project/conf/sqlite_vec"),
|
|
302
|
+
entrypoint: None,
|
|
303
|
+
}]
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
#[test]
|
|
308
|
+
fn intervening_plans_the_literal_entries_too_and_keeps_config_order() {
|
|
309
|
+
let first = Path::new("/project/one/.dirsql.toml");
|
|
310
|
+
let second = Path::new("/project/two/.dirsql.toml");
|
|
311
|
+
let plan = plan_config_extensions(
|
|
312
|
+
&[
|
|
313
|
+
source(
|
|
314
|
+
first,
|
|
315
|
+
"[[dirsql.extension]]\npath = \"ext/vec0.so\"\nentrypoint = \"sqlite3_vec_init\"\n",
|
|
316
|
+
),
|
|
317
|
+
source(second, "[[dirsql.extension]]\npath = \"sqlite_vec\"\n"),
|
|
318
|
+
],
|
|
319
|
+
PY,
|
|
320
|
+
)
|
|
321
|
+
.expect("a bare name anywhere makes the SDK intervene for the whole set");
|
|
322
|
+
|
|
323
|
+
assert_eq!(
|
|
324
|
+
plan,
|
|
325
|
+
vec![
|
|
326
|
+
PlanEntry::Literal {
|
|
327
|
+
path: PathBuf::from("/project/one/ext/vec0.so"),
|
|
328
|
+
entrypoint: Some("sqlite3_vec_init".into()),
|
|
329
|
+
},
|
|
330
|
+
PlanEntry::Package {
|
|
331
|
+
name: "sqlite_vec".into(),
|
|
332
|
+
shadow: PathBuf::from("/project/two/sqlite_vec"),
|
|
333
|
+
entrypoint: None,
|
|
334
|
+
},
|
|
335
|
+
]
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
#[test]
|
|
340
|
+
fn an_absolute_entry_path_is_left_alone() {
|
|
341
|
+
let path = Path::new("/project/.dirsql.toml");
|
|
342
|
+
let plan = plan_config_extensions(
|
|
343
|
+
&[source(
|
|
344
|
+
path,
|
|
345
|
+
"[[dirsql.extension]]\npath = \"/opt/vec0.so\"\n\n[[dirsql.extension]]\npath = \"sqlite_vec\"\n",
|
|
346
|
+
)],
|
|
347
|
+
PY,
|
|
348
|
+
)
|
|
349
|
+
.expect("intervening");
|
|
350
|
+
|
|
351
|
+
assert_eq!(
|
|
352
|
+
plan[0],
|
|
353
|
+
PlanEntry::Literal {
|
|
354
|
+
path: PathBuf::from("/opt/vec0.so"),
|
|
355
|
+
entrypoint: None,
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
#[test]
|
|
361
|
+
fn select_loadable_returns_the_single_matching_file() {
|
|
362
|
+
let dir = PathBuf::from("/site-packages/sqlite_vec");
|
|
363
|
+
let found = select_loadable(
|
|
364
|
+
"sqlite_vec",
|
|
365
|
+
std::slice::from_ref(&dir),
|
|
366
|
+
&[
|
|
367
|
+
dir.join("__init__.py"),
|
|
368
|
+
dir.join("vec0.so"),
|
|
369
|
+
dir.join("README.md"),
|
|
370
|
+
],
|
|
371
|
+
PY,
|
|
372
|
+
);
|
|
373
|
+
assert_eq!(found, Ok(dir.join("vec0.so")));
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#[test]
|
|
377
|
+
fn select_loadable_dedupes_and_sorts_before_counting() {
|
|
378
|
+
let dir = PathBuf::from("/pkg");
|
|
379
|
+
let found = select_loadable(
|
|
380
|
+
"vec",
|
|
381
|
+
std::slice::from_ref(&dir),
|
|
382
|
+
&[dir.join("vec0.so"), dir.join("vec0.so")],
|
|
383
|
+
PY,
|
|
384
|
+
);
|
|
385
|
+
assert_eq!(found, Ok(dir.join("vec0.so")));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
#[test]
|
|
389
|
+
fn select_loadable_reports_every_searched_directory_when_nothing_matches() {
|
|
390
|
+
let dirs = vec![PathBuf::from("/a"), PathBuf::from("/b")];
|
|
391
|
+
let err = select_loadable("vec", &dirs, &[PathBuf::from("/a/vec.py")], PY)
|
|
392
|
+
.expect_err("no loadable file");
|
|
393
|
+
assert_eq!(
|
|
394
|
+
err.to_string(),
|
|
395
|
+
"no loadable extension file (*.so / *.dylib / *.dll / *.pyd) found in package 'vec' (searched /a, /b)"
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
#[test]
|
|
400
|
+
fn select_loadable_rejects_an_ambiguous_package_in_sorted_order() {
|
|
401
|
+
let dir = PathBuf::from("/pkg");
|
|
402
|
+
let err = select_loadable(
|
|
403
|
+
"vec",
|
|
404
|
+
std::slice::from_ref(&dir),
|
|
405
|
+
&[dir.join("z.so"), dir.join("a.so")],
|
|
406
|
+
PY,
|
|
407
|
+
)
|
|
408
|
+
.expect_err("two loadable files");
|
|
409
|
+
assert_eq!(
|
|
410
|
+
err,
|
|
411
|
+
SelectError::Ambiguous {
|
|
412
|
+
name: "vec".into(),
|
|
413
|
+
matches: vec![dir.join("a.so"), dir.join("z.so")],
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
assert_eq!(
|
|
417
|
+
err.to_string(),
|
|
418
|
+
"multiple loadable extension files found in package 'vec': /pkg/a.so, /pkg/z.so; disambiguate with a literal path"
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|