dirsql 0.3.50__tar.gz → 0.3.52__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.50 → dirsql-0.3.52}/Cargo.lock +1 -1
- {dirsql-0.3.50 → dirsql-0.3.52}/PKG-INFO +1 -1
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/_async.py +38 -12
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/_dirsql.pyi +1 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/cli/resolve_config_extensions.py +17 -41
- dirsql-0.3.52/dirsql/resolve_config_extensions.py +71 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/resolve_extension.py +13 -9
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/api/index.md +1 -1
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/cli/config.md +3 -1
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/Cargo.toml +1 -1
- {dirsql-0.3.50/packages/rust → dirsql-0.3.52/packages/python}/docs/api/index.md +1 -1
- {dirsql-0.3.50/packages/rust → dirsql-0.3.52/packages/python}/docs/cli/config.md +3 -1
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/e2e-attestation.json +2 -2
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/src/lib.rs +10 -2
- dirsql-0.3.52/packages/python/tests/smoke/__init__.py +0 -0
- {dirsql-0.3.50/packages/python → dirsql-0.3.52/packages/rust}/docs/api/index.md +1 -1
- {dirsql-0.3.50/packages/python → dirsql-0.3.52/packages/rust}/docs/cli/config.md +3 -1
- {dirsql-0.3.50 → dirsql-0.3.52}/Cargo.toml +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/README.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/__init__.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/cli/binary_path.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/cli/interpret/__init__.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/cli/is_windows.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/cli/main.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/dirsql/py.typed +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/AGENTS.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/cli/http-api.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/cli/index.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/cli/init.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/cli/server.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/getting-started.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/guide/async.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/guide/crdt.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/guide/persistence.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/guide/querying.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/guide/tables.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/guide/watching.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/index.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/migrations.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/package.json +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/playwright.config.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/docs/vitest.config.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/README.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/conftest.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/cli/http-api.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/cli/index.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/cli/init.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/cli/server.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/guide/async.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/guide/crdt.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/guide/persistence.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/guide/querying.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/guide/tables.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/guide/watching.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/index.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/package.json +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/playwright.config.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/vitest.config.ts +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/README.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/cli/http-api.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/cli/index.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/cli/init.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/cli/server.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/guide/async.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/guide/crdt.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/guide/persistence.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/guide/querying.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/guide/tables.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/guide/watching.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/index.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/command.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/config.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/db.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.3.50 → dirsql-0.3.52}/pyproject.toml +0 -0
|
@@ -4,6 +4,7 @@ import asyncio
|
|
|
4
4
|
import os
|
|
5
5
|
|
|
6
6
|
from dirsql._dirsql import DirSQL as _RustDirSQL
|
|
7
|
+
from dirsql.resolve_config_extensions import resolve_config_extension_specs
|
|
7
8
|
from dirsql.resolve_extension import resolve_extension_path
|
|
8
9
|
|
|
9
10
|
|
|
@@ -56,7 +57,9 @@ class DirSQL:
|
|
|
56
57
|
Pass ``extensions`` -- a list of ``{"path": ..., "entrypoint": ...}`` dicts
|
|
57
58
|
(``entrypoint`` optional) -- to load SQLite extensions onto the connection
|
|
58
59
|
at startup. Any ``[[dirsql.extension]]`` entries in a ``config`` file are
|
|
59
|
-
appended after the programmatic ones.
|
|
60
|
+
appended after the programmatic ones. A ``path`` (programmatic or
|
|
61
|
+
config-file) may be a bare **package name**, resolved from the installed
|
|
62
|
+
package in the runtime env (#298 / #313).
|
|
60
63
|
"""
|
|
61
64
|
|
|
62
65
|
def __init__(
|
|
@@ -85,28 +88,51 @@ class DirSQL:
|
|
|
85
88
|
async def _init_bg(self):
|
|
86
89
|
"""Run the scan in the background."""
|
|
87
90
|
try:
|
|
88
|
-
self._db = await asyncio.to_thread(
|
|
89
|
-
_RustDirSQL,
|
|
90
|
-
self._root,
|
|
91
|
-
tables=self._tables,
|
|
92
|
-
ignore=self._ignore,
|
|
93
|
-
config=self._config,
|
|
94
|
-
persist=self._persist,
|
|
95
|
-
persist_path=self._persist_path,
|
|
96
|
-
extensions=self._resolved_extensions(),
|
|
97
|
-
)
|
|
91
|
+
self._db = await asyncio.to_thread(self._build_db)
|
|
98
92
|
except Exception as exc:
|
|
99
93
|
self._init_error = exc
|
|
100
94
|
finally:
|
|
101
95
|
self._ready_event.set()
|
|
102
96
|
|
|
97
|
+
def _build_db(self):
|
|
98
|
+
"""Resolve extensions and construct the Rust-backed instance.
|
|
99
|
+
|
|
100
|
+
Runs on a worker thread (via ``asyncio.to_thread``): both the
|
|
101
|
+
package-name resolution (``importlib`` + filesystem globs) and the
|
|
102
|
+
core's initial scan are blocking work.
|
|
103
|
+
|
|
104
|
+
When the ``config`` file names an extension by bare package name, the
|
|
105
|
+
SDK resolves every one of the config's ``[[dirsql.extension]]`` entries
|
|
106
|
+
itself (#313) -- appended after the programmatic ones, matching the
|
|
107
|
+
core's ordering -- and suppresses the core's own config-extension
|
|
108
|
+
loading so the entries are not loaded a second time (and the core never
|
|
109
|
+
sees the unresolvable bare name).
|
|
110
|
+
"""
|
|
111
|
+
extensions = self._resolved_extensions()
|
|
112
|
+
suppress = False
|
|
113
|
+
if self._config is not None:
|
|
114
|
+
config_extensions = resolve_config_extension_specs(self._config)
|
|
115
|
+
if config_extensions is not None:
|
|
116
|
+
extensions = [*(extensions or []), *config_extensions]
|
|
117
|
+
suppress = True
|
|
118
|
+
return _RustDirSQL(
|
|
119
|
+
self._root,
|
|
120
|
+
tables=self._tables,
|
|
121
|
+
ignore=self._ignore,
|
|
122
|
+
config=self._config,
|
|
123
|
+
persist=self._persist,
|
|
124
|
+
persist_path=self._persist_path,
|
|
125
|
+
extensions=extensions,
|
|
126
|
+
suppress_config_extensions=suppress,
|
|
127
|
+
)
|
|
128
|
+
|
|
103
129
|
def _resolved_extensions(self):
|
|
104
130
|
"""Resolve each programmatic extension's ``path`` to a loadable file.
|
|
105
131
|
|
|
106
132
|
A bare package name is resolved to the loadable installed in the runtime
|
|
107
133
|
env (#298); path-looking values are passed through verbatim (mirroring
|
|
108
134
|
the Rust builder, which takes programmatic paths as-is). Config-file
|
|
109
|
-
``[[dirsql.extension]]`` entries are
|
|
135
|
+
``[[dirsql.extension]]`` entries are handled by ``_build_db``.
|
|
110
136
|
"""
|
|
111
137
|
if not self._extensions:
|
|
112
138
|
return self._extensions
|
|
@@ -69,6 +69,7 @@ class DirSQL:
|
|
|
69
69
|
persist: bool = False,
|
|
70
70
|
persist_path: str | PathLike[str] | None = None,
|
|
71
71
|
extensions: list[ExtensionSpec] | None = None,
|
|
72
|
+
suppress_config_extensions: bool = False,
|
|
72
73
|
) -> None: ...
|
|
73
74
|
def query(self, sql: str) -> list[Row]: ...
|
|
74
75
|
def _start_watcher(self) -> None: ...
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
Mirrors the TypeScript launcher. The compiled ``dirsql`` binary reads a
|
|
4
4
|
``.dirsql.toml`` itself and loads its extensions literally -- it has no
|
|
5
5
|
``importlib``, so it cannot resolve a bare **package name** (#227). This
|
|
6
|
-
launcher can. When a TOML config names an extension by package name,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
launcher can. When a TOML config names an extension by package name, the
|
|
7
|
+
shared SDK resolver (:mod:`dirsql.resolve_config_extensions`, #313) resolves
|
|
8
|
+
every one of its extensions and this launcher passes the resolved literal
|
|
9
|
+
paths to the binary via repeatable ``--extension`` flags; the binary then
|
|
10
|
+
loads those and ignores the config's own extension entries (the Rust
|
|
11
|
+
``--extension`` flag / ``suppress_config_extensions``).
|
|
11
12
|
|
|
12
13
|
Native-language configs (``.py`` / ``.js`` / ``.mjs`` / ``.cjs``) are untouched:
|
|
13
14
|
the binary dispatches those to ``dirsql interpret``, whose handshake already
|
|
@@ -16,10 +17,7 @@ carries resolved paths.
|
|
|
16
17
|
|
|
17
18
|
from __future__ import annotations
|
|
18
19
|
|
|
19
|
-
import
|
|
20
|
-
import tomllib
|
|
21
|
-
|
|
22
|
-
from ..resolve_extension import is_bare_name, resolve_extension_path
|
|
20
|
+
from ..resolve_config_extensions import resolve_config_extension_specs
|
|
23
21
|
|
|
24
22
|
# Config extensions the binary dispatches to `dirsql interpret`; never
|
|
25
23
|
# pre-resolved here (that path resolves via the handshake).
|
|
@@ -28,14 +26,12 @@ _NATIVE_SUFFIXES = (".py", ".js", ".mjs", ".cjs")
|
|
|
28
26
|
|
|
29
27
|
def _config_path_from_argv(argv: list[str]) -> str:
|
|
30
28
|
"""The ``--config`` value (``--config X`` or ``--config=X``), or the default."""
|
|
31
|
-
i
|
|
32
|
-
while i < len(argv):
|
|
33
|
-
a = argv[i]
|
|
29
|
+
for i, a in enumerate(argv):
|
|
34
30
|
if a == "--config":
|
|
35
|
-
|
|
31
|
+
# A bare trailing `--config` (no following value) yields "".
|
|
32
|
+
return next(iter(argv[i + 1 :]), "")
|
|
36
33
|
if a.startswith("--config="):
|
|
37
34
|
return a[len("--config=") :]
|
|
38
|
-
i += 1
|
|
39
35
|
return "./.dirsql.toml"
|
|
40
36
|
|
|
41
37
|
|
|
@@ -48,34 +44,14 @@ def with_resolved_extensions(argv: list[str]) -> list[str]:
|
|
|
48
44
|
config_path = _config_path_from_argv(argv)
|
|
49
45
|
if config_path.endswith(_NATIVE_SUFFIXES):
|
|
50
46
|
return argv
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
try:
|
|
54
|
-
with open(config_path, "rb") as f:
|
|
55
|
-
doc = tomllib.load(f)
|
|
56
|
-
except (OSError, tomllib.TOMLDecodeError):
|
|
57
|
-
# Leave a malformed / unreadable config for the binary to report.
|
|
58
|
-
return argv
|
|
59
|
-
|
|
60
|
-
cfg = doc.get("dirsql") or {}
|
|
61
|
-
entries = cfg.get("extension") or []
|
|
62
|
-
if not isinstance(entries, list) or not entries:
|
|
63
|
-
return argv
|
|
64
|
-
# Only intervene when at least one path is a bare package name; a config
|
|
65
|
-
# with only literal paths keeps the binary's existing behavior untouched.
|
|
66
|
-
if not any(
|
|
67
|
-
isinstance(e, dict)
|
|
68
|
-
and isinstance(e.get("path"), str)
|
|
69
|
-
and is_bare_name(e["path"])
|
|
70
|
-
for e in entries
|
|
71
|
-
):
|
|
47
|
+
specs = resolve_config_extension_specs(config_path)
|
|
48
|
+
if specs is None:
|
|
72
49
|
return argv
|
|
73
|
-
|
|
74
|
-
base = os.path.dirname(os.path.abspath(config_path))
|
|
75
50
|
flags: list[str] = []
|
|
76
|
-
for
|
|
77
|
-
|
|
78
|
-
entrypoint = e.get("entrypoint")
|
|
51
|
+
for spec in specs:
|
|
52
|
+
entrypoint = spec["entrypoint"]
|
|
79
53
|
flags.append("--extension")
|
|
80
|
-
flags.append(
|
|
54
|
+
flags.append(
|
|
55
|
+
f"{spec['path']}::{entrypoint}" if entrypoint is not None else spec["path"]
|
|
56
|
+
)
|
|
81
57
|
return [*argv, *flags]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""SDK-side resolution of a TOML config's ``[[dirsql.extension]]`` entries.
|
|
2
|
+
|
|
3
|
+
The Rust core parses a ``.dirsql.toml`` itself and loads its extensions
|
|
4
|
+
literally -- it has no ``importlib``, so it cannot resolve a bare **package
|
|
5
|
+
name** (#227). The SDK can (#313). When a TOML config names an extension by
|
|
6
|
+
package name, the SDK resolves every one of its extensions here, hands the
|
|
7
|
+
core the resolved literal paths, and suppresses the core's own config-extension
|
|
8
|
+
loading (the Rust ``suppress_config_extensions`` builder toggle) so the
|
|
9
|
+
config's entries are not loaded a second time.
|
|
10
|
+
|
|
11
|
+
Shared by the ``DirSQL`` constructor (``config=`` path) and the CLI launcher
|
|
12
|
+
(``dirsql.cli.resolve_config_extensions``, which converts the resolved specs
|
|
13
|
+
into ``--extension`` flags for the binary).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import tomllib
|
|
20
|
+
|
|
21
|
+
from .resolve_extension import is_bare_name, resolve_extension_path
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def resolve_config_extension_specs(config_path):
|
|
25
|
+
"""Resolve a TOML config's ``[[dirsql.extension]]`` entries to literal paths.
|
|
26
|
+
|
|
27
|
+
Returns a list of ``{"path", "entrypoint"}`` dicts -- every entry resolved
|
|
28
|
+
via :func:`resolve_extension_path` against the config file's parent
|
|
29
|
+
directory -- when at least one entry's ``path`` is a bare package name.
|
|
30
|
+
Returns ``None`` when the caller should not intervene: the config is
|
|
31
|
+
missing, malformed, declares no extensions, or uses only literal paths --
|
|
32
|
+
leaving the core's own loading (and error reporting) untouched. Raises if
|
|
33
|
+
a package name cannot be resolved.
|
|
34
|
+
"""
|
|
35
|
+
if not os.path.isfile(config_path):
|
|
36
|
+
return None
|
|
37
|
+
try:
|
|
38
|
+
with open(config_path, "rb") as f:
|
|
39
|
+
doc = tomllib.load(f)
|
|
40
|
+
except (OSError, tomllib.TOMLDecodeError):
|
|
41
|
+
# Leave a malformed / unreadable config for the core to report.
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
cfg = doc.get("dirsql") or {}
|
|
45
|
+
entries = cfg.get("extension")
|
|
46
|
+
if not isinstance(entries, list):
|
|
47
|
+
return None
|
|
48
|
+
# Only intervene when at least one path is a bare package name; a config
|
|
49
|
+
# with only literal paths (or no entries at all) keeps the core's existing
|
|
50
|
+
# behavior untouched.
|
|
51
|
+
if not any(
|
|
52
|
+
isinstance(e, dict)
|
|
53
|
+
and isinstance(e.get("path"), str)
|
|
54
|
+
and is_bare_name(e["path"])
|
|
55
|
+
for e in entries
|
|
56
|
+
):
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
base = os.path.dirname(os.path.abspath(config_path))
|
|
60
|
+
specs = []
|
|
61
|
+
for e in entries:
|
|
62
|
+
entrypoint = e.get("entrypoint")
|
|
63
|
+
specs.append(
|
|
64
|
+
{
|
|
65
|
+
"path": resolve_extension_path(
|
|
66
|
+
e["path"], base=base, resolve_relative=True
|
|
67
|
+
),
|
|
68
|
+
"entrypoint": entrypoint if isinstance(entrypoint, str) else None,
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
return specs
|
|
@@ -73,18 +73,22 @@ def _resolve_package(name):
|
|
|
73
73
|
matches.update(_glob.glob(os.path.join(d, "**", pat), recursive=True))
|
|
74
74
|
found = sorted(matches)
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
)
|
|
82
|
-
|
|
76
|
+
# Exactly one loadable resolves; unpacking (rather than a guarded
|
|
77
|
+
# subscript) makes the zero- and multiple-match failures each observable.
|
|
78
|
+
try:
|
|
79
|
+
(single,) = found
|
|
80
|
+
except ValueError:
|
|
81
|
+
pat_desc = " / ".join(patterns)
|
|
82
|
+
if not found:
|
|
83
|
+
raise ValueError(
|
|
84
|
+
f"no loadable extension file ({pat_desc}) found in package "
|
|
85
|
+
f"{name!r} (searched {', '.join(dirs)})"
|
|
86
|
+
) from None
|
|
83
87
|
raise ValueError(
|
|
84
88
|
f"multiple loadable extension files found in package {name!r}: "
|
|
85
89
|
f"{', '.join(found)}; disambiguate with a literal path"
|
|
86
|
-
)
|
|
87
|
-
return
|
|
90
|
+
) from None
|
|
91
|
+
return single
|
|
88
92
|
|
|
89
93
|
|
|
90
94
|
def resolve_extension_path(path, base, resolve_relative):
|
|
@@ -77,7 +77,7 @@ In Python, the constructor starts scanning in a background thread and returns im
|
|
|
77
77
|
- `tables` -- List of `Table` definitions. Each defines a SQLite table, a glob pattern, and an extract function.
|
|
78
78
|
- `ignore` -- Optional list of glob patterns. Files matching any ignore pattern are skipped regardless of table globs.
|
|
79
79
|
- `config` -- Optional path to a `.dirsql.toml` config file. Its `[[table]]` entries are appended to any programmatic `tables`; its `[dirsql].ignore` patterns are appended to any explicit `ignore`; its optional `[dirsql].root` supplies the root directory when `root` is not passed explicitly; its `[[dirsql.extension]]` entries are appended to any programmatic `extensions`.
|
|
80
|
-
- `extensions` -- Optional SQLite extensions to load onto the connection at startup, before any table DDL (enable → load → disable, so the SQL `load_extension()` function is never left exposed). Each entry pairs a shared-library `path` with an optional `entrypoint` init-symbol override (Python: `{ "path", "entrypoint"? }` dicts; Rust: `Extension { path, entrypoint }`; TypeScript: `{ path, entrypoint? }` objects). A `path` is either a file path or a bare **package name**; a package name is resolved from the installed package (Python `importlib` / TypeScript `node_modules`, file-first, erroring on zero or multiple matches). This works on the Python/TypeScript constructor and CLI; the Rust binary and SDK are file-path-only. Programmatic entries load first, then any `[[dirsql.extension]]` from `config`. See [Loading extensions](../cli/config.md#loading-extensions).
|
|
80
|
+
- `extensions` -- Optional SQLite extensions to load onto the connection at startup, before any table DDL (enable → load → disable, so the SQL `load_extension()` function is never left exposed). Each entry pairs a shared-library `path` with an optional `entrypoint` init-symbol override (Python: `{ "path", "entrypoint"? }` dicts; Rust: `Extension { path, entrypoint }`; TypeScript: `{ path, entrypoint? }` objects). A `path` is either a file path or a bare **package name**; a package name is resolved from the installed package (Python `importlib` / TypeScript `node_modules`, file-first, erroring on zero or multiple matches). This works on the Python/TypeScript constructor — for both the programmatic `extensions` list and a `config` file's `[[dirsql.extension]]` entries — and on the CLI; the Rust binary and SDK are file-path-only. Programmatic entries load first, then any `[[dirsql.extension]]` from `config`. See [Loading extensions](../cli/config.md#loading-extensions).
|
|
81
81
|
|
|
82
82
|
### Methods
|
|
83
83
|
|
|
@@ -161,7 +161,9 @@ entrypoint = "sqlite3_myext_init"
|
|
|
161
161
|
- **`path`** — the extension's shared library: either a file path (`.so` /
|
|
162
162
|
`.dylib` / `.dll`, relative to the config file's directory) or a bare
|
|
163
163
|
**package name**. A package name is resolved from the installed package when
|
|
164
|
-
run through the pip/npm `dirsql` CLI
|
|
164
|
+
run through the pip/npm `dirsql` CLI, or when a Python/TypeScript `DirSQL`
|
|
165
|
+
loads the config in-process (`DirSQL(config=...)` /
|
|
166
|
+
`new DirSQL(configPath)`); the standalone Rust binary and the Rust SDK are
|
|
165
167
|
file-path-only.
|
|
166
168
|
- **`entrypoint`** *(optional)* — the extension's init symbol. When omitted,
|
|
167
169
|
SQLite derives a default from the filename; set it when that default does not
|
|
@@ -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.52"
|
|
8
8
|
edition.workspace = true
|
|
9
9
|
publish = false
|
|
10
10
|
readme = "README.md"
|
|
@@ -77,7 +77,7 @@ In Python, the constructor starts scanning in a background thread and returns im
|
|
|
77
77
|
- `tables` -- List of `Table` definitions. Each defines a SQLite table, a glob pattern, and an extract function.
|
|
78
78
|
- `ignore` -- Optional list of glob patterns. Files matching any ignore pattern are skipped regardless of table globs.
|
|
79
79
|
- `config` -- Optional path to a `.dirsql.toml` config file. Its `[[table]]` entries are appended to any programmatic `tables`; its `[dirsql].ignore` patterns are appended to any explicit `ignore`; its optional `[dirsql].root` supplies the root directory when `root` is not passed explicitly; its `[[dirsql.extension]]` entries are appended to any programmatic `extensions`.
|
|
80
|
-
- `extensions` -- Optional SQLite extensions to load onto the connection at startup, before any table DDL (enable → load → disable, so the SQL `load_extension()` function is never left exposed). Each entry pairs a shared-library `path` with an optional `entrypoint` init-symbol override (Python: `{ "path", "entrypoint"? }` dicts; Rust: `Extension { path, entrypoint }`; TypeScript: `{ path, entrypoint? }` objects). A `path` is either a file path or a bare **package name**; a package name is resolved from the installed package (Python `importlib` / TypeScript `node_modules`, file-first, erroring on zero or multiple matches). This works on the Python/TypeScript constructor and CLI; the Rust binary and SDK are file-path-only. Programmatic entries load first, then any `[[dirsql.extension]]` from `config`. See [Loading extensions](../cli/config.md#loading-extensions).
|
|
80
|
+
- `extensions` -- Optional SQLite extensions to load onto the connection at startup, before any table DDL (enable → load → disable, so the SQL `load_extension()` function is never left exposed). Each entry pairs a shared-library `path` with an optional `entrypoint` init-symbol override (Python: `{ "path", "entrypoint"? }` dicts; Rust: `Extension { path, entrypoint }`; TypeScript: `{ path, entrypoint? }` objects). A `path` is either a file path or a bare **package name**; a package name is resolved from the installed package (Python `importlib` / TypeScript `node_modules`, file-first, erroring on zero or multiple matches). This works on the Python/TypeScript constructor — for both the programmatic `extensions` list and a `config` file's `[[dirsql.extension]]` entries — and on the CLI; the Rust binary and SDK are file-path-only. Programmatic entries load first, then any `[[dirsql.extension]]` from `config`. See [Loading extensions](../cli/config.md#loading-extensions).
|
|
81
81
|
|
|
82
82
|
### Methods
|
|
83
83
|
|
|
@@ -161,7 +161,9 @@ entrypoint = "sqlite3_myext_init"
|
|
|
161
161
|
- **`path`** — the extension's shared library: either a file path (`.so` /
|
|
162
162
|
`.dylib` / `.dll`, relative to the config file's directory) or a bare
|
|
163
163
|
**package name**. A package name is resolved from the installed package when
|
|
164
|
-
run through the pip/npm `dirsql` CLI
|
|
164
|
+
run through the pip/npm `dirsql` CLI, or when a Python/TypeScript `DirSQL`
|
|
165
|
+
loads the config in-process (`DirSQL(config=...)` /
|
|
166
|
+
`new DirSQL(configPath)`); the standalone Rust binary and the Rust SDK are
|
|
165
167
|
file-path-only.
|
|
166
168
|
- **`entrypoint`** *(optional)* — the extension's init symbol. When omitted,
|
|
167
169
|
SQLite derives a default from the filename; set it when that default does not
|
|
@@ -114,8 +114,13 @@ mod python {
|
|
|
114
114
|
|
|
115
115
|
#[pymethods]
|
|
116
116
|
impl PyDirSQL {
|
|
117
|
+
/// `suppress_config_extensions` skips the core's own loading of the
|
|
118
|
+
/// config's `[[dirsql.extension]]` entries; the SDK sets it after
|
|
119
|
+
/// resolving those entries itself (package names need `importlib`,
|
|
120
|
+
/// which the core lacks -- #313) and passing the resolved literal
|
|
121
|
+
/// paths via `extensions`, so the entries are not loaded twice.
|
|
117
122
|
#[new]
|
|
118
|
-
#[pyo3(signature = (root=None, *, tables=None, ignore=None, config=None, persist=false, persist_path=None, extensions=None))]
|
|
123
|
+
#[pyo3(signature = (root=None, *, tables=None, ignore=None, config=None, persist=false, persist_path=None, extensions=None, suppress_config_extensions=false))]
|
|
119
124
|
fn new(
|
|
120
125
|
py: Python<'_>,
|
|
121
126
|
root: Option<String>,
|
|
@@ -125,6 +130,7 @@ mod python {
|
|
|
125
130
|
persist: bool,
|
|
126
131
|
persist_path: Option<PathBuf>,
|
|
127
132
|
extensions: Option<Vec<PyExtensionSpec>>,
|
|
133
|
+
suppress_config_extensions: bool,
|
|
128
134
|
) -> PyResult<Self> {
|
|
129
135
|
let rust_tables: Vec<Table> = tables
|
|
130
136
|
.as_deref()
|
|
@@ -164,7 +170,9 @@ mod python {
|
|
|
164
170
|
if !rust_extensions.is_empty() {
|
|
165
171
|
builder = builder.extensions(rust_extensions);
|
|
166
172
|
}
|
|
167
|
-
builder
|
|
173
|
+
builder
|
|
174
|
+
.suppress_config_extensions(suppress_config_extensions)
|
|
175
|
+
.build()
|
|
168
176
|
})
|
|
169
177
|
.map_err(to_py_err)?;
|
|
170
178
|
|
|
File without changes
|
|
@@ -77,7 +77,7 @@ In Python, the constructor starts scanning in a background thread and returns im
|
|
|
77
77
|
- `tables` -- List of `Table` definitions. Each defines a SQLite table, a glob pattern, and an extract function.
|
|
78
78
|
- `ignore` -- Optional list of glob patterns. Files matching any ignore pattern are skipped regardless of table globs.
|
|
79
79
|
- `config` -- Optional path to a `.dirsql.toml` config file. Its `[[table]]` entries are appended to any programmatic `tables`; its `[dirsql].ignore` patterns are appended to any explicit `ignore`; its optional `[dirsql].root` supplies the root directory when `root` is not passed explicitly; its `[[dirsql.extension]]` entries are appended to any programmatic `extensions`.
|
|
80
|
-
- `extensions` -- Optional SQLite extensions to load onto the connection at startup, before any table DDL (enable → load → disable, so the SQL `load_extension()` function is never left exposed). Each entry pairs a shared-library `path` with an optional `entrypoint` init-symbol override (Python: `{ "path", "entrypoint"? }` dicts; Rust: `Extension { path, entrypoint }`; TypeScript: `{ path, entrypoint? }` objects). A `path` is either a file path or a bare **package name**; a package name is resolved from the installed package (Python `importlib` / TypeScript `node_modules`, file-first, erroring on zero or multiple matches). This works on the Python/TypeScript constructor and CLI; the Rust binary and SDK are file-path-only. Programmatic entries load first, then any `[[dirsql.extension]]` from `config`. See [Loading extensions](../cli/config.md#loading-extensions).
|
|
80
|
+
- `extensions` -- Optional SQLite extensions to load onto the connection at startup, before any table DDL (enable → load → disable, so the SQL `load_extension()` function is never left exposed). Each entry pairs a shared-library `path` with an optional `entrypoint` init-symbol override (Python: `{ "path", "entrypoint"? }` dicts; Rust: `Extension { path, entrypoint }`; TypeScript: `{ path, entrypoint? }` objects). A `path` is either a file path or a bare **package name**; a package name is resolved from the installed package (Python `importlib` / TypeScript `node_modules`, file-first, erroring on zero or multiple matches). This works on the Python/TypeScript constructor — for both the programmatic `extensions` list and a `config` file's `[[dirsql.extension]]` entries — and on the CLI; the Rust binary and SDK are file-path-only. Programmatic entries load first, then any `[[dirsql.extension]]` from `config`. See [Loading extensions](../cli/config.md#loading-extensions).
|
|
81
81
|
|
|
82
82
|
### Methods
|
|
83
83
|
|
|
@@ -161,7 +161,9 @@ entrypoint = "sqlite3_myext_init"
|
|
|
161
161
|
- **`path`** — the extension's shared library: either a file path (`.so` /
|
|
162
162
|
`.dylib` / `.dll`, relative to the config file's directory) or a bare
|
|
163
163
|
**package name**. A package name is resolved from the installed package when
|
|
164
|
-
run through the pip/npm `dirsql` CLI
|
|
164
|
+
run through the pip/npm `dirsql` CLI, or when a Python/TypeScript `DirSQL`
|
|
165
|
+
loads the config in-process (`DirSQL(config=...)` /
|
|
166
|
+
`new DirSQL(configPath)`); the standalone Rust binary and the Rust SDK are
|
|
165
167
|
file-path-only.
|
|
166
168
|
- **`entrypoint`** *(optional)* — the extension's init symbol. When omitted,
|
|
167
169
|
SQLite derives a default from the filename; set it when that default does not
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql-0.3.50 → dirsql-0.3.52}/packages/python/docs/tests/integration/language-flag.spec.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|