dirsql 0.3.71__tar.gz → 0.3.73__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dirsql-0.3.71 → dirsql-0.3.73}/Cargo.lock +1 -1
- {dirsql-0.3.71 → dirsql-0.3.73}/PKG-INFO +1 -1
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/_async.py +7 -10
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/cli/main.py +1 -1
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/cli/resolve_config_extensions.py +7 -9
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/resolve_config_extensions.py +8 -12
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/resolve_extension.py +9 -18
- {dirsql-0.3.71/packages/rust → dirsql-0.3.73}/docs/howto/columns-from-paths.md +2 -8
- {dirsql-0.3.71/packages/python → dirsql-0.3.73}/docs/howto/define-tables.md +2 -16
- {dirsql-0.3.71/packages/python → dirsql-0.3.73}/docs/howto/extract-from-contents.md +2 -8
- {dirsql-0.3.71/packages/python → dirsql-0.3.73}/docs/howto/load-extension.md +2 -5
- {dirsql-0.3.71/packages/python → dirsql-0.3.73}/docs/howto/search-by-meaning.md +9 -17
- {dirsql-0.3.71/packages/rust → dirsql-0.3.73}/docs/howto/skip-files.md +1 -5
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/Cargo.toml +1 -1
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/conftest.py +4 -10
- {dirsql-0.3.71 → dirsql-0.3.73/packages/python}/docs/howto/columns-from-paths.md +2 -8
- {dirsql-0.3.71/packages/rust → dirsql-0.3.73/packages/python}/docs/howto/define-tables.md +2 -16
- {dirsql-0.3.71/packages/rust → dirsql-0.3.73/packages/python}/docs/howto/extract-from-contents.md +2 -8
- {dirsql-0.3.71/packages/rust → dirsql-0.3.73/packages/python}/docs/howto/load-extension.md +2 -5
- {dirsql-0.3.71/packages/rust → dirsql-0.3.73/packages/python}/docs/howto/search-by-meaning.md +9 -17
- {dirsql-0.3.71 → dirsql-0.3.73/packages/python}/docs/howto/skip-files.md +1 -5
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/e2e-attestation.json +2 -2
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/src/lib.rs +11 -26
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/tests/conftest.py +0 -1
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/benches/differ_bench.rs +0 -3
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/benches/scanner_bench.rs +0 -2
- {dirsql-0.3.71/packages/python → dirsql-0.3.73/packages/rust}/docs/howto/columns-from-paths.md +2 -8
- {dirsql-0.3.71 → dirsql-0.3.73/packages/rust}/docs/howto/define-tables.md +2 -16
- {dirsql-0.3.71 → dirsql-0.3.73/packages/rust}/docs/howto/extract-from-contents.md +2 -8
- {dirsql-0.3.71 → dirsql-0.3.73/packages/rust}/docs/howto/load-extension.md +2 -5
- {dirsql-0.3.71 → dirsql-0.3.73/packages/rust}/docs/howto/search-by-meaning.md +9 -17
- {dirsql-0.3.71/packages/python → dirsql-0.3.73/packages/rust}/docs/howto/skip-files.md +1 -5
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/bin/dirsql.rs +5 -10
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/cli/execute.rs +15 -2
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/cli/init.rs +5 -9
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/cli/mod.rs +8 -27
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/cli/serialize.rs +1 -9
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/cli/server.rs +2 -7
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/command.rs +5 -19
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/config.rs +14 -58
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/db.rs +58 -195
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/differ.rs +3 -40
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/lib.rs +115 -435
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/matcher.rs +1 -15
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/persist.rs +18 -57
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/scanner.rs +3 -13
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/watcher.rs +7 -11
- {dirsql-0.3.71 → dirsql-0.3.73}/Cargo.toml +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/README.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/__init__.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/cli/binary_path.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/cli/is_windows.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/dirsql/py.typed +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/AGENTS.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/explanation.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/getting-started.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/howto/embed.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/howto/persist.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/index.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/migrations.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/package.json +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/playwright.config.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/reference/cli.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/reference/columns.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/reference/config.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/reference/hooks.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/reference/http-api.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/reference/sdk.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/docs/vitest.config.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/README.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/index.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/package.json +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/playwright.config.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/reference/cli.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/reference/config.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/docs/vitest.config.ts +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/tests/binding/__init__.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/python/tests/smoke/__init__.py +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/README.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/index.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/reference/cli.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/reference/config.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.3.71 → dirsql-0.3.73}/pyproject.toml +0 -0
|
@@ -59,7 +59,7 @@ class DirSQL:
|
|
|
59
59
|
at startup. Any ``[[dirsql.extension]]`` entries in a ``config`` file are
|
|
60
60
|
appended after the programmatic ones. A ``path`` (programmatic or
|
|
61
61
|
config-file) may be a bare **package name**, resolved from the installed
|
|
62
|
-
package in the runtime env
|
|
62
|
+
package in the runtime env.
|
|
63
63
|
"""
|
|
64
64
|
|
|
65
65
|
def __init__(
|
|
@@ -98,15 +98,13 @@ class DirSQL:
|
|
|
98
98
|
"""Resolve extensions and construct the Rust-backed instance.
|
|
99
99
|
|
|
100
100
|
Runs on a worker thread (via ``asyncio.to_thread``): both the
|
|
101
|
-
package-name resolution
|
|
102
|
-
core's initial scan are blocking work.
|
|
101
|
+
package-name resolution and the core's initial scan are blocking.
|
|
103
102
|
|
|
104
103
|
When the ``config`` file names an extension by bare package name, the
|
|
105
104
|
SDK resolves every one of the config's ``[[dirsql.extension]]`` entries
|
|
106
|
-
itself
|
|
107
|
-
core's
|
|
108
|
-
|
|
109
|
-
sees the unresolvable bare name).
|
|
105
|
+
itself -- appended after the programmatic ones -- and suppresses the
|
|
106
|
+
core's own config-extension loading so the entries are not loaded a
|
|
107
|
+
second time (the core cannot resolve a bare name).
|
|
110
108
|
"""
|
|
111
109
|
extensions = self._resolved_extensions()
|
|
112
110
|
suppress = False
|
|
@@ -129,9 +127,8 @@ class DirSQL:
|
|
|
129
127
|
def _resolved_extensions(self):
|
|
130
128
|
"""Resolve each programmatic extension's ``path`` to a loadable file.
|
|
131
129
|
|
|
132
|
-
A bare package name is resolved to the loadable installed in the
|
|
133
|
-
env
|
|
134
|
-
the Rust builder, which takes programmatic paths as-is). Config-file
|
|
130
|
+
A bare package name is resolved to the loadable installed in the
|
|
131
|
+
runtime env; path-looking values pass through verbatim. Config-file
|
|
135
132
|
``[[dirsql.extension]]`` entries are handled by ``_build_db``.
|
|
136
133
|
"""
|
|
137
134
|
if not self._extensions:
|
|
@@ -24,7 +24,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
24
24
|
return 1
|
|
25
25
|
|
|
26
26
|
# Resolve any package-name extensions in a TOML config here (the binary
|
|
27
|
-
# can't) and pass them as `--extension` flags; a no-op otherwise
|
|
27
|
+
# can't) and pass them as `--extension` flags; a no-op otherwise.
|
|
28
28
|
try:
|
|
29
29
|
argv = with_resolved_extensions(argv)
|
|
30
30
|
except Exception as exc:
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"""Launcher-side resolution of a TOML config's ``[[dirsql.extension]]`` entries.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
loads those and ignores the config's own extension entries (the Rust
|
|
11
|
-
``--extension`` flag / ``suppress_config_extensions``).
|
|
3
|
+
The compiled ``dirsql`` binary loads a config's extensions literally -- it
|
|
4
|
+
has no ``importlib``, so it cannot resolve a bare **package name**. When a
|
|
5
|
+
TOML config names an extension by package name, the shared SDK resolver
|
|
6
|
+
(:mod:`dirsql.resolve_config_extensions`) resolves every one of its
|
|
7
|
+
extensions and this launcher passes the resolved literal paths to the binary
|
|
8
|
+
via repeatable ``--extension`` flags; the binary then loads those and ignores
|
|
9
|
+
the config's own extension entries.
|
|
12
10
|
|
|
13
11
|
Native-language configs (``.py`` / ``.js`` / ``.mjs`` / ``.cjs``) are untouched:
|
|
14
12
|
the binary dispatches those to ``dirsql interpret``, whose handshake already
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
"""SDK-side resolution of a TOML config's ``[[dirsql.extension]]`` entries.
|
|
2
2
|
|
|
3
|
-
The Rust core
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
config's entries are not loaded a second time.
|
|
3
|
+
The Rust core loads a config's extensions literally -- it has no
|
|
4
|
+
``importlib``, so it cannot resolve a bare **package name**. When a TOML
|
|
5
|
+
config names an extension by package name, the SDK resolves every one of its
|
|
6
|
+
extensions here, hands the core the resolved literal paths, and suppresses
|
|
7
|
+
the core's own config-extension loading (``suppress_config_extensions``) so
|
|
8
|
+
the config's entries are not loaded a second time.
|
|
10
9
|
|
|
11
10
|
Shared by the ``DirSQL`` constructor (``config=`` path) and the CLI launcher
|
|
12
|
-
(
|
|
13
|
-
into ``--extension`` flags for the binary).
|
|
11
|
+
(which converts the resolved specs into ``--extension`` flags).
|
|
14
12
|
"""
|
|
15
13
|
|
|
16
14
|
from __future__ import annotations
|
|
@@ -45,9 +43,7 @@ def resolve_config_extension_specs(config_path):
|
|
|
45
43
|
entries = cfg.get("extension")
|
|
46
44
|
if not isinstance(entries, list):
|
|
47
45
|
return None
|
|
48
|
-
# Only intervene when at least one path is a bare package name
|
|
49
|
-
# with only literal paths (or no entries at all) keeps the core's existing
|
|
50
|
-
# behavior untouched.
|
|
46
|
+
# Only intervene when at least one path is a bare package name.
|
|
51
47
|
if not any(
|
|
52
48
|
isinstance(e, dict)
|
|
53
49
|
and isinstance(e.get("path"), str)
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
"""Resolve an extension entry's ``path`` to a concrete loadable file.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
name
|
|
5
|
-
names a package installed in the runtime env, and dirsql discovers the loadable
|
|
6
|
-
file *inside* that package.
|
|
7
|
-
|
|
8
|
-
Resolution is an ordered probe (file-first, then package), so every literal
|
|
9
|
-
path from #225 keeps its old behavior and only a bare name reaches the package
|
|
10
|
-
machinery:
|
|
3
|
+
Resolution is an ordered probe (file-first, then package), so only a bare
|
|
4
|
+
package name reaches the package machinery:
|
|
11
5
|
|
|
12
6
|
1. **Path-looking** (contains a separator, or ends in ``.so`` / ``.dylib`` /
|
|
13
7
|
``.dll`` / ``.pyd``) -- returned as a file path: made absolute against
|
|
14
8
|
``base`` when ``resolve_relative`` is set (config-file entries), else
|
|
15
|
-
verbatim (programmatic entries
|
|
9
|
+
verbatim (programmatic entries).
|
|
16
10
|
2. **Bare name** -- a same-named local file under ``base`` *shadows* the
|
|
17
|
-
package
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
package; otherwise the package dir is located via
|
|
12
|
+
:func:`importlib.util.find_spec` and the current platform's loadable is
|
|
13
|
+
globbed from inside it. Zero matches and multiple matches are both hard
|
|
14
|
+
errors -- the caller must disambiguate with a literal path.
|
|
21
15
|
"""
|
|
22
16
|
|
|
23
17
|
import glob as _glob
|
|
@@ -25,9 +19,8 @@ import importlib.util
|
|
|
25
19
|
import os
|
|
26
20
|
import sys
|
|
27
21
|
|
|
28
|
-
# Suffixes that mark a value as "already a file path"
|
|
29
|
-
# never attempted
|
|
30
|
-
# a package directory.
|
|
22
|
+
# Suffixes that mark a value as "already a file path", so package resolution
|
|
23
|
+
# is never attempted.
|
|
31
24
|
_LOADABLE_SUFFIXES = (".so", ".dylib", ".dll", ".pyd")
|
|
32
25
|
|
|
33
26
|
|
|
@@ -73,8 +66,6 @@ def _resolve_package(name):
|
|
|
73
66
|
matches.update(_glob.glob(os.path.join(d, "**", pat), recursive=True))
|
|
74
67
|
found = sorted(matches)
|
|
75
68
|
|
|
76
|
-
# Exactly one loadable resolves; unpacking (rather than a guarded
|
|
77
|
-
# subscript) makes the zero- and multiple-match failures each observable.
|
|
78
69
|
try:
|
|
79
70
|
(single,) = found
|
|
80
71
|
except ValueError:
|
|
@@ -29,12 +29,8 @@ within one path segment) are in
|
|
|
29
29
|
|
|
30
30
|
## 2. Query the captured columns
|
|
31
31
|
|
|
32
|
-
Start the server (`npx dirsql` / `uvx dirsql`) and query:
|
|
33
|
-
|
|
34
32
|
```bash
|
|
35
|
-
|
|
36
|
-
-H 'content-type: application/json' \
|
|
37
|
-
-d '{"sql":"SELECT year, month, _basename FROM photos ORDER BY year, month"}'
|
|
33
|
+
dirsql query "SELECT year, month, _basename FROM photos ORDER BY year, month"
|
|
38
34
|
```
|
|
39
35
|
|
|
40
36
|
```json
|
|
@@ -44,9 +40,7 @@ curl -s http://localhost:7117/query \
|
|
|
44
40
|
Captures are real SQL columns, so aggregation works:
|
|
45
41
|
|
|
46
42
|
```bash
|
|
47
|
-
|
|
48
|
-
-H 'content-type: application/json' \
|
|
49
|
-
-d '{"sql":"SELECT year, COUNT(*) AS photos FROM photos GROUP BY year"}'
|
|
43
|
+
dirsql query "SELECT year, COUNT(*) AS photos FROM photos GROUP BY year"
|
|
50
44
|
```
|
|
51
45
|
|
|
52
46
|
```json
|
|
@@ -24,26 +24,12 @@ glob = "posts/**/*.md"
|
|
|
24
24
|
filesystem facts `dirsql` computes for every file. Facts are opt-in by
|
|
25
25
|
DDL: only the ones you declare become columns.
|
|
26
26
|
|
|
27
|
-
## 2.
|
|
28
|
-
|
|
29
|
-
::: code-group
|
|
30
|
-
|
|
31
|
-
```bash [npm]
|
|
32
|
-
npx dirsql
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
```bash [PyPI]
|
|
36
|
-
uvx dirsql
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
:::
|
|
27
|
+
## 2. Query the table
|
|
40
28
|
|
|
41
29
|
Each matched file is one row:
|
|
42
30
|
|
|
43
31
|
```bash
|
|
44
|
-
|
|
45
|
-
-H 'content-type: application/json' \
|
|
46
|
-
-d '{"sql":"SELECT _path, _size FROM posts ORDER BY _path"}'
|
|
32
|
+
dirsql query "SELECT _path, _size FROM posts ORDER BY _path"
|
|
47
33
|
```
|
|
48
34
|
|
|
49
35
|
```json
|
|
@@ -31,12 +31,8 @@ by every hook.
|
|
|
31
31
|
|
|
32
32
|
## 2. Query the extracted columns
|
|
33
33
|
|
|
34
|
-
Start the server (`npx dirsql` / `uvx dirsql`) and query:
|
|
35
|
-
|
|
36
34
|
```bash
|
|
37
|
-
|
|
38
|
-
-H 'content-type: application/json' \
|
|
39
|
-
-d '{"sql":"SELECT title, author, year, _path FROM books ORDER BY year"}'
|
|
35
|
+
dirsql query "SELECT title, author, year, _path FROM books ORDER BY year"
|
|
40
36
|
```
|
|
41
37
|
|
|
42
38
|
```json
|
|
@@ -61,9 +57,7 @@ on-file = "jq -c -s '.' {path}"
|
|
|
61
57
|
```
|
|
62
58
|
|
|
63
59
|
```bash
|
|
64
|
-
|
|
65
|
-
-H 'content-type: application/json' \
|
|
66
|
-
-d '{"sql":"SELECT event, user FROM events"}'
|
|
60
|
+
dirsql query "SELECT event, user FROM events"
|
|
67
61
|
```
|
|
68
62
|
|
|
69
63
|
```json
|
|
@@ -23,13 +23,10 @@ overrides the init symbol when it doesn't match the filename-derived
|
|
|
23
23
|
default — `sqlite-vec` is exactly such a case
|
|
24
24
|
([reference](../reference/config.md#dirsql-extension)).
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
functions are callable:
|
|
26
|
+
The extension's functions are callable:
|
|
28
27
|
|
|
29
28
|
```bash
|
|
30
|
-
|
|
31
|
-
-H 'content-type: application/json' \
|
|
32
|
-
-d '{"sql":"SELECT vec_version() AS vec_version"}'
|
|
29
|
+
dirsql query "SELECT vec_version() AS vec_version"
|
|
33
30
|
```
|
|
34
31
|
|
|
35
32
|
```json
|
|
@@ -99,20 +99,14 @@ installed `sqlite_vec` module to its bundled loadable. Naming rules per
|
|
|
99
99
|
runtime — and the literal-path alternative that works everywhere — are in
|
|
100
100
|
[Load a SQLite extension](./load-extension.md).
|
|
101
101
|
|
|
102
|
-
## 3.
|
|
102
|
+
## 3. Ask questions
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
Run with `sqlite-vec` available to the launcher's environment. The initial
|
|
105
|
+
scan runs `embed.py` once per note, then the query argument goes straight to
|
|
106
|
+
`pre-query`, exactly as a `POST /query` body would:
|
|
105
107
|
|
|
106
108
|
```bash
|
|
107
|
-
uvx --with sqlite-vec dirsql
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
The initial scan runs `embed.py` once per note. Then ask:
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
curl -s http://localhost:7117/query \
|
|
114
|
-
-H 'content-type: application/json' \
|
|
115
|
-
-d '{"q": "how do I cook pasta?"}'
|
|
109
|
+
uvx --with sqlite-vec dirsql query '{"q": "how do I cook pasta?"}'
|
|
116
110
|
```
|
|
117
111
|
|
|
118
112
|
```json
|
|
@@ -120,9 +114,7 @@ curl -s http://localhost:7117/query \
|
|
|
120
114
|
```
|
|
121
115
|
|
|
122
116
|
```bash
|
|
123
|
-
|
|
124
|
-
-H 'content-type: application/json' \
|
|
125
|
-
-d '{"q": "reviewing code on github"}'
|
|
117
|
+
uvx --with sqlite-vec dirsql query '{"q": "reviewing code on github"}'
|
|
126
118
|
```
|
|
127
119
|
|
|
128
120
|
```json
|
|
@@ -133,9 +125,9 @@ Neither question shares a keyword with its top note — "cook" appears
|
|
|
133
125
|
nowhere in `pasta.md`, "github" nowhere in `branches.md`. The distance
|
|
134
126
|
ranking is doing the work.
|
|
135
127
|
|
|
136
|
-
Because `pre-query` is set, the
|
|
137
|
-
`{"sql": …}` —
|
|
138
|
-
|
|
128
|
+
Because `pre-query` is set, the query argument is *not* the usual
|
|
129
|
+
`{"sql": …}` — it goes to your script as-is, which decides what SQL runs
|
|
130
|
+
([hook interactions](../reference/http-api.md#hook-interactions)).
|
|
139
131
|
|
|
140
132
|
## Recomputing vs. caching
|
|
141
133
|
|
|
@@ -31,12 +31,8 @@ ignored file never reaches any table — even one whose glob would match it.
|
|
|
31
31
|
|
|
32
32
|
## 2. Confirm what made it in
|
|
33
33
|
|
|
34
|
-
Start the server (`npx dirsql` / `uvx dirsql`) and check:
|
|
35
|
-
|
|
36
34
|
```bash
|
|
37
|
-
|
|
38
|
-
-H 'content-type: application/json' \
|
|
39
|
-
-d '{"sql":"SELECT _path FROM notes ORDER BY _path"}'
|
|
35
|
+
dirsql query "SELECT _path FROM notes ORDER BY _path"
|
|
40
36
|
```
|
|
41
37
|
|
|
42
38
|
```json
|
|
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
|
|
|
4
4
|
# pypi/maturin handler can rewrite it via `write-version` before
|
|
5
5
|
# `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
|
|
6
6
|
# and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.73"
|
|
8
8
|
edition.workspace = true
|
|
9
9
|
publish = false
|
|
10
10
|
readme = "README.md"
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
"""Stub the compiled `_dirsql` extension for unit tests that don't need it.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
imports real types from `dirsql._dirsql`.
|
|
8
|
-
|
|
9
|
-
The stub is installed ONLY when the real extension can't be imported.
|
|
10
|
-
When `maturin develop` has been run (as in CI), the real extension wins
|
|
11
|
-
and tests that depend on it — `_async_test.py`, the integration suites —
|
|
12
|
-
see the real bindings.
|
|
3
|
+
Must live here (not in a test file) so the stub is in place before pytest
|
|
4
|
+
imports `dirsql.__init__`, which imports real types from `dirsql._dirsql`.
|
|
5
|
+
Installed only when the real extension can't be imported; when `maturin
|
|
6
|
+
develop` has been run, the real bindings win.
|
|
13
7
|
"""
|
|
14
8
|
|
|
15
9
|
from __future__ import annotations
|
|
@@ -29,12 +29,8 @@ within one path segment) are in
|
|
|
29
29
|
|
|
30
30
|
## 2. Query the captured columns
|
|
31
31
|
|
|
32
|
-
Start the server (`npx dirsql` / `uvx dirsql`) and query:
|
|
33
|
-
|
|
34
32
|
```bash
|
|
35
|
-
|
|
36
|
-
-H 'content-type: application/json' \
|
|
37
|
-
-d '{"sql":"SELECT year, month, _basename FROM photos ORDER BY year, month"}'
|
|
33
|
+
dirsql query "SELECT year, month, _basename FROM photos ORDER BY year, month"
|
|
38
34
|
```
|
|
39
35
|
|
|
40
36
|
```json
|
|
@@ -44,9 +40,7 @@ curl -s http://localhost:7117/query \
|
|
|
44
40
|
Captures are real SQL columns, so aggregation works:
|
|
45
41
|
|
|
46
42
|
```bash
|
|
47
|
-
|
|
48
|
-
-H 'content-type: application/json' \
|
|
49
|
-
-d '{"sql":"SELECT year, COUNT(*) AS photos FROM photos GROUP BY year"}'
|
|
43
|
+
dirsql query "SELECT year, COUNT(*) AS photos FROM photos GROUP BY year"
|
|
50
44
|
```
|
|
51
45
|
|
|
52
46
|
```json
|
|
@@ -24,26 +24,12 @@ glob = "posts/**/*.md"
|
|
|
24
24
|
filesystem facts `dirsql` computes for every file. Facts are opt-in by
|
|
25
25
|
DDL: only the ones you declare become columns.
|
|
26
26
|
|
|
27
|
-
## 2.
|
|
28
|
-
|
|
29
|
-
::: code-group
|
|
30
|
-
|
|
31
|
-
```bash [npm]
|
|
32
|
-
npx dirsql
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
```bash [PyPI]
|
|
36
|
-
uvx dirsql
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
:::
|
|
27
|
+
## 2. Query the table
|
|
40
28
|
|
|
41
29
|
Each matched file is one row:
|
|
42
30
|
|
|
43
31
|
```bash
|
|
44
|
-
|
|
45
|
-
-H 'content-type: application/json' \
|
|
46
|
-
-d '{"sql":"SELECT _path, _size FROM posts ORDER BY _path"}'
|
|
32
|
+
dirsql query "SELECT _path, _size FROM posts ORDER BY _path"
|
|
47
33
|
```
|
|
48
34
|
|
|
49
35
|
```json
|
{dirsql-0.3.71/packages/rust → dirsql-0.3.73/packages/python}/docs/howto/extract-from-contents.md
RENAMED
|
@@ -31,12 +31,8 @@ by every hook.
|
|
|
31
31
|
|
|
32
32
|
## 2. Query the extracted columns
|
|
33
33
|
|
|
34
|
-
Start the server (`npx dirsql` / `uvx dirsql`) and query:
|
|
35
|
-
|
|
36
34
|
```bash
|
|
37
|
-
|
|
38
|
-
-H 'content-type: application/json' \
|
|
39
|
-
-d '{"sql":"SELECT title, author, year, _path FROM books ORDER BY year"}'
|
|
35
|
+
dirsql query "SELECT title, author, year, _path FROM books ORDER BY year"
|
|
40
36
|
```
|
|
41
37
|
|
|
42
38
|
```json
|
|
@@ -61,9 +57,7 @@ on-file = "jq -c -s '.' {path}"
|
|
|
61
57
|
```
|
|
62
58
|
|
|
63
59
|
```bash
|
|
64
|
-
|
|
65
|
-
-H 'content-type: application/json' \
|
|
66
|
-
-d '{"sql":"SELECT event, user FROM events"}'
|
|
60
|
+
dirsql query "SELECT event, user FROM events"
|
|
67
61
|
```
|
|
68
62
|
|
|
69
63
|
```json
|
|
@@ -23,13 +23,10 @@ overrides the init symbol when it doesn't match the filename-derived
|
|
|
23
23
|
default — `sqlite-vec` is exactly such a case
|
|
24
24
|
([reference](../reference/config.md#dirsql-extension)).
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
functions are callable:
|
|
26
|
+
The extension's functions are callable:
|
|
28
27
|
|
|
29
28
|
```bash
|
|
30
|
-
|
|
31
|
-
-H 'content-type: application/json' \
|
|
32
|
-
-d '{"sql":"SELECT vec_version() AS vec_version"}'
|
|
29
|
+
dirsql query "SELECT vec_version() AS vec_version"
|
|
33
30
|
```
|
|
34
31
|
|
|
35
32
|
```json
|
{dirsql-0.3.71/packages/rust → dirsql-0.3.73/packages/python}/docs/howto/search-by-meaning.md
RENAMED
|
@@ -99,20 +99,14 @@ installed `sqlite_vec` module to its bundled loadable. Naming rules per
|
|
|
99
99
|
runtime — and the literal-path alternative that works everywhere — are in
|
|
100
100
|
[Load a SQLite extension](./load-extension.md).
|
|
101
101
|
|
|
102
|
-
## 3.
|
|
102
|
+
## 3. Ask questions
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
Run with `sqlite-vec` available to the launcher's environment. The initial
|
|
105
|
+
scan runs `embed.py` once per note, then the query argument goes straight to
|
|
106
|
+
`pre-query`, exactly as a `POST /query` body would:
|
|
105
107
|
|
|
106
108
|
```bash
|
|
107
|
-
uvx --with sqlite-vec dirsql
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
The initial scan runs `embed.py` once per note. Then ask:
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
curl -s http://localhost:7117/query \
|
|
114
|
-
-H 'content-type: application/json' \
|
|
115
|
-
-d '{"q": "how do I cook pasta?"}'
|
|
109
|
+
uvx --with sqlite-vec dirsql query '{"q": "how do I cook pasta?"}'
|
|
116
110
|
```
|
|
117
111
|
|
|
118
112
|
```json
|
|
@@ -120,9 +114,7 @@ curl -s http://localhost:7117/query \
|
|
|
120
114
|
```
|
|
121
115
|
|
|
122
116
|
```bash
|
|
123
|
-
|
|
124
|
-
-H 'content-type: application/json' \
|
|
125
|
-
-d '{"q": "reviewing code on github"}'
|
|
117
|
+
uvx --with sqlite-vec dirsql query '{"q": "reviewing code on github"}'
|
|
126
118
|
```
|
|
127
119
|
|
|
128
120
|
```json
|
|
@@ -133,9 +125,9 @@ Neither question shares a keyword with its top note — "cook" appears
|
|
|
133
125
|
nowhere in `pasta.md`, "github" nowhere in `branches.md`. The distance
|
|
134
126
|
ranking is doing the work.
|
|
135
127
|
|
|
136
|
-
Because `pre-query` is set, the
|
|
137
|
-
`{"sql": …}` —
|
|
138
|
-
|
|
128
|
+
Because `pre-query` is set, the query argument is *not* the usual
|
|
129
|
+
`{"sql": …}` — it goes to your script as-is, which decides what SQL runs
|
|
130
|
+
([hook interactions](../reference/http-api.md#hook-interactions)).
|
|
139
131
|
|
|
140
132
|
## Recomputing vs. caching
|
|
141
133
|
|
|
@@ -31,12 +31,8 @@ ignored file never reaches any table — even one whose glob would match it.
|
|
|
31
31
|
|
|
32
32
|
## 2. Confirm what made it in
|
|
33
33
|
|
|
34
|
-
Start the server (`npx dirsql` / `uvx dirsql`) and check:
|
|
35
|
-
|
|
36
34
|
```bash
|
|
37
|
-
|
|
38
|
-
-H 'content-type: application/json' \
|
|
39
|
-
-d '{"sql":"SELECT _path FROM notes ORDER BY _path"}'
|
|
35
|
+
dirsql query "SELECT _path FROM notes ORDER BY _path"
|
|
40
36
|
```
|
|
41
37
|
|
|
42
38
|
```json
|
|
@@ -20,8 +20,6 @@ mod python {
|
|
|
20
20
|
use std::path::PathBuf;
|
|
21
21
|
use std::time::Duration;
|
|
22
22
|
|
|
23
|
-
// -- Public PyO3 classes ------------------------------------------------
|
|
24
|
-
|
|
25
23
|
/// A table definition. Mirrors `dirsql::Table` but holds a Python
|
|
26
24
|
/// callable for `extract`.
|
|
27
25
|
#[pyclass(name = "Table", frozen)]
|
|
@@ -34,15 +32,11 @@ mod python {
|
|
|
34
32
|
extract: Py<PyAny>,
|
|
35
33
|
#[pyo3(get)]
|
|
36
34
|
strict: bool,
|
|
37
|
-
/// Parsed table name (from `ddl`)
|
|
38
|
-
/// match `CREATE TABLE <name> (...)`.
|
|
39
|
-
///
|
|
40
|
-
///
|
|
41
|
-
///
|
|
42
|
-
/// rather than raising at construction so `DirSQL.ready()` keeps
|
|
43
|
-
/// surfacing malformed DDLs as the loud failure path (the Rust
|
|
44
|
-
/// core's `DirSqlError::Ddl`); callers that care about the name
|
|
45
|
-
/// before that point can check `t.name is None` themselves.
|
|
35
|
+
/// Parsed table name (from `ddl`) via `dirsql::db::parse_table_name`,
|
|
36
|
+
/// or `None` if the DDL doesn't match `CREATE TABLE <name> (...)`.
|
|
37
|
+
/// `None` rather than a construction error so `DirSQL.ready()` keeps
|
|
38
|
+
/// surfacing malformed DDLs as the loud failure path (the core's
|
|
39
|
+
/// `DirSqlError::Ddl`).
|
|
46
40
|
#[pyo3(get)]
|
|
47
41
|
name: Option<String>,
|
|
48
42
|
}
|
|
@@ -64,11 +58,9 @@ mod python {
|
|
|
64
58
|
}
|
|
65
59
|
|
|
66
60
|
/// Marshals a Python `{"path": str, "entrypoint"?: str}` mapping from the
|
|
67
|
-
/// `extensions=` constructor argument into a [`dirsql::Extension`].
|
|
68
|
-
/// the
|
|
69
|
-
///
|
|
70
|
-
/// programmatic surface does not resolve relative paths), matching
|
|
71
|
-
/// `DirSQLBuilder::extensions`.
|
|
61
|
+
/// `extensions=` constructor argument into a [`dirsql::Extension`]. Paths
|
|
62
|
+
/// are taken verbatim; the programmatic surface does not resolve relative
|
|
63
|
+
/// paths.
|
|
72
64
|
#[derive(FromPyObject)]
|
|
73
65
|
struct PyExtensionSpec {
|
|
74
66
|
#[pyo3(item)]
|
|
@@ -117,8 +109,8 @@ mod python {
|
|
|
117
109
|
/// `suppress_config_extensions` skips the core's own loading of the
|
|
118
110
|
/// config's `[[dirsql.extension]]` entries; the SDK sets it after
|
|
119
111
|
/// resolving those entries itself (package names need `importlib`,
|
|
120
|
-
/// which the core lacks
|
|
121
|
-
///
|
|
112
|
+
/// which the core lacks) and passing the resolved literal paths via
|
|
113
|
+
/// `extensions`, so the entries are not loaded twice.
|
|
122
114
|
#[new]
|
|
123
115
|
#[pyo3(signature = (root=None, *, tables=None, ignore=None, config=None, persist=false, persist_path=None, extensions=None, suppress_config_extensions=false))]
|
|
124
116
|
fn new(
|
|
@@ -205,8 +197,6 @@ mod python {
|
|
|
205
197
|
}
|
|
206
198
|
}
|
|
207
199
|
|
|
208
|
-
// -- Helpers ------------------------------------------------------------
|
|
209
|
-
|
|
210
200
|
fn build_table(py: Python<'_>, t: &PyTable) -> Table {
|
|
211
201
|
let extract_ref = t.extract.clone_ref(py);
|
|
212
202
|
let mut table = Table::try_new(
|
|
@@ -260,10 +250,7 @@ mod python {
|
|
|
260
250
|
/// Pure, GIL-free intermediate for a row event. [`row_event_to_plain`]
|
|
261
251
|
/// builds it from a core [`RowEvent`] (unit-testable without a Python
|
|
262
252
|
/// interpreter); [`row_event_to_py`] then marshals it into the
|
|
263
|
-
/// Python-facing [`PyRowEvent`] (the GIL step).
|
|
264
|
-
/// variant -> action / field-selection mapping testable at the unit tier,
|
|
265
|
-
/// mirroring the napi binding's pure `row_event_to_js`. The value-level
|
|
266
|
-
/// `Row -> PyDict` conversion stays GIL-bound (binding-tier covered).
|
|
253
|
+
/// Python-facing [`PyRowEvent`] (the GIL step).
|
|
267
254
|
struct PlainRowEvent {
|
|
268
255
|
table: Option<String>,
|
|
269
256
|
action: &'static str,
|
|
@@ -406,8 +393,6 @@ mod python {
|
|
|
406
393
|
}
|
|
407
394
|
}
|
|
408
395
|
|
|
409
|
-
// -- Module registration ------------------------------------------------
|
|
410
|
-
|
|
411
396
|
#[pymodule]
|
|
412
397
|
#[pyo3(name = "_dirsql")]
|
|
413
398
|
fn py_dirsql_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
@@ -15,7 +15,6 @@ def tmp_dir():
|
|
|
15
15
|
@pytest.fixture
|
|
16
16
|
def jsonl_dir(tmp_dir):
|
|
17
17
|
"""Create a temp dir with JSONL files for testing."""
|
|
18
|
-
# Create a simple JSONL file
|
|
19
18
|
os.makedirs(os.path.join(tmp_dir, "comments", "abc"), exist_ok=True)
|
|
20
19
|
os.makedirs(os.path.join(tmp_dir, "comments", "def"), exist_ok=True)
|
|
21
20
|
|